argument against:
slows down simplifier.
R
Jf
----- Original Message -----
From: Robert Dodier <robert.dodier at gmail.com>
Date: Friday, June 8, 2007 10:21 pm
Subject: declaration foo distributes over bar
> Hello,
>
> Here's a thought. How about making it possible to declare that
> some operator distributes over some other operator.
> The point of this would be to obviate special-case code
> that looks for lists, matrices, sums, etc.
> E.g. trigrat at present triggers an error if applied to a matrix;
> instead of patching the code, we could just make a declaration.
>
> Here's an example session.
>
> (%i1) load ("./distributes_over.mac");
> (%o1) ./distributes_over.mac
> (%i2) declare (foo distributes_over bar);
> (%o2) foo distributes_over bar
> (%i3) foo (bar (x, y, z));
> (%o3) bar(foo(x), foo(y), foo(z))
> (%i4) declare (foo distributes_over [matrix, set, "["]);
> (%o4) [foo distributes_over matrix, foo distributes_over set,
> foo distributes_over []
> (%i5) foo (matrix ([1, 2], [a, b]));
> [ foo(1) foo(2) ]
> (%o5) [ ]
> [ foo(a) foo(b) ]
> (%i6) foo ({a, b, c});
> (%o6) {foo(a), foo(b), foo(c)}
> (%i7) foo ([a, b, c]);
> (%o7) [foo(a), foo(b), foo(c)]
> (%i8) declare (foo distributes_over ["+", "*"]);
> (%o8) [foo distributes_over +, foo distributes_over *]
> (%i9) foo (a + b + c);
> (%o9) foo(c) + foo(b) + foo(a)
> (%i10) foo (a * b * c);
> (%o10) foo(a) foo(b) foo(c)
> (%i11) foo (a*b + c*d);
> (%o11) foo(c) foo(d) + foo(a) foo(b)
>
> Notes.
> (1) distributes_over is implemented as a simplification.
> Each left-hand (outer) operator gets a rule.
> Right-hand (inner) operators are stored as a property.
> (2) distributes_over as implemented below doesn't know
> what to do if the left-hand (outer) operator takes multiple
> arguments. I guess the matchdeclare and tellsimp need
> to be more complicated.
> (3) There is some code in share to declare operators
> as "threadable". I think that existing code can be improved
> in 2 ways. I think "distributes_over" is a more widely understood
> name. Also I think it is better to allow specifying the set of
> operators over which to distribute.
> (4) declare(f, distributes_over(g)) would be more like the
> existing declaration syntax, but I've never shared Maxima's
> hankering for paired arguments. Just put all the arguments
> into one predicate expression.
> (5) The code as it stands doesn't have any effect on
> user-defined infix, prefix, or postfix operators.
> I don't know why that is. I'll look into it some more.
> (6) I guess there should be corresponding
> featurep(f distributes_over g) and remove(f distributes_over g)
> but I haven't gotten to that yet.
> (7) Loopy declarations such as declare(foo distributes_over bar)
> and declare(bar distributes_over foo) cause stack overflow.
> I guess I'll have to fix that.
>
> FWIW
> Robert Dodier
>
> PS. Here's the code, as it stands.
> --------------- distributes_over.mac
> fix ("distributes_over");
>
> load ("distributes_over.lisp");
>
> declare_distributes_over (f, g) :=
> if listp (f)
> then map (lambda ([f1], declare_distributes_over (f1, g)), f)
> elseif listp (g)
> then map (lambda ([g1], declare_distributes_over (f, g1)), g)
> else
> (get (f, "distributes_over"),
> if %% = false
> then
> (put (f, [g], "distributes_over"),
> buildq ([f], lambda ([e], not atom (e) and member (op (e),
> get (f, "distributes_over")))),
> apply (matchdeclare, [g_expr, %%]),
> buildq ([f, g], [f (g_expr), apply (op (g_expr), map (f,
> args (g_expr)))]),
> apply (tellsimp, %%))
> elseif not member (g, %%)
> then put (f, cons (g, %%), "distributes_over"),
> f distributes_over g);
>
> --------------- distributes_over.lisp
> (let (($declare-original (get '$declare 'mfexpr*)))
> (defmspec $declare (expr)
> (let ((x (cadr expr)))
> (if (and (not (atom x)) (eq (caar x) '$distributes_over))
> (meval `(($declare_distributes_over) ,@(cdr x)))
> (apply $declare-original (list expr))))))
> _______________________________________________
> Maxima mailing list
> Maxima at math.utexas.edu
> http://www.math.utexas.edu/mailman/listinfo/maxima
>