Анонимная сокращенная функция

Что-то я не понимаю об анонимных функциях, используя короткую нотацию # (..)

Следующие работы:

REPL>  ((fn [s] s) "Eh")
"Eh"

Но это не так:

REPL>  (#(%) "Eh")

Это работает:

REPL> (#(str %) "Eh")
"Eh"

Я не понимаю, почему (# (%) "Eh" ) не работает, и в то же время мне не нужно использовать str in ((fn [s] s) "Eh" )

Они обе анонимные функции, и оба они берут здесь один параметр. Почему сокращенная нотация нуждается в функции, а другая - нет?

Ответ 1

#(...)

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

(fn [arg1 arg2 ...] (...))

(где количество argN зависит от того, сколько% N у вас есть в теле). Поэтому, когда вы пишете:

#(%)

он перевел на:

(fn [arg1] (arg1))

Обратите внимание, что это отличается от вашей первой анонимной функции, которая похожа:

(fn [arg1] arg1)

Ваша версия возвращает arg1 как значение, версия, которая исходит от расширения стенографии, пытается назвать ее функцией. Вы получаете ошибку, потому что строка не является допустимой функцией.

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

Ответ 2

Как уже отмечалось в других ответах, вы отправили #(%) на что-то вроде (fn [arg1] (arg1)), что совсем не совпадает с (fn [arg1] arg1).

@John Flatness указала, что вы можете просто использовать identity, но если вы ищете способ написать identity с помощью макроса отправки #(...), вы можете сделать это следующим образом:

#(-> %)

Объединив макрос отправки #(...) с макросом ->, он расширяется до значения (fn [arg1] (-> arg1)), который снова расширяется до (fn [arg1] arg1), который вам просто нужен. Я также нашел макрокоманду -> и #(...), полезную для написания простых функций, возвращающих векторы, например:

#(-> [%2 %1])

Ответ 3

Когда вы используете #(...), вы можете себе представить, что вы пишете (fn [args] (...)), включая скобки, которые вы начали сразу после фунта.

Итак, ваш нерабочий пример преобразуется в:

((fn [s] (s)) "Eh")

который, очевидно, не работает, потому что вы пытаетесь вызвать строку "Eh". Ваш пример с str работает, потому что теперь ваша функция (str s) вместо (s). (identity s) будет более близким аналогом к вашему первому примеру, так как он не будет принуждать к str.

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