194 lines
5.9 KiB
Text
194 lines
5.9 KiB
Text
|
title:: Syntax Shortcuts
|
||
|
summary:: syntactic sugar
|
||
|
categories:: Language
|
||
|
related:: Overviews/SymbolicNotations
|
||
|
|
||
|
section:: Introduction
|
||
|
|
||
|
This file shows a number of syntax equivalences in the compiler.
|
||
|
|
||
|
Because of the multiple syntax equivalences, some expressions can be written in many different ways. All of the following do the same thing and compile to the same code.
|
||
|
code::
|
||
|
// new argument syntax
|
||
|
|
||
|
(1..10).collect({|n| n.squared }); // receiver syntax
|
||
|
collect((1..10), {|n| n.squared }); // function call syntax
|
||
|
(1..10).collect {|n| n.squared }; // receiver syntax with trailing function arg
|
||
|
collect ((1..10)) {|n| n.squared }; // function call syntax with trailing function arg
|
||
|
(1..10) collect: {|n| n.squared }; // binary operator syntax
|
||
|
|
||
|
|
||
|
// old argument syntax
|
||
|
|
||
|
(1..10).collect({ arg n; n.squared }); // receiver syntax
|
||
|
collect((1..10), { arg n; n.squared }); // function call syntax
|
||
|
(1..10).collect { arg n; n.squared }; // receiver syntax with trailing function arg
|
||
|
collect ((1..10)) { arg n; n.squared }; // function call syntax with trailing function arg
|
||
|
(1..10) collect: { arg n; n.squared }; // binary operator syntax
|
||
|
|
||
|
|
||
|
// partial application syntax
|
||
|
|
||
|
(1..10).collect( _.squared ); // receiver syntax
|
||
|
collect((1..10), _.squared ); // function call syntax
|
||
|
(1..10) collect: _.squared ; // binary operator syntax
|
||
|
::
|
||
|
|
||
|
You could even start expanding out the equivalent of (1..10) which is really a shortcut for code:: series(1, nil, 10) ::. This could also be written code:: 1.series(nil,10) ::. This adds another 26 variations to the 13 variations above.
|
||
|
|
||
|
section:: Objects, functions, messages and arguments
|
||
|
|
||
|
subsection:: functional and receiver notation
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: f(x, y) :: || code:: x.f(y) ::
|
||
|
## code:: f(g(x)) :: || code:: x.g.f ::
|
||
|
::
|
||
|
|
||
|
subsection:: defining instance variable accessor methods
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code::
|
||
|
Thing { var x;
|
||
|
x { ^x }
|
||
|
x_ { arg z; x = z; }
|
||
|
}
|
||
|
:: || code:: Thing { var <>x; } ::
|
||
|
::
|
||
|
|
||
|
subsection:: calling an instance variable setter method
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: p.x_(y) :: || code:: p.x = y :: or code:: x(p) = y ::
|
||
|
::
|
||
|
|
||
|
subsection:: use a selector as binary operator
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: min(x, y) :: || code:: x min: y ::
|
||
|
::
|
||
|
|
||
|
subsection:: instantiate object
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: Point.new(3, 4); :: || code:: Point(3, 4) ::
|
||
|
::
|
||
|
|
||
|
subsection:: moving blocks out of argument lists
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: if (x<3, {\abc}, {\def}); :: || code:: if (x<3) {\abc} {\def} ::
|
||
|
## code:: z.do({|x| x.play }); :: || code:: z.do {|x| x.play }; ::
|
||
|
## code:: while({ a < b },{ a = a * 2 }); :: || code:: while { a < b } { a = a * 2 }; ::
|
||
|
::
|
||
|
|
||
|
subsection:: shorter argument lists
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: { arg x; x < 2 } :: || code:: {|x| x < 2 } ::
|
||
|
## code:: { arg x = 123; x < 2 } :: || code:: {|x = 123| x < 2 } ::
|
||
|
## code:: { arg x = 10.rand; x < 2 } :: || code:: {|x = (10.rand)| x < 2 } :: or code:: {|x(10.rand)| x < 2 } ::
|
||
|
::
|
||
|
note::
|
||
|
When using the new code::||:: syntax, the default value needs to be enclosed in parenthesis if it's not a literal.
|
||
|
::
|
||
|
|
||
|
subsection:: calling the 'value' method
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: f.value(x) :: || code:: f.(x) ::
|
||
|
::
|
||
|
|
||
|
subsection:: calling performList
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: object.performList(\method, a, b, array) :: || code:: object.method(a, b, *array) ::
|
||
|
::
|
||
|
|
||
|
subsection:: partial application
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: {|x| object.msg(a, x, b) } :: || code:: object.msg(a, _, b) ::
|
||
|
## code:: {|x,y| object.msg(a, x, y) } :: || code:: object.msg(a, _, _) ::
|
||
|
## code:: {|x| a + x } :: || code:: a + _ ::
|
||
|
## code:: {|x| [a, b, x] } :: || code:: [a, b, _] ::
|
||
|
## code:: {|x| (a: x) } :: || code:: (a: _) ::
|
||
|
::
|
||
|
|
||
|
|
||
|
section:: Collections
|
||
|
|
||
|
subsection:: create a collection
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: Set.new.add(3).add(4).add(5); :: || code:: Set[3, 4, 5] ::
|
||
|
## code:: Array[3, 4, 5]; :: || code:: [3, 4, 5] ::
|
||
|
::
|
||
|
|
||
|
subsection:: indexing elements
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: z.at(i) :: || code:: z[i] ::
|
||
|
## code:: z.put(i, y); :: || code:: z[i] = y; ::
|
||
|
::
|
||
|
|
||
|
subsection:: creating Events
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: Event[\a -> 1, \b -> 2] :: || code:: (a: 1, b: 2) ::
|
||
|
::
|
||
|
|
||
|
subsection:: creating Arrays with key-value pairs
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: [\a, 1, \b, 2] :: || code:: [a: 1, b: 2] ::
|
||
|
::
|
||
|
|
||
|
subsection:: creating arithmetic series
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: Array.series(16,1,1) :: or code:: series(1,nil,16) :: || code:: (1..16) ::
|
||
|
## code:: Array.series(6,1,2) :: or code:: series(1,3,11) :: || code:: (1,3..11) ::
|
||
|
::
|
||
|
There is also the similar syntax for creating an iterating link::Classes/Routine:: :
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: seriesIter(1,3,11) :: || code:: (:1,3..11) ::
|
||
|
::
|
||
|
|
||
|
subsection:: accessing subranges of Arrays
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: a.copyRange(4,8) :: || code:: a[4..8] ::
|
||
|
## code:: a.copyToEnd(4) :: || code:: a[4..] ::
|
||
|
## code:: a.copyFromStart(4) :: || code:: a[..4] ::
|
||
|
::
|
||
|
|
||
|
section:: Other shortcuts
|
||
|
|
||
|
subsection:: multiple assignment
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: x = z.at(0); y = z.at(1); :: || code:: # x, y = z; ::
|
||
|
::
|
||
|
|
||
|
subsection:: accessing environment variables
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: 'myName'.envirGet :: || code:: ~myName ::
|
||
|
## code:: 'myName'.envirSet(9); :: || code:: ~myName = 9; ::
|
||
|
::
|
||
|
|
||
|
subsection:: shorthand for Symbols
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: 'mySymbol' :: || code:: \mySymbol ::
|
||
|
::
|
||
|
|
||
|
subsection:: creating a Ref
|
||
|
table::
|
||
|
## instead of writing: || you can write:
|
||
|
## code:: Ref.new(thing) :: || code:: `thing ::
|
||
|
::
|
||
|
|