Как реализовать лямбду как функцию, вызванную “лямбда” в Clojure?

Я хотел бы смочь определить лямбды с помощью синтаксиса языка Common LISP в Clojure. Например:

(lambda (myarg)
  (some-functions-that-refer-to myarg))

Это должно привести к тому же как:

#(some-functions-that-refer-to %)

В моем случае я знаю, что у меня всегда будет точно один аргумент, настолько возможно, который упрощает вещи. (Но это можно назвать чем-либо - "myarg" или что бы то ни было.)

Я подозреваю, что осуществимое решение к" (defmacro лямбда... ". Если так, я не уверен в лучшем способе продолжиться. Как чисто перевести имя аргумента к %? И как закончить с корректной функцией?

Или, есть ли простое решение, чем запись моего собственного макроса, который на самом деле повторно реализует Clojure... лямбда?

16
задан dirtyvagabond 23 March 2010 в 04:02
поделиться

1 ответ

# (foo%) - это просто сокращение для (fn [arg] (foo arg)) . Нет причин писать макрос, который раскрывается в # (...) . Все % в конструкции # (...) в любом случае сразу же расширяются в генсимы.

user> `#(foo % %1 %2)
(fn* [user/p1__1877 user/p2__1878] 
  (user/foo user/p1__1877 user/p1__1877 user/p2__1878))

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

Разница между (fn [] ...) и (lambda () ...) в этом случае состоит в том, что «fn» короче для ввода, чем «lambda». ", а fn принимает вектор для своих привязок, тогда как lambda принимает список. Если вы используете Clojure, вам в конце концов придется к этому привыкнуть, потому что векторы всегда используются для коллекций привязок, во всех формах do и в для и ] binding и т. д. Причина этого, насколько я понимаю, в том, что списки используются для вызовов функций или макросов, а векторы используются для вещей, которые не являются вызовами (например, списки символов для привязки). Возможно, это упрощает визуальное сканирование кода, чем использование списков до конца. Clojure - это не Common Lisp, и вы испытаете боль, если попытаетесь заставить его быть.

Если вы действительно, действительно хотели это сделать, просто скажу, что вы это сделали:

user> (defmacro lambda [args & body]
        `(fn ~(vec args) ~@body))
user> ((lambda (x) (println x)) "foo")
foo
nil

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

26
ответ дан 30 November 2019 в 21:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: