需要注意的几点
iScheme 支持部分求值(Partial Evaluation),这意味着:
部分求值
>> (def mul (func (a b) (* a b)))
>> (func (a b) (* a b))
>> (mul 3 4)
>> 12
>> (mul 3)
>> (func (a:3 b) (* a b))
>> ((mul 3) 4)
>> 12
也就是说,当 SFunction 的实际参数(Argument)数量小于其形式参数(Parameter)的数量时,它依然是一个函数,无法被求值。
这个功能有什么用呢?生成高阶函数。有了部分求值,我们就可以使用
(def mul (func (a b) (* a b)))
(def mul3 (mul 3))
>> (mul3 3)
>> 9
而不用专门定义一个生成函数:
(def times (func (n) (func (n x) (* n x)) ) )
(def mul3 (times 3))
>> (mul3 3)
>> 9
SFunction#ToString 可以将其自身还原为源代码——从而大大简化了 iScheme 的理解和测试。
内置操作
iScheme 的内置操作有四种:算术|逻辑|比较|列表操作。
我选择了表达力(Expressiveness)强的 lambda 方法表来定义内置操作:
首先在 SScope 中添加静态字段 builtinFunctions ,以及对应的访问属性 BuiltinFunctions 和操作方法 BuildIn 。
public class SScope {
private static Dictionary<String, Func<SExpression[], SScope, SObject>> builtinFunctions =
new Dictionary<String, Func<SExpression[], SScope, SObject>>();
public static Dictionary<String, Func<SExpression[], SScope, SObject>> BuiltinFunctions {
get { return builtinFunctions; }
}
// Dirty HACK for fluent API.
public SScope BuildIn(String name, Func<SExpression[], SScope, SObject> builtinFuntion) {
SScope.builtinFunctions.Add(name, builtinFuntion);
return this;
}
}
注意:
-
Func<T1, T2, TRESULT> 是 C# 提供的委托类型,表示一个接受 T1 和 T2 ,返回 TRESULT
这里有一个小 HACK,使用实例方法(Instance Method)修改静态成员(Static Member),从而实现一套流畅的 API(参见Fluent Interface)。
接下来就可以这样定义内置操作:
new SScope(parent: null)
.BuildIn("+", addMethod)
.BuildIn("-", subMethod)
.BuildIn("*", mulMethod)
.BuildIn("/", divMethod);
一目了然。
断言(Assertion)扩展
为了便于进行断言,我对 Boolean 类型做了一点点扩展。
public static void OrThrows(this Boolean condition, String message = null) {
if (!condition) { throw new Exception(message ?? "WTF"); }
}
从而可以写出流畅的断言:
(a < 3).OrThrows("Value must be less than 3.");










