feat: replace IO class with System class and remove separate IO module

- Delete wren_io.c, wren_io.h, and io.wren source files
- Remove multi-arity print overloads and IO.read/IO.time methods
- Add System class with print, printAll, write, writeAll methods to core.wren
- Update all documentation examples and README to use System.print instead of IO.print
This commit is contained in:
Bob Nystrom
2015-09-15 14:46:09 +00:00
parent f12581a674
commit aa72900a9e
491 changed files with 3285 additions and 3544 deletions
+15 -15
View File
@@ -25,7 +25,7 @@ To let our unicorn do stuff, we need to give it methods.
:::dart
class Unicorn {
prance() {
IO.print("The unicorn prances in a fancy manner!")
System.print("The unicorn prances in a fancy manner!")
}
}
@@ -35,7 +35,7 @@ parameters, put their names inside the parentheses:
:::dart
class Unicorn {
prance(where, when) {
IO.print("The unicorn prances in " + where + " at " + when)
System.print("The unicorn prances in " + where + " at " + when)
}
}
@@ -49,15 +49,15 @@ fine:
:::dart
class Unicorn {
prance() {
IO.print("The unicorn prances in a fancy manner!")
System.print("The unicorn prances in a fancy manner!")
}
prance(where) {
IO.print("The unicorn prances in " + where)
System.print("The unicorn prances in " + where)
}
prance(where, when) {
IO.print("The unicorn prances in " + where + " at " + when)
System.print("The unicorn prances in " + where + " at " + when)
}
}
@@ -83,7 +83,7 @@ Many methods on a class exist to expose or compute some property of the object.
For example:
:::dart
IO.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:
@@ -152,12 +152,12 @@ You can define operators in your class like so:
class Unicorn {
// Infix:
+(other) {
IO.print("Adding to a unicorn?")
System.print("Adding to a unicorn?")
}
// Prefix:
! {
IO.print("Negating a unicorn?!")
System.print("Negating a unicorn?!")
}
}
@@ -191,7 +191,7 @@ like so:
:::dart
class Unicorn {
construct new(name, color) {
IO.print("My name is " + name + " and I am " + color + ".")
System.print("My name is " + name + " and I am " + color + ".")
}
}
@@ -210,7 +210,7 @@ and each can clarify how it creates the instance:
:::dart
class Unicorn {
construct brown(name) {
IO.print("My name is " + name + " and I am brown.")
System.print("My name is " + name + " and I am brown.")
}
}
@@ -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`:
:::dart
IO.print(Foo.bar) // null.
System.print(Foo.bar) // null.
They can be used from static methods:
:::dart
Foo.set("foo")
IO.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")
IO.print(foo2.baz) // updated.
System.print(foo2.baz) // updated.
## Inheritance
@@ -381,7 +381,7 @@ This also means constructors are not inherited:
:::dart
class Unicorn {
this new(name) {
IO.print("My name is " + name + ".")
System.print("My name is " + name + ".")
}
}
@@ -398,7 +398,7 @@ This means you can do `super` calls inside a constructor:
:::dart
class Unicorn {
this new(name) {
IO.print("My name is " + name + ".")
System.print("My name is " + name + ".")
}
}
+12 -12
View File
@@ -31,7 +31,7 @@ The simplest branching statement, `if` lets you conditionally skip a chunk of
code. It looks like this:
:::dart
if (ready) IO.print("go!")
if (ready) System.print("go!")
That evaluates the parenthesized expression after `if`. If it's true, then the
statement after the condition is evaluated. Otherwise it is skipped. Instead of
@@ -39,23 +39,23 @@ a statement, you can have a [block](syntax.html#blocks):
:::dart
if (ready) {
IO.print("getSet")
IO.print("go!")
System.print("getSet")
System.print("go!")
}
You may also provide an `else` branch. It will be executed if the condition is
false:
:::dart
if (ready) IO.print("go!") else IO.print("not ready!")
if (ready) System.print("go!") else System.print("not ready!")
And, of course, it can take a block too:
:::dart
if (ready) {
IO.print("go!")
System.print("go!")
} else {
IO.print("not ready!")
System.print("not ready!")
}
## While statements
@@ -100,7 +100,7 @@ That's what `for` is for. It looks like this:
:::dart
for (beatle in ["george", "john", "paul", "ringo"]) {
IO.print(beatle)
System.print(beatle)
}
A `for` loop has three components:
@@ -124,7 +124,7 @@ keyword all by itself. That will immediately exit out of the nearest enclosing
:::dart
for (i in [1, 2, 3, 4]) {
IO.print(i)
System.print(i)
if (i == 3) break
}
@@ -138,7 +138,7 @@ sequence of numbers, or loop a number of times. For that, you can create a
:::dart
for (i in 1..100) {
IO.print(i)
System.print(i)
}
This loops over the numbers from 1 to 100, including 100 itself. If you want to
@@ -146,7 +146,7 @@ leave off the last value, use three dots instead of two:
:::dart
for (i in 1...100) {
IO.print(i)
System.print(i)
}
This looks like some special "range" syntax in the `for` loop, but it's
@@ -168,7 +168,7 @@ When you write a loop like this:
:::dart
for (i in 1..100) {
IO.print(i)
System.print(i)
}
Wren sees it something like this:
@@ -178,7 +178,7 @@ Wren sees it something like this:
var seq_ = 1..100
while (iter_ = seq_.iterate(iter_)) {
var i = seq_.iteratorValue(iter_)
IO.print(i)
System.print(i)
}
First, Wren evaluates the sequence expression and stores it in a hidden
+3 -4
View File
@@ -9,10 +9,9 @@ Boolean values. There are two instances, `true` and `false`.
Returns the logical complement of the value.
> !true
false
> !false
true
:::dart
System.print(!true) // "false".
System.print(!false) // "true".
### toString
+3 -3
View File
@@ -15,14 +15,14 @@ The superclass of this class.
class Crustacean {}
class Crab is Crustacean {}
IO.print(Crab.supertype) // "Crustacean"
System.print(Crab.supertype) // "Crustacean".
A class with no explicit superclass implicitly inherits Object:
:::dart
IO.print(Crustacean.supertype) // "Object"
System.print(Crustacean.supertype) // "Object".
Object forms the root of the class hierarchy and has no supertype:
:::dart
IO.print(Object.supertype) // "null"
System.print(Object.supertype) // "null".
+13 -13
View File
@@ -10,7 +10,7 @@ fiber is run. Does not immediately start running the fiber.
:::dart
var fiber = Fiber.new {
IO.print("I won't get printed")
System.print("I won't get printed")
}
## Static Methods
@@ -34,14 +34,14 @@ here means the last fiber that was started using `call` and not `run`.
:::dart
var fiber = Fiber.new {
IO.print("Before yield")
System.print("Before yield")
Fiber.yield()
IO.print("After yield")
System.print("After yield")
}
fiber.call() // "Before yield"
IO.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,
:::dart
var fiber = Fiber.new {
IO.print(Fiber.yield()) // "value"
System.print(Fiber.yield()) // "value"
}
fiber.call() // Run until the first yield.
@@ -65,7 +65,7 @@ later.
:::dart
Fiber.yield()
IO.print("this does not get reached")
System.print("this does not get reached")
### Fiber.**yield**(value)
@@ -77,7 +77,7 @@ Similar to `Fiber.yield` but provides a value to return to the parent fiber's
Fiber.yield("value")
}
IO.print(fiber.call()) // "value"
System.print(fiber.call()) // "value"
## Methods
@@ -87,9 +87,9 @@ Starts or resumes the fiber if it is in a paused state.
:::dart
var fiber = Fiber.new {
IO.print("Fiber called")
System.print("Fiber called")
Fiber.yield()
IO.print("Fiber called again")
System.print("Fiber called again")
}
fiber.call() // Start it.
@@ -103,7 +103,7 @@ If the called fiber is resuming from a yield, the `yield()` method returns
:::dart
var fiber = Fiber.new {
IO.print(Fiber.yield())
System.print(Fiber.yield())
}
fiber.call()
@@ -116,7 +116,7 @@ Invokes the fiber or resumes the fiber if it is in a paused state and sets
:::dart
var fiber = Fiber.new {
IO.print(Fiber.yield())
System.print(Fiber.yield())
}
fiber.call()
+4 -4
View File
@@ -13,7 +13,7 @@ argument](../functions.html#block-arguments) to some other method.
:::dart
var fn = Fn.new {
IO.print("The body")
System.print("The body")
}
It is a runtime error if `function` is not a function.
@@ -25,8 +25,8 @@ It is a runtime error if `function` is not a function.
The number of arguments the function requires.
:::dart
IO.print(Fn.new {}.arity) // 0.
IO.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,7 +34,7 @@ Invokes the function with the given arguments.
:::dart
var fn = Fn.new { |arg|
IO.print(arg)
System.print(arg)
}
fn.call("Hello world") // Prints "Hello world".
+1 -1
View File
@@ -20,6 +20,6 @@ All Wren source files automatically have access to the following classes:
* [Range](range.html)
* [Sequence](sequence.html)
* [String](string.html)
* [IO](io.html)
* [System](system.html)
[embedding]: ../embedding-api.html
-60
View File
@@ -1,60 +0,0 @@
^title IO Class
^category core
The IO class can be used to read and write to and from the console.
## Static Methods
### IO.**print**(objects...)
Prints a series of objects to the console followed by a newline. Each object is
converted to a string by calling `toString` on it. This is overloaded to
support up to 16 objects. To pass more, use `printAll()`.
> IO.print("I like bananas")
I like bananas
> IO.print("Oranges", 10)
Oranges10
### IO.**printAll**(sequence)
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.
> IO.printAll([1, [2, 3], 4])
1[2, 3]4
### IO.**write**(object)
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.
> IO.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.
### IO.**read**()
Reads in a line of text from stdin. Note that the returned text includes the
trailing newline.
> var name = IO.read()
John
> IO.print("Hello " + name + "!")
Hello John
!
>
### IO.**read**(prompt)
Displays `prompt` then reads in a line of text from stdin. Note that the
returned text includes the trailing newline.
> var name = IO.read("Enter your name: ")
Enter your name: John
> IO.print("Hello " + name + "!")
Hello John
!
>
+8 -8
View File
@@ -26,14 +26,14 @@ Inserts the `item` at `index` in the list.
:::dart
var list = ["a", "b", "c", "d"]
list.insert(1, "e")
IO.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.
:::dart
var list = ["a", "b", "c"]
list.insert(3, "d")
IO.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")
IO.print(list) // "[a, b, c, d]"
System.print(list) // "[a, b, c, d]".
Returns the inserted item.
:::dart
IO.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.
:::dart
var list = ["a", "b", "c", "d"]
list.removeAt(1)
IO.print(list) // "[a, c, d]".
System.print(list) // "[a, c, d]".
Returns the removed item.
IO.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.
:::dart
var list = ["a", "b", "c"]
IO.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.
:::dart
var list = ["a", "b", "c"]
list[1] = "new"
IO.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.
+2 -2
View File
@@ -50,8 +50,8 @@ map, returns `null`.
:::dart
var map = {"george": "harrison", "ringo": "starr"}
IO.print(map["ringo"]) // "starr".
IO.print(map["pete"]) // "null".
System.print(map["ringo"]) // "starr".
System.print(map["pete"]) // "null".
### **[**key**]=**(value) operator
+2 -2
View File
@@ -7,5 +7,5 @@
Returns `true`, since `null` is considered [false](../control-flow.html#truth).
> !null
true
:::dart
System.print(!null) // "true".
+6 -6
View File
@@ -132,9 +132,9 @@ from the beginning number to the ending number.
:::dart
var range = 1.2..3.4
IO.print(range.min) // 1.2
IO.print(range.max) // 3.4
IO.print(range.isInclusive) // true
System.print(range.min) // 1.2
System.print(range.max) // 3.4
System.print(range.isInclusive) // true
### **...**(other) operator
@@ -143,6 +143,6 @@ from the beginning number to the ending number not including the ending number.
:::dart
var range = 1.2...3.4
IO.print(range.min) // 1.2
IO.print(range.max) // 3.4
IO.print(range.isInclusive) // false
System.print(range.min) // 1.2
System.print(range.max) // 3.4
System.print(range.isInclusive) // false
+5 -5
View File
@@ -59,7 +59,7 @@ and counting the number of times the returned value evaluates to `true`.
Iterates over the sequence, passing each element to the given `function`.
:::dart
["one", "two", "three"].each {|word| IO.print(word) }
["one", "two", "three"].each {|word| System.print(word) }
### **isEmpty**
@@ -88,7 +88,7 @@ original sequence while it is iterated.
:::dart
var doubles = [1, 2, 3].map {|n| n * 2 }
for (n in doubles) {
IO.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 +105,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)
IO.print(doubles) // [2, 4, 6].
System.print(doubles) // [2, 4, 6].
### **reduce**(function)
@@ -142,7 +142,7 @@ function `predicate`. If it returns `false`, the element is skipped.
:::dart
var odds = (1..10).where {|n| n % 2 == 1 }
for (n in odds) {
IO.print(n) // "1", "3", "5", "7", "9".
System.print(n) // "1", "3", "5", "7", "9".
}
The returned sequence is *lazy*. It only applies the filtering when you iterate
@@ -160,4 +160,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)
IO.print(odds) // [1, 3, 5].
System.print(odds) // [1, 3, 5].
+8 -8
View File
@@ -37,7 +37,7 @@ on strings *return* byte indexes too. So, for example, this does what you want:
:::dart
var metalBand = "Fäcëhämmër"
var hPosition = metalBand.indexOf("h")
IO.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
@@ -68,7 +68,7 @@ methods, the returned object also has a subscript operator that can be used to
directly index bytes.
:::dart
IO.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.
:::dart
var string = "(ᵔᴥᵔ)"
IO.print(string.codePoints[0]) // 40, for "(".
IO.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`.
:::dart
var string = "(ᵔᴥᵔ)"
IO.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)
}
IO.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`.
:::dart
IO.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:
:::dart
IO.print("I ♥ NY"[3]) // One-byte string whose value is 153.
System.print("I ♥ NY"[3]) // One-byte string whose value is 153.
It is a runtime error if `index` is greater than the number of bytes in the
string.
+43
View File
@@ -0,0 +1,43 @@
^title System Class
^category core
The System class is a grab-bag of functionality exposed by the VM, mostly for
use during development or debugging.
## Static Methods
### System.**print**()
Prints a single newline to the console.
### System.**print**(object)
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.
:::dart
System.print("I like bananas") // Prints "I like bananas".
### System.**printAll**(sequence)
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.
:::dart
System.printAll([1, [2, 3], 4]) // Prints "1[2, 3]4".
### System.**write**(object)
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.
:::dart
System.write(4 + 5) // Prints "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.
### System.**clock**
Returns the number of seconds (including fractional seconds) since the program
was started. This is usually used for benchmarking.
+1 -1
View File
@@ -70,7 +70,7 @@ You can tell the VM to execute a string of Wren source code like so:
:::c
WrenInterpretResult result = wrenInterpret(vm,
"<where>",
"IO.print(\"Hi!\")");
"System.print(\"Hi!\")");
The first string parameter is a "source path". It's just an arbitrary string that describes where the source code is from. It's what shows up in stack traces if a runtime error occurs in the code. It can be whatever you want as long as it's not `NULL`.
+2 -2
View File
@@ -108,7 +108,7 @@ For example, if you run this program:
}
var error = fiber.try()
IO.print("Caught error: ", error)
System.print("Caught error: " + error)
It prints:
@@ -120,7 +120,7 @@ usual. When a fiber has been aborted because of a runtime error, you can also
get the error from the fiber object. Continuing the above example:
:::dart
IO.print(fiber.error)
System.print(fiber.error)
This also prints:
+9 -9
View File
@@ -29,7 +29,7 @@ Wren is object-oriented, so most code consists of method calls. Most of them
look like so:
:::dart
IO.print("hello")
System.print("hello")
items.add("another")
items.insert(1, "value")
@@ -61,7 +61,7 @@ argument](functions.html#block-arguments):
:::dart
blondie.callMeAt(867, 5309) {
IO.print("This is the body!")
System.print("This is the body!")
}
Semantically, all method calls work like so:
@@ -98,7 +98,7 @@ call:
:::dart
class Base {
method {
IO.print("base method")
System.print("base method")
}
}
@@ -114,7 +114,7 @@ base class constructor:
:::dart
class Base {
this new(arg) {
IO.print("base constructor got ", arg)
System.print("base constructor got " + arg)
}
}
@@ -218,16 +218,16 @@ A `&&` ("logical and") expression evaluates the left-hand argument. If it's
and returns the right-hand argument.
:::dart
IO.print(false && 1) // false
IO.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:
:::dart
IO.print(false || 1) // 1
IO.print(1 || 2) // 1
System.print(false || 1) // 1
System.print(1 || 2) // 1
## The conditional operator `?:`
@@ -236,7 +236,7 @@ the little "if statement in the form of an expression" you know and love from C
and its brethren.
:::dart
IO.print(1 != 2 ? "math is sane" : "math is not sane!")
System.print(1 != 2 ? "math is sane" : "math is not sane!")
It takes a condition expression, followed by `?`, followed by a then
expression, a `:`, then an else expression. Just like `if`, it evaluates the
+9 -9
View File
@@ -28,7 +28,7 @@ using the `Fiber` class's constructor:
:::dart
var fiber = Fiber.new {
IO.print("This runs in a separate fiber.")
System.print("This runs in a separate fiber.")
}
Creating a fiber does not immediately run it. It's just a first class bundle of
@@ -48,7 +48,7 @@ until it passes control to another fiber. If it reaches the end of its body,
it's considered *done*:
:::dart
var fiber = Fiber.new { IO.print("Hi") }
var fiber = Fiber.new { System.print("Hi") }
fiber.isDone // false
fiber.call()
fiber.isDone // true
@@ -71,16 +71,16 @@ You can make a fiber yield by calling the static `yield()` method on `Fiber`:
:::dart
var fiber = Fiber.new {
IO.print("fiber 1")
System.print("fiber 1")
Fiber.yield()
IO.print("fiber 2")
System.print("fiber 2")
}
IO.print("main 1")
System.print("main 1")
fiber.call()
IO.print("main 2")
System.print("main 2")
fiber.call()
IO.print("main 3")
System.print("main 3")
This program prints:
@@ -105,7 +105,7 @@ of the `yield()` call:
:::dart
var fiber = Fiber.new {
var result = Fiber.yield()
IO.print(result)
System.print(result)
}
fiber.call("discarded")
@@ -124,7 +124,7 @@ invoke the fiber:
Fiber.yield("sent")
}
IO.print(fiber.call())
System.print(fiber.call())
This also prints "sent".
+8 -8
View File
@@ -22,7 +22,7 @@ a method. At its simplest, it looks like this:
:::dart
blondie.callMe {
IO.print("This is the body!")
System.print("This is the body!")
}
Here we're invoking the `callMe` method on `blondie`. We're passing one
@@ -44,7 +44,7 @@ the block just like a regular argument list. For example:
:::dart
blondie.callMeAt(867, 5309) {
IO.print("This is the body!")
System.print("This is the body!")
}
Of course, you don't *have* to use a block argument to pass a function to a
@@ -62,7 +62,7 @@ class's constructor:
:::dart
var someFn = Fn.new {
IO.print("Hi!")
System.print("Hi!")
}
As you can see it takes a block argument too! All the constructor does it
@@ -87,7 +87,7 @@ method is dynamically-dispatched like any other, so you can define your own
:::dart
class FakeFn {
call() {
IO.print("I'm feeling functional!")
System.print("I'm feeling functional!")
}
}
@@ -102,7 +102,7 @@ of the body, like so:
:::dart
blondie.callMe {|first, last|
IO.print("Hi, " + first + " " + last + "!")
System.print("Hi, " + first + " " + last + "!")
}
Here we're passing a function to `greet` that takes two parameters, `first` and
@@ -157,6 +157,6 @@ to`i`:
:::dart
var counter = Counter.create
IO.print(counter.call()) // Prints "1".
IO.print(counter.call()) // Prints "2".
IO.print(counter.call()) // Prints "3".
System.print(counter.call()) // Prints "1".
System.print(counter.call()) // Prints "2".
System.print(counter.call()) // Prints "3".
+4 -4
View File
@@ -49,12 +49,12 @@ interactive mode. You can type in a line of code, and it will immediately
execute it. Here's something to try:
:::dart
IO.print("Hello, world!")
System.print("Hello, world!")
Or a little more exciting:
:::dart
for (i in 1..10) IO.print("Counting up ", i)
for (i in 1..10) System.print("Counting up " + i.toString)
You can exit the interpreter using good old Ctrl-C or Ctrl-D, or just throw
your computer to the ground and storm off.
@@ -80,10 +80,10 @@ your favorite text editor and paste this into it:
y0 = y1
iter = iter + 1
}
IO.write(" .-:;+=xX$& "[iter])
System.write(" .-:;+=xX$& "[iter])
}
IO.print("")
System.print("")
}
Now run:
+3 -3
View File
@@ -6,11 +6,11 @@ Think Smalltalk in a Lua-sized package with a dash of Erlang and wrapped up in
a familiar, modern [syntax][].
:::dart
IO.print("Hello, world!")
System.print("Hello, world!")
class Wren {
flyTo(city) {
IO.print("Flying to ", city)
System.print("Flying to " + city)
}
}
@@ -18,7 +18,7 @@ a familiar, modern [syntax][].
["small", "clean", "fast"].each {|word| Fiber.yield(word) }
}
while (!adjectives.isDone) IO.print(adjectives.call())
while (!adjectives.isDone) System.print(adjectives.call())
* **Wren is small.** The VM implementation is under [4,000 semicolons][src].
You can skim the whole thing in an afternoon. It's *small*, but not
+7 -7
View File
@@ -59,14 +59,14 @@ existing element in the list using the subscript setter:
:::dart
hirsute[1] = "muttonchops"
IO.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:
:::dart
hirsute.add("goatee")
IO.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:
:::dart
var letters = ["a", "b", "c"]
letters.insert(3, "d") // OK: inserts at end.
IO.print(letters) // ["a", "b", "c", "d"]
System.print(letters) // ["a", "b", "c", "d"]
letters.insert(-2, "e") // Counts back from size after insert.
IO.print(letters) // ["a", "b", "c", "e", "d"]
System.print(letters) // ["a", "b", "c", "e", "d"]
## Removing elements
@@ -97,15 +97,15 @@ gap:
:::dart
var letters = ["a", "b", "c", "d"]
letters.removeAt(1)
IO.print(letters) // ["a", "c", "d"]
System.print(letters) // ["a", "c", "d"]
The `removeAt` method returns the removed item:
:::dart
IO.print(letters.removeAt(1)) // "c"
System.print(letters.removeAt(1)) // "c"
If you want to remove everything from the list, you can clear it:
:::dart
hirsute.clear()
IO.print(hirsute) // []
System.print(hirsute) // []
+12 -12
View File
@@ -58,7 +58,7 @@ To find the value associated with some key, again you use your friend the
subscript operator:
:::dart
IO.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()`:
:::dart
var belief = {"nihilism": null}
IO.print(belief["nihilism"]) // "null" though key exists.
IO.print(belief["solipsism"]) // Also "null".
IO.print(belief.containsKey("nihilism")) // "true".
IO.print(belief.containsKey("solipsism")) // "false".
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".
You can see how many entries a map contains using `count`:
:::dart
IO.print(capitals.count) // "3".
System.print(capitals.count) // "3".
## Removing entries
@@ -86,12 +86,12 @@ entry you want to delete:
:::dart
capitals.remove("Maine")
IO.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:
:::dart
IO.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()`:
:::dart
capitals.clear()
IO.print(capitals.count) // "0".
System.print(capitals.count) // "0".
[lists]: lists.html
@@ -120,14 +120,14 @@ If you want to see all of the key-value pairs in a map, the easiest way is to
iterate over the keys and use each to look up its value:
:::dart
var stateBirds = {
var birds = {
"Arizona": "Cactus wren",
"Hawaii": "Nēnē",
"Ohio": "Northern Cardinal"
}
for (state in stateBirds.keys) {
IO.print("The state bird of ", state, " is ", stateBirds[state])
for (state in birds.keys) {
System.print("The state bird of " + state + " is " + birds[state])
}
This program will print the three states and their birds. However, the *order*
+5 -5
View File
@@ -173,7 +173,7 @@ like:
import "shared"
// shared.wren
IO.print("Shared!")
System.print("Shared!")
Here, "a" and "b" both want to use "shared". If "shared" defines some top-level
state, we only want a single copy of that in memory. To handle this, a module's
@@ -211,14 +211,14 @@ For example:
import "a"
// a.wren
IO.print("start a")
System.print("start a")
import "b"
IO.print("end a")
System.print("end a")
// b.wren
IO.print("start b")
System.print("start b")
import "a"
IO.print("end b")
System.print("end b")
This program runs successfully and prints:
+7 -7
View File
@@ -54,15 +54,15 @@ Newlines (`\n`) are meaningful in Wren. They are used to separate statements:
:::dart
// Two statements:
IO.print("hi") // Newline.
IO.print("bye")
System.print("hi") // Newline.
System.print("bye")
Sometimes, though, a statement doesn't fit on a single line and jamming a
newline in the middle would trip it up. To handle that, Wren has a very simple
rule: It ignores a newline following any token that can't end a statement.
:::dart
IO.print( // Newline here is ignored.
System.print( // Newline here is ignored.
"hi")
In practice, this means you can put each statement on its own line and wrap
@@ -79,16 +79,16 @@ statement for the else:
:::dart
if (happy && knowIt) {
hands.clap
} else IO.print("sad")
} else System.print("sad")
Blocks have two similar but not identical forms. Typically, blocks contain a
series of statements like:
:::dart
{
IO.print("one")
IO.print("two")
IO.print("three")
System.print("one")
System.print("two")
System.print("three")
}
Blocks of this form when used for method and function bodies automatically
+1 -1
View File
@@ -38,7 +38,7 @@
<li><a href="range.html">Range</a></li>
<li><a href="sequence.html">Sequence</a></li>
<li><a href="string.html">String</a></li>
<li><a href="io.html">IO</a></li>
<li><a href="system.html">System</a></li>
</ul>
</section>
</nav>
+3 -3
View File
@@ -57,11 +57,11 @@ A handful of escape characters are supported:
A `\u` followed by four hex digits can be used to specify a Unicode code point:
:::dart
IO.print("\u0041\u0b83\u00DE") // "AஃÞ"
System.print("\u0041\u0b83\u00DE") // "AஃÞ"
A `\x` followed by two hex digits specifies a single unencoded byte:
IO.print("\x48\x69\x2e") // "Hi."
System.print("\x48\x69\x2e") // "Hi."
Strings are instances of class [String](core/string.html).
@@ -90,7 +90,7 @@ example:
:::dart
var list = ["a", "b", "c", "d", "e"]
var slice = list[1..3]
IO.print(slice) // ["b", "c", "d"]
System.print(slice) // ["b", "c", "d"]
Their class is [Range](core/range.html).
+7 -7
View File
@@ -13,7 +13,7 @@ defined, it can be accessed by name as you would expect.
:::dart
var animal = "Slow Loris"
IO.print(animal) // Prints "Slow Loris".
System.print(animal) // Prints "Slow Loris".
## Scope
@@ -22,11 +22,11 @@ until the end of the [block](syntax.html#blocks) where that definition appears.
:::dart
{
IO.print(a) // ERROR! a doesn't exist yet.
System.print(a) // ERROR! a doesn't exist yet.
var a = 123
IO.print(a) // "123"
System.print(a) // "123"
}
IO.print(a) // ERROR! a doesn't exist anymore.
System.print(a) // ERROR! 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,9 +38,9 @@ intend to do much).
var a = "outer"
{
var a = "inner"
IO.print(a) // Prints "inner".
System.print(a) // Prints "inner".
}
IO.print(a) // Prints "outer".
System.print(a) // Prints "outer".
Declaring a variable with the same name in the *same* scope *is* an error.
@@ -65,6 +65,6 @@ assigned value.
:::dart
var a = "before"
IO.print(a = "after") // Prints "after".
System.print(a = "after") // Prints "after".
**TODO: Top-level names.**