March 4, 2008, 6:59:31 pm
My colleague Andre's just posted an interesting experiment where DNU returns ^self and you attempt to do a boolean test on it. #mustBeBoolean runs through the DNU and returns self - yet the boolean test actually goes down the ifTrue: path instead of simply exploding.
He discovered the reason for this is that the bytecode is a false test, so since the resulting object isn't false it runs the true side of the equation. This is an interesting demonstration of "catching the VM out" .. instead of running the true side, a VM that isn't cheating and optimizing boolean tests should go in to an infinite loop.
Pondering this behavior, I suddenly wondered if I could simply implement mustBeBoolean on Object and UndefinedObject to return ^true and ^false and if that would immediately mean we could do boolean tests like they do in Ruby, Python, Perl.
Number>>mustBeBoolean ^self isZero not
Collection>>mustBeBoolean ^self notEmpty
The result is that you can send ifTrue:, ifFalse:, ifTrue:ifFalse: to any object and if it is nil, 0 or empty it will act as 'false' otherwise it will act as 'true'.
Eg: nil ifTrue: [self halt] ifFalse: . #() ifTrue: [self halt] ifFalse: . Object new ifTrue:  ifFalse: [self halt]. 0 ifTrue: [self halt] ifFalse: . 12 ifTrue:  ifFalse: [self halt].
I was surprised this worked, but sort of delighted too because it may actually prove useful and is reasonably backward compatible with the existing environment - in otherwords, it's generally considered a bug to do a boolean test on a non-boolean so people don't have their code do that.
I've published this hack in to public store as Oooleans - Booleans and Objects combined. I've also published Oooleans-Tests to make sure it behaves as expected. This was an interesting experiment and I'm pondering the implications. Naturally, having code run this way is a little inefficient.. but less failure is a good thing right?
By on March 4, 2008, 9:37:44 pm
By on March 4, 2008, 9:38:38 pm
By Michael Lucas-Smith on March 5, 2008, 12:19:18 am
By Antony Blakey on March 5, 2008, 1:10:06 am
By John M McIntosh on March 5, 2008, 6:12:16 am
By Bert Freudenberg on March 5, 2008, 6:12:38 am
By Ken Treis on March 6, 2008, 11:52:04 am
By nicolas cellier on March 6, 2008, 5:21:18 pm
By Michael Lucas-Smith on March 7, 2008, 2:30:37 am