Создать новую последовательность со значениями из функции - PullRequest
0 голосов
/ 28 ноября 2018

В соответствии с заголовком у меня есть следующий код:

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 тоже не работает).

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

(Благодаря @leorize, @mratsim и @ alehander42 из #nim в freenode).

Проблема с первыми решениями заключается в том, что индекс 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 индексы.Хотя это кажется нежелательной функцией.

Что касается подхода mapping , проблема здесь в том, что тип ввода - 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))

, которая также должна производить быстреекод.

0 голосов
/ 28 ноября 2018

Ошибка возникает из-за того, что вы пытаетесь использовать int64 для индексации последовательности result.Доступ к последовательностям осуществляется с использованием общего типа платформы int, который в зависимости от вашей платформы может иметь длину 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), но это может быть опасно в зависимости от значений, которые выперейти к процедуре.

...