Что это действительно означает, что язык программирования без стека?


[111]

См. https://regex101.com/r/ZA4qHz/1/ для отладки.

Соответствующие документы: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp

15
задан Community 23 May 2017 в 11:46
поделиться

2 ответа

Что на самом деле означает, что они не имеют стеков? Означает ли это, что они не используют стек вызовов?

Да, это верно.

Если они не используют стек вызовов, что они используют?

Точная реализация, конечно, варьироваться от языка к языку. В Stackless Python есть диспетчер, который запускает интерпретатор Python, используя самый верхний фрейм и его результаты. Интерпретатор обрабатывает коды операций по мере необходимости, пока не достигнет кода операции CALL_FUNCTION , сигнала, который вы собираетесь ввести в функцию. Это заставляет диспетчера построить новый фрейм с соответствующей информацией и вернуться к диспетчеру с флагом разворачивания. Оттуда диспетчер начинает заново, указывая переводчику на самый верхний кадр.

Языки без стеков избегают стеков вызовов по ряду причин, но во многих случаях они используются, так что некоторые программные конструкции становятся намного проще для реализации. Каноническим является продолжений . Продолжения - это очень мощные, очень простые структуры управления, которые могут представлять любую из обычных структур управления, с которыми вы, вероятно, уже знакомы (, тогда как , делают , if , switch и так далее).

Если это сбивает с толку, вы можете попробовать обернуть голову вокруг статьи в Википедии и, в частности, аналогии с продолжительным сэндвичем :

Скажем, вы на кухне перед холодильником и думаете о сэндвиче. Вы берете продолжение прямо там и суете его в карман. Затем вы достаете немного индейки и хлеба из холодильника и делаете себе бутерброд, который сейчас стоит на прилавке. Вы вызываете продолжение в своем кармане, и вы снова стоите перед холодильником, думая о бутерброде. Но, к счастью, на прилавке есть бутерброд, и все материалы, использованные для его приготовления, исчезли. Итак, вы съели его.

15
ответ дан 1 December 2019 в 02:46
поделиться

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

Чтобы эмулировать традиционный вызов / возврат в этой модели, вместо нажатия на адрес возврата и ожидания остатка кадра чтобы остаться нетронутым, вызывающая сторона закрывает оставшуюся часть своего кода и все переменные, которые все еще необходимы (остальные освобождаются). Затем он выполняет вызываемый вызов вызываемого абонента, передавая это продолжение в качестве аргумента. Когда вызываемый «возвращается», он делает это, вызывая это продолжение, передавая возвращаемое значение в качестве аргумента.

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

  1. блоки исключений / окончаний / и т. д. очень легко моделируются - если вы можете передать одно продолжение «возврата» в качестве аргумента, вы можете передать 2 (или более) так же легко. Блоки lisp-y «обработчик условия» (которые могут возвращать или не возвращать управление вызывающей стороне) также просты - передать продолжение для оставшейся части этой функции, которая может вызываться или не вызываться.
  2. Аналогично, множественные возвращаемые значения стало проще - передайте несколько аргументов в продолжение.
  3. Возвращаемые временные значения / копирование больше не отличаются от передачи аргументов функции. Это часто облегчает устранение временных.
  4. Оптимизация хвостовой рекурсии тривиальна - вызывающий просто передает полученное продолжение «возврат», а не захватывает новое.
11
ответ дан 1 December 2019 в 02:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: