A Zillion Ruby Kōans

NOTE: Because of formatting, I couldn’t have a curly bracket with a colon and an “o” or it turns up with some unavailable WordPress Emoticon URI. So thus I have changed items with this naming to :z_one and :z_two respectively.

Yup, still moving through all the Ruby Koans. There are, after all 276 of these things! 😉 So no more yapping, onto the notes and green lighting the tests. Cheers!

[sourcecode language=”ruby”]
def test_creating_hashes
empty_hash = Hash.new
assert_equal Hash, empty_hash.class
assert_equal({ }, empty_hash)
assert_equal 0, empty_hash.size
end

def test_hash_literals
hash = { :z_one => "uno", :z_two => "dos" }
assert_equal 2, hash.size
end

def test_accessing_hashes
hash = { :z_one => "uno", :z_two => "dos" }
assert_equal "uno", hash[:z_one]
assert_equal "dos", hash[:z_two]
assert_equal nil, hash[:doesnt_exist]
end
[/sourcecode]

From test_creating_hashes a Hash.new or {} both appear to create a new empty hash object. The second test creates and adds values to the hash. The third test has asserts that verify the data is inserted in the positions that are expected.

[sourcecode language=”ruby”]
def test_changing_hashes
hash = { :z_one => "uno", :z_two => "dos" }
hash[:z_one] = "eins"

expected = { :z_one => "eins", :z_two => "dos" }
assert_equal true, expected == hash

# Bonus Question: Why was "expected" broken out into a variable
# rather than used as a literal?
end
[/sourcecode]

Again, the hash is setup into the hash variable. Then the expected is setup in another variable. Since Ruby is pointer oriented, the expected variable is setup identical to the hash variable to assure that they truly are identical.

[sourcecode language=”ruby”]
def test_hash_is_unordered
hash1 = { :z_one => "uno", :z_two => "dos" }
hash2 = { :z_two => "dos", :z_one => "uno" }

assert_equal true, hash1 == hash2
end

def test_hash_keys
hash = { :z_one => "uno", :z_two => "dos" }
assert_equal 2, hash.keys.size
assert_equal true, hash.keys.include?(:z_one)
assert_equal true, hash.keys.include?(:z_two)
assert_equal Array, hash.keys.class
end

def test_hash_values
hash = { :z_one => "uno", :z_two => "dos" }
assert_equal 2, hash.values.size
assert_equal true, hash.values.include?("uno")
assert_equal true, hash.values.include?("dos")
assert_equal Array, hash.values.class
end
[/sourcecode]

test_hash_is_unordered shows that a hash, no matter the order the values are assigned, assigns them to the values that are directly set to.

[sourcecode language=”ruby”]
def test_combining_hashes
hash = { "jim" => 53, "amy" => 20, "dan" => 23 }
new_hash = hash.merge({ "jim" => 54, "jenny" => 26 })

assert_equal true, hash != new_hash

expected = { "jim" => __, "amy" => 20, "dan" => 23, "jenny" => __ }
assert_equal false, expected == new_hash
end
[/sourcecode]

This test asserts that the two different hashes are different, nothing amazing or odd there. The second part asserts that the next and expected hashes are different. Which again, is what we expect.

[sourcecode language=”ruby”]
def test_default_value
hash1 = Hash.new
hash1[:z_one] = 1

assert_equal 1, hash1[:z_one]
assert_equal nil, hash1[:z_two]

hash2 = Hash.new("dos")
hash2[:z_one] = 1

assert_equal 1, hash2[:z_one]
assert_equal "dos", hash2[:z_two]
end
[/sourcecode]

This test confirms that a hash with a request against a hash position that isn’t assigned to yet returns nil. The later two asserts show that a number compared to the hash position that contains a number compares as a number, and a string compared to a position that has a string also compares as equal.

Until next time, hack some koans.

Code Kōans

Recently (albeit it seems a few years after a lot of my fellow developers) I’ve dug into kōans. A kōan (Chinese 公案, Korean 공안, I had to put the symbols, but I just find them awesome 🙂 ) is a fundamental part of the history and lore of ZenBuddhism. It consists of a storydialogue, question, or statement, the meaning of which cannot be understood by rational thinking but may be accessible through intuition. The classic example is “Two hands clap and there is a sound; what is the sound of one hand?

The first set of koans I checked out (thanks to @Ang3lfir3) were the Clojure Kōans. I’ll admit, I had a slightly higher priority with Ruby so I grabbed the Ruby Kōans. I’ll get to the Clojure ones soon, as Clojure is a great language to work through and derive meaning through intuition. With that little intro, I’ll dive in…

The first file is absurdly easy, basically making sure reality exists in that true is true and true is not false. These seem pretty straight forward. When I got into the subsequent koan test files though, things started to get interesting. The Ruby Language itself started to show itself and how it actually works. When working through the koans, you’re actually working with real Ruby Unit Tests and code files. In my descriptions below I’ve cut those files up so I can comment in between each bit of code. I will however format each bit of code properly for readability. Cheers!

[sourcecode language=”ruby”]
class AboutObjects < EdgeCase::Koan
def test_everything_is_an_object
assert_equal true, 1.is_a?(Object)
assert_equal true, 1.5.is_a?(Object)
assert_equal true, "string".is_a?(Object)
assert_equal true, nil.is_a?(Object)
assert_equal true, Object.is_a?(Object)
end
[/sourcecode]

After running through this test, it’s a little obvious the point. Everything is an object. Get it? :O

[sourcecode language=”ruby”]
def test_objects_can_be_converted_to_strings
assert_equal "123", 123.to_s
assert_equal "", nil.to_s
end
[/sourcecode]

Ok, so I kind of feel that to_s is a bit silly for a method name, but whatever. I’m also assuming at this point that “nil” is a reserved object or something. I’m not sure what the assumption of nil is though, since it is an empty string, but sort of null, but not null, but maybe no value? I’ll just have to look this bit up later.

I did a search to dig this up and am even more confused now. I found this entry first, which would lead me to believe that nil is also a method on an object, but an object itself? Ok, I’ll read more later and move on to the next tests, maybe intuition will strike and I’ll all of a sudden realize what I’m working with here.

[sourcecode language=”ruby”]
def test_objects_can_be_inspected
assert_equal "123", 123.inspect
assert_equal "nil", nil.inspect
end
[/sourcecode]

The inspect method, seems simple enough. The method is or has a sort of default print out of what it is called under “inspection”. Ok, next…

[sourcecode language=”ruby”]
def test_every_object_has_an_id
obj = Object.new
assert_equal Fixnum, obj.object_id.class
end
[/sourcecode]

This is simple enough, every object gets an ID, whatever it may be. I’d bet it is unique, not that this test proves that. …I do wonder though, what exactly is Fixnum?

[sourcecode language=”ruby”]
def test_every_object_has_different_id
obj = Object.new
another_obj = Object.new
assert_equal true, obj.object_id != another_obj.object_id
end
[/sourcecode]

Ok, as I suspected, object IDs are unique. Got it.

[sourcecode language=”ruby”]
def test_some_system_objects_always_have_the_same_id
assert_equal 0, false.object_id
assert_equal 2, true.object_id
assert_equal 4, nil.object_id
end
[/sourcecode]

Umm. Yeah. Ok. That makes sense sort of. I’m now more confused about nil. It is 4, or null, or part of an enumeration? Who knows, who could tell from this test. I’ve got it though, false is zero, and two is true for some reason? I want to know what happened to one, which I suppose, is another thing I’ll have to intuit later. Onward!

[sourcecode language=”ruby”]
def test_small_integers_have_fixed_ids
assert_equal 1, 0.object_id
assert_equal 3, 1.object_id
assert_equal 5, 2.object_id
assert_equal 7, 3.object_id
assert_equal 9, 4.object_id
assert_equal 11, 5.object_id
assert_equal 13, 6.object_id
assert_equal 201, 100.object_id
# THINK ABOUT IT: 2x the number +1 == WTF? Why choose that?
# What pattern do the object IDs for small integers follow?
end
[/sourcecode]

Ok, I wanted to verify what the pattern was, so I actually added some asserts to this test. Hmmm, it appears, after adding the tests, that there is this nifty patter but I just can’t put my finger on it! 😉 (in case it isn’t evident, I’m being sarcastic here)

[sourcecode language=”ruby”]
def test_clone_creates_a_different_object
obj = Object.new
copy = obj.clone
assert_equal true, obj != copy
assert_equal true, obj.object_id != copy.object_id
end
end
[/sourcecode]

Ok, verified that object IDs stay unique upon creation or even cloning of new objects. This is an important thing to realize and understand within the overall design of Ruby. Enough for this short work through, more later, and again go and check out the Ruby Kōans yourself, they’re a lot of fun to work through.