Thread overview
typeof and block statements
Aug 12, 2010
simendsjo
Aug 12, 2010
simendsjo
Aug 12, 2010
simendsjo
Aug 12, 2010
simendsjo
Aug 12, 2010
Mafi
Aug 12, 2010
Stanislav Blinov
August 12, 2010
The spec doesn't mention anything about block statements in typeof declarations.

	//typeof({1}) a; // found } expecting ;
	//typeof({1}()) b; // same as a
	typeof(1) c; // int

I'm asking because isInputRange from std.range the idom from the b test:

template isInputRange(R)
{
    enum bool isInputRange = is(typeof(
    {
        R r;             // can define a range object
        if (r.empty) {}  // can test for empty
        r.popFront;          // can invoke next
        auto h = r.front; // can get the front of the range
    }()));
}


Also... The unittest contains
    static assert(isInputRange!(int[]));
    static assert(isInputRange!(char[]));

But arrays doesn't include these methods.. I don't understand a thing :(
August 12, 2010
On Thu, 12 Aug 2010 09:13:54 -0400, simendsjo <simen.endsjo@pandavre.com> wrote:

> The spec doesn't mention anything about block statements in typeof declarations.
>
> 	//typeof({1}) a; // found } expecting ;
> 	//typeof({1}()) b; // same as a
> 	typeof(1) c; // int

{...} is a function literal, a lambda function if you will.

Your lambda function contains a syntax error, the single line in it does not end in a semicolon.

Of course, if you made it:

{1;}

I think it might fail anyways, because 1; is not a statement.

>
> I'm asking because isInputRange from std.range the idom from the b test:
>
> template isInputRange(R)
> {
>      enum bool isInputRange = is(typeof(
>      {
>          R r;             // can define a range object
>          if (r.empty) {}  // can test for empty
>          r.popFront;          // can invoke next
>          auto h = r.front; // can get the front of the range
>      }()));
> }

is(typeof(...)) is sort of a hack to determine if something compiles or not.  If it does, then there will be a type associated with the expression, if not, then there will be no type.  There is also a __traits(compiles, ...) which I think really should be used for this purpose, but the isInputRange may predate that idiom.

Essentially, the isInputRange bool is true if the function literal that contains those four statements compiles.  What it translates to is, Does R support the functions necessary for input ranges.

I see a syntax error there, r.popFront is not a property, so it should look like this:

r.popFront();

It only works right now because mandatory () for non-properties is not implemented in the compiler yet.

>
>
> Also... The unittest contains
>      static assert(isInputRange!(int[]));
>      static assert(isInputRange!(char[]));
>
> But arrays doesn't include these methods.. I don't understand a thing :(

Arrays support "tacking on" extra methods to it.  Essentially, for arrays (and arrays only), the compiler will translate this:

arr.foo()

to this:

foo(arr)

See http://www.digitalmars.com/d/2.0/arrays.html#func-as-property
August 12, 2010
Am 12.08.2010 15:13, schrieb simendsjo:
> The spec doesn't mention anything about block statements in typeof
> declarations.
>
> //typeof({1}) a; // found } expecting ;
> //typeof({1}()) b; // same as a
> typeof(1) c; // int
>
> I'm asking because isInputRange from std.range the idom from the b test:
>
> template isInputRange(R)
> {
> enum bool isInputRange = is(typeof(
> {
> R r; // can define a range object
> if (r.empty) {} // can test for empty
> r.popFront; // can invoke next
> auto h = r.front; // can get the front of the range
> }()));
> }
>
>
> Also... The unittest contains
> static assert(isInputRange!(int[]));
> static assert(isInputRange!(char[]));
>
> But arrays doesn't include these methods.. I don't understand a thing :(
The braces create an delegate which should be directly called after its  creation (this do the parens). If you put this into typeof, this delegate will never be created, we just get the type of calling it. The type of calling a delegate is of course the delegate's return type which is automatically deduced.
Your exampley a and b are invalid beacuse '1' is not a valid statement it's only a expression. 'return 1;' would work as expected.
Why does the spec don't mention it? It's beacuse a delegate is always a valid expresion. typeof has no special case of braces.

Mafi
August 12, 2010
  12.08.2010 17:13, simendsjo wrote:
> The spec doesn't mention anything about block statements in typeof declarations.
>
>     //typeof({1}) a; // found } expecting ;
>     //typeof({1}()) b; // same as a
>     typeof(1) c; // int
>
> I'm asking because isInputRange from std.range the idom from the b test:
>
> template isInputRange(R)
> {
>     enum bool isInputRange = is(typeof(
>     {
>         R r;             // can define a range object
>         if (r.empty) {}  // can test for empty
>         r.popFront;          // can invoke next
>         auto h = r.front; // can get the front of the range
>     }()));
> }
>
This looks like a parameterless delegate to me :) Seems something akin to __traits(compiles).
>
> Also... The unittest contains
>     static assert(isInputRange!(int[]));
>     static assert(isInputRange!(char[]));
>
> But arrays doesn't include these methods.. I don't understand a thing :(
They don't, but std.array imported in std.range defines the methods for them.

-- 
*
*
**



August 12, 2010
On 12.08.2010 15:30, Steven Schveighoffer wrote:
> On Thu, 12 Aug 2010 09:13:54 -0400, simendsjo
> <simen.endsjo@pandavre.com> wrote:
>
>> The spec doesn't mention anything about block statements in typeof
>> declarations.
>>
>> //typeof({1}) a; // found } expecting ;
>> //typeof({1}()) b; // same as a
>> typeof(1) c; // int
>
> {...} is a function literal, a lambda function if you will.

I thought parameterless delegates were written () {}..

> Your lambda function contains a syntax error, the single line in it does
> not end in a semicolon.
>
> Of course, if you made it:
>
> {1;}
>
> I think it might fail anyways, because 1; is not a statement.

Why doesn't this work then?
typeof({return 1;}()) a; // found 'a' when expecting ';' following statement

>>
>> I'm asking because isInputRange from std.range the idom from the b test:
>>
>> template isInputRange(R)
>> {
>> enum bool isInputRange = is(typeof(
>> {
>> R r; // can define a range object
>> if (r.empty) {} // can test for empty
>> r.popFront; // can invoke next
>> auto h = r.front; // can get the front of the range
>> }()));
>> }
>
> is(typeof(...)) is sort of a hack to determine if something compiles or
> not. If it does, then there will be a type associated with the
> expression, if not, then there will be no type. There is also a
> __traits(compiles, ...) which I think really should be used for this
> purpose, but the isInputRange may predate that idiom.
>
> Essentially, the isInputRange bool is true if the function literal that
> contains those four statements compiles. What it translates to is, Does
> R support the functions necessary for input ranges.
>
> I see a syntax error there, r.popFront is not a property, so it should
> look like this:
>
> r.popFront();
>
> It only works right now because mandatory () for non-properties is not
> implemented in the compiler yet.

So once this is implemented, this template is always false?

>>
>>
>> Also... The unittest contains
>> static assert(isInputRange!(int[]));
>> static assert(isInputRange!(char[]));
>>
>> But arrays doesn't include these methods.. I don't understand a thing :(
>
> Arrays support "tacking on" extra methods to it. Essentially, for arrays
> (and arrays only), the compiler will translate this:
>
> arr.foo()
>
> to this:
>
> foo(arr)
>
> See http://www.digitalmars.com/d/2.0/arrays.html#func-as-property

Thanks!
August 12, 2010
On Thu, 12 Aug 2010 09:56:07 -0400, simendsjo <simen.endsjo@pandavre.com> wrote:

> On 12.08.2010 15:30, Steven Schveighoffer wrote:
>> On Thu, 12 Aug 2010 09:13:54 -0400, simendsjo
>> <simen.endsjo@pandavre.com> wrote:
>>
>>> The spec doesn't mention anything about block statements in typeof
>>> declarations.
>>>
>>> //typeof({1}) a; // found } expecting ;
>>> //typeof({1}()) b; // same as a
>>> typeof(1) c; // int
>>
>> {...} is a function literal, a lambda function if you will.
>
> I thought parameterless delegates were written () {}..
>
>> Your lambda function contains a syntax error, the single line in it does
>> not end in a semicolon.
>>
>> Of course, if you made it:
>>
>> {1;}
>>
>> I think it might fail anyways, because 1; is not a statement.
>
> Why doesn't this work then?
> typeof({return 1;}()) a; // found 'a' when expecting ';' following statement

First, this compiles for me.  Not sure why it doesn't for you.

Second, stringof is your friend.  Coupled with pragma(msg, ...) It allows you to "view" the type of an expression at compile time:

pragma(msg, typeof({return 1;}()).stringof);

Which when compiled on dmd 2.047 linux, prints:

int


>> I see a syntax error there, r.popFront is not a property, so it should
>> look like this:
>>
>> r.popFront();
>>
>> It only works right now because mandatory () for non-properties is not
>> implemented in the compiler yet.
>
> So once this is implemented, this template is always false?

Once mandatory parens for non-properties is implemented, the code will be changed to r.popFront();

-Steve
August 12, 2010
On 12.08.2010 16:19, Steven Schveighoffer wrote:
> On Thu, 12 Aug 2010 09:56:07 -0400, simendsjo
> <simen.endsjo@pandavre.com> wrote:
>
>> On 12.08.2010 15:30, Steven Schveighoffer wrote:
>>> On Thu, 12 Aug 2010 09:13:54 -0400, simendsjo
>>> <simen.endsjo@pandavre.com> wrote:
>>>
>>>> The spec doesn't mention anything about block statements in typeof
>>>> declarations.
>>>>
>>>> //typeof({1}) a; // found } expecting ;
>>>> //typeof({1}()) b; // same as a
>>>> typeof(1) c; // int
>>>
>>> {...} is a function literal, a lambda function if you will.
>>
>> I thought parameterless delegates were written () {}..
>>
>>> Your lambda function contains a syntax error, the single line in it does
>>> not end in a semicolon.
>>>
>>> Of course, if you made it:
>>>
>>> {1;}
>>>
>>> I think it might fail anyways, because 1; is not a statement.
>>
>> Why doesn't this work then?
>> typeof({return 1;}()) a; // found 'a' when expecting ';' following
>> statement
>
> First, this compiles for me. Not sure why it doesn't for you.
>
> Second, stringof is your friend. Coupled with pragma(msg, ...) It allows
> you to "view" the type of an expression at compile time:
>
> pragma(msg, typeof({return 1;}()).stringof);
>
> Which when compiled on dmd 2.047 linux, prints:
>
> int
>

Tested with dmd 2.048 on win7.

pragma(msg, "module:"~typeof({return 1;}()).stringof);

void main()
{
	pragma(msg, "main:"~typeof({return 1;}()).stringof);
	//typeof({return 1;}()) a; // found 'a' when expecting ';' following statement
}

prints
module:int
main:int



>>> I see a syntax error there, r.popFront is not a property, so it should
>>> look like this:
>>>
>>> r.popFront();
>>>
>>> It only works right now because mandatory () for non-properties is not
>>> implemented in the compiler yet.
>>
>> So once this is implemented, this template is always false?
>
> Once mandatory parens for non-properties is implemented, the code will
> be changed to r.popFront();
>
> -Steve

August 12, 2010
On Thu, 12 Aug 2010 10:29:41 -0400, simendsjo <simen.endsjo@pandavre.com> wrote:

> On 12.08.2010 16:19, Steven Schveighoffer wrote:
>> On Thu, 12 Aug 2010 09:56:07 -0400, simendsjo
>> <simen.endsjo@pandavre.com> wrote:
>>
>>> Why doesn't this work then?
>>> typeof({return 1;}()) a; // found 'a' when expecting ';' following
>>> statement
>>
>> First, this compiles for me. Not sure why it doesn't for you.
>>
>> Second, stringof is your friend. Coupled with pragma(msg, ...) It allows
>> you to "view" the type of an expression at compile time:
>>
>> pragma(msg, typeof({return 1;}()).stringof);
>>
>> Which when compiled on dmd 2.047 linux, prints:
>>
>> int
>>
>
> Tested with dmd 2.048 on win7.
>
> pragma(msg, "module:"~typeof({return 1;}()).stringof);
>
> void main()
> {
> 	pragma(msg, "main:"~typeof({return 1;}()).stringof);
> 	//typeof({return 1;}()) a; // found 'a' when expecting ';' following statement
> }
>
> prints
> module:int
> main:int
>

Ahh.  It fails on 2.047 also if you put the statement inside main.  If you declare it outside main, it works.

Looks like a bug.  Please file http://d.puremagic.com/issues/enter_bug.cgi

-Steve
August 12, 2010
On 12.08.2010 16:39, Steven Schveighoffer wrote:
(...)
>>
>> Tested with dmd 2.048 on win7.
>>
>> pragma(msg, "module:"~typeof({return 1;}()).stringof);
>>
>> void main()
>> {
>> pragma(msg, "main:"~typeof({return 1;}()).stringof);
>> //typeof({return 1;}()) a; // found 'a' when expecting ';' following
>> statement
>> }
>>
>> prints
>> module:int
>> main:int
>>
>
> Ahh. It fails on 2.047 also if you put the statement inside main. If you
> declare it outside main, it works.
>
> Looks like a bug. Please file http://d.puremagic.com/issues/enter_bug.cgi
>
> -Steve

http://d.puremagic.com/issues/show_bug.cgi?id=4633