Послесловие Clojure не выполняется из-за ошибки синтаксиса - почему?

В этой функции:

(defn my-post 
  [a] 
  {:post (number? %)}
  a)

Постословие не выполняется (или, по крайней мере, не вызывает ошибку утверждения). Теперь я знаю, что это должно было быть:

(defn my-post 
  [a] 
  {:post [(number? %)]} ;; note the square brackets around the expression
  a)

На самом деле это работает правильно.

Проблема в том, что это терпело неудачу, и потребовалось некоторое время, чтобы выяснить, что случилось. Нет синтаксических ошибок, исключений во время выполнения.

I would like to understand what Clojure does with this code, in order to understand why Clojure didn't complain. Macro expansions? Destructuring? Does the code just disappear if it doesn't see square braces?

3
Пожалуйста, объясните, что это за сообщение? Я не могу понять, какова цель этого метода.
добавлено автор Abimaran Kugathasan, источник

1 ответы

http://clojure.org/special_forms documents that the condition-map for fn (thus also defn) should be of the form:

{:pre [pre-expr*]
 :post [post-expr*]}

{:post (number? %)} will result in (number? %) being treated as a sequence of assertions, which means it's interpreted as two separate assertions: number? and %.

user> (macroexpand-1 '(fn [a] {:post (number? %)} a))
(fn*
 ([a]
  (clojure.core/let [% a]
   (clojure.core/assert number?)
   (clojure.core/assert %)
   %)))

(assert number?) always passes as long as number? is defined and has a true value, which being a core function, it probably does. (clojure.core/assert %) passes if % has a true value. It's bound to the value of your argument a via the let, so it passes if a has a true value. Try calling (my-post nil) with your first function definition and it'll fail the assertion.

user> (my-post nil)
; Evaluation aborted.
; Assert failed: %
;  [Thrown class java.lang.AssertionError]

Если вы правильно поместите свое пост-условие в вектор, он будет расширяться следующим образом:

user> (macroexpand-1 '(fn [a] {:post [(number? %)]} a))
(fn*
 ([a]
  (clojure.core/let [% a]
   (clojure.core/assert (number? %))
   %)))
5
добавлено
pro.jvm
pro.jvm
3 503 участник(ов)

Сообщество разработчиков Java Scala Kotlin Groovy Clojure Чат для нач-их: @javastart Наш сайт: projvm.com projvm.ru Наш канал: @proJVM Вакансии: @jvmjobs Конфы: @jvmconf

Clojure — русскоговорящее сообщество
Clojure — русскоговорящее сообщество
433 участник(ов)

Общаемся на темы, посвященный Clojure. Решаем проблемы, обмениваемся опытом и делимся новостями. Вакансии и поиск работы: @clojure_jobs Вам могут быть интересны: @javascript_ru, @nodejs_ru, @ruby_ru, @devops_ru, @devops_jobs