diff --git a/doc/site/classes.markdown b/doc/site/classes.markdown index bca2e39a..e436d3e6 100644 --- a/doc/site/classes.markdown +++ b/doc/site/classes.markdown @@ -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 { diff --git a/doc/site/concurrency.markdown b/doc/site/concurrency.markdown index 7a396a3d..9795cdad 100644 --- a/doc/site/concurrency.markdown +++ b/doc/site/concurrency.markdown @@ -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 diff --git a/doc/site/method-calls.markdown b/doc/site/method-calls.markdown index dbda3c9d..06ea79e7 100644 --- a/doc/site/method-calls.markdown +++ b/doc/site/method-calls.markdown @@ -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 diff --git a/doc/site/syntax.markdown b/doc/site/syntax.markdown index 80bbe28d..940743cc 100644 --- a/doc/site/syntax.markdown +++ b/doc/site/syntax.markdown @@ -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