Логическая векторная операция в стиле r в nim

Кто-нибудь знает, есть ли в Nim функция вроде ifelse в R, которая позволяет применять условные вычисления к векторам, эквивалентные:

a<-c(1,2,3,4)
b<-c(7,2,7,4)
c<-ifelse(a==b,a*b,a+b)

использование цикла и оператора if, else будет слишком медленным для больших векторов.

У меня есть несколько вопросов: когда вы говорите «использование цикла», вы имеете в виду использование цикла для циклического перебора векторных полей во время выполнения? Когда вы говорите «большой вектор», вы имеете в виду большие числа в векторе?

Benjamin 04.11.2018 05:11

jk Я читал о векторах в R, я дам вам ответ сегодня вечером или завтра. В любом случае «Векторы» Нима называются «Кортежами». И они делают именно то, о чем вы просите. Если функциональность, которую вы ищете, не встроена, вы можете написать то, что вам нужно.

Benjamin 04.11.2018 05:21
0
2
181
1

Ответы 1

Итак. В Nim кортеж использует ту же идею, что и вектор в R: структурная типизация. Надеюсь, я здесь на правильном пути. У Nim есть возможность делать что-то во время компиляции, а не во время выполнения, поэтому функции, встроенные для кортежей, такие как ==, имеют цикл в исходном коде, но на самом деле цикл распутывается во время компиляции, и поля ссылаются непосредственно во время выполнения. Таким образом, для скорости Tuple == Tuple будет максимально быстрым, независимо от количества полей в Tuple. Это можно проверить с помощью исходный код.

Я уверен, что вы сможете сделать именно то, о чем просите, убедившись, что эта небольшая функция, которую я написал, работает, поскольку * не был встроен для кортежей:

let
  v1 = (1,2,3,4)
  v2 = (7,2,7,4)

proc `*`[T:tuple](x, y: T): T =
  for a,b in fields(x, result):
    b = a
  for a,b in fields(y, result):
    b = b * a

echo $(v1 * v2) #prints (Field0: 7, Field1: 4, Field2: 21, Field3: 16)

Мы могли бы написать ту же функцию для сложения:

let
  v1 = (1,2,3,4)
  v2 = (7,2,7,4)

proc `+`[T:tuple](x, y: T): T =
  for a,b in fields(x, result):
    b = a
  for a,b in fields(y, result):
    b = b + a

echo $(v1 + v2)

Вот полный пример, который представляет собой комбинацию форум и функций выше:

proc `+`[T:tuple](x, y: T): T =
  for a,b in fields(x, result):
    b = a
  for a,b in fields(y, result):
    b = b + a

proc `*`[T:tuple](x, y: T): T =
  for a,b in fields(x, result):
    b = a
  for a,b in fields(y, result):
    b = b * a

let
  a = (1,2,3,4)
  b = (7,2,7,4)
  c = if v1 == v2: v1 * v2 else: v1 + v2

Надеюсь это поможет!

Спасибо, Бенджамин. По поводу ваших вопросов смотрите также forum.nim-lang.org/t/4343. В среде Ifelse было бы полезно переопределить все операнды для навыков кортежа. Возможно, эти расширенные операнды следует переименовать, чтобы их можно было использовать и вне функции ifelse (не затрагивая поведение классических операндов).

Nimrookie 05.11.2018 10:18

@Nimrookie Это то, что вы искали? Я очень заинтригован.

Benjamin 05.11.2018 15:13

@Nimrookie У меня такое чувство, что этот метод быстрее массивов. Вы хотите, чтобы я проверил это для вас?

Benjamin 05.11.2018 15:19

@Nimrookie В случае кортежей эти операторы вообще не были определены. На самом деле нет никаких изменений предыдущего поведения для + и *, потому что поведения не существовало, поэтому я не могу придумать вескую причину не использовать их. Как бы то ни было, это было бы чем-то, что могли бы подбросить другие участники Nim. Вы предлагаете добавить эту функцию в системный модуль Nim?

Benjamin 05.11.2018 15:31

@ Бенджамин: Да, было бы здорово! У меня есть опыт работы с C, гораздо больше с R и без нимов. Для моей задачи R ограничен производительностью, а C - слишком трудный путь с точки зрения рабочего процесса - если Nim такой способ, это было бы здорово. Заранее спасибо!

Nimrookie 05.11.2018 22:59

Другие вопросы по теме