From: Pierre Barbier de Reuille Date: 2006-03-26T21:26:27+09:00 Subject: Re: deciphering poignant guide chapter 4 example Hi, First, let me warn you that from what you describe, you have a Python viewpoint on the data structures and that it is quite different from many many languages. john_sips_tea@yahoo.com a �crit : > Hi, > > I'm reading through the poignant guide, and am a bit stuck at the end > of chapter 4 ( http://poignantguide.net/ruby/chapter-4.html ). It's > regarding the kitty_toys example: > > #!/usr/bin/ruby > > kitty_toys = [:shape => 'sock', :fabric => 'cashmere'] + [:shape => > 'mouse', :fabric => 'calico'] + [:shape => 'eggroll', :fabric => > 'chenille'] > > kitty_toys.sort_by { |toy| toy[:shape] }.each do |toy| puts "Blixy > has a #{ toy[:shape] } made of #{ toy[:fabric] }" end > > and I've actually got three sticking points with it: > > 1. For one thing, I don't understand the point of the ":shape" > syntax. I don't understand why the author doesn't just write the > string "shape" instead. What exactly is a "Symbol" object for? > > The poinant guide says it's just "words that look just like > variables". And "Symbols are lightweight strings." But that doesn't > help me much. The PickAxe 2nd ed, in chapter 3 says, "The construct > :artist is an expression that returns a Symbol object corresponding > to artist.", so, I can understand that (i.e. that there's some Symbol > class and we're getting an instance of it by using that notation), > but I'm still not getting the point... why not just use strings? What > does having "Symbols" buy the programmer? You can see symbols as read-only strings used to very quickly find informations in, for example, a hash table. The idea is to get an efficient implementation while keeping the code readable by human beings. As you seem to come from the Python's world, you probably know that Python's strings are immutable. And if you read a little bit about why strings in Python are immutable, you will see it's because they wanted to optimize the method lookup. Also you will learn that short Python's string are coded differently so that a simple integer lookup is used for method lookup. In the end, Python's string are what's called in Ruby Symbol and Ruby's strings have no equivalent in Python, as Python has no mutable string class. > > 2. Next up, why is > > kitty_toys = [:shape => 'sock', :fabric => 'cashmere'] + [:shape => > 'mouse', :fabric => 'calico'] + [:shape => 'eggroll', :fabric => > 'chenille'] > > supposed to be shorthand for > > kitty_toys = [ {:shape => 'sock', :fabric => 'cashmere'}, {:shape => > 'mouse', :fabric => 'calico'}, {:shape => 'eggroll', :fabric => > 'chenille'} ] > > How does that work? (Hmm... what does adding Arrays in Ruby mean > anyway? In Python it concatenates.) Why does this shorthand exist? > Hmm,.. it doesn't seem to be saving much finger typing... 3. Finally, > at the end of that example given in the poignant guide: > > #!/usr/bin/ruby > > # ... Create kitty_toys as shown above, then > > kitty_toys.sort_by { |toy| toy[:shape] }.each do |toy| puts "Blixy > has a #{ toy[:shape] } made of #{ toy[:fabric] }" end > > how does that "kitty_toys.sort_by" line work? I believe that braces > and "do ... end" are equivalent, so it looks to me like there's some > kind of "loop-in-a-loop" going on, as in: > > # Warning, Python code follows: for i in range(1, 8): for j in > range(1, 4): print i, j > > Is there a more verbose way of writing that kitty_toys snippet to > make it a bit more obvious what's going on? I mean, I guess the > sort_by method is probably looking for something to sort kitty_toys > on, and we're telling it to use what it finds in toy[:shape] for each > hash it iterates over, but then, is that next "each" looping over > items in a given hash, or ... gah. I'm not getting it. :) No, as said before, the sort_by returns an array ... which is further processed, so it more subsequent loops. You can expand it like that : sorted_kitty = kitty_toys.sort_by { |toy| toy[:shape] } sorted_kitty.each do |toy| [...] end The ruby equivalent of your python code would be : (1...8).each { |i| (1...4).each { |j| puts i,j} } > > Thanks, ---John >