Case Checks

R

Robert Klemme

When I couldn't sleep this morning, this came across my head:

class Check
def initialize(sym, args)
@args=args
instance_eval "def ===(obj); obj.#{sym}(*@args); end"
end

class <<self
def create(sym=nil, *args, &bl)
if bl
def bl.===(obj); call(obj); end
bl
elsif sym
new sym, args
else
raise "Need either block or symbol with arguments"
end
end

private :new
end
end


Now you can do:

Negative = Check.create {|x| x.kind_of? Numeric and x<0}
Positive = Check.create {|x| x.kind_of? Numeric and x>0}
Zero = Check.create {|x| x.kind_of? Numeric and x==0}

# error:
begin
Foo = Check.new :foo
raise "No exception!"
rescue NameError
# puts "ok"
end

[-2,-10,23,666,10.4,-23.4,"foo"].each do |i|
case i
when Negative
puts "#{i} Neg"
when Positive
puts "#{i} Pos"
when Zero
puts "#{i} Zero"
else
puts "#{i.inspect} not numeric"
end
end


Empty = Check.create :empty?

for i in 0..10 do
a=Array.new( i, "x" )

case a
when Empty
puts "empty"
else
puts "filled (#{a.inspect})"
end
end

robert
 
M

Martin DeMello

Robert Klemme said:
When I couldn't sleep this morning, this came across my head:

class Check
def initialize(sym, args)
@args=args
instance_eval "def ===(obj); obj.#{sym}(*@args); end"
end

class <<self
def create(sym=nil, *args, &bl)
if bl
def bl.===(obj); call(obj); end
bl
elsif sym
new sym, args
else
raise "Need either block or symbol with arguments"
end
end

private :new
end
end


Very nice! Here's an extension (untested):

def check(*args, &block)
checks = args
checks << Check.create(block) if block
class << checks
def ===(obj)
all? {|i| i === obj}
end
end
checks
end

allowing

case i
when check(Positive, Div5) {|x| x > 100}
...

martin
 
R

Robert Klemme

Martin DeMello said:
Very nice! Here's an extension (untested):
def check(*args, &block)
checks = args
checks << Check.create(block) if block
class << checks
def ===(obj)
all? {|i| i === obj}
end
end
checks
end

The create method is not called correctly. But I like the shorter
creation, i.e.,

check {|x| x == "bar"}

Corrected:

def check(*args, &block)
checks = args
checks << Check.create(&block) if block

class <<checks
def ===(obj)
all? {|i| i === obj}
end
end

checks
end

Of course, invoking check outside the case is more efficient for cases
where case is executed often.
allowing

case i
when check(Positive, Div5) {|x| x > 100}

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,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top