[#13775] Problems with racc rule definitions — Michael Neumann <neumann@...>

15 messages 2001/04/17
[#13795] Re: Problems with racc rule definitions — Minero Aoki <aamine@...> 2001/04/18

Hi,

[#13940] From Guido, with love... — Dave Thomas <Dave@...>

52 messages 2001/04/20

[#13953] regexp — James Ponder <james@...>

Hi, I'm new to ruby and am coming from a perl background - therefore I

19 messages 2001/04/21

[#14033] Distributed Ruby and heterogeneous networks — harryo@... (Harry Ohlsen)

I wrote my first small distributed application yesterday and it worked

15 messages 2001/04/22

[#14040] RCR: getClassFromString method — ptkwt@...1.aracnet.com (Phil Tomson)

It would be nice to have a function that returns a class type given a

20 messages 2001/04/22

[#14130] Re: Ruby mascot proposal — "Conrad Schneiker" <schneik@...>

Guy N. Hurst wrote:

21 messages 2001/04/24
[#14148] Re: Ruby mascot proposal — Stephen White <spwhite@...> 2001/04/24

On Tue, 24 Apr 2001, Conrad Schneiker wrote:

[#14188] Re: Ruby mascot proposal — matz@... (Yukihiro Matsumoto) 2001/04/25

Hi,

[#14193] Re: Ruby mascot proposal — "W. Kent Starr" <elderburn@...> 2001/04/25

On Tuesday 24 April 2001 23:02, Yukihiro Matsumoto wrote:

[#14138] Re: python on the smalltalk VM — Conrad Schneiker <schneik@...>

FYI: Thought this might be of interest to the JRuby and Ruby/GUI folks.

27 messages 2001/04/24
[#14153] Re: python on the smalltalk VM — Andrew Kuchling <akuchlin@...> 2001/04/24

Conrad Schneiker <schneik@austin.ibm.com> writes:

[#14154] array#flatten! question — Jim Freeze <jim@...> 2001/04/24

Hello.

[#14159] Can I insert into an array — Jim Freeze <jim@...> 2001/04/24

Ok, this may be a dumb question, but, is it possible to insert into an

[#14162] Re: Can I insert into an array — Dave Thomas <Dave@...> 2001/04/24

Jim Freeze <jim@freeze.org> writes:

[#14289] RCR: Array#insert — Shugo Maeda <shugo@...> 2001/04/27

At Wed, 25 Apr 2001 01:28:36 +0900,

[#14221] An or in an if. — Tim Pettman <tjp@...>

Hi there,

18 messages 2001/04/25

[#14267] Re: Ruby mascot proposal — "Conrad Schneiker" <schneik@...>

Danny van Bruggen,

16 messages 2001/04/26

[#14452] How to do it the Ruby-way 3 — Stefan Matthias Aust <sma@3plus4.de>

First a question: Why is

21 messages 2001/04/30

[ruby-talk:13469] Re: A subtle Hash bug

From: "Christoph Rippel" <crippel@...>
Date: 2001-04-04 03:29:24 UTC
List: ruby-talk #13469
> From: Mathieu Bouchard [mailto:matju@sympatico.ca]
[..]
> I'm not proposing that +Infinity should be indistinguishable from
> -Infinity. I'm asking why is +Infinity == +Infinity and -Infinity ==
> -Infinity.
Well,

basically the Numeric class hierarchy puts a nice OO-rapper around
the native C types integer and double and adds Bignum to it and
for the most part this was very well done - the identity methods 
seem the follow pattern
 
 * x == y     - if x,y are C-equal
 * x.eql? y   - if x,y are C-equal and no type conversion is necessary
 * x.equal? y - if x,y are id-equal (this effects Float and Bignum)

Since C's double has the unique constants +/- Infinity and NaN you 
need to guarantee that 
  1/0.0 == 1/0.0, 1/-0.0 == 1/-0.0,( 1/0.0) * 0 == (1/0.0) * 0 (== NaN)  
otherwise you would break this pattern. Anthing else would make the 
special value logic essentially unusable IMO.
 
This is not really relevant here but I sort believe that at least one
of Ruby's equal methods should have been a class method - something like
   Float.identical?(1, 1.0) # => true
This would have eliminated the problematic asymmetry of methods receiver 
versus method argument and it makes generally more sense anyway - the only
reason against this are the extra key strokes.

[...]
> > The exception raising behavior of zero-division and comparison
> > is type specific on the method receiver end
> >  2**29 <=> 1/0.0  # => -1 since  2**29 is a Fixnum   
> >  2**33 <=> 1/0.0  # FloatDomainError: Infinity since 2**33 is Bignum
> 
> this should return -1 since although +Infinity is not a precise number, it
> is greater than all other finite values and -Infinity. (it is however
> noncomparable to itself and to NaN)

I don't believe that this is such a good idea - you would get

    10**400 > 1.0  # => true
    10**400 + 10**400 > 1.0 + 10**400 # => false

since 1.0 + 10**400 is equal to Floats Infinity but the left hand side is
still an ordinary Bignum  which amounts to the mathematical equivalent 
of a containment breach during a nuclear reactor melt-down.

> >  1/ 0             # a ZeroDivisionError is raised for any Integer type
> 
> This is ok, because the Integer domain has no equivalent of Infinities and
> NaNs.
Yes ..

> > I actually have a Ruby hack of logical +/- Infinity's constants.
> > The semantics is closer to +/- nil and but you can perform limited
> > Arithmetic on them - I made them instances of +/- Infinity Classes
> > sub-typed from Numeric but this is not really necessary. (the are
> > necessarily smaller/bigger then floats infinities).
> 
> May I see that? Btw, what are +nil and -nil ???

I attached something below - the reason for calling them +/- nil is that 
they could be the return values of [].min, [].man etc. which currently 
return nil and if +/- Infinity would act as logical false values you
probably would not break any existing script.

> > methods input of any numeric object (except for Rational, which
> > is an eager beaver and tries to process input it does not 
> > understand instead of calling coerce).
> 
> Do you think Rational should be fixed to act, ehm, more rationally?

Don't know - the current behavior also breaks theoretical stuff like 
integral or field extension of the Integer Class by ``adding sqrt(2)'' 
etc. but this is not that problematic IMO.
To beat a dead horse of mine what Ruby is really missing is support for
Modules (and consequently Classes) parameterized by Module constant 
with a instantiation logic. 

[...]

Christoph

---------------
Sorry this is quite longish -  basically it was an exploration of the
Singleton class construction and I wanted to see on how far the poor
men's version of multi-dispatch (a.k.a. coerce) gets you - running 
examples with +/-infty as input is quite usefully for debugging and 
it is a better (that means fewer if-then-else constructs in your code) 
return value for certain method then nil, -1 etc.

------------
require 'infinity'
module Enumerable
def max; inject(Infinity.minus) {|a,b| (a > b ) ? a : b } end
end

p [].max         # => -infty
p [3,5,-9].max   # => 5


class Someclass
Minimalvalue= Infinity.minus
# .....

def size
   if empty?
	Minimalvalue
   else
	something_else
   end
end

end

------------
###### infinity.rb ############################
#	Copyright (c) 2001 by Christoph Rippel
#	Licensed under the same license as Ruby
###############################################

class Infinity < Numeric; end

######  Thread safety  ########
unless Infinity.instance_eval { @__initialized__ }
	Thread.critical = true
begin	

class Numeric
	#	The finite?, infinite? methods and the  Zero, One constants
	# 	are nice but not necessary.  Note that the Fixnums Zero, One 
	#	constants are the Zero, One constants of the whole Numeric 
	#	hierarchy  - the OO-manifestation that a (commutative) ring 	
	#	is the same thing as a (commutative) algebra. 
	def finite?; true end
	def infinite?; false end
	Zero = 0 
	One = 1
end

class Float
	Zero  = 0.0
	One = 1.0
end

module InfinityError
	#	The Error handling regime is probably brain dead ..
	class AdditionError           <  TypeError; end
	class SubtractionError        <  TypeError; end
	class InfinityDivisionError   <  TypeError; end
	class ZeroMultiplicationError <  TypeError; end  
	class ZeroDivisionError       <  ZeroDivisionError; end
	def addition;            raise AdditionError  end	
	def subtraction;         raise SubtractionError  end	
	def  infinityDiv(other); raise InfinityDivisionError end  
	def zeroMul(other);      raise ZeroMultiplicationError  end
	def zeroDiv(other);      raise ZeroDivisionError end
	def inspect;  'InfinityError handler' end
	def to_s;     'InfinityError handler' end
end


class Infinity 	
	#	Common instances methods 
	def finite?; false end
	def infinite?; true end
	def integer?; false end
	def succ; self end
	def next; self end
	def zero?; false end
	
	#	Utility methods to access the Instance and 
	#	Error handling object - rarely used
	def error_handler; type::Ehandler  end
	def instance; type::Instance end

	# 	Thread safety 	
	@__initialized__ = true 
	class << self
		def minus;  InfinityMinus::Instance  end
		def plus; InfinityPlus::Instance end
	end
end

class InfinityMinus < Infinity
	#	It is faster to define the less commonly methods  as
	#	instances methods - incidentally they are mostly 
	#	shared between the Instance and its mirror. 
	Instance = self.new
	Ehandler = Object.new.extend  InfinityError 
	def inspect; ' -infty' end
	def to_s; ' -infty' end
	def sgn; -1 end
	def times(&prog);   
		 Instance
	end
end
class InfinityPlus < Infinity
	Instance = self.new
	Ehandler = Object.new.extend  InfinityError
	def inspect; ' infty' end
	def to_s; ' infty' end
	def sgn; 1 end
	def times(&prog)
		prog.call(self) while true
		Instance
	end
end


class  << Infinity.minus	
	#	Defining the Mirror as a singleton constant is notably
	#	faster - the luxury of supporting infinite multiplication 
	#	and division is expensive because we need to create a 
	#	new coercion Array every time coerce is called.
	Minus = Infinity.minus
	Plus =  Infinity.plus
	Mirror = InfinityMinus.new 
	
	def coerce(other);  [Mirror, other]  end 
	def finite?; false end
	def <(other); !(equal? other) end
	def >(other); false end
	def <=>(other);   (equal? other) ? 0 : -1 end
	
	# 	defining -@ is not necessary but more efficient
	def -@; Plus end
	def +(other);  (other.equal? Plus) ?     Ehandler.addition :  Minus end	
	def -(other);  (other.equal? Minus) ? Ehandler.subtraction :  Minus end
	def *(other);
		return Plus   if other < 0
		return Minus  if other > 0 
		return Ehandler.zeroMul(other)
	end 
	def /(other) 
		return	Ehandler.infinityDiv(other)  unless other.finite? 			
		return Plus   if other < 0
		return Minus  if other > 0 
		return Ehandler.zeroDiv(other) 
	end  

class  << Mirror
	Minus = Infinity.minus
	Plus =  Infinity.plus
	
	def <(other); false end
	def >(other); true end
	def <=>(other);   1  end
		
	def +(other); Minus end
	def -(other); Plus end
	def *(other)
		return Plus   if other > 0
		return Minus  if other < 0 
		return Ehandler.zeroMul(other)
	end   
	def /(other) ; other.type::Zero    end  	
	def %(other) ; (other > 0 ) ? Minus : other end  
	#	def remainder(other); other end
	#	Ruby ignores the previous line 
end
end

class  << Infinity.plus	
	Plus =  Infinity.plus
	Mirror = InfinityPlus.new
	Minus = Infinity.minus
	
	def coerce(other);  [Mirror, other] end
	def finite?; false end
	
	def <(other); false  end
	def >(other); !(equal? other)   end
	def <=>(other);   (equal? other) ? 0 : 1 end

	def -@; Minus end
	def +(other); (other.equal? Minus) ?    Ehandler.addition :  Plus end	
	def -(other);  (other.equal? Plus) ? Ehandler.subtraction :  Plus  end
	def *(other);
		return Plus     if other > 0
		return Minus  if other < 0 
		return Ehandler.zeroMul(other)
	end 
	def /(other)
		return Ehandler.infinityDiv(other)  unless other.finite?
		return Plus     if other > 0
		return Minus  if other < 0 
		return Ehandler.zeroDiv(other)
	end
	
class  << Mirror
	Plus = Infinity.plus
	Minus = Infinity.minus
	
	def <(other); true end
	def >(other); false end
	def <=>(other);   -1  end
		
	def +(other); Plus end
	def -(other); Plus end
	def *(other); 
		return Plus     if other > 0
		return Minus  if other < 0 
		return Ehandler.zeroMul(other)
	end 
	def /(other);  (other.type)::Zero  end   
	def %(other) ; (other < 0 ) ? Plus : other end  
end
end 

class << Infinity
	undef_method :new
end

ensure
	Thread.critical = false
end		
end 

def Infinity.leftlogic_initialize
	Thread.critical = true
	begin
		::Infinity.class_eval (%{
		def to_truth; false end
		def &(other);   ::NIL & other end
		def ^ (other);  ::NIL ^ other end
		def | (other);  ::NIL | other end
		})	
	ensure 
		::Infinity.instance_eval (%{ def leftlogic_initialize; true end })
		Thread.critical = false
	end
	true
end	

------------
###### test.rb ################################ 
require 'infinity'

mi =  Infinity.minus
pi  = Infinity.plus


mi =  Infinity.minus
pi  = Infinity.plus

def p_ary (*ary); puts	ary.join ", " end	

x = mi
x -= 25
x *=  -13.0
y = 344.9999
y /=  pi


p_ary  "simple test", x, y,  34**34 / mi
p_ary   "x+  -infty", mi + mi, mi - pi, mi + 1, 1.0+ mi
p_ary  "x+ infty", pi + pi, pi - mi,   pi + 2.0,  -3**24 + pi
   
p_ary  "-infty <=> x",  mi <=> mi, mi <=> 0, mi <=> pi
p_ary  " x <=> - infty",  0 <=> mi, pi <=> mi

p_ary "infty <=> x",  pi <=> mi, pi <=> 0, pi <=> pi
p_ary " x <=> infty",   mi <=> pi, 31.3 <=> pi


p_ary  "-infty < x",  mi < mi, mi < 0, mi < pi
p_ary  " x < - infty",  0 < mi, pi < mi

p_ary "infty < x",  pi < mi, pi < 0, pi < pi
p_ary " x < infty",   mi < pi, 31.3 < pi


p_ary  "-infty > x",  mi > mi, mi > 0, mi > pi
p_ary  " x > - infty",  0 > mi, pi > mi

p_ary "infty > x",  pi > mi, pi > 0, pi > pi
p_ary " x > infty",   mi > pi, 31.3 > pi


p_ary  "-infty == x",  mi == mi, mi == 0, mi == pi
p_ary  " x == - infty",  0 == mi, pi == mi

p_ary "infty == x",  pi == mi, pi == 0, pi == pi
p_ary " x == infty",   mi == pi, 31.3 == pi


p "test of Ehandlers and *,/ etc. "
p " An alternative for the normal error-raising behavior" 

class << mi.error_handler
	def zeroMul(other); -other.type::One  end
	def infinityDiv(other); -other.sgn end
	def zeroDiv(other);	Infinity.minus end
end
class << pi.error_handler
	def zeroMul(other);  other.type::One end
	def infinityDiv(other); other.sgn end
	def zeroDiv(other);	Infinity.plus end
end

module InfinityError
	def addition; 0  end
	def subtraction; 0  end
end

p_ary   "-infty*x",  mi*mi, mi* (-1.0), mi* 0.0, mi * 23, mi*pi
p_ary   "-infty/x",  mi/mi, mi/ (-1.0), mi/ 0.0,  mi/ 1, mi/ pi
p_ary   "infty*x",  pi*mi, pi* (-1.0), pi* 0.0, pi * 23, pi*pi
p_ary   "infty/x",  pi/mi, pi/ (-1.0), pi/ 0.0,  pi/ 1, pi/ pi

p_ary   "x*-infty*x", -2.3* mi,0.0 * mi, 23* mi
p_ary   "x/ -infty",  -3.5/ mi,  0.0 /mi,  1/ mi,  mi/ 1, pi/ mi
p_ary   "x*infty", -2.3* pi,0.0 * mi, 23* mi
p_ary   "x/ infty",  mi/ - pi, 0.0 /pi,  1/ pi,  pi/ pi



p_ary "add", mi - mi, pi - pi, mi + pi, pi + mi

Infinity.leftlogic_initialize
p "left-logic test"
p_ary pi ^ mi, pi & 64, mi | false

 

In This Thread