/** 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}
}