Range#member? Oddity

On Sat, 14 Jan 2006 01:01:21 +0100, James Edward G. II
[email protected] wrote:

On Jan 13, 2006, at 5:54 PM, David V. wrote:

I’m pretty sure we don’t want to change the meaning of String
comparisons at this point. succ() just doesn’t happened to be defined
under those terms, because then it would be a lot less useful to us.
It’s hard for me to see any of that as “broken”.

James Edward G. II

I never said anything the like, the code breakage would be inexcusable.

My point is it’s String that behaves erreneously in this context and
isn’t
suitable for use in symbolic ranges, not a bug in Range code - the posts
were an objection to people wanting to mess up the Range interface.

David V.

On Sat, 14 Jan 2006 01:26:22 +0100, Logan C.
[email protected]
wrote:

s.succ > s and then alias strict_succ to succ for other classes
generated by String#succ to be in the array when doing a to_a for
instance. I believe the real solution would be to bring back the
distinction between member and include (possibly with a new name for the
method with the functionality of #member).

I agree that the change proposed would break Range#to_a for strings,
which
I can imagine being used. The real solution would be people coding
sanely
and using Integers to represent integers, and Strings to represent text

using unsuitable data types resulting in a bug is arguably not a
language
fault.

David V.

On Jan 13, 2006, at 7:18 PM, [email protected] wrote:

Gary W.

This seems to me to make the problem worse. People expect the values
generated by String#succ to be in the array when doing a to_a for
instance. I believe the real solution would be to bring back the
distinction between member and include (possibly with a new name for
the method with the functionality of #member).

On Jan 13, 2006, at 7:26 PM, Logan C. wrote:

This seems to me to make the problem worse. People expect the
values generated by String#succ to be in the array when doing a
to_a for instance. I believe the real solution would be to bring
back the distinction between member and include (possibly with a
new name for the method with the functionality of #member).

It seems strange to want Range to behave like an interval and to
also want Range#to_a to create a list of elements that don’t all
belong in that same interval.

I understand the desire to generate a sequence of strings
as defined by the current behavior of String#succ but I don’t understand
why you would want to use a Range object as a shortcut to that sequence.
That particular sequence really has nothing to do with an interval
or the ordering defined by String#<=>

Gary W.

On Jan 13, 2006, at 7:53 PM, [email protected] wrote:

I understand the desire to generate a sequence of strings
as defined by the current behavior of String#succ but I don’t
understand
why you would want to use a Range object as a shortcut to that
sequence.
That particular sequence really has nothing to do with an interval
or the ordering defined by String#<=>

As far as I can tell two classes(Well 4ish) have #succ methods.
Integers and Strings. For all integers x, x has the property that
x.succ > x is true.
There exists at least one String x for which x.succ > x is true, and
at least one String x for which x.succ > x is false. So the question
is, what is a Range? Is it a pair of end-points for checking between-
ness? Is it the set of all values between those end points? If it is
the second, I would argue that #to_a is meaningless for strings
because there are end points for which the set would have infinite
cardinality (i.e. (“a”…“b”), the set of strings matched by /^a+\z/
at least is in that “range”.).

Hi,

Am Samstag, 14. Jan 2006, 05:49:56 +0900 schrieb James Edward G. II:

=> false
irb(main):006:0> 2 < 10
=> true
irb(main):007:0> “2” < “10”
=> false

Bertram

On Sat, 14 Jan 2006 01:53:37 +0100, [email protected] wrote:

It seems strange to want Range to behave like an interval and to
also want Range#to_a to create a list of elements that don’t all
belong in that same interval.

It’s a Convenient Hack ™, and those are extremely hard to weed out
once
they catch hold. It’s the same as when people use #eval that must a
nightmare to the brave folks working on optimizing YARV (I want my clean
blocks!) instead of the much cleaner metaprogramming facilities in Ruby
that let you achieve 99% of what I’ve seen hacked with evals anyway.
(Very
obfuscated eval hacks notwithstanding).

David V.

James Edward G. II wrote:

=> false
In short: Don’t do this.

String ranges are very weird. They don’t obey the rule that
x.succ > x.

Since “2” > “10”, “2” is considered outside the range entirely.

If you really want to do this kind of thing, say
(“1”…“10”).to_a.member?(“2”)

Hal

Hal F. wrote:

James Edward G. II wrote:

=> false
In short: Don’t do this.

String ranges are very weird. They don’t obey the rule that
x.succ > x.

Since “2” > “10”, “2” is considered outside the range entirely.

If you really want to do this kind of thing, say
(“1”…“10”).to_a.member?(“2”)

Hal

If the two strings have the same length, the weirdness disappears.

Christer

Christer N. schrieb:

If the two strings have the same length, the weirdness disappears.
Very good point!

Regards,
Pit

Hi –

On Sat, 14 Jan 2006, Christer N. wrote:

If you really want to do this kind of thing, say
(“1”…“10”).to_a.member?(“2”)

Hal

If the two strings have the same length, the weirdness disappears.

But other weirdnesses arise :slight_smile:

irb(main):019:0> (“A”…“z”).member?(“g”)
=> true
irb(main):020:0> (“A”…“z”).to_a.include?(“g”)
=> false

David


David A. Black
[email protected]

“Ruby for Rails”, from Manning Publications, coming April 2006!

[email protected] wrote:

But other weirdnesses arise :slight_smile:

irb(main):019:0> (“A”…“z”).member?(“g”)
=> true
irb(main):020:0> (“A”…“z”).to_a.include?(“g”)
=> false

David

IMO, the thing at fault here is that Ranges include Enumerable. From a
mathematical POV, that’s nonsense, and that’s why oddities like this
exist. Things that can be used for ranges can not used like an
Enumarable (rational…rational, float…float), because those don’t have
#succ instance methods… and String ranges behave oddly because the
member? checks use the <=> behaviour, and each uses succ…

Regards,
Stefan

[email protected] wrote:

On Sat, 14 Jan 2006, Stefan W. wrote:
but enumerable means neither monotonically increasing nor finite. so
that a
range includes enumerable means only that one may start, but perhaps never
finish, to count the elements in the range. i think this is accurate isn’t
it?

cheers.

-a

Enumerable means that you can map the natural numbers to your set in an
invertable way, and that’s not possible for ranges of real numbers.
Being enumerable means the possibility of a “succ” operation, and
therefore of traversing the whole set with “each” (which may take
infinite time). Being enumerable implies a working each, now try
(1.0…2.0).each…

Regards,
Stefan

On Sat, 14 Jan 2006 17:03:59 +0100, Stefan W. [email protected]
wrote:

Enumerable means that you can map the natural numbers to your set in an
invertable way, and that’s not possible for ranges of real numbers.
Being enumerable means the possibility of a “succ” operation, and
therefore of traversing the whole set with “each” (which may take
infinite time). Being enumerable implies a working each, now try
(1.0…2.0).each…

Regards,
Stefan

There’s nothing wrong with enumerating ranges, you can well have
intervals
of natural numbers or other countably infinite sets. Bounded intervals
of
countable or countably infinite sets are finite sets and may be (not
necessarily though) enumerated in order using the successor operation,
which exists if the elements of the interval are well-ordered. It’s not
exactly an edge case, and distinguishing between ranges with finite and
infinite element counts

The issue with strings is that their ordering does not make them such
a
well-ordered countably infinite set. Because strings are compared using
textual comparison, as was already noted in this thread, for every two
given strings, there exists an infinite amount of strings between them.
For the sake of completion, strings in fact are a countably infinite
set, but their ordering doesn’t respect any mapping of strings to
natural
numbers.

Given this, the string successor operation doesn’t even make sense from
the mathemathical point of view. It is in this context defined ad hoc,
and
it’s usefulness lies in contexts of text processing.

Using a string Range is a convenient shortcut, but it’s a hack.
Nothing
more, nothing less. Strings don’t have a solid foundation for use in
maths. If you expect strings to behave as numbers, you’re wrong, they’re
not supposed to, any bugs are your fault, not the fault of the Ruby core
API. Moan and suffer.

David V.

David V. wrote:

There’s nothing wrong with enumerating ranges, you can well have
intervals of natural numbers or other countably infinite sets. Bounded
intervals of countable or countably infinite sets are finite sets and
may be (not necessarily though) enumerated in order using the successor
operation, which exists if the elements of the interval are
well-ordered. It’s not exactly an edge case, and distinguishing between
ranges with finite and infinite element counts

Your messages seems to have been truncated here. Also, you’re wrong,
bounded intervals of countably infinite sets do not have to be finite.
Consider [0,1] in the rational numbers. Rational numbers are countable,
the range is bounded, but the set is not finite (it is still countably
infinite).

Using a string Range is a convenient shortcut, but it’s a hack.
Nothing more, nothing less. Strings don’t have a solid foundation for
use in maths. If you expect strings to behave as numbers, you’re wrong,
they’re not supposed to, any bugs are your fault, not the fault of the
Ruby core API. Moan and suffer.

David V.

Range including Enumerable is a fault of the ruby core API, because
(1.0…20) pretends to be enumerable (is_a? returns true, responds_to?
:each returns true), but is not.

Regards, Stefan (who never had problems with string ranges, only with
Range including Enumerable)

On Sat, 14 Jan 2006, Stefan W. wrote:

IMO, the thing at fault here is that Ranges include Enumerable. From a
mathematical POV, that’s nonsense, and that’s why oddities like this exist.
Things that can be used for ranges can not used like an Enumarable
(rational…rational, float…float), because those don’t have #succ instance
methods… and String ranges behave oddly because the member? checks use the
<=> behaviour, and each uses succ…

but enumerable means neither monotonically increasing nor finite. so
that a
range includes enumerable means only that one may start, but perhaps
never
finish, to count the elements in the range. i think this is accurate
isn’t
it?

cheers.

-a

James Edward G. II schrieb:

=> false

James Edward G. II

I don’t know why to_a is working here.
I know that a range from ‘1’ to ‘10’ could be like you described, but it
doesn’t make a logical sense I think.
like (‘a’…‘ah’) what should that be?
[a-255.chr] and all a[0.chr-255.chr]?

This is what I think, of course.
Dunno if it makes sense :>

MfG
Retze

On Sat, 14 Jan 2006 19:54:55 +0100, Stefan W. [email protected]
wrote:

[snip]

Range including Enumerable is a fault of the ruby core API, because
(1.0…20) pretends to be enumerable (is_a? returns true, responds_to?
:each returns true), but is not.

That is, of course, misleading, but ranges are very commonly used in the
special cases when they are indeed enumerable, so I can understand why
it’s defined that way in the core API. Library design isn’t there to
replace programmer brains. You could theorethically check whether the
range endpoints are comparable, and whether the starting one defines
#succ, and then mix in Enumerable to the Ranges that indeed are to get
more strictly correct behaviour.

David V.

On Sun, 15 Jan 2006, Stefan W. wrote:

Enumerable means that you can map the natural numbers to your set in an
invertable way, and that’s not possible for ranges of real numbers. Being
enumerable means the possibility of a “succ” operation, and therefore of
traversing the whole set with “each” (which may take infinite time). Being
enumerable implies a working each, now try (1.0…2.0).each…

that is certainly true. however, there are no real numbers in computing

only rational numbers and rationals are countably infinite

http://mathworld.wolfram.com/CountablyInfinite.html
http://mathworld.wolfram.com/RationalNumber.html

while (1.0…2.0).each{|x| p x} cannot work with real numbers it can
certainly
work with a set of rational numbers - in computing terms you can
certainly
count from 1.0 to 2.0 by adding the floating point epsilon. my opinion
is
that we’re talking computer languages here, not mathematicaly ones, and
so any
idea of being ‘correct’ must be in the context of what computers can do.

in any case, ruby makes no guarantee that

(a…b).each{|x| p x}

will complete, so even if we had real numbers that would still be a
valid
construct - though mixing in Enumerable into Range would be strange then

  • but
    it not the case.

cheers.

-a

On Jan 14, 2006, at 4:41 PM, [email protected] wrote:

in any case, ruby makes no guarantee that

(a…b).each{|x| p x}

will complete, so even if we had real numbers that would still be a
valid
construct - though mixing in Enumerable into Range would be strange
then - but
it not the case.

Here’s a thought, get rid of #each and Enumerable from Range, but add
in a #to_enum method (no args) that would return an Enumerator for
the range. This way programmers could say, “I solemnly swear that I
know iterating thru a range of strings doesn’t make sense with
include, but I want to do it anyway.”

(“ab”…“xyz”).to_enum.to_a # etc…

On second thought, that looks unnecessary.

How about:

% cat a.rb
(“abc”…“wxyz”).to_a

% ruby -w a.rb
warning: You fool! By doing this you know include? will make no sense!

Maybe not.

Stupid ranges. Hmph.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs