Thread overview
What does __parameters return?
Sep 12, 2013
simendsjo
Sep 12, 2013
H. S. Teoh
Sep 12, 2013
simendsjo
Sep 12, 2013
H. S. Teoh
Sep 12, 2013
Andrej Mitrovic
Sep 13, 2013
simendsjo
Sep 13, 2013
Jacob Carlborg
Sep 13, 2013
simendsjo
September 12, 2013
The documentation says "the parameter tuple of a function, delegate, or function pointer. This includes the parameter types, names, and default values."

.. but what type is it?

Error: argument (int i, char c, string s, bool b = false) to typeof is not an expression

How am I supposed to get the parameter names using this?

It's possible to use .stringof, and then regular string handling to extract the names, but I guess there should be a simpler way if only I knew what it returned.
September 12, 2013
On Thu, Sep 12, 2013 at 08:44:29PM +0200, simendsjo wrote:
> The documentation says "the parameter tuple of a function, delegate, or function pointer. This includes the parameter types, names, and default values."
> 
> .. but what type is it?
> 
> Error: argument (int i, char c, string s, bool b = false) to typeof
> is not an expression
> 
> How am I supposed to get the parameter names using this?
> 
> It's possible to use .stringof, and then regular string handling to extract the names, but I guess there should be a simpler way if only I knew what it returned.

You're not going to like the answer to this one... :)

Here's some example code that uses __parameters to inspect a function and print out a list of its parameter types and names (my explanations are in the comments):

-------------snip-------------
import std.stdio;

// Example function we want to examine parameters for
int func(string x, float y, int z=123) {
	return 0;
}

void main() {
	// __parameters appears to only work inside is(...), in a quirky
	// special-cased syntax that ONLY works when written exactly in the
	// form is(TypeOfFunc Ident == __parameters), in which case Ident gets
	// aliased to a "parameter tuple", an elusive compiler internal entity
	// that is similar to, but not the same as, a "type tuple".
	static if (is(typeof(func) Params == __parameters)) {
		// You already know what does one this, I believe.
		pragma(msg, Params.stringof);

		// foreach works on parameter tuples, but it acts very weird.
		// If a single argument is given, it gets assigned to the
		// *type* of the parameter in question. If two arguments are
		// given, like here, the first is assigned the index into the
		// parameter tuple, and the second to the *type* of the
		// corresponding parameter.
		foreach (i, T; Params) {
			// This quirky behaviour of foreach on parameter tuples
			// means T is *not* the parameter itself, merely the
			// *type* of the parameter. To get the actual
			// parameter's description, we need a 1-element slice
			// of the parameter tuple. Thankfully, i has been
			// conveniently assigned the index of the current
			// parameter, so we can use that for the slicing:
			alias Param = Params[i .. i+1];

			// As I said, T is merely the type of the parameter,
			// not the parameter itself.
			alias ParamType = T;

			// The 1-element slice Param behaves as if it's an
			// independent entity with a name, so we can use
			// __traits(identifer, ...) to get at the parameter
			// name.
			string ParamName = __traits(identifier, Param);

			writeln("type=", T.stringof, " name=", ParamName);

			// Not shown here is the default parameter value.
			// Looking at std.traits.ParameterDefaultValueTuple,
			// there appears to be no direct way to get at this.
			// The only way seems to be to declare a function with
			// Param as its single argument, and then call that
			// function with no arguments so that the function can
			// return the default value of the parameter. This is
			// what Phobos actually does to build the default
			// parameter tuple.

			// Also not shown here is how to get at the
			// storage class of the parameter; I didn't look
			// into this, but your best reference would be
			// std.traits.ParameterStorageClass' code.
		}
	}
}
-------------snip-------------

Given the non-intuitive quirkiness of the whole thing, you're probably far better off using Phobos' std.traits.Parameter...Tuple templates to get at the various bits of function parameters.

Or just parse the string returned by the .stringof value, as you suggested.


T

-- 
Never wrestle a pig. You both get covered in mud, and the pig likes it.
September 12, 2013
On Thursday, 12 September 2013 at 19:41:26 UTC, H. S. Teoh wrote:
> On Thu, Sep 12, 2013 at 08:44:29PM +0200, simendsjo wrote:
(...)
>> .. but what type is it?
>> 
>> Error: argument (int i, char c, string s, bool b = false) to typeof
>> is not an expression
>> 
>> How am I supposed to get the parameter names using this?
>> 
(...)
>
> You're not going to like the answer to this one... :)
>
(...)
>
> Or just parse the string returned by the .stringof value, as you
> suggested.
>

