-
Notifications
You must be signed in to change notification settings - Fork 557
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
Fix null convertion in Num::fromString
(#1131)
#1132
base: main
Are you sure you want to change the base?
Conversation
When `strtod` returns `0.0`, no conversion could have happened. Handle the error case correctly.
If there's no conversion then However, your actual patch does handle that correctly. Personally, I'd like to have seen |
The statement "C itself which saves you having to trim off extraneous characters after the numerical part" is misleading. The libc API offers incremental parsing. As such it is up to the user to decide/handle error cases, such as extraneous characters. Being lax about extra characters is the lazy route. But I think I prefer the stricter route for parsing. It is more easier to compose (to parse more diverse inputs) and propagate errors. Relying on these incremental parsing API based on expected usages, always backfire when you have to fight against these expected usages. |
I suppose that #984 could provide this functionality. Though I'd argue that this behavior should be a separate function or using extra, optional parameters on I think if there is interest on this topic, we could open a new discussion. |
Well it's worth noting that However, the general vibe of the method seems to be to parse anything that looks in its entirety like a number and return In most cases that arise in practice you know (or think you know) that the numeric part will either be followed by a space + a word or by a fixed-length non-numeric suffix so it's easy to trim these off using Hadn't considered it but, yes, we could provide the above functionality via an extra parameter to I don't mind having a separate discussion about it though I suspect @mhermier might not be too keen as he's against the idea on principle. Perhaps it's best to leave it for now until we see what's going to happen about binary/octal literals and digit separators being added to the language which would, of course, necessitate #984 or something like it being seriously entertained. |
@PureFox48 I'm not against it, but if an API is complex and user can fall into a pit of partial success by being lazy, they will do. The problem with |
Well, if this were done as an extra parameter, then the user would have to explicitly set it. We'd therefore have: var a = Num.fromString("16rcafebabe") //> null
var b = Num.fromString("16rcafebabe", true) //> 16 So I don't really accept that this would be an easy pit into which a lazy user could unwittingly fall. However, I do accept that as we don't know what the future may hold we should stick to the status quo for now as far as the core library is concerned (folks like me can always roll their own) though I'd be very surprised indeed if Smalltalk-type integer literals were ever to be introduced into Wren! |
Anyway, I think the way it is fixed here is acceptable. |
Yes, so do I and the quicker it's merged the better. |
OK, this is what I've come up with for my 'str' module: class Str {
// ... (existing stuff)
// After trimming whitespace from the string 's', takes as many characters as possible
// to form a valid number and converts it thereto using the Num.fromString method.
// Returns null if such a conversion is impossible.
static toNum(s) {
if (s is Num) return s
if (!(s is String)) s = "%(s)"
s = s.trim()
var n = Num.fromString(s)
if (n) return n
if (s.count < 2) return null
var chars = s.toList
for (i in chars.count-1..1) {
chars.removeAt(i)
if (n = Num.fromString(chars.join())) return n
}
return null
}
}
var strs = ["", "?", "7Z", "3 dog night", "123.45 dollars", "$123.45", "-infiniteCalm", "nansAreGoodToEat", "0x1gen"]
for (s in strs) System.print("\"%(s)\" -> %(Str.toNum(s))")
/* output:
"" -> null
"?" -> null
"7Z" -> 7
"3 dog night" -> 3
"123.45 dollars" -> 123.45
"$123.45" -> null
"-infiniteCalm" -> -infinity
"nansAreGoodToEat" -> nan
"0x1gen" -> 1
*/ This isn't very efficient as I'm just removing characters from the end of the string until I find something that However, it's a heck of a lot less code than trying to parse the string from the front and deal with all the possibilities that can arise. As the strings would not usually be very long, it should be quick enough in practice. However, if anyone has any suggestions for improvement, I'd be glad to hear them :) |
When
strtod
returns0.0
, no conversion could have happened. Handle the error case correctly.