Аргументы функции нескольких типов - PullRequest
6 голосов
/ 07 сентября 2011

Я пытаюсь отложить различные вычисления.У меня есть функции следующей формы,

(defn a-fn [a b]
  (let [a (if (fn? a)
            a
            #(identity a))

        b (if (fn? b)
            b
            #(identity b))]
    (+ (a) (b))))

, это позволяет мне передавать a-fn, значение или функцию, которая возвращает значение,

(a-fn 1 2)    
(defn x [] 1)    
(defn y [] 2)    
(a-fn x y)
(a-fn x 2)

, что я делаю, это сборкасписок функций (например, описанных выше) для работы с некоторыми данными, fns может использовать другие fns для получения своих аргументов, или в некоторых случаях вещи не меняются, и им присваиваются значения в качестве аргументов.Мне было интересно, есть ли лучший способ добиться такого поведения?

Ответы [ 2 ]

6 голосов
/ 07 сентября 2011

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

user=> (defn a-fn [a b] (+ (force a) (force b)))
#'user/a-fn
user=> (a-fn 1 2)
3
user=> (def x (delay 1))
#'user/x
user=> (def y (delay 2))
#'user/y
user=> (a-fn x y)
3
user=> (a-fn x 2)
3

Если вы попробуете что-то вроде (delay (prn :hello) 1), чтобы проверить, когда вычисления выполненыобратите внимание, что печать объекта Delay заставляет его;поэтому (def x (delay ...)) является безопасным, но ввод простого (delay ...) в приглашении REPL не является.

2 голосов
/ 07 сентября 2011

Возможно, есть более элегантный способ сделать то, что вы хотите, но вот, по крайней мере, более общую версию:

(defn delayed [reducer & fs]
  (apply reducer (for [f fs] (if (fn? f) (f) f))))

(def a-fn (partial delayed +))

Так что delayed принимает произвольную функцию и список функций /ценности.Если развернуть все аргументы, а затем применить функцию к ним.Затем мы используем partial, чтобы определить a-fn, используя +:

user=> (a-fn 1 2)
3
user=> (a-fn (constantly 1) 2)
3
user=> (a-fn (constantly 1) 2 4)
7

В качестве альтернативы, delayed может иметь смысл возвращать функцию вместо использования частичного.Обратите внимание, что лучше.

Имя лучше, чем "задержано" приветствуется:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...