Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
July 17, 2015 Infinite range of nullable elements | ||||
---|---|---|---|---|
| ||||
At this moment I'm tempted to implement a function taking a range of elements E and returning an infinite range of Nullable!E. With this function ("cushion" for a lack of better name) I could do: auto a = [0,1,2,3,4,5,6,7,8,9]; foreach (e ; a.cushion.take(20)) writeln(e); // exactly 20 elements This would allow chaining together algorithms that need to look ahead in a range. Here's how I would implement the basic behaviour (could be extended to also forward bidirectional and random access functions): --- auto cushion(R)(R r) if (isInputRange!R) { static if (isInfinite!R) { return r; } else { struct _Cushion(R) { R r; alias E = ElementType!R; alias NE = Nullable!E; @property bool empty() { return false; } @property NE front() { return !r.empty ? NE(r.front) : NE(); } void popFront() { if (!r.empty) r.popFront(); } } return _Cushion!R(r); } } --- I didn't find anything like this Phobos. Did I miss something? Is this a bad idea for some reason? |
July 17, 2015 Re: Infinite range of nullable elements | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roland Hadinger | On Friday, 17 July 2015 at 07:42:09 UTC, Roland Hadinger wrote:
> At this moment I'm tempted to implement a function taking a range of elements E and returning an infinite range of Nullable!E.
>
> [...]
Wouldn't it still require the algorithms to check if an element isNull()? Calling get() on a null element will assert().
I'm wondering why it asserts instead of throwing.
|
July 17, 2015 Re: Infinite range of nullable elements | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roland Hadinger | On Friday, 17 July 2015 at 07:42:09 UTC, Roland Hadinger wrote:
> Here's how I would implement the basic behaviour (could be extended to also forward bidirectional and random access functions):
>
> ---
> auto cushion(R)(R r)
> if (isInputRange!R)
> {
> static if (isInfinite!R) { return r; } else {
>
> struct _Cushion(R)
> {
> R r;
>
> alias E = ElementType!R;
> alias NE = Nullable!E;
>
> @property bool empty() { return false; }
>
> @property NE front()
> {
> return !r.empty ? NE(r.front) : NE();
> }
>
> void popFront()
> {
> if (!r.empty) r.popFront();
> }
> }
>
> return _Cushion!R(r);
> }
> }
>
> ---
>
> I didn't find anything like this Phobos. Did I miss something?
The building blocks are there. You're `map`ping the original range to `Nullable`, and then you're `chain`ing an infinite range (`cycle`) of nulls behind.
----
import std.range: isInputRange;
auto cushion(R)(R r)
if (isInputRange!R)
{
import std.algorithm: map;
import std.range: chain, cycle, ElementType, only;
import std.typecons: Nullable;
alias E = ElementType!R;
alias NE = Nullable!E;
return chain(r.map!NE, NE().only.cycle);
}
----
|
July 17, 2015 Re: Infinite range of nullable elements | ||||
---|---|---|---|---|
| ||||
Posted in reply to Márcio Martins | On Friday, 17 July 2015 at 10:19:22 UTC, Márcio Martins wrote:
> On Friday, 17 July 2015 at 07:42:09 UTC, Roland Hadinger wrote:
>> At this moment I'm tempted to implement a function taking a range of elements E and returning an infinite range of Nullable!E.
>>
>> [...]
>
> Wouldn't it still require the algorithms to check if an element isNull()?
Naturally. But this check can be done further down the function chain,
so all the functions before will see an infinite range.
I'm currently writing a lexer (big loop with two levels of switch statements inside) that needs to some looking ahead in multiple states. Normally, each of those lookaheads would require a check for "end of input". I want to avoid this because of the large number of states.
|
July 17, 2015 Re: Infinite range of nullable elements | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On Friday, 17 July 2015 at 12:44:57 UTC, anonymous wrote:
> The building blocks are there. You're `map`ping the original range to `Nullable`, and then you're `chain`ing an infinite range (`cycle`) of nulls behind.
>
> ----
> import std.range: isInputRange;
>
> auto cushion(R)(R r)
> if (isInputRange!R)
> {
> import std.algorithm: map;
> import std.range: chain, cycle, ElementType, only;
> import std.typecons: Nullable;
>
> alias E = ElementType!R;
> alias NE = Nullable!E;
>
> return chain(r.map!NE, NE().only.cycle);
> }
> ----
Nice! I didn't think of using 'chain'.
|
Copyright © 1999-2021 by the D Language Foundation