From 9f99dd0196edda1e5bb6440abb9e7003d26ecfca Mon Sep 17 00:00:00 2001 From: def Date: Sun, 3 Aug 2014 14:11:57 +0200 Subject: [PATCH 1/2] Add list comprehensions to future module --- lib/pure/future.nim | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/lib/pure/future.nim b/lib/pure/future.nim index b7df05207d..121877ad12 100644 --- a/lib/pure/future.nim +++ b/lib/pure/future.nim @@ -115,3 +115,56 @@ macro `->`*(p, b: expr): expr {.immediate.} = ## f(2, 2) result = createProcType(p, b) + +type ListComprehension = object +var lc*: ListComprehension + +macro `[]`*(lc: ListComprehension, x, t): expr = + ## List comprehensions. + ## + ## .. code-block:: nimrod + ## + ## const n = 20 + ## echo lc[(x,y,z) | (x <- 1..n, y <- x..n, z <- y..n, x*x + y*y == z*z), + ## tuple[a,b,c: int]] + + expectLen(x, 3) + expectKind(x, nnkInfix) + expectKind(x[0], nnkIdent) + assert($x[0].ident == "|") + + result = newCall( + newDotExpr( + newIdentNode("result"), + newIdentNode("add")), + x[1]) + + for i in countdown(x[2].len-1, 0): + let y = x[2][i] + expectKind(y, nnkInfix) + expectMinLen(y, 1) + if y[0].kind == nnkIdent and $y[0].ident == "<-": + expectLen(y, 3) + result = newNimNode(nnkForStmt).add(y[1], y[2], result) + else: + result = newIfStmt((y, result)) + + result = newNimNode(nnkCall).add( + newNimNode(nnkPar).add( + newNimNode(nnkLambda).add( + newEmptyNode(), + newEmptyNode(), + newEmptyNode(), + newNimNode(nnkFormalParams).add( + newNimNode(nnkBracketExpr).add( + newIdentNode("seq"), + t)), + newEmptyNode(), + newEmptyNode(), + newStmtList( + newAssignment( + newIdentNode("result"), + newNimNode(nnkPrefix).add( + newIdentNode("@"), + newNimNode(nnkBracket))), + result)))) From c7898a0c81f0d6267e52b0ab77cb156588fed01c Mon Sep 17 00:00:00 2001 From: def Date: Sun, 3 Aug 2014 19:07:45 +0200 Subject: [PATCH 2/2] Extend list comprehension documentation --- lib/pure/future.nim | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/lib/pure/future.nim b/lib/pure/future.nim index 121877ad12..480ee2b0dc 100644 --- a/lib/pure/future.nim +++ b/lib/pure/future.nim @@ -119,35 +119,39 @@ macro `->`*(p, b: expr): expr {.immediate.} = type ListComprehension = object var lc*: ListComprehension -macro `[]`*(lc: ListComprehension, x, t): expr = - ## List comprehensions. +macro `[]`*(lc: ListComprehension, comp, typ: expr): expr = + ## List comprehension, returns a sequence. `comp` is the actual list + ## comprehension, for example ``x | (x <- 1..10, x mod 2 == 0)``. `typ` is + ## the type that will be stored inside the result seq. ## ## .. code-block:: nimrod ## + ## echo lc[x | (x <- 1..10, x mod 2 == 0), int] + ## ## const n = 20 ## echo lc[(x,y,z) | (x <- 1..n, y <- x..n, z <- y..n, x*x + y*y == z*z), ## tuple[a,b,c: int]] - expectLen(x, 3) - expectKind(x, nnkInfix) - expectKind(x[0], nnkIdent) - assert($x[0].ident == "|") + expectLen(comp, 3) + expectKind(comp, nnkInfix) + expectKind(comp[0], nnkIdent) + assert($comp[0].ident == "|") result = newCall( newDotExpr( newIdentNode("result"), newIdentNode("add")), - x[1]) + comp[1]) - for i in countdown(x[2].len-1, 0): - let y = x[2][i] - expectKind(y, nnkInfix) - expectMinLen(y, 1) - if y[0].kind == nnkIdent and $y[0].ident == "<-": - expectLen(y, 3) - result = newNimNode(nnkForStmt).add(y[1], y[2], result) + for i in countdown(comp[2].len-1, 0): + let x = comp[2][i] + expectKind(x, nnkInfix) + expectMinLen(x, 1) + if x[0].kind == nnkIdent and $x[0].ident == "<-": + expectLen(x, 3) + result = newNimNode(nnkForStmt).add(x[1], x[2], result) else: - result = newIfStmt((y, result)) + result = newIfStmt((x, result)) result = newNimNode(nnkCall).add( newNimNode(nnkPar).add( @@ -158,7 +162,7 @@ macro `[]`*(lc: ListComprehension, x, t): expr = newNimNode(nnkFormalParams).add( newNimNode(nnkBracketExpr).add( newIdentNode("seq"), - t)), + typ)), newEmptyNode(), newEmptyNode(), newStmtList(