Я читал о стековых языках программирования, таких как FORTH и Cat , и кажется, что, учитывая их природу, они могут выполнять только одно действие за раз, независимо от их парадигмы (FORTH обязателен, тогда как Cat функционален).
Императивный язык изменил бы стек, а чисто функциональный язык, такой как Joy , вернул бы новый стек, но дело в том, что одновременно используется только один стек.
Итак, могут ли языки программирования на основе стека быть параллельными? Могут ли они достичь параллелизма, используя несколько стеков одновременно или что-то похожее?
Можно ли реализовать ленивую оценку на языке программирования на основе стека?
Пожалуйста, поправьте меня, если я что-то неправильно понимаю относительно языков и понятий, упомянутых выше
concurrency
stacks
evaluation-strategies
Армандо Х.
источник
источник
Ответы:
Конечно.
Уже для обычных языков многопоточность обычно означает наличие нескольких стеков вызовов. Было бы совершенно естественно предоставить каждому потоку свой стек данных. Было бы просто иметь актера, скажем, тело которого было реализовано кодом на языке стеков. Явный параллелизм в духе
par
аннотаций GHC должен быть достаточно простым. Основная проблема с параллельным выполнением вещей заключается в том, что вы не знаете, каким будет эффект стека кода, пока вы его не выполните. Однако, используя Joy-подобный синтаксис, можно представить,[a b c] par
что он выполняетa b c
или против пустого стека или копии стека и сохранения только самого верхнего элемента стека по окончании (или подталкивания некоторого фиктивного значения, если стек пуст). Вы можете представить варианты. Неявный параллелизм было бы сложнее сделать наивно по сравнению, скажем, с чисто функциональным языком, но, безусловно, можно было бы сделать и это. Скомпилированный код пользовательского комбинатора часто не слишком отличается от «нормального» кода.Неизвестные эффекты стека снова сложная часть. Если вы разрабатываете язык так, чтобы все эффекты стека могли быть определены статически, то это не кажется слишком сложным. Если у вас лень быть явным, то это также кажется относительно простым и будет выглядеть примерно как цитаты Джой и
i
. Один язык, который называет себя ленивым конкатенационным языком, похоже, сочетает в себе оба вышеуказанных подхода из того, что я могу сказать. Я действительно не понимаю, как неявно ленивый конкатенационный язык будет работать перед лицом эффектов динамического стека, по крайней мере, не в какой-то неопределенной форме, но это может быть просто недостатком воображения с моей стороны.Между прочим, для языков на основе стека нередко бывает несколько стеков, например, у Forth есть стек данных и стек возвратов, в который вы также можете поместить произвольные данные.
источник
Я немного знаю о FORTH, поэтому я ограничусь этим. Это язык низкого уровня, предоставляющий вам как программисту доступ ко всем аппаратным ресурсам. Так что вы можете делать все что угодно.
совпадение
Для того, чтобы иметь параллельные программы (edit: используется для обозначения реальных параллельных программ), вам нужны как минимум два исполнительных блока (CPU). Было бы довольно тривиально внедрить слово в FORTH, например, «запустить это слово на процессоре 2, используя эти два аргумента». Слово будет распределять два необходимых стека на процессоре 2 и запускать слово. Вам нужно было бы ограничить себя в том, какие именно конструкции вы можете использовать в этой программе.
Если количество одновременных программ больше, чем количество исполняемых модулей, вы бы пошли для программ «псевдо-параллелла». В принципе, есть два способа сделать это: сопрограммы или упреждающая многозадачность. В любом случае возможно (не просто, но хорошо описано в литературе), как этого добиться, и FORTH позволяет вам получить доступ ко всем нужным материалам низкого уровня.
Ленивая оценка
Конечно, вы можете сделать это на FORTH, как и на любом другом языке программирования. Он не будет таким элегантным или «встроенным», как, скажем, в Haskell. Я буду использовать очень наивный пример.
Идея состоит в том, что вы определяете «функцию» (здесь используется свободно), которая возвращает набор вещей. Одним из примеров будет функция, которая возвращает все целые числа. Затем вы выполняете операции на этом множестве, и когда вы закончите, дайте результат. Например, вы можете захотеть суммировать все целые числа до тех пор, пока сумма не станет больше 1000. Не ленивая оценка сначала будет распределять все целые числа в виде набора, что невозможно, поскольку существует бесконечное число целых чисел. Затем он начал бы работать над этим набором. Ленивая реализация будет иметь способ «дать мне следующее значение в наборе». Для этого на самом деле нужна только одна переменная в функции "last value give".
Haskell делает вещи таким образом. Конечно, он обрабатывает более сложные ситуации, но идея та же. Это приукрашивает оценку таким образом, чтобы вы, как программист, могли сосредоточиться на проблеме, а не на том, как ее решить.
источник