May 08, 2012
On Tuesday, 8 May 2012 at 18:30:08 UTC, Timon Gehr wrote:
> On 05/08/2012 10:46 AM, Don Clugston wrote:
>> On 07/05/12 19:06, deadalnix wrote:
>>> Hi,
>>>
>>> Working on D I noticed that some statement, notably assert, are
>>> expression of type void. Why not all statement (that are not expression
>>> already) are expression ?
>>
>> assert isn't a statement. It's an expression ( same as is() ). What
>> makes you think it's a statement?
>>
>> The main use for a void expression is so that it can be used in a comma
>> expression; this is why assert is an expression.
>>
>> The curious thing, which may be the source of the confusion, is that
>> static assert() is a statement, while assert() is an expression. Maybe
>> static assert should also be an expression rather than a statement?
>
> static assert is a declaration.

It's a statement when used inside functions, and a "declaration" (DeclarationDefinition seems to be the spec's term for top-level constructs) elsewhere. Other syntactic constructs have a similar duality, e.g. import.

Everything inside a function is a statement, including variable declarations; they are declaration statements.

May 09, 2012
Le 07/05/2012 19:06, deadalnix a écrit :
> Hi,
>
> Working on D I noticed that some statement, notably assert, are
> expression of type void. Why not all statement (that are not expression
> already) are expression ?

I want to pop this question.

This is an important one. And nothing is documented about that.
May 09, 2012
On 07/05/2012 18:06, deadalnix wrote:
> Hi,
>
> Working on D I noticed that some statement, notably assert, are expression of type void.
> Why not all statement (that are not expression already) are expression ?

Because it wouldn't make sense.

The semantic of an ExpressionStatement is to evaluate the expression.

Creating a variable in the scope in which an expression appears, and controlling the flow of the function in which an expression appears, are beyond the scope of the expression evaluation mechanism.

To take an example, what sense would it make if
    return 42
were an expression?  What would its type be?  You would be able to do something like
    auto qwert() {
        return return 105;
    }
to instantly return from the function that called qwert.

OK, so assert, or exception throwing more generally, feels like that kind of thing.  But exceptions aren't part of the normal flow of program logic.  Exceptions can be, and indeed usually are, thrown in the process of evaluating an expression.  AssertExpression is an example of this.

Though this does suggest an answer of "because it can be" for why an assert is an expression.  Indeed, you could well ask why an assert is an expression but a throw isn't.  Maybe it was thought worth convoluting assert to make for concise code by including it in a CommaExpression - but not worth convoluting throw in the same way, since a throw throws unconditionally.

Not that it would be much more complicated to make throw an expression.  But you could always define a function of your own like

    void throwEx(Throwable t) { throw t; }

Stewart.
May 09, 2012
Le 09/05/2012 14:11, Stewart Gordon a écrit :
> On 07/05/2012 18:06, deadalnix wrote:
>> Hi,
>>
>> Working on D I noticed that some statement, notably assert, are
>> expression of type void.
>> Why not all statement (that are not expression already) are expression ?
>
> Because it wouldn't make sense.
>
> The semantic of an ExpressionStatement is to evaluate the expression.
>
> Creating a variable in the scope in which an expression appears, and
> controlling the flow of the function in which an expression appears, are
> beyond the scope of the expression evaluation mechanism.
>
> To take an example, what sense would it make if
> return 42
> were an expression?

The same as currently.

> What would its type be?

void

> You would be able to do
> something like
> auto qwert() {
> return return 105;
> }
> to instantly return from the function that called qwert.
>

No it is incorrect. but not grammatically, semantically.

Just like 3 + foo() is incorrect if foo's return type is void. It is grammatically correct.

> OK, so assert, or exception throwing more generally, feels like that
> kind of thing.

They don't feel like. It is specified (and even implemented, look in dmd source code) that assert is an expression for instance. Expression that is of type void (and so have no value).

As you are unable to explain why such a thing exist, I really doubt you are qualified to answer that question at all. I'm asking here about design decisions.

If you have no clue what I'm talking about please do not answer, or ask for more details.
July 09, 2012
>> I'm usually fairly ambivalent about the idea of statements being
>> expressions, but I would *love* for switch to be usable as an expression.
>> For instance, in Haxe, you can do stuff like the following, which I get a
>> ton of use out of and often wish D had:
>>
>> a = switch(b)
>> {
>>     case 1: "foo";
>>     case 2: "bar";
>>     case 3: "baz";
>>     case 4: "whee";
>>     default: "blork";
>> }
>>
>> The D equivalents aren't terrible, but they aren't nearly as nice.
>
> This won't work anyway. We are talking about language grammar here. If made expression, statement would be of type void. Just like assert is.

I see what you're saying, but this switch expression should really be of type string.

I certainly wish more things were expressions. "a = if (x) y; else z;" isn't especially useful since we have "a = x ? y : z", but consider instead something that doesn't map so easily to an expression:

// very loosely based on some Android code I wrote recently
dpWidth = _lastKnownWidth =
    if (window.isVisible()) {
        auto m = context.getResources().getSystemMetrics();
        // final statement as value of "if" expr
        window.getWidth() / m.pixelDensity();
    } else if (_lastKnownWidth != 0)
        _lastKnownWidth;
    else
        screenInfo().getWidth();

Or how about:

auto area = {
    auto tmp = foo.bar(baz);
    tmp.width * tmp.height;
}

I also wish "void" were a first-class type with sizeof==0 for maximum efficiency:

    int[void] intSet = [2:(), 3:(), 4:()]

Ditto for size of empty structs. D code should never need abominations like the C++ EBCO.
July 09, 2012
>     int[void] intSet = [2:(), 3:(), 4:()]
oops, void[int] intSet = [2:(), 3:(), 4:()] rather.
July 15, 2012
On 07/05/2012 21:27, Nick Sabalausky wrote:
<snip>
> I'm usually fairly ambivalent about the idea of statements being
> expressions, but I would *love* for switch to be usable as an expression.
<snip>

Switch cases are sequences of statements.  Allowing them to alternatively be expressions would create ambiguity in the grammar.

If you're designing a language and want switch expressions as well as switch statements, then don't try to make one look like the other.  For example, C didn't try to make conditional expressions look like if statements - it created a new syntax for conditional expressions.

That said, it's possible to design a language to have no distinction between expressions and statements.  But you can't really conflate the two syntaxes in an existing language.

Of course, D could have been designed as such a language.  But it wasn't.  It was designed to have the same overall look and feel as C.

Stewart.
July 15, 2012
David Piepgrass:

> Or how about:
>
> auto area = {
>     auto tmp = foo.bar(baz);
>     tmp.width * tmp.height;
> }

Rust is like that, but I don't see it as a significant improvement.


> I also wish "void" were a first-class type with sizeof==0 for maximum efficiency:
>
>     int[void] intSet = [2:(), 3:(), 4:()]

I prefer:

auto intSet = hashSet([2, 3, 4]);


> Ditto for size of empty structs.

There are reasons for D empty structs to be of 1 byte.


> D code should never need abominations like the C++ EBCO.

In D classes are never really empty (2 words is their minimum size, not counting GC bookkeeping), and there is no normal struct inheritance.

Bye,
bearophile
1 2
Next ›   Last »