From: Emmanuel Oga Date: 2008-08-16T02:27:58+09:00 Subject: Ruby: Boolean Challenge # 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.new(:first, args) end def or?(*args) @arguments << Operation.new(:or, args) self end def and?(*args) @arguments << Operation.new(:and, args) self end def true? @arguments.inject(false) do |result, operation| case operation.name when :or 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 -- Posted via http://www.ruby-forum.com/.