Martin said:

irb(main):005:0> ("aa".."b1").to_a

["aa".."zz" elided]

Then said:

Exactly.

And the same holds true of many a sequence, like even numbers. Now how can membership be optimized in a custom manner?

Maybe I'm about to say something silly (by not being up-to speed) but

why on earth could anyone consider the output from the above one-liner

to be sane? Not only is upper bound exceeded (under any sensible notion

of comparison) but many intermediate values are missing for example "b!"

and "a~" as well as more esoteric strings with control characters such

as "b\0" and all strings with capital letters in them?

To make matters worse, even if we accept that ranges have a peculiar

semantics over strings, they are inconsistent.

irb(main):001:0> ("aa".."b1")==="zz"

=> false

irb(main):002:0> ("aa".."b1").to_a.include? "zz"

=> true

The max method also behaves in a very counter intuitive way without

converting to an array:

irb(main):003:0> ("A".."d").max

=> "Z"

Establishing set membership is something for which (in other languages)

I've long had an active interest - which brings me to comment on the

even numbers question. A really powerful resolution of range would

support "modifiers":

Projection- Applying a function to each element

Selection- Filtering values which do not exist

Intersection- Retaining only values present in both

Union - Retaining values present in either

Minus - Retaining values present in the first but not the second.

It is interesting to note that it is possible to efficiently compute

membership (without enumerating all the possible values) unless

Projection is applied. If projection is applied then it is necessary

that the projection function can be inverted - which can't be done in

the general case. So, given an appropriate implementation of efficient

- the following generate the odd numbers below n.

efficient(0..n).filter { |x| x%2==0 }

efficient(0..(n/2)).project { |x| x=x*2 }

efficient(0..n).minus efficient(0..n).filter { |x| x%2==1 }

... and many, many more possibilities...

For each of these (except project, assuming no-one supplies the

hand-verified inverse to the supplied function) there are efficient

[i.e. far better than O(n)] ways to establish membership.

Does anyone not claim that ranges are broken with respect to strings?