www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why is length being tested on an int?

reply Shriramana Sharma writes:
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
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
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
prev sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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