Clojure a-t-il des continuations / coroutines / etc?

20

J'ai commencé à programmer avec Python, et j'étais vraiment confus par des concepts comme les coroutines et les fermetures.

Maintenant, je pense que je les connais à un niveau superficiel, mais je n'ai jamais ressenti ce moment "d'éveil", alors j'ai choisi d'apprendre Clojure. J'ai acheté le livre de Stuart Halloway et c'est bien, mais quand j'ai regardé l'index, il n'y avait pas de mots comme coroutine ou suite. Je les ai recherchés sur Google, mais il n'y a rien non plus.

Donc, ma question est:

Clojure a-t-il des continuations ou des coroutines pour effectuer des tâches comme le ping-pong sans débordement de pile?

Exemple Python (bien que Python standard ne prenne pas en charge une version complète de cette coroutine symétrique):

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

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

Réponses:

20

Clojure n'a pas d'appel / cc, mais vous ne voulez quand même pas de continuations non limitées .

Nous plaidons contre en call/cctant que fonctionnalité de langage de base, comme l'opération de contrôle distinguée pour implémenter nativement la relégation de tous les autres dans les bibliothèques. La primitive call/ccest une mauvaise abstraction - dans diverses significations de «mauvais» illustrées ci-dessous, - et sa capture de la poursuite de l'ensemble du programme n'est pas pratiquement utile. La seule récompense pour le travail acharné pour capturer efficacement toute la suite est un travail plus dur pour contourner la capture de la suite entière. Les utilisateurs et les implémenteurs sont mieux servis avec un ensemble de primitives de contrôle bien choisies de divers degrés de généralité avec des interactions bien pensées ...

... L'offre en call/cctant que fonctionnalité de contrôle de base en termes de laquelle toutes les autres installations de contrôle devraient être mises en œuvre s'avère une mauvaise idée. Les performances, les fuites de mémoire et de ressources, la facilité de mise en œuvre, la facilité d'utilisation, la facilité de raisonnement sont tous contre call/cc. S'il y a vraiment une fonction de contrôle distinguée à implémenter en tant que primitive, avec d'autres reléguées dans les bibliothèques, ce n'est pas le cas call/cc.

David Nolen a écrit une bibliothèque de continuations délimitées pour Clojure. Essaye le!

délimiter

Une bibliothèque de continuations délimitées pour Clojure 1.4.0 (et 1.3.0). Portions basées sur cl-cont de Slava Akhmechet ( http://defmacro.org ) ...

Frank Shearar
la source
2

Bien que Clojure n'ait pas de continuations ou de coroutines de première classe intégrées en tant que fonctionnalité de base, il est possible d'implémenter les vôtres.

Par exemple, core.async est une bibliothèque Clojure qui implémente le modèle CSP (Concurrent Sequential Processes). Il utilise une gomacro pour transformer le code qu'il contient en une machine à états. Bien qu'il ne s'agisse pas exactement de coroutines en soi, il peut être utilisé pour implémenter les mêmes modèles.

Il y a aussi pulley.cps , un compilateur de macros que j'ai créé qui transforme (via cps/ cps-fnmacros) le code Clojure écrit en style direct en style passant par la continuation. À ma connaissance, il s'agit du programme Clojure sur le thème de la continuation le plus complet. Il prend en charge la liaison dynamique, les exceptions, les appels entre le code natif et le code transformé (bien que la continuation ne soit pas maintenue dans tous les contextes). Pour le moment, seules les suites abortives (c'est-à-dire traditionnelles call-cc) sont prises en charge, mais j'ai des plans pour mettre en œuvre des suites délimitées à l'avenir.

Bien que pulley.cps ne fournisse pas directement de coroutines en soi, call-ccil est relativement simple de mettre en œuvre la vôtre. En fait, l'un des exemples est une simple mise en œuvre du multitâche coopératif . Ceci est développé dans l' exemple CSP . Il y a aussi un exemple Ping-Pong , mais c'est plus un exemple d'optimisation des appels de queue que des coroutines.

Bien entendu, ces types de transformations sont plus efficaces lorsqu'elles sont appliquées à l'ensemble du programme. Malheureusement, cela n'est pas possible avec les macros seules, qui sont localisées. Pourtant, même des transformations localisées peuvent être très efficaces.

Nathan Davis
la source
1

Clojure a-t-il des continuations ou des coroutines pour effectuer des tâches comme le ping-pong sans débordement de pile?

Vieille question, donc je ne suis même pas sûr si cette fonctionnalité était disponible à l'époque, mais pour tous ceux qui souhaitent implémenter une sorte de fonctionnalité "ping-pong", consultez le trampoline !

Je viens de le découvrir comme une réponse à ma question sur le style de continuation-passage efficace dans Clojure, ici: /programming/50952443/continuation-passing-style-does-not-seem-to-make-a -difference-in-clojure / 50955276 # 50955276 et je pense que c'est juste le boulot. J'en avais entendu parler il y a quelque temps, mais je n'avais jamais enquêté complètement. Plus me tromper. Contrairement à la plupart des autres solutions proposées, cela fonctionne simplement .

====== PS. Beaucoup d'informations sur le tutoriel en ligne,] voici quelques-unes que j'ai trouvées utiles

alex gian
la source
1
peut-être linkify trampoline pour pointer vers la documentation?
esoterik