2014-01-30 06:51:52 -08:00
|
|
|
^title Functions
|
|
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
No self-respecting language today can get by without functions—first
|
|
|
|
|
class little bundles of code. Since Wren is object-oriented, most of your code
|
|
|
|
|
will live in methods on classes, but free-floating functions are still
|
|
|
|
|
eminently handy.
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
Functions are objects like everything else in Wren, instances of the `Fn`
|
|
|
|
|
class.
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
## Block arguments
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
Most of the time you create a function just to pass it to some method. For
|
|
|
|
|
example, if you want to filter a [list](lists.html) by some criteria, you'll
|
|
|
|
|
call its `where` method, passing in a function that defines the predicate
|
|
|
|
|
you're filtering on.
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
Since that's the most common usage pattern, Wren's syntax optimizes for that.
|
|
|
|
|
Taking a page from Ruby, a function is created by passing a *block argument* to
|
|
|
|
|
a method. At its simplest, it looks like this:
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
<pre class="snippet">
|
|
|
|
|
blondie.callMe {
|
|
|
|
|
System.print("This is the body!")
|
|
|
|
|
}
|
|
|
|
|
</pre>
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
Here we're invoking the `callMe` method on `blondie`. We're passing one
|
2015-10-18 15:56:52 -07:00
|
|
|
argument, a function whose body is the
|
|
|
|
|
following [block](syntax.html#blocks)—everything between that pair of
|
|
|
|
|
curly braces.
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
Methods that take a block argument receive it as a normal parameter. `callMe`
|
|
|
|
|
could be defined like so:
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
<pre class="snippet">
|
|
|
|
|
class Blondie {
|
|
|
|
|
callMe(fn) {
|
|
|
|
|
// Call it...
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
var blondie = Blondie.new()
|
|
|
|
|
</pre>
|
2017-03-23 21:22:07 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
A method can take other arguments in addition to the block. They appear before
|
|
|
|
|
the block just like a regular argument list. For example:
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
<pre class="snippet">
|
|
|
|
|
blondie.callMeAt(867, 5309) {
|
|
|
|
|
System.print("This is the body!")
|
|
|
|
|
}
|
|
|
|
|
</pre>
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
Of course, you don't *have* to use a block argument to pass a function to a
|
|
|
|
|
method. If you already have a function object, you can pass it like a regular
|
|
|
|
|
argument:
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
<pre class="snippet">
|
|
|
|
|
var someFn = // Get a function...
|
|
|
|
|
blondie.callMe(someFn)
|
|
|
|
|
</pre>
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
Block arguments are purely sugar for creating a function and passing it in one
|
|
|
|
|
little blob of syntax. There are some times when you want to create a function
|
|
|
|
|
but *don't* need to pass it to a method. For that, you can call the `Fn`
|
|
|
|
|
class's constructor:
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
<pre class="snippet">
|
|
|
|
|
var someFn = Fn.new {
|
|
|
|
|
System.print("Hi!")
|
|
|
|
|
}
|
|
|
|
|
</pre>
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2021-03-02 12:27:23 -05:00
|
|
|
As you can see it takes a block argument too! All the constructor does is
|
|
|
|
|
return that argument, so this exists purely as a convenience method for you.
|
2014-04-04 20:45:12 -07:00
|
|
|
|
|
|
|
|
## Calling functions
|
|
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
Once you have a function, how do you invoke it? Like everything in Wren, you do
|
|
|
|
|
so by calling a method on it:
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
<pre class="snippet">
|
|
|
|
|
class Blondie {
|
|
|
|
|
callMe(fn) {
|
|
|
|
|
fn.call()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</pre>
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2015-02-26 23:08:36 -08:00
|
|
|
Functions expose a `call()` method that executes the body of the function. This
|
2015-01-03 23:27:02 -08:00
|
|
|
method is dynamically-dispatched like any other, so you can define your own
|
|
|
|
|
"function-like" classes and pass them to methods that expect "real" functions.
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
<pre class="snippet">
|
|
|
|
|
class FakeFn {
|
|
|
|
|
call() {
|
|
|
|
|
System.print("I'm feeling functional!")
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
blondie.callMe(FakeFn.new())
|
|
|
|
|
</pre>
|
2014-04-04 20:45:12 -07:00
|
|
|
|
|
|
|
|
## Function parameters
|
|
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
Of course, functions aren't very useful if you can't pass values to them. The
|
|
|
|
|
functions that we've seen so far take no arguments. To change that, you can
|
|
|
|
|
provide a parameter list surrounded by `|` immediately after the opening brace
|
|
|
|
|
of the body, like so:
|
2014-04-07 21:03:16 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
<pre class="snippet">
|
|
|
|
|
blondie.callMe {|first, last|
|
|
|
|
|
System.print("Hi, " + first + " " + last + "!")
|
|
|
|
|
}
|
|
|
|
|
</pre>
|
2014-04-07 21:03:16 -07:00
|
|
|
|
2019-09-30 09:02:55 -05:00
|
|
|
Here we're passing a function to `callMe` that takes two parameters, `first` and
|
2015-01-03 23:27:02 -08:00
|
|
|
`last`. They are passed to the function when it's called:
|
2014-04-07 21:03:16 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
<pre class="snippet">
|
|
|
|
|
class Blondie {
|
|
|
|
|
callMe(fn) {
|
|
|
|
|
fn.call("Debbie", "Harry")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</pre>
|
2014-04-07 21:03:16 -07:00
|
|
|
|
2015-01-23 20:33:05 -08:00
|
|
|
It's an error to call a function with fewer arguments than its parameter list
|
|
|
|
|
expects. If you pass too *many* arguments, the extras are ignored.
|
2014-04-07 21:03:16 -07:00
|
|
|
|
|
|
|
|
## Returning values
|
|
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
The body of a function is a [block](syntax.html#blocks). If it is a single
|
|
|
|
|
expression—more precisely if there is no newline after the `{` or
|
|
|
|
|
parameter list—then the function implicitly returns the value of the
|
|
|
|
|
expression.
|
2014-04-07 21:03:16 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
Otherwise, the body returns `null` by default. You can explicitly return a
|
|
|
|
|
value using a `return` statement. In other words, these two functions do the
|
|
|
|
|
same thing:
|
2014-04-07 21:03:16 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
<pre class="snippet">
|
|
|
|
|
Fn.new { "return value" }
|
2014-04-07 21:03:16 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
Fn.new {
|
|
|
|
|
return "return value"
|
|
|
|
|
}
|
|
|
|
|
</pre>
|
2014-04-04 20:45:12 -07:00
|
|
|
|
|
|
|
|
## Closures
|
|
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
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:
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
<pre class="snippet">
|
|
|
|
|
class Counter {
|
|
|
|
|
static create() {
|
|
|
|
|
var i = 0
|
|
|
|
|
return Fn.new { i = i + 1 }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</pre>
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2015-01-03 23:27:02 -08:00
|
|
|
Here, the `create` method returns the function created on its second line. That
|
|
|
|
|
function references a variable `i` declared outside of the function. Even after
|
|
|
|
|
the function is returned from `create`, it is still able to read and assign
|
|
|
|
|
to`i`:
|
2014-04-04 20:45:12 -07:00
|
|
|
|
2020-06-05 14:57:20 -07:00
|
|
|
<pre class="snippet">
|
|
|
|
|
var counter = Counter.create()
|
|
|
|
|
System.print(counter.call()) //> 1
|
|
|
|
|
System.print(counter.call()) //> 2
|
|
|
|
|
System.print(counter.call()) //> 3
|
|
|
|
|
</pre>
|
2015-11-07 11:09:04 -08:00
|
|
|
|
2019-02-05 18:18:24 -08:00
|
|
|
<br><hr>
|
2015-11-07 11:09:04 -08:00
|
|
|
<a class="right" href="classes.html">Classes →</a>
|
|
|
|
|
<a href="variables.html">← Variables</a>
|