mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-11 22:28:45 +01:00
Edit docs. Docs docs docs.
This commit is contained in:
@ -39,7 +39,7 @@ their names inside the parentheses:
|
||||
:::wren
|
||||
class Unicorn {
|
||||
prance(where, when) {
|
||||
System.print("The unicorn prances in " + where + " at " + when)
|
||||
System.print("The unicorn prances in %(where) at %(when).")
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,11 +55,11 @@ define multiple methods with the same name:
|
||||
}
|
||||
|
||||
prance(where) {
|
||||
System.print("The unicorn prances in " + where)
|
||||
System.print("The unicorn prances in %(where).")
|
||||
}
|
||||
|
||||
prance(where, when) {
|
||||
System.print("The unicorn prances in " + where + " at " + when)
|
||||
System.print("The unicorn prances in %(where) at %(when).")
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,7 +77,8 @@ A getter leaves off the parameter list and the parentheses:
|
||||
|
||||
:::wren
|
||||
class Unicorn {
|
||||
isFancy { true } // Unicorns are always fancy.
|
||||
// Unicorns are always fancy.
|
||||
isFancy { true }
|
||||
}
|
||||
|
||||
### Setters
|
||||
@ -87,7 +88,7 @@ A setter has `=` after the name, followed by a single parenthesized parameter:
|
||||
:::wren
|
||||
class Unicorn {
|
||||
rider=(value) {
|
||||
System.print("I am being ridden by " + value)
|
||||
System.print("I am being ridden by %(value).")
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +102,7 @@ Prefix operators, like getters, have no parameter list:
|
||||
:::wren
|
||||
class Unicorn {
|
||||
- {
|
||||
System.print("Negating a unicorn is weird")
|
||||
System.print("Negating a unicorn is weird.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +112,7 @@ right-hand operand:
|
||||
:::wren
|
||||
class Unicorn {
|
||||
-(other) {
|
||||
System.print("Subtracting " + other + " from a unicorn is weird")
|
||||
System.print("Subtracting %(other) from a unicorn is weird.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +139,7 @@ operator and a setter:
|
||||
:::wren
|
||||
class Unicorn {
|
||||
[index]=(value) {
|
||||
System.print("You can't stuff " + value + " into me at " + index)
|
||||
System.print("You can't stuff %(value) into me at %(index)!")
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,8 +182,20 @@ always refers to the instance whose method is currently being executed. This
|
||||
lets you invoke methods on "yourself".
|
||||
|
||||
It's an error to refer to `this` outside of a method. However, it's perfectly
|
||||
fine to use it inside a [function][] contained in a method. When you do, `this`
|
||||
still refers to the instance whose *method* is being called.
|
||||
fine to use it inside a [function][] declared *inside* a method. When you do,
|
||||
`this` still refers to the instance whose *method* is being called:
|
||||
|
||||
:::wren
|
||||
class Unicorn {
|
||||
name { "Francis" }
|
||||
|
||||
printNameThrice() {
|
||||
(1..3).each {
|
||||
// Use "this" inside the function passed to each().
|
||||
System.print(this.name) //> Francis
|
||||
} //> Francis
|
||||
} //> Francis
|
||||
}
|
||||
|
||||
[function]: functions.html
|
||||
|
||||
@ -435,14 +448,14 @@ A class can inherit from a "parent" or *superclass*. When you invoke a method
|
||||
on an object of some class, if it can't be found, it walks up the chain of
|
||||
superclasses looking for it there.
|
||||
|
||||
By default, any new class inherits from `Object`, which is the superclass from
|
||||
By default, any new class inherits from Object, which is the superclass from
|
||||
which all other classes ultimately descend. You can specify a different parent
|
||||
class using `is` when you declare the class:
|
||||
|
||||
:::wren
|
||||
class Pegasus is Unicorn {}
|
||||
|
||||
This declares a new class `Pegasus` that inherits from `Unicorn`.
|
||||
This declares a new class Pegasus that inherits from Unicorn.
|
||||
|
||||
Note that you should not create classes that inherit from the built-in types
|
||||
(Bool, Num, String, Range, List). The built-in types expect their internal bit
|
||||
@ -450,9 +463,9 @@ representation to be very specific and get horribly confused when you invoke one
|
||||
of the inherited built-in methods on the derived type.
|
||||
|
||||
The metaclass hierarchy does *not* parallel the regular class hierarchy. So, if
|
||||
`Pegasus` inherits from `Unicorn`, `Pegasus`'s metaclass will not inherit from
|
||||
`Unicorn`'s metaclass. In more prosaic terms, this means that static methods
|
||||
are not inherited.
|
||||
Pegasus inherits from Unicorn, Pegasus's metaclass does not inherit from
|
||||
Unicorn's metaclass. In more prosaic terms, this means that static methods are
|
||||
not inherited.
|
||||
|
||||
:::wren
|
||||
class Unicorn {
|
||||
|
||||
@ -23,7 +23,7 @@ fiber for every line of code you type in.
|
||||
|
||||
All Wren code runs within the context of a fiber. When you first start a Wren
|
||||
script, a main fiber is created for you automatically. You can spawn new fibers
|
||||
using the `Fiber` class's constructor:
|
||||
using the Fiber class's constructor:
|
||||
|
||||
:::wren
|
||||
var fiber = Fiber.new {
|
||||
@ -36,20 +36,20 @@ a [function](functions.html).
|
||||
|
||||
## Invoking fibers
|
||||
|
||||
Once you've created a fiber, you can invoke it (which suspends the current
|
||||
fiber) by calling its `call()` method:
|
||||
Once you've created a fiber, you can invoke it, which suspends the current
|
||||
fiber, by calling its `call()` method:
|
||||
|
||||
:::wren
|
||||
fiber.call()
|
||||
|
||||
The called fiber will execute its code until it reaches the end of its body or
|
||||
until it passes control to another fiber. If it reaches the end of its body,
|
||||
it's considered *done*:
|
||||
The called fiber executes until it reaches the end of its body or until it
|
||||
passes control to another fiber. If it reaches the end of its body, it's
|
||||
considered *done*:
|
||||
|
||||
:::wren
|
||||
var fiber = Fiber.new { System.print("Hi") }
|
||||
System.print(fiber.isDone) //> false
|
||||
fiber.call()
|
||||
fiber.call() //> "Hi"
|
||||
System.print(fiber.isDone) //> true
|
||||
|
||||
When it finishes, it automatically resumes the fiber that called it. It's a
|
||||
@ -66,34 +66,24 @@ Things get interesting when a fiber *yields*. A yielded fiber passes control
|
||||
*back* to the fiber that ran it, but *remembers where it is*. The next time the
|
||||
fiber is called, it picks up right where it left off and keeps going.
|
||||
|
||||
You can make a fiber yield by calling the static `yield()` method on `Fiber`:
|
||||
You make a fiber yield by calling the static `yield()` method on Fiber:
|
||||
|
||||
:::wren
|
||||
var fiber = Fiber.new {
|
||||
System.print("fiber 1")
|
||||
System.print("before yield")
|
||||
Fiber.yield()
|
||||
System.print("fiber 2")
|
||||
System.print("resumed")
|
||||
}
|
||||
|
||||
System.print("main 1")
|
||||
fiber.call()
|
||||
System.print("main 2")
|
||||
fiber.call()
|
||||
System.print("main 3")
|
||||
System.print("before call") //> before call
|
||||
fiber.call() //> before yield
|
||||
System.print("calling again") //> calling again
|
||||
fiber.call() //> resumed
|
||||
System.print("all done") //> add done
|
||||
|
||||
This program prints:
|
||||
|
||||
:::text
|
||||
main 1
|
||||
fiber 1
|
||||
main 2
|
||||
fiber 2
|
||||
main 3
|
||||
|
||||
Note that even though this program has *concurrency*, it's
|
||||
still *deterministic*. You can reason precisely about what it's doing and
|
||||
aren't at the mercy of a thread scheduler playing Russian roulette with your
|
||||
code.
|
||||
Note that even though this program uses *concurrency*, it is still
|
||||
*deterministic*. You can reason precisely about what it's doing and aren't at
|
||||
the mercy of a thread scheduler playing Russian roulette with your code.
|
||||
|
||||
## Passing values
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ cases.
|
||||
|
||||
It's also faster to execute. Since we know how many arguments are passed at
|
||||
compile time, we can compile this to directly call the right method and avoid
|
||||
any "if I got two arguments do this..." logic.
|
||||
any "if I got two arguments do this..." runtime work.
|
||||
|
||||
## Getters
|
||||
|
||||
@ -70,19 +70,6 @@ are *getters* and have no parentheses:
|
||||
1.23.sin //> 0.9424888019317
|
||||
[1, 2, 3].isEmpty //> false
|
||||
|
||||
Sometimes you have a method that doesn't need any parameters, but modifies the
|
||||
object or has some other side effect. For those, it's better to use empty
|
||||
parentheses:
|
||||
|
||||
:::wren
|
||||
list.clear()
|
||||
|
||||
Also, when a method supports multiple arities, it's typical to include the `()`
|
||||
in the zero-argument case to be consistent with the other versions:
|
||||
|
||||
Fiber.yield()
|
||||
Fiber.yield("value")
|
||||
|
||||
A getter is *not* the same as a method with an empty argument list. The `()` is
|
||||
part of the signature, so `count` and `count()` have different signatures.
|
||||
Unlike Ruby's optional parentheses, Wren wants to make sure you call a getter
|
||||
@ -92,21 +79,39 @@ like a getter and a `()` method like a `()` method. These don't work:
|
||||
"string".count()
|
||||
[1, 2, 3].clear
|
||||
|
||||
If you're defining some member that doesn't need any parameters, you need to
|
||||
decide if it should be a getter or a method with an empty `()` parameter list.
|
||||
The general guidelines are:
|
||||
|
||||
* If it modifies the object or has some other side effect, make it a method:
|
||||
|
||||
:::wren
|
||||
list.clear()
|
||||
|
||||
* If the method supports multiple arities, make the zero-parameter case a `()`
|
||||
method to be consistent with the other versions:
|
||||
|
||||
:::wren
|
||||
Fiber.yield()
|
||||
Fiber.yield("value")
|
||||
|
||||
* Otherwise, it can probably be a getter.
|
||||
|
||||
## Setters
|
||||
|
||||
A getter lets an object expose a public "property" that you can *read*.
|
||||
Likewise, a *setter* let you write to a property:
|
||||
Likewise, a *setter* lets you write to a property:
|
||||
|
||||
:::wren
|
||||
person.height = 74 // Grew up!
|
||||
|
||||
Despite the `=`, this is just another syntax for a method call. From the
|
||||
language's perspective, the above line is just a call to the `height=(_)`
|
||||
method, passing in `74`.
|
||||
method on `person`, passing in `74`.
|
||||
|
||||
Since the `=(_)` is in the setter's signature, an object can have both a getter
|
||||
and setter with the same name without a collision. This way, you can have
|
||||
read/write properties.
|
||||
and setter with the same name without a collision. Defining both lets you
|
||||
provide a read/write property.
|
||||
|
||||
## Operators
|
||||
|
||||
|
||||
@ -107,17 +107,17 @@ Blocks of this form when used for method and function bodies automatically
|
||||
return `null` after the block has completed. If you want to return a different
|
||||
value, you need an explicit `return` statement.
|
||||
|
||||
However, it's pretty common to have a method or function that just evaluates
|
||||
and returns the result of a single expression. For that, Wren has a more
|
||||
compact notation:
|
||||
However, it's pretty common to have a method or function that just evaluates and
|
||||
returns the result of a single expression. Some other languages use `=>` to
|
||||
define these. Wren uses:
|
||||
|
||||
:::wren
|
||||
{ "single expression" }
|
||||
|
||||
If there is no newline after the `{` (or after the parameter list in a
|
||||
[function](functions.html)), then the block may only contain a single
|
||||
expression, and it automatically returns the result of it. It's exactly the
|
||||
same as doing:
|
||||
expression, and it automatically returns the result of it. It's exactly the same
|
||||
as doing:
|
||||
|
||||
:::wren
|
||||
{
|
||||
@ -136,6 +136,14 @@ put a newline in there:
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
thing about this syntax as opposed to something like `=>` is that the *end* of
|
||||
the block has an explicit delimiter. That helps when chaining:
|
||||
|
||||
:::wren
|
||||
numbers.map {|n| n * 2 }.where {|n| n < 100 }
|
||||
|
||||
## Precedence and Associativity
|
||||
|
||||
We'll talk about Wren's different expression forms and what they mean in the
|
||||
|
||||
Reference in New Issue
Block a user