@@ -3401,6 +3401,102 @@ if (is (typeof(nullValue) == T))
3401
3401
assert (ntts.to! string () == " 2.5" );
3402
3402
}
3403
3403
3404
+ /**
3405
+ Unpacks the content of a $(D Nullable), performs an operation and packs it again. Does nothing if isNull.
3406
+
3407
+ When called on a $(D Nullable), $(D apply) will unpack the value contained in the $(D Nullable),
3408
+ pass it to the function you provide and wrap the result in another $(D Nullable) (if necessary).
3409
+ If the Nullable is null, $(D apply) will return null itself.
3410
+
3411
+ Params:
3412
+ t = a $(D Nullable)
3413
+ fun = a function operating on the content of the nullable
3414
+
3415
+ Returns:
3416
+ `fun(t.get).nullable` if `!t.isNull`, else `Nullable.init`.
3417
+
3418
+ See also:
3419
+ $(HTTP en.wikipedia.org/wiki/Monad_(functional_programming)#The_Maybe_monad, The `Maybe` monad)
3420
+ */
3421
+ template apply (alias fun)
3422
+ {
3423
+ import std.functional : unaryFun;
3424
+
3425
+ auto apply (T)(T t)
3426
+ if (isInstanceOf! (Nullable, T) && is (typeof (unaryFun! fun(T.init.get ))))
3427
+ {
3428
+ alias FunType = typeof (unaryFun! fun(T.init.get ));
3429
+
3430
+ enum MustWrapReturn = ! isInstanceOf! (Nullable, FunType);
3431
+
3432
+ static if (MustWrapReturn)
3433
+ {
3434
+ alias ReturnType = Nullable! FunType;
3435
+ }
3436
+ else
3437
+ {
3438
+ alias ReturnType = FunType;
3439
+ }
3440
+
3441
+ if (! t.isNull)
3442
+ {
3443
+ static if (MustWrapReturn)
3444
+ {
3445
+ return fun (t.get ).nullable;
3446
+ }
3447
+ else
3448
+ {
3449
+ return fun (t.get );
3450
+ }
3451
+ }
3452
+ else
3453
+ {
3454
+ return ReturnType.init;
3455
+ }
3456
+ }
3457
+ }
3458
+
3459
+ // /
3460
+ nothrow pure @nogc @safe unittest
3461
+ {
3462
+ alias toFloat = i => cast (float ) i;
3463
+
3464
+ Nullable! int sample;
3465
+
3466
+ // apply(null) results in a null $(D Nullable) of the function's return type.
3467
+ Nullable! float f = sample.apply! toFloat;
3468
+ assert (sample.isNull && f.isNull);
3469
+
3470
+ sample = 3 ;
3471
+
3472
+ // apply(non-null) calls the function and wraps the result in a $(D Nullable).
3473
+ f = sample.apply! toFloat;
3474
+ assert (! sample.isNull && ! f.isNull);
3475
+ assert (f.get == 3.0f );
3476
+ }
3477
+
3478
+ // /
3479
+ nothrow pure @nogc @safe unittest
3480
+ {
3481
+ alias greaterThree = i => (i > 3 ) ? i.nullable : Nullable! (typeof (i)).init;
3482
+
3483
+ Nullable! int sample;
3484
+
3485
+ // when the function already returns a $(D Nullable), that $(D Nullable) is not wrapped.
3486
+ auto result = sample.apply! greaterThree;
3487
+ assert (sample.isNull && result.isNull);
3488
+
3489
+ // The function may decide to return a null $(D Nullable).
3490
+ sample = 3 ;
3491
+ result = sample.apply! greaterThree;
3492
+ assert (! sample.isNull && result.isNull);
3493
+
3494
+ // Or it may return a value already wrapped in a $(D Nullable).
3495
+ sample = 4 ;
3496
+ result = sample.apply! greaterThree;
3497
+ assert (! sample.isNull && ! result.isNull);
3498
+ assert (result.get == 4 );
3499
+ }
3404
3500
3405
3501
/**
3406
3502
Just like $(D Nullable!T), except that the object refers to a value
0 commit comments