diff options
author | LemonBoy <LemonBoy@users.noreply.github.com> | 2018-08-07 18:45:27 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-08-07 18:45:27 +0200 |
commit | ba5e2d6fcb4d1dd5fde523076dafeed77360dba5 (patch) | |
tree | b4e599c254c2b10c612ac697e95f68f3fb8a86a6 | |
parent | 4d5cce9882d554ada9cf737d63e40880d88ba170 (diff) | |
download | Nim-ba5e2d6fcb4d1dd5fde523076dafeed77360dba5.tar.gz |
Make mapIt work on openArray's (#8543)
-rw-r--r-- | lib/pure/collections/sequtils.nim | 33 |
1 files 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" |