Implementación de soporte "generador" en un idioma personalizado -- dsl campo con yield campo con generator camp Relacionados El problema

Implementing “Generator” support in a custom language


3
vote

problema

Español

Tengo un poco de fettish para el diseño del idioma y actualmente estoy jugando con mi propio lenguaje de pasatiempo. ( http://rogeralsing.com/2010/2010/2010/04/14/Playing- con -lastic / )

Una cosa que realmente hace que mi mente sangra es "generadores" y la palabra clave "rendimiento". Sé que C # utiliza la transformación AST para transformar métodos enumeradores en statemachines.

¿Pero cómo funciona en otros idiomas? ¿Hay alguna manera de obtener el apoyo del generador en un idioma sin transformación AST? p.ej. ¿Languajes como Python o Ruby Resort a las transformaciones de ATT para resolver esto a?

(la pregunta es cómo se implementan los generadores bajo el capó en diferentes idiomas, no cómo escribir un generador en uno de ellos)

Original en ingles

I've got a bit of fettish for language design and I'm currently playing around with my own hobby language. (http://rogeralsing.com/2010/04/14/playing-with-plastic/)

One thing that really makes my mind bleed is "generators" and the "yield" keyword. I know C# uses AST transformation to transform enumerator methods into statemachines.

But how does it work in other languages? Is there any way to get generator support in a language w/o AST transformation? e.g. Does languages like Python or Ruby resort to AST transformations to solve this to?

(The question is how generators are implemented under the hood in different languages, not how to write a generator in one of them)

        
 
 

Lista de respuestas

5
 
vote
vote
La mejor respuesta
 

Los generadores son básicamente seminorutinas con algunas limitaciones molestas. Entonces, obviamente, puede implementarlos utilizando semi-corporaciones (y coroutinas completas, por supuesto).

Si no tiene coroutinas, puede usar cualquiera de las otras construcciones de flujo de control universal. Hay muchas construcciones de flujo de control que son "universales" en el sentido de que cada de control de control (incluidas todas las otras construcciones de flujo de control universal), incluidas las corovas y, por lo tanto, los generadores pueden ser (más o menos ) Trivialmente transformado en solo ese constructo universal.

El más conocido de esos es probablemente t_vertices3 . Con solo t_vertices4 , puede construir any otra construcción de flujo de control: t_vertices5 , t_vertices6 , t_vertices7 < / Código>, t_vertices8 , t_vertices9 , excepciones, hilos, llamadas de subrutina, llamadas de métodos, llamadas de función, etc., y, por supuesto, también corovas y generadores.

Casi todos los compatibles con las CPU vert_color0 (Aunque en una CPU, generalmente lo llaman vert_color1 ). De hecho, en muchos CPU, vert_color2 es el constructo de flujo de control solo , aunque hoy soporte nativo para al menos las llamadas subrutinas ( 99887776623 ) y tal vez Una forma primitiva de manejo de excepciones y / o primitivas de concurrencia (comparación y intercambio) generalmente también se construye.

Otro primitivo de flujo de control conocido son continuaciones. Las continuaciones son básicamente una variante más estructurada, mejor manejable y menos malvada de vert_color4 , especialmente popular en idiomas funcionales. Pero también hay algunos idiomas de bajo nivel que basan su flujo de control en continuaciones, por ejemplo, la máquina virtual de loros utiliza continuaciones para el flujo de control y creo que incluso hay algunas CPU basadas en la continuación en algún Laboratorio de Investigación en algún lugar.

c tiene una especie de forma de "mierda" de continuaciones ( vert_color5 y vert_color6 ), que son mucho menos potentes y menos fáciles de usar que las continuaciones "reales" , pero son lo suficientemente poderosos para implementar generadores (y, de hecho, pueden usarse para implementar continuaciones completas).

En una plataforma UNIX, vert_color7 se puede usar como una alternativa de nivel más potente y superior a vert_color8 / vert_color9 .

Otra construcción de flujo de control que es conocida, pero que probablemente no se mueva a la mente como un sustrato de bajo nivel construya las construcciones de flujo de control en la parte superior de, son excepciones. Hay un papel que muestra que las excepciones pueden ser más poderosas que las continuaciones, lo que hace que las excepciones sean esencialmente equivalentes a IndexVBOID0 y, por lo tanto, universalmente poderoso. Y, de hecho, las excepciones son a veces se utilizan como construcciones de flujo de control universal: el proyecto Microsoft Volta, que compiló .NET BYTECODE a JavaScript, usó excepciones de JavaScript para implementar .NET. HASTRAS Y GENERADORES.

No universal, pero probablemente lo suficientemente poderoso como para implementar generadores es simplemente optimización de llamadas de cola simple. (Yo podría estar equivocado, sin embargo. Desafortunadamente, no tengo una prueba). I Piensa Puede transformar un generador en un conjunto de funciones mutuamente recursivas. Sé que las máquinas estatales se pueden implementar utilizando llamadas de cola, por lo que también estoy seguro de que los generadores pueden, después de todo, C # implementa generadores como máquinas estatales. (Creo que esto funciona especialmente bien junto con la evaluación perezosa.)

Por último, pero no menos importante, en un idioma con una pila de llamadas reificadas (como la mayoría de las pequeñas smalltalks, por ejemplo), puede construir bastante tipo de construcciones de flujo de control que desee. (De hecho, una pila de llamadas reificada es básicamente el equivalente de nivel de bajo nivel procesal a la continuación funcional de alto nivel).

Entonces, ¿qué se ven Otras implementaciones de generadores?

LUA no tiene generadores per se, pero tiene corporales asimétricas completas. La implementación principal de C utiliza IndexVBOID1 / IndexVBOID2 para implementarlos.

Ruby tampoco tiene generadores per se, pero tiene IndexVBOID3 S, que se puede utilizar como generadores. IndexVBOID4 S No es parte del idioma, son una característica de la biblioteca. La IRM implementa IndexVBOID5 S utilizando continuaciones, que a su vez se implementan utilizando IndexVBOID6 / IndexVBOID7 . YARV implementa IndexVBOID8 S usando IndexVBOID9 s (que es el hechizo de ruby "coroutines"), y aquellos se implementan utilizando NULL0 / NULL1 . Creo que Jruby actualmente implementa NULL2 S usando hilos, pero quieren cambiar a algo mejor tan pronto como el JVM gana algo mejor cont Construye de flujo OL.

Python tiene generadores que en realidad son más o menos COROUTINAS FUERTAS. CPYTHON los implementa usando NULL3 / NULL4

.

 

Generators are basically semi-coroutines with some annoying limitations. So, obviously, you can implement them using semi-coroutines (and full coroutines, of course).

If you don't have coroutines, you can use any of the other universal control flow constructs. There are a lot of control flow constructs that are "universal" in the sense that every control flow construct (including all the other universal control flow constructs), including coroutines and thus generators can be (more or less) trivially transformed into only that universal construct.

The most well-known of those is probably GOTO. With just GOTO, you can build any other control flow construct: IF-THEN-ELSE, WHILE, FOR, REPEAT-UNTIL, FOREACH, exceptions, threads, subroutine calls, method calls, function calls and so on, and of course also coroutines and generators.

Almost all CPUs support GOTO (although in a CPU, they usually call it jmp). In fact, in many CPUs, GOTO is the only control flow construct, although today native support for at least subroutine calls (call) and maybe some primitive form of exception handling and/or concurrency primitive (compare-and-swap) are usually also built in.

Another well-known control flow primitive are continuations. Continuations are basically a more structured, better manageable and less evil variant of GOTO, especially popular in functional languages. But there also some low-level languages that base their control flow on continuations, for example the Parrot Virtual Machine uses continuations for control flow and I believe there are even some continuation-based CPUs in some research lab somewhere.

C has a sort-of "crappy" form of continuations (setjmp and longjmp), that are much less powerful and less easy to use than "real" continuations, but they are plenty powerful enough to implement generators (and in fact, can be used to implement full continuations).

On a Unix platform, setcontext can be used as a more powerful and higher level alternative to setjmp/longjmp.

Another control flow construct that is well-known, but doesn't probably spring to mind as a low-level substrate build other control flow constructs on top of, are exceptions. There is a paper that shows that exceptions can be more powerful than continuations, thus making exceptions essentially equivalent to GOTO and thus universally powerful. And, in fact, exceptions are sometimes used as universal control flow constructs: the Microsoft Volta project, which compiled .NET bytecode to JavaScript, used JavaScript exceptions to implement .NET threads and generators.

Not universal, but probably powerful enough to implement generators is just plain tail call optimization. (I might be wrong, though. I unfortunately don't have a proof.) I think you can transform a generator into a set of mutually tail-recursive functions. I know that state machines can be implemented using tail calls, so I'm pretty sure generators can, too, since, after all, C# implements generators as state machines. (I think this works especially well together with lazy evaluation.)

Last but not least, in a language with a reified call stack (like most Smalltalks for example), you can build pretty much any kind of control flow constructs you want. (In fact, a reified call stack is basically the procedural low-level equivalent to the functional high-level continuation.)

So, what do other implementations of generators look like?

Lua doesn't have generators per se, but it has full asymmetric coroutines. The main C implementation uses setjmp/longjmp to implement them.

Ruby also doesn't have generators per se, but it has Enumerators, that can be used as generators. Enumerators are not part of the language, they are a library feature. MRI implements Enumerators using continuations, which in turn are implemented using setjmp/longjmp. YARV implements Enumerators using Fibers (which is how Ruby spells "coroutines"), and those are implemented using setjmp/longjmp. I believe JRuby currently implements Enumerators using threads, but they want to switch to something better as soon as the JVM gains some better control flow constructs.

Python has generators that are actually more or less full-blown coroutines. CPython implements them using setjmp/longjmp.

 
 
 
 

Relacionados problema

0  Función generadora de Python con predicado  ( Python generator function with predicate ) 
def group_func(iterable,p): for i in iterable: yield [i] if p(i): yield i Estoy trabajando en group_func Sin embarg...

1  Código PHP para reemplazar ciertos valores en matriz, generador de código  ( Php code to replace certain values in array code generator ) 
Estoy tratando de escribir el código PHP como un proyecto de hobby para crear básicamente un generador de código "posible". El escenario es que tenemos una li...

3  Convertir el objeto de generador recursivo a la lista  ( Convert recursive generator object to list ) 
He estado tratando de implementar una estructura de árbol simple en Python. Un árbol comienza en un solo nodo "raíz" que tiene hijos, cada uno de sus hijos pu...

0  Configuración del generador para generar archivoSSSSSSS en lugar de CSS  ( Configuring generator to generate scss file instead of css ) 
Actualmente estoy jugando con rieles 3.1 RC4, y cuando intento generar un andamio: rails generate scaffold animal Me doy cuenta de que crea un archivo ...

0  ¿Cómo puedo generar una lista de colores semi-aleatorios?  ( How can i generate a list of semi random colours ) 
Quiero pasar por una lista de colores generados al azar y verificar si difieren entre sí. No como en colour1 == colour2 , pero asegurándose de que los colore...

3  Generador de números aleatorios único JavaScript  ( Unique random number generator javascript ) 
Estoy tratando de hacer un juego de bingo por diversión. He mirado en muchos lugares para un generador único, pero parece que no puedo encontrar uno. He trata...

2  Generando señales de audio seno, cuadrado, triángulo, sawtooth usando la clase Audiotrack de Android  ( Generating sine square triangle sawtooth audio signals using androids audiot ) 
Mi objetivo es generar sine , cuadrado , triángulo y sawtooth Signals con Android's Audiotrack clase. He realizado un intento basado en una tutoria...

1  Objetos de Pickle con generadores anidados  ( Pickle objects with nested generators ) 
Supongamos que tengo una lista anidada arbitrariamente en la que algunos de los elementos anidados pueden ser generadores. Por ejemplo: nested_gens = [ ...

2  Los rieles de borde no enumeran los generadores de complemento / gema  ( Edge rails doesnt list plugin gem generators ) 
Recientemente creó un esqueleto de proyecto con rieles de borde e instalado rspec , rspec-rails y NextPos = InStr(Pos, WholeLine, Sep)0 como complementos...

0  La precisión de la capacitación permanece constante después de aplicar un generador  ( Training accuracy remains constant after applying a generator ) 
Estoy trabajando en la segmentación de imágenes con UNET. Comencé con la imagen de una sola banda y entrené el modelo con el código inferior: from glob imp...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos