作用域
作用域决定程序的运行环境。iScheme使用嵌套作用域。
以下面的程序为例
>> (def x 1)
>> 1
>> (def y (begin (def x 2) (* x x)))
>> 4
>> x
>> 1

利用C#提供的 Dictionary<TKey, TValue> 类型,我们可以很容易的实现 iScheme 的作用域 SScope :
iScheme的作用域实现
public class SScope {
public SScope Parent { get; private set; }
private Dictionary<String, SObject> variableTable;
public SScope(SScope parent) {
this.Parent = parent;
this.variableTable = new Dictionary<String, SObject>();
}
public SObject Find(String name) {
SScope current = this;
while (current != null) {
if (current.variableTable.ContainsKey(name)) {
return current.variableTable[name];
}
current = current.Parent;
}
throw new Exception(name + " is not defined.");
}
public SObject Define(String name, SObject value) {
this.variableTable.Add(name, value);
return value;
}
}
类型实现
iScheme 的类型系统极其简单——只有数值,Bool,列表和函数,考虑到他们都是 iScheme 里面的值对象(Value Object),为了便于对它们进行统一处理,这里为它们设置一个统一的父类型 SObject :
public class SObject { }
数值类型
iScheme 的数值类型只是对 .Net 中 Int64 (即 C# 里的 long )的简单封装:
public class SNumber : SObject {
private readonly Int64 value;
public SNumber(Int64 value) {
this.value = value;
}
public override String ToString() {
return this.value.ToString();
}
public static implicit operator Int64(SNumber number) {
return number.value;
}
public static implicit operator SNumber(Int64 value) {
return new SNumber(value);
}
}
注意这里使用了 C# 的隐式操作符重载,这使得我们可以:
SNumber foo = 30;
SNumber bar = 40;
SNumber foobar = foo * bar;
而不必:
SNumber foo = new SNumber(value: 30);
SNumber bar = new SNumber(value: 40);
SNumber foobar = new SNumber(value: foo.Value * bar.Value);
为了方便,这里也为 SObject 增加了隐式操作符重载(尽管 Int64 可以被转换为 SNumber 且 SNumber 继承自 SObject ,但 .Net 无法直接把 Int64 转化为 SObject ):
public class SObject {
...
public static implicit operator SObject(Int64 value) {
return (SNumber)value;
}
}
Bool类型
由于 Bool 类型只有 True 和 False,所以使用静态对象就足矣。










