I'm finding Nim's syntax for calling lambdas awkward and verbose.
proc twice[T](input: T, fn: proc(t: T):T):T =
fn(fn(input))
let fourthPower = twice(10, proc(n: int): int =
echo "Gratuitous echo!"
return n * n
)
I'm aware of the ``sugar`` module. The => macro makes this a lot better, but it only seems to work with single-line lambdas.
let plusTwo = twice(10, (n) => n + 1)
Every attempt I've made to use it in a multi-line lambda fails with syntax errors:
let plusTwo = twice(10, (n) =>
echo "Another gratuitious echo"
n + 1) # Error: expected: ')', but got: 'n'
I like that templates and macros can be called with a block as a final parameter, but that feature is limited in that the block can't take any parameters and can't return a value.
Is there something I've missed? Or are there proposals to improve this in the future?
—Jens
Personally I think it's even harder to read than the plain proc version.
let plusTwo = twice(10) do (n:int) -> int:
echo "Another gratuitious echo"
n + 1
Not idiomatic, wouldn't recommend.
let plusTwo2 = twice(10, n => (
echo "Another gratuitious echo";
n + 1
))
I almost like this one! Unfortunately if you remove the brackets, you get "Error: expression expected, but found 'keyword block'"
let plusTwo3 = twice(10, n => (block:
echo "Another gratuitious echo"
n + 1
))
Does anyone know, is this a syntax limitation, or could the => operator be modified to allow a block expression without brackets?
Oh! I tried using block and wondered why it didn't work ... I didn't realize parens were necessary.
The do notation seems an improvement; it resolves two of the three complaints I gave above. If it had better type-inference I'd love it. Maybe that's why it's still experimental?
e.g. what I'd like to see is let plusTwo = twice(10) do (n):
Hm, not yet there, but arguably somewhat closer with auto:
let plusTwo = twice(10) do (n:auto) -> auto:
echo "Another gratuitious echo"
n + 1
Maybe this is close enough that now it could be wrapped in some macro to shorten even more?
I wouldn't depend on the do notation. The reason it's experimental is that it doesn't fit the language and may be removed entirely eventually.
Personally, I don't think this is too verbose:
let fourthPower = twice(10,
proc(n: int): int =
echo "Gratuitous echo!"
return n * n
)
It would look very similar in JS. In Python it would simply not be possible.
Another technique also seen in std lib.
template twiceIt(input, body: untyped): untyped =
type T = typeof(input)
let fn = proc(n: T): T =
let it {.inject.} = n
`body`
fn(fn(input))
let y = twiceIt 10:
echo "Gratuitous echo!"
return it * it