From ba5e2d6fcb4d1dd5fde523076dafeed77360dba5 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 7 Aug 2018 18:45:27 +0200 Subject: Make mapIt work on openArray's (#8543) --- lib/pure/collections/sequtils.nim | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index db33e41af..8f81fe4f5 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -635,6 +635,28 @@ template mapIt*(s, typ, op: untyped): untyped = result.add(op) result +# This is needed in order not to break the bootstrap, the fallback +# implementation is a "dumb" let that won't work in some cases (eg. when `exp` +# is an openArray) +when declared(macros.symKind): + macro evalOnce(v, exp: untyped): untyped = + expectKind(v, nnkIdent) + var val = exp + + result = newStmtList() + + # Not a parameter we can pass as-is, evaluate and store in a temporary + # variable + if exp.kind != nnkSym or exp.symKind != nskParam: + val = genSym() + result.add(newLetStmt(val, exp)) + + result.add( + newProc(name = genSym(nskTemplate, $v), params = [getType(untyped)], + body = val, procType = nnkTemplateDef)) +else: + macro evalOnce(v, exp: untyped): untyped = + result = newLetStmt(v, exp) template mapIt*(s, op: untyped): untyped = ## Convenience template around the ``map`` proc to reduce typing. @@ -654,8 +676,8 @@ template mapIt*(s, op: untyped): untyped = var it{.inject.}: type(items(s)); op)) var result: seq[outType] - when compiles(s.len): - let t = s + evalOnce(t, s) + when compiles(t.len): var i = 0 result = newSeq[outType](t.len) for it {.inject.} in t: @@ -663,7 +685,7 @@ template mapIt*(s, op: untyped): untyped = i += 1 else: result = @[] - for it {.inject.} in s: + for it {.inject.} in t: result.add(op) result @@ -1044,5 +1066,10 @@ when isMainModule: doAssert mapLiterals((1, ("abc"), 2), float, nested=false) == (float(1), "abc", float(2)) doAssert mapLiterals(([1], ("abc"), 2), `$`, nested=true) == (["1"], "abc", "2") + block: # mapIt with openArray + when declared(macros.symKind): + proc foo(x: openArray[int]): seq[int] = x.mapIt(it + 1) + doAssert foo([1,2,3]) == @[2,3,4] + when not defined(testing): echo "Finished doc tests" -- cgit 1.4.1-2-gfad0