Doc: closure example

This commit is contained in:
Celestino Amoroso 2024-09-18 20:48:12 +02:00
parent ba3dbb7f02
commit 778d00677d
2 changed files with 246 additions and 25 deletions

View File

@ -720,6 +720,15 @@ IMPORTANT: If the left variable is NOT defined, the right expression is not eval
`>>>` [blue]`var` +
[green]`3`
`>>>` [blue]`x ?! 5` +
[green]`nil`
`>>>` [blue]`x=1; x ?! 5` +
[green]`5`
`>>>` [blue]`y ?! (c=5); c` +
[red]`Eval Error: undefined variable or function "c"`
NOTE: These operators have a high priority, in particular higher than the operator [blue]`=`.
== Priorities of operators
@ -734,9 +743,10 @@ The table below shows all supported operators by decreasing priorities.
| [blue]`[`...`]` | _Postfix_ | _Dict item_ | _dict_ `[` _any_ `]` -> _any_
.2+|*INC*| [blue]`++` | _Postfix_ | _Post increment_| _integer-variable_ `++` -> _integer_
| [blue]`++` | _Postfix_ | _Next item_ | _iterator_ `++` -> _any_
.2+|*DEFAULT*| [blue]`??` | _Infix_ | _Default value_| _variable_ `??` _any-expr_ -> _any_
.3+|*DEFAULT*| [blue]`??` | _Infix_ | _Default value_| _variable_ `??` _any-expr_ -> _any_
| [blue]`?=` | _Infix_ | _Default/assign value_| _variable_ `?=` _any-expr_ -> _any_
.1+| *ITER*^1^| [blue]`()` | _Prefix_ | _Iterator value_ | `()` _iterator_ -> _any_
| [blue]`?!` | _Infix_ | _Alternate value_| _variable_ `?!` _any-expr_ -> _any_
//.1+| *ITER*^1^| [blue]`()` | _Prefix_ | _Iterator value_ | `()` _iterator_ -> _any_
.1+|*FACT*| [blue]`!` | _Postfix_ | _Factorial_| _integer_ `!` -> _integer_
.3+|*SIGN*| [blue]`+`, [blue]`-` | _Prefix_ | _Change-sign_| (`+`\|`-`) _number_ -> _number_
| [blue]`#` | _Prefix_ | _Lenght-of_ | `#` _collection_ -> _integer_
@ -775,7 +785,7 @@ The table below shows all supported operators by decreasing priorities.
.1+|*RANGE*| [blue]`:` | _Infix_ | _Index-range_ | _integer_ `:` _integer_ -> _integer-pair_
|===
^1^ Experimental
//^1^ Experimental
== Functions
@ -786,25 +796,122 @@ Functions in _Expr_ are very similar to functions available in many programming
=== _Expr_ function definition
A function is identified and referenced by its name. It can have zero or more parameter. _Expr_ functions also support optional parameters.
A function is identified and referenced by its name. It can have zero or more parameter. _Expr_ functions also support optional parameters and passing paramters by name.
.Expr's function definition syntax
====
*_function-definition_* = _identifier_ "**=**" "**func(**" [_param-list_] "**)**" "**{**" _multi-expression_ "**}**" +
_param_list_ = _required-param-list_ [ "**,**" _optional-param-list_ ] +
*_function-definition_* = _identifier_ "**=**" "**func(**" [_formal-param-list_] "**)**" "**{**" _multi-expression_ "**}**" +
_formal-param_list_ = _required-param-list_ [ "**,**" _optional-param-list_ ] +
_required-param-list_ = _identifier_ { "**,**" _identifier_ } +
_optional-param-list_ = _optional-parm_ { "**,**" _optional-param_ } +
_optional-param_ = _identifier_ "**=**" _any-expr_
_optional-param_ = _param-name_ "**=**" _any-expr_ +
_param-name_ = _identifier_
====
.Examples
#TODO#
`>>>` [gray]_// A simple function: it takes two parameters and returns their "sum"_**^(*)^** +
`>>>` [blue]`sum = func(a, b){ a + b }` +
[green]`sum(a, b):any{}`
^(\*)^ Since the plus, *+*, operator is defined for multiple data-types, the _sum()_ function can be used for any pair of that types.
`>>>` [gray]_// A more complex example: recursive calculation of the n-th value of Fibonacci's sequence_ +
`>>>` [blue]`fib = func(n){ n ? [0] {0}: [1] {1} :: {fib(n-1)+fib(n-2)} }` +
[green]`fib(n):any{}`
`>>>` [gray]_// Same function fib() but entered by splitting it over mulple text lines_ +
`>>>` [blue]`fib = func(n){ \` +
`\...` [blue]`{nbsp}{nbsp}n ? \` +
`\...` [blue]`{nbsp}{nbsp}{nbsp}{nbsp}[0] {0} : \` +
`\...` [blue]`{nbsp}{nbsp}{nbsp}{nbsp}[1] {1} :: \` +
`\...` [blue]`{nbsp}{nbsp}{nbsp}{nbsp}{ \` +
`\...` [blue]`{nbsp}{nbsp}{nbsp}{nbsp}{nbsp}{nbsp}fib(n-1) + fib(n-2) \` +
`\...` [blue]`{nbsp}{nbsp}{nbsp}{nbsp}} \` +
`\...` [blue]`}` +
[green]`fib(n):any{}`
`>>>` [gray]_// Required and optional parameters_ +
`>>>` [blue]`measure = func(value, unit="meter"){ value + " " + unit + (value > 1) ? [true] {"s"} :: {""}}` +
[green]`measure(value, unit="meter"):any{}`
=== _Golang_ function definition
Description of how to define Golan functions and how to bind them to _Expr_ are topics treated in another document that I'll write, one day, maybe.
=== Function calls
#TODO: function calls operations#
To call a function, either Expr or Golang type, it is necessary to specify its name and, at least, its required parameters.
.Function invocation syntax
====
*_function-call_* = _identifier_ "**(**" _actual-param-list_ "**)**" +
_actual-param-list_ = [_positional-params_] [_named-parameters_] +
_positional-params_ = _any-value_ { "*,*" _any-value_ } +
_named-params_ = _param-name_ "**=**" _any-value_ { "*,*" _param-name_ "**=**" _any-value_ } +
_param-name_ = _identifier_
====
.Examples of calling the `sum()` functions defined above
`>>>` [gray]_// sum of two integers_ +
`>>>` [blue]`sum(-6, 2)` +
[green]`-4` +
`>>>` [gray]_// same as above but passing the parameters by name_ +
`>>>` [blue]`sum(a=-6, b=2)` +
[green]`-4` +
`>>>` [gray]_// again, but swapping parameter positions (see the diff() examples below)_ +
`>>>` [blue]`sum(b=2, a=-6)` +
[green]`-4` +
`>>>` [gray]_// sum of a fraction and an integer_ +
`>>>` [blue]`sum(3|2, 2)` +
[green]`7|2` +
`>>>` [gray]_// sum of two strings_ +
`>>>` [blue]`sum("bye", "-bye")` +
[green]`"bye-bye"` +
`>>>` [gray]_// sum of two lists_ +
`>>>` [blue]`sum(["one", 1], ["two", 2])` +
[green]`["one", 1, "two", 2]`
.Examples of calling a function with parameters passed by name
`>>>` [gray]_// diff(a,b) calculates a-b_ +
`>>>` [blue]`diff = func(a,b){a-b}` +
[green]`diff(a, b):any{}` +
`>>>` [gray]_// simple invocation_ +
`>>>` [blue]`diff(10,8)` +
[green]`2` +
`>>>` [gray]_// swapped parameters passed by name_ +
`>>>` [blue]`diff(b=8,a=10)` +
[green]`2`
.Examples of calling the `fib()` function defined above
`>>>` [gray]_// Fibonacci sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ..._ +
`>>>` [blue]`fib(6)` +
[green]`8` +
`>>>` [blue]`fib(9)` +
[green]`34`
.Examples of calling the `measure()` functions defined above
`>>>` [gray]_// simple call_ +
`>>>` [blue]`measure(10,"litre")` +
[green]`"10 litres"` +
`>>>` [gray]_// accept the default unit_ +
`>>>` [blue]`measure(8)` +
[green]`"8 meters"` +
`>>>` [gray]_// without the required parameter 'value'_ +
`>>>` [blue]`measure(unit="degrees"))` +
[red]`Eval Error: measure(): missing params -- value`
.Examples of context binding (closures)
`>>>` [blue]`factory = func(n=2){ func(x){x*n} }` +
[green]`factory(n=2):any{}` +
`>>>` [blue]`double = factory()` +
[green]`double(x):any{}` +
`>>>` [blue]`triple = factory(3)` +
[green]`triple(x):any{}` +
`>>>` [blue]`double(5)` +
[green]`10` +
`>>>` [blue]`triple(5)` +
[green]`15`
Functions compute values in a local context (scope) that do not make effects on the calling context. This is the normal behavior. Using the reference operator [blue]`@` it is possibile to export local definition to the calling context.

View File

@ -1853,6 +1853,18 @@ If the left variable is NOT defined, the right expression is not evaluated at al
<p><code>&gt;&gt;&gt;</code> <code class="blue">var</code><br>
<code class="green">3</code></p>
</div>
<div class="paragraph">
<p><code>&gt;&gt;&gt;</code> <code class="blue">x ?! 5</code><br>
<code class="green">nil</code></p>
</div>
<div class="paragraph">
<p><code>&gt;&gt;&gt;</code> <code class="blue">x=1; x ?! 5</code><br>
<code class="green">5</code></p>
</div>
<div class="paragraph">
<p><code>&gt;&gt;&gt;</code> <code class="blue">y ?! (c=5); c</code><br>
<code class="red">Eval Error: undefined variable or function "c"</code></p>
</div>
<div class="admonitionblock note">
<table>
<tr>
@ -1920,7 +1932,7 @@ These operators have a high priority, in particular higher than the operator <co
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>iterator</em> <code>++</code> &#8594; <em>any</em></p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>DEFAULT</strong></p></td>
<td class="tableblock halign-center valign-top" rowspan="3"><p class="tableblock"><strong>DEFAULT</strong></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">??</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Default value</em></p></td>
@ -1933,11 +1945,10 @@ These operators have a high priority, in particular higher than the operator <co
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>variable</em> <code>?=</code> <em>any-expr</em> &#8594; <em>any</em></p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>ITER</strong><sup>1</sup></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">()</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Prefix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Iterator value</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code>()</code> <em>iterator</em> &#8594; <em>any</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">?!</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Alternate value</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>variable</em> <code>?!</code> <em>any-expr</em> &#8594; <em>any</em></p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>FACT</strong></p></td>
@ -2170,9 +2181,6 @@ These operators have a high priority, in particular higher than the operator <co
</tr>
</tbody>
</table>
<div class="paragraph">
<p><sup>1</sup> Experimental</p>
</div>
</div>
</div>
<div class="sect1">
@ -2194,23 +2202,51 @@ These operators have a high priority, in particular higher than the operator <co
<div class="sect2">
<h3 id="_expr_function_definition"><a class="anchor" href="#_expr_function_definition"></a><a class="link" href="#_expr_function_definition">6.1. <em>Expr</em> function definition</a></h3>
<div class="paragraph">
<p>A function is identified and referenced by its name. It can have zero or more parameter. <em>Expr</em> functions also support optional parameters.</p>
<p>A function is identified and referenced by its name. It can have zero or more parameter. <em>Expr</em> functions also support optional parameters and passing paramters by name.</p>
</div>
<div class="exampleblock">
<div class="title">Example 14. Expr&#8217;s function definition syntax</div>
<div class="content">
<div class="paragraph">
<p><strong><em>function-definition</em></strong> = <em>identifier</em> "<strong>=</strong>" "<strong>func(</strong>" [<em>param-list</em>] "<strong>)</strong>" "<strong>{</strong>" <em>multi-expression</em> "<strong>}</strong>"<br>
<em>param_list</em> = <em>required-param-list</em> [ "<strong>,</strong>" <em>optional-param-list</em> ]<br>
<p><strong><em>function-definition</em></strong> = <em>identifier</em> "<strong>=</strong>" "<strong>func(</strong>" [<em>formal-param-list</em>] "<strong>)</strong>" "<strong>{</strong>" <em>multi-expression</em> "<strong>}</strong>"<br>
<em>formal-param_list</em> = <em>required-param-list</em> [ "<strong>,</strong>" <em>optional-param-list</em> ]<br>
<em>required-param-list</em> = <em>identifier</em> { "<strong>,</strong>" <em>identifier</em> }<br>
<em>optional-param-list</em> = <em>optional-parm</em> { "<strong>,</strong>" <em>optional-param</em> }<br>
<em>optional-param</em> = <em>identifier</em> "<strong>=</strong>" <em>any-expr</em></p>
<em>optional-param</em> = <em>param-name</em> "<strong>=</strong>" <em>any-expr</em><br>
<em>param-name</em> = <em>identifier</em></p>
</div>
</div>
</div>
<div class="paragraph">
<div class="title">Examples</div>
<p><mark>TODO</mark></p>
<p><code>&gt;&gt;&gt;</code> <em class="gray">// A simple function: it takes two parameters and returns their "sum"</em><strong><sup>(*)</sup></strong><br>
<code>&gt;&gt;&gt;</code> <code class="blue">sum = func(a, b){ a + b }</code><br>
<code class="green">sum(a, b):any{}</code></p>
</div>
<div class="paragraph">
<p><sup>(*)</sup> Since the plus, *+*, operator is defined for multiple data-types, the <em>sum()</em> function can be used for any pair of that types.</p>
</div>
<div class="paragraph">
<p><code>&gt;&gt;&gt;</code> <em class="gray">// A more complex example: recursive calculation of the n-th value of Fibonacci&#8217;s sequence</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">fib = func(n){ n ? [0] {0}: [1] {1} :: {fib(n-1)+fib(n-2)} }</code><br>
<code class="green">fib(n):any{}</code></p>
</div>
<div class="paragraph">
<p><code>&gt;&gt;&gt;</code> <em class="gray">// Same function fib() but entered by splitting it over mulple text lines</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">fib = func(n){ \</code><br>
<code>...</code> <code class="blue">&#160;&#160;n ? \</code><br>
<code>...</code> <code class="blue">&#160;&#160;&#160;&#160;[0] {0} : \</code><br>
<code>...</code> <code class="blue">&#160;&#160;&#160;&#160;[1] {1} :: \</code><br>
<code>...</code> <code class="blue">&#160;&#160;&#160;&#160;{ \</code><br>
<code>...</code> <code class="blue">&#160;&#160;&#160;&#160;&#160;&#160;fib(n-1) + fib(n-2) \</code><br>
<code>...</code> <code class="blue">&#160;&#160;&#160;&#160;} \</code><br>
<code>...</code> <code class="blue">}</code><br>
<code class="green">fib(n):any{}</code></p>
</div>
<div class="paragraph">
<p><code>&gt;&gt;&gt;</code> <em class="gray">// Required and optional parameters</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">measure = func(value, unit="meter"){ value + " " + unit + (value &gt; 1) ? [true] {"s"} :: {""}}</code><br>
<code class="green">measure(value, unit="meter"):any{}</code></p>
</div>
</div>
<div class="sect2">
@ -2222,7 +2258,85 @@ These operators have a high priority, in particular higher than the operator <co
<div class="sect2">
<h3 id="_function_calls"><a class="anchor" href="#_function_calls"></a><a class="link" href="#_function_calls">6.3. Function calls</a></h3>
<div class="paragraph">
<p><mark>TODO: function calls operations</mark></p>
<p>To call a function, either Expr or Golang type, it is necessary to specify its name and, at least, its required parameters.</p>
</div>
<div class="exampleblock">
<div class="title">Example 15. Function invocation syntax</div>
<div class="content">
<div class="paragraph">
<p><strong><em>function-call</em></strong> = <em>identifier</em> "<strong>(</strong>" <em>actual-param-list</em> "<strong>)</strong>"<br>
<em>actual-param-list</em> = [<em>positional-params</em>] [<em>named-parameters</em>]<br>
<em>positional-params</em> = <em>any-value</em> { "<strong>,</strong>" <em>any-value</em> }<br>
<em>named-params</em> = <em>param-name</em> "<strong>=</strong>" <em>any-value</em> { "<strong>,</strong>" <em>param-name</em> "<strong>=</strong>" <em>any-value</em> }<br>
<em>param-name</em> = <em>identifier</em></p>
</div>
</div>
</div>
<div class="paragraph">
<div class="title">Examples of calling the <code>sum()</code> functions defined above</div>
<p><code>&gt;&gt;&gt;</code> <em class="gray">// sum of two integers</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">sum(-6, 2)</code><br>
<code class="green">-4</code><br>
<code>&gt;&gt;&gt;</code> <em class="gray">// same as above but passing the parameters by name</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">sum(a=-6, b=2)</code><br>
<code class="green">-4</code><br>
<code>&gt;&gt;&gt;</code> <em class="gray">// again, but swapping parameter positions (see the diff() examples below)</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">sum(b=2, a=-6)</code><br>
<code class="green">-4</code><br>
<code>&gt;&gt;&gt;</code> <em class="gray">// sum of a fraction and an integer</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">sum(3|2, 2)</code><br>
<code class="green">7|2</code><br>
<code>&gt;&gt;&gt;</code> <em class="gray">// sum of two strings</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">sum("bye", "-bye")</code><br>
<code class="green">"bye-bye"</code><br>
<code>&gt;&gt;&gt;</code> <em class="gray">// sum of two lists</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">sum(["one", 1], ["two", 2])</code><br>
<code class="green">["one", 1, "two", 2]</code></p>
</div>
<div class="paragraph">
<div class="title">Examples of calling a function with parameters passed by name</div>
<p><code>&gt;&gt;&gt;</code> <em class="gray">// diff(a,b) calculates a-b</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">diff = func(a,b){a-b}</code><br>
<code class="green">diff(a, b):any{}</code><br>
<code>&gt;&gt;&gt;</code> <em class="gray">// simple invocation</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">diff(10,8)</code><br>
<code class="green">2</code><br>
<code>&gt;&gt;&gt;</code> <em class="gray">// swapped parameters passed by name</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">diff(b=8,a=10)</code><br>
<code class="green">2</code></p>
</div>
<div class="paragraph">
<div class="title">Examples of calling the <code>fib()</code> function defined above</div>
<p><code>&gt;&gt;&gt;</code> <em class="gray">// Fibonacci sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, &#8230;&#8203;</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">fib(6)</code><br>
<code class="green">8</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">fib(9)</code><br>
<code class="green">34</code></p>
</div>
<div class="paragraph">
<div class="title">Examples of calling the <code>measure()</code> functions defined above</div>
<p><code>&gt;&gt;&gt;</code> <em class="gray">// simple call</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">measure(10,"litre")</code><br>
<code class="green">"10 litres"</code><br>
<code>&gt;&gt;&gt;</code> <em class="gray">// accept the default unit</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">measure(8)</code><br>
<code class="green">"8 meters"</code><br>
<code>&gt;&gt;&gt;</code> <em class="gray">// without the required parameter 'value'</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">measure(unit="degrees"))</code><br>
<code class="red">Eval Error: measure(): missing params&#8201;&#8212;&#8201;value</code></p>
</div>
<div class="paragraph">
<div class="title">Examples of context binding (closures)</div>
<p><code>&gt;&gt;&gt;</code> <code class="blue">factory = func(n=2){ func(x){x*n} }</code><br>
<code class="green">factory(n=2):any{}</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">double = factory()</code><br>
<code class="green">double(x):any{}</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">triple = factory(3)</code><br>
<code class="green">triple(x):any{}</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">double(5)</code><br>
<code class="green">10</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">triple(5)</code><br>
<code class="green">15</code></p>
</div>
<div class="paragraph">
<p>Functions compute values in a local context (scope) that do not make effects on the calling context. This is the normal behavior. Using the reference operator <code class="blue">@</code> it is possibile to export local definition to the calling context.</p>
@ -2267,7 +2381,7 @@ These operators have a high priority, in particular higher than the operator <co
</div>
<div id="footer">
<div id="footer-text">
Last updated 2024-09-14 11:58:38 +0200
Last updated 2024-09-18 20:46:46 +0200
</div>
</div>
</body>