使用函数值生成新序列
Generate a new sequence with values from a function
根据标题,我有以下代码:
proc squared(n: int64): int64 = n * n
echo squared(5)
生成以下输出:
25
但是,如果我知道想要使用 squared
填充序列,我会这样写:
import sequtils
proc squared_seq(n: int64): seq[int64] =
result = newSeq[int64](n)
for i in 0 ..< n:
result[i] = squared(i)
echo squared_seq(5)
我希望这会产生以下输出:
@[0, 1, 4, 9, 16]
但我得到的只是以下错误(在 result[i] = ...
行):
Error: type mismatch: got <seq[int64], int64, int64>
but expected one of:
proc `[]=`(s: var string; i: BackwardsIndex; x: char)
proc `[]=`[T, U](s: var string; x: HSlice[T, U]; b: string)
proc `[]=`[T](s: var openArray[T]; i: BackwardsIndex; x: T)
proc `[]=`[Idx, T, U, V](a: var array[Idx, T]; x: HSlice[U, V]; b: openArray[T])
template `[]=`(s: string; i: int; val: char)
proc `[]=`[I: Ordinal; T, S](a: T; i: I; x: S)
proc `[]=`[T, U, V](s: var seq[T]; x: HSlice[U, V]; b: openArray[T])
proc `[]=`[Idx, T](a: var array[Idx, T]; i: BackwardsIndex; x: T)
最终,这是某种形式的映射,因此我认为这段代码可以工作:
var arr = toSeq(0 ..< 5)
var sq_arr = map(arr, squared)
echo sq_arr
与之前相同的预期输出:
@[0, 1, 4, 9, 16]
但我得到的是(在 map
行):
Error: type mismatch: got <seq[int], proc (n: int64): int64{.noSideEffect, gcsafe, locks: 0.}>
but expected one of:
proc map[T](s: var openArray[T]; op: proc (x: var T) {.closure.})
first type mismatch at position: 2
required type: proc (x: var T){.closure.}
but expression 'squared' is of type: proc (n: int64): int64{.noSideEffect, gcsafe, locks: 0.}
proc map[T, S](s: openArray[T]; op: proc (x: T): S {.closure.}): seq[S]
first type mismatch at position: 2
required type: proc (x: T): S{.closure.}
but expression 'squared' is of type: proc (n: int64): int64{.noSideEffect, gcsafe, locks: 0.}
我做错了什么?
(我使用的是 Nim 0.19.0,但它也不适用于 Nim 0.18.0)。
错误发生是因为您试图使用 int64
来索引 result
序列。使用通用 int
平台类型访问序列,depending on your platform 可能是 32 位长或 64 位长。您可以将 squared_seq
参数更改为 int
并且它应该编译:
import sequtils
proc squared(n: int64): int64 = n * n
proc squared_seq(n: int): seq[int64] =
result = newSeq[int64](n)
for i in 0 ..< n:
result[i] = squared(i)
echo squared_seq(5)
或者,您可以将 int64
转换为 for i in 0 ..< int(n)
,但这可能很危险,具体取决于您传递给 proc 的值。
(感谢来自 freenode
中#nim 的@leorize、@mratsim 和@alehander42)。
第一个解决方案的问题是 seq
的索引必须是 int
并且 int64
到 int
的转换不是自动的。
像下面这样的东西会起作用,因为 squared
的签名所需的 int
到 int64
是自动的。
import sequtils
proc squared_seq(n: int64): seq[int64] =
result = newSeq[int64](n)
for i in 0 ..< int(n):
result[i] = squared(i)
或者,以下方法也有效:
proc squared_seq(n: int64): seq[int64] =
result = newSeq[int64](n)
for i in 0 ..< n:
result[int(i)] = squared(i)
但是我不太确定,如果以后只支持 int
索引,为什么 result = newSeq[int64](n)
不需要 n
是 int
。
不过,这似乎是一个不需要的功能。
关于映射方法,这里的问题是输入类型是int
,而squared()
需要int64
。在这种情况下,显然最好的方法是对 int
到 int64
序列使用某种代理方式,例如:
var arr = toSeq(0 ..< 5)
var sq_arr = map(arr, proc(x: int): int64 = squared(x))
或者,更好的是,强制 toSeq
产生 int64
,例如:
var arr = toSeq(0'i64 ..< 5'i64)
var sq_arr = map(arr, squared)
或者更好,使用 map
的类型放宽版本,即 mapIt
:
var arr = toSeq(0 ..< 5)
var sq_arr = mapIt(arr, squared(it))
这也应该会产生更快的代码。
根据标题,我有以下代码:
proc squared(n: int64): int64 = n * n
echo squared(5)
生成以下输出:
25
但是,如果我知道想要使用 squared
填充序列,我会这样写:
import sequtils
proc squared_seq(n: int64): seq[int64] =
result = newSeq[int64](n)
for i in 0 ..< n:
result[i] = squared(i)
echo squared_seq(5)
我希望这会产生以下输出:
@[0, 1, 4, 9, 16]
但我得到的只是以下错误(在 result[i] = ...
行):
Error: type mismatch: got <seq[int64], int64, int64>
but expected one of:
proc `[]=`(s: var string; i: BackwardsIndex; x: char)
proc `[]=`[T, U](s: var string; x: HSlice[T, U]; b: string)
proc `[]=`[T](s: var openArray[T]; i: BackwardsIndex; x: T)
proc `[]=`[Idx, T, U, V](a: var array[Idx, T]; x: HSlice[U, V]; b: openArray[T])
template `[]=`(s: string; i: int; val: char)
proc `[]=`[I: Ordinal; T, S](a: T; i: I; x: S)
proc `[]=`[T, U, V](s: var seq[T]; x: HSlice[U, V]; b: openArray[T])
proc `[]=`[Idx, T](a: var array[Idx, T]; i: BackwardsIndex; x: T)
最终,这是某种形式的映射,因此我认为这段代码可以工作:
var arr = toSeq(0 ..< 5)
var sq_arr = map(arr, squared)
echo sq_arr
与之前相同的预期输出:
@[0, 1, 4, 9, 16]
但我得到的是(在 map
行):
Error: type mismatch: got <seq[int], proc (n: int64): int64{.noSideEffect, gcsafe, locks: 0.}>
but expected one of:
proc map[T](s: var openArray[T]; op: proc (x: var T) {.closure.})
first type mismatch at position: 2
required type: proc (x: var T){.closure.}
but expression 'squared' is of type: proc (n: int64): int64{.noSideEffect, gcsafe, locks: 0.}
proc map[T, S](s: openArray[T]; op: proc (x: T): S {.closure.}): seq[S]
first type mismatch at position: 2
required type: proc (x: T): S{.closure.}
but expression 'squared' is of type: proc (n: int64): int64{.noSideEffect, gcsafe, locks: 0.}
我做错了什么?
(我使用的是 Nim 0.19.0,但它也不适用于 Nim 0.18.0)。
错误发生是因为您试图使用 int64
来索引 result
序列。使用通用 int
平台类型访问序列,depending on your platform 可能是 32 位长或 64 位长。您可以将 squared_seq
参数更改为 int
并且它应该编译:
import sequtils
proc squared(n: int64): int64 = n * n
proc squared_seq(n: int): seq[int64] =
result = newSeq[int64](n)
for i in 0 ..< n:
result[i] = squared(i)
echo squared_seq(5)
或者,您可以将 int64
转换为 for i in 0 ..< int(n)
,但这可能很危险,具体取决于您传递给 proc 的值。
(感谢来自 freenode
中#nim 的@leorize、@mratsim 和@alehander42)。
第一个解决方案的问题是 seq
的索引必须是 int
并且 int64
到 int
的转换不是自动的。
像下面这样的东西会起作用,因为 squared
的签名所需的 int
到 int64
是自动的。
import sequtils
proc squared_seq(n: int64): seq[int64] =
result = newSeq[int64](n)
for i in 0 ..< int(n):
result[i] = squared(i)
或者,以下方法也有效:
proc squared_seq(n: int64): seq[int64] =
result = newSeq[int64](n)
for i in 0 ..< n:
result[int(i)] = squared(i)
但是我不太确定,如果以后只支持 int
索引,为什么 result = newSeq[int64](n)
不需要 n
是 int
。
不过,这似乎是一个不需要的功能。
关于映射方法,这里的问题是输入类型是int
,而squared()
需要int64
。在这种情况下,显然最好的方法是对 int
到 int64
序列使用某种代理方式,例如:
var arr = toSeq(0 ..< 5)
var sq_arr = map(arr, proc(x: int): int64 = squared(x))
或者,更好的是,强制 toSeq
产生 int64
,例如:
var arr = toSeq(0'i64 ..< 5'i64)
var sq_arr = map(arr, squared)
或者更好,使用 map
的类型放宽版本,即 mapIt
:
var arr = toSeq(0 ..< 5)
var sq_arr = mapIt(arr, squared(it))
这也应该会产生更快的代码。