Nim: Arrow functions don't work as described

Created on 6 Aug 2020  路  12Comments  路  Source: nim-lang/Nim

The Nim for Typescript programmers wiki page says that this:

type Kitten = object
proc purr(this: Kitten) = echo "Purr Purr" # this
proc meow(self: Kitten) = echo "Meow Meow" # self

can be written as:

type Kitten = object
let purr = (this: Kitten) => echo "Purr Purr" # this
let meow = (self: Kitten) => echo "Meow Meow" # self

However, that produces an error:
typedesc not allowed as tuple field


Similarly, this
let purr = () => echo "Purr Purr" # No arguments

produces:
found '=>' of kind 'unknown'


Nim Compiler Version 1.2.6 [MacOSX: amd64]
Compiled at 2020-08-04
active boot switches: -d:release

All 12 comments

It should compile if you import the sugar module, which defines =>.
https://play.nim-lang.org/#ix=2tpf

If you've not imported 'sugar', please try (and presumably the wiki needs updated to reflect this if it doesn't mention it). If you've imported it, the error might be specific to MacOSX (I tried on Windows 10 with Nim 1.2.6 and both examples compiled with the import added).

Edit: I checked the wiki page and it says "Using Arrow Functions requires import sugar, on Nim syntax sugar is on the sugar module." Perhaps it'd be clearer to include it in each code fragment but it does mention this.

@alistairkeys

Yepp, sorry, didn't notice the note about having to import sugar. Thank you!
Do arrow functions only work with single line expressions?

The following gives an invalid indentation error for the second echo:

let purr = (this: Kitten) {.async.} =>
    echo "Meow meow"
    echo "Purr Purr"

I can't say I've ever tried multi-line arrow procs to be honest but they didn't work for me either. I tried a couple of things (like 'block:') but didn't have any success. As a stop-gap, you could separate statements with semi-colons on one line but that's ugly so please don't :).

The version without arrows works with multiple lines so if it's possible with arrow functions, there must be some different syntax.

Hopefully someone with more knowledge about this can chip in.

Thanks @alistairkeys!

but that's ugly so please don't :).

Yeah, I wouldn't want to do that :D

This works as a last ditch effort:

import sugar

let purr = (this: Kitten) => (block:
  echo "Meow meow"
  echo "Purr Purr")

I have reordered the Nim for TypeScript page to where the import sugar disclaimer is more visible.

For multiline lambdas, just use the "standard" way, without the sugar:

let purr = proc (this: Kitten) =
  echo "Meow meow"
  echo "Purr Purr"

Looking at the wiki, this statement is misleading:

Nim has Arrow Functions, they are syntax sugar for normal functions.

The statement implies that:

proc foo() = echo "foo"

is the same as

import sugar
let foo = () => echo "foo"

Which is wrong. The latter creates an anonymous proc, then assign the proc pointer to foo. This mean that when a stack trace is printed, you will see :anonymous as the proc name instead of foo. This also troubles debugging when you see colonanonymous__<hash here> in your debugger instead of the name you'd expect it to be.

Even worse, any proc created in that fashion will also be promoted into a closure if it access anything outside of its parameters. Closures are not lightweight and have a noticeable impact on performance if used without consideration (at least for native backends, may not be that much of an issue for JS).

s/normal/anonymous/ ?
Incidentally, it's not necessary to surround anonymous procs with parens

I don't think the closure issue is relevant here, as it applies to both forms of syntax, and to named as well as anonymous procs.

The example could highlight that you're converting normal procs to anonymous ones,

By swapping the sections around you could first discuss 'this'/'self'
Then introduce anonymous functions by converting the kitten example to the standard form, then show the arrow sugar

Anonymous Functions In Nim are just that, a function without a name. Here's our Kitten example with anonymous functions.

type Kitten = object
let purr = proc(this: Kitten) = echo "Purr Purr" 
let meow = proc(self: Kitten) = echo "Meow Meow" 

In a debugger or error message these will show up as ": anonymous"

Wiki explicitly says "Disclaimer: Everything on the Wiki is Unofficial".

I did not know how to make it more explicit than "Arrow Functions requires import sugar".

Everyone is welcome to help improving it.
:)

So? You are not being useful here with that comment. Plus, it's resolved.

Wiki explicitly says "Disclaimer: Everything on the Wiki is Unofficial".

Well, that disclaimer is hidden as hell.
Plus, _hlaaftana_ made the note about importing sugar more visible because it was woefully hidden as well.

Bug status is not resolved, maybe close this bug then ?.

I think of making it Bold, but too much Bold kinda stops having the visual significance, next time well use <marquee>.

:)

I can see the updates to the wiki page, closing.

Was this page helpful?
0 / 5 - 0 ratings