I have a question about passing multiple arguments in a function. Suppose I want to write a function (+- a b c .... n) that is equivalent to
a+b-c+....n
How would I go about this?
You would use a maco defined with 'define-macro', inside a macro you can use a function (args) to get all arguments in a list:
(define-macro (+-)
(let ((result 0) (sign true))
(dolist (p (args))
(if sign (inc 'result (eval p)) (dec 'result (eval p)))
(set 'sign (not sign)))
result))
(+- 1 2 3 4 5) => 3
(apply +- (sequence 1 1000)) => -500
This is a brute force solution, there must be a smarter way to do this, just wanted to show how to use (args).
Lutz
if
(+- a b c .... n)
is equivalent to
a+b-c+....n
rather than
(+- 1 2 3 4 5) => 3
shouldn't the result be:
1+2-3+4-5 => -1
so, if that is the intent, what about
> (define (+- x) (add (first x) (apply 'add (map 'mul (rest x) (series 1 -1 (length (rest x)))))))
> (+- '(1 2 3 4 5))
-1
>
but this is handling just one argument - the list - perhaps a macro is needed to collect up arguments first.
viz
> (define-macro (+-m) (+- (args)))
> (+-m 1 2 3 4 5)
-1
>
so doing it all in one place
> (define-macro (+-) (add (first (args)) (apply 'add (map 'mul (rest (args)) (series 1 -1 (length (rest (args))))))))
> (+- 1 2 3 4 5)
-1
>
Nigel
Nice but: (apply +- (sequence 1 5)) would not work, because you forgot to evaluate the (args).
But building on your idea and allowing also for one argument:
(define-macro (+- )
(let (signs (cons 1 (series 1 -1 (- (length (args)) 1))))
(apply 'add (map 'mul (map eval (args)) signs))))
(+- 1 2 3 4 5) => -1
(apply +- (sequence 1 5) => -1
The trap is, that the sequence of 1's starts with 2 1s (1 1 -1 1 -1 ...). This one works on one argument.
Lutz
Thanks for tidying it up
Nigel