www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Get variable symbol name that was passed to a paramater?

reply "Rob T" <alanb ucora.com> writes:
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
Nov 09 2013
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
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.
Nov 09 2013
next sibling parent reply "Rob T" <alanb ucora.com> writes:
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.
Nov 09 2013
parent reply Timothee Cour <thelastmammoth gmail.com> writes:
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.
Nov 09 2013
parent "Rob T" <alanb ucora.com> writes:
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
Nov 10 2013
prev sibling parent reply "Rob T" <alanb ucora.com> writes:
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
Nov 10 2013
parent "Dicebot" <public dicebot.lv> writes:
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.
Nov 10 2013
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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
Nov 09 2013
parent Timon Gehr <timon.gehr gmx.ch> writes:
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
Nov 09 2013