Skip to content

Commit 30cbc6c

Browse files
committed
lambda expressions, specifiers and operator
1 parent d90a88d commit 30cbc6c

File tree

2 files changed

+187
-7
lines changed

2 files changed

+187
-7
lines changed

content/design.md

+89
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,95 @@ Standard library offers many types composed of the built-ins, including (but not
439439
- Bytes, fixed and dynamic byte arrays: `Byte`, `Bytes16`, `Bytes32`, `Blob256`, `Blob64kB`, `Blob16MB` `Blob4GB` etc;
440440
- Commonly-used monads `Maybe`, `Either`, `Result`, `Ternary`.
441441

442+
### Lambda expressions
443+
444+
<aside>
445+
One of Cation's main features is an ability to treat data, values and functions the same way, making all of them
446+
first-class citizens.
447+
</aside>
448+
449+
<dfn>Lambda expressions</dfn> allow a combination of statements, capturing locally-defined values,
450+
to be treated as a function. They simplify passing functions as arguments to other functions, saving
451+
from boilerplate code.
452+
453+
Lambda expressions have several forms. The canonical one is a specifier form, which starts with a `lambda` keyword,
454+
followed by a value name, colon, argument and return type definition and body:
455+
456+
```
457+
let local: U8 = random
458+
lambda sq: x U8 -> U32
459+
pow 2 + local
460+
```
461+
462+
As any other specifier it can be put into a single line:
463+
```
464+
let local: U8 = random
465+
lambda sq: x U8 -> U32 := pow 2 + local
466+
```
467+
468+
<aside>
469+
The <code>.\</code> operator is shaped after Greek letter $\lambda$.
470+
</aside>
471+
472+
The second form is an operator form using `.\` or Greek `λ`; it allows anonymous lambda definitions which may span
473+
a single or multiple lines. The specific syntax of this form depends on whether the lambda is the last expression in
474+
the line:
475+
476+
```
477+
-- for the last expression in the line
478+
.\pow 2
479+
-- or even shorter
480+
.\^2
481+
```
482+
483+
If a lambda expression has to be followed by other expressions, one need to put the expression into a parenthesis:
484+
```
485+
.\(pow 2), _
486+
```
487+
488+
Lambda expressions may have own explicit arguments, separated from the function body using double-column. The return
489+
type may be omitted, and in this case if is inferred by the compiler from the body of the expression:
490+
```
491+
.\x U8 -> U16: x pow 2
492+
493+
-- With a type omission:
494+
.\x U8: x pow 2
495+
496+
-- If the expression is not at the end of a line
497+
.\(x U8: x pow 2), _
498+
```
499+
500+
Finally, there is the multiline forms of lambda expressions:
501+
```
502+
let lambdaFn := .\
503+
statement1
504+
statement2
505+
```
506+
507+
In can be used the same way as single-line expressions, with the only difference – there is no colon between the lambda
508+
declaration and the body:
509+
```
510+
.\ x U8
511+
x pow 2
512+
513+
.\ x U8 -> U16
514+
x pow 2
515+
516+
-- Here we can use multiline in the middle of other expression
517+
someFn arg1, .\(x U8 -> U16
518+
x pow 2
519+
), argLast
520+
```
521+
522+
The type of the lambda expression is `.\ input -> output`, and this type may be used in type annotations:
523+
```
524+
let squared: .\U8 -> U16 := .\pow 2
525+
```
526+
527+
<!-- TODO: add on currying:
528+
Functions with multiple arguments is the same as a function with single argument made of anonymous data type composing
529+
the list of the arguments. -->
530+
442531

443532
### Generics
444533

content/reference.md

+98-7
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,19 @@ identifier; `` `x` `` and `x` has the same meaning.
4242
### Keywords
4343

4444
The following keywords are reserved and can’t be used as identifiers, unless they’re escaped with backticks, as
45-
described above in [Identifiers](#identifiers). Keywords other than `let` can be used as field or variant names in
46-
data types, as parameter names in a function declaration or function call without being escaped with backticks.
45+
described above in [Identifiers](#identifiers). Keywords other than `let` and `lambda` can be used as field or variant
46+
names in data types, as parameter names in a function declaration or function call without being escaped with backticks.
4747

4848
- `data`: defines new data type
49+
- `class`: defines a new data type class
4950
- `fx`: defines new function (prefix function)
5051
- `infx`: defines new infix function
52+
- `lambda`: defines a lambda function
5153
- `alias`: defines a new alias for a function
52-
- `let`: defines new value with some data type
53-
- `class`: defines a new type class
54+
- `let`: defines new value
5455

55-
The following tokens are reserved as punctuation and can’t be used as custom operators: `(`, `)`, `{`, `}`, `[`, `]`,
56-
`.`, `,`, `|`, `:`, `;`, `#`, `=>`, `->`, `<-`, `<|`, `|>`, `>|`, `|?`, `|:`, `` ` ``, `~`.
56+
The following tokens are reserved as built-in operators and can’t be used in custom operators: `(`, `)`, `{`, `}`,
57+
`[`, `]`, `.`, `,`, `:`, `;`, `#`, `=>`, `->`, `<-`, `<|`, `|>`, `>|`, `|?`, `|:`, `.\`, `` ` ``.
5758

5859
### Literals
5960

@@ -228,6 +229,73 @@ or reverse the order of the expressions:
228229

229230
mulTry 2 <| 0..<100
230231

232+
#### Lambda operator
233+
234+
<dfn>Lambda operator</dfn> `.\`, with alias `λ` (Greek letter lambda) is a shorthand for creating lambda expressions.
235+
It has four forms:
236+
- single-line, end of line (trailing lambda):
237+
```
238+
.\args -> ret: expr
239+
```
240+
- single-line, alongside other expressions:
241+
```
242+
.\(args -> ret: expr), _
243+
```
244+
- multi-line, end of line (trailing lambda block):
245+
```
246+
.\args -> ret
247+
expr1
248+
expr2
249+
-- ...
250+
```
251+
- multi-line, alongside other expressions:
252+
```
253+
.\(args -> ret
254+
expr1
255+
expr2
256+
-- ...
257+
), _
258+
```
259+
260+
All forms may skip the return type `-> ret` part; in this case the return type is inferred by the compiler:
261+
```
262+
.\args: expr
263+
264+
.\(args: expr), _
265+
266+
.\args
267+
expr1
268+
expr2
269+
-- ...
270+
271+
.\(args
272+
expr1
273+
expr2
274+
-- ...
275+
), _
276+
```
277+
278+
If the lambda expression has no inputs, lambda operator must be simply followed by the expression itself with no
279+
colon used:
280+
```
281+
.\expr
282+
283+
.\(expr), _
284+
285+
.\
286+
expr1
287+
expr2
288+
-- ...
289+
290+
.\(
291+
expr1
292+
expr2
293+
-- ...
294+
), _
295+
```
296+
297+
See also [lambda specifier](#lambda-specifier).
298+
231299
### Standard library
232300

233301
#### Monadic operators
@@ -368,6 +436,10 @@ instantiated using a shorthand [range expressions](#range-expressions).
368436

369437
### Expressions
370438

439+
#### Lambda expressions
440+
441+
Lambda expressions have two forms: [operator](#lambda-operator) and [specifier](#lambda-specifier).
442+
371443
#### Collection comprehension
372444

373445
Grouping operator is `(`..`)` constructs an anonymous data type.
@@ -406,7 +478,26 @@ iterations, like with `$-1`, accessing the previous iteration result, or
406478

407479
#### Data class
408480

409-
#### Value
481+
#### Value specifier
482+
483+
#### Lambda specifier
484+
485+
<dfn>Lambda specifier</dfn> starts with a `lambda` keyword, followed by a value name, colon, argument and return type
486+
definition and body:
487+
488+
```
489+
let local: U8 = random
490+
lambda sq: x U8 -> U32
491+
pow 2 + local
492+
```
493+
494+
As any other specifier it can be put into a single line:
495+
```
496+
let local: U8 = random
497+
lambda sq: x U8 -> U32 := pow 2 + local
498+
```
499+
500+
See also [lambda operator](#lambda-operator).
410501

411502
## Generics
412503

0 commit comments

Comments
 (0)