comparison operations in case statements

J

Joel VanderWerf

This looks kind of cute, as a way to mix class-matching tests with
comparison operator tests in case statements. Too bad it's not really
practical (the commented out caching may help a bit, but may also use
too much memory):

class Comparator < Proc
def ===(val)
call val
end

def &(other)
compare do |val|
self[val] and other[val]
end
end
end

def compare
Comparator.new
end

class Numeric
#@comparator_lt = {}
def self.<(x)
#@comparator_lt[x] ||=
compare do |val|
self === val and val < x
end
end

#@comparator_gt = {}
def self.>(x)
#@comparator_gt[x] ||=
compare do |val|
self === val and val > x
end
end
end


raise unless (Numeric < 6) === 3
raise if (Integer < 6) === 2.3
raise if (Integer < 6) === "foo"

case 3
when (Numeric < 6) & (Numeric > 5); raise
when (Numeric < 0) & (Numeric > -10); raise
when (Numeric < 6) & (Numeric > 2)
else raise
end
 
L

Logan Capaldo

This looks kind of cute, as a way to mix class-matching tests with
comparison operator tests in case statements. Too bad it's not really
practical (the commented out caching may help a bit, but may also use
too much memory):

class Comparator < Proc
def ===(val)
call val
end

def &(other)
compare do |val|
self[val] and other[val]
end
end
end

def compare
Comparator.new
end

class Numeric
#@comparator_lt = {}
def self.<(x)
#@comparator_lt[x] ||=
compare do |val|
self === val and val < x
end
end

#@comparator_gt = {}
def self.>(x)
#@comparator_gt[x] ||=
compare do |val|
self === val and val > x
end
end
end


raise unless (Numeric < 6) === 3
raise if (Integer < 6) === 2.3
raise if (Integer < 6) === "foo"

case 3
when (Numeric < 6) & (Numeric > 5); raise
when (Numeric < 0) & (Numeric > -10); raise
when (Numeric < 6) & (Numeric > 2)
else raise
end

Neat. Seems a little redundant though

raise unless Numeric === 3
case
when 3 < 6 and 3 > 5; raise
when 3 < 0 and 3 > -10; raise
when 3 < 6 and 3 > 2
else raise
end

I'm presuming nine times out of ten the variable you'll run these
tests on will have less characters than Numeric for instance.

eg:
x = 3
raise unless Numeric === x
case
when x > 2; ...
end
 
R

Robert Klemme

Joel VanderWerf said:
This looks kind of cute, as a way to mix class-matching tests with
comparison operator tests in case statements. Too bad it's not really
practical (the commented out caching may help a bit, but may also use
too much memory):

class Comparator < Proc
def ===(val)
call val
end

def &(other)
compare do |val|
self[val] and other[val]
end
end
end

This doesn't allow for arbitrary chaining. You would rather have to return
something that overloads & as well. But that will be difficult in the light
of the last value returned (you don't know that it's the last value in the
method).
def compare
Comparator.new
end

class Numeric
#@comparator_lt = {}
def self.<(x)
#@comparator_lt[x] ||=
compare do |val|
self === val and val < x
end
end

#@comparator_gt = {}
def self.>(x)
#@comparator_gt[x] ||=
compare do |val|
self === val and val > x
end
end
end


raise unless (Numeric < 6) === 3
raise if (Integer < 6) === 2.3
raise if (Integer < 6) === "foo"

case 3
when (Numeric < 6) & (Numeric > 5); raise
when (Numeric < 0) & (Numeric > -10); raise
when (Numeric < 6) & (Numeric > 2)
else raise
end

I'd prefer the more general approach as I suggested a while back already:

module Kernel
private
condition(&cond)
class<<cond
alias :=== :call
end
cond
end
end

Then you can do

case 3
when condition {|x| x<6 && x>5}; ...

end

or

LESS_THAN_6_AND_GREATER_THAN_5 = condition {|x| x<6 && x>5}

case 3
when LESS_THAN_6_AND_GREATER_THAN_5; ...
....

or better

ILLEGAL = condition {|x| x<6 && x>5 or ...}

case x
when ILLEGAL; raise ...
....

Of course this looks silly in this case, but in more reasonable cases it
doesn't. For example

NEGATIVE = condition {|x|x<0}
EVEN = condition {|x| x%2==0}

case x
when NEGATIVE; raise "error!"
when EVEN; puts "found an even number"
end

which reads nicely.

Kind regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top