November 17, 2009
Lars T. Kyllingstad, el 17 de noviembre a las 15:12 me escribiste:
> Leandro Lucarella wrote:
> >Lars T. Kyllingstad, el 17 de noviembre a las 09:54 me escribiste:
> >>>In some ways the current code is better, because it actually checks if a construct works or not, rather than requiring a specific function signature.  Whether the code will work is really the minimal restriction you can place on the interface.  A specific may be too tight.  For instance, above you don't really care if empty returns bool or not.  Just if you can test it in an "if".
> >>Another, related way in which the current code is better is that it doesn't care whether empty, front, and popFront are functions or variables.  As we know, the standard trick for infinite ranges is to declare empty as an enum, not a function.
> >
> >Is not that hard to write:
> >bool empty() { return false; }
> >instead of
> >enum bool empty = false;
> 
> 
> That's why I mentioned infinite ranges. An infinite range is *defined* as a range where empty is implemented as
> 
>   enum bool empty = false;
> 
> isInfinite(Range) tests whether this is the case, which it wouldn't
> be able to do if empty() was a function.

OK, there are way to fix that too, but I see your point now.

-- 
Leandro Lucarella (AKA luca)                     http://llucax.com.ar/
----------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------
"The Guinness Book of Records" holds the record for being the most stolen book in public libraries
November 17, 2009
On 2009-11-17 09:12:04 -0500, "Lars T. Kyllingstad" <public@kyllingen.NOSPAMnet> said:

> That's why I mentioned infinite ranges. An infinite range is *defined* as a range where empty is implemented as
> 
>    enum bool empty = false;
> 
> isInfinite(Range) tests whether this is the case, which it wouldn't be able to do if empty() was a function.

Which makes me think: what about a range that can but may not necessarily be infinite depending on runtime parameters? For instance, you could have a range returning a rational number as decimal digits: some will be infinite and others will be finite depending on the rational number (like 1/3 vs. 1/4). You can't express that with an enum.

I guess you could fix that by overloading isInfinite for your specific range type though.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/

November 17, 2009
On Tue, Nov 17, 2009 at 5:51 AM, Leandro Lucarella <llucax@gmail.com> wrote:
> Bill Baxter, el 16 de noviembre a las 15:42 me escribiste:
>> On Mon, Nov 16, 2009 at 9:25 AM, Leandro Lucarella <llucax@gmail.com> wrote:
>>
>> This topic is actually very close to a discussion last week about retrieving error messages from failures of __traits(compiles, xxx).
>>
>> My question is: is it really that much of an improvement?
>>
>> I've rearranged your code to see the equivalent snippets side-by-side:
>>
>> > static interface InputRange(T) {
>> >        bool empty();
>> >        T front();
>> >        void popFront();
>> > }
>>
>>
>> > template isInputRange(R)
>> > {
>> >    enum bool isInputRange = is(typeof(
>> >    {
>> >        R r;
>> >        if (r.empty) {}
>> >        r.popFront;
>> >        auto h = r.front;
>> >    }()));
>> > }
>>
>> There's actually not that much difference here.  Of course we would
>> like several general improvements that have been discussed before:
>> 1) some kind of template 'this' so we don't have to repeat the template name.
>> 2) something better than is(typeof()) (or __traits(compiles, ...)) to
>> check if code is ok. [hoping for meta.compiles(...)]
>>
>> In some ways the current code is better, because it actually checks if a construct works or not, rather than requiring a specific function signature.  Whether the code will work is really the minimal restriction you can place on the interface.  A specific may be too tight.  For instance, above you don't really care if empty returns bool or not.  Just if you can test it in an "if".
>
> I think one could argue if being more restrictive is actually good or bad.
> Being more restrictive cold lead to less errors. Maybe if a struct empty()
> method returns, say, a pointer, I don't want to think it is *really*
> a range. Maybe that method is doing a lot of work and removing stuff, and
> then returning a pointer to some removed stuff. Anyway, I'm not saying
> that that couldn't happen even if empty() return bool (that's a risk when
> duck-typing, always :), I'm just saying I'm not so sure that being more
> restrictive is really a *bad thing*.

