# FUNCTION: LAMBDA - LAMBDA abstraction (from LAMBDA calculus) # # CALLING SEQUENCES: LAMBDA(x,f); or LAMBDA(x1,...,xn,f); # # PARAMETERS: # x,x1,x2,... - variable name or a list of variable names # f - algebraic expression (function of the variables) # # SYNOPSIS: # - This function implements the LAMBDA function of LAMBDA calculus. # If x is a name, then LAMBDA(x,f(x)) converts the input "expression" to a # "function" of x. The output is a Maple operator of the form # - If x is a list of names, then LAMBDA([v1,...,vn],f) outputs # a function of m variables (possibly 0). The output is a Maple angle # bracket operator of the form , # - The case LAMBDA(x1,x2,...,xn,f(x1,x2,...,xn)) is equivalent to repeated # application LAMBDA, namely LAMBDA(x1,LAMBDA(x2,...,xn,f(x1,x2,...,xn))) # - In the LAMBDA calculus, functions of more than one variable are treated # in this way as repeated application of functions of one variable. # The Maple LAMBDA function supports both. # # NB: that LAMBDA([],f) defines the nullary function () -> f # NB: that LAMBDA(f) is the identity function. # # EXAMPLES: # > f := LAMBDA(x,x^2+y+1/z); # 2 # f := # # > f(2); # 4 + y + 1/z # # > f := LAMBDA([x,y],x^2+y+1/z); # 2 # f := # # > f(2,3); # 7 + 1/z # # > f := LAMBDA([],x^2+y+1/z); # 2 # f := # # > f(); # 2 # x + y + 1/z # # > f := LAMBDA(x,y,x^2+y+1/z); # f := )|x> # # > f(2); # <4 + y + 1/z|y> # # > g := LAMBDA(y,x,x^2+y+1/z); # g := )|y> # # > g(2); # 2 # # # > f(2)(3); # 7 + 1/z # # > g(3)(2); # 7 + 1/z # # The implementation produces funny looking subs calls in the resulting # procedures. These substitutions are implementing nested lexical # scoping rules which Maple does not have. Just ignore them. # # Author: MBM Nov/90 # GENSYM := proc(x) subs( 'X' = x, proc() local X; X end )() end: LAMBDA := proc() local f, x, n, i, t, X, Y, Yp; f := args[nargs]; if nargs = 1 then RETURN(eval(f,1)) fi; x := args[1]; if type(x,name) then x := [x] elif type(x,set) then x := [op(x)] fi; if not type(x,list(name)) or nops(x) <> nops({op(x)}) then ERROR(`variables must be unique and of type name`) fi; if not type(x,list(string)) then n := nops(x); X := [ 'GENSYM( cat('x',``.i) )' $ i=1..n ]; RETURN( LAMBDA( X, args[2..nargs-1], subs( ['x[i]=X[i]'$ i=1..n], eval(f,1) ) ) ) fi; if nargs > 2 then f := LAMBDA( args[2..nargs-1], eval(f,1) ) fi; if has(eval(f,1), x) and hastype(eval(f,1),procedure) then Y := { 'op(i,x) = GENSYM(op(i,x))' $ i=1..nops(x) }; Yp := { 'rhs(op(i,Y))=lhs(op(i,Y))' $ i=1..nops(Y) }; f := subs(Y, eval(f,1) ); subs( {_PARMS=op(x),_SUBS=Yp,_BODY=eval(f,1)}, ) else subs( {_BODY=eval(f,1),_PARMS=op(x)}, <_BODY | _PARMS> ) fi end: