www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to easily construct objects with multi-param constructors from

reply "Rene Zwanenburg" <renezwanenburg gmail.com> writes:
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.
Aug 05 2014
next sibling parent "Rene Zwanenburg" <renezwanenburg gmail.com> writes:
On Tuesday, 5 August 2014 at 15:13:37 UTC, Rene Zwanenburg wrote:
 clean looking code to parse Wavefont OBJ files [0].
[0] http://en.wikipedia.org/wiki/Wavefront_.obj_file
Aug 05 2014
prev sibling parent reply Philippe Sigaud via Digitalmars-d-learn writes:
 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.
There is chunks: http://dlang.org/phobos/std_range.html#chunks
Aug 05 2014
parent reply "Rene Zwanenburg" <renezwanenburg gmail.com> writes:
On Tuesday, 5 August 2014 at 19:21:44 UTC, Philippe Sigaud via 
Digitalmars-d-learn wrote:
 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.
There is chunks: http://dlang.org/phobos/std_range.html#chunks
Yea, but that won't work for forward ranges. It only provides opIndex if the underlying range provides it. Since the chunk size is a runtime parameter it can't implement opIndex efficiently for non-random access ranges. staticChunks was a bit of a misnomer. staticTake would be a better name. The range would contains a static array and pops that number of elements from the input range. Then, opIndex can easily be defined.
Aug 06 2014
parent reply Philippe Sigaud via Digitalmars-d-learn writes:
 Yea, but that won't work for forward ranges. It only provides opIndex if the
 underlying range provides it. Since the chunk size is a runtime parameter it
 can't implement opIndex efficiently for non-random access ranges.
But in your case, your range is random-access, no? Or else, you can always map array on the chunks...
 staticChunks was a bit of a misnomer. staticTake would be a better name. The
 range would contains a static array and pops that number of elements from
 the input range. Then, opIndex can easily be defined.
What about takeExactly?
Aug 06 2014
parent "Rene Zwanenburg" <renezwanenburg gmail.com> writes:
On Wednesday, 6 August 2014 at 08:00:32 UTC, Philippe Sigaud via 
Digitalmars-d-learn wrote:
 Yea, but that won't work for forward ranges. It only provides 
 opIndex if the
 underlying range provides it. Since the chunk size is a 
 runtime parameter it
 can't implement opIndex efficiently for non-random access 
 ranges.
But in your case, your range is random-access, no?
Nope, splitter returns a forward range.
 Or else, you can always map array on the chunks...
Sure. But that would be a completely unnecessary allocation. I'm trying to avoid those, it's what ranges are supposed to be good at ;)
 staticChunks was a bit of a misnomer. staticTake would be a 
 better name. The
 range would contains a static array and pops that number of 
 elements from
 the input range. Then, opIndex can easily be defined.
What about takeExactly?
Same problem. As long as the 'count' parameter is a runtime value instead of a compile time value, it's impossible to define opIndex efficiently. Therefore the Phobos ranges don't do it.
Aug 06 2014