From: James Coglan Date: 2009-08-06T01:44:56+09:00 Subject: Re: Bizarre Range behavior --0016e68dbd97edbd0e047067b840 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit 2009/8/5 Rick DeNatale > On Wed, Aug 5, 2009 at 12:21 PM, Yukihiro Matsumoto > wrote: > > Hi, > > > > In message "Re: Bizarre Range behavior" > > on Wed, 5 Aug 2009 23:29:08 +0900, "David A. Black" < > dblack@rubypal.com> writes: > > > > |If you make this change, how would you then accomplish the old > > |version? In other words, if you wanted: > > | > > | "2".."19" > > | > > |to obey ASCII/character code logic, would there still be a way? > > > > The point is the current behavior is not really obeying > > ASCII/character code logic. It's a half-cooked magic (comparison done > > by dictionary order, but increment done by numerical order), so if we > > can come up with the better logic, we can override, I think. The > > current logic is too weird so that I believe none uses it in the real > > code. > > > > Since no one is using this logic, it doesn't matter if we change it, > > or keep it if compatibility matters most. I prefer moving forward. > > Well my vote is to cook it to use the methods of the endpoints rather > than doing something special IF the endpoints are strings and both > happen to be numerical. That seems as half cooked to me as the > current situation. > > And if you follow the "if they're numerical" path what do you do about > things like > > ("0x32".."0xFE").to_a > ("032".."0100").to_a > ("032".."0x32").to_a > > I say let strings be strings and numbers be numbers! Quite. I think consistency is important, and this is currently broken in 1.9: $ irb1.8 >> ('!'..']').to_a => ["!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] >> '9'.succ => "10" $ irb1.9 >> ('!'..']').to_a => ["!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]"] >> '9'.succ => "10" In 1.8, String#succ is consistently used for iteration; when '9'.succ yields '10', it spots that the endpoint is no longer reachable and ends the iteration. 1.9 seems to embody more special cases, as '9' is followed by ':' in the above range even though '9'.succ is still '10'. I think treating the alphanumerics as special is useful, e.g. I like that '9'.succ is '10' and 'z'.succ is 'aa' rather than using dumb charcode-based sequencing, but it is only useful if it is applied consistently and predictably. There is obviously room for debate over the above examples: the 1.9 one could be viewed as more complete even though it doesn't apply #succ consistently. A lot of these odd examples are edge cases that are unlikely to come up in production code, but personally I find the rules used by 1.8 easier to understand. If I define my own class, Range will use its #succ and #<=> methods to carry out its logic and I expect the same for built-in classes. -- James Coglan http://jcoglan.com --0016e68dbd97edbd0e047067b840--