Jump to page: 1 2
Thread overview
guard clause style static if
Jul 07, 2018
kdevel
Jul 07, 2018
rikki cattermole
Jul 07, 2018
kdevel
Jul 07, 2018
rikki cattermole
Jul 07, 2018
kdevel
Jul 07, 2018
rikki cattermole
Jul 07, 2018
kdevel
Jul 07, 2018
rikki cattermole
Jul 10, 2018
kdevel
Jul 10, 2018
Jonathan M Davis
Jul 07, 2018
Alex
Jul 10, 2018
kdevel
Jul 10, 2018
Timoses
Jul 10, 2018
kdevel
Jul 10, 2018
kdevel
Jul 10, 2018
Jonathan M Davis
Jul 10, 2018
Timoses
July 07, 2018
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?
July 07, 2018
On 07/07/2018 11:28 PM, 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;

else {

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

}

>     }
July 07, 2018
On Saturday, 7 July 2018 at 11:29:35 UTC, rikki cattermole wrote:
>>        static if (args.length == 0)
>>           return;
>
> else {
>
>> 
>>        writeln (args [0]);
>>        return bar (args [1 .. $]);
>
> }

That's not guard clause style [1][2].

[1] https://refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html
[2] http://wiki.c2.com/?GuardClause
July 07, 2018
On 07/07/2018 11:44 PM, kdevel wrote:
> On Saturday, 7 July 2018 at 11:29:35 UTC, rikki cattermole wrote:
>>>        static if (args.length == 0)
>>>           return;
>>
>> else {
>>
>>>
>>>        writeln (args [0]);
>>>        return bar (args [1 .. $]);
>>
>> }
> 
> That's not guard clause style [1][2].
> 
> [1] https://refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html 
> 
> [2] http://wiki.c2.com/?GuardClause

Neither was your original example.

"A method has conditional behavior that does not make clear what the normal path of execution is"

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

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

   void bar (T ...) (T args) if (T.length > 0)
   {
      writeln (args [0]);
      return bar (args [1 .. $]);
   }

(you meant T I suspect, as args is a runtime thing, but T is compile time, just like static if).
July 07, 2018
On Saturday, 7 July 2018 at 11:56:40 UTC, rikki cattermole wrote:
> On 07/07/2018 11:44 PM, kdevel wrote:
>> On Saturday, 7 July 2018 at 11:29:35 UTC, rikki cattermole wrote:
>>>>        static if (args.length == 0)
>>>>           return;
>>>
>>> else {
>>>
>>>>
>>>>        writeln (args [0]);
>>>>        return bar (args [1 .. $]);
>>>
>>> }
>> 
>> That's not guard clause style [1][2].
>> 
>> [1] https://refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html
>> 
>> [2] http://wiki.c2.com/?GuardClause
>
> Neither was your original example.

My example was

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

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

The guard clause is in lines 3 and 4.

> "A method has conditional behavior that does not make clear what the normal path of execution is"

In my example one immediately spots the "normal path of execution". Your
proposal

   void bar (T ...) (T args)
   {
      static if (args.length == 0)
         return;
      else {
        writeln (args [0]);
        return bar (args [1 .. $]);
      }
   }

leads to unreadable arrow code [3].

>    void bar (T ...) (T args) if (T.length == 0)
>    {
>       return;
>[removed]
>    }
>
>    void bar (T ...) (T args) if (T.length > 0)
>    {
>       writeln (args [0]);
>       return bar (args [1 .. $]);
>    }

Interesting alternative but using template constraints introduces code repetition: If you want to add another special case, say length == 4, you have to repeat the logical complement in the "else" branch:

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

    void bar (T ...) (T args) if (T.length == 4)
    {
    // some code
    }

    void bar (T ...) (T args) if (T.length > 0 && T.length != 4)
    {
       writeln (args [0]);
       return bar (args [1 .. $]);
    }

[3] https://blog.codinghorror.com/flattening-arrow-code/
July 08, 2018
On 08/07/2018 12:40 AM, kdevel wrote:
> Interesting alternative

That was not an alternative.
That is what your code was doing.
July 07, 2018
On Saturday, 7 July 2018 at 12:46:08 UTC, rikki cattermole wrote:
> On 08/07/2018 12:40 AM, kdevel wrote:
>> Interesting alternative
>
> That was not an alternative.
> That is what your code was doing.

What my original code was supposed to do. But it did not compile.

   Error: array index [0] is outside array bounds [0 .. 0]
   Error: string slice [1 .. 0] is out of bounds

My question is if it is intentionally failing to compile a static if guard clause.
July 08, 2018
On 08/07/2018 12:54 AM, kdevel wrote:
> On Saturday, 7 July 2018 at 12:46:08 UTC, rikki cattermole wrote:
>> On 08/07/2018 12:40 AM, kdevel wrote:
>>> Interesting alternative
>>
>> That was not an alternative.
>> That is what your code was doing.
> 
> What my original code was supposed to do. But it did not compile.
> 
>     Error: array index [0] is outside array bounds [0 .. 0]
>     Error: string slice [1 .. 0] is out of bounds
> 
> My question is if it is intentionally failing to compile a static if guard clause.

There is no such thing as a static if guard clause.

static if does not exist at runtime, only compile time. So when you erase it (CT -> RT)...

void func() {
	static if(true) {
		return;
	}

	func2();
}

becomes:

void func() {
	return;

	func2();
}

Which is clearly an error. Hence why you need to add else block.
July 07, 2018
On Saturday, 7 July 2018 at 12:54:03 UTC, kdevel wrote:
> On Saturday, 7 July 2018 at 12:46:08 UTC, rikki cattermole wrote:
>> On 08/07/2018 12:40 AM, kdevel wrote:
>>> Interesting alternative
>>
>> That was not an alternative.
>> That is what your code was doing.
>
> What my original code was supposed to do. But it did not compile.
>
>    Error: array index [0] is outside array bounds [0 .. 0]
>    Error: string slice [1 .. 0] is out of bounds
>
> My question is if it is intentionally failing to compile a static if guard clause.

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 constraint in form fun(...)(...) if(...) is a static construct. Therefore, all parts should be mentioned statically. And by

https://dlang.org/spec/version.html#staticif
paragraph: 24.5.4.2

a static if does not introduce a new scope. So, the argument about arrow code is not valid here.
July 09, 2018
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.

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

-Steve
« First   ‹ Prev
1 2