123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 | func make_adder(x:Int -> func(y:Int->Int))
return func(y:Int) x + y
func suffix_fn(fn:func(t:Text->Text), suffix:Text -> func(t:Text->Text))
return func(t:Text) fn(t)++suffix
func mul_func(n:Int, fn:func(x:Int->Int) -> func(x:Int->Int))
return func(x:Int) n*fn(x)
test "lambdas and higher-order functions"
>> add_one := func(x:Int) x + 1
>> add_one(10)
assert add_one(10) == 11
>> shout := func(msg:Text) say("$(msg.upper())!")
shout("hello")
>> asdf := add_one
>> asdf(99)
assert asdf(99) == 100
>> add_100 := make_adder(100)
>> add_100(5)
assert add_100(5) == 105
>> shout2 := suffix_fn(func(t:Text) t.upper(), "!")
>> shout2("hello")
assert shout2("hello") == "HELLO!"
>> abs100 := mul_func(100, Int.abs)
>> abs100(-5)
assert abs100(-5) == 500
test "nested lambdas"
# Test nested lambdas:
>> outer := "Hello"
>> fn := func()
return func()
return func()
defer say("$outer")
return outer
>> fn()()()
assert fn()()() == "Hello"
test "local declarations in a lambda with a declared return type"
# A lambda that declares a local and then explicitly returns used to report
# the local as already defined: typechecking the `return` re-derived the
# lambda's return type, which re-typechecked the body in a scope that
# already held the declarations made ahead of the return.
>> counted := func(t:Text -> Int)
trimmed := t.trim()
n := trimmed.length
return n + 1
>> counted(" abc ")
assert counted(" abc ") == 4
# The same body without an explicit `return`, and with the return type
# inferred rather than declared, always worked; keep both covered:
>> implicit := func(t:Text -> Int)
trimmed := t.trim()
trimmed.length
assert implicit(" abc ") == 3
>> inferred := func(t:Text)
trimmed := t.trim()
return trimmed.length
assert inferred(" abc ") == 3
# Declarations of container types go through the same path:
>> tallied := func(k:Int -> Int)
counts := {1: 10, 2: 20}
return counts[k] or 0
assert tallied(2) == 20
assert tallied(99) == 0
test "a lambda still can't shadow an outer variable"
shadowed := "outer"
assert shadowed == "outer"
nope := func(-> Int)
shadowed := "inner"
return shadowed.length
>> nope()
fails_compile "has already been defined"
|