I've been dabbling in this language while I learn Python to compare the 2 languages and see how they're similar and different to use.
In Python, you can write code like (just as an example):
to output a list of 1-10. I know that Nim recently added comprehensions through the collect() macro, but I can't figure out how to return the result of this collection as the output of a procedure directly, without using a variable to store the value first, like you can in that Python code above. How do you do this? Is it not possible, and a variable must be used. I read that collections can do everything that list comprehensions can do, so I assume that I just don't know how it works entirely, since I'm very new.
Sorry If this question already has an answer, but I couldn't find an answer when I tried looking myself. Thanks!
Seems like for some reason collect doesn't really support being used as an argument directly, but you can circumvent that using a block:
import std/sugar
echo(block:
collect(newSeq):
for i in 1..11:
i)
if you really want to get it all on one line you can also do this
import sugar
echo (block: collect(newSeq):( for i in 1..11: i))
This also works:
import std/sugar
template collected(make, iteration): untyped =
block:
collect(make): iteration
echo collected(newSeq, (for i in 1..11: i))
I just confirmed this. On stable I got: Error: expression 'x' is of type 'int' and has to be used (or discarded), but when I used choosenim to switch to devel (which was super easy btw) it worked exactly like I thought it would. The results of the operation in parens get collected into a list, and that list then gets returned as the output of collect().
It's good to know that this functionality is being added in a future release. Thanks for all of other solutions too everyone. I'll use those in the mean time, since learning the language on devel is probably a bad idea.
You're right, it does! You need to put "newSeq" first in stable, but in devel, you don't. That makes me wonder what the purpose of "newSeq" is. If you name it something else, it throws an error, so newSeq specifically is special, even though the Nim extension doesn't give it any special highlighting or completion it seems. I'm guessing that it determines what kind of comprehension is created, since I believe lists are called sequences in Nim. In devel, though, I wonder why it's no longer needed. How does it determine what container type to use?
Thanks for the info! I'll use this.
newSeq is a proc in the system module, included by default.
If you're using vs code, then you should be able to go to definition to see that -- right click context menu or F12 should do it.
@buster_blue: this is a perhaps useful summary:
import std/sugar, sets, tables
# Old style (E.g., Nim 1.2)
echo collect(newSeq, for i in 1..9: i)
echo collect(HashSet, for i in 1..9: {i})
echo collect(Table, for i in 1..9: {i: i+1})
# New style (e.g. current devel)
echo collect(for i in 1..9: i)
echo collect(for i in 1..9: {i})
echo collect(for i in 1..9: {i: i+1})
The old style continues to work and can be useful if you have some container you would like to collect into that is not one of the standard 3 (either from the stdlib or in Nimble or wherever).I spent some time trying to use an if in a one line collect, if I had tried to compile, the indentation error would have saved me some time but VS Code squiggly line was misleading. The solution was simply wrapping the if in parens.
Just in case someone else finds this thread in similar pursuit, I will put an example:
collect(for n in seq: (if n == x: n))
I've recently learned about collections (as I'm learning Nim) and I prefer collections on multiple lines as then everything is clear to me:
collect:
for n in seq:
if n == x: n
When it gets a little more complicated, it's even more important for me to break it out, eg:
let mySeq = collect:
for i in 1 .. 9:
if i notin myOtherSeq: continue
if i mod 3 != 0: i else: 0
It's not so complicated that it should be moved it to a proc / func, and doing it like this is very readable. It's one of the elegant things about Nim for me.
Yes I could put it in one line, but personally I wouldn't want to.
Yes I could put it in one line, but personally I wouldn't want to.
Thank you, you nailed it. :-)