doc: add statement separators and one-line message handler support
This commit is contained in:
@@ -48,51 +48,36 @@ class Person
|
||||
compatibility with lambdas.
|
||||
**/
|
||||
- init(name:name age:age)
|
||||
self.name = name
|
||||
self.age = age
|
||||
end
|
||||
self::name = name.
|
||||
self::age = age.
|
||||
|
||||
- test(param:data _:extra)
|
||||
cout put:'Received {data}, {extra}'
|
||||
end
|
||||
- test(param:data _:extra) | cout put:'Received {data}, {extra}'.
|
||||
|
||||
- name
|
||||
^self.name
|
||||
end
|
||||
- name | ^self::name.
|
||||
|
||||
- age
|
||||
^self.age
|
||||
end
|
||||
- age | ^self::age.
|
||||
|
||||
- ageInMonths
|
||||
^self.age * 12
|
||||
end
|
||||
- ageInMonths | ^self::age * 12.
|
||||
|
||||
- setName:name
|
||||
self.name = name
|
||||
end
|
||||
- setName:name | self::name = name.
|
||||
|
||||
- setAge:age
|
||||
self.age = age
|
||||
end
|
||||
- setAge:age | self::age = age.
|
||||
|
||||
- setAge:age inUnit:units
|
||||
match units in
|
||||
#years => self.age = age,
|
||||
#months => self.age = age / 12,
|
||||
#days => self.age = age / 365,
|
||||
_ => self.age = 0,
|
||||
end
|
||||
end
|
||||
#years => self::age = age,
|
||||
#months => self::age = age / 12,
|
||||
#days => self::age = age / 365,
|
||||
_ => self::age = 0,
|
||||
end.
|
||||
|
||||
- getAgeInUnit:units
|
||||
^match units in
|
||||
#years => self.age,
|
||||
#months => self.age / 12,
|
||||
#days => self.age / 365,
|
||||
#years => self::age,
|
||||
#months => self::age / 12,
|
||||
#days => self::age / 365,
|
||||
_ => 0,
|
||||
end
|
||||
end
|
||||
end.
|
||||
|
||||
/* Properties are defined using the $ symbol.
|
||||
They accomplish two things:
|
||||
@@ -120,16 +105,14 @@ class Person
|
||||
*/
|
||||
$ exampleProperty
|
||||
get => self.val,
|
||||
set => self.val = value
|
||||
end
|
||||
set => self.val = value.
|
||||
|
||||
/* Without the lambda synthesis, the property would look like this:
|
||||
Note that this is the only time it is legal to access private fields
|
||||
via `self` from a lambda. */
|
||||
$ exampleProperty
|
||||
get => [ ^self.val ],
|
||||
set => [ :x | self.val = x ]
|
||||
end
|
||||
set => [ :x | self.val = x ].
|
||||
|
||||
/* The `get` element of a property doesn't have to be a lambda, it can
|
||||
be any value. When the property is accessed, the value provided will
|
||||
@@ -138,8 +121,7 @@ class Person
|
||||
If either the `set` or `get` elements are not provided, the property
|
||||
becomes read-only or write-only respectively */
|
||||
$ exampleProperty2
|
||||
get => 42
|
||||
end
|
||||
get => 42.
|
||||
|
||||
/* A property can also be configured to act just like a regular variable,
|
||||
by setting the getter and setters to default implementations.
|
||||
@@ -158,8 +140,8 @@ class Person
|
||||
$ exampleProperty4 (get)
|
||||
end
|
||||
|
||||
p1 = Person new(name:'John Doe' age:34)
|
||||
p1 setAge:100 inUnit:#months
|
||||
p1 = Person new(name:'John Doe' age:34).
|
||||
p1 setAge:100 inUnit:#months.
|
||||
|
||||
|
||||
/**
|
||||
@@ -167,13 +149,13 @@ p1 setAge:100 inUnit:#months
|
||||
still required. this is part of the reason why unlabeled parameters are
|
||||
weird and not recommended.
|
||||
**/
|
||||
p1 test(param:'Hello' :'World')
|
||||
p1 test(param:'Hello' :'World').
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
i = 0
|
||||
i = 0.
|
||||
while i < 100 do
|
||||
cout put:'Count is {i}'
|
||||
cout put:'Count is {i}'.
|
||||
i += 2
|
||||
end
|
||||
|
||||
@@ -185,7 +167,7 @@ end
|
||||
a lambda's parameters are *always* unlabeled, and the underscore (_) before
|
||||
the label colon (:) is unnecessary.
|
||||
**/
|
||||
0 to:100 step:2 do:[ :i | cout put:'Count: {i}' ]
|
||||
0 to:100 step:2 do:[ :i | cout put:'Count: {i}' ].
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -206,14 +188,14 @@ end
|
||||
safe for a method to return a lambda that references variables in its
|
||||
local context.
|
||||
**/
|
||||
q = 32
|
||||
l = [ cout put:'Value of q is {q}' ] /* value of `q` is captured here */
|
||||
q = 64
|
||||
_ = l call /* prints 'Value of q is 32' */
|
||||
q = 32.
|
||||
l = [ cout put:'Value of q is {q}' ]. /* value of `q` is captured here */
|
||||
q = 64.
|
||||
_ = l call. /* prints 'Value of q is 32' */
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
j = 32
|
||||
j = 32.
|
||||
|
||||
/**
|
||||
expressions are terminated with a newline.
|
||||
@@ -229,7 +211,7 @@ j = 32
|
||||
|
||||
i < j
|
||||
if:[ cout put:'True!' ]
|
||||
else:[ cout put:'False!' ]
|
||||
else:[ cout put:'False!' ].
|
||||
|
||||
if i < j then
|
||||
cout put:'True!'
|
||||
@@ -237,21 +219,21 @@ end
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
pkg = {}
|
||||
pkg = {}.
|
||||
|
||||
/**
|
||||
Packages can be indexed via integer or string. If a package is index with a
|
||||
variable, the value of the variable is used as the index.
|
||||
**/
|
||||
|
||||
pkg[0] = 16
|
||||
pkg[0] = 16.
|
||||
|
||||
/* All of these accesses are equivalent */
|
||||
pkg['x'] = 32
|
||||
pkg.x = 32
|
||||
pkg['x'] = 32.
|
||||
pkg->x = 32.
|
||||
|
||||
index = 'x'
|
||||
pkg[index] = 32
|
||||
index = 'x'.
|
||||
pkg[index] = 32.
|
||||
|
||||
/**
|
||||
this syntax, and the pkg.* instructions that it translates to, is
|
||||
@@ -270,15 +252,15 @@ pkg[index] = 32
|
||||
/******************************************************************************/
|
||||
|
||||
/* integer constants can be written in all sorts of interesting formats */
|
||||
i = 100
|
||||
i = 0x100
|
||||
i = 0200
|
||||
i = 0b1010101
|
||||
i = 1_000_000_000
|
||||
i = 100.
|
||||
i = 0x100.
|
||||
i = 0200.
|
||||
i = 0b1010101.
|
||||
i = 1_000_000_000.
|
||||
|
||||
/* tuples can be used to create a set of values */
|
||||
|
||||
tuple = (32, 'a string')
|
||||
tuple = (32, 'a string').
|
||||
|
||||
/**
|
||||
they are similar to packages, except they only support consecutive integer
|
||||
@@ -308,12 +290,12 @@ end
|
||||
it can only appear on the left of an assignment, and anything
|
||||
assigned to it is discarded.
|
||||
*/
|
||||
_ = 3 * 2
|
||||
_ = 3 * 2.
|
||||
|
||||
/* it is mostly used with pattern-matching and destructuring. */
|
||||
|
||||
a = (32, 64)
|
||||
(_, v) = a
|
||||
a = (32, 64).
|
||||
(_, v) = a.
|
||||
|
||||
/* v is now equal to 64 */
|
||||
|
||||
@@ -360,7 +342,7 @@ end
|
||||
onError:[ :err |
|
||||
cout put:'Unknown error occurred ({err msg})'
|
||||
];
|
||||
call
|
||||
call.
|
||||
|
||||
/**
|
||||
this example doesn't meet any of the conditions required for implicit
|
||||
@@ -375,7 +357,7 @@ end
|
||||
v = 5
|
||||
squared
|
||||
squared
|
||||
squared
|
||||
squared.
|
||||
|
||||
/**
|
||||
below are some examples of throwing errors. when an error is thrown,
|
||||
@@ -397,22 +379,22 @@ v = 5
|
||||
**/
|
||||
|
||||
/* example 1) */
|
||||
throw 'an error occurred')
|
||||
throw 'an error occurred'.
|
||||
|
||||
/* example 2) */
|
||||
throw { i => 32, s => 'error' }
|
||||
throw { i => 32, s => 'error' }.
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
x = 32
|
||||
/* a whole bunch of ways of doing conditionals using lambdas and messages */
|
||||
[ cout put:'Hello, world!' ] if:x > 10
|
||||
[ cout put:'Hello, world!' ] unless:x <= 10
|
||||
[ cout put:'Hello, world!' ] if:x > 10.
|
||||
[ cout put:'Hello, world!' ] unless:x <= 10.
|
||||
|
||||
/* and the equivalent 'fancy' syntax */
|
||||
|
||||
cout put:'Hello, world!' if x > 10
|
||||
cout put:'Hello, world!' unless x <= 10
|
||||
cout put:'Hello, world!' if x > 10.
|
||||
cout put:'Hello, world!' unless x <= 10.
|
||||
|
||||
/**
|
||||
NOTE that keywords (if, end, try, and so on) can still be used as message
|
||||
@@ -457,10 +439,10 @@ cout put:'Hello, world!' unless x <= 10
|
||||
|
||||
p1
|
||||
setAge:2 squared squared + 4 squared multiply(by:2 add:4 + 1 * 3)
|
||||
in:'mon' + 'ths'
|
||||
in:'mon' + 'ths'.
|
||||
(p1
|
||||
setAge:(((2 squared) squared) + ((4 squared) multiply(by:2 add:(4 + (1 * 3)))))
|
||||
in:('mon' + 'ths'))
|
||||
in:('mon' + 'ths')).
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -473,8 +455,8 @@ p1
|
||||
the first one uses fancy list/package comprehension syntax.
|
||||
the second one uses pure message/lambda syntax.
|
||||
**/
|
||||
data = { x + 1 for x in 0 to:100 if (x % 2) == 0 }
|
||||
data = (0 to: 100) select:[ :x | ^(x % 2) == 0 ] collect:[ :x | ^x + 1 ]
|
||||
data = { x + 1 for x in 0 to:100 if (x % 2) == 0 }.
|
||||
data = (0 to: 100) select:[ :x | ^(x % 2) == 0 ] collect:[ :x | ^x + 1 ].
|
||||
|
||||
/**
|
||||
for a package comprehension that follows this template:
|
||||
@@ -501,9 +483,9 @@ data = (0 to: 100) select:[ :x | ^(x % 2) == 0 ] collect:[ :x | ^x + 1 ]
|
||||
collection literal, and then uses -map: to create a second package by
|
||||
doubling each of the numbers in the fist package.
|
||||
**/
|
||||
pkg1 = { 1, 2, 3, 4, 5 }
|
||||
pkg2 = { x * 2 for x in pkg1 }
|
||||
pkg2 = pkg1 map:[ :x | ^x * 2 ]
|
||||
pkg1 = { 1, 2, 3, 4, 5 }.
|
||||
pkg2 = { x * 2 for x in pkg1 }.
|
||||
pkg2 = pkg1 map:[ :x | ^x * 2 ].
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -514,15 +496,15 @@ pkg2 = pkg1 map:[ :x | ^x * 2 ]
|
||||
**/
|
||||
|
||||
age = Person new(name:'John Doe' age:34);
|
||||
setAge:144 inUnit:TimeUnit.MONTHS;
|
||||
ageInMonths
|
||||
setAge:144 inUnit:#months;
|
||||
ageInMonths.
|
||||
|
||||
-- age now has the value 144
|
||||
-- the same behaviour can be achieved by using do..end
|
||||
|
||||
age = do
|
||||
x = Person new(name:'John Doe' age:34)
|
||||
x setAge:144 inUnit:TimeUnit.MONTHS
|
||||
x = Person new(name:'John Doe' age:34).
|
||||
x setAge:144 inUnit:#months.
|
||||
x ageInMonths
|
||||
end
|
||||
|
||||
@@ -545,17 +527,17 @@ end
|
||||
**/
|
||||
|
||||
p1 = Person new(name:'John Doe' age:34);
|
||||
setAge:100 inUnit:TimeUnit.MONTHS;
|
||||
yourself
|
||||
setAge:100 inUnit:#months;
|
||||
yourself.
|
||||
|
||||
/* p1 now contains the Person object */
|
||||
/* again, with do..end */
|
||||
|
||||
p1 = do
|
||||
x = Person new(name:'John Doe' age:34)
|
||||
x setAge:100 inUnit:TimeUnit.MONTHS
|
||||
x = Person new(name:'John Doe' age:34).
|
||||
x setAge:100 inUnit:#months.
|
||||
x
|
||||
end
|
||||
end.
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -570,10 +552,10 @@ end
|
||||
the block as a whole evaluates to. also, the result of the last expression
|
||||
evaluated in a block will be taken as its overall value. */
|
||||
val = do
|
||||
x = 3
|
||||
y = 2
|
||||
x = 3.
|
||||
y = 2.
|
||||
x * y
|
||||
end
|
||||
end.
|
||||
|
||||
/* after this statement is executed, `val` will be equal to 6. */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user