digitalmars.D.learn - Cartesian product of immutable ranges
- matovitch (37/37) Jan 26 2014 I posted a question on stackoverflow about the cartesian product
- Stanislav Blinov (12/21) Jan 26 2014 B and C aren't, but B[] and C[] are. That's what's going on when
- matovitch (11/30) Jan 26 2014 You mean that two input ranges are created from the immutable
- Jakob Ovrum (12/21) Jan 26 2014 `Zip` must be explicitly instantiated, which allows you to
- matovitch (4/29) Jan 26 2014 Thank you very much for these very clear explanations ! I am
- matovitch (11/16) Jan 26 2014 Here is the problem...
- Stanislav Blinov (5/5) Jan 26 2014 You might want to consider submitting a bug report on account of
I posted a question on stackoverflow about the cartesian product of immutable ranges : http://stackoverflow.com/questions/21368501/cartesian-product-of-immutable-ranges There are a lot of various thing I don't understand. This code compiles and run : import std.stdio; import std.range; import std.algorithm; void main() { immutable int[] B = [ 1, 2, 3 ]; int[] C = [ 4, 5, 6 ]; auto BC = cartesianProduct(B, C); writeln(BC); } This one doesn't : import std.stdio; import std.range; import std.algorithm; void main() { int[] B = [ 1, 2, 3 ]; immutable int[] C = [ 4, 5, 6 ]; auto BC = cartesianProduct(B, C); writeln(BC); } And this one does : import std.stdio; import std.range; import std.algorithm; void main() { immutable int[] B = [ 1, 2, 3 ]; immutable int[] C = [ 4, 5, 6 ]; auto BC = zip(B, C); writeln(BC); } Here B and C aren't inputRange thought acording to the template constraint of zip there should be. How can it compiles ? How to compute the cartesian product of two immutable ranges ?
Jan 26 2014
On Sunday, 26 January 2014 at 21:49:37 UTC, matovitch wrote:void main() { immutable int[] B = [ 1, 2, 3 ]; immutable int[] C = [ 4, 5, 6 ]; auto BC = zip(B, C); writeln(BC); } Here B and C aren't inputRange thought acording to the template constraint of zip there should be. How can it compiles ?B and C aren't, but B[] and C[] are. That's what's going on when you pass an array as function argument: a full slice is taken. See for yourself: void foo(R)(R r) { writeln(R.stringof); } foo(B); // will print immutable(int)[]How to compute the cartesian product of two immutable ranges ?Short answer: with std.algorithm - you can't. Because internally it (Zip, actually) performs assignments, and you can't assign to immutable(T). Why?
Jan 26 2014
On Sunday, 26 January 2014 at 22:19:47 UTC, Stanislav Blinov wrote:On Sunday, 26 January 2014 at 21:49:37 UTC, matovitch wrote:You mean that two input ranges are created from the immutable arrays when I call the function ? Zip doesn't compiles while zip compile. :/ Here is the implementation of zip : auto zip(Ranges...)(Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges)) { return Zip!Ranges(ranges); }void main() { immutable int[] B = [ 1, 2, 3 ]; immutable int[] C = [ 4, 5, 6 ]; auto BC = zip(B, C); writeln(BC); } Here B and C aren't inputRange thought acording to the template constraint of zip there should be. How can it compiles ?B and C aren't, but B[] and C[] are. That's what's going on when you pass an array as function argument: a full slice is taken. See for yourself: void foo(R)(R r) { writeln(R.stringof); } foo(B); // will print immutable(int)[]
Jan 26 2014
On Sunday, 26 January 2014 at 22:32:32 UTC, matovitch wrote:You mean that two input ranges are created from the immutable arrays when I call the function ? Zip doesn't compiles while zip compile. :/`Zip` must be explicitly instantiated, which allows you to attempt to instantiate it with head-immutable slices, which isn't allowed because head-immutable slices aren't input ranges due to a lack of working `popFront()`.Here is the implementation of zip : auto zip(Ranges...)(Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges)) { return Zip!Ranges(ranges); }`zip` is a range constructor function. These are used to allow IFTI (Implicit Function Template Instantiation) to infer template arguments, so the user doesn't have to provide them explicitly. With IFTI, head-immutable and head-const are stripped from slice types, so even though you pass immutable(int[]), the parameter type is set to be immutable(int)[], i.e. an mutable slice of immutable integers. Only the latter is a valid input range.
Jan 26 2014
On Sunday, 26 January 2014 at 22:52:56 UTC, Jakob Ovrum wrote:On Sunday, 26 January 2014 at 22:32:32 UTC, matovitch wrote:Thank you very much for these very clear explanations ! I am quite tired tonight and shouldn't have started to code in the first place anyway. ;-)You mean that two input ranges are created from the immutable arrays when I call the function ? Zip doesn't compiles while zip compile. :/`Zip` must be explicitly instantiated, which allows you to attempt to instantiate it with head-immutable slices, which isn't allowed because head-immutable slices aren't input ranges due to a lack of working `popFront()`.Here is the implementation of zip : auto zip(Ranges...)(Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges)) { return Zip!Ranges(ranges); }`zip` is a range constructor function. These are used to allow IFTI (Implicit Function Template Instantiation) to infer template arguments, so the user doesn't have to provide them explicitly. With IFTI, head-immutable and head-const are stripped from slice types, so even though you pass immutable(int[]), the parameter type is set to be immutable(int)[], i.e. an mutable slice of immutable integers. Only the latter is a valid input range.
Jan 26 2014
On Sunday, 26 January 2014 at 22:19:47 UTC, Stanislav Blinov wrote:On Sunday, 26 January 2014 at 21:49:37 UTC, matovitch wrote: Short answer: with std.algorithm - you can't. Because internally it (Zip, actually) performs assignments, and you can't assign to immutable(T). Why?Here is the problem... import std.stdio; import std.range; import std.algorithm; void main() { writeln(zip([1,2,4,3], take(Repeat!(immutable(int))(2), 4))); } With the current implementation the second order immutable should be stripped...
Jan 26 2014
You might want to consider submitting a bug report on account of cartesianProduct() not being able to deal with ranges of immutable elements. The worst that can happen is that you'd get a real expert's explanation on why it's not a bug. But who knows, perhaps it is :)
Jan 26 2014