forked from Mirror/wren
documentation revisions and missing pieces
This commit is contained in:
@ -267,7 +267,7 @@ inside a method works like this:
|
|||||||
|
|
||||||
So, in the above example, we hit case #2 and it prints "Francis". Distinguishing
|
So, in the above example, we hit case #2 and it prints "Francis". Distinguishing
|
||||||
self sends from outer variables based on the *case* of the first letter in the
|
self sends from outer variables based on the *case* of the first letter in the
|
||||||
name probably seems crazy but it works surprisingly well. Method names are
|
name probably seems weird but it works surprisingly well. Method names are
|
||||||
lowercase in Wren. Class names are capitalized.
|
lowercase in Wren. Class names are capitalized.
|
||||||
|
|
||||||
Most of the time, when you're in a method and want to access a name from outside
|
Most of the time, when you're in a method and want to access a name from outside
|
||||||
|
|||||||
@ -88,8 +88,7 @@ The basic process is simple:
|
|||||||
If there are no failures, you're good to go.
|
If there are no failures, you're good to go.
|
||||||
|
|
||||||
2. **[Fork the repo][fork] so you can change it locally.** Please make your
|
2. **[Fork the repo][fork] so you can change it locally.** Please make your
|
||||||
changes in separate [feature branches][] to make things a little easier on
|
changes in separate [feature branches][] to make things a little easier.
|
||||||
me.
|
|
||||||
|
|
||||||
3. **Change the code.** Please follow the style of the surrounding code. That
|
3. **Change the code.** Please follow the style of the surrounding code. That
|
||||||
basically means `camelCase` names, `{` on the next line, keep within 80
|
basically means `camelCase` names, `{` on the next line, keep within 80
|
||||||
@ -105,8 +104,7 @@ The basic process is simple:
|
|||||||
6. **Add your name and email to the [AUTHORS][] file if you haven't already.**
|
6. **Add your name and email to the [AUTHORS][] file if you haven't already.**
|
||||||
|
|
||||||
7. **Send a [pull request][].** Pat yourself on the back for contributing to a
|
7. **Send a [pull request][].** Pat yourself on the back for contributing to a
|
||||||
fun open source project! I'll take it from here and hopefully we'll get it
|
fun open source project!
|
||||||
landed smoothly.
|
|
||||||
|
|
||||||
## Getting help
|
## Getting help
|
||||||
|
|
||||||
|
|||||||
@ -65,7 +65,7 @@ if (ready) {
|
|||||||
|
|
||||||
Unlike most other [operators][] in Wren which are just a special syntax for
|
Unlike most other [operators][] in Wren which are just a special syntax for
|
||||||
[method calls][], the `&&` and `||` operators are special. This is because they
|
[method calls][], the `&&` and `||` operators are special. This is because they
|
||||||
only conditionally evaluate right operand—they short-circuit.
|
only conditionally evaluate the right operand—they short-circuit.
|
||||||
|
|
||||||
[operators]: method-calls.html#operators
|
[operators]: method-calls.html#operators
|
||||||
[method calls]: method-calls.html
|
[method calls]: method-calls.html
|
||||||
@ -92,7 +92,7 @@ System.print(1 || 2) //> 1
|
|||||||
|
|
||||||
Also known as the "ternary" operator since it takes three arguments, Wren has
|
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
|
the little "if statement in the form of an expression" you know and love from C
|
||||||
and its brethren.
|
and similar languages.
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
System.print(1 != 2 ? "math is sane" : "math is not sane!")
|
System.print(1 != 2 ? "math is sane" : "math is not sane!")
|
||||||
|
|||||||
@ -1,129 +1,43 @@
|
|||||||
^title Functions
|
^title Functions
|
||||||
|
|
||||||
No self-respecting language today can get by without functions—first
|
Like many languages today, functions in Wren are little bundles of code
|
||||||
class little bundles of code. Since Wren is object-oriented, most of your code
|
you can store in a variable, or pass as an argument to a method.
|
||||||
will live in methods on classes, but free-floating functions are still
|
|
||||||
eminently handy.
|
Notice there's a difference between _function_ and _method_.
|
||||||
|
|
||||||
|
Since Wren is object-oriented, most of your code will live in methods on
|
||||||
|
classes, but free-floating functions are still eminently handy.
|
||||||
|
|
||||||
Functions are objects like everything else in Wren, instances of the `Fn`
|
Functions are objects like everything else in Wren, instances of the `Fn`
|
||||||
class.
|
class.
|
||||||
|
|
||||||
## Block arguments
|
## Creating a function
|
||||||
|
|
||||||
Most of the time you create a function just to pass it to some method. For
|
To create a function, we call `Fn.new`, which takes a block to execute.
|
||||||
example, if you want to filter a [list](lists.html) by some criteria, you'll
|
To call the function, we use `.call()` on the function instance.
|
||||||
call its `where` method, passing in a function that defines the predicate
|
|
||||||
you're filtering on.
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
blondie.callMe {
|
var sayHello = Fn.new { System.print("hello") }
|
||||||
System.print("This is the body!")
|
|
||||||
}
|
sayHello.call() //> hello
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
Here we're invoking the `callMe` method on `blondie`. We're passing one
|
Note that we'll see a shorthand syntax for creating a function below.
|
||||||
argument, a function whose body is the
|
|
||||||
following [block](syntax.html#blocks)—everything between that pair of
|
|
||||||
curly braces.
|
|
||||||
|
|
||||||
Methods that take a block argument receive it as a normal parameter. `callMe`
|
|
||||||
could be defined like so:
|
|
||||||
|
|
||||||
<pre class="snippet">
|
|
||||||
class Blondie {
|
|
||||||
callMe(fn) {
|
|
||||||
// Call it...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var blondie = Blondie.new()
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
A method can take other arguments in addition to the block. They appear before
|
|
||||||
the block just like a regular argument list. For example:
|
|
||||||
|
|
||||||
<pre class="snippet">
|
|
||||||
blondie.callMeAt(867, 5309) {
|
|
||||||
System.print("This is the body!")
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
<pre class="snippet">
|
|
||||||
var someFn = // Get a function...
|
|
||||||
blondie.callMe(someFn)
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
<pre class="snippet">
|
|
||||||
var someFn = Fn.new {
|
|
||||||
System.print("Hi!")
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Calling functions
|
|
||||||
|
|
||||||
Once you have a function, how do you invoke it? Like everything in Wren, you do
|
|
||||||
so by calling a method on it:
|
|
||||||
|
|
||||||
<pre class="snippet">
|
|
||||||
class Blondie {
|
|
||||||
callMe(fn) {
|
|
||||||
fn.call()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
Functions expose a `call()` method that executes the body of the function. This
|
|
||||||
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.
|
|
||||||
|
|
||||||
<pre class="snippet">
|
|
||||||
class FakeFn {
|
|
||||||
call() {
|
|
||||||
System.print("I'm feeling functional!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
blondie.callMe(FakeFn.new())
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
## Function parameters
|
## Function parameters
|
||||||
|
|
||||||
Of course, functions aren't very useful if you can't pass values to them. The
|
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
|
function above takes no arguments. To change that, you can provide a parameter
|
||||||
provide a parameter list surrounded by `|` immediately after the opening brace
|
list surrounded by `|` immediately after the opening brace of the body.
|
||||||
of the body, like so:
|
|
||||||
|
To pass arguments to the function, pass them to the `call` method:
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
blondie.callMe {|first, last|
|
var sayMessage {|recipient, message|
|
||||||
System.print("Hi, " + first + " " + last + "!")
|
System.print("message for %(recipient): %(message)")
|
||||||
}
|
}
|
||||||
</pre>
|
|
||||||
|
|
||||||
Here we're passing a function to `callMe` that takes two parameters, `first` and
|
sayMessage.call("Bob", "Good day!")
|
||||||
`last`. They are passed to the function when it's called:
|
|
||||||
|
|
||||||
<pre class="snippet">
|
|
||||||
class Blondie {
|
|
||||||
callMe(fn) {
|
|
||||||
fn.call("Debbie", "Harry")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
It's an error to call a function with fewer arguments than its parameter list
|
It's an error to call a function with fewer arguments than its parameter list
|
||||||
@ -148,6 +62,14 @@ Fn.new {
|
|||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
The return value is handed back to you when using `call`:
|
||||||
|
|
||||||
|
<pre class="snippet">
|
||||||
|
var fn = Fn.new { "some value" }
|
||||||
|
var result = fn.call()
|
||||||
|
System.print(result) //> some value
|
||||||
|
</pre>
|
||||||
|
|
||||||
## Closures
|
## Closures
|
||||||
|
|
||||||
As you expect, functions are closures—they can access variables defined
|
As you expect, functions are closures—they can access variables defined
|
||||||
@ -175,6 +97,149 @@ System.print(counter.call()) //> 2
|
|||||||
System.print(counter.call()) //> 3
|
System.print(counter.call()) //> 3
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
## Callable classes
|
||||||
|
|
||||||
|
Because `Fn` is a class, and responds to `call()`, any class can respond to
|
||||||
|
`call()` 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.
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
## Block arguments
|
||||||
|
|
||||||
|
Very frequently, functions are passed to methods to be called. There are
|
||||||
|
countless examples of this in Wren, like [list](lists.html) can be filtered
|
||||||
|
using a method `where` which accepts a function:
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
This syntax is a bit less fun to read and write, so Wren implements the
|
||||||
|
_block argument_ concept. When a function is being passed to a method,
|
||||||
|
and is the last argument to the method, it can use a shorter syntax:
|
||||||
|
_just the block part_.
|
||||||
|
|
||||||
|
Let's use a block argument for `list.where`, it's the last (only) argument:
|
||||||
|
|
||||||
|
<pre class="snippet">
|
||||||
|
var list = [1, 2, 3, 4, 5]
|
||||||
|
var filtered = list.where {|value| value > 3 }
|
||||||
|
System.print(filtered.toList) //> [4, 5]
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
We've seen this before in a previous page using `map` and `where`:
|
||||||
|
|
||||||
|
<pre class="snippet">
|
||||||
|
numbers.map {|n| n * 2 }.where {|n| n < 100 }
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
## Block argument example
|
||||||
|
|
||||||
|
Let's look at a complete example, so we can see both ends.
|
||||||
|
|
||||||
|
This may be a bit of a spoiler for [classes](classes.html), so feel free
|
||||||
|
to read that page first and come back.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
Now let's try with the extra button argument:
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
Notice that we still pass the other arguments normally,
|
||||||
|
it's only the last argument that is special.
|
||||||
|
|
||||||
|
**Just a regular function**
|
||||||
|
|
||||||
|
Block arguments are purely syntax sugar for creating a function and passing it
|
||||||
|
in one little blob of syntax. These two are equivalent:
|
||||||
|
|
||||||
|
<pre class="snippet">
|
||||||
|
onClick(Fn.new { System.print("clicked") })
|
||||||
|
onClick { System.print("clicked") }
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
And this is just as valid:
|
||||||
|
|
||||||
|
<pre class="snippet">
|
||||||
|
var onEvent = Fn.new {|button|
|
||||||
|
System.print("clicked by button %(button)")
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick(onEvent)
|
||||||
|
onClick(1, onEvent)
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
**Fn.new**
|
||||||
|
As you may have noticed by now, `Fn` accepts a block argument for the `Fn.new`.
|
||||||
|
All the constructor does is return that argument right back to you!
|
||||||
|
|
||||||
|
|
||||||
<br><hr>
|
<br><hr>
|
||||||
<a class="right" href="classes.html">Classes →</a>
|
<a class="right" href="classes.html">Classes →</a>
|
||||||
<a href="variables.html">← Variables</a>
|
<a href="variables.html">← Variables</a>
|
||||||
|
|||||||
@ -20,23 +20,23 @@ element you want. Like most languages, indexes start at zero:
|
|||||||
[subscript operator]: method-calls.html#subscripts
|
[subscript operator]: method-calls.html#subscripts
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
var hirsute = ["sideburns", "porkchops", "'stache", "goatee"]
|
var trees = ["cedar", "birch", "oak", "willow"]
|
||||||
System.print(hirsute[0]) //> sideburns
|
System.print(trees[0]) //> cedar
|
||||||
System.print(hirsute[1]) //> porkchops
|
System.print(trees[1]) //> birch
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
Negative indices counts backwards from the end:
|
Negative indices counts backwards from the end:
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
System.print(hirsute[-1]) //> goatee
|
System.print(trees[-1]) //> willow
|
||||||
System.print(hirsute[-2]) //> 'stache
|
System.print(trees[-2]) //> oak
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
It's a runtime error to pass an index outside of the bounds of the list. If you
|
It's a runtime error to pass an index outside of the bounds of the list. If you
|
||||||
don't know what those bounds are, you can find out using count:
|
don't know what those bounds are, you can find out using count:
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
System.print(hirsute.count) //> 4
|
System.print(trees.count) //> 4
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## Slices and ranges
|
## Slices and ranges
|
||||||
@ -45,7 +45,7 @@ Sometimes you want to copy a chunk of elements from a list. You can do that by
|
|||||||
passing a [range](values.html#ranges) to the subscript operator, like so:
|
passing a [range](values.html#ranges) to the subscript operator, like so:
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
System.print(hirsute[1..2]) //> [porkchops, 'stache]
|
System.print(trees[1..2]) //> [birch, oak]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
This returns a new list containing the elements of the original list whose
|
This returns a new list containing the elements of the original list whose
|
||||||
@ -56,7 +56,7 @@ Negative bounds also work like they do when passing a single number, so to copy
|
|||||||
a list, you can just do:
|
a list, you can just do:
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
hirsute[0..-1]
|
trees[0..-1]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## Adding elements
|
## Adding elements
|
||||||
@ -65,22 +65,22 @@ Lists are *mutable*, meaning their contents can be changed. You can swap out an
|
|||||||
existing element in the list using the subscript setter:
|
existing element in the list using the subscript setter:
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
hirsute[1] = "muttonchops"
|
trees[1] = "spruce"
|
||||||
System.print(hirsute[1]) //> muttonchops
|
System.print(trees[1]) //> spruce
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
It's an error to set an element that's out of bounds. To grow a list, you can
|
It's an error to set an element that's out of bounds. To grow a list, you can
|
||||||
use `add` to append a single item to the end:
|
use `add` to append a single item to the end:
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
hirsute.add("goatee")
|
trees.add("maple")
|
||||||
System.print(hirsute.count) //> 5
|
System.print(trees.count) //> 5
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
You can insert a new element at a specific position using `insert`:
|
You can insert a new element at a specific position using `insert`:
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
hirsute.insert(2, "soul patch")
|
trees.insert(2, "hickory")
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
The first argument is the index to insert at, and the second is the value to
|
The first argument is the index to insert at, and the second is the value to
|
||||||
@ -143,8 +143,8 @@ System.print(letters.remove("not found")) //> null
|
|||||||
If you want to remove everything from the list, you can clear it:
|
If you want to remove everything from the list, you can clear it:
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
hirsute.clear()
|
trees.clear()
|
||||||
System.print(hirsute) //> []
|
System.print(trees) //> []
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<br><hr>
|
<br><hr>
|
||||||
|
|||||||
@ -9,22 +9,26 @@ curly braces. Each entry is a key and a value separated by a colon:
|
|||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
{
|
{
|
||||||
"George": "Harrison",
|
"maple": "Sugar Maple (Acer Saccharum)",
|
||||||
"John": "Lennon",
|
"larch": "Alpine Larch (Larix Lyallii)",
|
||||||
"Paul": "McCartney",
|
"oak": "Red Oak (Quercus Rubra)",
|
||||||
"Ringo": "Starr"
|
"fir": "Fraser Fir (Abies Fraseri)"
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
This creates a map that associates the first name of each Beatle with his last
|
This creates a map that associates a type of tree (key) to a specific
|
||||||
name. Syntactically, in a map literal, keys can be any literal, a variable
|
tree within that family (value). Syntactically, in a map literal, keys
|
||||||
name, or a parenthesized expression. Values can be any expression. Here, we're
|
can be any literal, a variable name, or a parenthesized expression.
|
||||||
using string literals for both keys and values.
|
Values can be any expression. Here, we're using string literals for both keys
|
||||||
|
and values.
|
||||||
|
|
||||||
*Semantically*, values can be any object, and multiple keys may map to the same
|
*Semantically*, values can be any object, and multiple keys may map to the same
|
||||||
value. Keys have a few limitations. They must be one of the immutable built-in
|
value.
|
||||||
|
|
||||||
|
Keys have a few limitations. They must be one of the immutable built-in
|
||||||
[value types][] in Wren. That means a number, string, range, bool, or `null`.
|
[value types][] in Wren. That means a number, string, range, bool, or `null`.
|
||||||
You can also use a [class object][] as a key.
|
You can also use a [class object][] as a key (not an instance of that class,
|
||||||
|
the actual class itself).
|
||||||
|
|
||||||
[value types]: values.html
|
[value types]: values.html
|
||||||
[class object]: classes.html
|
[class object]: classes.html
|
||||||
@ -67,12 +71,12 @@ doesn't necessarily mean the key wasn't found.
|
|||||||
To tell definitively if a key exists, you can call `containsKey()`:
|
To tell definitively if a key exists, you can call `containsKey()`:
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
var belief = {"nihilism": null}
|
var capitals = {"Georgia": null}
|
||||||
|
|
||||||
System.print(belief["nihilism"]) //> null (though key exists)
|
System.print(capitals["Georgia"]) //> null (though key exists)
|
||||||
System.print(belief["solipsism"]) //> null
|
System.print(capitals["Idaho"]) //> null
|
||||||
System.print(belief.containsKey("nihilism")) //> true
|
System.print(capitals.containsKey("Georgia")) //> true
|
||||||
System.print(belief.containsKey("solipsism")) //> false
|
System.print(capitals.containsKey("Idaho")) //> false
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
You can see how many entries a map contains using `count`:
|
You can see how many entries a map contains using `count`:
|
||||||
@ -113,16 +117,38 @@ System.print(capitals.count) //> 0
|
|||||||
|
|
||||||
The subscript operator works well for finding values when you know the key
|
The subscript operator works well for finding values when you know the key
|
||||||
you're looking for, but sometimes you want to see everything that's in the map.
|
you're looking for, but sometimes you want to see everything that's in the map.
|
||||||
For that, map exposes two methods: `keys` and `values`.
|
You can use a regular for loop to iterate the contents, and map exposes two
|
||||||
|
additional methods to access the contents: `keys` and `values`.
|
||||||
|
|
||||||
The first returns a [Sequence][] that [iterates][] over all of the keys in the
|
The `keys` method on a map returns a [Sequence][] that [iterates][] over all of
|
||||||
map, and the second returns one that iterates over the values.
|
the keys in the map, and the `values` method returns one that iterates over the values.
|
||||||
|
|
||||||
[sequence]: modules/core/sequence.html
|
[sequence]: modules/core/sequence.html
|
||||||
[iterates]: control-flow.html#the-iterator-protocol
|
[iterates]: control-flow.html#the-iterator-protocol
|
||||||
|
|
||||||
If you want to see all of the key-value pairs in a map, the easiest way is to
|
Regardless of how you iterate, the *order* that things are iterated in
|
||||||
iterate over the keys and use each to look up its value:
|
isn't defined. Wren makes no promises about what order keys and values are
|
||||||
|
iterated. All it promises is that every entry will appear exactly once.
|
||||||
|
|
||||||
|
**Iterating with for(entry in map)**
|
||||||
|
When you iterate a map with `for`, you'll be handed an _entry_, which contains
|
||||||
|
a `key` and a `value` field. That gives you the info for each element in the map.
|
||||||
|
|
||||||
|
<pre class="snippet">
|
||||||
|
var birds = {
|
||||||
|
"Arizona": "Cactus wren",
|
||||||
|
"Hawaii": "Nēnē",
|
||||||
|
"Ohio": "Northern Cardinal"
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bird in birds) {
|
||||||
|
System.print("The state bird of %(bird.key) is %(bird.value)")
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
**Iterating using the keys**
|
||||||
|
|
||||||
|
You can also iterate over the keys and use each to look up its value:
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
var birds = {
|
var birds = {
|
||||||
@ -132,15 +158,10 @@ var birds = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (state in birds.keys) {
|
for (state in birds.keys) {
|
||||||
System.print("The state bird of " + state + " is " + birds[state])
|
System.print("The state bird of %(state) is " + birds[state])
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
This program prints the three states and their birds. However, the *order*
|
|
||||||
that they are printed isn't defined. Wren makes no promises about what order
|
|
||||||
keys and values are iterated in when you use these methods. All it promises is
|
|
||||||
that every entry will appear exactly once.
|
|
||||||
|
|
||||||
<br><hr>
|
<br><hr>
|
||||||
<a class="right" href="method-calls.html">Method Calls →</a>
|
<a class="right" href="method-calls.html">Method Calls →</a>
|
||||||
<a href="lists.html">← Lists</a>
|
<a href="lists.html">← Lists</a>
|
||||||
|
|||||||
@ -52,7 +52,9 @@ In a language like Python or JavaScript, these would both call a single `int()`
|
|||||||
method, which has some kind of "optional" parameter. The body of the method
|
method, which has some kind of "optional" parameter. The body of the method
|
||||||
figures out how many arguments were passed and uses control flow to handle the
|
figures out how many arguments were passed and uses control flow to handle the
|
||||||
two different behaviors. That means first parameter represents "max unless
|
two different behaviors. That means first parameter represents "max unless
|
||||||
another parameter was passed, in which case it's min". Kind of gross.
|
another parameter was passed, in which case it's min".
|
||||||
|
|
||||||
|
This type of 'variadic' code isn't ideal, so Wren doesn't encourage it.
|
||||||
|
|
||||||
In Wren, these are calls to two entirely separate methods, `int(_,_)` and
|
In Wren, these are calls to two entirely separate methods, `int(_,_)` and
|
||||||
`int(_)`. This makes it easier to define "overloads" like this since you don't
|
`int(_)`. This makes it easier to define "overloads" like this since you don't
|
||||||
@ -163,7 +165,7 @@ like mocks or proxies where you want an object to masquerade as a certain class.
|
|||||||
|
|
||||||
## Subscripts
|
## Subscripts
|
||||||
|
|
||||||
Another familiar syntax from math class is *subscripting* using square brackets
|
Another familiar syntax from math is *subscripting* using square brackets
|
||||||
(`[]`). It's handy for working with collection-like objects. For example:
|
(`[]`). It's handy for working with collection-like objects. For example:
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
|
|||||||
@ -149,7 +149,7 @@ put a newline in there:
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
Using an initial newline after the `{` does feel a little weird or magical, but
|
Using an initial newline after the `{` does feel a little weird or magical, but
|
||||||
newlines are already significant in Wren, so it's not totally crazy. The nice
|
newlines are already significant in Wren, so it's not totally unreasonable. The nice
|
||||||
thing about this syntax as opposed to something like `=>` is that the *end* of
|
thing about this syntax as opposed to something like `=>` is that the *end* of
|
||||||
the block has an explicit delimiter. That helps when chaining:
|
the block has an explicit delimiter. That helps when chaining:
|
||||||
|
|
||||||
|
|||||||
@ -199,12 +199,16 @@ This creates a range from four to six *not* including six itself. Ranges are
|
|||||||
commonly used for [iterating](control-flow.html#for-statements) over a
|
commonly used for [iterating](control-flow.html#for-statements) over a
|
||||||
sequences of numbers, but are useful in other places too. You can pass them to
|
sequences of numbers, but are useful in other places too. You can pass them to
|
||||||
a [list](lists.html)'s subscript operator to return a subset of the list, for
|
a [list](lists.html)'s subscript operator to return a subset of the list, for
|
||||||
example:
|
example, or on a String, the substring in that range:
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
var list = ["a", "b", "c", "d", "e"]
|
var list = ["a", "b", "c", "d", "e"]
|
||||||
var slice = list[1..3]
|
var slice = list[1..3]
|
||||||
System.print(slice) //> [b, c, d]
|
System.print(slice) //> [b, c, d]
|
||||||
|
|
||||||
|
var string = "hello wren"
|
||||||
|
var wren = string[-4..-1]
|
||||||
|
System.print(wren) //> wren
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
Their class is [Range][].
|
Their class is [Range][].
|
||||||
|
|||||||
@ -54,7 +54,7 @@ var a = "again" //! "a" is already declared.
|
|||||||
|
|
||||||
## Assignment
|
## Assignment
|
||||||
|
|
||||||
After a variable has been declared, you can assign to it using `=`:
|
After a variable has been declared, you can assign to it using `=`
|
||||||
|
|
||||||
<pre class="snippet">
|
<pre class="snippet">
|
||||||
var a = 123
|
var a = 123
|
||||||
|
|||||||
Reference in New Issue
Block a user