Re: Why is length being tested on an int?

2017-10-27 Thread Jonathan M Davis via Digitalmars-d-learn
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:
>
> (6): Error: no property 'length' for type 'int'
> (7): Error: function .myFunc (string arg) is not
> callable using argument types (int)
> (11): Error: template instance .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



Re: Why is length being tested on an int?

2017-10-27 Thread Adam D. Ruppe via Digitalmars-d-learn
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
}


Why is length being tested on an int?

2017-10-27 Thread Shriramana Sharma via Digitalmars-d-learn
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:

(6): Error: no property 'length' for type 'int'
(7): Error: function .myFunc (string arg) is not 
callable using argument types (int)
(11): Error: template instance .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!