January 08, 2009
On Thu, Jan 8, 2009 at 1:27 PM, Denis Koroskin <2korden@gmail.com> wrote:
> On Thu, 08 Jan 2009 07:22:53 +0300, BCS <ao@pathlink.com> wrote:
>
>> Reply to Brad,
>>
>>> Restating in the form of a question... When would you _ever_ want {...} to not form a scope?
>>>
>>
>> static if(foo)
>> {
>>    int i;
>>    float x;
>> }
>>
>>
>
> Yeah, and version(foo) belongs here, too.
>

I think I said this before, but I do think it would be nice if there
was some kind of alternate non-scope block delimiter syntax in D.
When you have static ifs mixed with regular ifs and versions it starts
to be pretty difficult to see the flow of things.
Something like

static if (x) ::
     some stuff
::


--bb
January 08, 2009
BCS wrote:
> Reply to Brad,
> 
>> Restating in the form of a question... When would you _ever_ want {...} to not form a scope?
>>
> 
> static if(foo)
> {
>    int i;
>    float x;
> }
> 

That and the version one are good examples.

However, the case example isn't.  It actually already forms a scope, and that's a good thing.  Example:

switch (foo)
{
    case 1:
    {
       int i;
    }

    case 2:
       i = 0; // build error (error: undefined identifier i
}

Later,
Brad
January 08, 2009
Brad Roberts wrote:
> Jason House wrote:
>> I don't think this answers their question. What curly braces mean
>> after a label is clearly a design decision that you made when writing
>> D. It seems that the choice is the opposite of what people expect.
>> Can you explain why it should be NonScope?
> 
> Restating in the form of a question... When would you _ever_ want {...}
> to not form a scope?

version (foo)
{
    int i;
}
...
version (foo)
{
    bar(i);
}

Writing labeled block statements is something more likely to be generated by an automated D code generator, and it's convenient to be able to control if a scope is generated or not.
January 08, 2009
Brad Roberts:

> Restating in the form of a question... When would you _ever_ want {...} to not form a scope?

Recently I have shown a possible syntax for express general unsafeties in D code, for example:

unsafe (bounds, overflow) {
  ... // here there's no array bound checks, not integral overflow checks
}

I think this safe(...){...} and unsafe(...){...} don't need to form a scope, like static if.

--------------------------

Bill Baxter:

>I do think it would be nice if there was some kind of alternate non-scope block delimiter syntax in D. When you have static ifs mixed with regular ifs and versions it starts to be pretty difficult to see the flow of things. Something like
static if (x) ::
     some stuff
::<

Probably I don't understand that syntax. A more full example may help me understand it. But if I understand it correctly, then I don't like that syntax. The {} add a little of noise, but help you know for sure inside where you are (the alternative, if the indenting level are low enough is of course the Python stile). Your style (if I understand it correctly) reminds me the way you use in Pascal to define compiler directives in blocks of code, and it leads to troubles compared to the static if {} of D.

Bye,
bearophile
January 08, 2009
On Thu, Jan 8, 2009 at 5:36 PM, bearophile <bearophileHUGS@lycos.com> wrote:
> Brad Roberts:
>
>> Restating in the form of a question... When would you _ever_ want {...} to not form a scope?
>
> Recently I have shown a possible syntax for express general unsafeties in D code, for example:
>
> unsafe (bounds, overflow) {
>  ... // here there's no array bound checks, not integral overflow checks
> }
>
> I think this safe(...){...} and unsafe(...){...} don't need to form a scope, like static if.
>
> --------------------------
>
> Bill Baxter:
>
>>I do think it would be nice if there was some kind of alternate non-scope block delimiter syntax in D. When you have static ifs mixed with regular ifs and versions it starts to be pretty difficult to see the flow of things. Something like
> static if (x) ::
>     some stuff
> ::<
>
> Probably I don't understand that syntax.

It just means curly braces. I don't really care what syntax it is, just something besides { and } for non-scope blocks.

> A more full example may help me understand it. But if I understand it correctly, then I don't like that syntax. The {} add a little of noise, but help you know for sure inside where you are

Do they really help you see where you are in something like this:

void Do_something(T)(int i)
{
   if (i == 0) {
     static if (is(T==A)) {
           A.SomeAlias x;
     }
     else static if(is(T==B)) {
           B.SubType x;
     }
     else {
         T x;
      }
      x = ... whatever
   }
   else {
       int y = x;
   }
}

To me it's hard to see those variable declarations as being anything
other than scoped to the blocks they're in.
So all I'm saying is if we could have some different delimiters for
non-scope blocks then it might be nice, and make it easier to see when
scopes are ending and when they are not.

--bb
January 08, 2009
Bill Baxter:
> To me it's hard to see those variable declarations as being anything
> other than scoped to the blocks they're in.
> So all I'm saying is if we could have some different delimiters for
> non-scope blocks then it might be nice, and make it easier to see when
> scopes are ending and when they are not.

*Now* I understand, and I see your point.
It's the usual problem: ASCII doesn't have enough ways to represent containers and delimiters :-)

So if this is your original code (I have improved your indentations and improved readability a little):

void doSomething(T)(int i) {
    if (i == 0) {
        static if (is(T == A)) {
            A.SomeAlias x;
        } else static if(is(T == B)) {
            B.SubType x;
        } else {
            T x;
        }

        x = ... whatever
   }
   else
        int y = x;
}


This can be the new version following your idea:

void doSomething(T)(int i) {
    if (i == 0) {
        static if (is(T == A)) ::
            A.SomeAlias x;
        :: else static if(is(T == B)) ::
            B.SubType x;
        :: else ::
            T x;
        ::

        x = ... whatever
   }
   else
        int y = x;
}


But the problem is that :: don't have a head and tail, so the code is even less easy to read.

This version uses (* ... *), used in Pascal to denote comments:

void doSomething(T)(int i) {
    if (i == 0) {
        static if (is(T == A)) (*
            A.SomeAlias x;
        *) else static if(is(T == B)) (*
            B.SubType x;
        *) else (*
            T x;
        *)

        x = ... whatever
   }
   else
        int y = x;
}


I don't like that too, even if it's a bit better than the version with ::.

Two other possibilities:

void doSomething(T)(int i) {
    if (i == 0) {
        static if (is(T == A)) {|
            A.SomeAlias x;
        |} else static if(is(T == B)) {|
            B.SubType x;
        |} else {|
            T x;
        |}

        x = ... whatever
   }
   else
        int y = x;
}


