E
Emmanuel Oga
# Paste url: http://gist.github.com/5603
# Gist Paste Clone URL: git://gist.github.com/5603.git
# [Impossible?] CHALLENGE: See pending spec at the bottom
#
# PROBLEM: I want to replace statements like this:
#
# puts (OddRecognizer.new.knows?(1) or OddRecognizer.new.knows?(3)) ?
"there are odds" : "there is no odd"
#
# With something like this:
# puts OddRecognizer.new.knows?(1).or?(3) ? "there are odds" : "there
is no odd"
#
# OddRecognizer is just a trivial class just to prove my concept
class OddRecognizer
def knows?(value)
(value % 2) == 0
end
end
require 'rubygems'
require 'spec'
describe OddRecognizer do
before :each do
@recognizer = OddRecognizer.new
end
it "should recognize 2" do
@recognizer.knows?(2).should be_true
end
it "should not recognize 3" do
@recognizer.knows?(3).should be_false
end
end
# Here's the implementation
class BooleanEvaluator
Operation = Struct.new :name, :arguments
def initialize(target, method, *args)
@target, @method = target, method
@arguments = Array.new << Operation.newfirst, args)
end
def or?(*args)
@arguments << Operation.newor, args)
self
end
def and?(*args)
@arguments << Operation.newand, args)
self
end
def true?
@arguments.inject(false) do |result, operation|
case operation.name
when r then result or @target.send(@method,
*operation.arguments)
when :and then result and @target.send(@method,
*operation.arguments)
else @target.send(@method,
*operation.arguments)
end
end
end
end
# For now let's add a new method that will behave like I want.
class OddRecognizer
def mknows?(*args)
BooleanEvaluator.new(self, :knows?, *args)
end
end
# Let's test it.
describe OddRecognizer do
before :each do
@recognizer = OddRecognizer.new
end
it "should return false for 1 or 3 or 5" do
@recognizer.mknows?(1).or?(3).or?(5).true?.should be_false
end
it "should return true for 1 or 3 or 6" do
@recognizer.mknows?(1).or?(3).or?(6).true?.should be_true
end
# Here lies the problem: in ruby, everything that is not nil nor false
evaluates
# as true in conditional expressions.... Is there any way to modify
BooleanEvaluator
# (or implement it in a different way) to make this work? I don't
think so,
# but maybe there is a way to implement something more close to the
thing I want.
it "should return true for 1 or 3 or 6 without having to call true at
the end" do
pending "Impossible in ruby?" do
@recognizer.mknows?(1).or?(3).or?(5).should be_true
end
end
end
# Gist Paste Clone URL: git://gist.github.com/5603.git
# [Impossible?] CHALLENGE: See pending spec at the bottom
#
# PROBLEM: I want to replace statements like this:
#
# puts (OddRecognizer.new.knows?(1) or OddRecognizer.new.knows?(3)) ?
"there are odds" : "there is no odd"
#
# With something like this:
# puts OddRecognizer.new.knows?(1).or?(3) ? "there are odds" : "there
is no odd"
#
# OddRecognizer is just a trivial class just to prove my concept
class OddRecognizer
def knows?(value)
(value % 2) == 0
end
end
require 'rubygems'
require 'spec'
describe OddRecognizer do
before :each do
@recognizer = OddRecognizer.new
end
it "should recognize 2" do
@recognizer.knows?(2).should be_true
end
it "should not recognize 3" do
@recognizer.knows?(3).should be_false
end
end
# Here's the implementation
class BooleanEvaluator
Operation = Struct.new :name, :arguments
def initialize(target, method, *args)
@target, @method = target, method
@arguments = Array.new << Operation.newfirst, args)
end
def or?(*args)
@arguments << Operation.newor, args)
self
end
def and?(*args)
@arguments << Operation.newand, args)
self
end
def true?
@arguments.inject(false) do |result, operation|
case operation.name
when r then result or @target.send(@method,
*operation.arguments)
when :and then result and @target.send(@method,
*operation.arguments)
else @target.send(@method,
*operation.arguments)
end
end
end
end
# For now let's add a new method that will behave like I want.
class OddRecognizer
def mknows?(*args)
BooleanEvaluator.new(self, :knows?, *args)
end
end
# Let's test it.
describe OddRecognizer do
before :each do
@recognizer = OddRecognizer.new
end
it "should return false for 1 or 3 or 5" do
@recognizer.mknows?(1).or?(3).or?(5).true?.should be_false
end
it "should return true for 1 or 3 or 6" do
@recognizer.mknows?(1).or?(3).or?(6).true?.should be_true
end
# Here lies the problem: in ruby, everything that is not nil nor false
evaluates
# as true in conditional expressions.... Is there any way to modify
BooleanEvaluator
# (or implement it in a different way) to make this work? I don't
think so,
# but maybe there is a way to implement something more close to the
thing I want.
it "should return true for 1 or 3 or 6 without having to call true at
the end" do
pending "Impossible in ruby?" do
@recognizer.mknows?(1).or?(3).or?(5).should be_true
end
end
end