极致之美——百行代码实现全新智能语言第1/6页

2019-06-03 01:56:00于海丽

foo
[]
[foo]
[foo,bar]
[a,b,[c],d]
最后一个表达式是由四个元素组成的表, 第三个元素本身是由一个元素组成的表. 
在算术中表达式 1 + 1 得出值2. 正确的Lisp表达式也有值. 如果表达式e得出值v,我们说e返回v. 下一步我们将定义几种表达式以及它们的返回值. 
如果一个表达式是表,我们称第一个元素为操作符,其余的元素为自变量.我们将定义七个原始(从公理的意义上说)操作符: quote,atom,eq,car,cdr,cons,和 cond. 
[quote,x] 返回x. 我们把[quote,x]简记为[_,x]. 
> [quote,a]
a
> [_,a]
a
> [quote,[a b c]]
[a,b,c]
quote = _ = function(args)
{
 if(arguments.length < 1)
  return [];
 else if(arguments.length >= 1)
 {
  return arguments[0];
 }
};

[atom,x]返回原子true如果x的值是一个原子或是空表,否则返回[]. 在Lisp中我们按惯例用原子true表示真, 而用空表表示假. 
> [atom,[_,a]]
true
> [atom,[_,[a,b,c]]]
[]
> [atom,[_,[]]]
true
atom = function(arg)
{
 var tmp = LispScript.Run(arg); //先对参数求值
 if(!(tmp instanceof Array) || tmp.length <= 0)
  return true;
 else
  return [];
};

既然有了一个自变量需要求值的操作符, 我们可以看一下quote的作用. 通过引用(quote)一个表,我们避免它被求值. 一个未被引用的表作为自变量传给象 atom这样的操作符将被视为代码: 
> [atom,[atom,[_,a]]]
true
反之一个被引用的表仅被视为表, 在此例中就是有两个元素的表: 
> [atom,[_,[atom,[_,a]]]]
[]
这与我们在英语中使用引号的方式一致. Cambridge(剑桥)是一个位于麻萨诸塞州有90000人口的城镇. 而"Cambridge"是一个由9个字母组成的单词. 
引用看上去可能有点奇怪因为极少有其它语言有类似的概念. 它和Lisp最与众不同的特征紧密联系:代码和数据由相同的数据结构构成, 而我们用quote操作符来区分它们. 
[eq,x,y]返回t如果x和y的值是同一个原子或都是空表, 否则返回[]. 
> [eq,[_,a],[_,a]]
true
> [eq,[_,a],[_,b]]
[]
> [eq,[_,[]],[_,[]]]
true
equal = eq = function(arg1, arg2)
{
 var tmp1 = LispScript.Run(arg1);
 var tmp2 = LispScript.Run(arg2);   //先对参数求值
 if(!(tmp1 instanceof Array) && !(tmp2 instanceof Array) &&