Choosing arity of a template function
A generic function receives an argument called "partition" by alias. That may work in one of the following ways: partition(range); partition!less(range); partition!less(range, n); // n is a number I tried this: static if (is(partition == function) || is(partition == delegate)) partition(r); else if (__traits(compiles, partition!less(r, n))) partition!less(r, n); else partition!less(r); The first test works very nice. The second does not; the compiler attempts to instantiate the template wrongly and spits a bunch of errors before giving up, in spite of the whole "let me know silently whether this compiles" thing. So, what's an elegant solution to this? I looked up std.traits but nothing seems to help. (Tried arity, no avail.) Thanks, Andrei
Re: Choosing arity of a template function
On 02/26/2016 06:09 PM, Andrei Alexandrescu wrote: A generic function receives an argument called "partition" by alias. That may work in one of the following ways: partition(range); partition!less(range); partition!less(range, n); // n is a number I tried this: static if (is(partition == function) || is(partition == delegate)) partition(r); else if (__traits(compiles, partition!less(r, n))) partition!less(r, n); else partition!less(r); The first test works very nice. The second does not; the compiler attempts to instantiate the template wrongly and spits a bunch of errors before giving up, in spite of the whole "let me know silently whether this compiles" thing. So, what's an elegant solution to this? I looked up std.traits but nothing seems to help. (Tried arity, no avail.) Urgh, forgot the "static" in front of the second "if". It does work now. Nevertheless, I'm still on lookout for a more elegant solution! I have this mindset that using __traits(compiles) is some sort of cheating. Andrei
Re: Choosing arity of a template function
On Friday, 26 February 2016 at 23:11:32 UTC, Andrei Alexandrescu wrote: Urgh, forgot the "static" in front of the second "if". It does work now. Perhaps that should be an error instead; Going from a static if to an else if... seems easy enough to spot and insist a fix (much like assignment inside an if statement is illegal).
Re: Choosing arity of a template function
On Friday, 26 February 2016 at 23:18:30 UTC, Era Scarecrow wrote: On Friday, 26 February 2016 at 23:11:32 UTC, Andrei Alexandrescu wrote: Urgh, forgot the "static" in front of the second "if". It does work now. Perhaps that should be an error instead; Going from a static if to an else if... seems easy enough to spot and insist a fix (much like assignment inside an if statement is illegal). What about automatically inferring it? It sounds reasonnable, much like saying that "static" actually is for the whole if/elseif block.
Re: Choosing arity of a template function
On Fri, 26 Feb 2016 23:46:11 +, cym13 wrote: > On Friday, 26 February 2016 at 23:18:30 UTC, Era Scarecrow wrote: >> On Friday, 26 February 2016 at 23:11:32 UTC, Andrei Alexandrescu wrote: >>> Urgh, forgot the "static" in front of the second "if". It does work >>> now. >> >> Perhaps that should be an error instead; Going from a static >> if to an else if... seems easy enough to spot and insist a fix (much >> like assignment inside an if statement is illegal). > > What about automatically inferring it? It sounds reasonnable, much like > saying that "static" actually is for the whole if/elseif block. static if (oggSupportEnabled) playOggFile(); else if (config.loggingEnabled) info("ogg support not enabled; skipping playback"); So, no, unless you want to make curly braces mandatory for conditional bodies.
Re: Choosing arity of a template function
On Friday, 26 February 2016 at 23:11:32 UTC, Andrei Alexandrescu wrote: Urgh, forgot the "static" in front of the second "if". It does work now. Nevertheless, I'm still on lookout for a more elegant solution! I have this mindset that using __traits(compiles) is some sort of cheating. There's nothing cheating about using __traits(compiles). It's basically the same as using is(typeof(foo)) and is(typeof({statement;})), albeit arguably a bit more explicit about the fact that it's testing what compiles. And there are plenty of cases where one of those is exactly what code should be doing. Now, if it's a test that needs to be done frequently, then it makes sense to create a wrapper for it that makes using it cleaner, so I think that you're right in the sense that we should be looking to have reusable traits to test with rather than using __traits(compiles) or is(typeof(blah)) heavily, but they're still fine to use when the occasion calls for it - especially if the test in question isn't something that's going to need to be done in much code. So, to a great extent, the question is whether what you're trying to do here is something that very many folks are going to want to do, and if it is, then we should find a way to do it without __traits(compiles), but if not, then I'm not sure that I'd worry much about it. - Jonathan M Davis
Re: Choosing arity of a template function
On Friday, 26 February 2016 at 23:53:06 UTC, Chris Wright wrote: On Fri, 26 Feb 2016 23:46:11 +, cym13 wrote: On Friday, 26 February 2016 at 23:18:30 UTC, Era Scarecrow wrote: On Friday, 26 February 2016 at 23:11:32 UTC, Andrei Alexandrescu wrote: Urgh, forgot the "static" in front of the second "if". It does work now. Perhaps that should be an error instead; Going from a static if to an else if... seems easy enough to spot and insist a fix (much like assignment inside an if statement is illegal). What about automatically inferring it? It sounds reasonnable, much like saying that "static" actually is for the whole if/elseif block. static if (oggSupportEnabled) playOggFile(); else if (config.loggingEnabled) info("ogg support not enabled; skipping playback"); So, no, unless you want to make curly braces mandatory for conditional bodies. Only for switching between static and non-static code. Besides with the static if's, 1 level of bracing doesn't make a new scope anyways (if i remember correctly).
Re: Choosing arity of a template function
On Sat, 27 Feb 2016 01:25:31 +, Era Scarecrow wrote: > On Friday, 26 February 2016 at 23:53:06 UTC, Chris Wright wrote: >> On Fri, 26 Feb 2016 23:46:11 +, cym13 wrote: >>> On Friday, 26 February 2016 at 23:18:30 UTC, Era Scarecrow wrote: On Friday, 26 February 2016 at 23:11:32 UTC, Andrei Alexandrescu wrote: > Urgh, forgot the "static" in front of the second "if". It does work > now. Perhaps that should be an error instead; Going from a static if to an else if... seems easy enough to spot and insist a fix (much like assignment inside an if statement is illegal). >>> >>> What about automatically inferring it? It sounds reasonnable, >>> much like saying that "static" actually is for the whole if/elseif >>> block. >> >> static if (oggSupportEnabled) >> playOggFile(); >> else >> if (config.loggingEnabled) >> info("ogg support not enabled; skipping playback"); >> >> So, no, unless you want to make curly braces mandatory for conditional >> bodies. > > Only for switching between static and non-static code. Besides > with the static if's, 1 level of bracing doesn't make a new scope > anyways (if i remember correctly). This would be a great thing for a lint tool to check, but for a language change, it's breaking, and the justification is a bit short.
Re: Choosing arity of a template function
It isn't cheating but IMO it's bad form. If you can do it without __traits(compiles) (or is(typeof()), etc.) you should, because there are many reasons why something will not compile, and only one of those reasons is the one you want to know. If there's no way around using it, you should still try to limit what is passed to __traits(compiles). enum hasFront(T) = __traits(compiles, { auto _ = T.init.font; }); It's fairly easy to spot such a typo when it's only one line, but the risk of having some other compiler error being the reason your static if branch isn't taken grows very quickly with each additional line or bit of complexity.
Re: Choosing arity of a template function
On 2/26/2016 3:09 PM, Andrei Alexandrescu wrote: (Tried arity, no avail.) Get the type of the function, the tuple of its parameter types, and the .length of that tuple.
Re: Choosing arity of a template function
On Friday, 26 February 2016 at 23:11:32 UTC, Andrei Alexandrescu wrote: On 02/26/2016 06:09 PM, Andrei Alexandrescu wrote: static if (is(partition == function) || is(partition == delegate)) partition(r); else if (__traits(compiles, partition!less(r, n))) partition!less(r, n); else partition!less(r); Nevertheless, I'm still on lookout for a more elegant solution! I have this mindset that using __traits(compiles) is some sort of cheating. I don't see it as cheating; in fact it is more elegant, because it checks for exactly the thing you depend on, namely that `partition` is callable. Your explicit check above rejects structs with opCall(), for example, which is probably not what you intended.
Re: Choosing arity of a template function
On 02/27/2016 07:38 AM, Marc Schütz wrote: I don't see it as cheating; in fact it is more elegant, because it checks for exactly the thing you depend on, namely that `partition` is callable. Your explicit check above rejects structs with opCall(), for example, which is probably not what you intended. Good point. Unrelated: I also noticed that if the template has an error inside, the error messages when using it with __traits(compiles) are mightily confusing. -- Andrei
Re: Choosing arity of a template function
On 27.02.2016 01:03, Jonathan M Davis wrote: There's nothing cheating about using __traits(compiles). It's basically the same as using is(typeof(foo)) and is(typeof({statement;})), albeit arguably a bit more explicit about the fact that it's testing what compiles. The two are subtly different and only __traits(compiles,...) reliably checks for compilability. Never use is(typeof(...)) unless you know exactly what you are doing. void main(){ int x; static void foo(){ static assert(is(typeof({return x;}))); static assert(!__traits(compiles,{return x;})); //auto a={return x;}; // error } }
Re: Choosing arity of a template function
On 02/27/2016 01:09 AM, Andrei Alexandrescu wrote: > static if (is(partition == function) || is(partition == delegate)) > partition(r); > else if (__traits(compiles, partition!less(r, n))) > partition!less(r, n); > else > partition!less(r); > > The first test works very nice. The second does not; the compiler > attempts to instantiate the template wrongly and spits a bunch of errors > before giving up, in spite of the whole "let me know silently whether > this compiles" thing. > > So, what's an elegant solution to this? I looked up std.traits but > nothing seems to help. (Tried arity, no avail.) Untested: bool hasArityOverload ( alias F ) ( ) { import std.traits; if (!isSomeFunction!(F!less)) return false; alias ParamTypes = Parameters!(F!less); if (ParamTypes.length != 2) return false; return isInputRange!(ParamTypes[0]) && is(ParamTypes[0] : uint); } Much more verbose but kess chance of accidental passing/failing by unrelated reasons. In "casual" application code I'd still probably go with `__traits(compiles)`.
Re: Choosing arity of a template function
On Friday, 26 February 2016 at 23:09:52 UTC, Andrei Alexandrescu wrote: So, what's an elegant solution to this? I looked up std.traits but nothing seems to help. (Tried arity, no avail.) There's this[1] PR which implements exactly what you want, but it's currently not passing the auto-tester. 1. https://github.com/D-Programming-Language/dmd/pull/5201
Re: Choosing arity of a template function
On 03/03/2016 02:54 PM, Meta wrote: On Friday, 26 February 2016 at 23:09:52 UTC, Andrei Alexandrescu wrote: So, what's an elegant solution to this? I looked up std.traits but nothing seems to help. (Tried arity, no avail.) There's this[1] PR which implements exactly what you want, but it's currently not passing the auto-tester. 1. https://github.com/D-Programming-Language/dmd/pull/5201 Thanks! That will push introspection considerably further. I toggled auto-pull. -- Andrei
Re: Choosing arity of a template function
On Thursday, 3 March 2016 at 21:06:12 UTC, Andrei Alexandrescu wrote: Thanks! That will push introspection considerably further. I toggled auto-pull. -- Andrei I would recommend cancelling that as it's currently failing on Linux and FreeBSD.
Re: Choosing arity of a template function
On Thursday, 3 March 2016 at 21:06:12 UTC, Andrei Alexandrescu wrote: Thanks! That will push introspection considerably further. I toggled auto-pull. -- Andrei I made the simplest change possible to get it to compile, PR here[1]. It adds an extra allocation so any suggestions on eliminating that are welcome. 1. https://github.com/D-Programming-Language/dmd/pull/5496