В некоторых случаях вы можете поймать ArityException
с; в зависимости от контекста и функции, вызывающей ArityException
.
Я собираюсь сразу признать, что я спекулирую на некоторых аспектах, потому что я никогда раньше не изучал это слишком глубоко.
Сначала посмотрите, что произойдет, если вы вызовете inc
в контексте, в котором очевидно, что количество предоставленных аргументов неверно:
(inc)
CompilerException clojure.lang.ArityException: Wrong number of args (0) passed to: core/inc--inliner--4489, compiling: . . .
Интересная часть inc--inliner--4489
. Если вы посмотрите на определение inc
, к нему будут прикреплены метаданные:
:inline (fn [x] `(. clojure.lang.Numbers (~(if *unchecked-math* 'unchecked_inc 'inc) ~x)))
Раньше я никогда не заглядывал в :inline
слишком глубоко, но я всегда полагал, что это означает, что он попытается встроить вызов (незначительно), чтобы уменьшить накладные расходы. В этом случае он пытается встроить inc
, чтобы он был просто вызовом clojure.lang.Numbers/inc
или clojure.lang.Numbers/unchecked_inc
; в зависимости от состояния *unchecked-math*
. Также обратите внимание, как начинается ошибка:
CompilerException clojure.lang.ArityException
В вашем примере вы не можете поймать прямо (inc)
, потому что этот вызов завершается с ошибкой в время компиляции , прежде чем код даже будет запущен. Он знает, что (inc)
никогда не будет правильным, поэтому он немедленно завершится неудачей. Это хорошая вещь, хотя. (inc)
никогда не будет верным , так что нет смысла пытаться его поймать.
Однако существуют обстоятельства, при которых перехват исключения арности может иметь смысл (хотя, вероятно, есть более эффективные способы решения проблемы *
). Скажем, вы запрещаете вызову inc
, который должен быть встроен, как предложил @Rulle, apply
с аргументами:
(try
(apply inc [])
(catch clojure.lang.ArityException e
(println "Caught!")))
Caught!
Компилятор не может точно знать, произойдет ли сбой inc
, потому что это зависит от количества аргументов, переданных apply
; которые могут зависеть от вещей во время выполнения. В этом случае код на самом деле может быть запущен, а также способен поймать его ArityException
.
Принимая :inline
из уравнения, вы также можете увидеть, что ваша пользовательская функция может поймать свою ArityException
с меньшим количеством суеты, поскольку вызов не встроен, поэтому он не завершится во время компиляции :
(defn hello [arg])
(try
(hello) ; No apply
(catch clojure.lang.ArityException e
(println "Caught!")))
Caught!
*
Не могу сказать, что мне когда-либо приходилось ловить ArityException
, и я не могу вспомнить ни одного обстоятельства, когда это было бы уместно. Даже если вы используете apply
, более разумно было бы заранее проверить аргументы или даже переосмыслить использование apply
. Если использование apply
приводит к ArityException
, возможно, в вашей логике есть недостаток, заключающийся в том, что использование try
просто накладывает пластырь.