Why is length being tested on an int?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sat Oct 28 02:54:56 UTC 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



More information about the Digitalmars-d-learn mailing list