mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 20:17:42 +00:00
* fix mapIt issues #12625 & #12639: 1. fallback to call `map` when the result of `op` is a closure; 2. use `items(s)` in the for loop. * fix test errors. * add comments and InType is moved. * fix ident.
This commit is contained in:
@@ -924,24 +924,46 @@ template mapIt*(s: typed, op: untyped): untyped =
|
||||
block:
|
||||
var it{.inject.}: type(items(s));
|
||||
op))
|
||||
when compiles(s.len):
|
||||
block: # using a block avoids https://github.com/nim-lang/Nim/issues/8580
|
||||
when OutType is not (proc):
|
||||
# Here, we avoid to create closures in loops.
|
||||
# This avoids https://github.com/nim-lang/Nim/issues/12625
|
||||
when compiles(s.len):
|
||||
block: # using a block avoids https://github.com/nim-lang/Nim/issues/8580
|
||||
|
||||
# BUG: `evalOnceAs(s2, s, false)` would lead to C compile errors
|
||||
# (`error: use of undeclared identifier`) instead of Nim compile errors
|
||||
evalOnceAs(s2, s, compiles((let _ = s)))
|
||||
# BUG: `evalOnceAs(s2, s, false)` would lead to C compile errors
|
||||
# (`error: use of undeclared identifier`) instead of Nim compile errors
|
||||
evalOnceAs(s2, s, compiles((let _ = s)))
|
||||
|
||||
var i = 0
|
||||
var result = newSeq[OutType](s2.len)
|
||||
for it {.inject.} in s2:
|
||||
result[i] = op
|
||||
i += 1
|
||||
var i = 0
|
||||
var result = newSeq[OutType](s2.len)
|
||||
for it {.inject.} in s2:
|
||||
result[i] = op
|
||||
i += 1
|
||||
result
|
||||
else:
|
||||
var result: seq[OutType] = @[]
|
||||
# use `items` to avoid https://github.com/nim-lang/Nim/issues/12639
|
||||
for it {.inject.} in items(s):
|
||||
result.add(op)
|
||||
result
|
||||
else:
|
||||
var result: seq[OutType] = @[]
|
||||
for it {.inject.} in s:
|
||||
result.add(op)
|
||||
result
|
||||
# `op` is going to create closures in loops, let's fallback to `map`.
|
||||
# NOTE: Without this fallback, developers have to define a helper function and
|
||||
# call `map`:
|
||||
# [1, 2].map((it) => ((x: int) => it + x))
|
||||
# With this fallback, above code can be simplified to:
|
||||
# [1, 2].mapIt((x: int) => it + x)
|
||||
# In this case, `mapIt` is just syntax sugar for `map`.
|
||||
|
||||
when defined(nimHasTypeof):
|
||||
type InType = typeof(items(s), typeOfIter)
|
||||
else:
|
||||
type InType = type(items(s))
|
||||
# Use a help proc `f` to create closures for each element in `s`
|
||||
let f = proc (x: InType): OutType =
|
||||
let it {.inject.} = x
|
||||
op
|
||||
map(s, f)
|
||||
|
||||
template applyIt*(varSeq, op: untyped) =
|
||||
## Convenience template around the mutable ``apply`` proc to reduce typing.
|
||||
|
||||
@@ -204,3 +204,6 @@ block ttoseq:
|
||||
var y: type("a b c".split)
|
||||
y = "xzy"
|
||||
stdout.write("\n")
|
||||
|
||||
block tseqmapitchain:
|
||||
doAssert @[101, 102] == [1, 2].mapIt(func (x: int): int = it + x).mapIt(it(100))
|
||||
Reference in New Issue
Block a user