[Issue 9086] New: std.typecons.appendIfNotNull() or a better idea

d-bugmail at puremagic.com d-bugmail at puremagic.com
Tue Nov 27 18:21:33 PST 2012


http://d.puremagic.com/issues/show_bug.cgi?id=9086

           Summary: std.typecons.appendIfNotNull() or a better idea
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Phobos
        AssignedTo: nobody at puremagic.com
        ReportedBy: bearophile_hugs at eml.cc


--- Comment #0 from bearophile_hugs at eml.cc 2012-11-27 18:21:31 PST ---
A problem with std.typecons.Nullable is that the D type system is not powerful
enough to see this is correct code:


import std.typecons;
void main() nothrow {
    alias Nothing = Nullable!int;
    Nothing[] items;
    foreach (i; 0 .. 10)
        items ~= (i % 2) ? Nothing(i) : Nothing();

    int[] result;
    foreach (x; items)
        if (!x.isNull)
            result ~= x.get; // Error: x.get is not nothrow
}


Another problem is that "x.get" verifies the enforcement even in the "then"
clause, this is wasted computation, because x was tested already.


One common enough use case for Nullable is to create arrays of Nullables and
then filter out the null values.

Currently code like this can't be nothrow:

items.filter!(x => !x.isNull)().map!(x => x.get)()



So I have created a little function named appendIfNotNull() that is nothrow:

import std.typecons;

void appendIfNotNull(T)(ref T[] items, Nullable!T x) pure nothrow {
    try {
        if (!x.isNull)
            items ~= x.get;
    } catch (Exception e) // enforce() exception.
        assert(0);
}

// Demo code --------------------------
import std.stdio, std.algorithm;

alias Nothing = Nullable!int;

Nothing[] foo(int n) nothrow {
    typeof(return) result;
    foreach (i; n .. n + 6)
        result ~= (i % 2) ? Nothing(i) : Nothing();
    return result;
}

int[] bar() nothrow {
    typeof(return) numbers;
    foreach (i; 0 .. 3)
        foreach (x; foo(i * 10))
            numbers.appendIfNotNull(x);
    return numbers;
}

void main() {
    writeln(bar());
    foo(1).filter!(x => !x.isNull)().map!(x => x.get)().writeln();
}


appendIfNotNull() is nothrow, but it wastes efficiency. So here is a simpler
and more efficient implementation for the std.typecons module (because _isNull
and _value fields are private):


void appendIfNotNull(T)(ref T[] items, Nullable!T x) nothrow {
    if (!x._isNull)
        items ~= x._value;
}


Improvements for appendIfNotNull:
- items instead of a T[] should be a range that supports appending.
- x should be allowed to be one of both types of Nullables.


appendIfNotNull() is not a very generic function, something better can be
invented, usable in more cases. More general ideas are welcome.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list