void doSomething(T)(int i) {
    if (i == 0) {
        static if (is(T == A)) {#
            A.SomeAlias x;
        #} else static if(is(T == B)) {#
            B.SubType x;
        #} else {#
            T x;
        #}

        x = ... whatever
   }
   else
        int y = x;
}

I don't think lot of people will appreciate those.
So the lack of different block delimiters may make this problem have no better solution.

Bye,
bearophile
January 08, 2009
Bill Baxter Wrote:
> On Thu, Jan 8, 2009 at 5:36 PM, bearophile <bearophileHUGS@lycos.com> wrote:
> > Brad Roberts:
> >
> >> Restating in the form of a question... When would you _ever_ want {...} to not form a scope?
> >
> > Recently I have shown a possible syntax for express general unsafeties in D code, for example:
> >
> > unsafe (bounds, overflow) {
> >  ... // here there's no array bound checks, not integral overflow checks
> > }
> >
> > I think this safe(...){...} and unsafe(...){...} don't need to form a scope, like static if.
> >
> > --------------------------
> >
> > Bill Baxter:
> >
> >>I do think it would be nice if there was some kind of alternate non-scope block delimiter syntax in D. When you have static ifs mixed with regular ifs and versions it starts to be pretty difficult to see the flow of things. Something like
> > static if (x) ::
> >     some stuff
> > ::<
> >
> > Probably I don't understand that syntax.
> 
> It just means curly braces. I don't really care what syntax it is, just something besides { and } for non-scope blocks.
> 
> > A more full example may help me understand it. But if I understand it correctly, then I don't like that syntax. The {} add a little of noise, but help you know for sure inside where you are
> 
> Do they really help you see where you are in something like this:
> 
> void Do_something(T)(int i)
> {
>    if (i == 0) {
>      static if (is(T==A)) {
>            A.SomeAlias x;
>      }
>      else static if(is(T==B)) {
>            B.SubType x;
>      }
>      else {
>          T x;
>       }
>       x = ... whatever
>    }
>    else {
>        int y = x;
>    }
> }
> 
> To me it's hard to see those variable declarations as being anything
> other than scoped to the blocks they're in.
> So all I'm saying is if we could have some different delimiters for
> non-scope blocks then it might be nice, and make it easier to see when
> scopes are ending and when they are not.
> 
> --bb

I'd do:

void Do_something(T)(int i)
{
    if (i == 0)
    {
static if (is(T==A))
{
        A.SomeAlias x;
}
else static if(is(T==B))
{
        B.SubType x;
}
else
{
        T x;
}
        x = ... whatever
    }
    else
    {
        int y = x;
    }
}

it's parallel programming...


January 08, 2009
On Fri, Jan 9, 2009 at 4:29 AM, Nicolas <dransic@free.fr> wrote:
> Bill Baxter Wrote:
>> On Thu, Jan 8, 2009 at 5:36 PM, bearophile <bearophileHUGS@lycos.com> wrote:
>> > Brad Roberts:
>> >
>> >> Restating in the form of a question... When would you _ever_ want {...} to not form a scope?
>> >
>> > Recently I have shown a possible syntax for express general unsafeties in D code, for example:
>> >
>> > unsafe (bounds, overflow) {
>> >  ... // here there's no array bound checks, not integral overflow checks
>> > }
>> >
>> > I think this safe(...){...} and unsafe(...){...} don't need to form a scope, like static if.
>> >
>> > --------------------------
>> >
>> > Bill Baxter:
>> >
>> >>I do think it would be nice if there was some kind of alternate non-scope block delimiter syntax in D. When you have static ifs mixed with regular ifs and versions it starts to be pretty difficult to see the flow of things. Something like
>> > static if (x) ::
>> >     some stuff
>> > ::<
>> >
>> > Probably I don't understand that syntax.
>>
>> It just means curly braces. I don't really care what syntax it is, just something besides { and } for non-scope blocks.
>>
>> > A more full example may help me understand it. But if I understand it correctly, then I don't like that syntax. The {} add a little of noise, but help you know for sure inside where you are
>>
>> Do they really help you see where you are in something like this:
>>
>> void Do_something(T)(int i)
>> {
>>    if (i == 0) {
>>      static if (is(T==A)) {
>>            A.SomeAlias x;
>>      }
>>      else static if(is(T==B)) {
>>            B.SubType x;
>>      }
>>      else {
>>          T x;
>>       }
>>       x = ... whatever
>>    }
>>    else {
>>        int y = x;
>>    }
>> }
>>
>> To me it's hard to see those variable declarations as being anything
>> other than scoped to the blocks they're in.
>> So all I'm saying is if we could have some different delimiters for
>> non-scope blocks then it might be nice, and make it easier to see when
>> scopes are ending and when they are not.
>>
>> --bb
>
> I'd do:
>
> void Do_something(T)(int i)
> {
>    if (i == 0)
>    {
> static if (is(T==A))
> {
>        A.SomeAlias x;
> }
> else static if(is(T==B))
> {
>        B.SubType x;
> }
> else
> {
>        T x;
> }
>        x = ... whatever
>    }
>    else
>    {
>        int y = x;
>    }
> }
>
> it's parallel programming...

I'm having trouble resisting the urge to re-indent that code.  It totally looks like someone got their tabs and spaces mixed up.

--bb
January 10, 2009
Walter Bright wrote:
<snip>
> Writing labeled block statements is something more likely to be generated by an automated D code generator, 

I still don't get it.

> and it's convenient to be able to control if a scope is generated or not.

To force a block to create a scope:

{{
    ...
}}

To force a block not to create a scope:

version (all) {
    ...
}

Stewart.
January 16, 2009
bearophile wrote:
> Bill Baxter:
>> To me it's hard to see those variable declarations as being anything
>> other than scoped to the blocks they're in.
>> So all I'm saying is if we could have some different delimiters for
>> non-scope blocks then it might be nice, and make it easier to see when
>> scopes are ending and when they are not.
>
> *Now* I understand, and I see your point.
> It's the usual problem: ASCII doesn't have enough ways to represent containers and delimiters :-)
>
> So if this is your original code (I have improved your indentations and improved readability a little):
>
> void doSomething(T)(int i) {
>      if (i == 0) {
>          static if (is(T == A)) {
>              A.SomeAlias x;
>          } else static if(is(T == B)) {
>              B.SubType x;
>          } else {
>              T x;
>          }
>
>          x = ... whatever
>     }
>     else
>          int y = x;
> }
>
>
> This can be the new version following your idea:
>
> void doSomething(T)(int i) {
>      if (i == 0) {
>          static if (is(T == A)) ::
>              A.SomeAlias x;
>          :: else static if(is(T == B)) ::
>              B.SubType x;
>          :: else ::
>              T x;
>          ::
>
>          x = ... whatever
>     }
>     else
>          int y = x;
> }
>
>
> But the problem is that :: don't have a head and tail, so the code is even less easy to read.
>
> This version uses (* ... *), used in Pascal to denote comments:
>
> void doSomething(T)(int i) {
>      if (i == 0) {
>          static if (is(T == A)) (*
>              A.SomeAlias x;
>          *) else static if(is(T == B)) (*
>              B.SubType x;
>          *) else (*
>              T x;
>          *)
>
>          x = ... whatever
>     }
>     else
>          int y = x;
> }
>
>
> I don't like that too, even if it's a bit better than the version with ::.
>
> Two other possibilities:
>
> void doSomething(T)(int i) {
>      if (i == 0) {
>          static if (is(T == A)) {|
>              A.SomeAlias x;
>          |} else static if(is(T == B)) {|
>              B.SubType x;
>          |} else {|
>              T x;
>          |}
>
>          x = ... whatever
>     }
>     else
>          int y = x;
> }
>
>
> void doSomething(T)(int i) {
>      if (i == 0) {
>          static if (is(T == A)) {#
>              A.SomeAlias x;
>          #} else static if(is(T == B)) {#
>              B.SubType x;
>          #} else {#
>              T x;
>          #}
>
>          x = ... whatever
>     }
>     else
>          int y = x;
> }
>
> I don't think lot of people will appreciate those.
> So the lack of different block delimiters may make this problem have no better solution.
>
> Bye,
> bearophile

in C# they use the same syntax as the c pre-processor for conditional compilation and such even though C# doesn't have a pre-processor and the syntax is interpreted by the compiler. the above would be something like:

 void doSomething(T)(int i) {
      if (i == 0) {
          #if (is(T == A))
              A.SomeAlias x;
          #elif (is(T == B))
              B.SubType x;
          #else
              T x;
          #endif

          x = ... whatever
     }
     else
          int y = x;
 }

D can always revert to this kind of syntax for compile time code.