/** This file is part of Shapes. ** ** Shapes is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** any later version. ** ** Shapes is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with Shapes. If not, see . ** ** Copyright 2008, 2010, 2014, 2015 Henrik Tidefelt **/ /** This feature example is named after the reminding concept from Scheme. ** Anyway, "values" refers to the possibility of returning multiple values from a function. However, ** this is not done the way it is in Scheme, where a bunch of values can only be returned through ** certain continuations. Here, multiple values are combined in one value which we denote a "structure" ** (which can be given a composite type) and special constructs are used to use a structure in function calls or to ** bind the contained values to variables. **/ ##lookin ..Shapes /** In the first example, some values are simply put in a certain order. **/ { multi: \ x → (> x x+1 x+2 <) user: \ a1 a2 a3 → 100*a1 + 10*a2 + a3 /** Note the special syntax used to call a function with the values expanded: **/ IO..•stdout << user [] <>[multi 5] << "{n} } /** In the next example, some values are simply put in a certain order, and we combine this ** with an evaluated cut. **/ { multi: \ x → (> x a3:x+1 a2:x+2 <) user: \ a1 a2 a3 a4 → 1000*a4 + 100*a1 + 10*a2 + a3 IO..•stdout << user [...] <>[multi 5] [] 9<< "{n} } /** Here, we show how to also pass states to a function, and also that the structure with values need ** not be returned from a function, but can be created anywhere. Also, it is shown how named parts ** can be accessed using field access notation. **/ { bunch: (> 6 a3:7 a2:8 <) user: \ •dst a1 a2 a3 → { •dst << 100*a1 + 10*a2 + a3 << "{n} } [(user [...] <>bunch) IO..•stdout ] /** The following syntax might be supported in the future. For now, ** it is considered a risk of ambiguity to mix the two forms of ** function application. **/ |** [user IO..•stdout <>bunch] IO..•stdout << `Field access: a2 = ´ << bunch.a2 << "{n} /** By the way, parts that are not named cannot be accessed in a similar way. However, ** note that we can always to this: **/ IO..•stdout << `The first argument is: a1 = ´ << ( \ a1 a2 a3 → a1 ) [] <>bunch << "{n} /** ... but note that this requires that we know the names of the named parts of , for ** otherwise there will be an error when the function is applied. **/ } /** Like in (lambda args ) construct in Scheme, we can define a function that gets just a structure as argument. ** There's also a construct that corresponds to (lambda ( . moreargs) ). ** In Shapes, the construct is called a "sink". Note that functions with a sink may be tricky from a type system point ** of view, so code that wish to be type-compilant should not use sinks. **/ { foo: \ •out <> args → { •out << `a = ´ << args.a << `, b = ´ << args.b << "{n} } [foo IO..•stdout b:2 a:1] bar: \ •out a <> args → { •out << `a = ´ << a << `, b = ´ << args.b << `, c = ´ << args.c << "{n} } [bar IO..•stdout 0 c:2 b:1] /** Sinks themselves cannot be passed as a named argument. Hence, the name of the sink can be used without ** confusion: **/ boo: \ •out <> args → { •out << `args = ´ << args.args << "{n} } [boo IO..•stdout args:7] } /** Next, we turn to how parts of a structure can conveniently be given names in the local scope. ** The semantics remind a little bit of function calls, but are actually rather different. **/ { { /** We begin with a structure with only ordered parts. **/ bunch: (> 6 7 8 <) { /** Just like in a function call, we can receive the parts of a structure by order: **/ (< x y z >): bunch IO..•stdout << `x = ´ << x << `, y = ´ << y << `, z = ´ << z << "{n} } { /** It is an error to not take care of all ordered parts. The following would result in an error. **/ |** (< x y >): bunch /** Unless we have a sink! **/ (< x y <> rest >): bunch (< z >): rest IO..•stdout << `From the sink, z = ´ << z << "{n} } { /** On the other hand, we can provide defaults if there are not enough ordered parts: **/ (< x y z w:14 >): bunch IO..•stdout << `w = ´ << w << "{n} } } { /** When it comes to named parts of a structure, there are some differences to the semantics of calling ** a function. First, it is not required that all named parts are received. This makes it possible to ** extract only the parts of a structure with are useful, and avoids cluttering the destination scope with ** variables of no use. ** Second, the variables being introduced in the current scope are generally named different from the ** names bound to the values in the structure. **/ bunch: (> a1:6 a3:7 a2:8 <) { /** Here is a typical extraction of two named parts. Note that without the dot before the names ** that refer to parts of the structure, this would be the syntax that specifies a default values. **/ (< x:.a1 y:.a2 >): bunch IO..•stdout << `x = ´ << x << `, y = ´ << y << "{n} } { /** To receive the parts by their own names, the following syntax may be thought of (and implemented) ** as a low level syntax sugar. **/ (< a2:." a3:." >): bunch IO..•stdout << `a2 = ´ << a2 << `, a3 = ´ << a3 << "{n} } { /** Defaults can be provided. **/ def: 1000 (< a2:." a4:.":def >): bunch IO..•stdout << `a2 = ´ << a2 << `, a4 = ´ << a4 << "{n} } } { /** Ordered and named parts can be used at the same time, as shown by these examples. However, it sould ** be noted that they cannot interact, so there are no fancy combinations to be explained here. **/ bunch: (> 6 a3:7 a2:8 <) { (< x y:.a2 a3:." >): bunch IO..•stdout << `x = ´ << x << `, y = ´ << y << `, a3 = ´ << a3 << "{n} } { (< x y:1000 >): bunch IO..•stdout << `x = ´ << x << `, y = ´ << y << "{n} } } } /** Let us also have a look at the function here. **/ { /** To see the relevance of discussing here, note that we may define a Scheme-like ** function like this: **/ apply: \ fun args → ( fun [] <>[Data..unlist args] ) IO..•stdout << `Using apply to compute the sum of two values: ´ << [apply (+) [Data..list 4 5]] << "{n} /** Let us now verify that it is the inverse of in the following senses: **/ lst: [Data..list 1 2 3] showList: \ lst → [lst.foldl \ p e → ( p + ( String..newString << `(´ << e << `)´ ) ) `´] IO..•stdout << [showList lst] << ` vs ´ << [showList ( Data..list [] <>[Data..unlist lst] )] << "{n} struct: (> 'a 'b 'c <) showStruct: \ struct → (( \ x y z → ( String..newString << `(´ << x << `)´ << `(´ << y << `)´ << `(´ << z << `)´ )) [] <>struct) IO..•stdout << [showStruct struct] << ` vs ´ << [showStruct [Data..unlist ( Data..list [] <>struct )]] << "{n} }