## digitalmars.D.learn - Infinite range of nullable elements

• Roland Hadinger (38/38) Jul 17 2015 At this moment I'm tempted to implement a function taking a range
• =?UTF-8?B?Ik3DoXJjaW8=?= Martins" (4/8) Jul 17 2015 Wouldn't it still require the algorithms to check if an element
• Roland Hadinger (9/17) Jul 17 2015 Naturally. But this check can be done further down the function
• anonymous (17/45) Jul 17 2015 The building blocks are there. You're `map`ping the original
```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

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?
```
Jul 17 2015
=?UTF-8?B?Ik3DoXJjaW8=?= Martins" <marcioapm gmail.com> writes:
```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.
```
Jul 17 2015
```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.
```
Jul 17 2015
"anonymous" <anonymous example.com> writes:
```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);
}
----
```
Jul 17 2015
```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'.
```
Jul 17 2015