--Boundary-BbmQBhCDarzOwKkYHIDdqSCDXrJ
Content-Type: text/plain
Content-Transfer-Encoding: 8bit

On Mon, 05 Jul 1999, you wrote:
>Hi, 

Hi,

first sorry for my late response, but I have waited, if another one
wants to post his/hers opinion. As that did not happen, I have decided
to send a Ruby-written Interval class to the list as prove-of-concept
as matz has supposed :-)

That class with a test is attached on that mail. Please consider, that
I had to write a dummy MyInt class, which do the same as the original
Integer class, as there are no Integer#succ and Integer#pred methods
with optional stepsize argument. If we already had them, I would not
need MyInt!

>
>In message "[ruby-talk:00429] Re: New feature for Ruby?"
>    on 99/07/03, Clemens Hintze <c.hintze / gmx.net> writes:
>>But I perhaps lack ability to write articles so that a magazin would
>>publish it! But nevertheless, I will try it someday :-)
>
>I long for your articles!

I will certainly send it to you before I give it to a magazin. But the
problem is... Do you understand German? ;-)

>
>By the way, I also would like to translate Matz and his collaborator's
>book about Ruby which will be published in near future in Japan. But I
>need a collaborator who correct my Engrish if I'm permitted to
>translate.

I really would like to help... but I have the same problem like you!
English is not my mother language. So I assume, I could translate such
a book into German, but not into an error-free English. Nor could I
correct somebodys English. It is not impossible, that I would
miscorrect such a (formerly correct) text ;-)

>
>>But Ruby already have magical increment of Strings, means String#succ!
>>And if I do a `"".succ' I will get an `"\377"'. As I didn't consider
>>that behavior as the one one would expect, I have patched String#succ,
>>so that it would raise an exception.
>
>That maybe important.  I think succ is allowed to be non one-to-one
>mapping, such that, str1.succ str2.succ for str1 ! tr2.  But
>either str.pred.succ str or str.succ.pred str should be held for
>arbitrary String str, I think.

I second that.

[...]

>For such objects, I feel a suitable name is `Sequence' rather than
>Interval. The name Sequence itself means descrete series, i.e.,
>enumerable and one dimensional. But Interval reminds me and
>mathematicians so general region as it may be use to a continuum or a
>higher dimensional structure. Other opinions?

It seems only mine :-) I think, that Sequence would also be okay,
perhaps. As I have told you, the name is coming from the Smalltalk
world not from any logical or even mathematical insight!

[...]

>Hummm, Fixnum is distinct from Integer in its functions, especially,
>the spacial cost. I've not recognized yet such major difference
>between Range and Interval. I feel some of problems or restrictions on
>Range seems to able to be solve by extending Range. I'd like to listen
>other persons' (including Matz's again) opinions. 

That was my first proposal! Enhance Range, so that all that features
would be offered by Range. The first patch, I've send to matz was such
an enhancement of Range.

But as I can also understand matz, saying, Range is defined as it is,
if he wants a new class for that purpose. It really doesn't matter for
me, whether we enhance the current Range class, write a new Interval
class or even call that class Sequence! I only want all these features
build-in into the interpreter, as it should be possible to iterate
forth and back with every stepsize. *Damned*, every simple BASIC
interpreter could do that! :-(

It really hurts me, that the mighty Ruby have use some esoteric
methods to archive the same goal :-(

[...]

>-- gotoken

\cle
--Boundary-BbmQBhCDarzOwKkYHIDdqSCDXrJ
Content-Type: text/x-ruby;
  namenterval.rb"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="Interval.rb"

#!/bin/env ruby


def interval(start, stop, step=1)
	Interval::new(start, stop, step)
end


class Interval
	include Enumerable

	attr_reader :first, :last, :step

	def initialize(start, stop, step=1)
		raise ArgumentError, "XXX1" if not (start.respond_to?(:<=>))
		up = ((start <=> stop) <= 0) 
		@cmp = up ? (:<=) : (:>=)
		@advfn = up ? (:succ) : (:pred)
		raise ArgumentError, "XXX2" if not (start.respond_to?(@advfn))
		raise ArgumentError, "XXX3" if step <= 0
		@first = start
		@last = stop
		@step = step
	end

	def each
		value = @first
		while (cmp = (value <=> @last)).send(@cmp, 0)
			yield value
			break if cmp == 0
			value = value.send(@advfn, @step)
		end
		nil
	end

	def [](index)
		i = 0
		each do |element|
			return element if i == index
			i += 1
		end
		nil
	end
end


if __FILE__ == $0

	# The class MyInt implements an Integer representation class. As
	# Integer currently lacks of a corresponding `succ' and `pred'
	# method with arguments, I have to use that dummy class to prove
	# the concept for the class Interval!
	#
	# matz: Why it is not possible to overwrite an integer
	# representation's `succ' method with a singleton one?

	class MyInt
		include Comparable

		attr_reader :val
		def initialize(i)
			@val = i
		end
		def succ(n)
			MyInt::new(@val + n)
		end
		def pred(n)
			MyInt::new(@val - n)
		end
		def <=>(other)
			@val <=> other.val
		end
		def coerce(other)
			if other.type == MyInt
				[self, MyInt::new(other)]
			else
				[@val, other]
			end
		end
		def to_s
			"#{@val}"
		end
		def inspect
			to_s
		end
	end
			
	# Here begin the examples. If later the class Integer owns the
	# methods `succ' and `pred' with optional stepsize argument, this
	# examples would work with normal Integers too.

	print "===Upwards Interval 1..9===\n"
    for i in interval(MyInt::new(1), MyInt::new(9))
		p(i)
	end

	print "===Downwards Interval 9..1===\n"
	for i in interval(MyInt::new(9), MyInt::new(1))
		p(i)
	end

	print "===Upwards 1..9 step 3===\n"
	for i in interval(MyInt::new(1), MyInt::new(9), 3)
		p(i)
	end

	print "===Downwards 9..1 step 3===\n"
	i = Interval::new(MyInt::new(9), MyInt::new(1), 3)
	i.each{ |el| p(el) }

	print "===Is 3 in that interval? (answer: true): "
	p(i.include?(MyInt::new(3)))

	print "===Is 2 in that interval? (answer: false): "
	p(i.include?(MyInt::new(2)))

	print "===What is the first element? (answer: 9): "; p(i[0])
	print "===What is the second element? (answer: 6): "; p(i[1])
	print "===What is the third element? (answer: 3): "; p(i[2])
end

--Boundary-BbmQBhCDarzOwKkYHIDdqSCDXrJ--