maps_over_lists or distribute_over



Sometimes ago, I have proposed a bit of code to support the mapping of
functions with one argument over lists, matrices and equations more
generally:

((and (mbagp (cadr x))
      $listarith
      (get (caar x) 'maps_over_lists))
 ;; A list or matrix, $listarith is T and the function has the
 ;; property to map over lists.
 ;; Simplify e.g. f([x,y,z]) -> [f(x),f(y),f(z)]
 ;; Only functions with one argument can have this property.
 ;; This code does not check it, but generates a Lisp error
 ;; if the property 'maps-over-lists is provided for a function
 ;; with more than one argument.
 (cons (caadr x)
       (mapcar #'(lambda (u) (simplify (list (car x) u)))
               (cdadr x))))

We can support the property for functions with one argument, e.g. 

(dolist (x '(%sin 
             %cos 
             %tan))
  (setf (get x 'maps_over_lists) t))

I have got the feedback from Robert, that it might be better to
generalize this even more to allow declarations like

   declare(foo, distribute_over("[")

This is a more general second attempt for an extension to the function
simplifya to support the mapping over a general operator:

((and (not (atom (cadr x)))
      (not (atom (caadr x)))
      (member (caaadr x) (get (caar x) 'distributes_over))
      ;; Do not distribute of lists, if $listarith is false
      (or $listarith (not (eq (caaadr x) 'mlist))))
 (cons (caadr x)
       (mapcar #'(lambda (u) (simplify (list (car x) u))) (cdadr x))))

The operators are stored on the property list in a list to the indicator
'distributes_over. With the following declarations we get the
functionality of maps_over_lists too:

(dolist (x '(%sin 
             %cos 
             %tan))
  (setf (get x 'distributes_over) '(mlist $matrix mequal)))

I have started to write an extension to the function declare to allow
the declaration distribute_over too. But I have got a problem. The
function declare is only prepared to accept atoms as a parameter.
Therefore, to get the proposed syntax declare(foo, distribute_over(bar))
the function declare has to be extended. 

Conclusions:

1. 
The first attempt generalizes the property maps_over_lists for functions
with one argument. Functions with the property maps_over_lists behave
like the implemented arithmetic operators "+", "*", "^", e.g.

   sin([a, b, c]) --> [sin(a), sin(b), sin(c)]

Only the mapping over lists, matrices and equations is supported. It is
easy to implement an extension to the function declare to allow user
defined declarations like

  declare(foo, maps_over_lists)

2.
The second attempt gives in a first step the equivalent functionality
for the user. This implementation can be extended to support not only
lists, matrices, and equations, but any other operator too. The
operators are collected in a list on the property list.
To allow the syntax declare(foo, distribute_over(bar)) the function
declare has to be extended. Another way might be to introduce a new
function like

  declare_distribute_over(foo, bar)


I think we should start with an implementation to support the mapping of
functions more generally. I like both approaches. The first one is more
simple and the second one is more general.

The testsuite has no problems with both solutions.

Dieter Kaiser