Is this code "D-ish" enough?

Justin Whear justin at economicmodeling.com
Wed Aug 7 13:31:04 PDT 2013


The key problem here is that you have an unstructured range of bytes and 
you want to provide a function to iteratively structure it.  The 
splitting and chunking functionality in Phobos doesn't fit because the 
records are not of fixed size nor do they contain a usable delimiter.  
Unfortunately, I can't think of anything currently in Phobos that makes 
this easy.

My take on this was to define a range which induces structure over 
another by consuming it with a user function; for lack of a better term I 
called it "restructure".  It works much like map, except instead of 
passing an element to the user function, it passes the range itself and 
the function is expected to consume some amount of it.

Here's the code rewritten (without your formatting map) with the 
restructure function:

import std.stdio,
	std.range,
	std.algorithm,
	std.file,
	std.typecons;
import std.bitmanip : readAs = read;

void main(string[] args)
{
	string readZeroTerminatedString(R)(ref R range)
	{
		return (cast(char[])range.until!('\0').array).idup;
	}

	// Read file as range of bytes
	File("binsplit.bin", "rb")
		.byChunk(1024 * 4)
		.joiner

		// Induce our record structure over that range
		.restructure!(r => tuple(r.readAs!int, 
r.readZeroTerminatedString))

		// Sort the records by the first field (id)
		.sort((a, b) => a[0] < b[0])

		// Write to stdout
		.copy(stdout.lockingTextWriter);
}

And here's a quick and dirty outline of the restructure function itself.  
Unfortunately, it doesn't actually compile due to needing to take the 
source range by ref.  Also, the user function needs to take the range by 
ref so that it can be consumed.

auto restructure(alias Fun, R)(ref R range)
	if (isInputRange!R 
		//TODO test Fun: must be an unary function taking R
	)
{
	struct Result
	{
		alias F = typeof(Fun(range));
		private R range;
		private F _front;

		bool empty() @property { return range.empty; }
		F front() @property { return _front; }
		void popFront()
		{
			_front = Fun(range);
		}
	}

	return Result(range);
}


More information about the Digitalmars-d-learn mailing list