-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFunctions.t2t
167 lines (130 loc) · 5.82 KB
/
Functions.t2t
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
Functions
%!includeconf: config.t2t
== Basic ==
A function takes a tuple of values and returns a tuple of values. A function
is a block bound to a name.
== Declaration ==
```
[[ (uint16, uint16) split ( i:uint32 ):
return ( i >> 16, i & 0xFFFF );
]]
// inside a function only
var makeBigger = [[(real v); v + 1.43 ]]; // return type is inferred to be real.
```
The first thing inside the delimiter is the function signature. It is optinal and
ends with a colon. The colon is not nessary if it is omitted.
To the left side of the function name is the return tuple. The name can begin
with any alphabetic character or an underscore and contain any alphanumeric
characters as well as underscores. The name can be ignored if the function is
being used (assigned to a delegate or passed to a function). Anonymous functions
may also omit the arguments and return tuples in which case the return types
will be inferred and the function will take no arguments. If there is one tuple
present it will be assumed to be the arguments. If an anonymous function is
being created inside the argument list of a function the types of the arguments
may be omitted and they will be the types that the parameter specifies in it's
definition.
A function will return the value of the last statement executed. If you wish to
return a value earlier you can use a return statement. The return statement
will return the values passed to it.
=== Blocks ===
Blocks are similar to functions, the main difference is that blocks have the
added advantage of having access to the scope of the enclosing function. Also
you cannot return from a block. Return statements inside blocks will return
from the enclosing function. Blocks cannot be bound to a name accessable outside
of the function they are declared in. Therefore if ``filter`` in the following
example attempts to store the delegate passed to it, this will fail to compile.
The rules for defining blocks are nearly identical to functions except you use
``{`` and ``}`` instead of ``[[`` and ``]]``.
```
set.filter({(i): i % 2 == 0 });
var pivot = 8;
set.filter({(i): i > pivot });
```
=== Default Arguments ===
```
[[ (a:Collection) collectionMin ( a:Collection, min :int = 10 ):
a.map({(i:int): i > min ? i : min });
]]
```
Default arguments are the value that should be passed if an argument is not
specified by the caller. If any argument has a default value all the arguments
to the right of it must also have a default value. Default values may refer to
anything that can be accessed from the location of the function declaration and
any previous arguments.
=== Named return values ===
```
{ (r:String) createString ( in:Collection!String ):
r = ""
in.foreach([[(s:String);
r += s;
]])
}
```
Named return values allow you to use a value inside a function and it will
automatically be returned at the end. The type of a named return value must be
a class. The value will not be initialized. If any return value has a name all
return values to the right of it must also have a name. If you use a return
statement you do not need to provide values for the named items. If the name
of a return value is the same as that of an argument the value will be
initialized with the value passed in.
=== Macros ===
Pool does not have explicit macros but you can use local blocks or functions as
macros.
```
{ @unittest:
[[ (bool) isCloseF(f1:real, f2:real, tol:real = 0.001):
return f1+tol > f2 && f1-tol < f2;
]]
{ (bool) isCloseB(f1:real, f2:real, tol:real = 0.001):
f1+tol > f2 && f1-tol < f2;
}
assert(isCloseF(sin(Pi*0.0, 0)));
assert(isCloseF(sin(Pi*0.5, 0)));
assert(isCloseB(sin(Pi*1.0, 0)));
assert(isCloseB(sin(Pi*1.5, 0)));
}
```
== Calling ==
```
var i = sin(Pi/2);
```
Function calls are similar to most C-style languages. It is the name of the
function followed by a tuple of arguments.
== Getter and Setter Functions ==
Modern programming practices frown upon public variables. This creates many
functions such as ``getValue()`` and ``setValue()``. This causes a lack of
member variables and a waste of beautiful syntax. Pool allows you to write
setters and getters and they can act just like regular variables. This adds
meaning and elegance to code. These are compatiable with regular assignment so
you can start of with public variables and switch them to getters and setters
when you need them and code that uses them will only need a recompile.
```
// If you have this:
public var randomNumber = 4; // chosen by fair dice role.
// guaranteed to be random.
// And you later decide you want an actually random number you can change it
// to this:
var source = RandomGenerator(4);
@property @public [[randomNumber: source.get() ]]
// No setter -- How can you set a random number?
```
The syntax for a getter is the ``@property`` tag, followed by the function
definition. If it does not take any arguments it can be called as a getter.
The syntax for a setter is the ``@property`` tag, followed by the function
definition. It must take arguments. If there are no values in the return tuple
then the assignment can't be used as a right-hand value.
```
var r = randomNumber;
randomNumber = 3; // Error: setter not defined.
```
Although this example is not the best useage of property functions it clearly
illistrates many benifits. When writing property functions it is recommended
that you follow the below guidelines so that your code makes sense to a new
reader.
- Calling the getter multiple times should yield the same result and keep the
object that it was called on semanticaly the same.
- The setter should return the value passed to it.
- Many people will expect that getters are not expensive. It is often a good
idea to cache the values so that repeated calls are cheep.
In general try to use property functions when the function acts like a regular
variable.