0

does anyone know if Nim has a function like 'ifelse' in R that allows to apply conditional calculations on vectors, equivalent to:

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

using a loop and 'if, else' statement would be too slow for large vectors.

Nimrookie
  • 79
  • 3
  • I have some questions: When you say, "using a loop," do you mean using a loop to loop through the vector's fields at runtime? When you say a "large vector" do you mean large numbers in the vector? – Benjamin Nov 04 '18 at 04:11
  • jk I read up on vectors in R I will give you an answer either tonight or tomorrow. In any case, Nim's "Vectors" are called "Tuples". And they do exactly what you're asking. If the functionality you are looking for isn't built in, you could write what you needed. – Benjamin Nov 04 '18 at 04:21

1 Answers1

1

Ok so. In Nim a Tuple uses the same idea as a vector in R: structural typing. Hopefully I'm on track here. Nim has the ability to do stuff during compile time as opposed to runtime, so the functions that are built in for Tuples, like == have a loop in their source code, but in actuality the loop is unraveling at compile time, and the fields are being referenced directly at runtime. So for speed, Tuple == Tuple will be as fast as it could possibly be, regardless of the number of fields in the Tuple. This can be verified via the source code.

I am certain you can do exactly what you are asking after verifying that this little function I wrote works since * wasn't built in for Tuples:

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)

We could write the same function for addition:

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)

Here's a full example which is a combination of the forum convo and the functions above:

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

Hope this helps!

Benjamin
  • 1,832
  • 1
  • 17
  • 27
  • Thanks Benjamin. With regard to your questions please see also https://forum.nim-lang.org/t/4343. In the environment of Ifelse a re-definition of all operands for tuple skills would be useful. Maybe this advanced operands should be renamed - so they can be used outside ifelse-function as well (without touching behavior of classical operands). – Nimrookie Nov 05 '18 at 09:18
  • @Nimrookie Is this what you were looking for? I'm very intrigued. – Benjamin Nov 05 '18 at 14:13
  • @Nimrookie I have a feeling this method is faster than arrays. Would you like me to test that out for you? – Benjamin Nov 05 '18 at 14:19
  • @Nimrookie In the case of tuples, these operators were not defined at all. There isn't really any modification of previous behavior for + and * because the behavior didn't exist so I can't think of a good reason to not use them. Regardless, that would be something some fellow Nim contributors could throw around. Are you suggesting this functionality should be added to the Nim system module? – Benjamin Nov 05 '18 at 14:31
  • @ Benjamin: Yes that would be great! I have some C experience, much more R and no Nim. For my task R is limited by performance and C is a too stony path in term of workflow - if Nim is the way this would be great. Thanks in advance! – Nimrookie Nov 05 '18 at 21:59