1 /** This file is part of Shapes.
3 ** Shapes is free software: you can redistribute it and/or modify
4 ** it under the terms of the GNU General Public License as published by
5 ** the Free Software Foundation, either version 3 of the License, or
8 ** Shapes is distributed in the hope that it will be useful,
9 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 ** GNU General Public License for more details.
13 ** You should have received a copy of the GNU General Public License
14 ** along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 ** Copyright 2008, 2010, 2014, 2015 Henrik Tidefelt
19 /** This feature example is named after the reminding concept from Scheme.
20 ** Anyway, "values" refers to the possibility of returning multiple values from a function. However,
21 ** this is not done the way it is in Scheme, where a bunch of values can only be returned through
22 ** certain continuations. Here, multiple values are combined in one value which we denote a "structure"
23 ** (which can be given a composite type) and special constructs are used to use a structure in function calls or to
24 ** bind the contained values to variables.
29 /** In the first example, some values are simply put in a certain order.
32 multi: \ x → (> x x+1 x+2 <)
34 user: \ a1 a2 a3 → 100*a1 + 10*a2 + a3
36 /** Note the special syntax used to call a function with the values expanded:
38 IO..•stdout << user [] <>[multi 5] << "{n}
41 /** In the next example, some values are simply put in a certain order, and we combine this
42 ** with an evaluated cut.
45 multi: \ x → (> x a3:x+1 a2:x+2 <)
47 user: \ a1 a2 a3 a4 → 1000*a4 + 100*a1 + 10*a2 + a3
49 IO..•stdout << user [...] <>[multi 5] [] 9<< "{n}
53 /** Here, we show how to also pass states to a function, and also that the structure with values need
54 ** not be returned from a function, but can be created anywhere. Also, it is shown how named parts
55 ** can be accessed using field access notation.
58 bunch: (> 6 a3:7 a2:8 <)
60 user: \ •dst a1 a2 a3 →
62 •dst << 100*a1 + 10*a2 + a3 << "{n}
64 [(user [...] <>bunch) IO..•stdout ]
66 /** The following syntax might be supported in the future. For now,
67 ** it is considered a risk of ambiguity to mix the two forms of
68 ** function application.
70 |** [user IO..•stdout <>bunch]
72 IO..•stdout << `Field access: a2 = ´ << bunch.a2 << "{n}
73 /** By the way, parts that are not named cannot be accessed in a similar way. However,
74 ** note that we can always to this:
76 IO..•stdout << `The first argument is: a1 = ´ << ( \ a1 a2 a3 → a1 ) [] <>bunch << "{n}
77 /** ... but note that this requires that we know the names of the named parts of <bunch>, for
78 ** otherwise there will be an error when the function is applied.
83 /** Like in (lambda args <body>) construct in Scheme, we can define a function that gets just a structure as argument.
84 ** There's also a construct that corresponds to (lambda (<arglist> . moreargs) <body>).
85 ** In Shapes, the construct is called a "sink". Note that functions with a sink may be tricky from a type system point
86 ** of view, so code that wish to be type-compilant should not use sinks.
91 •out << `a = ´ << args.a << `, b = ´ << args.b << "{n}
94 [foo IO..•stdout b:2 a:1]
96 bar: \ •out a <> args →
98 •out << `a = ´ << a << `, b = ´ << args.b << `, c = ´ << args.c << "{n}
101 [bar IO..•stdout 0 c:2 b:1]
104 /** Sinks themselves cannot be passed as a named argument. Hence, the name of the sink can be used without
108 boo: \ •out <> args →
110 •out << `args = ´ << args.args << "{n}
113 [boo IO..•stdout args:7]
116 /** Next, we turn to how parts of a structure can conveniently be given names in the local scope.
117 ** The semantics remind a little bit of function calls, but are actually rather different.
122 /** We begin with a structure with only ordered parts.
127 /** Just like in a function call, we can receive the parts of a structure by order:
130 IO..•stdout << `x = ´ << x << `, y = ´ << y << `, z = ´ << z << "{n}
134 /** It is an error to not take care of all ordered parts. The following would result in an error.
138 /** Unless we have a sink!
140 (< x y <> rest >): bunch
142 IO..•stdout << `From the sink, z = ´ << z << "{n}
146 /** On the other hand, we can provide defaults if there are not enough ordered parts:
148 (< x y z w:14 >): bunch
150 IO..•stdout << `w = ´ << w << "{n}
156 /** When it comes to named parts of a structure, there are some differences to the semantics of calling
157 ** a function. First, it is not required that all named parts are received. This makes it possible to
158 ** extract only the parts of a structure with are useful, and avoids cluttering the destination scope with
159 ** variables of no use.
160 ** Second, the variables being introduced in the current scope are generally named different from the
161 ** names bound to the values in the structure.
163 bunch: (> a1:6 a3:7 a2:8 <)
166 /** Here is a typical extraction of two named parts. Note that without the dot before the names
167 ** that refer to parts of the structure, this would be the syntax that specifies a default values.
174 IO..•stdout << `x = ´ << x << `, y = ´ << y << "{n}
178 /** To receive the parts by their own names, the following syntax may be thought of (and implemented)
179 ** as a low level syntax sugar.
181 (< a2:." a3:." >): bunch
182 IO..•stdout << `a2 = ´ << a2 << `, a3 = ´ << a3 << "{n}
186 /** Defaults can be provided.
189 (< a2:." a4:.":def >): bunch
190 IO..•stdout << `a2 = ´ << a2 << `, a4 = ´ << a4 << "{n}
195 /** Ordered and named parts can be used at the same time, as shown by these examples. However, it sould
196 ** be noted that they cannot interact, so there are no fancy combinations to be explained here.
199 bunch: (> 6 a3:7 a2:8 <)
202 (< x y:.a2 a3:." >): bunch
203 IO..•stdout << `x = ´ << x << `, y = ´ << y << `, a3 = ´ << a3 << "{n}
207 (< x y:1000 >): bunch
208 IO..•stdout << `x = ´ << x << `, y = ´ << y << "{n}
216 /** Let us also have a look at the <unlist> function here.
219 /** To see the relevance of discussing <unlist> here, note that we may define a Scheme-like <apply>
220 ** function like this:
222 apply: \ fun args → ( fun [] <>[Data..unlist args] )
224 IO..•stdout << `Using apply to compute the sum of two values: ´ << [apply (+) [Data..list 4 5]] << "{n}
226 /** Let us now verify that it is the inverse of <list> in the following senses:
228 lst: [Data..list 1 2 3]
229 showList: \ lst → [lst.foldl \ p e → ( p + ( String..newString << `(´ << e << `)´ ) ) `´]
230 IO..•stdout << [showList lst] << ` vs ´ << [showList ( list [] <>[Data..unlist lst] )] << "{n}
232 struct: (> 'a 'b 'c <)
233 showStruct: \ struct → (( \ x y z → ( String..newString << `(´ << x << `)´ << `(´ << y << `)´ << `(´ << z << `)´ )) [] <>struct)
234 IO..•stdout << [showStruct struct] << ` vs ´ << [showStruct [Data..unlist ( Data..list [] <>struct )]] << "{n}