2

I wrote this macro that rewrites e.g. (sum-expr (1 2 3)) as (+ 1 2 3):

(defmacro sum-expr (expr-list)
  `(+ ,@expr-list))

=> SUM-EXPR

For example:

(sum-expr ((+ 1 3) (* 3 4) (- 8 4)))

=> 20

How can I define an equivalent function using defun?

3
  • 1
    Do you want the function to take as inputs expressions or a list of numbers to add? Commented May 3, 2021 at 14:33
  • 4
    (reduce #'+ ...) is what you want. There is no purpose in having this be a macro. Commented May 3, 2021 at 15:37
  • this needs a bit more info for a complete answer - do you need to pass it as a quoted list? Since you can't pass ((+ 1 3) (* 3 4) (- 8 4)) as an argument to a function. You need to pass either '((+ 1 3) (* 3 4) (- 8 4)) or (list (+ 1 3) (* 3 4) (- 8 4)). The first one needs a more complex solution; the latter is simpler Commented May 3, 2021 at 20:47

2 Answers 2

2

As @LeonardoDagnino already mentioned it in comment:

(defun sum-expr (lst)
  (apply #'+ lst))

Would be very lispy, but implementation-dependent CALL-ARGUMENTS-LIMIT limits in some implementations the length of lst to 50 as discussed e.g. here .Therefore, the solution with reduce is cleaner.

Sign up to request clarification or add additional context in comments.

Comments

0

Sounds like you need to evaluate the expressions in your list, and then reduce the resulting list by the addition function.

We can evaluate lisp expressions with eval, which we can apply to each element of the input list with mapcar.

We can then use reduce on the resulting list to find the sum.

(defun sum-expr (list)
  (reduce #'+ (mapcar #'eval list)))

This makes a lot of assumptions about the structure and type of your input, but for a simple problem with well-understood inputs, it should be fine.

(You may be interested in Why exactly is eval evil?)

3 Comments

Could also use apply instead of reduce since + already accepts multiple arguments.
You don't need eval if you just rely on normal evaluation order, and reduce is what you use for arbitrary lists. Apply is for argument management, not for shoehorning data into rest arguments.
@Svante If the input specification is more flexible than "a list of expressions", I agree. If, in fact, the requirements are a function that takes a list, I don't see another way. What am I missing?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.