mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-12 06:38:45 +01:00
260 lines
17 KiB
HTML
260 lines
17 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
|
||
<title>Control Flow – Wren</title>
|
||
<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>
|
||
<ul>
|
||
<li><a href="getting-started.html">Getting Started</a></li>
|
||
</ul>
|
||
<section>
|
||
<h2>language</h2>
|
||
<ul>
|
||
<li><a href="syntax.html">Syntax</a></li>
|
||
<li><a href="expressions.html">Expressions</a></li>
|
||
<li><a href="variables.html">Variables</a></li>
|
||
<li><a href="control-flow.html">Control Flow</a></li>
|
||
<li><a href="error-handling.html">Error Handling</a></li>
|
||
<li><a href="modules.html">Modules</a></li>
|
||
</ul>
|
||
</section>
|
||
<section>
|
||
<h2>types</h2>
|
||
<ul>
|
||
<li><a href="values.html">Values</a></li>
|
||
<li><a href="classes.html">Classes</a></li>
|
||
<li><a href="fibers.html">Fibers</a></li>
|
||
<li><a href="functions.html">Functions</a></li>
|
||
<li><a href="lists.html">Lists</a></li>
|
||
<li><a href="maps.html">Maps</a></li>
|
||
</ul>
|
||
</section>
|
||
<section>
|
||
<h2>reference</h2>
|
||
<ul>
|
||
<li><a href="core">Core Library</a></li>
|
||
<li><a href="embedding-api.html">Embedding API</a></li>
|
||
<li><a href="performance.html">Performance</a></li>
|
||
<li><a href="community.html">Community</a></li>
|
||
<li><a href="contributing.html">Contributing</a></li>
|
||
<li><a href="qa.html">Q & A</a></li>
|
||
</ul>
|
||
</section>
|
||
</nav>
|
||
<main>
|
||
<h1>Control Flow</h1>
|
||
<p>Control flow is used to determine which chunks of code are executed and how
|
||
many times. <em>Branching</em> statements deciding 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 is conditional on the value of some expression. We take the entire
|
||
universe of possible values 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>
|
||
<div class="codehilite"><pre><span class="k">if</span> <span class="p">(</span><span class="n">ready</span><span class="p">)</span> <span class="n">IO</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s2">"go!"</span><span class="p">)</span>
|
||
</pre></div>
|
||
|
||
|
||
<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>
|
||
<div class="codehilite"><pre><span class="k">if</span> <span class="p">(</span><span class="n">ready</span><span class="p">)</span> <span class="p">{</span>
|
||
<span class="n">IO</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s2">"getSet"</span><span class="p">)</span>
|
||
<span class="n">IO</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s2">"go!"</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>You may also provide an <code>else</code> branch. It will be executed if the condition is
|
||
false:</p>
|
||
<div class="codehilite"><pre><span class="k">if</span> <span class="p">(</span><span class="n">ready</span><span class="p">)</span> <span class="n">IO</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s2">"go!"</span><span class="p">)</span> <span class="k">else</span> <span class="n">IO</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s2">"not ready!"</span><span class="p">)</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>And, of course, it can take a block too:</p>
|
||
<div class="codehilite"><pre><span class="k">if</span> <span class="p">(</span><span class="n">ready</span><span class="p">)</span> <span class="p">{</span>
|
||
<span class="n">IO</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s2">"go!"</span><span class="p">)</span>
|
||
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
||
<span class="n">IO</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s2">"not ready!"</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
|
||
|
||
<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>
|
||
<div class="codehilite"><pre><span class="c1">// Hailstone sequence.</span>
|
||
<span class="kd">var</span> <span class="n">n</span> <span class="o">=</span> <span class="m">27</span>
|
||
<span class="k">while</span> <span class="p">(</span><span class="n">n</span> <span class="o">!=</span> <span class="m">1</span><span class="p">)</span> <span class="p">{</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="m">2</span> <span class="o">==</span> <span class="m">0</span><span class="p">)</span> <span class="p">{</span>
|
||
<span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="m">2</span>
|
||
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
||
<span class="n">n</span> <span class="o">=</span> <span class="m">3</span> <span class="o">*</span> <span class="n">n</span> <span class="o">+</span> <span class="m">1</span>
|
||
<span class="p">}</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
|
||
|
||
<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>
|
||
<div class="codehilite"><pre><span class="kd">var</span> <span class="n">n</span> <span class="o">=</span> <span class="m">27</span>
|
||
<span class="k">while</span> <span class="p">(</span><span class="n">n</span> <span class="o">!=</span> <span class="m">1</span><span class="p">)</span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="m">2</span> <span class="o">==</span> <span class="m">0</span><span class="p">)</span> <span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="m">2</span> <span class="k">else</span> <span class="n">n</span> <span class="o">=</span> <span class="m">3</span> <span class="o">*</span> <span class="n">n</span> <span class="o">+</span> <span class="m">1</span>
|
||
</pre></div>
|
||
|
||
|
||
<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 for. It looks like this:</p>
|
||
<div class="codehilite"><pre><span class="k">for</span> <span class="p">(</span><span class="n">beatle</span> <span class="k">in</span> <span class="p">[</span><span class="s2">"george"</span><span class="p">,</span> <span class="s2">"john"</span><span class="p">,</span> <span class="s2">"paul"</span><span class="p">,</span> <span class="s2">"ringo"</span><span class="p">])</span> <span class="p">{</span>
|
||
<span class="n">IO</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">beatle</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
|
||
|
||
<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 will immediately exit out of the nearest enclosing
|
||
<code>while</code> or <code>for</code> loop.</p>
|
||
<div class="codehilite"><pre><span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="k">in</span> <span class="p">[</span><span class="m">1</span><span class="p">,</span> <span class="m">2</span><span class="p">,</span> <span class="m">3</span><span class="p">,</span> <span class="m">4</span><span class="p">])</span> <span class="p">{</span>
|
||
<span class="n">IO</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="m">3</span><span class="p">)</span> <span class="k">break</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>So this program will print the numbers from 1 to 3, but will not print 4.</p>
|
||
<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>
|
||
<div class="codehilite"><pre><span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="k">in</span> <span class="m">1.</span><span class="p">.</span><span class="m">100</span><span class="p">)</span> <span class="p">{</span>
|
||
<span class="n">IO</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
|
||
|
||
<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>
|
||
<div class="codehilite"><pre><span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="k">in</span> <span class="m">1.</span><span class="p">..</span><span class="m">100</span><span class="p">)</span> <span class="p">{</span>
|
||
<span class="n">IO</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
|
||
|
||
<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="expressions.html#operators">other operators</a>, they are just
|
||
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 a <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>
|
||
<div class="codehilite"><pre><span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="k">in</span> <span class="m">1.</span><span class="p">.</span><span class="m">100</span><span class="p">)</span> <span class="p">{</span>
|
||
<span class="n">IO</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>Wren sees it something like this:</p>
|
||
<div class="codehilite"><pre><span class="kd">var</span> <span class="n">iter_</span> <span class="o">=</span> <span class="kc">null</span>
|
||
<span class="kd">var</span> <span class="n">seq_</span> <span class="o">=</span> <span class="m">1.</span><span class="p">.</span><span class="m">100</span>
|
||
<span class="k">while</span> <span class="p">(</span><span class="n">iter_</span> <span class="o">=</span> <span class="n">seq_</span><span class="p">.</span><span class="n">iterate</span><span class="p">(</span><span class="n">iter_</span><span class="p">))</span> <span class="p">{</span>
|
||
<span class="kd">var</span> <span class="n">i</span> <span class="o">=</span> <span class="n">seq_</span><span class="p">.</span><span class="n">iteratorValue</span><span class="p">(</span><span class="n">iter_</span><span class="p">)</span>
|
||
<span class="n">IO</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
|
||
|
||
<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>
|
||
</main>
|
||
</div>
|
||
<footer>
|
||
<div class="page">
|
||
<div class="main-column">
|
||
<p>Wren lives <a href="https://github.com/munificent/wren">on GitHub</a> — Made with ❤ by <a href="http://journal.stuffwithstuff.com/">Bob Nystrom</a> and <a href="https://github.com/munificent/wren/blob/master/AUTHORS">friends</a>.</p>
|
||
<div class="main-column">
|
||
</div>
|
||
</footer>
|
||
</body>
|
||
</html>
|