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.

Reply via email to