Bug 6756 – Idea about std.stdio.chunks and std.range.chunks
Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2011-10-01T18:51:00Z
Last change time
2015-03-23T13:05:08Z
Assigned to
nobody
Creator
bearophile_hugs
Comments
Comment #0 by bearophile_hugs — 2011-10-01T18:51:32Z
I'm finding the recently introduced std.range.chunks quite useful. In Mathematica there is a similar function (but not lazy and even too much powerful) named Partition:
http://reference.wolfram.com/mathematica/ref/Partition.html
Unfortunately the one in Phobos often causes a name collision in my code:
import std.stdio, std.range;
void main() {
auto ch = chunks(iota(15), 2);
writeln(ch);
}
It gives:
test.d(3): Error: std.stdio.chunks at ...\dmd2\src\phobos\std\stdio.d(2038) conflicts with std.range.chunks(Source) at ...\dmd2\src\phobos\std\range.d(5261)
So you have to write:
import std.stdio, std.range;
void main() {
auto ch = std.range.chunks(iota(15), 2);
writeln(ch);
}
std.stdio.chunks is a struct with this constructor:
struct chunks {
private File f;
private size_t size;
this(File f, size_t size) {
...
While std.range.chunks is a helper function:
Chunks!(Source) chunks(Source)(Source source, size_t chunkSize) {
return typeof(return)(source, chunkSize);
}
That uses:
struct Chunks(Source) if(hasSlicing!Source && hasLength!Source) {
this(Source source, size_t chunkSize) {
this._source = source;
this._chunkSize = chunkSize;
}
...
}
I think you never call std.range.chunks with a File as first argument. The cause of the problem is probably shown in this little test:
struct Foo {}
void bar(Foo x) {}
void bar(T)(T x) if (!is(T == Foo)) {}
//void bar(T)(T x) if (is(T == Foo)) {}
void main() {
bar([1, 2, 3]);
bar(Foo());
}
test.d(4): Error: template test.bar(T) if (!is(T == Foo)) conflicts with function test.bar at test.d(3)
I don't know if in future DMD will allow overloading of functions with templates, but in the meantime a possible solution is to rename the std.stdio.chunks struct to a name that starts with upper case:
struct Chunks
{
private File f;
private size_t size;
// private string fileName; // Currently, no use
this(F f, size_t size)
To introduce a lowercase little helper function template with a template constraint that the first template argument must be a File:
Chunks chunks(F)(F f, size_t size) if (is(F == File))
{
return Chunks(f, size);
}
(This doesn't cause a code bloat because std.stdio.range gets gets instantiated with only one type for the first argument, so it's like a single regular function.)
And then to add a negative template constraint to std.range.chunks:
Chunks!(Source) chunks(Source)(Source source, size_t chunkSize)
if (!is(Source == File) && hasSlicing!Source && hasLength!Source)
{
return typeof(return)(source, chunkSize);
}
I think this solves the name collision problem.
By the way, do you know why std.range.Chunks has a template constraint while its helper function std.range.chunks doesn't have it? Most times you call std.range.chunks. So if you call it with wrong arguments you receive a template error inside std.range instead in your code. This is not good. So I think std.range.chunks needs the same template constraint as std.range.Chunks (plus !is(Source == File) at the start if you accept the idea shown here).
Comment #1 by john.loughran.colvin — 2015-03-23T13:05:08Z
There is no clash anymore, the example given works fine.