RFCs icon indicating copy to clipboard operation
RFCs copied to clipboard

RFC: Variadic Generics

Open barcharcraz opened this issue 12 years ago • 11 comments

As far as I can tell Nimrod does not support any kind of variadic generic. That is a generic procedure that can take 0 or more type arguments.

The motivation for this is for functions like printf where you would like to have a variadic function where each one of the variadic parameters has a different type. The varargs feature does not do this.

Both c++ and D implement variadic generics in such a way where a parameter of type T... can be zero or more types and it can be decomposed into T1, Rest... in a parameter list.

For reference both c++ and D support this feature http://dlang.org/variadic-function-templates.html Variadic Templates, section 14.5.3 of the latest c++ draft standard (n3242) Rust has a ticket open for this at: https://github.com/mozilla/rust/issues/10124

barcharcraz avatar Mar 20 '14 17:03 barcharcraz

This issue have two parts:

  1. Supporting the definitions of generic types such as TVariant that may depend on a list of types supplied as a parameter.

  2. Supporting procs taking heterogeneously typed varargs.

For point 1, there are several existing methods that you can try to explore - you can emulate the list of types as a single tuple type param. Then you'll be able to use some easily added magics to the typetraits module or just the good old type(x) operator that will let you access the individual types of the "list". Alternatively, you can represent the list as a single static[seq[typedesc]] param. This will have the advantage that any algorithms defined over sequences will work out of the box on type lists (no need for Boost.MPL). Both methods are not covered yet in the test suite, so be prepared for bugs and please send reports.

For point 2, the currently supported way is to rely on a macro that will accept the params and directly handle them or repackage them as a tuple that will be passed to a generic proc. In the manual, you'll find an example for a safePrintf marco that makes use of this approach: http://build.nim-lang.org/docs/manual.html#special-types-typedesc

A small task on my to-do list is to automate this repackaging as a tuple in order to let you write more easily such generic procs with heterogeneous varargs.

zah avatar Mar 20 '14 18:03 zah

$50 bounty has been posted on this issue https://www.bountysource.com/issues/1446763-rfc-variadic-generics. Thanks @Henry

dom96 avatar Aug 08 '15 22:08 dom96

Maybe some kind of HLists? https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0#heterogenous-lists

reactormonk avatar Aug 08 '15 22:08 reactormonk

@dom96 : No problem, I like the idea of BountySource and wanted to get the ball rolling.

I am migrating from Xl2 to Nim and in Xl2 variadic generics are a fundamental part of the design being used for multi-argument, multi-type write functions and I rather like this appoach. There is an example on https://en.wikipedia.org/wiki/XL_(programming_language) and examples provided:

// Test that simple recursive definitions of variadics work
use XL.UI.CONSOLE

generic type ordered

function MyMax (X : ordered) return ordered is
    WriteLn "MyMax one ", X
    return X

function MyMax (X : ordered; ...) return ordered is
    result := MyMax(...)
    Write "MyMax more ", X, " and ", result
    if result < X then
        result := X
    WriteLn " is ", result

K : integer := MyMax(1, 2, 3, 4)
M : real := MyMax (1.5, 7.9, 8.43)

WriteLn "K=", K
WriteLn "M=", M

While this example shows all the arguments of the same type they need not be as in the Write and WriteLn library functions:

to Write(F : file; W : writable; ...) is
// ------------------------------------------------------------------------
//   Write a writable and something else to a file
// ------------------------------------------------------------------------
    any.Write F, W
    any.Write F, ...

Maybe studying the implementation of variadic generics in the xl2 compiler will help.

Henry avatar Aug 09 '15 07:08 Henry

As far as syntax goes, why not simply reuse the varargs metatype? It's not as if a generic parameter list is actually restricted to typedesc arguments (see array constructors).

Varriount avatar Aug 09 '15 08:08 Varriount

The examples are all trivially implementable with a macro and/or varargs[T, conv].

Araq avatar Mar 29 '16 12:03 Araq

@Araq but there are still things like matrices and other areas that would benefit from variadic generic types.

Varriount avatar Mar 29 '16 19:03 Varriount

It should be easy enough to use tuples and the getType API in these cases though. Somebody needs to write this code and demonstrate what problems it causes.

Araq avatar Mar 29 '16 19:03 Araq

@Araq, does your method allow for taking a variable number of template parameter constants (say, ints) and generating an array of function pointers from a template function with them? E.g. in C++:

template <int o>
int offset(const int i)
{
    return i - o;
}

template <int... Offs>
void make_funcs()
{
    std::array<std::function<int(int)>, sizeof...(Offs)> offs{ offset<Offs>... };
    // [...]
}

Pardon me if it's obvious to do this with compile time functions in Nim, but I'm curious, because this sort of pattern heavily simplifies metaprogramming for me.

seankhl avatar Jun 09 '16 04:06 seankhl

variadic generics would help the createThead proc. now the startable procs have an arbitrary arity of one.

lightness1024 avatar Apr 05 '18 14:04 lightness1024

The benefits are tiny, Nim has tuples, you can pass a tuple to thread proc.

Araq avatar Apr 05 '18 22:04 Araq