Updating documentation and examples with new core namespaces
[shapes.git] / examples / features / values.blank
blobd63a18f72dd2340ca17f7138615cf39af83076b5
1 /** This file is part of Shapes.
2  **
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
6  ** any later version.
7  **
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.
12  **
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/>.
15  **
16  ** Copyright 2008, 2010, 2014, 2015 Henrik Tidefelt
17  **/
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.
25  **/
27 ##lookin ..Shapes
29 /** In the first example, some values are simply put in a certain order.
30  **/
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:
37    **/
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.
43  **/
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.
56  **/
58   bunch: (>  6  a3:7  a2:8  <)
60   user: \ •dst a1 a2 a3 →
61     {
62       •dst << 100*a1 + 10*a2 + a3 << "{n}
63     }
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.
69    **/
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:
75    **/
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.
79    **/
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.
87  **/
89   foo: \ •out <> args →
90   {
91     •out << `a = ´ << args.a << `, b = ´ << args.b << "{n}
92   }
94   [foo IO..•stdout b:2 a:1]
96   bar: \ •out a <> args →
97   {
98     •out << `a = ´ << a << `, b = ´ << args.b << `, c = ´ << args.c << "{n}
99   }
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
105    ** confusion:
106    **/
108   boo: \ •out <> args →
109   {
110     •out << `args = ´ << args.args << "{n}
111   }
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.
118  **/
121   {
122     /** We begin with a structure with only ordered parts.
123      **/
124     bunch: (>  6  7  8  <)
126     {
127       /** Just like in a function call, we can receive the parts of a structure by order:
128        **/
129       (< x y z >): bunch
130       IO..•stdout << `x = ´ << x << `, y = ´ << y << `, z = ´ << z << "{n}
131     }
133     {
134       /** It is an error to not take care of all ordered parts.  The following would result in an error.
135        **/
136 |**      (< x y >): bunch
138       /** Unless we have a sink!
139        **/
140       (< x y <> rest >): bunch
141       (< z >): rest
142       IO..•stdout << `From the sink, z = ´ << z << "{n}
143     }
145     {
146       /** On the other hand, we can provide defaults if there are not enough ordered parts:
147        **/
148       (< x y z w:14 >): bunch
150       IO..•stdout << `w = ´ << w << "{n}
151     }
153   }
155   {
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.
162      **/
163     bunch: (>  a1:6  a3:7  a2:8  <)
165     {
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.
168        **/
169       (<
170         x:.a1
171         y:.a2
172       >): bunch
174       IO..•stdout << `x = ´ << x  << `, y = ´ << y << "{n}
175     }
177     {
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.
180        **/
181       (< a2:." a3:." >): bunch
182       IO..•stdout << `a2 = ´ << a2 << `, a3 = ´ << a3 << "{n}
183     }
185     {
186       /** Defaults can be provided.
187        **/
188       def: 1000
189       (< a2:." a4:.":def >): bunch
190       IO..•stdout << `a2 = ´ << a2 << `, a4 = ´ << a4 << "{n}
191     }
192   }
194   {
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.
197      **/
199     bunch: (>  6  a3:7  a2:8  <)
201     {
202       (<  x  y:.a2  a3:."  >): bunch
203       IO..•stdout << `x = ´ << x << `, y = ´ << y << `, a3 = ´ << a3 << "{n}
204     }
206     {
207       (<  x  y:1000 >): bunch
208       IO..•stdout << `x = ´ << x << `, y = ´ << y << "{n}
209     }
211   }
216 /** Let us also have a look at the <unlist> function here.
217  **/
219   /** To see the relevance of discussing <unlist> here, note that we may define a Scheme-like <apply>
220    ** function like this:
221    **/
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:
227    **/
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}