Help me escape optional parens hell

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Jun 24 05:09:16 PDT 2017


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


More information about the Digitalmars-d-learn mailing list