Flow-control structures: Difference between revisions

m
→‎{{header|Ada}}: added 'return'
m (syntax highlighting fixup automation)
m (→‎{{header|Ada}}: added 'return')
 
(15 intermediate revisions by 8 users not shown)
Line 1:
{{Task|Control Structures}}
{{Control Structures}}
[[Category:Flow control]]
 
;Task:
Line 136 ⟶ 137:
 
===exit===
Exit is used to break out of loops. Exit can be used with a label to break out of an inner loop to an outer loop and its enclosing outer loop:
<syntaxhighlight lang="ada">Outer:
loop
-- do something
loop
--if doFinished somethingthen
loop
-- do something else
exit Outer; -- exits both the inner and outer loops
end loopif;
-- do something else
end loop;</syntaxhighlight>
end loop;
end loop Outer;</syntaxhighlight>
or, more idiomatically,
<syntaxhighlight lang="ada">Outer:
loop
-- do something
loop
exit Outer when Finished;
-- do something else
end loop;
end loop Outer;</syntaxhighlight>
 
===return===
A procedure can be exited early, if there’s no more to be done.
<syntaxhighlight lang="ada">procedure Foo is
begin
-- do something
if Nothing_More_To_Do then
return;
end if;
-- do more
end Foo;</syntaxhighlight>
 
===asynchronous transfer of control===
A sequence of operation can be aborted with an asynchronous transfer of control to an alternative:
Line 280 ⟶ 304:
addeq R0,R0,#1 ;almost any instruction can be made conditional. If the flag state doesn't match the condition code, the instruction
;has no effect on registers or memory.</syntaxhighlight>
 
=={{header|Arturo}}==
=== return ===
return from the function currently being execute
=== loop control ===
Arturo's loop control statements are: <code>break</code> and <code>continue</code>
=== exceptions ===
Normally, in Arturo we'd use either <code>try [...]</code> or <code>try? [...] else [...]</code> blocks.
 
=={{header|AutoHotkey}}==
Line 778 ⟶ 810:
 
[[Category:E examples needing attention]] <!-- Needs runnable examples, description of escape-catch, and maybe links to other flow control pages -->
 
=={{header|EasyLang}}==
 
With '''break <n>''' you can break out of a nested loop
 
<syntaxhighlight>
sum = 80036
for i = 0 to 50
for j = 0 to 50
if i * i + j * j * j = sum
print i & "² + " & j & "³ = " & sum
break 2
.
.
.
</syntaxhighlight>
{{out}}
<pre>
23² + 43³ = 80036
</pre>
 
=={{header|Erlang}}==
Line 1,307 ⟶ 1,359:
func1()</syntaxhighlight>
This is because Lua supports proper tail recursion. This means that because something being returned is necessarily the last action in a function, the interpreter treats a function call in this 'tail' position much like a GOTO in other languages and does not create a new stack level.
 
=={{header|M2000 Interpreter}}==
M2000 has labels, Goto, Gosub, On Goto, On Gosub, and can use numeric labels immediate at Then and Else clause. Goto can be used inside a block, or structure which may have hidden block. We can't use Goto to jump to outer module (calling module). Also we can't start a module from a label.
 
Gosub level controlled by Recursion.Limit (which is 10000 by default but we can change it to anything, like 1000000, using Recursion.limit 1000000), depends only from size of memory for 32bit applications (2Gbyte).
 
Every is a block structure for execution code synchronized by timer. If code exit execution time of block's constant time, executed later at same phase. There are three more statements for tasks, AFTER, THREAD and MAIN.TASK for executing code based on time in sequential of concurrent fashion, not shown here.
 
We can use Error "name of error" to produce error and we can catch it through a Try block.
 
 
====Use of Labels====
<syntaxhighlight lang="m2000 interpreter">
Module Inner {
long x=random(1, 2)
on x goto 90, 100
090 print "can print here if is "+x // if x=1
100 Print "ok"
gosub 500
alfa: // no statement here only comments because : is also statement separator
print "ok too"
integer c
Every 100 { // every 100 miliseconds this block executed
c++
gosub printc
if c>9 then 200
}
print "no print here"
200 Gosub exitUsingGoto
Every 100 { // every 100 miliseconds this block executed
c++
gosub printc
if c>19 then exit
}
gosub 500
try ok {
on x gosub 400, 1234
}
if ok else print error$ // sub not found (if x=2)
goto 1234 ' not exist so this is an exit from module
400 print "can print here if is "+x // if x=1
end
printc:
Print c
return
500 Print "exit from block using exit" : return
exitUsingGoto:
Print "exit from block using goto"
return
}
Inner
</syntaxhighlight>
 
