问题
I'm writing a small Lisp interpreter in C#, and it's basically working already. Currently I'm using an interface to represent functions:
public interface LispFunction
{
object Apply(ArrayList parameters);
}
The interface is implemented by multiple classes for internal (standard) functions, lambdas, macro expansion, calling methods in .net objects via reflection and so on. Please note that speed is NOT an issue here, just the joy of getting the interpreter to, and use it at, work.
Now I'd like my little Lisp to accept arbitrary C# lambdas to be used within the interpreter, like this:
Lisp foo = new Lisp();
foo.GlobalEnvironment.AddFunction("test", (bool a, int b) => a ? b : "whoops");
foo.Eval(foo.Read("(test #t 5)")); // Should evaluate to (object) 5
First thing that came to my mind was using Func<...>
, but I'd have to use lots of overloaded methods for Func<a>
, Func<a, b>
, Func<a, b, c>
and so on.
Is there a possibility in C# to accept arbitrary lambdas to be called via reflection later?
回答1:
Is there a possibility in C# to accept arbitrary lambdas to be called via reflection later?
Well you can write a method to take an arbitrary delegate:
public void AddFunction(string name, Delegate function)
However, the conversion from a lambda expression has to be as a specific delegate, so you'd need:
Func<bool, string, string> function = (a, b) => a ? b : "whoops"
foo.GlobalEnvironment.AddFunction("test", function);
Or cast within the call:
foo.GlobalEnvironment.AddFunction("test",
(Func<bool, string, string>)((a, b) => a ? b : "whoops"));
You could put all the overloading in one place, keeping AddFunction
entirely general, but having a static class like this (a bit like Tuple
):
public static class Func
{
public Func<TResult> Create(Func<TResult> function) { return function; }
public Func<T1, TResult> Create(Func<T1, TResult> function)
{
return function;
}
public Func<T1, T2, TResult> Create(Func<T1, T2, TResult> function)
{
return function;
}
// etc
}
This class basically just exists for convenience. You'd then call:
foo.GlobalEnvironment.AddFunction("test",
Func.Create((bool a, string b) => a ? b : "whoops"));
来源:https://stackoverflow.com/questions/10347634/universal-func-type-in-c-sharp