A Small Contribution to Phobos

monarch_dodra monarchdodra at gmail.com
Sun Jun 2 08:41:56 PDT 2013


On Sunday, 2 June 2013 at 13:07:18 UTC, Andrei Alexandrescu wrote:
> On 6/2/13 1:58 AM, Meta wrote:
>>> For reference type ranges and input ranges which are not 
>>> forward
>>> ranges, this
>>> will consume the range and return nothing.
>>
>> I originally wrote it to accept forward ranges and use save, 
>> but I
>> wanted to make it as inclusive as possible. I guess I 
>> overlooked the
>> case of ref ranges.
> [snip]
>
> Thanks for sharing your ideas.
>
> I think consuming all of a range evaluating front and doing 
> nothing should be the role of reduce with only one parameter 
> (the range). That overload would take the range to be 
> "exhausted" and return void. Thus your example becomes:
>
> [1, 2, 3, 4].map!(n => n.writeln).reduce;
>
>
> Andrei

One of the problems with using "map" for something such as this, 
is that the resulting object is not a range, since "front" now 
returns void, and a range *must* return a value. So that code 
will never compile (since reduce will ask for at least input 
range). Heck, I think we should make it so that map refuses to 
compile with an operator that returns void. It doesn't make much 
sense as-is.

Usage has to be something like:

map!((n) {n.writeln; return n;})

which is quite clunky. The idea of a "tee" range, that takes n, 
runs an operation on it, and then returns said n as is becomes 
really very useful (and more idiomatic). [1, 2, 3, 4].tee!(n => 
n.writeln). There! perfect :)

I've dabbled in implementing such a function, but there are 
conceptual problems: If the user calls "front" twice in a row, 
then should "fun" be called twice? If user popsFront without 
calling front, should "fun" be called at all?

Should it keep track of calls, to guarantee 1, and only 1, call 
on each element?

I'm not sure there is a correct answer to that, which is one of 
the reasons I haven't actually submitted anything.

--------

I don't think "argument-less reduce" should do what you describe, 
as it would be a bit confusing what the function does. 1-names; 
1-operation, IMO. Users might accidentally think they are getting 
an additive reduction :(

I think a function called "walk", in line with "walkLength", 
would be much more appropriate, and make more sense to boot!

But we run into the same problem... Should "walk" call front 
between each element? Both answers are correct, IMO.


More information about the Digitalmars-d mailing list