====Use of Call Back function====
M2000 has no yield statement/function. We can use a call back function to get results, before a module exit. The call back function act as code in the calling module (has same scope), but has a difference: we can't use goto/gosub out of it
 
<syntaxhighlight lang="m2000 interpreter">
module outer {
static m as long=100 // if m not exist created
module count (&a(), b) {
long c=1
do
if b(c) then exit
call a(c)
c++
always
}
long z, i=100
// function k used as call back function, through lazy$()
function k {
read new i
print i // print 1 and 2
z+=i
m++
}
count lazy$(&k()), (lambda (i)->i>=3)
print z=3, i=100, m
}
clear // clear variables (and static variables) from this point
outer // m is 102
outer // m is 104
outer // m is 106
</syntaxhighlight>
 
====Using Break/Continue in Select Case====
Normally the Break statement break module (exit from module) or a Try { } block. Normally Continue is like exit in ordinary blocks or a new iteration for loop structures. For a Select case, a Break make the execution of other blocks from other cases to executed until "case else" or a continue statement. Both ends goes to end select. So break works in reverse of c's break. Without block { } in cases, Break and Continue works for the outer block (like normal break and continue). We can use Goto in cases, to exit select/end select structure, using or not using block in cases. Gosub can be used as usual everywhere.
 
<syntaxhighlight lang="m2000 interpreter">
Module checkSelect {
long m, i, k
for k=1 to 10
m=10
i=random(5, 10)
select case i
case <6
print "less than 6"
case 6
{
m++: break // break case block, and continue to next block
}
case 7
{
m++: break
}
case 8
{
m++: continue // exit after end select
}
case 9
print "is 9"
case else
print "more than 9"
end select
print m, i
next
}
checkSelect
</syntaxhighlight>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
Line 2,144 ⟶ 2,316:
1
 
=={{header|Quackery}}==
 
A Quackery program is a dynamic array ('''''nest''''') of numbers (bigints) operators (opcodes or primitives) and nests (named or explicit). It is evaluated by a depth first traversal of the structure, placing numbers on a data stack, and keeping track of the evaluation with a return stack. Flow control is achieved with meta-control flow operators, which modify the return stack during evaluation. The naming convention for meta-control flow operators is to wrap them in reversed brackets. They are <code>]again[ ]done[ ]if[ ]iff[ ]else[ ]'[ ]do[ ]this[</code> and <code>]bailby[</code>.
 
