From 8edc610287d7ae081b8c722919447e1865955df2 Mon Sep 17 00:00:00 2001 From: Bob Nystrom Date: Sat, 3 Jan 2015 23:27:54 -0800 Subject: [PATCH] Republish docs. --- branching.html | 130 ------------- classes.html | 189 ++++++++++++++----- contributing.html | 21 ++- looping.html => control-flow.html | 139 +++++++++++--- core-library.html | 55 ++++-- embedding-api.html | 17 +- error-handling.html | 93 ++++++--- expressions.html | 300 ++++++++++++++++++++++++++++++ fibers.html | 102 +++++++--- functions.html | 82 +++++--- getting-started.html | 37 ++-- index.html | 39 ++-- lists.html | 49 +++-- maps.html | 8 +- method-calls.html | 160 ---------------- performance.html | 131 ++++++++++--- qa.html | 79 ++++++-- syntax.html | 88 +++++---- values.html | 51 +++-- variables.html | 17 +- 20 files changed, 1166 insertions(+), 621 deletions(-) delete mode 100644 branching.html rename looping.html => control-flow.html (55%) create mode 100644 expressions.html delete mode 100644 method-calls.html diff --git a/branching.html b/branching.html deleted file mode 100644 index c7b88d0b..00000000 --- a/branching.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - -Branching – Wren - - - - - - -
-
-
-

wren

-

a classy little scripting language

-
-
-
-
- -
-

Branching

-

Control flow is used to determine which chunks of code are executed and how many times. Expressions and statements for deciding whether or not to execute some code are called branching and are covered here. To execute something more than once, you'll want looping.

-

Truth #

-

Branching is conditional on the value of some expression. We take the entire universe of possible values and divide them into two buckets: some we consider "true" and the rest are "false". If the expression results in a value in the true bucket, we branch one way. Otherwise, we go the other way.

-

Obviously, the boolean true is in the "true" bucket and false is in "false", but what about values of other types? The choice is ultimately arbitrary, and different languages have different rules. Wren's rules follow Ruby:

-
    -
  • The boolean value false is false.
  • -
  • The null value null is false.
  • -
  • Everything else is true.
  • -
-

This means 0, empty strings, and empty collections are all considered "true" values.

-

If statements #

-

The simplest branching statement, if lets you conditionally skip a chunk of code. It looks like this:

-
if (ready) IO.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 a statement, you can have a block:

-
if (ready) {
-  IO.print("getSet")
-  IO.print("go!")
-}
-
- - -

You may also provide an else branch. It will be executed if the condition is false:

-
if (ready) IO.print("go!") else IO.print("not ready!")
-
- - -

And, of course, it can take a block too:

-
if (ready) {
-  IO.print("go!")
-} else {
-  IO.print("not ready!")
-}
-
- - -

The logical operators && and || #

-

The && and || operators are lumped here under branching because they conditionally execute some code—they short-circuit. Both of them are infix operators, and, depending on the value of the left-hand side, the right-hand operand expression may or may not be evaluated.

-

An && ("logical and") expression evaluates the left-hand argument. If it's false, it returns that value. Otherwise it evaluates and returns the right-hand argument.

-
IO.print(false && 1)  // false
-IO.print(1 && 2)      // 2
-
- - -

An || ("logical or") expression is reversed. If the left-hand argument is true, it's returned, otherwise the right-hand argument is evaluated and returned:

-
IO.print(false || 1)  // 1
-IO.print(1 || 2)      // 1
-
- - -

The conditional operator ?: #

-

Also known as the "ternary" operator since it takes three arguments, Wren has the little "if statement in the form of an expression" you know and love from C and its bretheren.

-
IO.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 condition. If true, it evaluates (and returns) the then expression. Otherwise it does the else expression.

-
-
- - - \ No newline at end of file diff --git a/classes.html b/classes.html index 050258c4..790cf227 100644 --- a/classes.html +++ b/classes.html @@ -27,10 +27,9 @@

