lambda syntax added

This commit is contained in:
sergeych committed 2025-06-02 14:02:01 +04:00
1 parent 2344e19857
commit 19a2a1d909
10 files changed
+342 -59

No files matched your search

+34 -9
View File
@@ -2,24 +2,24 @@
## Closures/scopes isolation
Each block has own scope, in which it can safely uses closures and override
outer vars:
> blocks are no-yet-ready lambda declaration so this sample will soon be altered
Each block has own scope, in which it can safely use closures and override
outer vars. Lets use some lambdas to create isolated scopes:
var param = "global"
val prefix = "param in "
val scope1 = {
var param = prefix + "scope1"
param
}
val scope2 = {
var param = prefix + "scope2"
param
}
// note that block returns its last value
println(scope1)
println(scope2)
println(scope1())
println(scope2())
println(param)
>>> param in scope1
>>> param in scope2
@@ -38,7 +38,9 @@ One interesting way of using closure isolation is to keep state of the functions
counter = counter + 1
was
}
}
}()
// notice using of () above: it calls the lambda block that returns
// a function (callable!) that we will use:
println(getAndIncrement())
println(getAndIncrement())
println(getAndIncrement())
@@ -49,4 +51,27 @@ One interesting way of using closure isolation is to keep state of the functions
Inner `counter` is not accessible from outside, no way; still it is kept
between calls in the closure, as inner function `doit`, returned from the
block, keeps reference to it and keeps it alive.
block, keeps reference to it and keeps it alive.
The example above could be rewritten using inner lambda, too:
val getAndIncrement = {
// will be updated by doIt()
var counter = 0
// we return callable fn from the block:
{
val was = counter
counter = counter + 1
was
}
}()
// notice using of () above: it calls the lambda block that returns
// a function (callable!) that we will use:
println(getAndIncrement())
println(getAndIncrement())
println(getAndIncrement())
>>> 0
>>> 1
>>> 2
>>> void
+59 -13
View File
@@ -219,7 +219,17 @@ likely will know some English, the rest is the pure uncertainty.
Notice how function definition return a value, instance of `Callable`.
You can use both `fn` and `fun`. Note that function declaration _is an expression returning callable_.
You can use both `fn` and `fun`. Note that function declaration _is an expression returning callable_,
but Lyng syntax requires using the __lambda syntax__ to create such.
val check = {
it > 0 && it < 100
}
assert( check(1) )
assert( !check(101) )
>>> void
See lambdas section below.
There are default parameters in Lyng:
@@ -239,13 +249,16 @@ Each __block has an isolated context that can be accessed from closures__. For e
var counter = 1
// this is ok: coumter is incremented
// this is ok: counter is incremented
fun increment(amount=1) {
// use counter from a closure:
counter = counter + amount
}
val taskAlias = fun someTask() {
increment(10)
assert( counter == 11 )
val callable = {
// this obscures global outer var with a local one
var counter = 0
// ...
@@ -253,24 +266,57 @@ Each __block has an isolated context that can be accessed from closures__. For e
// ...
counter
}
assert(callable() == 1)
// but the global counter is not changed:
assert(counter == 11)
>>> void
As was told, `fun` statement return callable for the function, it could be used as a parameter, or elsewhere
to call it:
## Lambda functions
val taskAlias = fun someTask() {
println("Hello")
Lambda expression is a block with optional argument list ending with `->`. If argument list is omitted,
the call arguments will be assigned to `it`:
lambda = {
it + "!"
}
// call the callable stored in the var
taskAlias()
// or directly:
someTask()
>>> Hello
>>> Hello
assert( lambda is Callable)
assert( lambda("hello") == "hello!" )
void
### `it` assignment rules
When lambda is called with:
- no arguments: `it == void`
- exactly one argument: `it` will be assigned to it
- more than 1 argument: `it` will be a `List` with these arguments:
Here is an example:
val lambda = { it }
assert( lambda() == void )
assert( lambda("one") == "one")
assert( lambda("one", "two") == ["one", "two"])
>>> void
If you need to create _unnamed_ function, use alternative syntax (TBD, like { -> } ?)
### Declaring parameters
Parameter is a list of comma-separated names, with optional default value; last
one could be with ellipsis that means "the rest pf arguments as List":
assert( { a -> a }(10) == 10 )
assert( { a, b -> [a,b] }(1,2) == [1,2])
assert( { a, b=-1 -> [a,b] }(1) == [1,-1])
assert( { a, b...-> [a,...b] }(100) == [100])
// notice that splat syntax in array literal unrills
// ellipsis-caught arguments back:
assert( { a, b...-> [a,...b] }(100, 1, 2, 3) == [100, 1, 2, 3])
void
# Lists (aka arrays)
Lyng has built-in mutable array class `List` with simple literals: