Martin wrote:
> irb(main):005:0> ("aa".."b1").to_a
> ["aa".."zz" elided]
Then - Trans wrote:
> 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?