按照标题,我有以下代码:
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)。
答案 0 :(得分:1)
发生错误是因为您试图使用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的值。
答案 1 :(得分:1)
(感谢freenode
中#nim的@ leorize,@ mratsim和@ alehander42)。
第一个解决方案的问题是seq
的索引必须为int
,并且int64
到int
的转换不是自动的。
由于int
的签名所要求的int64
至squared
是自动的,因此类似以下的事情会起作用。
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)
但是,我不太确定,如果以后仅支持result = newSeq[int64](n)
索引,为什么n
不需要int
为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))
这还会产生更快的代码。