www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why does stringof not like functions with arguments?

reply Jason Brady <evervision hotmail.com> writes:
Why does the following code error out with:

app.d(12,10): Error: function app.FunctionWithArguments (uint i) 
is not callable using argument types ()

Code:

import std.stdio;

void FunctionWithoutArguments() {
}

void FunctionWithArguments(uint i) {
}

void main()
{
	writeln(FunctionWithoutArguments.stringof);
	writeln(FunctionWithArguments.stringof);
}
Aug 08 2017
next sibling parent Olivier FAURE <olivier.faure epitech.eu> writes:
On Wednesday, 9 August 2017 at 01:39:07 UTC, Jason Brady wrote:
 Why does the following code error out with:

 app.d(12,10): Error: function app.FunctionWithArguments (uint 
 i) is not callable using argument types ()

 Code:

 import std.stdio;

 void FunctionWithoutArguments() {
 }

 void FunctionWithArguments(uint i) {
 }

 void main()
 {
 	writeln(FunctionWithoutArguments.stringof);
 	writeln(FunctionWithArguments.stringof);
 }
I'm not sure how `stringof` actually works, but it expects a valid expression as its prefix. `FunctionWithoutArguments` is a valid expression (optional parentheses), but `FunctionWithArguments` is not.
Aug 09 2017
prev sibling next sibling parent Biotronic <simen.kjaras gmail.com> writes:
On Wednesday, 9 August 2017 at 01:39:07 UTC, Jason Brady wrote:
 Why does the following code error out with:

 app.d(12,10): Error: function app.FunctionWithArguments (uint 
 i) is not callable using argument types ()
Like Olivier said, stringof expects a valid expression. There are a few other options: module foo; import std.traits; pragma(msg, bar(3).stringof); // prints "bar(3)" pragma(msg, (&bar).stringof); // "& bar" pragma(msg, fullyQualifiedName!bar); // "foo.bar" pragma(msg, __traits(identifier, bar)); // "bar" void bar(int n) {}
Aug 09 2017
prev sibling parent reply Meta <jared771 gmail.com> writes:
On Wednesday, 9 August 2017 at 01:39:07 UTC, Jason Brady wrote:
 Why does the following code error out with:

 app.d(12,10): Error: function app.FunctionWithArguments (uint 
 i) is not callable using argument types ()

 Code:

 import std.stdio;

 void FunctionWithoutArguments() {
 }

 void FunctionWithArguments(uint i) {
 }

 void main()
 {
 	writeln(FunctionWithoutArguments.stringof);
 	writeln(FunctionWithArguments.stringof);
 }
Welcome to optional parentheses hell. Please enjoy your stay. Because function calls in D can optionally omit the parens, `FunctionWithArguments.stringof` is actually attempting to call `FunctionWithArguments` without any arguments, and then call `stringof` on the result. In other words, it's actually trying to do this: writeln(FunctionWithArguments().stringof); And the D compiler is rightly telling you that you can't call the function with no arguments. The easiest solution is to use __traits(identifier) instead: writeln(__traits(identifier, FunctionWithArguments)); You can make a handy template helper to do this for you: enum stringOf(alias symbol) = __traits(identifier, symbol); writeln(stringOf!FunctionWithArguments);
Aug 10 2017
next sibling parent reply Jason Brady <evervision hotmail.com> writes:
On Thursday, 10 August 2017 at 14:51:22 UTC, Meta wrote:
 Welcome to optional parentheses hell. Please enjoy your stay.

 Because function calls in D can optionally omit the parens, 
 `FunctionWithArguments.stringof` is actually attempting to call 
 `FunctionWithArguments` without any arguments, and then call 
 `stringof` on the result. In other words, it's actually trying 
 to do this:

 writeln(FunctionWithArguments().stringof);

 And the D compiler is rightly telling you that you can't call 
 the function with no arguments. The easiest solution is to use 
 __traits(identifier) instead:

 writeln(__traits(identifier, FunctionWithArguments));

 You can make a handy template helper to do this for you:

 enum stringOf(alias symbol) = __traits(identifier, symbol);
 writeln(stringOf!FunctionWithArguments);
Wow. That makes perfect sense. I forgot stringof works only with expressions and that a function name is a valid expression in the case of UCF. I already found the __traits as a workaround, but the template helper is a great idea. Thanks!
Aug 10 2017
parent Meta <jared771 gmail.com> writes:
On Thursday, 10 August 2017 at 15:55:41 UTC, Jason Brady wrote:
 Wow. That makes perfect sense. I forgot stringof works only 
 with expressions
It works with symbols too. See the following: template test(){} pragma(msg, test.stringof);
Aug 10 2017
prev sibling parent Chad Joan <chadjoan gmail.com> writes:
On Thursday, 10 August 2017 at 14:51:22 UTC, Meta wrote:
 On Wednesday, 9 August 2017 at 01:39:07 UTC, Jason Brady wrote:
 Why does the following code error out with:

 app.d(12,10): Error: function app.FunctionWithArguments (uint 
 i) is not callable using argument types ()

 Code:

 import std.stdio;

 void FunctionWithoutArguments() {
 }

 void FunctionWithArguments(uint i) {
 }

 void main()
 {
 	writeln(FunctionWithoutArguments.stringof);
 	writeln(FunctionWithArguments.stringof);
 }
Welcome to optional parentheses hell. Please enjoy your stay. [...]
Muahahaha it's necromancy time! ... meaning I just ran into this problem. Again. And it sucked. And I found this thread. Again. Now it's time for me to be less of a dummy and post my solution. This seems to have different solutions depending on what you want out of the function symbol. The advice already given in this thread is great if you want to print the function's name (and maybe a couple other things I already forgot). But what I needed was to print the function's *signature*. Basically, I want to writeln(FunctionWithArguments.stringof); and get this output: void FunctionWithArguments(uint i) I didn't quite get there. I got this far: void(uint i) But for what I'm doing right now, that's good enough. Alright here's how it's done: writeln(typeof(FunctionWithArguments).stringof); So it was ultimately really easy. At least, for this one very specific use-case. I just about kicked myself. The previous example then becomes this: import std.stdio; void FunctionWithoutArguments() { } void FunctionWithArguments(uint i) { } void main() { writeln(typeof(FunctionWithoutArguments).stringof); writeln(typeof(FunctionWithArguments).stringof); } I needed this when writing a program that checks for whether functions visible from alias-this statements are included in the results of __traits(getOverloads,...). Here is the end result: https://pastebin.com/yj3idDhp And no. No they are not. :3
Jul 31 2020