@@ -725,7 +725,6 @@ deprecated
725
725
assertThrown(enf(false , " blah" ));
726
726
}
727
727
728
-
729
728
/+ +
730
729
Catches and returns the exception thrown from the given expression.
731
730
If no exception is thrown, then null is returned and $(D result) is
@@ -796,10 +795,11 @@ T collectException(T : Throwable = Exception, E)(lazy E expression)
796
795
return null ;
797
796
}
798
797
798
+ // /
799
799
@safe unittest
800
800
{
801
801
int foo () { throw new Exception (" blah" ); }
802
- assert (collectException(foo()));
802
+ assert (collectException(foo()).msg == " blah " );
803
803
}
804
804
805
805
/+ +
@@ -975,19 +975,24 @@ immutable(T[U]) assumeUnique(T, U)(ref T[U] array) pure nothrow
975
975
return result;
976
976
}
977
977
978
+ // /
978
979
@system unittest
979
980
{
980
- // @system due to assumeUnique
981
981
int [] arr = new int [1 ];
982
- auto arr1 = assumeUnique(arr);
983
- assert (is (typeof (arr1) == immutable (int )[]) && arr == null );
982
+ auto arr1 = arr.assumeUnique;
983
+ static assert (is (typeof (arr1) == immutable (int )[]));
984
+ assert (arr == null );
985
+ assert (arr1 == [0 ]);
984
986
}
985
987
988
+ // /
986
989
@system unittest
987
990
{
988
991
int [string ] arr = [" a" :1 ];
989
- auto arr1 = assumeUnique(arr);
990
- assert (is (typeof (arr1) == immutable (int [string ])) && arr == null );
992
+ auto arr1 = arr.assumeUnique;
993
+ static assert (is (typeof (arr1) == immutable (int [string ])));
994
+ assert (arr == null );
995
+ assert (arr1.keys == [" a" ]);
991
996
}
992
997
993
998
/**
@@ -1582,25 +1587,28 @@ class ErrnoException : Exception
1582
1587
_errno = errno;
1583
1588
super (msg ~ " (" ~ errnoString(errno) ~ " )" , file, line);
1584
1589
}
1590
+ }
1585
1591
1586
- @system unittest
1587
- {
1588
- import core.stdc.errno : errno, EAGAIN ;
1592
+ // /
1593
+ @system unittest
1594
+ {
1595
+ import core.stdc.errno : EAGAIN ;
1596
+ auto ex = new ErrnoException(" oh no" , EAGAIN );
1597
+ assert (ex.errno == EAGAIN );
1598
+ }
1589
1599
1590
- auto old = errno;
1591
- scope (exit) errno = old;
1600
+ // / errno is used by default if no explicit error code is provided
1601
+ @system unittest
1602
+ {
1603
+ import core.stdc.errno : errno, EAGAIN ;
1592
1604
1593
- errno = EAGAIN ;
1594
- auto ex = new ErrnoException(" oh no" );
1595
- assert (ex.errno == EAGAIN );
1596
- }
1605
+ auto old = errno;
1606
+ scope (exit) errno = old;
1597
1607
1598
- @system unittest
1599
- {
1600
- import core.stdc.errno : EAGAIN ;
1601
- auto ex = new ErrnoException(" oh no" , EAGAIN );
1602
- assert (ex.errno == EAGAIN );
1603
- }
1608
+ // fake that errno got set by the callee
1609
+ errno = EAGAIN ;
1610
+ auto ex = new ErrnoException(" oh no" );
1611
+ assert (ex.errno == EAGAIN );
1604
1612
}
1605
1613
1606
1614
/+ +
@@ -1619,63 +1627,7 @@ class ErrnoException : Exception
1619
1627
Returns:
1620
1628
expression, if it does not throw. Otherwise, returns the result of
1621
1629
errorHandler.
1622
-
1623
- Example:
1624
- $(RUNNABLE_EXAMPLE
1625
- --------------------
1626
- //Revert to a default value upon an error:
1627
- assert("x".to!int().ifThrown(0) == 0);
1628
- --------------------
1629
- )
1630
-
1631
- You can also chain multiple calls to ifThrown, each capturing errors from the
1632
- entire preceding expression.
1633
-
1634
- Example:
1635
- $(RUNNABLE_EXAMPLE
1636
- --------------------
1637
- //Chaining multiple calls to ifThrown to attempt multiple things in a row:
1638
- string s="true";
1639
- assert(s.to!int().
1640
- ifThrown(cast(int) s.to!double()).
1641
- ifThrown(cast(int) s.to!bool())
1642
- == 1);
1643
-
1644
- //Respond differently to different types of errors
1645
- assert(enforce("x".to!int() < 1).to!string()
1646
- .ifThrown!ConvException("not a number")
1647
- .ifThrown!Exception("number too small")
1648
- == "not a number");
1649
- --------------------
1650
- )
1651
-
1652
- The expression and the errorHandler must have a common type they can both
1653
- be implicitly casted to, and that type will be the type of the compound
1654
- expression.
1655
-
1656
- Example:
1657
- $(RUNNABLE_EXAMPLE
1658
- --------------------
1659
- //null and new Object have a common type(Object).
1660
- static assert(is(typeof(null.ifThrown(new Object())) == Object));
1661
- static assert(is(typeof((new Object()).ifThrown(null)) == Object));
1662
-
1663
- //1 and new Object do not have a common type.
1664
- static assert(!__traits(compiles, 1.ifThrown(new Object())));
1665
- static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1666
- --------------------
1667
- )
1668
-
1669
- If you need to use the actual thrown exception, you can use a delegate.
1670
- Example:
1671
-
1672
- $(RUNNABLE_EXAMPLE
1673
- --------------------
1674
- //Use a lambda to get the thrown object.
1675
- assert("%s".format().ifThrown!Exception(e => e.classinfo.name) == "std.format.FormatException");
1676
- --------------------
1677
- )
1678
- +/
1630
+ +/
1679
1631
// lazy version
1680
1632
CommonType! (T1 , T2 ) ifThrown(E : Throwable = Exception , T1 , T2 )(lazy scope T1 expression, lazy scope T2 errorHandler)
1681
1633
{
@@ -1738,6 +1690,59 @@ CommonType!(T1, T2) ifThrown(T1, T2)(lazy scope T1 expression, scope T2 delegate
1738
1690
}
1739
1691
}
1740
1692
1693
+ // / Revert to a default value upon an error:
1694
+ @safe unittest
1695
+ {
1696
+ import std.conv : to;
1697
+ assert (" x" .to! int .ifThrown(0 ) == 0 );
1698
+ }
1699
+
1700
+ /**
1701
+ Chain multiple calls to ifThrown, each capturing errors from the
1702
+ entire preceding expression.
1703
+ */
1704
+ @safe unittest
1705
+ {
1706
+ import std.conv : ConvException, to;
1707
+ string s = " true" ;
1708
+ assert (s.to! int .ifThrown(cast (int ) s.to! double )
1709
+ .ifThrown(cast (int ) s.to! bool ) == 1 );
1710
+
1711
+ s = " 2.0" ;
1712
+ assert (s.to! int .ifThrown(cast (int ) s.to! double )
1713
+ .ifThrown(cast (int ) s.to! bool ) == 2 );
1714
+
1715
+ // Respond differently to different types of errors
1716
+ alias orFallback = (lazy a) => a.ifThrown! ConvException(" not a number" )
1717
+ .ifThrown! Exception (" number too small" );
1718
+
1719
+ assert (orFallback(enforce(" x" .to! int < 1 ).to! string ) == " not a number" );
1720
+ assert (orFallback(enforce(" 2" .to! int < 1 ).to! string ) == " number too small" );
1721
+ }
1722
+
1723
+ /**
1724
+ The expression and the errorHandler must have a common type they can both
1725
+ be implicitly casted to, and that type will be the type of the compound
1726
+ expression.
1727
+ */
1728
+ @safe unittest
1729
+ {
1730
+ // null and new Object have a common type(Object).
1731
+ static assert (is (typeof (null .ifThrown(new Object ())) == Object ));
1732
+ static assert (is (typeof ((new Object ()).ifThrown(null )) == Object ));
1733
+
1734
+ // 1 and new Object do not have a common type.
1735
+ static assert (! __traits(compiles, 1. ifThrown(new Object ())));
1736
+ static assert (! __traits(compiles, (new Object ()).ifThrown(1 )));
1737
+ }
1738
+
1739
+ // / Use a lambda to get the thrown object.
1740
+ @system unittest
1741
+ {
1742
+ import std.format : format;
1743
+ assert (" %s" .format.ifThrown! Exception (e => e.classinfo.name) == " std.format.FormatException" );
1744
+ }
1745
+
1741
1746
// Verify Examples
1742
1747
@system unittest
1743
1748
{
@@ -1841,6 +1846,40 @@ enum RangePrimitive
1841
1846
pop = popFront | popBack, // / Ditto
1842
1847
}
1843
1848
1849
+ // /
1850
+ pure @safe unittest
1851
+ {
1852
+ import std.algorithm.comparison : equal;
1853
+ import std.algorithm.iteration : map, splitter;
1854
+ import std.conv : to, ConvException;
1855
+
1856
+ auto s = " 12,1337z32,54,2,7,9,1z,6,8" ;
1857
+
1858
+ // The next line composition will throw when iterated
1859
+ // as some elements of the input do not convert to integer
1860
+ auto r = s.splitter(' ,' ).map! (a => to! int (a));
1861
+
1862
+ // Substitute 0 for cases of ConvException
1863
+ auto h = r.handle! (ConvException, RangePrimitive.front, (e, r) => 0 );
1864
+ assert (h.equal([12 , 0 , 54 , 2 , 7 , 9 , 0 , 6 , 8 ]));
1865
+ }
1866
+
1867
+ // /
1868
+ pure @safe unittest
1869
+ {
1870
+ import std.algorithm.comparison : equal;
1871
+ import std.range : retro;
1872
+ import std.utf : UTFException;
1873
+
1874
+ auto str = " hello\xFF world" ; // 0xFF is an invalid UTF-8 code unit
1875
+
1876
+ auto handled = str.handle! (UTFException, RangePrimitive.access,
1877
+ (e, r) => ' ' ); // Replace invalid code points with spaces
1878
+
1879
+ assert (handled.equal(" hello world" )); // `front` is handled,
1880
+ assert (handled.retro.equal(" dlrow olleh" )); // as well as `back`
1881
+ }
1882
+
1844
1883
/* * Handle exceptions thrown from range primitives.
1845
1884
1846
1885
Use the $(LREF RangePrimitive) enum to specify which primitives to _handle.
0 commit comments