Re: guard clause style static if

2018-07-10 Thread kdevel via Digitalmars-d-learn

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.);
   }



Re: guard clause style static if

2018-07-10 Thread Steven Schveighoffer via Digitalmars-d-learn

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


Re: guard clause style static if

2018-07-10 Thread Timoses via Digitalmars-d-learn

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).


Re: guard clause style static if

2018-07-10 Thread Timoses via Digitalmars-d-learn

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/yndsroswikghknzlx...@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.



[...]


Re: guard clause style static if

2018-07-10 Thread Jonathan M Davis via Digitalmars-d-learn
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





Re: guard clause style static if

2018-07-10 Thread kdevel via Digitalmars-d-learn

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.


Re: guard clause style static if

2018-07-10 Thread Jonathan M Davis via Digitalmars-d-learn
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





Re: guard clause style static if

2018-07-10 Thread kdevel via Digitalmars-d-learn

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.


Re: guard clause style static if

2018-07-10 Thread kdevel via Digitalmars-d-learn
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.


Re: guard clause style static if

2018-07-09 Thread Steven Schveighoffer via Digitalmars-d-learn

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


Re: guard clause style static if

2018-07-07 Thread Alex via Digitalmars-d-learn

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.


Re: guard clause style static if

2018-07-07 Thread rikki cattermole via Digitalmars-d-learn

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.


Re: guard clause style static if

2018-07-07 Thread kdevel via Digitalmars-d-learn

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.


Re: guard clause style static if

2018-07-07 Thread rikki cattermole via Digitalmars-d-learn

On 08/07/2018 12:40 AM, kdevel wrote:

Interesting alternative


That was not an alternative.
That is what your code was doing.


Re: guard clause style static if

2018-07-07 Thread kdevel via Digitalmars-d-learn

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/


Re: guard clause style static if

2018-07-07 Thread rikki cattermole via Digitalmars-d-learn

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).


Re: guard clause style static if

2018-07-07 Thread kdevel via Digitalmars-d-learn

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


Re: guard clause style static if

2018-07-07 Thread rikki cattermole via Digitalmars-d-learn

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 .. $]);


}


    }