Thread overview
Why is length being tested on an int?
Oct 28, 2017
Shriramana Sharma
Oct 28, 2017
Adam D. Ruppe
Oct 28, 2017
Jonathan M Davis
October 28, 2017
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!

October 28, 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
}
October 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