If that's what you want, the D way gives you the option of checking

       is(typeof(R.empty)==bool)

But yeh, that is klunkier than just writing out the function signature you're expecting.


> And about what's nice or ugly, I agree the current way of doing stuff is not too bad, there are a few details that are not *that* nice. But with duck-typing I think the same that with tuples: those little details makes you feel that D doesn't support the concept so well, and make people resistant to use them. When something feels natural in a language, you use it all the time, for me, the current way to do tuples and duck-typing looks very artificial and harder than it should.

Agreed.  But as for the duck typing aspect, I think there isn't
necessarily an either-or choice here.
For instance, in D, we could allow a static interface to have a static
assert block:

     static interface InputRange(T) {
         static assert (meta.compiles({
               if (this.empty) {};  // this is a shortcut for T.init
         }));
         T front();
         void popFront();
      }

Or something like that.  "Invariant {}" might be better there.

>> But in terms of functionality it seems we cover pretty much everything static interface gives you.
>
> I know that, I started this proposal just saying that =)

Ah.  Sorry, I missed that comment.

--bb
November 18, 2009
In order to achieve good completion support by editors (like
IntelliSense) with duck-typed variables, concept-checking code should
contain more type information than that of the code now used in Phobos.

Example:

  static interface InputRange(T) {
    const bool empty();
    T front();
    void popFront();
  }

or in the current D syntax,

  template isInputRange(T, R) {
    enum isInputRange =
      is(const(R).init.empty() == bool) &&
      is(R.init.front() == T) &&
      is(R.init.popFront() == void);
  }

How do you think about this?
November 19, 2009
Leandro Lucarella <llucax@gmail.com> wrote:

> What do you think?

I was inspired:

template staticInterface( T, iface ) {
	static assert( is( iface == interface ) );
	static assert( is( T == struct ) );
	alias staticInterfaceImpl!( T, MemberTuple!( iface ) ) staticInterface;
}

template staticInterfaceImpl( T, U... ) {
	static if ( U.length ) {
		enum staticInterfaceImpl = isIn!( U[ 0 ], U[ 1 ], MemberTuple!( T ) ) && staticInterfaceImpl!( T, U[ 2..$ ] );
	} else {
		enum staticInterfaceImpl = true;
	}
}

template MemberTuple( T ) {
	alias allMembersToTypeTuple!( T, __traits( allMembers, T ) ) MemberTuple;
}

template allMembersToTypeTuple( T, alias U, V... ) {
	static if( U.length ) {
		alias allMembersToTypeTuple!( T, U[1..$], U[ 0 ], typeof( mixin( T.stringof ~ "." ~ U[ 0 ] ) ), V ) allMembersToTypeTuple;
	} else {
		alias V allMembersToTypeTuple;
	}
}

template isIn( string name, T, U... ) {
	static if ( U.length ) {
		enum isIn = ( name == U[ 0 ] && is( T == U[ 1 ] ) ) || isIn!( name, T, U[ 2..$ ] );
	} else {
		enum isIn = false;
	}
}

Usage:

interface I;
struct S;
static if ( staticInterface!( S, I ) ) {}

There may be problems with this, and it might not match everything as nicely as it should, but it's a proof-of-concept. I'm open to suggestions on how to extend/fix it.

-- 
Simen
November 19, 2009
Simen kjaeraas, el 19 de noviembre a las 12:47 me escribiste:
> Leandro Lucarella <llucax@gmail.com> wrote:
> 
> >What do you think?
> 
> I was inspired:
> 
[...]
> 
> Usage:
> 
> interface I;
> struct S;
> static if ( staticInterface!( S, I ) ) {}
[...]

Nice! :)


-- 
Leandro Lucarella (AKA luca)                     http://llucax.com.ar/
----------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------
- Los romanos no tenían paz, loco... Necesitaban un poco de chala...
1 2 3
Next ›   Last »