digitalmars.D.announce - Slides from LASER 2012
- Andrei Alexandrescu (14/14) Sep 20 2012 I've had the honor of rubbing shoulders for a week at
- Simen Kjaeraas (5/18) Sep 20 2012 Cool. And now the inevitable: Will there be video?
- Andrei Alexandrescu (3/4) Sep 20 2012 No video was taken.
- Simen Kjaeraas (5/9) Sep 21 2012 *sadface*
- deadalnix (2/16) Sep 20 2012 What is Sininimp-Mulinint object-oriented style ?
- Peter Alexander (5/6) Sep 20 2012 I believe it's some weird way of saying:
- Andrei Alexandrescu (3/4) Sep 20 2012 Single inheritance of implementation, multiple inheritance of interface.
- bearophile (42/49) Sep 20 2012 Formalizing D purity is probably possible, but it already has
- Timon Gehr (46/94) Sep 20 2012 Formalising it is not hard, but the D implementation will have to be
- bearophile (12/17) Sep 20 2012 I am not sure of this, given the amount of special cases it
- deadalnix (2/5) Sep 20 2012 This is made for less special cases. Which is an improvement.
- Timon Gehr (6/20) Sep 20 2012 Well, => for functions is a trivial parser change, and tuple
- bearophile (4/26) Sep 20 2012 And thank you for the code example.
- deadalnix (4/32) Sep 20 2012 I proposed something similar in the epic delegate thread. I observe that...
- bearophile (7/17) Sep 20 2012 What's the purpose of the dynRange suffix here?
- Timon Gehr (5/22) Sep 20 2012 chain has type Result. dynRange takes an arbitrary range and transforms
- bearophile (7/12) Sep 20 2012 I see. So that chain() is the normal chain of Phobos :-)
- Timon Gehr (38/48) Sep 20 2012 Proof of concept:
- Dmitry Olshansky (6/58) Sep 21 2012 I swear I've seen it somewhere in Phobos:
- Timon Gehr (14/76) Sep 21 2012 (Assuming you relate to the range part, and not the delay part.)
- David Nadlinger (10/11) Sep 20 2012 Bummer that they didn't hold the event in Zurich – maybe I
- Nick Sabalausky (12/19) Sep 20 2012 Maybe we could have an interface tester: Something that will
- Andrei Alexandrescu (4/14) Sep 20 2012 In fairness, this issue is in the air at this time. We're still mulling
- renoX (9/9) Sep 20 2012 Thank for these slides.
- Timon Gehr (3/12) Sep 20 2012 The result is an int but value range propagation makes it compile. The
- Andrei Alexandrescu (6/15) Sep 20 2012 Yes, it's a bug in the slides. Thanks! A correct example would be:
- renoX (6/26) Sep 21 2012 Ah, I understand better now.
I've had the honor of rubbing shoulders for a week at http://laser.inf.ethz.ch/2012/ with Roberto Ierusalimschy, Ivar Jacobson, Erik Meijer, Bertrand Meyer, Martin Odersky, Simon Peyton-Jones, and Guido van Rossum. It was awesome, and I got many good tips on how to grow our community. In particular, I've enjoyed a few good discussions with Simon and Martin about D's approach to doing things. In particular, Martin has been quite impressed with our approach to purity and immutability. We are considering a collaboration with one of his students on a paper to formalize the approach and possibly adapt it to Scala. So, these are the slides I've used (though of course they don't tell much of the story). http://laser.inf.ethz.ch/2012/slides/Alexandrescu/2-D%20course%20parts%201%20and%202.pdf Andrei
Sep 20 2012
On Thu, 20 Sep 2012 14:57:45 +0200, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I've had the honor of rubbing shoulders for a week at http://laser.inf.ethz.ch/2012/ with Roberto Ierusalimschy, Ivar Jacobson, Erik Meijer, Bertrand Meyer, Martin Odersky, Simon Peyton-Jones, and Guido van Rossum. It was awesome, and I got many good tips on how to grow our community. In particular, I've enjoyed a few good discussions with Simon and Martin about D's approach to doing things. In particular, Martin has been quite impressed with our approach to purity and immutability. We are considering a collaboration with one of his students on a paper to formalize the approach and possibly adapt it to Scala. So, these are the slides I've used (though of course they don't tell much of the story). http://laser.inf.ethz.ch/2012/slides/Alexandrescu/2-D%20course%20parts%201%20and%202.pdfCool. And now the inevitable: Will there be video? -- Simen
Sep 20 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
Sep 20 2012
On Fri, 21 Sep 2012 05:58:21 +0200, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 9/20/12 10:06 AM, Simen Kjaeraas wrote:*sadface* -- SimenCool. And now the inevitable: Will there be video?No video was taken. Andrei
Sep 21 2012
Le 20/09/2012 14:57, Andrei Alexandrescu a écrit :I've had the honor of rubbing shoulders for a week at http://laser.inf.ethz.ch/2012/ with Roberto Ierusalimschy, Ivar Jacobson, Erik Meijer, Bertrand Meyer, Martin Odersky, Simon Peyton-Jones, and Guido van Rossum. It was awesome, and I got many good tips on how to grow our community. In particular, I've enjoyed a few good discussions with Simon and Martin about D's approach to doing things. In particular, Martin has been quite impressed with our approach to purity and immutability. We are considering a collaboration with one of his students on a paper to formalize the approach and possibly adapt it to Scala. So, these are the slides I've used (though of course they don't tell much of the story). http://laser.inf.ethz.ch/2012/slides/Alexandrescu/2-D%20course%20parts%201%20and%202.pdf AndreiWhat is Sininimp-Mulinint object-oriented style ?
Sep 20 2012
On Thursday, 20 September 2012 at 14:15:22 UTC, deadalnix wrote:What is Sininimp-Mulinint object-oriented style ?I believe it's some weird way of saying: SINgle INheritance of IMPlementation MULtiple INheritance of INTerfaces As opposed to C++ where you can multiply inherit implementations.
Sep 20 2012
On 9/20/12 10:16 AM, deadalnix wrote:What is Sininimp-Mulinint object-oriented style ?Single inheritance of implementation, multiple inheritance of interface. Andrei
Sep 20 2012
Andrei Alexandrescu:In particular, Martin has been quite impressed with our approach to purity and immutability. We are considering a collaboration with one of his students on a paper to formalize the approach and possibly adapt it to Scala.Formalizing D purity is probably possible, but it already has many special cases, and few more are coming (see Bugzilla on this)! Regarding cross pollination with Scala: despite I generally don't like lazy lists in high-performance code, in many other kinds of code they are very handy, as in Haskell, Perl6 and Scala (in Scala they are named purely functional lazy streams). lazily, the Range-based version in D is sometimes several times longer, much more easy to get wrong, harder to write, etc. This is Haskell code to test if just the leaves of two binary trees contain the same data, this code is lazy: data Tree a = Leaf a | Node (Tree a) (Tree a) fringe :: Tree a -> [a] fringe (Leaf x) = [x] fringe (Node n1 n2) = fringe n1 ++ fringe n2 sameFringe :: (Eq a) => Tree a -> Tree a -> Bool sameFringe t1 t2 = fringe t1 == fringe t2 Doing the same thing in D, using ranges, is possible, but the code is ten times longer or more: http://rosettacode.org/wiki/Same_Fringe#Strong_Lazy_Version Similar code is possible in Scala (and in this case most of the saving of lines of code doesn't come from pattern matching and algebraic data types, but from the good support for lazy lists/streams). This kind of code is very common, even when you aren't coding in functional style. --------------------So, these are the slides I've used (though of course they don't tell much of the story). http://laser.inf.ethz.ch/2012/slides/Alexandrescu/2-D%20course%20parts%201%20and%202.pdfThank you for the slides. I hope we'll have the range-based min(), and argmin/argmax in Phobos :-) -------------------- At page 33: auto m = s.argmin!((x) => x.length); This isn't compiled with -property. So what's the right way to write D code? In Python to avoid that lambda there is a len() global function, that just calls the __len__ attribute/property of collections and objects. So an equivalent Python version is: auto m = s.argmin!len; Bye, bearophile
Sep 20 2012
On 09/20/2012 04:23 PM, bearophile wrote:Andrei Alexandrescu:Formalising it is not hard, but the D implementation will have to be fixed. Just decouple 'immutable' and 'pure' completely, int foo()pure{ int x; immutable int y; void bar()pure{ x++; // ok } int baz()pure immutable{ return y; // ok } int foo()pure immutable{ return x; // error } } then rename pure to somethingother and make pure a synonym for somethingother immutable and add that to Scala.In particular, Martin has been quite impressed with our approach to purity and immutability. We are considering a collaboration with one of his students on a paper to formalize the approach and possibly adapt it to Scala.Formalizing D purity is probably possible, but it already has many special cases, and few more are coming (see Bugzilla on this)!Regarding cross pollination with Scala: despite I generally don't like lazy lists in high-performance code, in many other kinds of code they are very handy, as in Haskell, Perl6 and Scala (in Scala they are named purely functional lazy streams). the Range-based version in D is sometimes several times longer, much more easy to get wrong, harder to write, etc. This is Haskell code to test if just the leaves of two binary trees contain the same data, this code is lazy: data Tree a = Leaf a | Node (Tree a) (Tree a) fringe :: Tree a -> [a] fringe (Leaf x) = [x] fringe (Node n1 n2) = fringe n1 ++ fringe n2 sameFringe :: (Eq a) => Tree a -> Tree a -> Bool sameFringe t1 t2 = fringe t1 == fringe t2 Doing the same thing in D, using ranges, is possible, but the code is ten times longer or more: http://rosettacode.org/wiki/Same_Fringe#Strong_Lazy_VersionThe translation is (spaces added for your convenience, you won't get me to use parens though): 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); } for suitable definitions of ADT, DynRange/dynRange, cons and empty. So those would be nice additions to Phobos. Obviously this would look even better: mixin ADT!q{ Tree(T): Leaf(T x), Node(Tree a, Tree b) }; DynRange!T fringe(T)(Tree!T t) => 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) => t1.fringe == t2.fringe; 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.Similar code is possible in Scala (and in this case most of the saving of lines of code doesn't come from pattern matching and algebraic data types, but from the good support for lazy lists/streams). This kind of code is very common, even when you aren't coding in functional style. --------------------There is no 'right' way. But this is the pretty way, the way you use to show off the language at a presentation (otherwise you'll get questions like: "that is all well, but what on earth is that second pair of parens for?")So, these are the slides I've used (though of course they don't tell much of the story). http://laser.inf.ethz.ch/2012/slides/Alexandrescu/2-D%20course%20parts%201%20and%202.pdfThank you for the slides. I hope we'll have the range-based min(), and argmin/argmax in Phobos :-) -------------------- At page 33: auto m = s.argmin!((x) => x.length); This isn't compiled with -property. So what's the right way to write D code?In Python to avoid that lambda there is a len() global function, that just calls the __len__ attribute/property of collections and objects. So an equivalent Python version is: auto m = s.argmin!len; Bye, bearophile
Sep 20 2012
Timon Gehr:Formalising it is not hard,I am not sure of this, given the amount of special cases it already has.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.There is no 'right' way.So we don't agree even on what we have to agree :-) And having multiple correct ways to do something is often bad :-( Bye, bearophile
Sep 20 2012
Le 20/09/2012 18:55, bearophile a Ă©crit :Timon Gehr:This is made for less special cases. Which is an improvement.Formalising it is not hard,I am not sure of this, given the amount of special cases it already has.
Sep 20 2012
On 09/20/2012 06:55 PM, bearophile wrote:Timon Gehr:Which special cases do you refer to?Formalising it is not hard,I am not sure of this, given the amount of special cases it already has.Well, => for functions is a trivial parser change, and tuple destructuring is already implemented. (but not pulled)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.I agree.There is no 'right' way.So we don't agree even on what we have to 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.
Sep 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); } for suitable definitions of ADT, DynRange/dynRange, cons and empty. So those would be nice additions to Phobos. Obviously this would look even better: mixin ADT!q{ Tree(T): Leaf(T x), Node(Tree a, Tree b) }; DynRange!T fringe(T)(Tree!T t) => 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) => t1.fringe == t2.fringe;And thank you for the code example. Bye, bearophile
Sep 20 2012
Le 20/09/2012 18:39, Timon Gehr a Ă©crit :On 09/20/2012 04:23 PM, bearophile wrote:I proposed something similar in the epic delegate thread. I observe that thing fall together nicely with it on several topics. It seems like the way to go.Andrei Alexandrescu:Formalising it is not hard, but the D implementation will have to be fixed. Just decouple 'immutable' and 'pure' completely, int foo()pure{ int x; immutable int y; void bar()pure{ x++; // ok } int baz()pure immutable{ return y; // ok } int foo()pure immutable{ return x; // error } } then rename pure to somethingother and make pure a synonym for somethingother immutable and add that to Scala.In particular, Martin has been quite impressed with our approach to purity and immutability. We are considering a collaboration with one of his students on a paper to formalize the approach and possibly adapt it to Scala.Formalizing D purity is probably possible, but it already has many special cases, and few more are coming (see Bugzilla on this)!
Sep 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
Sep 20 2012
On 09/20/2012 11:33 PM, 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.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).dynRangeMaybe a "~" operator can be defined for such dynRanges, to avoid the chain().Yes, that should certainly be done. (it can be more efficient.)
Sep 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
Sep 20 2012
On 09/21/2012 12:51 AM, bearophile wrote:Timon Gehr:Exactly.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, bearophileProof 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.
Sep 20 2012
On 21-Sep-12 03:27, Timon Gehr wrote:On 09/21/2012 12:51 AM, bearophile wrote:I swear I've seen it somewhere in Phobos: http://dlang.org/phobos/std_range.html#InputRangeObject and friends. Maybe we ought to lay a better infrastructure for it. -- Dmitry OlshanskyTimon Gehr:Exactly.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, bearophileProof 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.
Sep 21 2012
On 09/21/2012 07:46 PM, Dmitry Olshansky wrote:On 21-Sep-12 03:27, Timon Gehr wrote:(Assuming you relate to the range part, and not the delay part.) I am aware of that. That one is unusable in its current state. import std.range; void main(){ auto r = iota(0,10).inputRangeObject; auto t = [1,2,3,4,5].inputRangeObject; import std.stdio; writeln(r,r,t,t); // [0,1,2,3,4,5,6,7,8,9][][1,2,3,4,5][] } Yes, I could use 'save' everywhere, but I really do not want to. The 'dynamic' range should behave the same as the one exposing the full static type. It shouldn't be made so easy to make aliasing-related errors.On 09/21/2012 12:51 AM, bearophile wrote:I swear I've seen it somewhere in Phobos: http://dlang.org/phobos/std_range.html#InputRangeObject and friends. Maybe we ought to lay a better infrastructure for it.Timon Gehr:Exactly.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, bearophileProof 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.
Sep 21 2012
Bummer that they didn't hold the event in Zurich – maybe I would have managed to sneak in… ;) On Thursday, 20 September 2012 at 12:56:44 UTC, Andrei Alexandrescu wrote:http://laser.inf.ethz.ch/2012/slides/Alexandrescu/2-D%20course%20parts%201%20and%202.pdfThe 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. David
Sep 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.
Sep 20 2012
On 9/20/12 11:06 AM, David Nadlinger wrote:Bummer that they didn't hold the event in Zurich – maybe I would have managed to sneak in… ;) On Thursday, 20 September 2012 at 12:56:44 UTC, Andrei Alexandrescu wrote:In fairness, this issue is in the air at this time. We're still mulling over on characterizing infinite ranges that offer random access. Andreihttp://laser.inf.ethz.ch/2012/slides/Alexandrescu/2-D%20course%20parts%201%20and%202.pdfThe 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.
Sep 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
Sep 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, renoXThe result is an int but value range propagation makes it compile. The slide seems to be in error.
Sep 20 2012
On 9/20/12 6:03 PM, 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, renoXYes, it's a bug in the slides. Thanks! A correct example would be: byte a, b; int c = 1; b = c | a; Andrei
Sep 20 2012
On Friday, 21 September 2012 at 04:56:04 UTC, Andrei Alexandrescu wrote:On 9/20/12 6:03 PM, renoX wrote:Ah, I understand better now. Thanks for your reply. BR, renoXThank 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, renoXYes, it's a bug in the slides. Thanks! A correct example would be: byte a, b; int c = 1; b = c | a; Andrei
Sep 21 2012