language

@@ -59,8 +58,11 @@

Classes

Every value in Wren is an object, and every object is an instance of a class. -Even true and false are full-featured objects—instances of the Bool class.

-

Classes contain both behavior and state. Behavior is defined in methods which are stored in the class. State is defined in fields, whose values are stored in each instance.

+Even true and false are full-featured objects—instances of the Bool +class.

+

Classes contain both behavior and state. Behavior is defined in methods +which are stored in the class. State is defined in fields, whose values are +stored in each instance.

Defining a class #

Classes are created using the class keyword, unsurprisingly:

class Unicorn {}
@@ -78,7 +80,8 @@ Even true and false are full-featured objects—in
 
-

This defines a prance method that takes no arguments. To support parameters, add a parenthesized parameter list after the method's name:

+

This defines a prance method that takes no arguments. To support parameters, +add a parenthesized parameter list after the method's name:

class Unicorn {
   prance(where, when) {
     IO.print("The unicorn prances in " + where + " at " + when)
@@ -87,7 +90,11 @@ Even true and false are full-featured objects—in
 
-

Unlike most other dynamically-typed languages, in Wren you can have multiple methods in a class with the same name, as long as they take a different number of parameters. In technical terms, you can overload by arity. So this class is fine:

+

Arity #

+

Unlike most other dynamically-typed languages, in Wren you can have multiple +methods in a class with the same name, as long as they take a different number +of parameters. In technical terms, you can overload by arity. So this class +is fine:

class Unicorn {
   prance {
     IO.print("The unicorn prances in a fancy manner!")
@@ -104,39 +111,25 @@ Even true and false are full-featured objects—in
 
-

When you call the prance method, it selects the right one based on how many arguments you pass it.

-

Constructors #

-

To create a new instance of a class, you use the new keyword. We can make a unicorn like so:

-
new Unicorn
+

And you can call each of the methods like so:

+
var unicorn = new Unicorn
+unicorn.prance
+unicorn.prance("Antwerp")
+unicorn.prance("Brussels", "high noon")
 
-

You almost always want to define some state or do some other initialization on a new object. For that, you'll want to define a constructor, like so:

-
class Unicorn {
-  new {
-    IO.print("I am a constructor!")
-  }
-}
-
- - -

When you create an instance with new, its constructor will be invoked. It's just a method with a special name. Like methods, you can pass arguments to the constructor by adding a parenthesized parameter list after new:

-
class Unicorn {
-  new(name, color) {
-    IO.print("My name is " + name + " and I am " + color + ".")
-  }
-}
-
- - -

Values are passed to the constructor like so:

-
new Unicorn("Flicker", "purple")
-
- - -

Like other methods, you can overload constructors by arity.

-

Operators #

-

Operators are just special syntax for regular method calls on the left hand operand (or only operand in the case of unary operators like ! and ~). You can define them like so:

+

The number of arguments provided at the callsite determines which method is +chosen.

+

It's often natural to have the same conceptual operation work with different +sets of arguments. In other languages, you'd define a single method for the +operation and have to check for "undefined" or missing arguments. Wren just +treats them as different methods that you can implement separately.

+

Operators #

+

Operators are just special syntax for a method call on the left hand operand +(or only operand in the case of unary operators like ! and ~). In other +words, you can think of a + b as meaning a.+(b).

+

You can define operators in your class like so:

class Unicorn {
   // Infix:
   +(other) {
@@ -160,23 +153,120 @@ Even true and false are full-featured objects—in
 
-

Note that - can be both a prefix and infix operator. If there's a parameter list, it's the infix one, otherwise, it's prefix. Since Wren supports overloading by arity, it's no problem for a class to define both.

-

Operator overloading is really useful for types like vectors and complex numbers where the reader knows what the operators will do, but can make code deeply confusing if overused. When in doubt, use a real name.

-

Setters #

-

TODO: ...

-

Fields #

+

Note that - can be both a prefix and infix operator. If there's a parameter +list, it's the infix one, otherwise, it's prefix. Since Wren supports +overloading by arity, it's no problem for a class to define both.

+

Subscript operators #

TODO

+

Setters #

+

TODO

+

Constructors #

+

To create a new instance of a class, you use the new keyword. We can make a +unicorn like so:

+
new Unicorn
+
+ + +

You almost always want to define some state or do some other initialization on +a new object. For that, you'll want to define a constructor, like so:

+
class Unicorn {
+  new {
+    IO.print("I am a constructor!")
+  }
+}
+
+ + +

When you create an instance with new, its constructor will be invoked. It's +just a method with a special name. Like methods, you can pass arguments to the +constructor by adding a parenthesized parameter list after new:

+
class Unicorn {
+  new(name, color) {
+    IO.print("My name is " + name + " and I am " + color + ".")
+  }
+}
+
+ + +

Values are passed to the constructor like so:

+
new Unicorn("Flicker", "purple")
+
+ + +

Like other methods, you can overload constructors by arity.

+

Fields #

+

All state stored in instances is stored in fields. Each field has a named +that starts with an underscore.

+
class Rectangle {
+  area { _width * _height }
+
+  // Other stuff...
+}
+
+ + +

Here, _width and _height in the area getter refer +to fields on the rectangle instance. You can think of them like this.width +and this.height in other languages.

+

When a field name appears, Wren looks for the nearest enclosing class and looks +up the field on the instance of that class. Field names cannot be used outside +of an instance method. They can be used inside a function +in a method. Wren will look outside any nested functions until it finds an +enclosing method.

+

Unlike variables, fields are implicitly declared by simply +assigning to them. If you access a field before it has been initialized, its +value is null.

+

Encapsulation #

+

All fields are protected in Wren—an object's fields can only be +directly accessed from within methods defined on the object's class, or its +superclasses. You cannot even access fields on another instance of your own +class, unlike C++ and Java.

+

If you want to make a property of an object visible, you need to define a +getter to expose it:

+
class Rectangle {
+  width { _width }
+  height { _height }
+
+  // ...
+}
+
+ + +

To allow outside code to modify the field, you'll also need to provide setters:

+
class Rectangle {
+  width=(value) { _width = value }
+  height=(value) { _height = value }
+}
+
+ + +

One thing we've learned in the past forty years of software engineering is that +encapsulating state tends to make code easier to maintain, so Wren defaults to +keeping your object's state pretty tightly bundled up. Don't feel that you have +to or even should define getters or setters for most of your object's fields.

Metaclasses and static members #

TODO

+

Static fields #

+

A name that starts with two underscores is a static field. They work +similar to fields except the data is stored on the class itself, and +not the instance. They can be used in both instance and static methods.

+

TODO: Example.

Inheritance #

-

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 which all other classes ultimately descend. You can specify a different parent class using is when you declare the class:

+

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 +which all other classes ultimately descend. You can specify a different parent +class using is when you declare the class:

class Pegasus is Unicorn {}
 

This declares a new class Pegasus that inherits from Unicorn.

-

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.

+

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.

class Unicorn {
   // Unicorns cannot fly. :(
   static canFly { false }
@@ -188,7 +278,9 @@ Even true and false are full-featured objects—in
 
-

Constructors, however, initialize the instance after it has been created. They are defined as instance methods on the class and not on the metaclass. That means that constructors are inherited.

+

Constructors, however, initialize the instance after it has been created. +They are defined as instance methods on the class and not on the metaclass. +That means that constructors are inherited.

class Unicorn {
   new(name) {
     IO.print("My name is " + name + ".")
@@ -199,11 +291,6 @@ Even true and false are full-featured objects—in
 
 new Pegasus("Fred") // Prints "My name is Fred.".
 
- - -

Superclass method calls #

-

TODO

-

TODO: this