Passing multiple arguments

Started by Jeremy Dunn, November 04, 2004, 03:18:23 PM

Previous topic - Next topic

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

#1
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

nigelbrown

#2
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

#3
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

nigelbrown

#4
Thanks for tidying it up

Nigel