Nim equivalent of Python's list comprehension
Asked Answered
E

4

22

Since Nim shares a lot of features with Python, i would not be surprised if it implements Python's list comprehension too:

string = "Hello 12345 World"
numbers = [x for x in string if x.isdigit()]
# ['1', '2', '3', '4', '5']

Is this actually possible in Nim? If not, could be implemented with templates/macros ?

Endocardium answered 27/4, 2015 at 12:33 Comment(0)
E
20

UPDATE: List comprehension has been deprecated since version 0.19.9 (Source). A good alternative is to use the new sugar.collect macro.

Another update: As of 2023, list comprehension has been removed.


Outdated original answer

List comprehension is implemented in Nim in the sugar package (i.e., you have to import sugar). It is implemented as a macro called lc and allows to write list comprehensions like this:

lc[x | (x <- 1..10, x mod 2 == 0), int]

lc[(x,y,z) | (x <- 1..n, y <- x..n, z <- y..n, x*x + y*y == z*z), tuple[a,b,c: int]]

Note that the macro requires to specify the type of the elements.

Excurrent answered 27/4, 2015 at 12:55 Comment(7)
@Downvoter: Surprised to get downvotes here. Is it just because the other answer has been updated or is there something wrong with my answer?Excurrent
Your answer is right, and since you were the first that commented on future module, i'll mark yours as the correct.Endocardium
List comprehensions are deprecated since version 0.19.9.Wanonah
For a library-based solution check out github.com/alehander42/comprehensionBragdon
the prefered way of doing this is with the collect macro in sugar nim-lang.org/docs/sugar.html#collect.m%2Cuntyped%2CuntypedGlabrous
@daten-kieker That information that the answer is outdated is written in the first paragraph of the answer. I'll try to make it even more obvious...Excurrent
@Excurrent - sorry, my bad. Too focused on the code snippet, I guess. I'll delete my comment.Mischief
A
9

According to rosettacode, Nim has no list comprehensions, but they can be created through metaprogramming.

[EDIT]

As pointed out by bluenote10, list comprehensions are now part of the future module:

import future
var str = "Hello 12345 World"
echo lc[x | (x <- str, ord(x) - ord('0') in 0..9),  char]

The above snippet yields @[1, 2, 3, 4, 5]

Azzieb answered 27/4, 2015 at 12:36 Comment(2)
Looks like this is exactly what is now part of the future module.Excurrent
As of 2023-06-17 this answer doesn't work anymore. The new way is the answer by @dotfelixb)Mischief
P
6

Original

import sugar

let items = collect(newSeq):
  for x in @[1, 2, 3]: x * 2

echo items

outputs @[2, 4, 6]

Updated to answer question

import sugar
import sequtils
import strutils

let numbers = collect: # collect from suger
  for x in "Hello 12345 World".toSeq: # toSeq from sequtils
    if x.isDigit: # isDigit from strutils
      x

echo numbers

outputs @['1', '2', '3', '4', '5']

Palmira answered 16/10, 2020 at 21:42 Comment(0)
A
2

Nim translation of your code:

import sugar, strutils
var str = "Hello 12345 World"
echo collect(for s in str:
  if s.isDigit(): s)
Aegisthus answered 3/11, 2021 at 7:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.