forked from Mirror/wren
Style example output and errors in the docs.
This commit is contained in:
@ -83,7 +83,7 @@ Many methods on a class exist to expose or compute some property of the object.
|
||||
For example:
|
||||
|
||||
:::wren
|
||||
System.print("string".count) // "6".
|
||||
System.print("string".count) //> 6
|
||||
|
||||
These *getters* are just another kind of method—one without a parameter
|
||||
list. You can define them like so:
|
||||
@ -326,13 +326,13 @@ not the instance. They can be used in *both* instance and static methods.
|
||||
Just like instance fields, static fields are initially `null`:
|
||||
|
||||
:::wren
|
||||
System.print(Foo.bar) // null.
|
||||
System.print(Foo.bar) //> null
|
||||
|
||||
They can be used from static methods:
|
||||
|
||||
:::wren
|
||||
Foo.set("foo")
|
||||
System.print(Foo.bar) // foo.
|
||||
System.print(Foo.bar) //> foo
|
||||
|
||||
And also instance methods. When you do so, there is still only one static field
|
||||
shared among all instances of the class:
|
||||
@ -342,7 +342,7 @@ shared among all instances of the class:
|
||||
var foo2 = Foo.new()
|
||||
|
||||
foo1.setFromInstance("updated")
|
||||
System.print(foo2.baz) // updated.
|
||||
System.print(foo2.baz) //> updated
|
||||
|
||||
## Inheritance
|
||||
|
||||
@ -374,20 +374,20 @@ are not inherited.
|
||||
|
||||
class Pegasus is Unicorn {}
|
||||
|
||||
Pegasus.canFly // ERROR: Static methods are not inherited.
|
||||
Pegasus.canFly //! Static methods are not inherited.
|
||||
|
||||
This also means constructors are not inherited:
|
||||
|
||||
:::wren
|
||||
class Unicorn {
|
||||
this new(name) {
|
||||
construct new(name) {
|
||||
System.print("My name is " + name + ".")
|
||||
}
|
||||
}
|
||||
|
||||
class Pegasus is Unicorn {}
|
||||
|
||||
Pegasus.new("Fred") // Error!
|
||||
Pegasus.new("Fred") //! Pegasus does not define new().
|
||||
|
||||
Each class gets to control how it may be constructed independently of its base
|
||||
classes. However, constructor *initializers* are inherited since those are
|
||||
@ -397,15 +397,15 @@ This means you can do `super` calls inside a constructor:
|
||||
|
||||
:::wren
|
||||
class Unicorn {
|
||||
this new(name) {
|
||||
construct new(name) {
|
||||
System.print("My name is " + name + ".")
|
||||
}
|
||||
}
|
||||
|
||||
class Pegasus is Unicorn {
|
||||
this new(name) {
|
||||
construct new(name) {
|
||||
super(name)
|
||||
}
|
||||
}
|
||||
|
||||
Pegasus.new("Fred") // Prints "My name is Fred.".
|
||||
Pegasus.new("Fred") //> My name is Fred
|
||||
|
||||
@ -10,8 +10,8 @@ Boolean values. There are two instances, `true` and `false`.
|
||||
Returns the logical complement of the value.
|
||||
|
||||
:::wren
|
||||
System.print(!true) // "false".
|
||||
System.print(!false) // "true".
|
||||
System.print(!true) //> false
|
||||
System.print(!false) //> true
|
||||
|
||||
### toString
|
||||
|
||||
|
||||
@ -15,14 +15,14 @@ The superclass of this class.
|
||||
class Crustacean {}
|
||||
class Crab is Crustacean {}
|
||||
|
||||
System.print(Crab.supertype) // "Crustacean".
|
||||
System.print(Crab.supertype) //> Crustacean
|
||||
|
||||
A class with no explicit superclass implicitly inherits Object:
|
||||
|
||||
:::wren
|
||||
System.print(Crustacean.supertype) // "Object".
|
||||
System.print(Crustacean.supertype) //> Object
|
||||
|
||||
Object forms the root of the class hierarchy and has no supertype:
|
||||
|
||||
:::wren
|
||||
System.print(Object.supertype) // "null".
|
||||
System.print(Object.supertype) //> null
|
||||
|
||||
@ -39,9 +39,9 @@ here means the last fiber that was started using `call` and not `run`.
|
||||
System.print("After yield")
|
||||
}
|
||||
|
||||
fiber.call() // "Before yield"
|
||||
System.print("After call") // "After call"
|
||||
fiber.call() // "After yield"
|
||||
fiber.call() //> Before yield
|
||||
System.print("After call") //> After call
|
||||
fiber.call() //> After yield
|
||||
|
||||
When resumed, the parent fiber's `call()` method returns `null`.
|
||||
|
||||
@ -50,7 +50,7 @@ If a yielded fiber is resumed by calling `call()` or `run()` with an argument,
|
||||
|
||||
:::wren
|
||||
var fiber = Fiber.new {
|
||||
System.print(Fiber.yield()) // "value"
|
||||
System.print(Fiber.yield()) //> value
|
||||
}
|
||||
|
||||
fiber.call() // Run until the first yield.
|
||||
@ -77,7 +77,7 @@ Similar to `Fiber.yield` but provides a value to return to the parent fiber's
|
||||
Fiber.yield("value")
|
||||
}
|
||||
|
||||
System.print(fiber.call()) // "value"
|
||||
System.print(fiber.call()) //> value
|
||||
|
||||
## Methods
|
||||
|
||||
@ -107,7 +107,7 @@ If the called fiber is resuming from a yield, the `yield()` method returns
|
||||
}
|
||||
|
||||
fiber.call()
|
||||
fiber.call() // Prints "null".
|
||||
fiber.call() //> null
|
||||
|
||||
### **call**(value)
|
||||
|
||||
@ -120,7 +120,7 @@ Invokes the fiber or resumes the fiber if it is in a paused state and sets
|
||||
}
|
||||
|
||||
fiber.call()
|
||||
fiber.call("value") // Prints "value".
|
||||
fiber.call("value") //> value
|
||||
|
||||
### **isDone**
|
||||
|
||||
|
||||
@ -25,8 +25,8 @@ It is a runtime error if `function` is not a function.
|
||||
The number of arguments the function requires.
|
||||
|
||||
:::wren
|
||||
System.print(Fn.new {}.arity) // 0.
|
||||
System.print(Fn.new {|a, b, c| a }.arity) // 3.
|
||||
System.print(Fn.new {}.arity) //> 0
|
||||
System.print(Fn.new {|a, b, c| a }.arity) //> 3
|
||||
|
||||
### **call**(args...)
|
||||
|
||||
@ -34,10 +34,10 @@ Invokes the function with the given arguments.
|
||||
|
||||
:::wren
|
||||
var fn = Fn.new { |arg|
|
||||
System.print(arg)
|
||||
System.print(arg) //> Hello world
|
||||
}
|
||||
|
||||
fn.call("Hello world") // Prints "Hello world".
|
||||
fn.call("Hello world")
|
||||
|
||||
It is a runtime error if the number of arguments given is less than the arity
|
||||
of the function. If more arguments are given than the function's arity they are
|
||||
|
||||
@ -26,14 +26,14 @@ Inserts the `item` at `index` in the list.
|
||||
:::wren
|
||||
var list = ["a", "b", "c", "d"]
|
||||
list.insert(1, "e")
|
||||
System.print(list) // "[a, e, b, c, d]".
|
||||
System.print(list) //> [a, e, b, c, d]
|
||||
|
||||
The `index` may be one past the last index in the list to append an element.
|
||||
|
||||
:::wren
|
||||
var list = ["a", "b", "c"]
|
||||
list.insert(3, "d")
|
||||
System.print(list) // "[a, b, c, d]".
|
||||
System.print(list) //> [a, b, c, d]
|
||||
|
||||
If `index` is negative, it counts backwards from the end of the list. It bases this on the length of the list *after* inserted the element, so that `-1` will append the element, not insert it before the last element.
|
||||
|
||||
@ -41,12 +41,12 @@ If `index` is negative, it counts backwards from the end of the list. It bases t
|
||||
var list = ["a", "b"]
|
||||
list.insert(-1, "d")
|
||||
list.insert(-2, "c")
|
||||
System.print(list) // "[a, b, c, d]".
|
||||
System.print(list) //> [a, b, c, d]
|
||||
|
||||
Returns the inserted item.
|
||||
|
||||
:::wren
|
||||
System.print(["a", "c"].insert(1, "b")) // "b".
|
||||
System.print(["a", "c"].insert(1, "b")) //> b
|
||||
|
||||
It is a runtime error if the index is not an integer or is out of bounds.
|
||||
|
||||
@ -64,11 +64,11 @@ are shifted up to fill in where the removed element was.
|
||||
:::wren
|
||||
var list = ["a", "b", "c", "d"]
|
||||
list.removeAt(1)
|
||||
System.print(list) // "[a, c, d]".
|
||||
System.print(list) //> [a, c, d]
|
||||
|
||||
Returns the removed item.
|
||||
|
||||
System.print(["a", "b", "c"].removeAt(1)) // "b".
|
||||
System.print(["a", "b", "c"].removeAt(1)) //> b
|
||||
|
||||
It is a runtime error if the index is not an integer or is out of bounds.
|
||||
|
||||
@ -79,7 +79,7 @@ the end of the list where `-1` is the last element.
|
||||
|
||||
:::wren
|
||||
var list = ["a", "b", "c"]
|
||||
System.print(list[1]) // "b".
|
||||
System.print(list[1]) //> b
|
||||
|
||||
It is a runtime error if the index is not an integer or is out of bounds.
|
||||
|
||||
@ -91,6 +91,6 @@ backwards from the end of the list where `-1` is the last element.
|
||||
:::wren
|
||||
var list = ["a", "b", "c"]
|
||||
list[1] = "new"
|
||||
System.print(list) // "[a, new, c]".
|
||||
System.print(list) //> [a, new, c]
|
||||
|
||||
It is a runtime error if the index is not an integer or is out of bounds.
|
||||
|
||||
@ -50,8 +50,8 @@ map, returns `null`.
|
||||
|
||||
:::wren
|
||||
var map = {"george": "harrison", "ringo": "starr"}
|
||||
System.print(map["ringo"]) // "starr".
|
||||
System.print(map["pete"]) // "null".
|
||||
System.print(map["ringo"]) //> starr
|
||||
System.print(map["pete"]) //> null
|
||||
|
||||
### **[**key**]=**(value) operator
|
||||
|
||||
|
||||
@ -8,4 +8,4 @@
|
||||
Returns `true`, since `null` is considered [false](../control-flow.html#truth).
|
||||
|
||||
:::wren
|
||||
System.print(!null) // "true".
|
||||
System.print(!null) //> true
|
||||
|
||||
@ -12,7 +12,7 @@ It is a runtime error if `value` is not a string.
|
||||
|
||||
### Num.**pi**
|
||||
|
||||
The value of π.
|
||||
The value of π.
|
||||
|
||||
## Methods
|
||||
|
||||
@ -21,7 +21,7 @@ The value of π.
|
||||
The absolute value of the number.
|
||||
|
||||
:::wren
|
||||
-123.abs // 123
|
||||
System.print(-123.abs) //> 123
|
||||
|
||||
### **acos**
|
||||
|
||||
@ -45,8 +45,8 @@ numbers to determine the quadrant of the result.
|
||||
Rounds the number up to the nearest integer.
|
||||
|
||||
:::wren
|
||||
1.5.ceil // 2
|
||||
(-3.2).ceil // -3
|
||||
System.print(1.5.ceil) //> 2
|
||||
System.print((-3.2).ceil) //> -3
|
||||
|
||||
### **cos**
|
||||
|
||||
@ -57,24 +57,24 @@ The cosine of the number.
|
||||
Rounds the number down to the nearest integer.
|
||||
|
||||
:::wren
|
||||
1.5.floor // 1
|
||||
(-3.2).floor // -4
|
||||
System.print(1.5.floor) //> 1
|
||||
System.print((-3.2).floor) //> -4
|
||||
|
||||
### **isInfinity**
|
||||
|
||||
Whether the number is positive or negative infinity or not.
|
||||
|
||||
:::wren
|
||||
99999.isInfinity // false
|
||||
(1/0).isInfinity // true
|
||||
System.print(99999.isInfinity) //> false
|
||||
System.print((1/0).isInfinity) //> true
|
||||
|
||||
### **isInteger**
|
||||
|
||||
Whether the number is an integer or has some fractional component.
|
||||
|
||||
:::wren
|
||||
2.isInteger // true
|
||||
2.3.isInteger // false
|
||||
System.print(2.isInteger) //> true
|
||||
System.print(2.3.isInteger) //> false
|
||||
|
||||
### **isNan**
|
||||
|
||||
@ -100,7 +100,7 @@ Negates the number.
|
||||
|
||||
:::wren
|
||||
var a = 123
|
||||
-a // -123
|
||||
System.print(-a) //> -123
|
||||
|
||||
### **-**(other), **+**(other), **/**(other), **\***(other) operators
|
||||
|
||||
@ -148,9 +148,9 @@ from the beginning number to the ending number.
|
||||
|
||||
:::wren
|
||||
var range = 1.2..3.4
|
||||
System.print(range.min) // 1.2
|
||||
System.print(range.max) // 3.4
|
||||
System.print(range.isInclusive) // true
|
||||
System.print(range.min) //> 1.2
|
||||
System.print(range.max) //> 3.4
|
||||
System.print(range.isInclusive) //> true
|
||||
|
||||
### **...**(other) operator
|
||||
|
||||
@ -159,6 +159,6 @@ from the beginning number to the ending number not including the ending number.
|
||||
|
||||
:::wren
|
||||
var range = 1.2...3.4
|
||||
System.print(range.min) // 1.2
|
||||
System.print(range.max) // 3.4
|
||||
System.print(range.isInclusive) // false
|
||||
System.print(range.min) //> 1.2
|
||||
System.print(range.max) //> 3.4
|
||||
System.print(range.isInclusive) //> false
|
||||
|
||||
@ -14,8 +14,8 @@ The starting point of the range. A range may be backwards, so this can be
|
||||
greater than [to].
|
||||
|
||||
:::wren
|
||||
(3..5).min // 3.
|
||||
(4..2).min // 4.
|
||||
System.print((3..5).min) //> 3
|
||||
System.print((4..2).min) //> 4
|
||||
|
||||
### **to**
|
||||
|
||||
@ -23,8 +23,8 @@ The endpoint of the range. If the range is inclusive, this value is included,
|
||||
otherwise it is not.
|
||||
|
||||
:::wren
|
||||
(3..5).min // 5.
|
||||
(4..2).min // 2.
|
||||
System.print((3..5).min) //> 5
|
||||
System.print((4..2).min) //> 2
|
||||
|
||||
### **min**
|
||||
|
||||
@ -32,8 +32,8 @@ The minimum bound of the range. Returns either `from`, or `to`, whichever is
|
||||
lower.
|
||||
|
||||
:::wren
|
||||
(3..5).min // 3.
|
||||
(4..2).min // 2.
|
||||
System.print((3..5).min) //> 3
|
||||
System.print((4..2).min) //> 2
|
||||
|
||||
### **max**
|
||||
|
||||
@ -41,16 +41,16 @@ The maximum bound of the range. Returns either `from`, or `to`, whichever is
|
||||
greater.
|
||||
|
||||
:::wren
|
||||
(3..5).min // 5.
|
||||
(4..2).min // 4.
|
||||
System.print((3..5).min) //> 5
|
||||
System.print((4..2).min) //> 4
|
||||
|
||||
### **isInclusive**
|
||||
|
||||
Whether or not the range includes `to`. (`from` is always included.)
|
||||
|
||||
:::wren
|
||||
(3..5).isInclusive // true.
|
||||
(3...5).isInclusive // false.
|
||||
System.print((3..5).isInclusive) //> true
|
||||
System.print((3...5).isInclusive) //> false
|
||||
|
||||
### **iterate**(iterator), **iteratorValue**(iterator)
|
||||
|
||||
|
||||
@ -17,8 +17,8 @@ If it returns something [false](../control-flow.html#truth), stops iterating
|
||||
and returns the value. Otherwise, returns `true`.
|
||||
|
||||
:::wren
|
||||
[1, 2, 3].all {|n| n > 2} // False.
|
||||
[1, 2, 3].all {|n| n < 4} // True.
|
||||
System.print([1, 2, 3].all {|n| n > 2}) //> false
|
||||
System.print([1, 2, 3].all {|n| n < 4}) //> true
|
||||
|
||||
### **any**(predicate)
|
||||
|
||||
@ -29,8 +29,8 @@ If it returns something [true](../control-flow.html#truth), stops iterating and
|
||||
returns that value. Otherwise, returns `false`.
|
||||
|
||||
:::wren
|
||||
[1, 2, 3].any {|n| n < 1} // False.
|
||||
[1, 2, 3].any {|n| n > 2} // True.
|
||||
System.print([1, 2, 3].any {|n| n < 1}) //> false
|
||||
System.print([1, 2, 3].any {|n| n > 2}) //> true
|
||||
|
||||
### **contains**(element)
|
||||
|
||||
@ -51,8 +51,8 @@ Iterates over the sequence, passing each element to the function `predicate`
|
||||
and counting the number of times the returned value evaluates to `true`.
|
||||
|
||||
:::wren
|
||||
[1, 2, 3].count {|n| n > 2} // 1.
|
||||
[1, 2, 3].count {|n| n < 4} // 3.
|
||||
System.print([1, 2, 3].count {|n| n > 2}) //> 1
|
||||
System.print([1, 2, 3].count {|n| n < 4}) //> 3
|
||||
|
||||
### **each**(function)
|
||||
|
||||
@ -88,7 +88,9 @@ original sequence while it is iterated.
|
||||
:::wren
|
||||
var doubles = [1, 2, 3].map {|n| n * 2 }
|
||||
for (n in doubles) {
|
||||
System.print(n) // "2", "4", "6".
|
||||
System.print(n) //> 2
|
||||
//> 4
|
||||
//> 6
|
||||
}
|
||||
|
||||
The returned sequence is *lazy*. It only applies the mapping when you iterate
|
||||
@ -105,7 +107,7 @@ To force eager evaluation, just call `.toList` on the result.
|
||||
var numbers = [1, 2, 3]
|
||||
var doubles = numbers.map {|n| n * 2 }.toList
|
||||
numbers.add(4)
|
||||
System.print(doubles) // [2, 4, 6].
|
||||
System.print(doubles) //> [2, 4, 6]
|
||||
|
||||
### **reduce**(function)
|
||||
|
||||
@ -127,7 +129,7 @@ the sequence is empty, returns `seed`.
|
||||
Creates a [list](list.html) containing all the elements in the sequence.
|
||||
|
||||
:::wren
|
||||
(1..3).toList // [1, 2, 3].
|
||||
System.print((1..3).toList) //> [1, 2, 3]
|
||||
|
||||
If the sequence is already a list, this creates a copy of it.
|
||||
|
||||
@ -140,9 +142,11 @@ During iteration, each element in the original sequence is passed to the
|
||||
function `predicate`. If it returns `false`, the element is skipped.
|
||||
|
||||
:::wren
|
||||
var odds = (1..10).where {|n| n % 2 == 1 }
|
||||
var odds = (1..6).where {|n| n % 2 == 1 }
|
||||
for (n in odds) {
|
||||
System.print(n) // "1", "3", "5", "7", "9".
|
||||
System.print(n) //> 1
|
||||
//> 3
|
||||
//> 5
|
||||
}
|
||||
|
||||
The returned sequence is *lazy*. It only applies the filtering when you iterate
|
||||
@ -160,4 +164,4 @@ To force eager evaluation, just call `.toList` on the result.
|
||||
var numbers = [1, 2, 3, 4, 5, 6]
|
||||
var odds = numbers.where {|n| n % 2 == 1 }.toList
|
||||
numbers.add(7)
|
||||
System.print(odds) // [1, 3, 5].
|
||||
System.print(odds) //> [1, 3, 5]
|
||||
|
||||
@ -37,7 +37,7 @@ on strings *return* byte indexes too. So, for example, this does what you want:
|
||||
:::wren
|
||||
var metalBand = "Fäcëhämmër"
|
||||
var hPosition = metalBand.indexOf("h")
|
||||
System.print(metalBand[hPosition]) // "h"
|
||||
System.print(metalBand[hPosition]) //> h
|
||||
|
||||
If you want to work with a string as a sequence numeric code points, call the
|
||||
`codePoints` getter. It returns a [Sequence](sequence.html) that decodes UTF-8
|
||||
@ -53,7 +53,7 @@ ignores any UTF-8 encoding and works directly at the byte level.
|
||||
Creates a new string containing the UTF-8 encoding of `codePoint`.
|
||||
|
||||
:::wren
|
||||
String.fromCodePoint(8225) // "‡"
|
||||
String.fromCodePoint(8225) //> ‡
|
||||
|
||||
It is a runtime error if `codePoint` is not an integer between `0` and
|
||||
`0x10ffff`, inclusive.
|
||||
@ -68,7 +68,7 @@ methods, the returned object also has a subscript operator that can be used to
|
||||
directly index bytes.
|
||||
|
||||
:::wren
|
||||
System.print("hello".bytes[1]) // 101, for "e".
|
||||
System.print("hello".bytes[1]) //> 101 (for "e")
|
||||
|
||||
The `count` method on the returned sequence returns the number of bytes in the
|
||||
string. Unlike `count` on the string itself, it does not have to iterate over
|
||||
@ -83,15 +83,15 @@ single-character strings, this returns the numeric code point values.
|
||||
|
||||
:::wren
|
||||
var string = "(ᵔᴥᵔ)"
|
||||
System.print(string.codePoints[0]) // 40, for "(".
|
||||
System.print(string.codePoints[4]) // 7461, for "ᴥ".
|
||||
System.print(string.codePoints[0]) //> 40 (for "(")
|
||||
System.print(string.codePoints[4]) //> 7461 (for "ᴥ")
|
||||
|
||||
If the byte at `index` does not begin a valid UTF-8 sequence, or the end of the
|
||||
string is reached before the sequence is complete, returns `-1`.
|
||||
|
||||
:::wren
|
||||
var string = "(ᵔᴥᵔ)"
|
||||
System.print(string.codePoints[2]) // -1, in the middle of "ᵔ".
|
||||
System.print(string.codePoints[2]) //> -1 (in the middle of "ᵔ")
|
||||
|
||||
### **contains**(other)
|
||||
|
||||
@ -132,7 +132,7 @@ for iterating over the *code points* in the string:
|
||||
codePoints.add(c)
|
||||
}
|
||||
|
||||
System.print(codePoints) // ["(", "ᵔ", "ᴥ", "ᵔ", ")"].
|
||||
System.print(codePoints) //> [(, ᵔ, ᴥ, ᵔ, )]
|
||||
|
||||
If the string contains any bytes that are not valid UTF-8, this iterates over
|
||||
those too, one byte at a time.
|
||||
@ -162,7 +162,7 @@ Check if the string is not equal to `other`.
|
||||
Returns a string containing the code point starting at byte `index`.
|
||||
|
||||
:::wren
|
||||
System.print("ʕ•ᴥ•ʔ"[5]) // "ᴥ".
|
||||
System.print("ʕ•ᴥ•ʔ"[5]) //> ᴥ
|
||||
|
||||
Since `ʕ` is two bytes in UTF-8 and `•` is three, the fifth byte points to the
|
||||
bear's nose.
|
||||
@ -171,7 +171,7 @@ If `index` points into the middle of a UTF-8 sequence or at otherwise invalid
|
||||
UTF-8, this returns a one-byte string containing the byte at that index:
|
||||
|
||||
:::wren
|
||||
System.print("I ♥ NY"[3]) // One-byte string whose value is 153.
|
||||
System.print("I ♥ NY"[3]) //> (one-byte string [153])
|
||||
|
||||
It is a runtime error if `index` is greater than the number of bytes in the
|
||||
string.
|
||||
|
||||
@ -16,7 +16,7 @@ Prints [object] to the console followed by a newline. If not already a string,
|
||||
the object is converted to a string by calling `toString` on it.
|
||||
|
||||
:::wren
|
||||
System.print("I like bananas") // Prints "I like bananas".
|
||||
System.print("I like bananas") //> I like bananas
|
||||
|
||||
### System.**printAll**(sequence)
|
||||
|
||||
@ -24,7 +24,7 @@ Iterates over [sequence] and prints each element, then prints a single newline
|
||||
at the end. Each element is converted to a string by calling `toString` on it.
|
||||
|
||||
:::wren
|
||||
System.printAll([1, [2, 3], 4]) // Prints "1[2, 3]4".
|
||||
System.printAll([1, [2, 3], 4]) //> 1[2, 3]4
|
||||
|
||||
### System.**write**(object)
|
||||
|
||||
@ -32,7 +32,7 @@ Prints a single value to the console, but does not print a newline character
|
||||
afterwards. Converts the value to a string by calling `toString` on it.
|
||||
|
||||
:::wren
|
||||
System.write(4 + 5) // Prints "9".
|
||||
System.write(4 + 5) //> 9
|
||||
|
||||
In the above example, the result of `4 + 5` is printed, and then the prompt is
|
||||
printed on the same line because no newline character was printed afterwards.
|
||||
|
||||
@ -11,11 +11,11 @@ simple bugs where your code doesn't follow the language's grammar, like:
|
||||
:::wren
|
||||
1 + * 2
|
||||
|
||||
Wren will detect these errors as soon as it tries to read your code. When it
|
||||
hits one, you'll get a friendly error message, like:
|
||||
Wren detects these errors as soon as it tries to read your code. When it hits
|
||||
one, you get a friendly error message, like:
|
||||
|
||||
:::text
|
||||
[script.wren line 1] Error on '*': Unexpected token for expression.
|
||||
[main line 1] Error on '*': Unexpected token for expression.
|
||||
|
||||
Some slightly more "semantic" errors fall into this bucket too. Things like
|
||||
using a variable that hasn't been defined, or declaring two variables with the
|
||||
@ -28,7 +28,7 @@ same name in the same scope. So if you do:
|
||||
Wren tells you:
|
||||
|
||||
:::text
|
||||
[script.wren line 2] Error on 'a': Top-level variable is already defined.
|
||||
[main line 2] Error on 'a': Top-level variable is already defined.
|
||||
|
||||
Note that it does this before it executes *any* code. Unlike some other
|
||||
scripting languages, Wren tries to help you find your errors as soon as
|
||||
@ -78,7 +78,7 @@ This exits with:
|
||||
|
||||
:::text
|
||||
Subscript must be a number or a range.
|
||||
[script.wren line 2] in (script)
|
||||
[main line 2] in (script)
|
||||
|
||||
These are the most two common kinds of runtime errors, but there are others.
|
||||
Stuff like out of bounds errors on lists, calling a function with the wrong
|
||||
|
||||
@ -97,14 +97,14 @@ call:
|
||||
|
||||
:::wren
|
||||
class Base {
|
||||
method {
|
||||
method() {
|
||||
System.print("base method")
|
||||
}
|
||||
}
|
||||
|
||||
class Derived is Base {
|
||||
method {
|
||||
super.method // Prints "base method".
|
||||
method() {
|
||||
super.method() //> base method
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,19 +113,17 @@ base class constructor:
|
||||
|
||||
:::wren
|
||||
class Base {
|
||||
this new(arg) {
|
||||
System.print("base constructor got " + arg)
|
||||
construct new(arg) {
|
||||
System.print("base got " + arg)
|
||||
}
|
||||
}
|
||||
|
||||
class Derived is Base {
|
||||
this new() {
|
||||
super("value") // Prints "base constructor got value".
|
||||
construct new() {
|
||||
super("value") //> base got value
|
||||
}
|
||||
}
|
||||
|
||||
**TODO: constructors**
|
||||
|
||||
## Operators
|
||||
|
||||
Wren has most of the same operators you know and love with the same precedence
|
||||
@ -213,21 +211,20 @@ value of the left-hand side, the right-hand operand expression may or may not
|
||||
be evaluated. Because of this, they cannot be overloaded and their behavior is
|
||||
fixed.
|
||||
|
||||
A `&&` ("logical and") expression evaluates the left-hand argument. If it's
|
||||
[false](control-flow.html#truth), it returns that value. Otherwise it evaluates
|
||||
and returns the right-hand argument.
|
||||
A `&&` ("logical and") expression evaluates the left-hand argument. If
|
||||
it's [false](control-flow.html#truth), it returns that value. Otherwise it evaluates and returns the right-hand argument.
|
||||
|
||||
:::wren
|
||||
System.print(false && 1) // false
|
||||
System.print(1 && 2) // 2
|
||||
System.print(false && 1) //> false
|
||||
System.print(1 && 2) //> 2
|
||||
|
||||
An `||` ("logical or") expression is reversed. If the left-hand argument is
|
||||
[true](control-flow.html#truth), it's returned, otherwise the right-hand
|
||||
argument is evaluated and returned:
|
||||
|
||||
:::wren
|
||||
System.print(false || 1) // 1
|
||||
System.print(1 || 2) // 1
|
||||
System.print(false || 1) //> 1
|
||||
System.print(1 || 2) //> 1
|
||||
|
||||
## The conditional operator `?:`
|
||||
|
||||
@ -251,11 +248,11 @@ operand is a class. It evaluates to `true` if the object is an instance of the
|
||||
class (or one of its subclasses).
|
||||
|
||||
:::wren
|
||||
123 is Num // true
|
||||
"s" is Num // false
|
||||
null is String // false
|
||||
[] is List // true
|
||||
[] is Sequence // true
|
||||
System.print(123 is Num) //> true
|
||||
System.print("s" is Num) //> false
|
||||
System.print(null is String) //> false
|
||||
System.print([] is List) //> true
|
||||
System.print([] is Sequence) //> true
|
||||
|
||||
## Precedence
|
||||
|
||||
|
||||
@ -32,8 +32,8 @@ using the `Fiber` class's constructor:
|
||||
}
|
||||
|
||||
Creating a fiber does not immediately run it. It's just a first class bundle of
|
||||
code sitting there waiting to be activated, a bit like a
|
||||
[function](functions.html).
|
||||
code sitting there waiting to be activated, a bit like
|
||||
a [function](functions.html).
|
||||
|
||||
## Invoking fibers
|
||||
|
||||
@ -49,9 +49,9 @@ it's considered *done*:
|
||||
|
||||
:::wren
|
||||
var fiber = Fiber.new { System.print("Hi") }
|
||||
fiber.isDone // false
|
||||
System.print(fiber.isDone) //> false
|
||||
fiber.call()
|
||||
fiber.isDone // true
|
||||
System.print(fiber.isDone) //> true
|
||||
|
||||
When it finishes, it automatically resumes the fiber that called it. It's a
|
||||
runtime error to try to call a fiber that is already done.
|
||||
@ -91,9 +91,10 @@ This program prints:
|
||||
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 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.
|
||||
|
||||
## Passing values
|
||||
|
||||
@ -116,7 +117,7 @@ ignored. That's because the fiber isn't waiting on a `yield()` call, so there's
|
||||
nowhere for the sent value to go.
|
||||
|
||||
Fibers can also pass values *back* when they yield. If you pass an argument to
|
||||
`yield()`, that will become the return value of the `call` that was used to
|
||||
`yield()`, that will become the return value of the `call()` that was used to
|
||||
invoke the fiber:
|
||||
|
||||
:::wren
|
||||
@ -135,8 +136,8 @@ Python and C# that have *generators*. Those let you define a function call that
|
||||
you can suspend and resume. When using the function, it appears like a sequence
|
||||
you can iterate over.
|
||||
|
||||
Wren's fibers can do that, but they can do much more. Like Lua, they are full
|
||||
*coroutines*—they can suspend from anywhere in the callstack. For
|
||||
Wren's fibers can do that, but they can do much more. Like Lua, they are
|
||||
full *coroutines*—they can suspend from anywhere in the callstack. For
|
||||
example:
|
||||
|
||||
:::wren
|
||||
|
||||
@ -26,8 +26,9 @@ a method. At its simplest, it looks like this:
|
||||
}
|
||||
|
||||
Here we're invoking the `callMe` method on `blondie`. We're passing one
|
||||
argument, a function whose body is the following
|
||||
[block](syntax.html#blocks)—everything between that pair of curly braces.
|
||||
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:
|
||||
@ -144,7 +145,7 @@ leaving the scope where the function is defined:
|
||||
|
||||
:::wren
|
||||
class Counter {
|
||||
static create {
|
||||
static create() {
|
||||
var i = 0
|
||||
return Fn.new { i = i + 1 }
|
||||
}
|
||||
@ -156,7 +157,7 @@ the function is returned from `create`, it is still able to read and assign
|
||||
to`i`:
|
||||
|
||||
:::wren
|
||||
var counter = Counter.create
|
||||
System.print(counter.call()) // Prints "1".
|
||||
System.print(counter.call()) // Prints "2".
|
||||
System.print(counter.call()) // Prints "3".
|
||||
var counter = Counter.create()
|
||||
System.print(counter.call()) //> 1
|
||||
System.print(counter.call()) //> 2
|
||||
System.print(counter.call()) //> 3
|
||||
|
||||
@ -19,20 +19,20 @@ element you want. Like most languages, indexes start at zero:
|
||||
|
||||
:::wren
|
||||
var hirsute = ["sideburns", "porkchops", "'stache", "goatee"]
|
||||
hirsute[0] // "sideburns".
|
||||
hirsute[1] // "porkchops".
|
||||
hirsute[0] //> sideburns
|
||||
hirsute[1] //> porkchops
|
||||
|
||||
Negative indices counts backwards from the end:
|
||||
|
||||
:::wren
|
||||
hirsute[-1] // "goatee".
|
||||
hirsute[-2] // "'stache".
|
||||
hirsute[-1] //> goatee
|
||||
hirsute[-2] //> 'stache
|
||||
|
||||
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:
|
||||
|
||||
:::wren
|
||||
hirsute.count // 4.
|
||||
hirsute.count //> 4
|
||||
|
||||
## Slices and ranges
|
||||
|
||||
@ -40,7 +40,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:
|
||||
|
||||
:::wren
|
||||
hirsute[1..2] // ["porkchops", "'stache"].
|
||||
hirsute[1..2] //> [porkchops, 'stache]
|
||||
|
||||
This returns a new list containing the elements of the original list whose
|
||||
indices are within the given range. Both inclusive and exclusive ranges work
|
||||
@ -59,14 +59,14 @@ existing element in the list using the subscript setter:
|
||||
|
||||
:::wren
|
||||
hirsute[1] = "muttonchops"
|
||||
System.print(hirsute[1]) // muttonchops.
|
||||
System.print(hirsute[1]) //> muttonchops
|
||||
|
||||
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:
|
||||
|
||||
:::wren
|
||||
hirsute.add("goatee")
|
||||
System.print(hirsute.count) // 4.
|
||||
System.print(hirsute.count) //> 4
|
||||
|
||||
You can insert a new element at a specific position using `insert`:
|
||||
|
||||
@ -84,9 +84,9 @@ back. Doing so counts back from the size of the list *after* it's grown by one:
|
||||
:::wren
|
||||
var letters = ["a", "b", "c"]
|
||||
letters.insert(3, "d") // OK: inserts at end.
|
||||
System.print(letters) // ["a", "b", "c", "d"]
|
||||
System.print(letters) //> [a, b, c, d]
|
||||
letters.insert(-2, "e") // Counts back from size after insert.
|
||||
System.print(letters) // ["a", "b", "c", "e", "d"]
|
||||
System.print(letters) //> [a, b, c, e, d]
|
||||
|
||||
## Removing elements
|
||||
|
||||
@ -97,15 +97,15 @@ gap:
|
||||
:::wren
|
||||
var letters = ["a", "b", "c", "d"]
|
||||
letters.removeAt(1)
|
||||
System.print(letters) // ["a", "c", "d"]
|
||||
System.print(letters) //> [a, c, d]
|
||||
|
||||
The `removeAt` method returns the removed item:
|
||||
|
||||
:::wren
|
||||
System.print(letters.removeAt(1)) // "c"
|
||||
System.print(letters.removeAt(1)) //> c
|
||||
|
||||
If you want to remove everything from the list, you can clear it:
|
||||
|
||||
:::wren
|
||||
hirsute.clear()
|
||||
System.print(hirsute) // []
|
||||
System.print(hirsute) //> []
|
||||
|
||||
@ -58,7 +58,7 @@ To find the value associated with some key, again you use your friend the
|
||||
subscript operator:
|
||||
|
||||
:::wren
|
||||
System.print(capitals["Idaho"]) // "Boise".
|
||||
System.print(capitals["Idaho"]) //> Boise
|
||||
|
||||
If the key is present, this returns its value. Otherwise, it returns `null`. Of
|
||||
course, `null` itself can also be used as a value, so seeing `null` here
|
||||
@ -69,15 +69,15 @@ To tell definitively if a key exists, you can call `containsKey()`:
|
||||
:::wren
|
||||
var belief = {"nihilism": null}
|
||||
|
||||
System.print(belief["nihilism"]) // "null" though key exists.
|
||||
System.print(belief["solipsism"]) // Also "null".
|
||||
System.print(belief.containsKey("nihilism")) // "true".
|
||||
System.print(belief.containsKey("solipsism")) // "false".
|
||||
System.print(belief["nihilism"]) //> null (though key exists)
|
||||
System.print(belief["solipsism"]) //> null
|
||||
System.print(belief.containsKey("nihilism")) //> true
|
||||
System.print(belief.containsKey("solipsism")) //> false
|
||||
|
||||
You can see how many entries a map contains using `count`:
|
||||
|
||||
:::wren
|
||||
System.print(capitals.count) // "3".
|
||||
System.print(capitals.count) //> 3
|
||||
|
||||
## Removing entries
|
||||
|
||||
@ -86,12 +86,12 @@ entry you want to delete:
|
||||
|
||||
:::wren
|
||||
capitals.remove("Maine")
|
||||
System.print(capitals.containsKey("Maine")) // "false".
|
||||
System.print(capitals.containsKey("Maine")) //> false
|
||||
|
||||
If the key was found, this returns the value that was associated with it:
|
||||
|
||||
:::wren
|
||||
System.print(capitals.remove("Georgia")) // "Atlanta".
|
||||
System.print(capitals.remove("Georgia")) //> Atlanta
|
||||
|
||||
If the key wasn't in the map to begin with, `remove()` just returns `null`.
|
||||
|
||||
@ -100,7 +100,7 @@ can just call `clear()`:
|
||||
|
||||
:::wren
|
||||
capitals.clear()
|
||||
System.print(capitals.count) // "0".
|
||||
System.print(capitals.count) //> 0
|
||||
|
||||
[lists]: lists.html
|
||||
|
||||
|
||||
@ -138,6 +138,13 @@ h2 {
|
||||
font: 500 24px $header;
|
||||
margin: 24px 0 0 0;
|
||||
color: $link;
|
||||
|
||||
code {
|
||||
border: none;
|
||||
background: inherit;
|
||||
color: inherit;
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
@ -245,7 +252,7 @@ footer {
|
||||
span.vc { color: hsl(130, 60%, 40%); }
|
||||
|
||||
// Numbers.
|
||||
span.m, span.mi, span.mf { color: hsl(30, 80%, 45%); }// hsl(90, 80%, 35%)
|
||||
span.m, span.mi, span.mf { color: hsl(30, 80%, 45%); }
|
||||
|
||||
// Strings.
|
||||
span.s, span.s2 { color: hsl(40, 80%, 45%); }
|
||||
@ -257,6 +264,29 @@ footer {
|
||||
|
||||
// Preprocessor directives.
|
||||
span.cp { color: hsl(270, 40%, 60%); }
|
||||
|
||||
span.output {
|
||||
float: right;
|
||||
color: hsl(150, 50%, 45%);
|
||||
|
||||
&::before, &::after {
|
||||
color: hsl(150, 50%, 80%);
|
||||
}
|
||||
|
||||
// Tall angle brackets.
|
||||
&::before { content: "\276c "; }
|
||||
&::after { content: ' \276d'; }
|
||||
}
|
||||
|
||||
span.error {
|
||||
float: right;
|
||||
color: hsl(350, 50%, 60%);
|
||||
|
||||
&::before {
|
||||
color: hsl(350, 50%, 75%);
|
||||
content: "Error: ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Have a different primary color for the core library docs.
|
||||
|
||||
@ -91,7 +91,7 @@ statement for the else:
|
||||
|
||||
:::wren
|
||||
if (happy && knowIt) {
|
||||
hands.clap
|
||||
hands.clap()
|
||||
} else System.print("sad")
|
||||
|
||||
Blocks have two similar but not identical forms. Typically, blocks contain a
|
||||
|
||||
@ -57,12 +57,12 @@ A handful of escape characters are supported:
|
||||
A `\u` followed by four hex digits can be used to specify a Unicode code point:
|
||||
|
||||
:::wren
|
||||
System.print("\u0041\u0b83\u00DE") // "AஃÞ"
|
||||
System.print("\u0041\u0b83\u00DE") //> AஃÞ
|
||||
|
||||
A `\x` followed by two hex digits specifies a single unencoded byte:
|
||||
|
||||
:::wren
|
||||
System.print("\x48\x69\x2e") // "Hi."
|
||||
System.print("\x48\x69\x2e") //> Hi.
|
||||
|
||||
Strings are instances of class [String](core/string.html).
|
||||
|
||||
@ -91,7 +91,7 @@ example:
|
||||
:::wren
|
||||
var list = ["a", "b", "c", "d", "e"]
|
||||
var slice = list[1..3]
|
||||
System.print(slice) // ["b", "c", "d"]
|
||||
System.print(slice) //> [b, c, d]
|
||||
|
||||
Their class is [Range](core/range.html).
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ defined, it can be accessed by name as you would expect.
|
||||
|
||||
:::wren
|
||||
var animal = "Slow Loris"
|
||||
System.print(animal) // Prints "Slow Loris".
|
||||
System.print(animal) //> Slow Loris
|
||||
|
||||
## Scope
|
||||
|
||||
@ -22,11 +22,11 @@ until the end of the [block](syntax.html#blocks) where that definition appears.
|
||||
|
||||
:::wren
|
||||
{
|
||||
System.print(a) // ERROR! a doesn't exist yet.
|
||||
System.print(a) //! "a" doesn't exist yet.
|
||||
var a = 123
|
||||
System.print(a) // "123"
|
||||
System.print(a) //> 123
|
||||
}
|
||||
System.print(a) // ERROR! a doesn't exist anymore.
|
||||
System.print(a) //! "a" doesn't exist anymore.
|
||||
|
||||
Variables defined at the top level of a script are *top-level* and are visible
|
||||
to the [module](modules.html) system. All other variables are *local*.
|
||||
@ -38,15 +38,15 @@ intend to do much).
|
||||
var a = "outer"
|
||||
{
|
||||
var a = "inner"
|
||||
System.print(a) // Prints "inner".
|
||||
System.print(a) //> inner
|
||||
}
|
||||
System.print(a) // Prints "outer".
|
||||
System.print(a) //> outer
|
||||
|
||||
Declaring a variable with the same name in the *same* scope *is* an error.
|
||||
|
||||
:::wren
|
||||
var a = "hi"
|
||||
var a = "again" // ERROR!
|
||||
var a = "again" //! "a" is already declared.
|
||||
|
||||
## Assignment
|
||||
|
||||
@ -65,6 +65,6 @@ assigned value.
|
||||
|
||||
:::wren
|
||||
var a = "before"
|
||||
System.print(a = "after") // Prints "after".
|
||||
System.print(a = "after") //> after
|
||||
|
||||
**TODO: Top-level names.**
|
||||
|
||||
@ -93,6 +93,10 @@ def format_file(path, skip_up_to_date):
|
||||
|
||||
html = markdown.markdown(contents, ['def_list', 'codehilite', 'smarty'])
|
||||
|
||||
# Use special formatting for example output and errors.
|
||||
html = html.replace('<span class="c1">//> ', '<span class="output">')
|
||||
html = html.replace('<span class="c1">//! ', '<span class="error">')
|
||||
|
||||
modified = datetime.fromtimestamp(os.path.getmtime(in_path))
|
||||
mod_str = modified.strftime('%B %d, %Y')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user