Обычные вкусности применяются, когда мы можем предполагать чистоту и ссылочную прозрачность.Мы можем автоматически запоминать горячие точки.Мы можем автоматически распараллеливать вычисления.Мы можем справиться с множеством условий гонки.Мы также можем использовать совместное использование структуры с данными, которые, как мы знаем, не могут быть изменены, например, (квази) примитиву «cons ()» не нужно копировать cons-ячейки в списке, к которому он относится.Эти клетки никак не влияют, если на них указывает другая конс-клетка.Этот пример довольно очевиден, но компиляторы часто являются хорошими исполнителями при выяснении более сложного совместного использования структуры.
Однако на самом деле определить, является ли лямбда (функция) чистой или имеет ссылочную прозрачность, очень сложно в Common Lisp.Помните, что funcall (foo bar) начинается с просмотра (символ-функция foo).Таким образом, в этом случае
(defun foo (bar)
(cons 'zot bar))
foo () является чистым.
Следующая лямбда также чиста.
(defun quux ()
(mapcar #'foo '(zong ding flop)))
Однако позже мы можем переопределить foo:
(let ((accu -1))
(defun foo (bar)
(incf accu)))
Следующий вызов quux () больше не является чистым!Старый чистый foo () был переопределен как нечистая лямбда.Хлоп.Этот пример может быть несколько надуманным, но нередко лексически переопределять некоторые функции, например, с помощью блока let.В этом случае невозможно знать, что произойдет во время компиляции.
Common Lisp имеет очень динамичную семантику, поэтому возможность определить поток управления и поток данных заранее (например, при компиляции)очень тяжело, а в большинстве полезных случаев совершенно неразрешимо.Это довольно типично для языков с динамическими системами типов.В Лиспе есть много распространенных идиом, которые нельзя использовать, если вы должны использовать статическую типизацию.В основном это те, которые противостоят любой попытке сделать многозначительный статический анализ.Мы можем сделать это для примитивов, таких как минусы и друзья.Но для лямбд, связанных с другими вещами, кроме примитивов, мы находимся в гораздо более глубокой воде, особенно в тех случаях, когда нам нужно взглянуть на сложное взаимодействие между функциями.Помните, что лямбда чиста только в том случае, если все лямбды, которые она называет, также чисты.
На моей голове, возможно, с некоторой глубокой макрологией, можно покончить с проблемой переопределения.В некотором смысле каждая лямбда получает дополнительный аргумент, который представляет собой монаду, которая представляет все состояние изображения lisp (очевидно, мы можем ограничить себя тем, на что будет в действительности смотреть функция).Но, вероятно, более полезно иметь возможность декларировать чистоту самостоятельно, в том смысле, что мы обещаем компилятору, что эта лямбда действительно чистая.Последствия, если это не так, тогда не определены, и могут возникнуть всевозможные беспорядки ...