Скорочена анонімна функція


85

Щось я не розумію в анонімних функціях, використовуючи короткий запис # (..)

Наступні роботи:

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

Але це не означає:

REPL>  (#(%) "Eh")

Це працює:

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

Я не розумію, чому (# (%) "Eh") не працює, і в той же час мені не потрібно використовувати str в ((fn [s] s) "Eh")

Вони обидва анонімні функції, і обидва вони беруть тут один параметр. Навіщо скороченому позначенню потрібна функція, а іншому - ні?

Відповіді:


126
#(...)

це скорочення для

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

(де кількість argN залежить від того, скільки% N у вас в організмі). Отже, коли ви пишете:

#(%)

це перекладено на:

(fn [arg1] (arg1))

Зверніть увагу, що це відрізняється від вашої першої анонімної функції:

(fn [arg1] arg1)

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

Оскільки стенограма містить набір дужок навколо тіла, вона може бути використана лише для виконання одного виклику функції або спеціальної форми.


64

Як вже було чудово зазначено в інших відповідях, #(%)опубліковане вами насправді розширюється до чогось типу (fn [arg1] (arg1)), що зовсім не те саме, що (fn [arg1] arg1).

@John Flatness зазначив, що ви можете просто використовувати identity, але якщо ви шукаєте спосіб писати identityза допомогою #(...)макросу відправлення, ви можете зробити це так:

#(-> %)

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

#(-> [%2 %1])

20

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

Отже, ваш неробочий приклад перетворює на:

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

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

Це має сенс, якщо ви задумаєтесь, оскільки, крім цього абсолютно мінімального прикладу, кожна анонімна функція збирається щось викликати , тому було б трохи нерозумно вимагати іншого вкладеного набору парен, щоб насправді здійснити виклик.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.