Thread overview
Get variable symbol name that was passed to a paramater?
Nov 09, 2013
Rob T
Nov 09, 2013
Dicebot
Nov 09, 2013
Rob T
Nov 10, 2013
Timothee Cour
Nov 11, 2013
Rob T
Nov 11, 2013
Rob T
Nov 11, 2013
Dicebot
Nov 10, 2013
Timon Gehr
Nov 10, 2013
Timon Gehr
Oct 15, 2019
Arredondo
November 09, 2013
I have a template function called "inspect" that takes two variables as arguments,

void inspect(T)( string symbol, T value )
{
   writeln(symbol, " = ", value);
}

int y = 100;

inspect( y.stringof, y );

writes to console

y = 100

I am wondering if there's a way to pass only the variable and have the inspect function determine the variable's symbol name as passed rather than have to pass both the name and value separately?

void inspect(T)( T value )
{
   writeln( ? , " = ", value);
}


I've tried a template with alias parameter

void inspect(alias value)()
{
   writeln( value.stringof , " = ", value);
}

It works except when passing a variable contained inside a struct or class due to a missing "this" during evaluation, I'm also worried about template bloat.

I figure mixins may help, but not if it's same or less convenient to use as the double entry method.

Any suggestions, or is it just impossible or not worth trying?

--rt
November 09, 2013
On Saturday, 9 November 2013 at 09:12:21 UTC, Rob T wrote:
> It works except when passing a variable contained inside a struct or class due to a missing "this" during evaluation, I'm also worried about template bloat.
>
> I figure mixins may help, but not if it's same or less convenient to use as the double entry method.
>
> Any suggestions, or is it just impossible or not worth trying?

I have not found good workaround for this so far and consider it a main use case for template alias parameter enhancement.
November 09, 2013
On Saturday, 9 November 2013 at 11:07:08 UTC, Dicebot wrote:
> On Saturday, 9 November 2013 at 09:12:21 UTC, Rob T wrote:
>> It works except when passing a variable contained inside a struct or class due to a missing "this" during evaluation, I'm also worried about template bloat.
>>
>> I figure mixins may help, but not if it's same or less convenient to use as the double entry method.
>>
>> Any suggestions, or is it just impossible or not worth trying?
>
> I have not found good workaround for this so far and consider it a main use case for template alias parameter enhancement.

Do you know if there's already a enhancement request posted for this? I'll make one if not.
November 10, 2013
can your 'inspect' method handle:
* multiple arguments?
* expressions?

I wrote a function that does both, it's one of those things that are very useful for quick debugging:

import util.prettyprint;
void main(){
  int x=23;
  double y=2.4;
  writelnL(x,y,x*y);
}

//output:
file test.d:7 {
  x=int{23},
  y=double{2.4},
  x*y=double{55.2},
}

-----
The way it works:
void writelnL(string file=__FILE__, Line_t line=__LINE__, T...)(T args){
...
auto argNames=getArgNamesFromFile(file,line);
...
}

This reads at runtime file/line and caches the information with memoize to avoid re-reading the same file/line multiple times. I had also tried reading the file/line at compile time using import(file)[line] but that resulted in massive compile time slow-downs even when the actual writelnL wasn't used at runtime. Then the code parses the line to extract each argument names using a simplified D grammar.

However this still has some runtime penalty (reading a whole file just for
1 line) and is doing more work than necessary, as compiler has access to
this info.
I've already asked for this in the past (see email: "feature request:
__ARGS__ for logging (cf __FILE__, __LINE__, __FUNC___):

but Jacob pointed out that AST macros would make this un-necessary (like wise with another proposal I made "proposal: a new string litteral to embed variables in a string" ):

"I don't think that __ARGS__ is a bad idea, I just think that there are several features in D which could be replaced with a library solution using AST macros (if those were available)"

So let's either get a roadmap for introducing AST macros (preferred) or let's allow this very simple __ARGS__ in the language.



On Sat, Nov 9, 2013 at 11:05 AM, Rob T <alanb@ucora.com> wrote:

> On Saturday, 9 November 2013 at 11:07:08 UTC, Dicebot wrote:
>
>> On Saturday, 9 November 2013 at 09:12:21 UTC, Rob T wrote:
>>
>>> It works except when passing a variable contained inside a struct or class due to a missing "this" during evaluation, I'm also worried about template bloat.
>>>
>>> I figure mixins may help, but not if it's same or less convenient to use as the double entry method.
>>>
>>> Any suggestions, or is it just impossible or not worth trying?
>>>
>>
>> I have not found good workaround for this so far and consider it a main use case for template alias parameter enhancement.
>>
>
> Do you know if there's already a enhancement request posted for this? I'll make one if not.
>


November 10, 2013
On 11/09/2013 10:12 AM, Rob T wrote:
>
> I am wondering if there's a way to pass only the variable and have the
> inspect function determine the variable's symbol name as passed rather
> than have to pass both the name and value separately?
> ...

Well, yes, but the following does not scale that well, and it is somewhat fragile, since there is no way to get column information.

import std.stdio;
import std.string;
import std.algorithm;
import std.range;
import std.conv;

template LineCache(string f){ enum LineCache = import(__FILE__).splitLines(); }

void inspect(string f=__FILE__,int l=__LINE__,T)( T value ){
    enum name=LineCache!__FILE__[l-1].find("inspect").drop("inspect".length).find("(").drop(1).until!(a=>a==')').to!string.strip;
    writeln(name ~ " = ", value);
}

