/* the following two lines will have to be changed to have the correct load paths for the named files on windows, mac, unix, etc for my macbook... and an sbcl maxima load("/Users/fateman/documents/lisp/e18w"); */ /* batch this file on windows */ load("c:/lisp/e18w.lisp"); [infix("->", 49,49), infix("?",150,150), infix ("/;", 50,50), infix ("|",50,50), nary("|"), infix(":$", 50,50), infix("/.",48,48), infix("//.",48,48), infix("@",160,160), infix("//",60,60), postfix(".$",90), prefix("?",300,300)]$ [ "|"([b%]):=apply(Alternatives,b%), "/;"(a%,b%):=Condition(a%,b%), "/."(a%,b%):=ReplaceAll(a%,b%), ":$"(a%,b%):=Pattern(a%,b%), ".$"(a%) :=Optional(a%), "//"(a%,b%):=apply(b%,[a%]), define(funmake(nounify("@"),[a%,b%]),apply(a%,[b%])), "//."(a%,b%):=ReplaceRepeated(a%,b%), "?"(a%,b%):=PatternTest(a%,b%), "->"(a%,b%):=Rule(a%,b%) ]$ mma(e%):= pt(e%)$ /* converts atoms with _ in them */ /*now much of mma syntax can be just typed in to maxima. e.g. */ mma(a_foo?bar); /* should be PatternTest(Pattern(a,Blank(foo)),bar) */ mp1(p,e):= m1(mma(p),e)$ mp1all(p,e):=m1all(mma(p),e)$ ruleoptimize(qq):=apply(Rule,[ProcOptional(first(qq)),rest(qq)])$ /* do more, later? */ RuleToFunction(qq):= /* this should be cached for each rule qq */ (qq:pt(qq), block([ /* make the defined function parameters unique */ e:gensym("e"), /* the argument to the function made from the rule*/ ans:gensym("a"), /*temp variable, the answer from m1 */ lhs:inpart(qq,1), rhs:inpart(qq,2) ], buildq([lhs,rhs,therule,e,p,r,ans,qq], lambda([e], /* Here's the model function for the rule */ block([ ans:m1(lhs,e)], if ans#false then Substall(ans,rhs))))))$ oprule(rr):= apply(Rule,[ProcOptional(pt(first(rr))),second(rr)])$ ReplaceAll(exp,onerule):= if onerule=[] then exp else if listp(onerule) then ReplaceAll(ReplaceAll(exp,first(onerule)),rest(onerule)) else scandown(RuleToFunction(oprule(onerule)),exp)$ /* try mma(f(a)+g(b)/. a->3) mma(f(3)+g(4)/. a_integer-> foo) mma ( g(3,4)+g(4,3) /. g(a_integer,b_integer)?(a>b) -> foo ); optional not quite working ( mma(x+y/. (a_+Optional(b_) )-> m(a,b)));. b should also be bound to 0, default for + */ /* how to simulate the definition of a procedure which in mma has pattern matching explicit in its argument list? for example, f[a_Integer,b_?EvenQ,0]:= foo[a,b] The trick is to realize that this is NOT, I repeat NOT actually defining a procedure in Mathematica. It is defining a pattern match/ replacement -- that is, a simplification rule. f(a,b):= ... IS DIFFERENT in Maxima. It IS defining a procedure. The equivalent to the mma notation f[a_Integer,b_?EvenQ,0]:= foo[a,b] is more like matchdeclare(a,integerp, b,evenp) tellsimp(f(a,b,0), foo(a,b)). In Maxima we used defrule(r1, f(a,b,0), foo(a,b)) and then messed around with the "rule" property of the atom/symbol r1. A cleaner version would be to just do this: r1: Rule (a,b) or r1: a->b and then extend the notion of function call /function application embedded in maxima (actually the lisp procedure mapply1) so that mapply1 can not only apply lisp functions and maxima functions and maxima lambdas, and matrix subscripts etc etc, but also Rules. We can queue up Rules according to our own priorities and hook them into Maxima by, for example, saying matchdeclare (xxx,any) ; tellsimp(f(xxx), apply1(xxx,r1,r2,r3)) ... can't do tellsimp(f(xxx),apply1(f(xxx),r1,r2...)), a loop Maybe we need something subtler than tellsimp ? :( TellsimpByRules(f, r1,r2, ...) which means that f(xxx) is simplified by apply1(f(xxx),r1,r2,...). Note that we have to queue up rules (as does tellsimp, tellsimpafter) if we simulate mma definitions like f[a_,b_,0]:= a+b; f[a_,b_,1]:= a*b; I don't know if it is possible to do this without using Lisp to interface to the simplifier. Though maybe tellsimp etc could be used as an interface? Missing, bare __ . conflicts with Maxima syntax. Use temp__ . Also conflicting with Maxima syntax, use of ":" in pattern, hence :$. Default, OneIdentity, Optional,Alternatives,Except, Repeated, RepeatedNull, . Head doesn't know Complex? Also user-interface for SetAttributes. just not yet. Second thoughts on Rule, implemented in Maxima. Assume that we fix up mp1 so that it returns false if there is no match [ ] if there is a match but no parameters are bound or a maxima list like [bind(x,val_of_x), bind(y, val_of_y),...] then Rule (pattern, replacement) is a maxima program rfun(exp) that does this: let ans=mp1(pattern,exp). If ans=false then return exp. If ans= [ ] then return replacement. If ans = [ x=a, y=b, ...] then return subst(ans,replacement). This is not quite right if one of the rhs is "Segment". This makes it necessary to do this program, Rule() in lisp, I think. */ /* setting defaults so that in ... a_$.+b we get Optional(Pattern(a,Blank()), 0)+ b because get("+",Default) returns 0 since put("+", 0, Default) how to see defaults?? */ put("+", 0, Default)$ put("*", 0, Default)$ GetDefaultOp(op):= get(op,Default) $ /* for now */ MmaInfix:true$