Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function to check whether std.conv.to will succeed #9914

Open
dlangBugzillaToGithub opened this issue Oct 23, 2011 · 7 comments
Open

Function to check whether std.conv.to will succeed #9914

dlangBugzillaToGithub opened this issue Oct 23, 2011 · 7 comments

Comments

@dlangBugzillaToGithub
Copy link

issues.dlang (@jmdavis) reported this on 2011-10-23T00:17:49Z

Transfered from https://issues.dlang.org/show_bug.cgi?id=6843

CC List

Description

In some cases, std.conv.to will complain at compile time that it can't do a particular conversion, but in others it depends on runtime values. For instance, to!int("hello world") will fail at runtime. Currently, the only way to know if such a conversion will succed is to call std.conv.to and then catch the ConvException when it fails. However, unfortunately, exception handling is _very_ expensive in D (as in an expression which throws an exception is more than 100x slower than one that doesn't), so in cases where there's a good chance that std.conv.to will fail (or when you just want to check whether it will succeed or not) are _very_ expensive.

I would very much like to see a function in std.conv.to which returned whether std.conv.to will succeed or not so that it will be efficient to check whether std.conv.to will succeed or not. And actually, because it's not particularly efficient to call such a function and then call std.conv.to (since that would do the conversion twice - though that's still far more efficient than testing with std.conv.to, since exceptions are so expensive), the function should probably give the converted value as well if it succeeded.

For instance, we could have

bool tryTo(T, S)(S toConvert) {...}
bool tryTo(T, S)(S toConvert, out T result) {...}

The first version checks whether the conversion will succeed (probably doing the full conversion) and returns whether it succeeded or not, whereas the second version does the full conversion and not only returns whether it succeeded or not, but it sets result to the result of the conversion (or T.init upon failure - though out should do that automatically if result is never set within the function).

We should probably have the same for std.conv.parse as well.

bool tryParse(Target, Source)(ref Source s) {...}
bool tryParse(Target, Source)(ref Source s, out Target result) {...}

It's probably not quite as useful for parse (particularly since tryParse would still need to consume s in the first overload to be consistent), but it would make parsing more efficient when parsing failures are common.

Regardless, tryTo would make dealing with std.conv.to _much_ more efficient in cases where conversion failures are common.
@dlangBugzillaToGithub
Copy link
Author

issues.dlang (@jmdavis) commented on 2011-10-23T00:19:29Z

Oh, and std.conv.to and std.conv.parse would probably use tryTo and tryParse respectively internally in order to reduced code duplication, but I suppose that that's up whoever implements them.

@dlangBugzillaToGithub
Copy link
Author

bearophile_hugs commented on 2011-10-23T07:38:45Z

This seems a kind of dupe of bug 6840

@dlangBugzillaToGithub
Copy link
Author

issues.dlang (@jmdavis) commented on 2011-10-23T11:10:36Z

They're similar but not the same. Bug# 6840 is suggesting the creation of a template which wraps whether std.conv.to succeeds by catching the exception. This is highly inefficient and ends up creating a new type in the deal, which is messier IMHO.

What I'm suggesting here is that a new function be created which doesn't risk a ConvException being thrown at all, completely avoiding the huge inefficiency of catching the thrown exception.

And if we were to do something like maybeTo, I'd be tempted to find a way to generalize it beyond std.conv.to to encompass any function which returns a value and could have thrown an exception (probably by taking the function as aliased template argument) rather than making it specific to std.conv.to. But that's so insanely inefficient, that I wouldn't be in hurry to add something like that to Phobos.

@dlangBugzillaToGithub
Copy link
Author

bearophile_hugs commented on 2011-10-23T12:46:46Z

(In reply to comment #3)
> They're similar but not the same. Bug# 6840 is suggesting the creation of a
> template which wraps whether std.conv.to succeeds by catching the exception.
> This is highly inefficient and ends up creating a new type in the deal, which
> is messier IMHO.
> 
> What I'm suggesting here is that a new function be created which doesn't risk a
> ConvException being thrown at all, completely avoiding the huge inefficiency of
> catching the thrown exception.

You have missed this part of that bug 6840:

> 2) This simple implementation of maybeTo contains a try-catch, but there is no
> need to actually throw and catch an exception in all wrong conversion cases.
> Example: when Tin is string and Tout is int, maybeTo is free to use something
> lighter, like a C function that produces no exceptions, instead of to!(). I
> think this allows the compiler to perform some extra optimizations.

If you create a conversion function that doesn't throw, then it is useful to create a maybeTo :-)

@dlangBugzillaToGithub
Copy link
Author

issues.dlang (@jmdavis) commented on 2011-10-23T12:53:16Z

And this enhancement request is for a conversion function which doesn't throw. And once you have such a function, I see no need for maybeTo, but that's a separate argument. Regardless, maybeTo _without_ a separate conversion function which doesn't throw is too inefficient to even consider IMHO.

@dlangBugzillaToGithub
Copy link
Author

issues.dlang (@jmdavis) commented on 2013-09-06T21:54:18Z

Another possibility would be a function which did the same thing as std.conv.to except that it returned success, and the actual result was returned via an out parameter. That's even more similar to maybeTo, but again, a key difference is that there is zero throwing going on whatsoever and std.conv.to would not be benig wrapped, since the key thing we need here IMHO is to avoid throwing for efficiency's sake. This would probably require breaking out many of the toImpl functions so that they use this new function and then throw on failure (in order to avoid code duplication).

Ultimately, issue# 6840 and this one are looking to solve essentially the same problem though.

@dlangBugzillaToGithub
Copy link
Author

andrei (@andralex) commented on 2016-10-15T01:08:29Z

Related: https://issues.dlang.org/show_bug.cgi?id=6840

@LightBender LightBender removed the P4 label Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants