Есть ли у Clojure продолжения / сопрограммы / и т. Д.?

20

Я начал программировать на Python, и меня действительно смутили такие понятия, как сопрограммы и замыкания.

Теперь я думаю, что знаю их на каком-то поверхностном уровне, но я никогда не чувствовал этот момент «просветления», поэтому я решил изучать Clojure. Я купил книгу Стюарта Хэллоуэя, и она хороша, но когда я посмотрел на указатель, не было слов, таких как сопрограмма или продолжение. Я гуглил их, но там тоже ничего нет.

Итак, мой вопрос:

Есть ли у Clojure продолжения или сопрограммы для выполнения задач типа пинг-понга без переполнения стека?

Пример Python (хотя стандартный Python не поддерживает полнофункциональную версию этой симметричной сопрограммы):

def ping():
  while 1:
   print "ping"
   function to switching to pong

def pong():
  while 1:
   function to switching to ping
   print "pong"
послушник
источник

Ответы:

20

У Clojure нет call / cc, но вы все равно не хотите неограниченных продолжений .

Мы выступаем против call/ccв качестве основной функции языка, как отличительной управляющей операции для реализации естественного перевода всех остальных к библиотекам. Примитив call/ccявляется плохой абстракцией - в различных значениях «плохой», показанной ниже, - и его захват продолжения всей программы практически бесполезен. Единственная награда за усердную работу по эффективному захвату всего продолжения - это более тяжелая работа, чтобы обойти захват всего продолжения. И пользователям, и разработчикам лучше обслуживать набор правильно выбранных управляющих примитивов различной степени универсальности с хорошо продуманными взаимодействиями ...

... Предложение call/ccв качестве основной функции управления, с точки зрения которой должны быть реализованы все другие средства управления, оказывается плохой идеей. Производительность, утечка памяти и ресурсов, простота внедрения, простота использования, простота рассуждений - все это противоречит call/cc. Если есть действительно одна особенность управления, которую нужно реализовать в качестве примитива, а другие отправляются в библиотеки, это не так call/cc.

Дэвид Нолен написал библиотеку продолжений с разделителями для Clojure. Попробуйте!

delimc

Библиотека продолжений с разделителями для Clojure 1.4.0 (и 1.3.0). Порции на основе кл-конт Славы Ахмехета ( http://defmacro.org ) ...

Фрэнк Шиарар
источник
2

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

Например, core.async - это библиотека Clojure, которая реализует модель CSP (параллельные последовательные процессы). Он использует goмакрос для преобразования кода в конечный автомат. Хотя это не совсем сопрограммы как таковые, они могут быть использованы для реализации тех же шаблонов.

Существует также pulley.cps , созданный мной макрос-компилятор, который преобразует (через cps/ cps-fnmacros) код Clojure, написанный в прямом стиле, в стиль передачи продолжения. Насколько мне известно, это самая полная программа Clojure на тему продолжения. Он поддерживает динамическое связывание, исключения, обратный вызов между собственным и преобразованным кодом (хотя продолжение не поддерживается в разных контекстах). На данный момент call-ccподдерживаются только неудачные продолжения (то есть традиционные ), но у меня есть планы реализовать продолжения с разделителями в будущем.

Несмотря на то, что pulley.cps напрямую не предоставляет сопрограммы как таковые, call-ccреализовать его самостоятельно относительно просто. Фактически, один из примеров - простая реализация совместной многозадачности . Это дополнительно основано на примере CSP . Есть также пример Ping-Pong , но это скорее пример оптимизации хвостовых вызовов, чем сопрограмм.

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

Натан Дэвис
источник
1

Есть ли у Clojure продолжения или сопрограммы для выполнения задач типа пинг-понга без переполнения стека?

Старый вопрос, так что я даже не уверен, была ли эта функция доступной в то время, но для любого, кто хочет реализовать какую-либо функциональность «пинг-понга», посетите батут !

Я только что обнаружил это как ответ на мой вопрос об эффективном стиле прохождения продолжения в Clojure, здесь: /programming/50952443/continuation-passing-style-does-not-seem-to-make-a -difference-in-clojure / 50955276 # 50955276 и я думаю, что это просто работа. Я слышал об этом некоторое время назад, но никогда полностью не исследовал. Больше обманешь меня. В отличие от многих других предлагаемых решений, это просто работает .

====== PS. Множество учебной информации в Интернете,] вот несколько, которые я нашел полезными

Алекс Джиан
источник
1
может быть, связать батут, чтобы указать на документацию?
esoterik