Thanks. I just ended up using both is(__parameters and is(function to fetch the parameter names. Sometimes it seems things are added to D without a very thorough design phase, but then again, it starts with "__", so I guess I'm on my own :)
September 12, 2013
On Thu, Sep 12, 2013 at 10:40:06PM +0200, simendsjo wrote:
> On Thursday, 12 September 2013 at 19:41:26 UTC, H. S. Teoh wrote:
> >On Thu, Sep 12, 2013 at 08:44:29PM +0200, simendsjo wrote:
> (...)
> >>.. but what type is it?
> >>
> >>Error: argument (int i, char c, string s, bool b = false) to typeof
> >>is not an expression
> >>
> >>How am I supposed to get the parameter names using this?
> >>
> (...)
> >
> >You're not going to like the answer to this one... :)
> >
> (...)
> >
> >Or just parse the string returned by the .stringof value, as you suggested.
> >
> 
> Thanks. I just ended up using both is(__parameters and is(function to fetch the parameter names. Sometimes it seems things are added to D without a very thorough design phase, but then again, it starts with "__", so I guess I'm on my own :)

I think Walter's official statement on the matter is that __traits is not intended to be used by user code, but to allow Phobos to access compiler internals so that it can provide more user-friendly wrappers around the raw functionality.


T

-- 
Nobody is perfect.  I am Nobody. -- pepoluan, GKC forum
September 12, 2013
On 9/12/13, simendsjo <simendsjo@gmail.com> wrote:
> Thanks. I just ended up using both is(__parameters and is(function to fetch the parameter names. Sometimes it seems things are added to D without a very thorough design phase, but then again, it starts with "__", so I guess I'm on my own :)

Have you tried using ParameterIdentifierTuple from std.traits?
September 13, 2013
On Thursday, 12 September 2013 at 21:33:48 UTC, Andrej Mitrovic wrote:
> On 9/12/13, simendsjo <simendsjo@gmail.com> wrote:
>> Thanks. I just ended up using both is(__parameters and
>> is(function to fetch the parameter names. Sometimes it seems
>> things are added to D without a very thorough design phase, but
>> then again, it starts with "__", so I guess I'm on my own :)
>
> Have you tried using ParameterIdentifierTuple from std.traits?

The problem with this is that you need to supply the symbol. If you are located inside an overloaded function, you will get the first function defined when using the function name. This means you'll have to look at the parent, get overloads, and then find the correct overload (the one you're currently in) by doing some __parameters hacking.

And if you're in a templated function, it looks even worse. Seems I cannot get the "overloads" of a template.

So my solution is to use a mixin template..

The template itself defines a dummy variable (so you don't have to pass a symbol), use __traits(parent), and then use __parameters and __traits(function) to find the names.

Of course, calling ParameterIdentifierTuple!(__traits(parent ... in the mixin template simplifies the implementation quite a bit.

Didn't know you could call __traits(identifier for the __parameter values. __parameters is practically undocumented, and doesn't even have an example.
September 13, 2013
On 2013-09-13 08:33, simendsjo wrote:

> Didn't know you could call __traits(identifier for the __parameter
> values. __parameters is practically undocumented, and doesn't even have
> an example.

It's documented here:

http://dlang.org/expression.html#IsExpression

Scroll down to the table, next to format 6. Sure, it's not documented much, but at least it's mentioned.

-- 
/Jacob Carlborg
September 13, 2013
On Friday, 13 September 2013 at 07:42:48 UTC, Jacob Carlborg wrote:
> On 2013-09-13 08:33, simendsjo wrote:
>
>> Didn't know you could call __traits(identifier for the __parameter
>> values. __parameters is practically undocumented, and doesn't even have
>> an example.
>
> It's documented here:
>
> http://dlang.org/expression.html#IsExpression
>
> Scroll down to the table, next to format 6. Sure, it's not documented much, but at least it's mentioned.

Yeah, I copied the documentation in my first post - a single line: "the parameter tuple of a function,
delegate, or function pointer. This includes the parameter types,
names, and default values."

But it's quite strange..