September 20, 2012
Le 20/09/2012 18:55, bearophile a écrit :
> Timon Gehr:
>
>> Formalising it is not hard,
>
> I am not sure of this, given the amount of special cases it already has.
>

This is made for less special cases. Which is an improvement.
September 20, 2012
On 09/20/2012 06:55 PM, bearophile wrote:
> Timon Gehr:
>
>> Formalising it is not hard,
>
> I am not sure of this, given the amount of special cases it already has.
>

Which special cases do you refer to?

>
>> The number of lines equals the Haskell example in this case.
>> Interestingly, you have opened an enhancement request on this and then
>> argued against it.
>
> I am not against it, it's a nice syntax. But I think there are more
> useful things to change/add, like syntax to destructure tuples, that I
> need every 20 lines of code or so. When you put out many suggestions, I
> think it's important to specify what you think is more important and
> what's less important.
>

Well, => for functions is a trivial parser change, and tuple
destructuring is already implemented. (but not pulled)

>
>> There is no 'right' way.
>
> So we don't agree even on what we have to agree :-)

I agree.

>
> And having multiple correct ways to do something is often bad :-(
>

Then we're fine. These are two notations for doing it the same way.
September 20, 2012
Timon Gehr:

> mixin ADT!q{ Tree(T): Leaf(T x), Node(Tree a, Tree b) };
>
> DynRange!T fringe(T)(Tree!T t){
>     return t.match!(
>         (Leaf l) => cons(l.x, empty),
>         (Node n) => chain(n.a.fringe, n.b.fringe).dynRange,
>     );
> }
>
> bool sameFringe(T)(Tree!T t1, Tree!T t2){
>     return equal(t1.fringe, t2.fringe);
> }

What's the purpose of the dynRange suffix here?
(Node n) => chain(n.a.fringe, n.b.fringe).dynRange

Maybe a "~" operator can be defined for such dynRanges, to avoid the chain().

Bye,
bearophile
September 20, 2012
Thank for these slides.

I didn't get some part of the VRP slides: p40 of the third lesson:
byte a, b, c;
a = 1;
b = c | a; // error
Is-this really an error? A binary-or operation on bytes should return a byte..

BR,
renoX
September 20, 2012
On 09/20/2012 11:33 PM, bearophile wrote:
> Timon Gehr:
>
>> mixin ADT!q{ Tree(T): Leaf(T x), Node(Tree a, Tree b) };
>>
>> DynRange!T fringe(T)(Tree!T t){
>>     return t.match!(
>>         (Leaf l) => cons(l.x, empty),
>>         (Node n) => chain(n.a.fringe, n.b.fringe).dynRange,
>>     );
>> }
>>
>> bool sameFringe(T)(Tree!T t1, Tree!T t2){
>>     return equal(t1.fringe, t2.fringe);
>> }
>
> What's the purpose of the dynRange suffix here?
> (Node n) => chain(n.a.fringe, n.b.fringe).dynRange
>

chain has type Result. dynRange takes an arbitrary range and transforms
it into a range with the same value/vs reference behaviour whose static
type depends only on the element type.

> Maybe a "~" operator can be defined for such dynRanges, to avoid the
> chain().

Yes, that should certainly be done. (it can be more efficient.)

September 20, 2012
On 09/21/2012 12:03 AM, renoX wrote:
> Thank for these slides.
>
> I didn't get some part of the VRP slides: p40 of the third lesson:
> byte a, b, c;
> a = 1;
> b = c | a; // error
> Is-this really an error? A binary-or operation on bytes should return a
> byte..
>
> BR,
> renoX

The result is an int but value range propagation makes it compile. The
slide seems to be in error.
September 20, 2012
On Thu, 20 Sep 2012 17:06:19 +0200
"David Nadlinger" <see@klickverbot.at> wrote:
> 
> The code on slide 6 contains an issue resp. inaccuracy: Not all random access ranges are sliceable. Sometimes I wonder (and this is not at all intended as a snide remark!) if it is too easy to make mistakes regarding template constraints, if even you as the (co-?) designer of std.range get them wrong occasionally.
> 

Maybe we could have an interface tester: Something that will automatically try to pass in a bunch of known types to whatever templated function you give it (and maybe a limited subset of combinations for multiple args), and makes sure the the result is always either "Compiles OK" or "Match not found", and never a compile error from *inside* the given function template. When it compiles OK, maybe it could even automatically run associated unittests (not sure though).

I don't know that this could be done as a library, as it would require distinguishing between different types of compile errors. But I bet it could reasonably be done as a CLI tool that invokes DMD.

September 20, 2012
Timon Gehr:

> chain has type Result. dynRange takes an arbitrary range and transforms
> it into a range with the same value/vs reference behaviour whose static
> type depends only on the element type.

I see. So that chain() is the normal chain of Phobos :-)

(But is DynRange a lazy stream/sequence? This is the most important thing, because creating an eager linked list is kind of easy already, and misses the main point of my "request".)

Bye,
bearophile
September 20, 2012
On 09/21/2012 12:51 AM, bearophile wrote:
> Timon Gehr:
>
>> chain has type Result. dynRange takes an arbitrary range and transforms
>> it into a range with the same value/vs reference behaviour whose static
>> type depends only on the element type.
>
> I see. So that chain() is the normal chain of Phobos :-)
>

Exactly.

> (But is DynRange a lazy stream/sequence? This is the most important
> thing, because creating an eager linked list is kind of easy already,
> and misses the main point of my "request".)
>
> Bye,
> bearophile

Proof of concept:

import std.range, std.algorithm;
struct DynRange(T){
    @property T front(){ return frontImpl(); }
    @property bool empty(){ return emptyImpl(); }
    void popFront(){
        auto u = popFrontImpl();
        frontImpl = u.frontImpl;
        emptyImpl = u.emptyImpl;
        popFrontImpl = u.popFrontImpl;
    }
private:
    T delegate() frontImpl;
    bool delegate() emptyImpl;
    DynRange!T delegate() popFrontImpl;
}
DynRange!(ElementType!R) dynRange(R)(R range)if(isInputRange!R){
    DynRange!(ElementType!R) result;
    result.frontImpl = ()=>range.front;
    result.emptyImpl = ()=>range.empty;
    result.popFrontImpl = (){
        auto newRange = range;
        newRange.popFront();
        return dynRange(newRange);
    };
    return result;
}

void main(){
    auto r = iota(0,10).dynRange;
    auto t = [1,2,3,4,5].dynRange;
    import std.stdio;
    writeln(r,r,t,t);
}

To allow the definition of recursive lazy ranges, we'd also need
a facility to 'delay' computation. I'll post a proof of concept
tomorrow, by implementing eg. a lazy prime sieve.


September 21, 2012
On 9/20/12 10:06 AM, Simen Kjaeraas wrote:
> Cool. And now the inevitable: Will there be video?

No video was taken.

Andrei