4

我正在用 C# 编写一个小型 Lisp 解释器,它基本上已经可以工作了。目前我正在使用一个接口来表示函数:

public interface LispFunction
{
    object Apply(ArrayList parameters);
}

该接口由多个类实现,用于内部(标准)函数、lambda、宏扩展、通过反射调用 .net 对象中的方法等。请注意,速度在这里不是问题,只是让口译员在工作中使用它的乐趣。

现在我希望我的小 Lisp 接受在解释器中使用的任意 C# lambda,如下所示:

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

我想到的第一件事是使用Func<...>,但我必须为 、 等使用大量Func<a>重载Func<a, b>方法Func<a, b, c>

C# 中是否有可能接受稍后通过反射调用的任意 lambda?

4

1 回答 1

9

C# 中是否有可能接受稍后通过反射调用的任意 lambda?

好吧,您可以编写一个方法来获取任意委托

public void AddFunction(string name, Delegate function)

但是,来自 lambda 表达式的转换必须作为特定的委托,因此您需要:

Func<bool, string, string> function = (a, b) => a ? b : "whoops"
foo.GlobalEnvironment.AddFunction("test", function);

或在通话中投射:

foo.GlobalEnvironment.AddFunction("test",
    (Func<bool, string, string>)((a, b) => a ? b : "whoops"));

您可以将所有重载放在一个地方,保持AddFunction完全通用,但有一个像这样的静态类(有点像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
}

这个类基本上只是为了方便而存在。然后你会打电话:

foo.GlobalEnvironment.AddFunction("test",
    Func.Create((bool a, string b) => a ? b : "whoops"));
于 2012-04-27T08:54:44.027 回答