[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Ruby: Boolean Challenge

Emmanuel Oga

8/15/2008 5:28:00 PM

# Paste url: http://gist.githu...
# 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-....

11 Answers

Emmanuel Oga

8/15/2008 5:32:00 PM

0

Errata:

Instead of:

puts (OddRecognizer.new.knows?(1) or OddRecognizer.new.knows?(3)) ?
"there are odds" : "there is no odd"

First example should be

recognizer = OddRecognizer.new
puts (recognizer.knows?(1) or recognizer.knows?(3)) ? "there are odds"
: "there is no odd"

That needs to be changed to:

puts OddRecognizer.new.knows?(1).or?(3) ? "there are odds" : "there is
no odd"

--
Posted via http://www.ruby-....

Patrick Li

8/15/2008 5:53:00 PM

0

heh...
this will work... but i wouldn't suggest using it for anything other
than intellectual enjoyment.

class FalseOddRecognizer < NilClass
//#same methods as TrueOddRecognizer
end

class TrueOddRecognizer
//#same methods as before
end

Now, in knows(), return a FalseOddRecognizer when false and a
TrueOddRecognizer on true.

The trick is that Ruby evaluates all subclasses of NilClass to false.

--
Posted via http://www.ruby-....

Emmanuel Oga

8/15/2008 6:04:00 PM

0

> The trick is that Ruby evaluates all subclasses of NilClass to false.

The problem is that, if I extend NilClass, I wont be able to use new
anymore

class Test < NilClass; end;

Test.new # NoMethodError: undefined method `new' for Test:Class


--
Posted via http://www.ruby-....

David A. Black

8/15/2008 6:11:00 PM

0

Hi --

On Sat, 16 Aug 2008, Emmanuel Oga wrote:

> # Paste url: http://gist.githu...
> # 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

Do you mean EvenRecognizer?


David

--
Rails training from David A. Black and Ruby Power and Light:
* Advancing With Rails August 18-21 Edison, NJ
* Co-taught by D.A. Black and Erik Kastner
See http://www.r... for details and updates!

Adam Shelly

8/15/2008 6:19:00 PM

0

On 8/15/08, Emmanuel Oga <oga_emmanuel_oga@yahoo.com.ar> wrote:

> 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
>
Maybe I'm dense, but if the recognizer knows 2 but not 3 ... doesn't
that make it an EvenRecognizer?

I know this doesn't effect the fundamental problem, but the examples
might be easier to understand if the names were consistent.

Gordon Thiesfeld

8/15/2008 6:21:00 PM

0

On Fri, Aug 15, 2008 at 1:04 PM, Emmanuel Oga
<oga_emmanuel_oga@yahoo.com.ar> wrote:
>> The trick is that Ruby evaluates all subclasses of NilClass to false.
>
> The problem is that, if I extend NilClass, I wont be able to use new
> anymore
>
> class Test < NilClass; end;
>
> Test.new # NoMethodError: undefined method `new' for Test:Class
>
>
> --
> Posted via http://www.ruby-....
>
>


I'm not sure I understand what you're looking for, but this passes your specs.

http://gist.githu...

Actually, I think there was a typo on line 94.

- @recognizer.mknows?(1).or?(3).or?(5).should be_true
+ @recognizer.mknows?(1).or?(3).or?(6).should be_true

After I fixed that, it passes the specs.

Emmanuel Oga

8/15/2008 6:27:00 PM

0

Hi David

>> class OddRecognizer
>> def knows?(value)
>> (value % 2) == 0
>> end
>> end

> Do you mean EvenRecognizer?

True, I confused the two terms (even, odd). I tend to make that mistake,
I also then to confuse the words Tuesday and Thursday :)


--
Posted via http://www.ruby-....

Emmanuel Oga

8/15/2008 6:55:00 PM

0

> http://gist.githu...
>
> Actually, I think there was a typo on line 94.
>
> - @recognizer.mknows?(1).or?(3).or?(5).should be_true
> + @recognizer.mknows?(1).or?(3).or?(6).should be_true
>
> After I fixed that, it passes the specs.

Yes I had a couple of typos, I think I have fixed them now. I'm not sure
about your change though, but I think the last edit I made makes more
clear what I'm needing:

it "should return false for 1 or 3 or 5 without having to call true at
the end" do
pending "Impossible in ruby?" do
lambda do
# needed functionality is to remove last true? and make it work
anyway.
raise if @recognizer.mknows?(1).or?(3).or?(5)#.true?
end.should_not raise_error
end
end

P.S.: GIST RULES!!! :D

--
Posted via http://www.ruby-....

Patrick Li

8/15/2008 7:24:00 PM

0

Hey,
Sorry for the late reply: I was out to lunch:

I didn't know you can't instantiate NilClass.
Anyway here's a workaround involving singletons:

class OddRecognizer
def knows(num)
return self if num%2==0

o = nil
class << o
def or(num)
return self if num%2==1
return OddRecognizer.new
end
end
return o
end

alias :or :knows
end

It was an interesting question from a intellectual standpoint.
But I wouldn't touch this code with a ten foot pole. lol

-Patrick
--
Posted via http://www.ruby-....

Emmanuel Oga

8/15/2008 8:00:00 PM

0

> class OddRecognizer
> def knows(num)
> return self if num%2==0
> class << nil
> def or(num)
> return self if num%2==1
> return OddRecognizer.new
> end
> end
> nil
> end
>
> alias :or :knows
> end

Patrick:

that sure works, the problem is that nil is extended with a or method
that is not very intuitive for it...

>> nil.or(2)
=> #<OddRecognizer:0xb7a626bc> what the ·$%!$%!$%@!!!!

Code pollution at is maximum expression hahaha

I thought of doing something like that with false instead of nil, but
is the same problem. And you can't dup nil true nor false obviously :)

> It was an interesting question from a intellectual standpoint.
> But I wouldn't touch this code with a ten foot pole. lol

Hahaha I agree.
--
Posted via http://www.ruby-....