Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. Siebel дает обширное краткое изложение (для простых случаев так или иначе) возможных источников утечек, и нет ни одного из тех здесь. Оба value
и factor
оценены только однажды и в порядке, и rem
не имеет никаких побочных эффектов.
Это не хороший Lisp хотя, потому что нет никакой причины использовать макрос в этом случае. Функция
(defun multp (value factor)
(zerop (rem value factor)))
идентично для всех практических целей. (Отметьте использование zerop
. Я думаю, что это делает вещи более ясными в этом случае, но в случаях, где необходимо выделиться, что значение Вы тестируете, могло бы все еще быть значимым, если это - что-то другое, затем обнуляют, (= ... 0)
могло бы быть лучше),
Ваш макрос выглядит хорошо мне. Я не знаю, каков текучий макрос, но Ваш довольно прост и не требует никакого gensyms. До, если это - "хороший" Lisp, мое эмпирическое правило состоит в том, чтобы использовать макрос только, когда функция не сделает, и в этом случае функция может использоваться вместо Вашего макроса. Однако, если этим решением работы для Вас там не является никакая причина не использовать его.
Ну, в принципе пользователь мог сделать это:
(flet ((= (&rest args) nil))
(multp 40 10))
который оценил бы к NIL... за исключением того, что CL ANSI делает его недопустимым для повторного переплетения наиболее стандартных символов, включая CL: =, таким образом, Вы находитесь на безопасной стороне в данном случае.
В generial, конечно, необходимо знать об обеих справочной непрозрачности (получающий идентификаторы от контекста, макрос расширен в), и макро-негигиена (пропускающий идентификаторы к расширенному коду).
Нет, никакой символ, представленный в "лексическом закрытии макроса", не выпущен к внешней стороне.
Обратите внимание, что утечка является не ОБЯЗАТЕЛЬНО плохой вещью, даже если случайная утечка почти всегда. Для одного проекта я продолжил работать, я нашел, что макрос, подобный этому, был полезен:
(defmacro ana-and (&rest forms)
(loop for form in (reverse forms)
for completion = form then `(let ((it ,form))
(when it
,completion))
finally (return completion)))
Это позволило мне добираться, "замыкание накоротко" вещей должно было быть сделано в последовательности с аргументами, перенесенными от предыдущих вызовов в последовательности (и отказ, сообщенный путем возврата NIL). Определенный контекст, от которого этот код, для рукописного синтаксического анализатора для конфигурационного файла, который имеет cobbled-together-enough синтаксис, что запись надлежащего синтаксического анализатора с помощью парсера-генератора была большим количеством работы, чем прокрутка руки.