4

I need to unpack the varargs from a procedure's input to use as a procedure's individual arguments..

In python you can "unpack" lists of arguments for function calls like so:

def fun(a, b, c, d):
    print(a, b, c, d)
 
my_list = [1, 2, 3, 4]
 
# Unpacking list into four arguments
fun(*my_list)  # asterisk does the unpacking

So each item in the list is used as an individual argument in the function call.

Is this possible to do in nim? I know you can accept an arbitrary amount of procedure arguments with varargs but I want to unpack the sequence of arguments from varargs to use them as individual arguments for a different procedure call that doesn't accept varargs.

Let's say I'm trying to unpack a sequence of arguments to create a procedure that can run any arbitrary procedure(with an arbitrary amount of arguments) and tell the user how long it took to run said procedure. I don't want to write all my procedures to accept a varargs type and so unpacking the sequence would be the best solution, if possible.

import times


proc timeit*[T] (the_func: proc, passed_args: varargs[T]): float =
    let t = cpuTime()
    var the_results = the_func(passed_args)  # This is where I need to unpack arguments
    cpuTime() - t


proc test_func(x: int, y: int): int =
    x + y


echo timeit(test_func, 15, 5)

I know this code isn't correct and I'm very new to nim so I'm having some difficulties wrapping my head around the proper way to do this.

RattleyCooper
  • 4,997
  • 5
  • 27
  • 43

1 Answers1

4

See unpackVarargs from macros stdlib.

import std/[times, macros]

template timeIt*(theFunc: proc, passedArgs: varargs[typed]): float =
  let t = cpuTime()
  echo unpackVarargs(theFunc, passedArgs)
  cpuTime() - t

proc add2(arg1, arg2: int): int =
  result = arg1 + arg2

proc add3(arg1, arg2, arg3: float): float =
  result = arg1 + arg2 + arg3

echo timeIt(add2, 15, 5)
echo timeIt(add3, 15.5, 123.12, 10.009)

https://play.nim-lang.org/#ix=3rwD


Here's an alternative answer that doesn't even need unpackVarargs (Credit: GitHub @timotheecour).. it uses varargs[untyped] type in the timeIt template instead:

import std/[times]

template timeIt*(theFunc: proc, passedArgs: varargs[untyped]): float =
  let t = cpuTime()
  echo theFunc(passedArgs)
  cpuTime() - t

proc add2(arg1, arg2: int): int =
  result = arg1 + arg2

proc add3(arg1, arg2, arg3: float): float =
  result = arg1 + arg2 + arg3

echo timeIt(add2, 15, 5)
echo timeIt(add3, 15.5, 123.12, 10.009)

https://play.nim-lang.org/#ix=3rwM

Kaushal Modi
  • 1,258
  • 2
  • 20
  • 43