mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-10 21:58:48 +01:00
333 lines
12 KiB
HTML
333 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
|
|
<title>Functions – 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>Functions</h2>
|
|
<p>Like many languages today, functions in Wren are little bundles of code
|
|
you can store in a variable, or pass as an argument to a method. </p>
|
|
<p>Notice there’s a difference between <em>function</em> and <em>method</em>.</p>
|
|
<p>Since Wren is object-oriented, most of your code will live in methods on
|
|
classes, but free-floating functions are still eminently handy. </p>
|
|
<p>Functions are objects like everything else in Wren, instances of the <code>Fn</code>
|
|
class.</p>
|
|
<h2>Creating a function <a href="#creating-a-function" name="creating-a-function" class="header-anchor">#</a></h2>
|
|
<p>To create a function, we call <code>Fn.new</code>, which takes a block to execute.
|
|
To call the function, we use <code>.call()</code> on the function instance.</p>
|
|
<pre class="snippet">
|
|
var sayHello = Fn.new { System.print("hello") }
|
|
|
|
sayHello.call() //> hello
|
|
</pre>
|
|
|
|
<p>Note that we’ll see a shorthand syntax for creating a function below.</p>
|
|
<h2>Function parameters <a href="#function-parameters" name="function-parameters" class="header-anchor">#</a></h2>
|
|
<p>Of course, functions aren’t very useful if you can’t pass values to them. The
|
|
function above takes no arguments. To change that, you can provide a parameter
|
|
list surrounded by <code>|</code> immediately after the opening brace of the body.</p>
|
|
<p>To pass arguments to the function, pass them to the <code>call</code> method:</p>
|
|
<pre class="snippet">
|
|
var sayMessage = Fn.new {|recipient, message|
|
|
System.print("message for %(recipient): %(message)")
|
|
}
|
|
|
|
sayMessage.call("Bob", "Good day!")
|
|
</pre>
|
|
|
|
<p>It’s an error to call a function with fewer arguments than its parameter list
|
|
expects. If you pass too <em>many</em> arguments, the extras are ignored.</p>
|
|
<h2>Returning values <a href="#returning-values" name="returning-values" class="header-anchor">#</a></h2>
|
|
<p>The body of a function is a <a href="syntax.html#blocks">block</a>. If it is a single
|
|
expression—more precisely if there is no newline after the <code>{</code> or
|
|
parameter list—then the function implicitly returns the value of the
|
|
expression.</p>
|
|
<p>Otherwise, the body returns <code>null</code> by default. You can explicitly return a
|
|
value using a <code>return</code> statement. In other words, these two functions do the
|
|
same thing:</p>
|
|
<pre class="snippet">
|
|
Fn.new { "return value" }
|
|
|
|
Fn.new {
|
|
return "return value"
|
|
}
|
|
</pre>
|
|
|
|
<p>The return value is handed back to you when using <code>call</code>:</p>
|
|
<pre class="snippet">
|
|
var fn = Fn.new { "some value" }
|
|
var result = fn.call()
|
|
System.print(result) //> some value
|
|
</pre>
|
|
|
|
<h2>Closures <a href="#closures" name="closures" class="header-anchor">#</a></h2>
|
|
<p>As you expect, functions are closures—they can access variables defined
|
|
outside of their scope. They will hold onto closed-over variables even after
|
|
leaving the scope where the function is defined:</p>
|
|
<pre class="snippet">
|
|
class Counter {
|
|
static create() {
|
|
var i = 0
|
|
return Fn.new { i = i + 1 }
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
<p>Here, the <code>create</code> method returns the function created on its second line. That
|
|
function references a variable <code>i</code> declared outside of the function. Even after
|
|
the function is returned from <code>create</code>, it is still able to read and assign
|
|
to<code>i</code>:</p>
|
|
<pre class="snippet">
|
|
var counter = Counter.create()
|
|
System.print(counter.call()) //> 1
|
|
System.print(counter.call()) //> 2
|
|
System.print(counter.call()) //> 3
|
|
</pre>
|
|
|
|
<h2>Callable classes <a href="#callable-classes" name="callable-classes" class="header-anchor">#</a></h2>
|
|
<p>Because <code>Fn</code> is a class, and responds to <code>call()</code>, any class can respond to
|
|
<code>call()</code> and be used in place of a function. This is particularly handy when
|
|
the function is passed to a method to be called, like a callback or event.</p>
|
|
<pre class="snippet">
|
|
class Callable {
|
|
construct new() {}
|
|
call(name, version) {
|
|
System.print("called %(name) with version %(version)")
|
|
}
|
|
}
|
|
|
|
var fn = Callable.new()
|
|
fn.call("wren", "0.4.0")
|
|
</pre>
|
|
|
|
<h2>Block arguments <a href="#block-arguments" name="block-arguments" class="header-anchor">#</a></h2>
|
|
<p>Very frequently, functions are passed to methods to be called. There are
|
|
countless examples of this in Wren, like <a href="lists.html">list</a> can be filtered
|
|
using a method <code>where</code> which accepts a function:</p>
|
|
<pre class="snippet">
|
|
var list = [1, 2, 3, 4, 5]
|
|
var filtered = list.where(Fn.new {|value| value > 3 })
|
|
System.print(filtered.toList) //> [4, 5]
|
|
</pre>
|
|
|
|
<p>This syntax is a bit less fun to read and write, so Wren implements the
|
|
<em>block argument</em> concept. When a function is being passed to a method,
|
|
and is the last argument to the method, it can use a shorter syntax:
|
|
<em>just the block part</em>.</p>
|
|
<p>Let’s use a block argument for <code>list.where</code>, it’s the last (only) argument:</p>
|
|
<pre class="snippet">
|
|
var list = [1, 2, 3, 4, 5]
|
|
var filtered = list.where {|value| value > 3 }
|
|
System.print(filtered.toList) //> [4, 5]
|
|
</pre>
|
|
|
|
<p>We’ve seen this before in a previous page using <code>map</code> and <code>where</code>:</p>
|
|
<pre class="snippet">
|
|
numbers.map {|n| n * 2 }.where {|n| n < 100 }
|
|
</pre>
|
|
|
|
<h2>Block argument example <a href="#block-argument-example" name="block-argument-example" class="header-anchor">#</a></h2>
|
|
<p>Let’s look at a complete example, so we can see both ends.</p>
|
|
<p>Here’s a fictional class for something that will call a function
|
|
when a click event is sent to it. It allows us to pass just a
|
|
function and assume the left mouse button, or to pass a button and a function.</p>
|
|
<pre class="snippet">
|
|
class Clickable {
|
|
construct new() {
|
|
_fn = null
|
|
_button = 0
|
|
}
|
|
|
|
onClick(fn) {
|
|
_fn = fn
|
|
}
|
|
|
|
onClick(button, fn) {
|
|
_button = button
|
|
_fn = fn
|
|
}
|
|
|
|
fireEvent(button) {
|
|
if(_fn && button == _button) {
|
|
_fn.call(button)
|
|
}
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
<p>Now that we’ve got the clickable class, let’s use it.
|
|
We’ll start by using the method that accepts just a function
|
|
because we’re fine with it just being the default left mouse button.</p>
|
|
<pre class="snippet">
|
|
var link = Clickable.new()
|
|
|
|
link.onClick {|button|
|
|
System.print("I was clicked by button %(button)")
|
|
}
|
|
|
|
// send a left mouse click
|
|
// normally this would happen from elsewhere
|
|
|
|
link.fireEvent(0) //> I was clicked by button 0
|
|
</pre>
|
|
|
|
<p>Now let’s try with the extra button argument:</p>
|
|
<pre class="snippet">
|
|
var contextMenu = Clickable.new()
|
|
|
|
contextMenu.onClick(1) {|button|
|
|
System.print("I was right-clicked")
|
|
}
|
|
|
|
link.fireEvent(0) //> (nothing happened)
|
|
link.fireEvent(1) //> I was right-clicked
|
|
</pre>
|
|
|
|
<p>Notice that we still pass the other arguments normally,
|
|
it’s only the last argument that is special.</p>
|
|
<p><strong>Just a regular function</strong> </p>
|
|
<p>Block arguments are purely syntax sugar for creating a function and passing it
|
|
in one little blob of syntax. These two are equivalent:</p>
|
|
<pre class="snippet">
|
|
onClick(Fn.new { System.print("clicked") })
|
|
onClick { System.print("clicked") }
|
|
</pre>
|
|
|
|
<p>And this is just as valid:</p>
|
|
<pre class="snippet">
|
|
var onEvent = Fn.new {|button|
|
|
System.print("clicked by button %(button)")
|
|
}
|
|
|
|
onClick(onEvent)
|
|
onClick(1, onEvent)
|
|
</pre>
|
|
|
|
<p><strong>Fn.new</strong> <br />
|
|
As you may have noticed by now, <code>Fn</code> accepts a block argument for the <code>Fn.new</code>.
|
|
All the constructor does is return that argument right back to you!</p>
|
|
<p><br><hr>
|
|
<a class="right" href="classes.html">Classes →</a>
|
|
<a href="variables.html">← Variables</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>
|