Passing multiple arguments

For the Compleat Fan
Locked
Jeremy Dunn
Posts: 95
Joined: Wed Oct 13, 2004 8:02 pm
Location: Bellingham WA

Passing multiple arguments

Post by Jeremy Dunn »

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?

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

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:

Code: Select all

(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

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia

Post by nigelbrown »

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

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

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:

Code: Select all

(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

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia

Post by nigelbrown »

Thanks for tidying it up
Nigel

Locked