В clojure 1.1 все вызовы были динамическими, что означает, что вы можете переопределить функцию в REPL, и она будет автоматически включена в запущенную программу. Это также было приятно для таких вещей, как dotrace.
В clojure 1.2 многие вызовы кажутся статически связанными, и если я хочу заменить функцию, иногда мне нужно найти все места, где она была вызвана, и поставить # перед ними.
Хуже того, я не могу предсказать, где мне это нужно.
Можно ли вернуться к старому стандарту динамической компоновки? Возможно, если вам нужна дополнительная скорость, вы можете переключить ее обратно на производственное приложение, но для разработки я предпочитаю поведение 1.1.
Я надеюсь на какой-то вариант компилятора, например * warn-on-reflection *.
Edit:
Я запутался в том, что происходит. В частности, здесь представлены две функции. Я предпочитаю поведение второго. Как я могу заставить первого вести себя как второй, как я полагаю, он раньше делал в 1.1?
user> (clojure-version)
"1.2.0"
user> (defn factorial[n] (if (< n 2) n (* n (factorial (dec n)))))
#'user/factorial
user> (require 'clojure.contrib.trace)
user> (clojure.contrib.trace/dotrace (factorial) (factorial 10))
TRACE t1670: (factorial 10)
TRACE t1670: => 3628800
user> (defn factorial[n] (if (< n 2) n (* n (#'factorial (dec n)))))
#'user/factorial
user> (clojure.contrib.trace/dotrace (factorial) (factorial 10))
TRACE t1681: (factorial 10)
TRACE t1682: | (factorial 9)
TRACE t1683: | | (factorial 8)
TRACE t1684: | | | (factorial 7)
TRACE t1685: | | | | (factorial 6)
TRACE t1686: | | | | | (factorial 5)
TRACE t1687: | | | | | | (factorial 4)
TRACE t1688: | | | | | | | (factorial 3)
TRACE t1689: | | | | | | | | (factorial 2)
TRACE t1690: | | | | | | | | | (factorial 1)
TRACE t1690: | | | | | | | | | => 1
TRACE t1689: | | | | | | | | => 2
TRACE t1688: | | | | | | | => 6
TRACE t1687: | | | | | | => 24
TRACE t1686: | | | | | => 120
TRACE t1685: | | | | => 720
TRACE t1684: | | | => 5040
TRACE t1683: | | => 40320
TRACE t1682: | => 362880
TRACE t1681: => 3628800
3628800
Изменить (на весь вопрос и сменить заголовок):
Joost указывает ниже, что на самом деле происходит то, что сам вызов факториала оптимизируется. Я не понимаю, почему это было бы сделано, так как вы не можете делать так много рекурсивных "я" без выдувания стека, но это объясняет наблюдаемое поведение. Возможно, это как-то связано с анонимными самообслуживаниями.
Первоначальная причина моего вопроса заключалась в том, что я пытался написать http://www.learningclojure.com/2011/03/hello-web-dynamic-compojure-web.html, и меня раздражало количество мест, которые у меня были чтобы ввести # ', чтобы получить поведение, которое я ожидал. Это и дотчасть заставляли меня думать, что общее динамическое поведение ушло, и что "на лету" переопределение, которое работает в некоторых местах, должно быть сделано с помощью какого-то умного взлома.
В ретроспективе, кажется, странный вывод, чтобы перейти, но теперь я просто смущен (что лучше!). Есть ли ссылки на все это? Я хотел бы иметь общую теорию о том, когда это будет работать, и когда этого не произойдет.