July 10, 2018
On Tuesday, 10 July 2018 at 00:11:27 UTC, Steven Schveighoffer wrote:
> On 7/7/18 7:28 AM, kdevel wrote:
>> It appears not to be possible to use static if in "guard clause style" as in
>> 
>>     void bar (T ...) (T args)
>>     {
>>        static if (args.length == 0)
>>           return;
>> 
>>        writeln (args [0]);
>>        return bar (args [1 .. $]);
>>     }
>> 
>> Is this intended?
>
> Yes.
>
> Try just a normal if -- it will have the same effect (the optimizer will eliminate the dead code), but will compile.

I would like to suggest an extension of the language by introducing

    static return Expression_opt;

which shall have the effect of a return plus that the remaining lines in the current block are treated as if they were enclosed in an else block.

> Of course, you have to fix your second part to only return bar if args.length > 0!

This violates DRY. Same problem as with the template constraints version where the condition used in every special case has to be repeated in the general case.
July 10, 2018
On Saturday, 7 July 2018 at 13:03:32 UTC, rikki cattermole wrote:
> void func() {
> 	return;
>
> 	func2();
> }
>
> Which is clearly an error. Hence why you need to add else block.

There is no error in this generated code because func2 is unreachable. That there is a state/stage during compilation in which the call to func2 exists and is checked is an implementation detail which IMHO shall not be exposed to the user.
July 10, 2018
On Saturday, 7 July 2018 at 13:12:59 UTC, Alex wrote:
> The site you cited for the guard clause above (c2.com)
> works at runtime.

?

> The intention is to shorten the paths inside a function, I think. Therefore, a static "guard clause" is a contradiction, if I understand it correctly.

The term "guard clause" denotes a style of organizing code differently. The addressee is not the compiler but the human.
July 10, 2018
On Tuesday, 10 July 2018 05:52:59 MDT kdevel via Digitalmars-d-learn wrote:
> On Saturday, 7 July 2018 at 13:03:32 UTC, rikki cattermole wrote:
> > void func() {
> >
> >     return;
> >
> >     func2();
> >
> > }
> >
> > Which is clearly an error. Hence why you need to add else block.
>
> There is no error in this generated code because func2 is unreachable.

If you don't get an error with code like

void func()
{
    return;
    func2();
}

then you're not compiling with -w. A _lot_ of projects compile with -w (IIRC, it's the default for dub). So, unless you're dealing with code that only you are going to be using, and you can guarantee that it will never be compiled with -w, then you're going to have problems with code like this. If you want to ensure that your code is going to be usable by other folks, then you should be compiling with -w.

> That there is a state/stage during compilation in
> which the call to func2 exists and is checked is an
> implementation detail which IMHO shall not be exposed to the user.

It's going to matter if your code doesn't compile, since at that point, the implementation detail impacts the user. And unreachable code is something that won't compile for most projects.

- Jonathan M Davis



July 10, 2018
On Tuesday, 10 July 2018 05:38:33 MDT kdevel via Digitalmars-d-learn wrote:
> I would like to suggest an extension of the language by introducing
>
>      static return Expression_opt;
>
> which shall have the effect of a return plus that the remaining lines in the current block are treated as if they were enclosed in an else block.

Well, you can propose it, but it really doesn't fit with how static if works. static if doesn't have anything to do with control flow, whereas what you're proposing here would, which would arguably make it that much more confusing. I confess that I don't understand what the problem is with simply adding an else block. It's simple, and it works right now without any language changes.

- Jonathan M Davis



July 10, 2018
On Tuesday, 10 July 2018 at 12:05:11 UTC, kdevel wrote:
> On Saturday, 7 July 2018 at 13:12:59 UTC, Alex wrote:
>> The site you cited for the guard clause above (c2.com)
>> works at runtime.
>
> ?

static if works at compile team and only inserts code into the final code for run-time depending on the condition (which has to be known at compile time). In your case

   void bar (T ...) (T args)
   {
      static if (args.length == 0)
         return;

      writeln (args [0]);
      return bar (args [1 .. $]);
   }

you could also write

      static if (T.length == 0)

