I’m trying to write a small little scripting engine for a bullet hell game and I would like to do it in F#. I wrote some C# code to conceptualize it, but I’m having trouble porting it to F#. The C# code is posted below, and I would like some help porting it to F#. I have a feeling the matching F# code will be significantly smaller. I’m open to any sort of creative solutions 🙂
interface IRunner
{
Result Run(int data);
}
struct Result
{
public Result(int data, IRunner next)
{
Data = data;
Next = next;
}
public int Data;
public IRunner Next;
}
class AddOne : IRunner
{
public Result Run(int data)
{
return new Result(data + 1, null);
}
}
class Idle : IRunner
{
public Result Run(int data)
{
return new Result(data, null);
}
}
class Pair : IRunner
{
IRunner _one;
IRunner _two;
public Pair(IRunner one, IRunner two)
{
_one = one;
_two = two;
}
public Result Run(int data)
{
var res = _one.Run(data);
if (res.Next != null)
return new Result(res.Data, new Pair(res.Next, _two));
return new Result(res.Data, _two);
}
}
class Repeat : IRunner
{
int _counter;
IRunner _toRun;
public Repeat(IRunner toRun, int counter)
{
_toRun = toRun;
_counter = counter;
}
public Result Run(int data)
{
var res = _toRun.Run(data);
if (_counter > 1)
{
if (res.Next != null)
return new Result(res.Data,
new Pair(res.Next,
new Repeat(_toRun, _counter - 1)));
return new Result(res.Data, new Repeat(_toRun, _counter - 1));
}
return res;
}
}
class Sequence : IRunner
{
IEnumerator<IRunner> _runner;
public Sequence(IEnumerator<IRunner> runner)
{
_runner = runner;
}
public Result Run(int data)
{
var res = _runner.Current.Run(data);
bool next = _runner.MoveNext();
if (res.Next != null)
{
return new Result(res.Data,
new Pair(res.Next, new Sequence(_runner)));
}
return new Result(res.Data, new Sequence(_runner));
}
}
Here’s something that’s almost a direct translation of the same solution strategy.
That said, I think there may be a better/simpler representation choice, I’m still mulling it over.
EDIT
Here’s another way that’s a little more refined… am still trying to see if there’s a good way to work in a “list”, since the results seem isomorphic to cons cells…
EDIT
One more version, it uses lists, but now I’ve a feeling for what’s weird here…
It’s almost just like an ‘Action queue’, a list of
int->intfunctions. But each guy can produce some ‘suffix actions’ that run immediately after him (but before the remaining work in the would-be queue), and trying to maintain the ordering with a purely functional data structure is potentially inefficient (without the right tree/queue library at hand). It would be interesting to know how this will be used/consumed, as perhaps a small change there might allow for a completely different strategy.