Подтвердить что ты не робот

Как `let` реализован в Clojure и каковы его накладные расходы?

Я вижу два способа реализации привязок let. Во-первых, как известно из SICP, let может быть реализовано как лямбда-функция. Это удобно и просто, но с учетом того факта, что каждая лямбда (fn) переводится в отдельный класс в JVM, а количество раз let используется в средней программе, это кажется очень и очень дорогостоящим.

Во-вторых, привязки let могут быть переведены непосредственно в локальные переменные Java . Это дает очень небольшие накладные расходы, но сохранение привязок в стеке нарушает семантику языка: в этом случае создание закрытий просто невозможно - сохраненные значения будут уничтожены сразу после разворачивания стека.

Итак, какова фактическая реализация, используемая в Clojure? Понятно, что указывается на соответствующие строки в Clojure.

4b9b3361

Ответ 1

let -переменные переменные сохраняются как окончательные локальные значения в стеке.

Поскольку они являются окончательными, они могут быть привязаны к закрытию, если это необходимо (это аналогично тому, как вы можете использовать конечную локальную переменную в анонимном внутреннем классе в Java). Под капотом JVM копирует значение в объект, представляющий замыкание (где он хранится как окончательное поле). В результате закрытие все еще работает даже после того, как рама стека уходит.

В целом, ограниченные переменные чрезвычайно низки накладные расходы, вы не должны вообще колебаться от их использования с точки зрения производительности. Вероятно, на JVM не может быть лучше.

Ответ 2

Локальными переменными являются указатели, выделенные в стеке, указывающие на значения/объекты в куче. Указатель выходит из области видимости, но объект остается в живых, пока у него остается указатель.