All of the functionality you mention can be had now, it’s just that it
wouldn’t be as fast. So most of the points are moot. Only 5 & 6
remain. Also, 7 isn’t exactly true, since it would require a extra
compare operation in the back-end to see if a default was given and
return that, or else return 0. But that is probably negligible.
Wow, thanks for doing the numbers Jordan.
I know it can be done now, but such basic functionality is best done
fast and right ie. in C. There would be zillions of examples of tight
loops in frameworks, libraries and peoples applications out there that
does string to number conversions, eg. a SQL results to a Fixnum.
Some have said that performance is less of an issue in the exceptional
case, but just how exceptional bad input is depends on the application,
and shouldn’t cause a 20x time difference. eg if 1 in 20 input values
are bad, the conversion takes twice as long.
<very useful numbers deleted, see previous post>
If I may make three counter-points against your suggestion:
1.) It is wierd and completely unintuitive for to_i to return anything
other than integer! Maybe it’s just me, but that would be like
calling to_a and getting back a String. Holy return types Batman, what
gives?
I get this, but it would only do so because “you asked for it”. This
kind of thing isn’t uncommon in Ruby though.
2.) Would a non-zero default really be used enough (or in cases where
the speed of using something like the code I listed above with regexps
is not fast enougg) to warrant inclusion? Do you have any real world
examples that are not just corner-cases?
If I was implementing Ruby I would lean towards nil as the default (0
would come a close second best in my mind). It would allow the ‘or’
operators to be used for any defaults eg. (aString.to_i || 0) would
achieve a default of 0.
The most common example that comes to mind is when reading in
configuration where you are reading a value from a string source eg. xml
and if a value isn’t provided you return a sensible default which isn’t
normally 0.
3.) (Like Ara said…) If you’re worried about the performance of
exceptions, how helpful is it to do something like: “10a”.to_i(nil) %
2? That’s either going to terminate with a NoMethodError, or you’ll
have to rescue it (eating just as much cycles).
In that example, you asked for a nil default, and thats what you got.
matz reminds us that to_i already takes a base argument. I guess the
default value would have to be the second default argument - not so
pretty.
Robert suggests a block handler. I don’t know what the performance
implications are of blocks, but I guess it would work, and obviously
allow more advanced handling. Most of the time however I would just
return a value, not do any logic.
Because of the existing base argument on to_i, and the need to keep such
basic methods simple and fast, and the 7 points I listed previously, I
propose the following :
as_i(default=nil) and as_f(default=nil) methods added to Fixnum, Float,
String
For Float.as_i, NaN, Infinity etc would return the default.
If I’m outnumbered on the default argument, then as_i and as_f could
simply be equivalent to to_i and to_f, just with a nil default. I would
then use (aString.as_i || DEFAULT_VALUE).
If enough people would use an optional block and its not a significant
performance drag, that could be added too.
Thanks again Jordan for the numbers,
magpie.