Saturday, February 12, 2011

Working with the Standard Library in Ruby

Aww yeah, lots of progress today! I got through chapter 6 and 7 of Beginning Ruby. Chapter 6 took me through making a basic text-based dungeon, including designing and manipulating classes for the dungeon, rooms inside of it and a player character. I also defined a means of navigating the dungeon.

However, when I said basic, I meant just that. It's just a four room dungeon with no easy way to get input from players and interpret that into changes in the dungeon itself. Apparently I won't be learning about collecting data until chapter 9. I'm getting impatient, since I've wanted to use variables defined by a user from the beginning, since it's obviously more practical than a static variable. All in good time, I suppose.

Chapter 7 was all about the require command, libraries and Ruby Gems.

Wrong Gem! Beginning Ruby walked me through installing and including various Gems. Easy enough!

The require command and why you'd want to use it is another concept that came easily to me. I find the more I learn about Ruby, the more I get why people like it so much. Some of the syntax itself gives me trouble, but the basic concepts are simple. Maybe that's true for most programming languages, but it's especially true for Ruby.

I did have a question about Ruby. Is code that is easier to read later usually preferable to code that's more efficient? I know a lot of things can be done on a single line, but are usually spread out over a few lines for readability. If I'm correct and readable code is typically preferred, is that unique to Ruby? Seems like it is.

7 comments:

  1. (Read/modify/maintain)ability is usually preferred, but try to steer clear of gross inefficiencies. You'll understand what these are as you continue.

    Keep in mind, the Ruby interpreter does not see code like a human. It's speed is only loosely correlated with number of lines, most important is what you're doing with those lines. It's very rare to try and squeeze functionality onto one line unless it is easier to read like that.

    The biggest place you'll see code squeezed onto one line is in multiple calls to array manipulation. Take this example which spans 4 lines.

    users = User.all
    addresses = users.map { |u| u.address.zip_code }
    zip_codes.uniq!
    zip_codes.sort!

    It is very common for Rails programmers to write this in a different form, which, once you're accustomed to it, is much more readable. Note this relies on ActiveSupport extensions being loaded.

    zip_codes = User.all.map(&:address).map(&:zip_code).uniq.sort

    But keep in mind, to the interpreter, these are roughly equivalent for a small number of users. As the number of elements in the array grows large (1000+), their differences become more apparent. Interestingly, the first version is probably much faster, as it calls only 1 block, and modifies arrays in place instead of creating new ones. Since it is very rare to deal with such a large number of items in Ruby, you should default to writing code that is easy to read for you, understanding that you may need to revisit it if the requirements change.

    ReplyDelete
  2. were you able to get the game to work? I keep getting a nomethod error for the detect method in this part of code.

    def find_room_in_dungeon(reference)
    @rooms.detect { |room| room.reference == reference }
    end

    The detect gets an error
    So it is supposed to basically go throw the array and pick the room that you refer to in the reference local variable.I am not sure what went wrong. tweet me @spencerpcooley if you can help

    ReplyDelete
  3. Spencer, that bit of code looks fine. So there are two likely ways to get that error to happen.

    1) @rooms is not set to anything at all. The error you get is because you're calling a method on nil. This could happen if you have accidentally mistyped the variable name @rooms elsewhere, say you called it @maze when you first initialized it.

    2) @rooms is set to something that doesn't support detect. This could happen if you accidentally wrote another value to @rooms. A simple way to test this theory is to add this line above the detect code.

    puts "@rooms = " + @rooms.inspect

    Now you'd be able to see if it was set to something other than an Array, but you'll still have to find the offending code.

    ReplyDelete
  4. @Spencer

    Seconding what Elijah said. I had similar errors, due to mistyping a variable. Are you running it from the command line or from a text editor? I was able to get basic functionality of the dungeon working and plan to come back and flesh the code out a bit more when I get a handle on this database thing.

    ReplyDelete
  5. The problem ended up being that I set the variable as @room and then I tried to use it as @rooms when I declared the find_room_in_dungeon method. I have been working through the book on my little netbook so I think my eyes were strained by the tiny screen. I am using command line by the way. Thanks for your help. I asked the same question on stack overflow and the author of the book ended up responding to it haha. Thought that was pretty cool. @tyler

    ReplyDelete
  6. @tyler do you have a twitter account?

    ReplyDelete
  7. @Spencer that is pretty cool! I've been working through Beginning Ruby since the middle of January and I love it. A great resource.

    I'm @illbzo1 on Twitter.

    ReplyDelete