digitalmars.D.learn - How to get number of parameters in lambda?
- Andrey Zherikov (8/8) Mar 08 2021 What should I use to get number of lambda arguments? Like get 2
- Paul Backus (5/13) Mar 08 2021 Typeless lambdas are templates, and there's no way to examine the
- Andrey Zherikov (15/16) Mar 08 2021 Just to make things simple: I have a 'caller' that calls some
- Paul Backus (22/38) Mar 08 2021 If you know the arguments you want to call the function with, the
- Paul Backus (2/4) Mar 08 2021 Typo; this should of course say `f(1, 2)`.
- Adam D. Ruppe (8/10) Mar 08 2021 It'd be nice if we could at least get the arity of a template,
- Andrey Zherikov (5/30) Mar 09 2021 In case of function template this is possible but the original
- Paul Backus (7/10) Mar 09 2021 Yes, you're correct. The issue is that the compiler currently
What should I use to get number of lambda arguments? Like get 2 for "(arg1, arg2) {}". std.traits.Parameters doesn't work because isCallable returns false. alias f = (arg1, arg2) {}; writeln(isCallable!f); // prints false Specifying argument types works, e.g. isCallable returns true for (int arg1, int arg2) {}, but I'm looking for a solution for type-less lambdas.
Mar 08 2021
On Monday, 8 March 2021 at 23:07:18 UTC, Andrey Zherikov wrote:What should I use to get number of lambda arguments? Like get 2 for "(arg1, arg2) {}". std.traits.Parameters doesn't work because isCallable returns false. alias f = (arg1, arg2) {}; writeln(isCallable!f); // prints false Specifying argument types works, e.g. isCallable returns true for (int arg1, int arg2) {}, but I'm looking for a solution for type-less lambdas.Typeless lambdas are templates, and there's no way to examine the arguments of a template function without first instantiating it, so I'm afraid you're out of luck. What's the larger problem you're trying to solve here?
Mar 08 2021
On Tuesday, 9 March 2021 at 01:38:52 UTC, Paul Backus wrote:What's the larger problem you're trying to solve here?Just to make things simple: I have a 'caller' that calls some function provided as an alias template argument and I want to support different number of arguments (purpose is to provide additional parameters if 'f' supports): void caller(alias f)() { static if(/*one parameter*/) f(1); else static if(/*two parameters*/) f(1, 2); } I understand that types are not available since they are undefined until instantiation. But why can't I get argument count? Is it possible that it can change during instantiation?
Mar 08 2021
On Tuesday, 9 March 2021 at 02:24:07 UTC, Andrey Zherikov wrote:On Tuesday, 9 March 2021 at 01:38:52 UTC, Paul Backus wrote:If you know the arguments you want to call the function with, the easiest way to check if you can do it is with __traits(compiles): static if (__traits(compiles, f(1))) f(1); else static if (__traits(compiles, f(1, 2))) f(2);What's the larger problem you're trying to solve here?Just to make things simple: I have a 'caller' that calls some function provided as an alias template argument and I want to support different number of arguments (purpose is to provide additional parameters if 'f' supports): void caller(alias f)() { static if(/*one parameter*/) f(1); else static if(/*two parameters*/) f(1, 2); }I understand that types are not available since they are undefined until instantiation. But why can't I get argument count? Is it possible that it can change during instantiation?Yes, it's possible. For example: template fun(T) { static if (is(T == int)) { void fun(T a, T b) { /* ... */ } } else { void fun(T a) { /* ... */ } } } Of course, code like this is rare in practice, but because it's technically possible, the compiler can't assume *anything* about a template function before it's been instantiated.
Mar 08 2021
On Tuesday, 9 March 2021 at 03:08:14 UTC, Paul Backus wrote:else static if (__traits(compiles, f(1, 2))) f(2);Typo; this should of course say `f(1, 2)`.
Mar 08 2021
On Tuesday, 9 March 2021 at 03:08:14 UTC, Paul Backus wrote:Yes, it's possible. For example: template fun(T) {It'd be nice if we could at least get the arity of a template, then perhaps speculatively instantiate it and reflect on the eponymous function then. (that's a lot of jargon lol but like some kind of reflection over template parameters is definitely possible... just the compiler doesn't offer any facilities for it at all. Then once you're past that layer you can start trying other things.)
Mar 08 2021
On Tuesday, 9 March 2021 at 03:08:14 UTC, Paul Backus wrote:If you know the arguments you want to call the function with, the easiest way to check if you can do it is with __traits(compiles): static if (__traits(compiles, f(1))) f(1); else static if (__traits(compiles, f(1, 2))) f(2);Yes, I can do some magic with this.In case of function template this is possible but the original question was about lambdas. There is no way that lambda can change number of parameters during instantiation, am I right?I understand that types are not available since they are undefined until instantiation. But why can't I get argument count? Is it possible that it can change during instantiation?Yes, it's possible. For example: template fun(T) { static if (is(T == int)) { void fun(T a, T b) { /* ... */ } } else { void fun(T a) { /* ... */ } } } Of course, code like this is rare in practice, but because it's technically possible, the compiler can't assume *anything* about a template function before it's been instantiated.
Mar 09 2021
On Tuesday, 9 March 2021 at 14:22:44 UTC, Andrey Zherikov wrote:In case of function template this is possible but the original question was about lambdas. There is no way that lambda can change number of parameters during instantiation, am I right?Yes, you're correct. The issue is that the compiler currently can't tell the difference between a template lambda and a non-lambda function template. This could be changed, but having a language feature that works for lambdas but not for named functions is probably not such a great idea.
Mar 09 2021