How to easily construct objects with multi-param constructors from lazy ranges?
Rene Zwanenburg via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Tue Aug 5 08:13:36 PDT 2014
Here's something which I've run into a few times now without
finding a pretty solution. When parsing a text file using lazy
ranges and algorithms you will have to convert a string range to
an object at some point.
In this particular case I was curious to see if I could write
clean looking code to parse Wavefont OBJ files [0]. A simple OBJ
file could look like this:
v 0 1 0
v 1 1 0
v 1 0 0
v 0 0 0
vn 0 0 1
f 3//1 2//1 1//1
f 3//1 4//1 2//1
Now, to parse the vertex positions (the lines beginning with 'v')
I use:
struct vec3
{
float[3] v;
this(float x, float y, float z){ ... }
}
void foo()
{
auto lines =
File("SomeFile.obj")
.byLine
.map!(a => a.strip)
.filter!(a => !a.empty)
.filter!(a => !a.startsWith('#'));
auto vertices =
lines
.filter!(a => a.startsWith('v'))
.map!(a => a.splitter)
// Now what?
}
What is a nice way to convert the forward range ["v", "0", "1",
"0"] to a vec3, without unneccessary allocations? Creating a
constructor function like
vec3 parseVec(R)(R range)
{
vec3 v;
v.v[0] = range.front.to!float;
range.popFront();
// Etc.
return v;
}
seems terribly awkward to me.
Some range which takes an at compile time known number of
elements from an input range and provides opIndex seems perfect
to me, but as far as I know there's no such thing in Phobos. It
would allow
auto vertices =
lines
.filter!(a => a.startsWith('v'))
.map!(a => a.splitter)
.map!(a => a.staticChunks!4)
.map!(a => vec3(a[1].to!float, a[2].to!float, a[3].to!float));
without heap allocations. Anyone know if Phobos has something
like this? Or another approach?
If not I'm willing to create something like staticChunks if
there's interest to add it to std.range.
More information about the Digitalmars-d-learn
mailing list