Articulo de referencia

Flujo de control

En software , el flujo de control describe cómo progresa la ejecución de un comando al siguiente. En muchos contextos, como el código máquina y un lenguaje de programación imper...

En software , el flujo de control describe cómo progresa la ejecución de un comando al siguiente. En muchos contextos, como el código máquina y un lenguaje de programación imperativo , el control progresa secuencialmente (al comando ubicado inmediatamente después del comando que se está ejecutando actualmente), excepto cuando un comando transfiere el control a otro punto ; en ese caso, el comando se clasifica como un comando de flujo de control. Dependiendo del contexto, se utilizan otros términos en lugar de comando . Por ejemplo, en código máquina, el término típico es instrucción y en un lenguaje imperativo, el término típico es sentencia .

Si bien un lenguaje imperativo codifica explícitamente el flujo de control, los lenguajes de otros paradigmas de programación se centran menos en este aspecto. Un lenguaje declarativo especifica los resultados deseados sin prescribir un orden de operaciones. Un lenguaje funcional utiliza tanto construcciones del lenguaje como funciones para controlar el flujo, aunque generalmente no se las denomine sentencias de control de flujo.

En un conjunto de instrucciones de la unidad central de procesamiento , una instrucción de control de flujo suele modificar el contador de programa y puede ser una bifurcación incondicional (también conocida como salto) o una bifurcación condicional. Un enfoque alternativo es la predicación , que habilita instrucciones de forma condicional en lugar de realizar bifurcaciones.

Una transferencia de flujo de control asíncrona , como una interrupción o una señal, altera el flujo normal de control hacia un manejador antes de devolver el control al punto donde se interrumpió.

Una forma de atacar el software es redirigir el flujo de ejecución. Se utilizan diversas técnicas de integridad del flujo de control , como los canarios de pila , la protección contra desbordamiento de búfer , las pilas en la sombra y la verificación de punteros de tabla virtual , para defenderse de estos ataques. [ 1 ] [ 2 ] [ 3 ]

Estructura

El flujo de control está estrechamente relacionado con la estructura del código. El control fluye según las líneas definidas por la estructura y las reglas de ejecución del lenguaje. Este concepto general de estructura no debe confundirse con la programación estructurada , que limita la estructura a la secuenciación, la selección y la iteración basadas en la organización en bloques .

Secuencia

La ejecución secuencial es la estructura más básica. Si bien no todo el código es secuencial por naturaleza, el código imperativo sí lo es.

Etiqueta

Una etiqueta identifica una posición en el código fuente . Algunas instrucciones de control de flujo hacen referencia a una etiqueta para que el control salte a la línea etiquetada. Aparte de marcar una posición, una etiqueta no tiene ningún otro efecto.

Algunos lenguajes limitan una etiqueta a un número que a veces se denomina número de línea , aunque esto implica el índice inherente de la línea, no una etiqueta. No obstante, estas etiquetas numéricas suelen requerir un incremento de arriba a abajo en un archivo, incluso si no son secuenciales. Por ejemplo, en BASIC:

10 SEA X = 3 20 IMPRIMIR X 30 IR A 10

En muchos lenguajes de programación, una etiqueta es un identificador alfanumérico que suele aparecer al principio de una línea, seguido inmediatamente por dos puntos. Por ejemplo, el siguiente código C define una etiqueta Successen la línea 3 que identifica un punto de destino de salto en la primera instrucción que la sigue (línea 4).

void f ( bool ok ) {si ( ok ) {ir al éxito ;}devolver ;éxito :printf ( "OK" );}

Bloquear

La mayoría de los lenguajes permiten organizar secuencias de código en bloques . Al usarlos con una instrucción de control, el inicio de un bloque indica el punto de salto. Por ejemplo, en el siguiente código C (que utiliza llaves para delimitar un bloque), el control salta de la línea 1 a la 4 si `done` es falso.

si ( hecho ) {printf ( "Todo listo" );} demás {printf ( "Sigo trabajando en ello" );}

Control

Se han ideado numerosos comandos de control para los lenguajes de programación. Esta sección describe las construcciones más destacadas y está organizada por funcionalidad.

Función

Una función proporciona control de flujo, de modo que cuando se la llama, la ejecución salta al inicio del código de la función y, cuando esta finaliza, el control regresa al punto de llamada. En el siguiente código C, el control salta de la línea 6 a la 2 para llamar a la función foo(). Luego, tras completar el cuerpo de la función (imprimiendo "Hola"), el control regresa al punto de llamada, línea 7.

void foo () {printf ( "Hola" );}barra vacía () {foo ();printf ( "Hecho" );}

Rama

A branch command moves the point of execution from the point in the code that contains the command to the point that the command specifies.

Jump

A jump command unconditionally branches control to another point in the code, and is the most basic form of controlling the flow of code.

In a high-level language, this is often provided as a goto statement. Although the keyword may be upper or lower case or one or two words depending on the language, it is like: goto label. When control reaches a goto statement, control then jumps to the statement that follows the indicated label. The goto statement has been considered harmful by many computer scientists, including Dijkstra.

Conditional branch

A conditional statement jumps control based on the value of a Boolean expression. Common variations include:

if-goto
Jumps to a label based on a condition; a high-level programming statement that closely mimics a similar used machine code instruction
if-then
Rather than being restricted to a jump, a statement or block is executed if the expression is true. In a language that does not include the then keyword, this can be called an if statement.
if-then-else
Like if-then, but with a second action to be performed if the condition is false. In a language that does not include the then keyword, this can be called an if-else statement.
Nested
Conditional statements are often nested inside other conditional statements.
Arithmetic if
Early Fortran, had an arithmetic if (a.k.a. three-way if) that tests whether a numeric value is negative, zero, or positive. This statement was deemed obsolete in Fortran-90, and deleted as of Fortran 2018.
Operator
Some languages have an operator form, such as the ternary conditional operator.
When and unless
Perl supplements a C-style if with when and unless.
Messages
Smalltalk uses ifTrue and ifFalse messages to implement conditionals, rather than a language construct.

The following Pascal code shows a simple if-then-else. The syntax is similar in Ada:

ifa>0thenwriteln("yes")elsewriteln("no");

In C:

if(a>0){puts("yes");}else{puts("no");}

In bash:

if[$a-gt0];thenecho"yes"elseecho"no"fi

In Python:

ifa>0:print("yes")else:print("no")

In Lisp:

(princ(if(pluspa)"yes""no"))

Multiway branch

A multiway branch jumps control based on matching values. There is usually a provision for a default action if no match is found. A switch statement can allow compiler optimizations, such as lookup tables. In dynamic languages, the cases may not be limited to constant expressions, and might extend to pattern matching, as in the shell script example on the right, where the *) implements the default case as a glob matching any string. Case logic can also be implemented in functional form, as in SQL's decode statement.

The following Pascal code shows a relatively simple switch statement. Pascal uses the case keyword instead of switch.

casesomeCharof'a':actionOnA;'x':actionOnX;'y','z':actionOnYandZ;elseactionOnNoMatch;end;

In Ada:

casesomeChariswhen'a'=>actionOnA;when'x'=>actionOnX;when'y'|'z'=>actionOnYandZ;whenothers=>actionOnNoMatch;end;

In C:

switch(someChar){case'a':actionOnA;break;case'x':actionOnX;break;case'y':case'z':actionOnYandZ;break;default:actionOnNoMatch;}

In Bash:

case$someCharina)actionOnA;;x)actionOnX;;[yz])actionOnYandZ;;*)actionOnNoMatch;;esac

In Lisp:

