map.red 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. module map; % Mapping univariate functions to composite objects.
  2. % Author: Herbert Melenk.
  3. % Syntax: map(unary-function,linear-structure-or-matrix)
  4. %
  5. % map(sqrt ,{1,2,3,4});
  6. % map(df(~u,x),mat((x^2,sin x)));
  7. %
  8. % select(unary-predicate,linear-structure)
  9. %
  10. % select(evenp,{1,2,3,4,5,6,7});
  11. % select(evenp deg(~u,x),(x+y)^5);
  12. %
  13. % The function/predicate may contain one free variable.
  14. put('!~map,'oldnam,'map);
  15. put('map,'newnam,'!~map);
  16. put('!~map,'psopfn,'map!-eval);
  17. put('!~map,'rtypefn,'getrtypecadr);
  18. symbolic procedure getrtypecadr u; getrtype cadr u;
  19. symbolic procedure map!-eval u;
  20. <<if length u neq 2 then rederr "illegal number of arguments for map";
  21. map!-eval1(reval cadr u,car u,
  22. function(lambda y;y),'aeval)>>;
  23. symbolic procedure !~map(b,a);
  24. % Called only inside matrix expressions.
  25. cdr map!-eval1('mat . matsm a,b,
  26. function (lambda w; list('!*sq,w,t)),'simp);
  27. symbolic procedure map!-eval1(o,q,fcn1,fcn2);
  28. % o structure to be mapped.
  29. % q map expression (univariate function).
  30. % fcn1 function for evaluating members of o.
  31. % fcn2 function computing results (e.g. aeval).
  32. begin scalar v,w;
  33. v := '!&!&x;
  34. if idp q
  35. and (get(q,'simpfn) or get(q,'number!-of!-args)=1)
  36. then <<w:=v; q:={q,v}>>
  37. else if eqcar(q,'replaceby) then
  38. <<w:=cadr q; q:=caddr q>>
  39. else
  40. <<w:=map!-frvarsof(q,nil);
  41. if null w then rederr "map/select: no free variable found" else
  42. if cdr w then rederr "map/select: free variable ambiguous";
  43. w := car w;
  44. >>;
  45. if eqcar(w,'!~) then w:=cadr w;
  46. q := sublis({w.v,{'!~,w}.v},q);
  47. if atom o then rederr "cannot map for atom";
  48. return if car o ='mat then
  49. 'mat . for each row in cdr o collect
  50. for each w in row collect
  51. map!-eval2(w,v,q,fcn1,fcn2)
  52. else car o . for each w in cdr o collect
  53. map!-eval2(w,v,q,fcn1,fcn2);
  54. end;
  55. symbolic procedure map!-eval2(w,v,q,fcn1,fcn2);
  56. begin scalar r;
  57. r :=evalletsub2({{{'replaceby ,v,apply1(fcn1,w)}},
  58. {fcn2,mkquote q}},nil);
  59. if errorp r then rederr "error during map";
  60. return car r;
  61. end;
  62. symbolic procedure map!-frvarsof(q,l);
  63. if atom q then l
  64. else if car q eq '!~ then
  65. if q member l then l else q.l
  66. else map!-frvarsof(cdr q,map!-frvarsof(car q,l));
  67. symbolic procedure select!-eval u;
  68. % select from a list l members according to a boolean test.
  69. begin scalar l,w,v,r;
  70. l := reval cadr u; w := car u;
  71. if atom l or (car l neq'list and not flagp(car l,'nary)) then
  72. typerr(l,"select operand");
  73. if idp w and get(w,'number!-of!-args)=1 then w:={w,{'~,'!&!&}};
  74. if eqcar(w,'replaceby) then <<v:=cadr w;w:=caddr w>>;
  75. w:=freequote formbool(w,nil,'algebraic);
  76. if v then w:={'replaceby,v,w};
  77. r:=for each q in
  78. pair(cdr map!-eval1(l,w,function(lambda y;y),'lispeval),cdr l)
  79. join if car q and car q neq 0 then {cdr q};
  80. if r then return car l . r;
  81. if (r:=atsoc(car l,'((plus . 0)(times . 1)(and . 1)(or . 0))))
  82. then return cdr r
  83. else rederr {"empty selection for operator ",car l}
  84. end;
  85. symbolic procedure freequote u;
  86. % Preserve structure where possible.
  87. if atom u then u
  88. else if car u eq 'list and cdr u and cadr u = '(quote !~)
  89. then mkquote{'!~,cadr caddr u}
  90. else (if v=u then u else v)
  91. where v = freequote car u . freequote cdr u;
  92. put('select,'psopfn,'select!-eval);
  93. put('select,'number!-of!-args,2);
  94. endmodule;
  95. end;