Самый элегантный/эффективный способ определения функций с использованием одних и тех же переменных

Я определил несколько функций, используя некоторые переменные, которые обычно вычисляются в большинстве из них. Поэтому я использую ключевые слова-аргументы, которые по умолчанию вычисляют нужные значения.

Пример:

(defun f (a b &key (distance (distance a b))) (c a b distance))
(defun g (a b &key (distance (distance a b))) (if (< distance (r a b))
                                                (f a b :distance distance)))
(defun h (a b &key (distance (distance a b))) (d a b distance))
(defun i (a b &key (distance (distance a b))) (g a b :distance distance)
                                              (h a b :distance distance))

Каждая функция должна иметь возможность вызываться отдельно без указания ключевых слов-аргументов.

Но теперь мне также нужно определить вычисление ключевых слов-аргументов в каждой функции.

Есть ли более элегантный/эффективный способ делать такие вещи? (Я думал о ленивом вычислении и динамическом программировании)


person cl-porky11    schedule 29.03.2015    source источник
comment
Можете ли вы привести пример, как «ленивое вычисление» или «динамическое программирование» помогут решить вашу проблему?   -  person Rainer Joswig    schedule 29.03.2015
comment
Я не уверен, если это поможет. Если бы я нашел решение таким образом, я бы не спрашивал. Если бы я мог писать функции нормально, но они оцениваются только один раз при вызове некоторых функций, я думаю, это было бы более элегантно.   -  person cl-porky11    schedule 29.03.2015


Ответы (2)


Вы можете использовать #=:

(defun foo (a b &key #1=(distance (distance a b))) #|...|#)

(defun bar (a b &key #1#) #|... |#)
person Svante    schedule 30.03.2015

Я бы, наверное, попал в макрос. например

 (defmacro def-distance-fun (name &body body)
     `(defun ,name (a b &key (distance (distance a b))) ,@body))

 (def-distance-fun foo
       … blah )

Если имена «a» и «b» являются переменными, вы можете немного поизобретать, предоставив символы переменных в макрос, и макрос может достаточно легко включать привязки только к аргументам ключевого слова, которые вы назвали; например

  (when (member 'distance lambda-list)
      `(distance (distance ,(first lambda-list) ,(second lambda-list))))
person BRPocock    schedule 31.03.2015