digitalmars.D.learn - Why is length being tested on an int?
- Shriramana Sharma (25/25) Oct 27 2017 Hello. I want a function to be able to take any arguments like
- Adam D. Ruppe (15/18) Oct 27 2017 That's a runtime check and therefore the code must run to be
- Jonathan M Davis (41/66) Oct 27 2017 Okay. is(typeof(arg) == string) will be evaluated at compile time, becau...
Hello. I want a function to be able to take any arguments like write() and print them out but quoting string arguments of length more than 1. So I write the following quote: import std.stdio; string myFunc(string arg) { return '\"' ~ arg ~ '\"'; } void myWrite(T ...)(T args) { foreach (arg; args) if (is(typeof(arg) == string) && arg.length > 1) write(myFunc(arg)); else write(arg); } void main() { myWrite("Hello", 1, "c"); } However I am getting the error even when compiling: <src>(6): Error: no property 'length' for type 'int' <src>(7): Error: function <src>.myFunc (string arg) is not callable using argument types (int) <src>(11): Error: template instance <src>.myWrite!(string, int, string) error instantiating I am not sure why, given short circuit evaluation, it is testing the length of the int argument? Or is it that the problem is at compile time itself so short circuit doesn't come into play? How to rewrite the function so I don't get the error? Thanks!
Oct 27 2017
On Saturday, 28 October 2017 at 02:38:43 UTC, Shriramana Sharma wrote:if (is(typeof(arg) == string) && arg.length > 1) I am not sure why, given short circuit evaluation, it is testing the length of the int argument?That's a runtime check and therefore the code must run to be short circuited at all... which means it must compile the whole thing first. Break the is() part into a separate static if, then put the runtime length check inside that. More like static if(is(typeof(arg) == string)) { if(arg.length > 1) // handle else // string of short length } else { // not a string }
Oct 27 2017
On Saturday, October 28, 2017 02:38:43 Shriramana Sharma via Digitalmars-d- learn wrote:Hello. I want a function to be able to take any arguments like write() and print them out but quoting string arguments of length more than 1. So I write the following quote: import std.stdio; string myFunc(string arg) { return '\"' ~ arg ~ '\"'; } void myWrite(T ...)(T args) { foreach (arg; args) if (is(typeof(arg) == string) && arg.length > 1) write(myFunc(arg)); else write(arg); } void main() { myWrite("Hello", 1, "c"); } However I am getting the error even when compiling: <src>(6): Error: no property 'length' for type 'int' <src>(7): Error: function <src>.myFunc (string arg) is not callable using argument types (int) <src>(11): Error: template instance <src>.myWrite!(string, int, string) error instantiating I am not sure why, given short circuit evaluation, it is testing the length of the int argument? Or is it that the problem is at compile time itself so short circuit doesn't come into play? How to rewrite the function so I don't get the error? Thanks!Okay. is(typeof(arg) == string) will be evaluated at compile time, because is expressions are compile time constructs. However, an if statement is a runtime construct, so it's going to be evaluated at runtime (which does look like it's probably what you want for arg.length > 1). So, what you're getting is essentially either if(true && arg.length > 1) write(myFunc(arg)) else write(arg); or if(false && arg.length > 1) write(myFunc(arg)) else write(arg); depending on the type of arg. In either case, arg.length has to compile. The evaluation of whether it's true or not may be shortcutted, but that doesn't mean that its semantics don't have to be valid. You're going to need to break up what you're doing. e.g. static if(is(typeof(arg) == string)) { if(arg.length > 1) write(myFunc(arg)); else write(arg); } else write(arg); The other thing is that even with a static if and all of the conditions being compile-time (which they need to be for a static if), && and || don't shortcut the semantic check any more than that gets shortcutted with a runtime if statement. So, even if arg were completely a compile-time thing, static if(is(typeof(arg) == string) && arg.length > 1) { } would only be valid code if typeof(arg) has length (though the second condition would only be evaluated if arg were a string). There are times where it would be nice if && and || shortcutted the semantic check with static if, but for better or worse, they don't. - Jonathan M Davis
Oct 27 2017