lisp: правильно вызывать функцию с двумя параметрами, которые зависят друг от друга - PullRequest
2 голосов
/ 18 октября 2019

Допустим, я хочу вызвать функцию foo, которая требует 2 аргумента a и b. (foo a b).
И в некоторых случаях использования значения этих параметров зависят друг от друга, например:

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

Существует ли (lisp) шаблон для такого рода проблем? (Или мне нужно написать собственный макрос для этого?)

Ответы [ 2 ]

5 голосов
/ 18 октября 2019

Примеры:

Применение списка:

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

Аналогично, но с несколькими значениями:

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

Связывание нескольких значений:

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

Вложенный let:

(let ((something (something-p)))
  (let ((a (if something 'a1 'b2))
        (b (if something 'b1 'b2)))
    (foo a b)))
3 голосов
/ 18 октября 2019

Ваш пример на самом деле не иллюстрирует взаимозависимость параметров. Что касается условного аспекта, вы можете встраивать произвольные условия в вызов вашей функции. Таким образом, вы можете иметь, например:

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

РЕДАКТИРОВАТЬ: Если вы беспокоитесь о множественных оценках something-p, вы всегда можете сохранить значение одной оценки в переменной let, например:

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