# Smalltalk's favorite Boolean method

**URL:** <https://www.ruby-forum.com/t/smalltalks-favorite-boolean-method/57497>\
**Category:** Ruby\
**Created:** [April 11, 2006, 3:13pm UTC](https://www.ruby-forum.com/t/smalltalks-favorite-boolean-method/57497 "2006-04-11T15:13:14Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![ruby-rider](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/76d3ee/32.png) [@ruby-rider](https://www.ruby-forum.com/u/ruby-rider)\
**Post date:** [April 11, 2006, 3:13pm UTC](https://www.ruby-forum.com/t/smalltalks-favorite-boolean-method/57497/1 "2006-04-11T15:13:14Z")

</div>

Hi,

For a long time I have been programming Smalltalk.  
Recently, Ruby “got me” and I was wondering how the  
famous ifTrue:ifFalse: could be added to the System.

1 = 2  
ifTrue:  
[Transcript show: “true!”]  
ifFalse:  
[Transcript show: “false!”]

So at least the following works but I was hoping that it would have the  
same elegance. “proc” was needed to create a real block instance.

* * *

def true.ifTrue\_ifFalse(trueBlock , falseBlock)  
trueBlock.call  
end

def false.ifTrue\_ifFalse(trueBlock , falseBlock)  
falseBlock.call  
end

(1==2).ifTrue\_ifFalse(  
proc { p “true!”},  
proc { p “false!”}  
)

(1!=2).ifTrue\_ifFalse(  
proc { p “true!”},  
proc { p “false!”}  
)

---

<div class="post-metadata">

**Author:** ![ruby-rider](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/76d3ee/32.png) [@ruby-rider](https://www.ruby-forum.com/u/ruby-rider)\
**Post date:** [April 11, 2006, 3:35pm UTC](https://www.ruby-forum.com/t/smalltalks-favorite-boolean-method/57497/2 "2006-04-11T15:35:34Z")

</div>

On Apr 11, 2006, at 8:13 AM, Ernest Micklei wrote:

> [Transcript show: “false!”]
> 
> So at least the following works but I was hoping that it would have  
> the  
> same elegance. “proc” was needed to create a real block instance.

Here’s an alternate syntax that does away with the need to call proc():

> > class Object  
> > def true?  
> > yield self if self  
> > self  
> > end  
> > def false?  
> > yield self unless self  
> > self  
> > end  
> > end  
> > =\> nil
> 
> > (1 == 2).true? { puts “True!” }.false? { puts “False!” }  
> > False!  
> > =\> false
> 
> > (1 != 2).true? { puts “True!” }.false? { puts “False!” }  
> > True!  
> > =\> true

Hope that gives you some fresh ideas.

James Edward G. II

---

<div class="post-metadata">

**Author:** ![ruby-rider](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/76d3ee/32.png) [@ruby-rider](https://www.ruby-forum.com/u/ruby-rider)\
**Post date:** [April 11, 2006, 5:26pm UTC](https://www.ruby-forum.com/t/smalltalks-favorite-boolean-method/57497/3 "2006-04-11T17:26:20Z")

</div>

James Edward G. II [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> =\> nil
> 
> > > (1 == 2).true? { puts “True!” }.false? { puts “False!” }  
> > > False!  
> > > =\> false  
> > > (1 != 2).true? { puts “True!” }.false? { puts “False!” }  
> > > True!  
> > > =\> true
> 
> Hope that gives you some fresh ideas.

_hears 1000 functional programmers whine about return values getting  
lost_

---

<div class="post-metadata">

**Author:** ![ruby-rider](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/76d3ee/32.png) [@ruby-rider](https://www.ruby-forum.com/u/ruby-rider)\
**Post date:** [April 11, 2006, 6:57pm UTC](https://www.ruby-forum.com/t/smalltalks-favorite-boolean-method/57497/4 "2006-04-11T18:57:52Z")

</div>

On Apr 11, 2006, at 10:24 AM, Christian N. wrote:

> > > > end
> 
> _hears 1000 functional programmers whine about return values  
> getting lost_

I didn’t say I _liked_ it. I just said it got rid of the need to  
call proc() twice. A boring if statement is all I need. 😉

James Edward G. II

---

<div class="post-metadata">

**Author:** ![ruby-rider](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/76d3ee/32.png) [@ruby-rider](https://www.ruby-forum.com/u/ruby-rider)\
**Post date:** [April 11, 2006, 9:25pm UTC](https://www.ruby-forum.com/t/smalltalks-favorite-boolean-method/57497/5 "2006-04-11T21:25:42Z")

</div>

Christian N. wrote:

> _hears 1000 functional programmers whine about return values getting  
> lost_

Just so all those functional programmers don’t lose their return values:

* * *

class Object  
def true?  
TrueValue.new(yield)  
end  
def false?  
TrueValue.new(nil)  
end  
end

class FalseClass  
def true?  
FalseValue.new(nil)  
end  
def false?  
FalseValue.new(yield)  
end  
end

class NilClass  
def true?  
FalseValue.new(nil)  
end  
def false?  
FalseValue.new(yield)  
end  
end

class BooleanValue  
attr\_reader :value  
def initialize(val)  
@value = val  
end  
def true?  
self  
end  
def false?  
self  
end  
end

class TrueValue \< BooleanValue  
def true?  
TrueValue.new(yield)  
end  
end

class FalseValue \< BooleanValue  
def false?  
FalseValue.new(yield)  
end  
end

require ‘test/unit’  
class TestTrueFalse \< Test::Unit::TestCase  
def test\_false\_results  
assert\_equal nil, false.true? { no }.value  
assert\_equal yes, false.true? { no }.false? { yes }.value  
assert\_equal yes, false.false? { yes }.value  
assert\_equal yes, false.false? { yes }.true? { no }.value  
end

def test\_nil\_results  
assert\_equal nil, nil.true? { no }.value  
assert\_equal yes, nil.true? { no }.false? { yes }.value  
assert\_equal yes, nil.false? { yes }.value  
assert\_equal yes, nil.false? { yes }.true? { no }.value  
end

def test\_true\_results  
assert\_equal yes, true.true? { yes }.value  
assert\_equal yes, true.true? { yes }.false? { no }.value  
assert\_equal nil, true.false? { no }.value  
assert\_equal yes, true.false? { no }.true? { yes }.value  
end

def test\_object\_results  
assert\_equal yes, “hi”.true? { yes }.value  
assert\_equal yes, “hi”.true? { yes }.false? { no }.value  
assert\_equal nil, “hi”.false? { no }.value  
assert\_equal yes, “hi”.false? { no }.true? { yes }.value  
end

def test\_true\_true\_chains  
check\_chain(true, :true?)  
check\_chain(“hi”, :true?)  
assert\_equal nil, nil.true? { no }.true? { no }.value  
assert\_equal nil, false.true? { no }.true? { no }.value  
end

def test\_false\_false\_chains  
assert\_equal nil, “hi”.false? { no }.false? { no }.value  
assert\_equal nil, true.false? { no }.false? { no }.value  
check\_chain(nil, :false?)  
check\_chain(false, :false?)  
end

def check\_chain(value, method)  
i = 0  
assert\_equal 3,  
value.  
send(method) { i += 1 }.  
send(method) { i += 2 }.value  
assert\_equal 3, i  
end

def yes  
:yes  
end

def no  
fail “Should never execute this”  
end  
end

–  
– Jim W.

---

<div class="post-metadata">

**Author:** ![ruby-rider](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/76d3ee/32.png) [@ruby-rider](https://www.ruby-forum.com/u/ruby-rider)\
**Post date:** [April 12, 2006, 3:05pm UTC](https://www.ruby-forum.com/t/smalltalks-favorite-boolean-method/57497/6 "2006-04-12T15:05:54Z")

</div>

On Apr 11, 2006, at 2:25 PM, Jim W. wrote:

> Christian N. wrote:
> 
> > _hears 1000 functional programmers whine about return values getting  
> > lost_
> 
> Just so all those functional programmers don’t lose their return  
> values:

[Massive amount of code snipped]

Me thinks Jim W. is ether really smart or just has too much free  
time.  
🙂

Jim F.

---

<div class="post-metadata">

**Author:** ![ruby-rider](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/76d3ee/32.png) [@ruby-rider](https://www.ruby-forum.com/u/ruby-rider)\
**Post date:** [April 12, 2006, 7:17am UTC](https://www.ruby-forum.com/t/smalltalks-favorite-boolean-method/57497/7 "2006-04-12T07:17:18Z")

</div>

What about:

case (1 == 2)  
when true:  
p ‘true’  
when false:  
p ‘false’  
end

If you don’t like the ternary operator the above syntax is pretty clear.

Roy

---

<div class="post-metadata">

**Author:** ![ruby-rider](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/76d3ee/32.png) [@ruby-rider](https://www.ruby-forum.com/u/ruby-rider)\
**Post date:** [April 12, 2006, 5:07pm UTC](https://www.ruby-forum.com/t/smalltalks-favorite-boolean-method/57497/8 "2006-04-12T17:07:22Z")

</div>

Roy S. wrote:

> What about:
> 
> case (1 == 2)  
> when true:  
> p ‘true’  
> when false:  
> p ‘false’  
> end
> 
> If you don’t like the ternary operator the above syntax is pretty clear.

Ah Roy … You are spoiling the fun by being practical (insert big wink  
here).

Actually the point of the exercise is to demonstrate that if/then/else  
can be completely implemented in terms of polymorphic method sends  
without using an if statement (or ternary operator) in that  
implementation. It is kind of a theoretical point that conditional  
operations can be implemented with polymorphism (just as polymorphism  
can be implemented with condition primitives).

No one is advocating that this code be used in preference to Ruby’s  
natural if statement. We are just showing that it can be done fairly  
easily. (If you want a real challenge, try implementing the same in  
Java … same rules, no if statements allowed in the implementation. I  
managed it once, but I had to resort to using a Hash table for lookups).

The same can be done with looping constructs. Here’s an implementation  
of a “while” loop done entirely with polymorphic method calls. (Since  
while is a reserved word, I’m using ‘repeat’ instead)

Example Usage:

i = 0  
repeat { i \< 10 }.do { puts i; i += 1 }

Implementation:

alias repeat proc

class Proc  
def do(&block)  
call.false? { return nil }  
block.call  
self.do(&block)  
end  
end

Much simplier than the if thing, mainly because you generally don’t  
worry about return values from the while loop. Notice the use of tail  
recursion. If Ruby were properly tail recursive, that implementation  
would be adequate. But since we face the possibility of statck  
overflow, here’s a (slower) version without the overflow problem:

class Proc  
def do\_cc(&block)  
goto = nil  
callcc { |cc| goto = cc }  
call.false? { return nil }  
block.call  
goto.call  
end  
end

All in fun and games.

–  
– Jim W.
