Bug 18374 – Add range functions to Nullable

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P1
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2018-02-05T10:33:12Z
Last change time
2022-03-27T20:48:54Z
Assigned to
No Owner
Creator
Piotr Mitana

Comments

Comment #0 by piotr.mitana — 2018-02-05T10:33:12Z
I suggest to add the range functions to the Nullable, so that it can be treated as either empty or one element long range. Treating Nullable as a range will by very handy in my opinion - it could be mapped, filtered, joined and processed with all the other algorithms without checking the presence explicitely. Let's say that I am regularly receiving from somewhere (for example via user input or network) structures with optional data stored in Nullable. I want to process the optional data in some way if they are present. Similar solution is present in Scala, where functions such as map, filter etc. can be applied to options in the same way as to lists. Structure and range: -------------------------------------------------- struct Data { string requiredData; Nullable!string optionalData; } InputRange!Data toProcess; void process(string optionalData) { /*...*/ } /* Current solution: */ toProcess.map!(x => x.optionalData) .filter!(x => x.isNull) .each!process; /* Nullable as a range solution: */ toProcess.each!(x => x.optionalData.each!process); -------------------------------------------------- In fact every time I do "if(nullable.isNull) nullable.get.whatever()", i could do "nullable.each!whatever" or similar. I think there are more significant gains possible, but I thought only of this simple example now. It could be discussed, but I believe that Nullable could be both a bidirectional and random access range. What could range methods do: front/back: Asserts not nullified and calls get() (the same as other ranges throw AssertError if front(0 is called on empty range). popFront/popBack: Removing the front element and moving to the next one actually is equal to nullifying in this case. empty: Aliased do isNull. save: Defined only if the underlying type is copiable. Returns the new nullable with a copy of underlying element or empty nullable if this one was null. length: Return 0 or 1 depending on if the range is null. opIndex: Throws if isNull or index > 0. Otherwise returns an underlying element.
Comment #1 by greensunny12 — 2018-06-24T15:01:53Z
Are you aware of the new `apply`? https://dlang.org/changelog/2.080.0.html#std-typecons-nullable-apply It still would be great to have Nullable and ranges working nicely together, but at least apply is a start.
Comment #2 by piotr.mitana — 2018-06-25T09:27:06Z
(In reply to Seb from comment #1) > Are you aware of the new `apply`? > > https://dlang.org/changelog/2.080.0.html#std-typecons-nullable-apply > > It still would be great to have Nullable and ranges working nicely together, > but at least apply is a start. I am, but it wasn't there the day I have created this issue. apply() definitely does the trick. It still lacks one case though - when we want to call the void function unless the value is null: --------------- Nullable!int something; something.apply!writeln; --------------- I still think that Nullable as a range might be more powerful and its integration with the range behavior might be save some LoC in some places, but I cannot come up of an example now.
Comment #3 by elpenguino+D — 2022-03-27T20:48:54Z