Передача списка функций в 'map' в clojure дает ноль - PullRequest
1 голос
/ 06 марта 2019

Я пробую несколько примеров clojure.

(def sum #(reduce + %))

(def avg #(/ (sum %) (count %)))

(defn stats
  [numbers]
  (map #(% numbers) '(sum, avg)) ;;works when it is [sum avg]
  )

Когда я вызываю функцию статистики

 (stats [1 24  235 34511 0 14])

возвращает (nil nil). Но если я изменю код, указанный в комментарии, он вернет ожидаемый результат.

(34785 11595/2)

Почему нельзя передать функции в виде списка?

1 Ответ

7 голосов
/ 06 марта 2019

Вы можете передать функции в аргументе коллекции в map, но префикс ' в вашем примере это цитирование списка, поэтому содержимое - это символы sum и avg вместо значений .

'(sum avg)     ;; quoted list, contents are symbols
'[sum avg]     ;; quoted vector, contents are symbols
(list sum avg) ;; list of the functions, using `list` fn to create a list
[sum avg]      ;; vector of the functions

' является сокращением для quote.

Литералы без кавычек обрабатываются специально. Clojure интерпретирует литерал списка без кавычек как вызов, где первый элемент в списке ссылается на то, что вызывается. Например, это вызовет функцию sum, передав функцию avg в качестве первого аргумента (который не будет работать):

(sum avg)

Путем map проверки функции type над списками в кавычках и без кавычек мы можем увидеть разницу в типах элементов списка:

user=> (map type '(conj assoc))
(clojure.lang.Symbol clojure.lang.Symbol)          ;; symbols
user=> (map type (list conj assoc))
(clojure.core$conj__5112 clojure.core$assoc__5138) ;; fn values

Вот еще один подробный ответ о цитировании: Использование цитаты в Clojure

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