www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Help me escape optional parens hell

reply Meta <jared771 gmail.com> writes:
The code:

alias Response = Nullable!(string, "empty response (error)");

Response processMessage(string commandModule)(string message, 
bool isCommand)
{
     import std.meta;
     import std.string;
     import std.traits;

     import command_uda;

     mixin("import " ~ commandModule ~ ';');
     bool foundCommandMatch = false;
     foreach(symbol; getSymbolsByUDA!(mixin(commandModule), 
Command))
     {
         enum commandUDA = getUDAs!(symbol, Command)[0];
         auto commandPhrase = commandUDA.phrase == "" ? 
symbol.stringof : commandUDA.phrase; //Error: function <function 
signature> is not callable using argument types ()
         auto commandPhrasePattern = 
regex(`^%s\s`.format(commandPhrase));
         if (message.matchFirst(commandPhrasePattern) && 
!foundCommandMatch)
         {
             version(responseDebug) writeln("Matched command ", 
symbol.stringof, " with phrase '", commandPhrase, "'\n"); //Same 
issue
             return Response(symbol(message.strip()));
         }
     }

     return Response.init;
}

I've been banging my head against this and cannot figure out why 
`symbol.stringof` is being called instead of getting a string of 
the symbol. I tried to create a reduced test case but it works 
fine:

import std.stdio;
import std.traits;

enum Attr;

 Attr string test1() { return __FUNCTION__; }
 Attr string test2() { return __FUNCTION__; }

void process()
{
	foreach (symbol; getSymbolsByUDA!(mixin(__MODULE__), Attr))
	{
		writeln("The result of calling ", symbol.stringof, " is ", 
symbol());
	}
}

void main()
{
	process();
}

So I have no clue what I'm doing wrong. This is driving me insane.
Jun 24
next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
Meta wrote:

 So I have no clue what I'm doing wrong. This is driving me insane.
aaaah. known $#^#$ ^ %. enum SymName = (&symbol).stringof[2..$]; // this, instead of symbol.stringof dirty hack, let's hope that DMD devs won't change `.toString()` output (i.e. first two chars will always be "& "). besides this, i know no other way to stop compiler from calling the function there.
Jun 24
next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
ketmar wrote:

 `.toString()`
toChars(). ;-)
Jun 24
prev sibling next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
ketmar wrote:

 Meta wrote:

 So I have no clue what I'm doing wrong. This is driving me insane.
aaaah. known $#^#$ ^ %. enum SymName = (&symbol).stringof[2..$]; // this, instead of symbol.stringof dirty hack, let's hope that DMD devs won't change `.toString()` output (i.e. first two chars will always be "& "). besides this, i know no other way to stop compiler from calling the function there.
i hope devs won't break string representation: i bet that there is ALOT of code that is using this trick. i myself borrowed it from some other module several years ago. and it looks that the module where i found it borrowed the trick from some another module. a really long history. ;-)
Jun 24
prev sibling parent Meta <jared771 gmail.com> writes:
On Saturday, 24 June 2017 at 08:08:33 UTC, ketmar wrote:
 Meta wrote:

 So I have no clue what I'm doing wrong. This is driving me 
 insane.
aaaah. known $#^#$ ^ %. enum SymName = (&symbol).stringof[2..$]; // this, instead of symbol.stringof dirty hack, let's hope that DMD devs won't change `.toString()` output (i.e. first two chars will always be "& "). besides this, i know no other way to stop compiler from calling the function there.
It's dirty but I guess I'll have to go with this hack for the time being. Also, I filed a bug: https://issues.dlang.org/show_bug.cgi?id=17546
Jun 24
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/24/17 3:53 AM, Meta wrote:
 The code:
 
 alias Response = Nullable!(string, "empty response (error)");
 
 Response processMessage(string commandModule)(string message, bool 
 isCommand)
 {
      import std.meta;
      import std.string;
      import std.traits;
 
      import command_uda;
 
      mixin("import " ~ commandModule ~ ';');
      bool foundCommandMatch = false;
      foreach(symbol; getSymbolsByUDA!(mixin(commandModule), Command))
      {
          enum commandUDA = getUDAs!(symbol, Command)[0];
          auto commandPhrase = commandUDA.phrase == "" ? symbol.stringof 
 : commandUDA.phrase; //Error: function <function signature> is not 
 callable using argument types ()
          auto commandPhrasePattern = regex(`^%s\s`.format(commandPhrase));
          if (message.matchFirst(commandPhrasePattern) && 
 !foundCommandMatch)
          {
              version(responseDebug) writeln("Matched command ", 
 symbol.stringof, " with phrase '", commandPhrase, "'\n"); //Same issue
              return Response(symbol(message.strip()));
          }
      }
 
      return Response.init;
 }
 
 I've been banging my head against this and cannot figure out why 
 `symbol.stringof` is being called instead of getting a string of the 
 symbol. I tried to create a reduced test case but it works fine:
 
 import std.stdio;
 import std.traits;
 
 enum Attr;
 
  Attr string test1() { return __FUNCTION__; }
  Attr string test2() { return __FUNCTION__; }
 
 void process()
 {
      foreach (symbol; getSymbolsByUDA!(mixin(__MODULE__), Attr))
      {
          writeln("The result of calling ", symbol.stringof, " is ", 
 symbol());
      }
 }
 
 void main()
 {
      process();
 }
 
 So I have no clue what I'm doing wrong. This is driving me insane.
I know what you are doing wrong in your reduced case. Try this instead: Attr string test1(int) { return __FUNCTION__; } Attr string test2(int) { return __FUNCTION__; } void process() { foreach (symbol; getSymbolsByUDA!(mixin(__MODULE__), Attr)) { writeln("The result of calling ", symbol.stringof, " is ", symbol(1)); } } The reason your version "works" is because your functions actually are callable with no args! I tried many things including: enum symbolname = symbol.stringof; enum symbolname = (symbol).stringof; pragma(msg, symbol.stringof); Nothing works. If this isn't already a bug, you should file it. Aside from ketmar's workaround, I can't think of one. It's interesting that the ability to call without parentheses is what causes the error, yet when you *can* call without parentheses, it doesn't actually do so (symbol.stringof prints the name of the symbol). This seems very obviously to be a bug. -Steve
Jun 24