www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Default-valued nothrow nogc std.conv:to

reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
Have anyone tried to implement a variant of `std.conv.to` that 
can be `nothrow  nogc` if the exception handling is replaced by 
an extra second parameter (`defaultValue`) returned iff the call 
to `to` throws?

I currently have a solution

https://github.com/nordlow/phobos-next/blob/b7a5c589d890f6b7bef7c5f2588fa93d90d19d62/src/conv_ex.d#L10

that is `nothrow` but not (yet) ` nogc`:


CommonType!(T, U) toWithDefault(T, U, S)(S value, U defaultValue)
     if (haveCommonType!(T, U))
{
     try
     {
         import std.conv : to;
         return value.to!T;
     }
     catch (Exception e) // assume ConvException. TODO can we 
capture ConvException instead make it inferred nothrow
     {
         return defaultValue;
     }
}

Is there any way I can make it ` nogc` without having to modify 
the code in `std.conv`?

Further, can anybody think of a more consice naming than 
`toWithDefault`?
Apr 22
next sibling parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Saturday, 22 April 2017 at 12:14:26 UTC, Nordlöw wrote:
 Is there any way I can make it ` nogc` without having to modify 
 the code in `std.conv`?
If I get this to work, I'm gonna try pushing it into std.conv.
Apr 22
next sibling parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Saturday, 22 April 2017 at 12:16:19 UTC, Nordlöw wrote:
 On Saturday, 22 April 2017 at 12:14:26 UTC, Nordlöw wrote:
 Is there any way I can make it ` nogc` without having to 
 modify the code in `std.conv`?
If I get this to work, I'm gonna try pushing it into std.conv.
If defaultValue is not lazy, it's potentially wasteful. But at the moment, lazy are never inferred as nothrow: https://issues.dlang.org/show_bug.cgi?id=12647
Apr 22
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Saturday, 22 April 2017 at 15:36:56 UTC, Stanislav Blinov 
wrote:
 On Saturday, 22 April 2017 at 12:16:19 UTC, Nordlöw wrote:
 On Saturday, 22 April 2017 at 12:14:26 UTC, Nordlöw wrote:
 Is there any way I can make it ` nogc` without having to 
 modify the code in `std.conv`?
If I get this to work, I'm gonna try pushing it into std.conv.
If defaultValue is not lazy, it's potentially wasteful.
What do you mean with "potentially wasteful"? Excess calls to copy constructors?
Apr 22
parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Saturday, 22 April 2017 at 16:41:00 UTC, Nordlöw wrote:

 If defaultValue is not lazy, it's potentially wasteful.
What do you mean with "potentially wasteful"? Excess calls to copy constructors?
Evaluation of an expression the result of which might not be used. defaultValue could be anything: a literal, an lvalue, a result of a function call...
Apr 22
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 4/22/17 6:57 PM, Stanislav Blinov wrote:
 On Saturday, 22 April 2017 at 16:41:00 UTC, Nordlöw wrote:

 If defaultValue is not lazy, it's potentially wasteful.
What do you mean with "potentially wasteful"? Excess calls to copy constructors?
Evaluation of an expression the result of which might not be used. defaultValue could be anything: a literal, an lvalue, a result of a function call...
IMO you are overenginering this. defaultValue will most likely be something distinct such as compile-time constant. --- Dmitry Olshansky
Apr 22
parent Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Saturday, 22 April 2017 at 18:26:56 UTC, Dmitry Olshansky 
wrote:
 On 4/22/17 6:57 PM, Stanislav Blinov wrote:
 On Saturday, 22 April 2017 at 16:41:00 UTC, Nordlöw wrote:

 If defaultValue is not lazy, it's potentially wasteful.
What do you mean with "potentially wasteful"? Excess calls to copy constructors?
Evaluation of an expression the result of which might not be used. defaultValue could be anything: a literal, an lvalue, a result of a function call...
IMO you are overenginering this. defaultValue will most likely be something distinct such as compile-time constant.
I'm looking at it from the perspective of it being added to Phobos, which seems to be Nordlöw's intent. There should not be any assumptions in that scenario, or there should be an overload for the "most likely" case. The signature says: defaultValue will be anything convertible to typeof(defaultValue), and is going to be evaluated regardless of whether or not std.conv.to() call throws. All I'm saying is the purpose *suggests* that the defaultValue parameter should be lazy, and that that currently annotating it so defeats that purpose is due to a bug. Although one could work around the bug for the time being by using std.exception.assumeWontThrow.
Apr 22
prev sibling parent Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Saturday, 22 April 2017 at 12:16:19 UTC, Nordlöw wrote:
 On Saturday, 22 April 2017 at 12:14:26 UTC, Nordlöw wrote:
 If I get this to work, I'm gonna try pushing it into std.conv.
Another bit to pick on is the return value. auto x = toWithDefault!int("1", 0.0f); typeof(x) will be float even though the caller requested a conversion to int. Probably should be T toWithDefault(T,S,U)(S v, /*lazy*/ U defaultValue) if (is(typeof(() { T r = defaultValue; }))) { //... }
Apr 22
prev sibling next sibling parent =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Saturday, 22 April 2017 at 12:14:26 UTC, Nordlöw wrote:
     if (haveCommonType!(T, U))
Defined as: /// Is `true` iff `Types` all share a common type. enum bool haveCommonType(Types...) = !is(CommonType!Types == void); import std.traits : CommonType;
Apr 22
prev sibling parent crimaniak <crimaniak gmail.com> writes:
On Saturday, 22 April 2017 at 12:14:26 UTC, Nordlöw wrote:
 Have anyone tried to implement a variant of `std.conv.to` that 
 can be `nothrow  nogc` if the exception handling is replaced by 
 an extra second parameter (`defaultValue`) returned iff the 
 call to `to` throws?
There is common ifThrown template in Phobos: https://dlang.org/phobos/std_exception.html#ifThrown I think it's better to add nothrow ifThrown implementation if needed. As for me, for such cases, where input data can be not relevant, is better to use Nullable type to indicate the error. In this case, an input value equal to the default value does not cause problems. Something like this: import std.typecons: Nullable; Nullable!T nullableTo(T, S)(S source) { import std.conv : to; try return Nullable!T(source.to!T); catch(Exception e) return Nullable!T(); } T orElse(T)(Nullable!T n, T value){ return n.isNull() ? value : n.get; } unittest { assert(! "0".nullableTo!int.isNull); assert("0.0".nullableTo!int.isNull); assert("123.45".nullableTo!int.isNull); assert("123".nullableTo!int.get == 123); // And easy convertable to default value variant assert("123.45".nullableTo!int.orElse(5) == 5); }
Apr 23