void main(){
    int a;
    int b=3;
    inspect(a);
    inspect(a+2);
    inspect(a+b);
}


$ dmd -J. -run tt.d
a = 0
a+2 = 2
a+b = 3

November 10, 2013
On 11/10/2013 01:51 AM, Timon Gehr wrote:
> On 11/09/2013 10:12 AM, Rob T wrote:
>>
>> I am wondering if there's a way to pass only the variable and have the
>> inspect function determine the variable's symbol name as passed rather
>> than have to pass both the name and value separately?
>> ...
>
> Well, yes, but the following does not scale that well, and it is
> somewhat fragile, since there is no way to get column information.
>
> import std.stdio;
> import std.string;
> import std.algorithm;
> import std.range;
> import std.conv;
>
> template LineCache(string f){ enum LineCache =
> import(__FILE__).splitLines(); }
>
> void inspect(string f=__FILE__,int l=__LINE__,T)( T value ){
>      enum
> name=LineCache!__FILE__[l-1].find("inspect").drop("inspect".length).find("(").drop(1).until!(a=>a==')').to!string.strip;
> ...

Oops. There's a typo. It should read LineCache!f, obviously.

>      writeln(name ~ " = ", value);
> }
>
> void main(){
>      int a;
>      int b=3;
>      inspect(a);
>      inspect(a+2);
>      inspect(a+b);
> }
>
>
> $ dmd -J. -run tt.d
> a = 0
> a+2 = 2
> a+b = 3
>

November 11, 2013
On Saturday, 9 November 2013 at 11:07:08 UTC, Dicebot wrote:
> On Saturday, 9 November 2013 at 09:12:21 UTC, Rob T wrote:
>> It works except when passing a variable contained inside a struct or class due to a missing "this" during evaluation, I'm also worried about template bloat.
>>
>> I figure mixins may help, but not if it's same or less convenient to use as the double entry method.
>>
>> Any suggestions, or is it just impossible or not worth trying?
>
> I have not found good workaround for this so far and consider it a main use case for template alias parameter enhancement.


There are other corner cases where alias for the inspect function will fail. For example, when used inside a class or struct method, a compiler error results stating that the symbol is not accessible to a non-global function.

It may be that enhancing alias is not the right way to solve this problem.

As was mentioned, the other method of importing and parsing the source file won't scale well and are ridiculous overkill for what should be a simple thing to do.

--rt
November 11, 2013
On Sunday, 10 November 2013 at 00:08:11 UTC, Timothee Cour wrote:
[...]
> I've already asked for this in the past (see email: "feature request:
> __ARGS__ for logging (cf __FILE__, __LINE__, __FUNC___):
>
> but Jacob pointed out that AST macros would make this un-necessary (like
> wise with another proposal I made "proposal: a new string litteral to embed
> variables in a string" ):
>
> "I don't think that __ARGS__ is a bad idea, I just think that there are
> several features in D which could be replaced with a library solution using
> AST macros (if those were available)"
>
> So let's either get a roadmap for introducing AST macros (preferred) or
> let's allow this very simple __ARGS__ in the language.
>

Agreed. I did think that AST macro's may present a solution, also the __ARGS__ solution is a good possibility too. I use __PRETTY_FUNCTION__ a lot now that we finally got it, and __ARGS__ would be an excellent addition that I would definitely use.

If AST macros can allow us to define library solutions to create something like  __PRETTY_FUNCTION__ and __ARGS__, that would be the ultimate solution for sure.

--rt
November 11, 2013
On Monday, 11 November 2013 at 00:59:03 UTC, Rob T wrote:
> There are other corner cases where alias for the inspect function will fail. For example, when used inside a class or struct method, a compiler error results stating that the symbol is not accessible to a non-global function.
>
> It may be that enhancing alias is not the right way to solve this problem.
>
> As was mentioned, the other method of importing and parsing the source file won't scale well and are ridiculous overkill for what should be a simple thing to do.

What I mean is that template alias parameter is intended to be a pass-by-name thing. But the way it works it capture the symbol name tied to the type, not symbol name of actual instance. As it is a template it should be always possible to refer to variable/field valid in instantiating context via such aliased name without loosing actual data context. But it will require considerably more powerful alias definition.
October 15, 2019
So, 6 years later, what is the idiomatic way of doing this? Has there been any progress on this matter?

As far as I can tell from this thread, all proposed solutions are imperfect in some way, which is a shame for a language with "Second to none reflection".

Arredondo.

On Saturday, 9 November 2013 at 09:12:21 UTC, Rob T wrote:
> I have a template function called "inspect" that takes two variables as arguments,
>
> void inspect(T)( string symbol, T value )
> {
>    writeln(symbol, " = ", value);
> }
>
> int y = 100;
>
> inspect( y.stringof, y );
>
> writes to console
>
> y = 100
>
> I am wondering if there's a way to pass only the variable and have the inspect function determine the variable's symbol name as passed rather than have to pass both the name and value separately?
>
> void inspect(T)( T value )
> {
>    writeln( ? , " = ", value);
> }
>
>
> I've tried a template with alias parameter
>
> void inspect(alias value)()
> {
>    writeln( value.stringof , " = ", value);
> }
>
> It works except when passing a variable contained inside a struct or class due to a missing "this" during evaluation, I'm also worried about template bloat.
>
> I figure mixins may help, but not if it's same or less convenient to use as the double entry method.
>
> Any suggestions, or is it just impossible or not worth trying?
>
> --rt