mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-10 21:58:48 +01:00
362 lines
15 KiB
HTML
362 lines
15 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
|
|
<title>Control Flow – Wren</title>
|
|
<script type="application/javascript" src="prism.js" data-manual></script>
|
|
<script type="application/javascript" src="codejar.js"></script>
|
|
<script type="application/javascript" src="wren.js"></script>
|
|
<link rel="stylesheet" type="text/css" href="prism.css" />
|
|
<link rel="stylesheet" type="text/css" href="style.css" />
|
|
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
|
|
<!-- Tell mobile browsers we're optimized for them and they don't need to crop
|
|
the viewport. -->
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
|
|
</head>
|
|
<body id="top">
|
|
<header>
|
|
<div class="page">
|
|
<div class="main-column">
|
|
<h1><a href="./">wren</a></h1>
|
|
<h2>a classy little scripting language</h2>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
<div class="page">
|
|
<nav class="big">
|
|
<a href="./"><img src="./wren.svg" class="logo"></a>
|
|
<ul>
|
|
<li><a href="getting-started.html">Getting Started</a></li>
|
|
<li><a href="contributing.html">Contributing</a></li>
|
|
<li><a href="blog">Blog</a></li>
|
|
<li><a href="try">Try it!</a></li>
|
|
</ul>
|
|
<section>
|
|
<h2>guides</h2>
|
|
<ul>
|
|
<li><a href="syntax.html">Syntax</a></li>
|
|
<li><a href="values.html">Values</a></li>
|
|
<li><a href="lists.html">Lists</a></li>
|
|
<li><a href="maps.html">Maps</a></li>
|
|
<li><a href="method-calls.html">Method Calls</a></li>
|
|
<li><a href="control-flow.html">Control Flow</a></li>
|
|
<li><a href="variables.html">Variables</a></li>
|
|
<li><a href="classes.html">Classes</a></li>
|
|
<li><a href="functions.html">Functions</a></li>
|
|
<li><a href="concurrency.html">Concurrency</a></li>
|
|
<li><a href="error-handling.html">Error Handling</a></li>
|
|
<li><a href="modularity.html">Modularity</a></li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>API docs</h2>
|
|
<ul>
|
|
<li><a href="modules">Modules</a></li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>reference</h2>
|
|
<ul>
|
|
<li><a href="cli">Wren CLI</a></li>
|
|
<li><a href="embedding">Embedding</a></li>
|
|
<li><a href="performance.html">Performance</a></li>
|
|
<li><a href="qa.html">Q & A</a></li>
|
|
</ul>
|
|
</section>
|
|
</nav>
|
|
<nav class="small">
|
|
<table>
|
|
<tr>
|
|
<div><a href="getting-started.html">Getting Started</a></div>
|
|
<div><a href="contributing.html">Contributing</a></div>
|
|
<div><a href="blog">Blog</a></div>
|
|
<div><a href="try">Try it!</a></div>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2"><h2>guides</h2></td>
|
|
<td><h2>reference</h2></td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<ul>
|
|
<li><a href="syntax.html">Syntax</a></li>
|
|
<li><a href="values.html">Values</a></li>
|
|
<li><a href="lists.html">Lists</a></li>
|
|
<li><a href="maps.html">Maps</a></li>
|
|
<li><a href="method-calls.html">Method Calls</a></li>
|
|
<li><a href="control-flow.html">Control Flow</a></li>
|
|
</ul>
|
|
</td>
|
|
<td>
|
|
<ul>
|
|
<li><a href="variables.html">Variables</a></li>
|
|
<li><a href="classes.html">Classes</a></li>
|
|
<li><a href="functions.html">Functions</a></li>
|
|
<li><a href="concurrency.html">Concurrency</a></li>
|
|
<li><a href="error-handling.html">Error Handling</a></li>
|
|
<li><a href="modularity.html">Modularity</a></li>
|
|
</ul>
|
|
</td>
|
|
<td>
|
|
<ul>
|
|
<li><a href="modules">API/Modules</a></li>
|
|
<li><a href="embedding">Embedding</a></li>
|
|
<li><a href="performance.html">Performance</a></li>
|
|
<li><a href="qa.html">Q & A</a></li>
|
|
</ul>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</nav>
|
|
<main>
|
|
<h2>Control Flow</h2>
|
|
<p>Control flow is used to determine which chunks of code are executed and how many
|
|
times. <em>Branching</em> statements and expressions decide whether or not to execute
|
|
some code and <em>looping</em> ones execute something more than once.</p>
|
|
<h2>Truth <a href="#truth" name="truth" class="header-anchor">#</a></h2>
|
|
<p>All control flow is based on <em>deciding</em> whether or not to do something. This
|
|
decision depends on some expression’s value. We take the entire universe of
|
|
possible objects and divide them into two buckets: some we consider “true” and
|
|
the rest are “false”. If the expression results in a value in the true bucket,
|
|
we do one thing. Otherwise, we do something else.</p>
|
|
<p>Obviously, the boolean <code>true</code> is in the “true” bucket and <code>false</code> is in
|
|
“false”, but what about values of other types? The choice is ultimately
|
|
arbitrary, and different languages have different rules. Wren’s rules follow
|
|
Ruby:</p>
|
|
<ul>
|
|
<li>The boolean value <code>false</code> is false.</li>
|
|
<li>The null value <code>null</code> is false.</li>
|
|
<li>Everything else is true.</li>
|
|
</ul>
|
|
<p>This means <code>0</code>, empty strings, and empty collections are all considered “true”
|
|
values.</p>
|
|
<h2>If statements <a href="#if-statements" name="if-statements" class="header-anchor">#</a></h2>
|
|
<p>The simplest branching statement, <code>if</code> lets you conditionally skip a chunk of
|
|
code. It looks like this:</p>
|
|
<pre class="snippet">
|
|
if (ready) System.print("go!")
|
|
</pre>
|
|
|
|
<p>That evaluates the parenthesized expression after <code>if</code>. If it’s true, then the
|
|
statement after the condition is evaluated. Otherwise it is skipped. Instead of
|
|
a statement, you can have a <a href="syntax.html#blocks">block</a>:</p>
|
|
<pre class="snippet">
|
|
if (ready) {
|
|
System.print("getSet")
|
|
System.print("go!")
|
|
}
|
|
</pre>
|
|
|
|
<p>You may also provide an <code>else</code> branch. It will be executed if the condition is
|
|
false:</p>
|
|
<pre class="snippet">
|
|
if (ready) System.print("go!") else System.print("not ready!")
|
|
</pre>
|
|
|
|
<p>And, of course, it can take a block too:</p>
|
|
<pre class="snippet">
|
|
if (ready) {
|
|
System.print("go!")
|
|
} else {
|
|
System.print("not ready!")
|
|
}
|
|
</pre>
|
|
|
|
<h2>Logical operators <a href="#logical-operators" name="logical-operators" class="header-anchor">#</a></h2>
|
|
<p>Unlike most other <a href="method-calls.html#operators">operators</a> in Wren which are just a special syntax for
|
|
<a href="method-calls.html">method calls</a>, the <code>&&</code> and <code>||</code> operators are special. This is because they
|
|
only conditionally evaluate the right operand—they short-circuit.</p>
|
|
<p>A <code>&&</code> (“logical and”) expression evaluates the left-hand argument. If it’s
|
|
false, it returns that value. Otherwise it evaluates and returns the right-hand
|
|
argument.</p>
|
|
<pre class="snippet">
|
|
System.print(false && 1) //> false
|
|
System.print(1 && 2) //> 2
|
|
</pre>
|
|
|
|
<p>A <code>||</code> (“logical or”) expression is reversed. If the left-hand argument is
|
|
<em>true</em>, it’s returned, otherwise the right-hand argument is evaluated and
|
|
returned:</p>
|
|
<pre class="snippet">
|
|
System.print(false || 1) //> 1
|
|
System.print(1 || 2) //> 1
|
|
</pre>
|
|
|
|
<h2>The conditional operator <code>?:</code> <a href="#the-conditional-operator-" name="the-conditional-operator-" class="header-anchor">#</a></h2>
|
|
<p>Also known as the “ternary” operator since it takes three arguments, Wren has
|
|
the little “if statement in the form of an expression” you know and love from C
|
|
and similar languages.</p>
|
|
<pre class="snippet">
|
|
System.print(1 != 2 ? "math is sane" : "math is not sane!")
|
|
</pre>
|
|
|
|
<p>It takes a condition expression, followed by <code>?</code>, followed by a then
|
|
expression, a <code>:</code>, then an else expression. Just like <code>if</code>, it evaluates the
|
|
condition. If true, it evaluates and returns the then expression. Otherwise
|
|
it does the else expression.</p>
|
|
<h2>While statements <a href="#while-statements" name="while-statements" class="header-anchor">#</a></h2>
|
|
<p>It’s hard to write a useful program without executing some chunk of code
|
|
repeatedly. To do that, you use looping statements. There are two in Wren, and
|
|
they should be familiar if you’ve used other imperative languages.</p>
|
|
<p>The simplest, a <code>while</code> statement executes a chunk of code as long as a
|
|
condition continues to hold. For example:</p>
|
|
<pre class="snippet">
|
|
// Hailstone sequence.
|
|
var n = 27
|
|
while (n != 1) {
|
|
if (n % 2 == 0) {
|
|
n = n / 2
|
|
} else {
|
|
n = 3 * n + 1
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
<p>This evaluates the expression <code>n != 1</code>. If it is true, then it executes the
|
|
following body. After that, it loops back to the top, and evaluates the
|
|
condition again. It keeps doing this as long as the condition evaluates to
|
|
something true.</p>
|
|
<p>The condition for a while loop can be any expression, and must be surrounded by
|
|
parentheses. The body of the loop is usually a curly block but can also be a
|
|
single statement:</p>
|
|
<pre class="snippet">
|
|
var n = 27
|
|
while (n != 1) if (n % 2 == 0) n = n / 2 else n = 3 * n + 1
|
|
</pre>
|
|
|
|
<h2>For statements <a href="#for-statements" name="for-statements" class="header-anchor">#</a></h2>
|
|
<p>While statements are useful when you want to loop indefinitely or according to
|
|
some complex condition. But in most cases, you’re looping through
|
|
a <a href="lists.html">list</a>, a series of numbers, or some other “sequence” object.
|
|
That’s what <code>for</code> is, uh, for. It looks like this:</p>
|
|
<pre class="snippet">
|
|
for (beatle in ["george", "john", "paul", "ringo"]) {
|
|
System.print(beatle)
|
|
}
|
|
</pre>
|
|
|
|
<p>A <code>for</code> loop has three components:</p>
|
|
<ol>
|
|
<li>
|
|
<p>A <em>variable name</em> to bind. In the example, that’s <code>beatle</code>. Wren will create
|
|
a new variable with that name whose scope is the body of the loop.</p>
|
|
</li>
|
|
<li>
|
|
<p>A <em>sequence expression</em>. This determines what you’re looping over. It gets
|
|
evaluated <em>once</em> before the body of the loop. In this case, it’s a list
|
|
literal, but it can be any expression.</p>
|
|
</li>
|
|
<li>
|
|
<p>A <em>body</em>. This is a curly block or a single statement. It gets executed once
|
|
for each iteration of the loop.</p>
|
|
</li>
|
|
</ol>
|
|
<h2>Break statements <a href="#break-statements" name="break-statements" class="header-anchor">#</a></h2>
|
|
<p>Sometimes, right in the middle of a loop body, you decide you want to bail out
|
|
and stop. To do that, you can use a <code>break</code> statement. It’s just the <code>break</code>
|
|
keyword all by itself. That immediately exits out of the nearest enclosing
|
|
<code>while</code> or <code>for</code> loop.</p>
|
|
<pre class="snippet">
|
|
for (i in [1, 2, 3, 4]) {
|
|
System.print(i) //> 1
|
|
if (i == 3) break //> 2
|
|
} //> 3
|
|
</pre>
|
|
|
|
<h2>Continue statements <a href="#continue-statements" name="continue-statements" class="header-anchor">#</a></h2>
|
|
<p>During the execution of a loop body, you might decide that you want to skip the
|
|
rest of this iteration and move on to the next one. You can use a <code>continue</code>
|
|
statement to do that. It’s just the <code>continue</code> keyword all by itself. Execution
|
|
will immediately jump to the beginning of the next loop iteration (and check the
|
|
loop conditions).</p>
|
|
<pre class="snippet">
|
|
for (i in [1, 2, 3, 4]) {
|
|
if (i == 2) continue //> 1
|
|
System.print(i) //> 3
|
|
} //> 4
|
|
</pre>
|
|
|
|
<h2>Numeric ranges <a href="#numeric-ranges" name="numeric-ranges" class="header-anchor">#</a></h2>
|
|
<p>Lists are one common use for <code>for</code> loops, but sometimes you want to walk over a
|
|
sequence of numbers, or loop a number of times. For that, you can create a
|
|
<a href="values.html#ranges">range</a>, like so:</p>
|
|
<pre class="snippet">
|
|
for (i in 1..100) {
|
|
System.print(i)
|
|
}
|
|
</pre>
|
|
|
|
<p>This loops over the numbers from 1 to 100, including 100 itself. If you want to
|
|
leave off the last value, use three dots instead of two:</p>
|
|
<pre class="snippet">
|
|
for (i in 1...100) {
|
|
System.print(i)
|
|
}
|
|
</pre>
|
|
|
|
<p>This looks like some special “range” syntax in the <code>for</code> loop, but it’s actually
|
|
just a pair of operators. The <code>..</code> and <code>...</code> syntax are infix “range” operators.
|
|
Like <a href="method-calls.html#operators">other operators</a>, they are special syntax for a regular method
|
|
call. The number type implements them and returns a <a href="values.html#ranges">range object</a> that knows
|
|
how to iterate over a series of numbers.</p>
|
|
<h2>The iterator protocol <a href="#the-iterator-protocol" name="the-iterator-protocol" class="header-anchor">#</a></h2>
|
|
<p>Lists and ranges cover the two most common kinds of loops, but you should also
|
|
be able to define your own sequences. To enable that, the semantics of <code>for</code>
|
|
are defined in terms of an “iterator protocol”. The loop itself doesn’t know
|
|
anything about lists or ranges, it just knows how to call two particular
|
|
methods on the object that resulted from evaluating the sequence expression.</p>
|
|
<p>When you write a loop like this:</p>
|
|
<pre class="snippet">
|
|
for (i in 1..100) {
|
|
System.print(i)
|
|
}
|
|
</pre>
|
|
|
|
<p>Wren sees it something like this:</p>
|
|
<pre class="snippet">
|
|
var iter_ = null
|
|
var seq_ = 1..100
|
|
while (iter_ = seq_.iterate(iter_)) {
|
|
var i = seq_.iteratorValue(iter_)
|
|
System.print(i)
|
|
}
|
|
</pre>
|
|
|
|
<p>First, Wren evaluates the sequence expression and stores it in a hidden
|
|
variable (written <code>seq_</code> in the example but in reality it doesn’t have a name
|
|
you can use). It also creates a hidden “iterator” variable and initializes it
|
|
to <code>null</code>.</p>
|
|
<p>Each iteration, it calls <code>iterate()</code> on the sequence, passing in the current
|
|
iterator value. (In the first iteration, it passes in <code>null</code>.) The sequence’s
|
|
job is to take that iterator and advance it to the next element in the
|
|
sequence. (Or, in the case where the iterator is <code>null</code>, to advance it to the
|
|
<em>first</em> element). It then returns either the new iterator, or <code>false</code> to
|
|
indicate that there are no more elements.</p>
|
|
<p>If <code>false</code> is returned, Wren exits out of the loop and we’re done. If anything
|
|
else is returned, that means that we have advanced to a new valid element. To
|
|
get that, Wren then calls <code>iteratorValue()</code> on the sequence and passes in the
|
|
iterator value that it just got from calling <code>iterate()</code>. The sequence uses
|
|
that to look up and return the appropriate element.</p>
|
|
<p>The built-in <a href="lists.html">List</a> and <a href="values.html#ranges">Range</a> types implement
|
|
<code>iterate()</code> and <code>iteratorValue()</code> to walk over their respective sequences. You
|
|
can implement the same methods in your classes to make your own types iterable.</p>
|
|
<p><br><hr>
|
|
<a class="right" href="variables.html">Variables →</a>
|
|
<a href="method-calls.html">← Method Calls</a></p>
|
|
</main>
|
|
</div>
|
|
<footer>
|
|
<div class="page">
|
|
<div class="main-column">
|
|
<p>Wren lives
|
|
<a href="https://github.com/wren-lang/wren">on GitHub</a>
|
|
— Made with ❤ by
|
|
<a href="http://journal.stuffwithstuff.com/">Bob Nystrom</a> and
|
|
<a href="https://github.com/wren-lang/wren/blob/main/AUTHORS">friends</a>.
|
|
</p>
|
|
<div class="main-column">
|
|
</div>
|
|
</footer>
|
|
</body>
|
|
</html>
|