lisp: properly calling a function with 2 parameters which depend on each other

Viewed 80

Let's say, I want to call function foo, which requires 2 arguments a and b. (foo a b).
And in some use cases, the values of those parameters depend on each other, like this:

(let (a
      b)
  (if (something-p)
      (progn 
        (setq a 'a1)
        (setq b 'b1))
    (progn
      (setq a 'a2)
      (setq b 'b2)))
  (foo a b))

Is there a (lisp) pattern for this kind of problem? (Or do I need to write my own macro for that?)

2 Answers

Examples:

Applying a list:

(apply #'foo
       (if (something-p)
          (list 'a1 'b1)
          (list 'a2 'b2)))

Similar, but with multiple values:

(multiple-value-call #'foo
  (if (something)
     (values 'a1 'b1)
     (values 'a2 'b2)))

Binding multiple values:

(multiple-value-bind (a b)
    (if (something)
        (values 'a1 'b1)
        (values 'a2 'b2))
  (foo a b))

Nested let:

(let ((something (something-p)))
  (let ((a (if something 'a1 'b2))
        (b (if something 'b1 'b2)))
    (foo a b)))

Your example does not really illustrate the parameters' mutual interdependence. As for the conditional aspect, you can embed arbitrary conditions into your function call. So you could have e.g.:

(foo (if (something-p) 'a1 'a2)
     (if (something-p) 'b1 'b2))

EDIT: If you're concerned about multiple evaluations of something-p, you can always store the value of a single evaluation in a let variable like this:

(let ((c (something-p)))
  (foo (if c 'a1 'a2)
       (if c 'b1 'b2)))
Related