import std.stdio, std.string;
void main() {
writeln(isNumeric("3.14")); // true
writeln(isNumeric("3.14"w)); // false
writeln(isNumeric("3.14"d)); // false
}
The problem is that we have isNumeric(...), which takes an argument using runtime variadics and figures out whether it's numeric. The default (if it's not one of the listed types) is to return false. However, the type list has wchar[] and dchar[], not immutable(wchar)[] and immutable(dchar)[]:
else if (_arguments[0] == typeid(wchar[]))
return isNumeric(std.utf.toUTF8(va_arg!(wchar[])(_argptr)));
else if (_arguments[0] == typeid(dchar[]))
return isNumeric(std.utf.toUTF8(va_arg!(dstring)(_argptr)));
This leads to the default return false statement being executed. IMHO the solution is to just deprecate isNumeric(...), since it seems pretty useless anyhow, and template isNumeric(string) and make it:
isNumeric(String)(String s) if(isSomeString!(String))
This would also solve bug 3609.
Comment #1 by andrei — 2011-06-05T16:35:20Z
I find isNumeric quite a silly function. It has definitions for the following cases:
bool isNumeric(cons char[], bool allowSep = false);
bool isNumeric(...);
bool isNumeric(Typeinfo[], argptr);
It was probably meant to help some scripting, although the approach and behavior are rather bizarre (e.g. the second overload ignores everything but the first argument).
I suggest we just remove them all. Thoughts?
Comment #2 by issues.dlang — 2011-06-05T17:14:26Z
Doesn't hurt my feelings any. I've been working on std.string lately, and I was wondering what to do with all of those weird overloads for isNumeric. I honestly don't understand why they're their in the first place - not to mention that std.string is for processing _strings_, and those overloads are doing other weird things. Not to mention, isNumeric is under its own license! Given what it says, I _think_ that we can just remove that license (it claims Public Domain / Contributed to Digital Mars), but I don't know. And honestly, do we actually need isNumeric at all? It's from 2005, so it was clearly written for D1 when we didn't have std.algorithm.
This is actually a perfect use case for an all function.
all!isdigit(str);
Since we don't yet _have_ proper all or any functions (unless they were added, and I didn't notice), we can do
!canFind((dchar a){return !isdigit(a);})(str);
isNumeric isn't really needed at all IMHO. But regardless, I see no reason keep the non-string versions of isNumeric around.
Comment #3 by issues.dlang — 2011-06-05T17:31:26Z
Actually, thinking about it a bit more, given the issues of possible negative sign and possible decimal point, perhaps keeping a version of isNumeric around is a good idea (since checking each character with isdigit doesn't cut it in that case), but I still think that the non-string versions of isNumeric should go.
Comment #4 by andrei — 2011-06-05T17:35:27Z
The main issue I'm having with isNumeric is that it's almost as much work as actually parsing the thing. So why not just parse it as a double and see if it sticks? Most of the time, if it's numeric, you also would want to know the value.
Comment #5 by issues.dlang — 2011-06-05T17:50:20Z
Well, in order to properly determine whether a string is fully numeric and convertible to an int or float or whatever, I believe that you _do_ have to parse the whole thing. I don't see how you can really get around that except when shortcutting if you find a character which makes the string fail for isNumeric.
to throws if you can't convert the whole string, and parse throws if you can't convert any of it. So, checking for convertibility by doing the conversion would be a _bad_ idea, because handling exceptions is extremely expensive. And so, there should definitely be a way to check for convertibility prior to converting. Phobos provides the tools to do that, but given the extra complication of - and ., it seems like it would just force people to keep reinventing the wheel if we didn't have a function like isNumeric which said whether a string was numeric. And technically, with that in mind, there would be benefit in having isInt, isFloat, etc. in addition to isNumeric.
So, I don't think that the fact that the string needs to be fully parsed is an issue. It's a given and can't be gotten around. And in comparison to the cost of an exception being thrown, it's generally going to be a negligible cost. However, what I think that this highlights is that it would be generally useful to know prior to calling parse or to whether parse or to will succeed. And that being the case, maybe we need a more general solution in std.conv where you can call a function to test whether _any_ particular call to parse or to will succeed. And _that_ being the case, std.string.isNumeric should probably go away, but we'd need the new functions in std.conv first.
Comment #6 by lovelydear — 2012-04-21T14:55:45Z
PS E:\DigitalMars\dmd2\samples> rdmd bug.d
bug.d(5): Error: function std.string.isNumeric is deprecated
bug.d(6): Error: function std.string.isNumeric is deprecated
Close with WONTFIX ?
Comment #7 by issues.dlang — 2012-04-21T15:12:25Z
No. I don't think so. The one overload of isNumeric which hasn't been deprecated is the one that takes in char[]. With the deprecated ones removed, it'll be possible to make it work with in wchar[] and in dchar[] without breaking any code. It's the other crazy overloads which have to go and thus are deprecated.
Comment #8 by dlang-bugzilla — 2014-01-04T20:55:27Z
Created attachment 1311
draft patch
The current implementation of isNumeric works just fine with wchar and dchar strings. However, making the function a template causes conflicts with the std.typecons.isNumeric template. An ugly workaround would be declaring a non-templated overload set of wrappers around the templated implementation.
Comment #9 by ben.james.jones — 2019-04-16T17:12:19Z