The first five, <code>]done[ ]again[ ]if[ ]iff[ ]else[</code>, are used to create a mix and match set of control flow words.
 
<pre>
[ ]again[ ] is again
[ ]done[ ] is done
[ ]if[ ] is if
[ ]iff[ ] is iff
[ ]else[ ] is else</pre>
 
<code>again</code> causes evaluation of the current nest to start again.
 
<code>done</code> causes evaluation of the current nest to end, and evaluation of the calling nest to continue.
 
<code>if</code> conditionally skips over the next item in the nest being evaluated. (dependant on the top of the data stack; it skips if the TOS is zero, and does not skip if it is a non-zero number. If it is not a number evaluation halts and a problem is reported.
 
<code>iff</code> is like <code>if</code> but conditionally skips over the next two items. It combines with <code>else</code> (below) to form an if...else... construct, and with other words to form more control flow structures (below).
 
<code>else</code> unconditionally skips over the next item in the nest being evaluated.
 
Also provided are <code>until</code> and <code>while</code>, and the programmer can add more as desired.
 
<pre>[ not if ]again[ ] is until
[ not if ]done[ ] is while</pre>
 
As this is a mix and match word set, complex control-flow structures can be made, restricted only to single-point of entry, achieved by the intentional omission of a <code>go-to</code> operator. For example, this code fragment from the task [[Largest number divisible by its digits#Quackery|Largest number divisible by its digits]].
<pre> [ 504 -
dup digits
dup 5 has iff
drop again
dup 0 has iff
drop again
repeats if again ]</pre>
 
<code>' do this</code>enable first and higher order functions, and recursion. They are defined using meta control flow operators.
<pre>
[ ]'[ ] is '
[ ]do[ ] is do
[ ]this[ ] is this</pre>
 
<code>'</code> unconditionally skips over the next item in the current nest, and places (a pointer to) it on the data stack.
 
<code>do</code> evaluates the item on the top of the data stack.
 
<code>this</code> places (a pointer to) the nest currently being evaluated on the data stack. so, for example, the phrase <code>this do</code> will cause the nest containing the phrase to be evaluated recursively. For convenience, the word <code>recurse</code> is provided which does the same thing.
 
<pre>[ ]this[ do ] is recurse</pre>
 
For more complex recursive situations the words <code>this</code> and <code>do</code> can be deployed at different levels of nesting, and additionally a forward referencing mechanism is provided. This example is from the task [[Mutual recursion#Quackery|Mutual recursion]].
<pre> forward is f ( n --> n )
 
[ dup 0 = if done
dup 1 - recurse f - ] is m ( n --> n )
[ dup 0 = iff 1+ done
dup 1 - recurse m - ]
resolves f ( n --> n )</pre>
 
<code>]'[</code> and <code>do</code> are also used to create the iterative looping word <code>times</code>, which will repeat the next item in the nest a specified number of times. The index of the loop is available from the word <code>i^</code>, which counts up from zero with each iteration, and the word <code>i</code>, which counts down to zero. The index can be modified with the words <code>step</code>, which causes the index to be incremented by a specified number, <code>refresh</code>, which resets it to the originally specified number of iterations, and <code>conclude</code>, which will sets it to zero.
 
<code>times</code> is used in the definition of <code>witheach</code>, which iterates over a nest placing the next item in the nest on the data stack with each iteration, so <code>I^ I step refresh conclude</code> are available within <code>witheach</code> loops.
<pre> ' [ 10 11 12 13 14 15 16 17 18 19 ]
witheach
[ dup 14 > iff
[ drop conclude ] done
echo
say " is item number " i^ echo cr
2 step ]</pre>
{{out}}
 
<pre>10 is item number 0
12 is item number 2
14 is item number 4</pre>
 
<code>witheach</code> can be used to define [[Higher-order functions#Quackery|Higher-order functions]].
 
<code>]bail-by[</code> removes a specified number of returns from the return stack. This is a high risk activity, as the data stack and ancillary stacks used by <code>times</code> and others are not restored in the process, additionally many words add items to the return stack that need to be accounted for. Without proper precautions it is an effective way of causing unpredictable behaviour (usually crashing). It exists primarily for the backtracking provided by the words <code>backup</code>, <code>bail</code>, and <code>bailed</code>, which do take the proper precautions.
 
=={{header|Racket}}==
Line 2,904 ⟶ 3,156:
=== On Error Goto ===
 
This brancesbranches in the event of an error. Usually there is an Exit (Sub|Function) to seperateseparate the normal code from the error handling code
 
<syntaxhighlight lang="vbnet"> Sub foo()
Line 2,976 ⟶ 3,228:
 
The following code demonstrates each of the above apart from '''Fiber.suspend''' which simply exits a CLI script.
<syntaxhighlight lang="ecmascriptwren">var func = Fn.new { |n|
var i = 1
while (true) {
Line 2,992 ⟶ 3,244:
 
var fiber = Fiber.new {
Fiber.abort("Demo error") // error occcurredoccurred, abort script
}
 
Line 2,998 ⟶ 3,250:
for (n in a) {
func.call(n)
if (n > 2) return // end module and hence the script as itsit's a single module script
var error = fiber.try() // catch any error
System.print("Caught error: " + error)
Line 3,012 ⟶ 3,264:
</pre>
 
=={{header|XPL0}}==
XPL0 does not have a ''goto'' statement, but it has other similar
statements. Its ''quit'' statement jumps out of a ''loop'' block. A
''return'' jumps out of a procedure, or a function where it's also used
to return the numerical result of the function. A ''return'' in the main
procedure terminates a program. An ''exit'' statement terminates a
program from any location. Like the ''return'' statement, it can send an
optional value, in this case to the operating system.
 
Some routines called ''intrinsics'' that are automatically included in a
program also affect flow control. The Abort intrinsic is like the
''exit'' statement except it does not return a value. (It's deprecated in
preference to ''exit''.) The Restart intrinsic, which can be called from
anywhere, restarts a program at its beginning. (The Rerun intrinsic is
used to distinguish a restart from a normal start.) Certain errors such
as divide-by-zero or attempting to open a non-existent file abort a
program. The Trap intrinsic can disable this feature. It's normally used
with the GetErr intrinsic, which provides a way to detect these kinds of
errors and handle them without aborting.
 
=={{header|Yabasic}}==
5

edits