网络编程
位置:首页>> 网络编程>> JavaScript>> 极致之美——百行代码实现全新智能语言Lisp(3)

极致之美——百行代码实现全新智能语言Lisp(3)

作者:月影 来源:51js 发布时间:2010-07-13 13:07:00 

标签:Lisp,javascript


接着我们定义一个记号来描述函数.函数表示为[lambda, [...], e],其中 ...是原子(叫做参数),e是表达式. 如果表达式的第一个元素形式如上
[[lambda,[...],e],...]

则称为函数调用.它的值计算如下.每一个表达式先求值,然后e再求值.在e的求值过程中,每个出现在e中的的值是相应的在最近一次的函数调用中的值.

> [[lambda,['x'],[cons,'x',[_,[c]]]],[_,a]]
[a,c]
> [[lambda,['x','y'],[cons,'x',[cdr,'y']]],[_,z],[_,[a,b,c]]]
[z,b,c]


lambda = function(args, code)
{
 if(code instanceof Array)
 {
  var fun = new Function(args,
   "for(var i = 0; i < arguments.length; i++) arguments[i] = LispScript.Run(arguments[i]);return LispScript.Run("+code.toEvalString()+");");

  var globalFuncName = __funList.pop();
 
  fun._funName = globalFuncName;

  if(globalFuncName != null)
   self[globalFuncName] = fun;

  return fun;
 }

 return [];
};

 

如果一个表达式的第一个元素f是原子且f不是原始操作符
[f ...]

并且f的值是一个函数[lambda,[...]],则以上表达式的值就是

[[lambda,[...],e],...]

的值. 换句话说,参数在表达式中不但可以作为自变量也可以作为操作符使用:

> [[lambda,[f],[f,[_,[b,c]]],[_,[lambda,[x],[cons,[_,a],x]]]
[a,b,c]

有另外一个函数记号使得函数能提及它本身,这样我们就能方便地定义递归函数.记号

[label,f,[lambda,[...],e]]

表示一个象[lambda,[...],e]那样的函数,加上这样的特性: 任何出现在e中的f将求值为此label表达式, 就好象f是此函数的参数.

假设我们要定义函数[subst,x,y,z], 它取表达式x,原子y和表z做参数,返回一个象z那样的表, 不过z中出现的y(在任何嵌套层次上)被x代替.

> [subst,[_,m],[_,b],[_,[a,b,[a,b,c],d]]]
[a,m,[a,m,c],d]

我们可以这样表示此函数

[label,subst,[lambda,[x,y,z],
               [cond,[[atom,z],
                      [cond,[[eq,z,y],x],
                            true,z]]],
                     [true,[cons,[subst,x,y,[car,z]],
                               [subst,x,y,[cdr,z]]]]]]]


label = function(funName, funDef)
{
 __funList.push(funName);

 return LispScript.Run(funDef);
};

我们简记f=[label,f,[lambda,[...],e]]为
[defun,f,[...],e]


defun = function(funName, args, code)
{
 __funList.push(funName);
 
 if(code instanceof Array)
 {
  var fun = new Function(args,
   "for(var i = 0; i < arguments.length; i++) arguments[i] = LispScript.Run(arguments[i]);return LispScript.Run("+code.toEvalString()+");");

  var globalFuncName = __funList.pop();

  fun._funName = globalFuncName;

  if(globalFuncName != null)
   self[globalFuncName] = fun;

  return fun;
 }

 return [];
};

于是

[defun,subst,[x,y,z],
  [cond,[[atom,z],
         [cond,[[eq,z,y],x],
               [true,z]]],
     [true,[cons,[subst,x,y,[car,z]],
                  [subst,x,y,[cdr,z]]]]]]

偶然地我们在这儿看到如何写cond表达式的缺省子句. 第一个元素是't的子句总是会成功的. 于是
[cond,[x,y],[[_,true],z]]

等同于我们在某些语言中写的
if x then y else z

对于函数调用,具有如下结构:[FunName,[_,args]]
其中FunName是函数名称,[_,args]是指定参数引用列表args
注意[FunName,args]也是合法的,但是和[FunName,[_,args]]有所区别,对于前者,指令在被调用之前先计算args的值,把计算出的值作为参数列表代入函数计算(期望args计算结果为List),而后者的args参数列表在函数指令调用时才被计算

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com