Skip to content

Commit

Permalink
Make mapIt work on openArray's (#8543)
Browse files Browse the repository at this point in the history
  • Loading branch information
LemonBoy authored and Araq committed Aug 7, 2018
1 parent 4d5cce9 commit ba5e2d6
Showing 1 changed file with 30 additions and 3 deletions.
33 changes: 30 additions & 3 deletions lib/pure/collections/sequtils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -654,16 +676,16 @@ 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:
result[i] = op
i += 1
else:
result = @[]
for it {.inject.} in s:
for it {.inject.} in t:
result.add(op)
result

Expand Down Expand Up @@ -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"

0 comments on commit ba5e2d6

Please sign in to comment.