so in case T.length == 0 the resulting run-time code would yield

   void bar (T args) // in that case T is nothing
   {
      return;

      writeln (args [0]);
      return bar (args [1 .. $]);
   }

So the only thing you can control with static if statements is "what code to run" depending on the template arguments.

The problem with the error messages you are getting (https://forum.dlang.org/post/yndsroswikghknzlxwqi@forum.dlang.org) is that the compiler checks during compilation time whether `args[0]` is valid (which in above case it is not). So you can't use args like a "normal array" as you would in control statements during run-time. I don't know what exactly `args` represents in the background.

> [...]
July 10, 2018
On Tuesday, 10 July 2018 at 12:10:27 UTC, Jonathan M Davis wrote:
> On Tuesday, 10 July 2018 05:38:33 MDT kdevel via Digitalmars-d-learn wrote:
>> I would like to suggest an extension of the language by introducing
>>
>>      static return Expression_opt;
>>
>> which shall have the effect of a return plus that the remaining lines in the current block are treated as if they were enclosed in an else block.
>
> Well, you can propose it, but it really doesn't fit with how static if works. static if doesn't have anything to do with control flow, whereas what you're proposing here would, which would arguably make it that much more confusing. I confess that I don't understand what the problem is with simply adding an else block. It's simple, and it works right now without any language changes.
>
> - Jonathan M Davis

Actually, it's kind of controlling "compile-time control flow". If you had

auto func(T)(T args)
{
    static if (T.length == 0)
        static return;

    return args[0];
}

then `static return;` would instruct the compiler to skip the rest of the code and only insert a `return;`, omitting any code that follows. So the result in above case with `T.length == 0` would be:

void func()
{
    return;
}

To me that sounds like a very nice feature, considering that I often found myself in the same situation where I didn't feel like the static `else` statement was really necessary (comparing to the usual way to control flow (at run-time) with convential if-else statements).
July 10, 2018
On 7/10/18 7:38 AM, kdevel wrote:
> On Tuesday, 10 July 2018 at 00:11:27 UTC, Steven Schveighoffer wrote:
>> On 7/7/18 7:28 AM, kdevel wrote:
>>> It appears not to be possible to use static if in "guard clause style" as in
>>>
>>>     void bar (T ...) (T args)
>>>     {
>>>        static if (args.length == 0)
>>>           return;
>>>
>>>        writeln (args [0]);
>>>        return bar (args [1 .. $]);
>>>     }
>>>
>>> Is this intended?
>>
>> Yes.
>>
>> Try just a normal if -- it will have the same effect (the optimizer will eliminate the dead code), but will compile.
> 
> I would like to suggest an extension of the language by introducing
> 
>      static return Expression_opt;
> 
> which shall have the effect of a return plus that the remaining lines in the current block are treated as if they were enclosed in an else block.
I think it's simpler than that. IMO, any time you have a static if that uses template parameters, it should be treated for purposes of detecting unreachable code as if it were a normal if statement. To the user "unreachable" code means it never can be reached. But that code CAN be reached with different compile-time parameters.

Your anecdote is easy to solve, but it's much more difficult to do something like this in a static loop.

I don't want to introduce more syntax, this is basically a lint error.

>> Of course, you have to fix your second part to only return bar if args.length > 0!
> 
> This violates DRY. Same problem as with the template constraints version where the condition used in every special case has to be repeated in the general case.

Sorry, but it has to try to compile this, and args[1 .. $] is invalid at compile time.

You can get it back to being DRY by using else.

-Steve
July 10, 2018
On Saturday, 7 July 2018 at 11:56:40 UTC, rikki cattermole wrote:
>    void bar (T ...) (T args) if (T.length == 0)
>    {
>       return;
>
[...]
>    }
>
>    void bar (T ...) (T args) if (T.length > 0)
>    {
>       writeln (args [0]);
>       return bar (args [1 .. $]);
>    }

This is a version without a second condition:

   import std.stdio;

   void foo ()
   {
      writeln;
   }

   void foo (T ...) (T args) if (T.length > 0)
   {
      writeln ("arg = ", args [0]);
      foo (args[1 .. $]);
   }

   void main ()
   {
      foo ();
      foo (1);
      foo (1, "2");
      foo (1, 2, 3.);
   }

1 2
Next ›   Last »