(casesome-char((#\a)action-on-a)((#\x)action-on-x)((#\y#\z)action-on-y-and-z)(elseaction-on-no-match))

In Fortran:

select case(someChar)case('a')actionOnAcase('x')actionOnXcase('y','z')actionOnYandZcase defaultactionOnNoMatchend select

Loop

basic types of program loops

A loop is a sequence of statements, loop body, which is executed a number of times based on runtime state. The body is executed once for each item of a collection (definite iteration), until a condition is met (indefinite iteration), or infinitely. A loop inside the loop body is called a nested loop.[4][5][6] Early exit from a loop may be supported via a break statement.[7][8]

In a functional programming language, such as Haskell and Scheme, both recursive and iterative processes are expressed with tail recursive procedures instead of looping constructs that are syntactic.

Numeric

A relatively simple yet useful loop iterates over a range of numeric values. A simple form starts at an integer value, ends at a larger integer value and iterates for each integer value between. Often, the increment can be any integer value (even negative, to loop from a larger to a smaller value).

Example in BASIC:

FORI=1TONxxxNEXTI

Example in Pascal:

forI:=1toNdobeginxxxend;

Example in Fortran:

DO I=1,NxxxEND DO

In many programming languages, only integers can be used at all or reliably. As a floating-point number is represented imprecisely due to hardware constraints, the following loop might iterate 9 or 10 times, depending on various factors such as rounding error, hardware, compiler. Furthermore, if the increment of X occurs by repeated addition, accumulated rounding errors may mean that the value of X in each iteration can differ quite significantly from the commonly expected sequence of 0.1, 0.2, 0.3, ..., 1.0.

for X := 0.1 step 0.1 to 1.0 do

Condition-controlled

Some loop constructs iterate until a condition is true. Some variations test the condition at the start of the loop; others test at the end. If the test is at the start, the body may be skipped completely. At the end, the body is always executed at least once.

Example in Visual Basic:

DOWHILE(test)xxxLOOP

Example in Pascal:

repeatxxxuntiltest;

Example in C family of pre-test:

while(test){xxx}

Example in C family of post-test:

doxxxwhile(test);

Although using the for keyword, the three-part C-style loop is a condition-based construct, not a numeric-based one. The second part, the condition, is evaluated before each loop, so the loop is pre-test. The first part is a place to initialize state, and the third part is for incrementing for the next iteration, but both aspects can be performed elsewhere. The following C code implements the logic of a numeric loop that iterates for i from 0 to n-1.

for(inti=0;i<n;++i){xxx}

Enumeration

Some loop constructs enumerate the items of a collection; iterating for each item.

Example in Smalltalk:

someCollectiondo: [:eachElement|xxx].

Example in Pascal:

forIteminCollectiondobeginxxxend;

Example in Raku:

foreach (item; myCollection) { xxx } 

Example in TCL:

foreachsomeArray{xxx}

Example in PHP:

foreach($someArrayas$k=>$v){xxx}

Example in Java:

Collection<String>coll;for(Strings:coll){}

Example in C#:

foreach(stringsinmyStringCollection){xxx}

Example in PowerShell where 'foreach' is an alias of 'ForEach-Object':

someCollection|foreach{$_}

Example in Fortran:

forall(index=first:last:step...)

Scala has for-expressions, which generalise collection-controlled loops, and also support other uses, such as asynchronous programming. Haskell has do-expressions and comprehensions, which together provide similar function to for-expressions in Scala.

Infinite

In computer programming, an infinite loop (or endless loop)[9][10] is a sequence of instructions that, as written, will continue endlessly, unless an external intervention occurs, such as turning off power via a switch or pulling a plug. It may be intentional.

There is no general algorithm to determine whether a computer program contains an infinite loop or not; this is the halting problem.

Loop-and-a-half problem

Common loop structures sometimes result in duplicated code, either repeated statements or repeated conditions. This arises for various reasons and has various proposed solutions to eliminate or minimize code duplication.[11] Other than the traditional unstructured solution of a goto statement,[12] general structured solutions include having a conditional (if statement) inside the loop (possibly duplicating the condition but not the statements) or wrapping repeated logic in a function (so there is a duplicated function call, but the statements are not duplicated).[11]

A common case is where the start of the loop is always executed, but the end may be skipped on the last iteration.[12] This was dubbed by Dijkstra a loop which is performed "n and a half times",[13] and is now called the loop-and-a-half problem.[8] Common cases include reading data in the first part, checking for end of data, and then processing the data in the second part; or processing, checking for end, and then preparing for the next iteration.[12][8] In these cases, the first part of the loop is executed n{\displaystyle n} times, but the second part is only executed n1{\displaystyle n-1} times.

This problem has been recognized at least since 1967 by Knuth, with Wirth suggesting solving it via early loop exit.[14] Since the 1990s this has been the most commonly taught solution, using a break statement, as in:[8]

loopstatementsifconditionbreakstatementsrepeat

A subtlety of this solution is that the condition is the opposite of a usual while condition: rewriting whilecondition ... repeat with an exit in the middle requires reversing the condition: loop ... if notconditionexit ... repeat. The loop with test in the middle control structure explicitly supports the loop-an-a-half use case, without reversing the condition.[14]

Unstructured

Una estructura de bucle proporciona criterios de finalización estructurados que dan como resultado otra iteración o la continuación de la ejecución después de la instrucción del bucle. Sin embargo, muchos lenguajes admiten diversas estructuras de control de flujo no estructuradas.

Próxima iteración temprana
Algunos lenguajes proporcionan una construcción que salta el control al principio del cuerpo del bucle para la siguiente iteración; por ejemplo, continue(el más común), skip, [ 15 ]cycle (Fortran), o next(Perl y Ruby).
Rehacer iteración
Algunos lenguajes, como Perl [ 16 ] y Ruby, [ 17 ] tienen una redoinstrucción que salta al inicio del cuerpo para la misma iteración.
Reanudar
Ruby tiene una retryinstrucción que reinicia todo el bucle desde la primera iteración. [ 18 ]
Salida anticipada

La salida temprana salta el control a después del cuerpo del bucle [ 19 ] [ 8 ] Por ejemplo, al buscar en una lista, puede detener el bucle cuando se encuentra el elemento. Algunos lenguajes de programación proporcionan una instrucción como break(la mayoría de los lenguajes), Exit(Visual Basic) o last(Perl).

En el siguiente código Ada, el bucle finaliza cuando X es 0.

bucle Obtener ( X ); si X = 0 entonces salir ; fin si ; HacerAlgo ( X ); fin bucle ;

Un estilo más idiomático utiliza exit when:

bucle Obtener ( X ); salir cuando X = 0 ; HacerAlgo ( X ); fin del bucle ;

Python admite la ejecución condicional de código dependiendo de si un bucle se ha cerrado prematuramente (con una breakinstrucción `if`) o no, mediante el uso de una cláusula `else` dentro del bucle. En el siguiente código Python, la elsecláusula `else` está vinculada a la forinstrucción `if`, y no a la ifinstrucción interna. Tanto `if` forcomo while`else` de Python admiten dicha cláusula `else`, que se ejecuta solo si no se ha cerrado prematuramente el bucle.

for n in set_of_numbers : if isprime ( n ): print ( "El conjunto contiene un número primo" ) break else : print ( "El conjunto no contenía ningún número primo" )
Descansos de varios niveles

Some languages support breaking out of nested loops; in theory circles, these are called multi-level breaks. One common use example is searching a multi-dimensional table. This can be done either via multilevel breaks (break out of N levels), as in bash[20] and PHP,[21] or via labeled breaks (break out and continue at given label), as in Ada, Go, Java, Rust and Perl.[22] Alternatives to multilevel breaks include single breaks, together with a state variable which is tested to break out another level; exceptions, which are caught at the level being broken out to; placing the nested loops in a function and using return to effect termination of the entire nested loop; or using a label and a goto statement. Neither C nor C++ currently have multilevel break or named loops, and the usual alternative is to use a goto to implement a labeled break.[23] However, the inclusion of this feature has been proposed,[24] and was added to C2Y.,[25] following the Java syntax. Python does not have a multilevel break or continue – this was proposed in PEP 3136, and rejected on the basis that the added complexity was not worth the rare legitimate use.[26]

The notion of multi-level breaks is of some interest in theoretical computer science, because it gives rise to what is today called the Kosaraju hierarchy.[27] In 1973 S. Rao Kosaraju refined the structured program theorem by proving that it is possible to avoid adding additional variables in structured programming, as long as arbitrary-depth, multi-level breaks from loops are allowed.[28] Furthermore, Kosaraju proved that a strict hierarchy of programs exists: for every integer n, there exists a program containing a multi-level break of depth n that cannot be rewritten as a program with multi-level breaks of depth less than n without introducing added variables.[27]

In his 2004 textbook, David Watt uses Tennent's notion of sequencer to explain the similarity between multi-level breaks and return statements. Watt notes that a class of sequencers known as escape sequencers, defined as "sequencer that terminates execution of a textually enclosing command or procedure", encompasses both breaks from loops (including multi-level breaks) and return statements. As commonly implemented, however, return sequencers may also carry a (return) value, whereas the break sequencer as implemented in contemporary languages usually cannot.[29]

Middle test

The following structure was proposed by Dahl in 1972:[30]

looploop xxx1 read(char); while test; whilenot atEndOfFile; xxx2 write(char); repeat; repeat;

The construction here can be thought of as a do loop with the while check in the middle, which allows clear loop-and-a-half logic. Further, by omitting individual components, this single construction can replace several constructions in most programming languages. If xxx1 is omitted, we get a loop with the test at the top (a traditional while loop). If xxx2 is omitted, we get a loop with the test at the bottom, equivalent to a do while loop in many languages. If while is omitted, we get an infinite loop. This construction also allows keeping the same polarity of the condition even when in the middle, unlike early exit, which requires reversing the polarity (adding a not),[14] functioning as until instead of while.

This structure is not widely supported, with most languages instead using if ... break for conditional early exit.

This is supported by some languages, such as Forth, where the syntax is BEGIN ... WHILE ... REPEAT,[31] and the shell script languages Bourne shell (sh) and bash, where the syntax is while ... do ... done or until ... do ... done, as:[32][33]

mientras la instrucción-1 instrucción-2 ... condición hacer instrucción-a instrucción-b ... hecho

La sintaxis del shell funciona porque el bucle while (o until ) acepta una lista de comandos como condición, [ 34 ] formalmente:

mientras se ejecutan los comandos de prueba ; hacer los comandos consecuentes ; hecho

El valor (estado de salida) de la lista de comandos de prueba es el valor del último comando, y estos se pueden separar con saltos de línea, lo que da como resultado la forma idiomática anterior.

Es posible construir estructuras similares en C y C++ con el operador coma , y ​​en otros lenguajes con construcciones similares , que permiten encajar una lista de instrucciones en la condición while:

mientras ( declaración_1 , declaración_2 , condición ) { declaración_a ; declaración_b ; }

Aunque legal, esto es marginal y se utiliza principalmente, si acaso, solo para casos cortos de modificación y posterior prueba, como en: [ 35 ]

while ( read_string ( s ), strlen ( s ) > 0 ) { // ... }

Variantes e invariantes de bucles

Las variantes e invariantes de bucle se utilizan para expresar la corrección de los bucles. [ 36 ]

En términos prácticos, una variante de bucle es una expresión entera con un valor inicial no negativo. El valor de la variante debe disminuir durante cada iteración del bucle, pero nunca debe volverse negativo durante su correcta ejecución. Las variantes de bucle se utilizan para garantizar que los bucles finalicen.

Un invariante de bucle es una aserción que debe ser verdadera antes de la primera iteración y permanecer verdadera después de cada iteración. Esto implica que, cuando un bucle finaliza correctamente, tanto la condición de salida como el invariante de bucle se cumplen. Los invariantes de bucle se utilizan para supervisar propiedades específicas de un bucle durante iteraciones sucesivas.

Algunos lenguajes de programación, como Eiffel, incluyen soporte nativo para variantes e invariantes de bucles. En otros casos, el soporte es un complemento, como la especificación del lenguaje de modelado de Java para las sentencias de bucle en Java .

Sublenguaje de bucle

Some Lisp dialects provide an extensive sublanguage for describing Loops. An early example can be found in Conversional Lisp of Interlisp. Common Lisp[37] provides a Loop macro which implements such a sublanguage.

Loop system cross-reference table

  1. awhile (true) does not count as an infinite loop for this purpose, because it is not a dedicated language structure.
  2. abcdefgh C's for (init; test; increment) loop is a general loop construct, not specifically a counting one, although it is often used for that.
  3. abc Deep breaks may be accomplished in APL, C, C++ and C# through the use of labels and gotos.
  4. a Iteration over objects was added in PHP 5.
  5. abcdef A counting loop can be simulated by iterating over an incrementing list or generator, for instance, Python's range().
  6. abcde Deep breaks may be accomplished through the use of exception handling.
  7. a There is no special construct, since the while function can be used for this.
  8. a There is no special construct, but users can define general loop functions.
  9. a The C++11 standard introduced the range-based for. In the STL, there is a std::for_eachtemplate function which can iterate on STL containers and call a unary function for each element.[38] The functionality also can be constructed as macro on these containers.[39]
  10. a Numeric looping is effected by iteration across an integer interval; early exit by including an additional condition for exit.
  11. a Eiffel supports a reserved word retry, however it is used in exception handling, not loop control.
  12. a Requires Java Modeling Language (JML) behavioral interface specification language.
  13. a Requires loop variants to be integers; transfinite variants are not supported. Eiffel: Why loop variants are integers
  14. a D supports infinite collections, and the ability to iterate over those collections. This does not require any special construct.
  15. a Deep breaks can be achieved using GO TO and procedures.
  16. a Common Lisp predates the concept of generic collection type.
  17. ab Odin's general for loop supports syntax shortcuts for conditional loop and infinite loop.

Non-local

Many programming languages, especially those favoring more dynamic styles of programming, offer constructs for non-local control flow which cause execution to jump from the current execution point to a predeclared point. Notable examples follow.

Condition handling

The earliest Fortran compilers supported statements for handling exceptional conditions including IF ACCUMULATOR OVERFLOW, IF QUOTIENT OVERFLOW, and IF DIVIDE CHECK. In the interest of machine independence, they were not included in FORTRAN IV and the Fortran 66 Standard. However, since Fortran 2003 it is possible to test for numerical issues via calls to functions in the IEEE_EXCEPTIONS module.

PL/I has some 22 standard conditions (e.g., ZERODIVIDE SUBSCRIPTRANGE ENDFILE) which can be raised and which can be intercepted by: ON condition action; Programmers can also define and use their own named conditions.

Like the unstructured if, only one statement can be specified so in many cases a GOTO is needed to decide where flow of control should resume.

Unfortunately, some implementations had a substantial overhead in both space and time (especially SUBSCRIPTRANGE), so many programmers tried to avoid using conditions.

A typical example of syntax:

ONconditionGOTOlabel

Exception handling

Many modern languages natively support exception handling. Generally, exceptional control flow starts with an exception object being thrown (a.k.a. raised). Control then proceeds to the inner-most exception handler for the call stack. If the handler handles the exception, then flow control reverts to normal. Otherwise, control proceeds outward to containing handlers until one handles the exception or the program reaches the outermost scope and exits. As control flows to progressively outer handlers, aspects that would normally occur such as popping the call stack are handled automatically.

The following C++ code demonstrates structured exception handling. If an exception propagates from the execution of doSomething() and the exception object type matches one of the types specified in a catch clause, then that clause is executed. For example, if an exception of type SomeException is propagated by doSomething(), then control jumps from line 2 to 4 and the message "Caught SomeException" is printed and then control jumps to after the try statement, line 8. If an exception of any other type is propagated, then control jumps from line 2 to 6. If no exception, then control jumps from 2 to 8.

try{doSomething();}catch(constSomeException&e)std::println("Caught SomeException: {}",e.what());}catch(...){std::println("Unknown error");}doNextThing();

Many languages use the C++ keywords (throw, try and catch), but some languages use other keywords. For example, Ada uses exception to introduce an exception handler and when instead of catch. AppleScript incorporates placeholders in the syntax to extract information about the exception as shown in the following AppleScript code.

trysetmyNumbertomyNumber/0onerrorenumbernfromftotpartialresultprif(e="Can't divide by zero")thendisplay dialog"You must not do that"endtry

In many languages (including Object Pascal, D, Java, C#, and Python) a finally clause at the end of a try statement is executed at the end of the try statement, whether an exception propagates from the rest of the try or not. The following C# code ensures that the stream stream is closed.

FileStreamstream=null;try{stream=newFileStream("logfile.txt",FileMode.Create);returnProcessStuff(stream);}finally{if(stream!=null){stream.Close();}}

Since this pattern is common, C# provides the using statement to ensure cleanup. In the following code, even if ProcessStuff() propagates an exception, the stream object is released. Python's with statement and Ruby's block argument to File.open are used to similar effect.

using(FileStreamstream=new("logfile.txt",FileMode.Create)){returnProcessStuff(stream);}

Continuation

In computer science, a continuation is an abstract representation of the control state of a computer program. A continuation implements (reifies) the program control state, i.e. the continuation is a data structure that represents the computational process at a given point in the process's execution; the created data structure can be accessed by the programming language, instead of being hidden in the runtime environment. Continuations are useful for encoding other control mechanisms in programming languages such as exceptions, generators, coroutines, and so on.

The "current continuation" or "continuation of the computation step" is the continuation that, from the perspective of running code, would be derived from the current point in a program's execution. The term continuations can also be used to refer to first-class continuations, which are constructs that give a programming language the ability to save the execution state at any point and return to that point at a later point in the program, possibly multiple times.

Generator

En informática , un generador es una rutina que se puede usar para controlar el comportamiento iterativo de un bucle . Todos los generadores son también iteradores . [ 40 ] Un generador es muy similar a una función que devuelve un array , ya que un generador tiene parámetros , se puede llamar y genera una secuencia de valores. Sin embargo, en lugar de construir un array que contenga todos los valores y devolverlos todos a la vez, un generador produce los valores uno a uno, lo que requiere menos memoria y permite que quien lo llama comience a procesar los primeros valores de inmediato. En resumen, un generador se parece a una función pero se comporta como un iterador .

Los generadores pueden implementarse en términos de construcciones de flujo de control más expresivas, como corrutinas o continuaciones de primera clase . [ 41 ] Los generadores, también conocidos como semicorrutinas, [ 42 ] son ​​un caso especial de (y más débiles que) las corrutinas, ya que siempre devuelven el control al llamador (al pasar un valor de vuelta), en lugar de especificar una corrutina a la que saltar; véase la comparación de corrutinas con generadores .

Corutina

Las corrutinas son componentes de programas informáticos que pueden suspenderse y reanudarse —generalizando las subrutinas— para la multitarea cooperativa . Son muy adecuadas para implementar componentes de programas comunes como tareas cooperativas , excepciones , bucles de eventos , iteradores , listas infinitas y tuberías .

Se las ha descrito como "funciones cuya ejecución se puede pausar". [ 43 ]

Melvin Conway acuñó el término corrutina en 1958 cuando lo aplicó a la construcción de un programa de ensamblaje . [ 44 ] La primera explicación publicada de la corrutina apareció más tarde, en 1963. [ 45 ]

VEN DE

In computer programming, COMEFROM is a control flow statement that causes control flow to jump to the statement after it when control reaches the point specified by the COMEFROM argument. The statement is intended to be the opposite of goto and is considered to be more a joke than serious computer science. Often the specified jump point is identified as a label. For example, COMEFROM x specifies that when control reaches the label x, then control continues at the statement after the COMEFROM.

A major difference with goto is that goto depends on the local structure of the code, while COMEFROM depends on the global structure. A goto statement transfers control when control reaches the statement, but COMEFROM requires the processor (i.e. interpreter) to scan for COMEFROM statements so that when control reaches any of the specified points, the processor can make the jump. The resulting logic tends to be difficult to understand since there is no indication near a jump point that control will in fact jump. One must study the entire program to see if any COMEFROM statements reference that point.

The semantics of a COMEFROM statement varies by programming language. In some languages, the jump occurs before the statement at the specified point is executed and in others the jump occurs after. Depending on the language, multiple COMEFROM statements that reference the same point may be invalid, non-deterministic, executed in some order, or induce parallel or otherwise concurrent processing as seen in Threaded Intercal.

COMEFROM was initially seen in lists of joke assembly language instructions (as 'CMFRM'). It was elaborated upon in a Datamation article by R. Lawrence Clark in 1973,[46] written in response to Edsger Dijkstra's letter Go To Statement Considered Harmful. COMEFROM was eventually implemented in the C-INTERCAL variant of the esoteric programming languageINTERCAL along with the even more obscure 'computed COMEFROM'. There were also Fortran proposals[47] for 'assigned COME FROM' and a 'DONT' statement (to complement the existing 'DO' loop).

Event-based early exit from nested loop

Zahn's construct was proposed in 1974,[48] and discussed in Knuth (1974). A modified version is presented here.

exitwhen EventA or EventB or EventC; xxx exits EventA: actionA EventB: actionB EventC: actionC endexit;

exitwhen is used to specify the events which may occur within xxx, their occurrence is indicated by using the name of the event as a statement. When some event does occur, the relevant action is carried out, and then control passes just after endexit. This construction provides a very clear separation between determining that some situation applies, and the action to be taken for that situation.

exitwhen is conceptually similar to exception handling, and exceptions or similar constructs are used for this purpose in many languages.

The following simple example involves searching a two-dimensional table for a particular item.

exitwhen found or missing; for I := 1 to N dofor J := 1 to M doif table[I,J] = target then found; missing; exits found: print ("item is in table"); missing: print ("item is not in table"); endexit;

See also

References

  1. Payer, Mathias; Kuznetsov, Volodymyr. "On differences between the CFI, CPS, and CPI properties". nebelwelt.net. Retrieved 2016-06-01.
  2. "Adobe Flash Bug Discovery Leads To New Attack Mitigation Method". Dark Reading. 10 November 2015. Retrieved 2016-06-01.
  3. Endgame. "Endgame to Present at Black Hat USA 2016". www.prnewswire.com (Press release). Retrieved 2016-06-01.
  4. "Nested Loops in C with Examples". GeeksforGeeks. 2019-11-25. Retrieved 2024-03-14.
  5. "Python Nested Loops". www.w3schools.com. Retrieved 2024-03-14.
  6. Dean, Jenna (2019-11-22). "Nested Loops". The Startup. Retrieved 2024-03-14.
  7. Knuth, Donald E. (1974). "Structured Programming with go to Statements". Computing Surveys. 6 (4): 261–301. CiteSeerX 10.1.1.103.6084. doi:10.1145/356635.356640. S2CID 207630080.
  8. 12345Roberts, E. [1995] "Loop Exits and Structured Programming: Reopening the DebateArchived 2014-07-25 at the Wayback Machine," ACM SIGCSE Bulletin, (27)1: 268–272.
  9. "Endless loop dictionary definition". Archived from the original on 2020-08-01. Retrieved 2020-01-22.
  10. "What is infinite loop (endless loop)". Archived from the original on 2019-07-15. Retrieved 2020-01-22.
  11. 12"Messy Loop Conditions". WikiWikiWeb. 2014-11-03.
  12. 123Knuth 1974, p. 278, Simple Iterations.
  13. Edsger W. Dijkstra, personal communication to Donald Knuth on 1974-01-03, cited in Knuth (1974, p. 278, Simple Iterations)
  14. 123Knuth 1974, p. 279.
  15. "What is a loop and how we can use them?". Archived from the original on 2020-07-28. Retrieved 2020-05-25.
  16. "redo - perldoc.perl.org". perldoc.perl.org. Retrieved 2020-09-25.
  17. "control_expressions - Documentation for Ruby 2.4.0". docs.ruby-lang.org. Retrieved 2020-09-25.
  18. "control_expressions - Documentation for Ruby 2.3.0". docs.ruby-lang.org. Retrieved 2020-09-25.
  19. Is a common way to solve the loop-and-a-half problem.
  20. Advanced Bash Scripting Guide: 11.3. Loop Control
  21. PHP Manual: "break"
  22. perldoc: last
  23. comp.lang.c FAQ list · "Question 20.20b"
  24. "named-loops" . open-std.org . 18 de septiembre de 2024.
  25. "Tecnología de la información — Lenguajes de programación — C" (PDF) . open-std.org . 4 de mayo de 2025.
  26. [Python-3000] Anuncio de PEP 3136 , Guido van Rossum
  27. 1 2 Kozen, Dexter (2008). "El teorema de Böhm-Jacopini es falso, proposicionalmente". Matemáticas de la construcción de programas (PDF) . Notas de clase en ciencias de la computación. Vol. 5133. págs. 177-192 . CiteSeerX 10.1.1.218.9241 . doi : 10.1007/978-3-540-70594-9_11 . ISBN    978-3-540-70593-2.
  28. Kosaraju, S. Rao. "Análisis de programas estructurados", Proc. Fifth Annual ACM Syrup. Theory of Computing, (mayo de 1973), 240-252; también en J. Computer and System Sciences, 9, 3 (diciembre de 1974), citado por Knuth (1974) .
  29. David Anthony Watt; William Findlay (2004). Conceptos de diseño de lenguajes de programación . John Wiley & Sons. págs. 215–221 . ISBN  978-0-470-85320-7.
  30. Dahl, Dijkstra y Hoare, "Programación estructurada", Academic Press, 1972.
  31. "6. Dejar que se vuelva loco" .
  32. "3.2.5.1 Estructuras de bucle" , Manual de referencia de GNU Bash , 18 de mayo de 2025
  33. "¿Cómo podría un lenguaje hacer que el bucle y medio sea menos propenso a errores?" . Stack Exchange: Diseño e implementación de lenguajes de programación .
  34. "3.2.4 Listas de comandos" , Manual de referencia de GNU Bash , 18 de mayo de 2025
  35. "¿Qué hace el operador coma ,?" . Stack Overflow .
  36. Meyer, Bertrand (1991). Eiffel: El lenguaje . Prentice Hall. pp. 129–131 . 
  37. "Macro LOOP de Common Lisp" .
  38. for_each . Sgi.com. Consultado el 09-11-2010.
  39. Capítulo 1. Boost.Foreach Archivado el 29/01/2010 en Wayback Machine . Boost-sandbox.sourceforge.net (19/12/2009). Consultado el 09/11/2010.
  40. ¿Cuál es la diferencia entre un iterador y un generador?
  41. Kiselyov, Oleg (enero de 2004). "Formas generales de recorrer colecciones en Scheme" .
  42. Anthony Ralston (2000). Enciclopedia de informática . Nature Pub. Group. ISBN 978-1-56159-248-7. Consultado el 11 de mayo de 2013 .
  43. "How the heck does async/await work in Python 3.5?". Tall, Snarky Canadian. 2016-02-11. Archived from the original on 2023-01-10. Retrieved 2023-01-10.
  44. Knuth, Donald Ervin (1997). Fundamental Algorithms(PDF). The Art of Computer Programming. Vol. 1 (3rd ed.). Addison-Wesley. Section 1.4.5: History and Bibliography, pp. 229. ISBN 978-0-201-89683-1. Archived(PDF) from the original on 2019-10-21.
  45. Conway, Melvin E. (July 1963). "Design of a Separable Transition-diagram Compiler"(PDF). Communications of the ACM. 6 (7). ACM: 396–408. doi:10.1145/366663.366704. ISSN 0001-0782. S2CID 10559786. Archived(PDF) from the original on 2022-04-06. Retrieved 2019-10-21 via ACM Digital Library.
  46. Clarke, Lawrence, "We don't know where to GOTO if we don't know where we've COME FROM. This linguistic innovation lives up to all expectations.", Datamation (article), archived from the original on 2018-07-16, retrieved 2004-09-24.
  47. Modell, Howard; Slater, William (April 1978). "Structured programming considered harmful". ACM SIGPLAN Notices. 13 (4): 76–79. doi:10.1145/953411.953418. Retrieved 18 July 2014.
  48. Zahn, C. T. "A control statement for natural top-down structured programming" presented at Symposium on Programming Languages, Paris, 1974.
  • Wikimedia Commons logo Media related to Control flow at Wikimedia Commons
  • Go To Statement Considered Harmful
  • A Linguistic Contribution of GOTO-less Programming
  • "Structured Programming with Go To Statements"(PDF). Archived from the original(PDF) on 2009-08-24. (2.88 MB)
  • "IBM 704 Manual"(PDF). (31.4 MB)