General Assembly WDI, Week 4

Rubber ducks, Das Sound Machine, and spaceship operators.

Day 15

Monday was project presentation day: we each got five minutes to present our Tic-Tac-Toe games, and two minutes to field questions. I found myself strangely nervous—I was proud of what I had accomplished, but the thought of having to stand up and talk about it, justifying my decisions and explaining my approach, was terrifying.

The order of our presentations was randomized, and I drew one of the last slots, which gave me some time over lunch to open up a couple of different tabs and zoom in on a few things I wanted to talk about in my code—specifically, how I automatically logged users in when they signed up (this Stack Overflow question on passing additional data to AJAX callbacks, which I mentioned in my last weekly write-up, was helpful) and how I checked whether a game had been won or tied. I was proud of the first, and not so proud of the second—I still don’t think a Tic-Tac-Toe game should take 60 lines of code to figure out if it’s over, and near the top of my to-do list is streamlining this.

Taking the time to tee up a browser tab for each of my talking points helped the presentation go smoothly, and at the end, the instructors gave us each a rubber duck, then sent us home early to get some rest. All in all: a good day.

Day 16

Our assignment on Monday night was to walk through a couple of intro to Ruby tutorials and, if we had time, to read Why’s (Poignant) Guide to Ruby. It….

I….

It’s hard to describe.

You should probably read it for yourself.

And then, if it sparks your curiosity as much as it did mine, read Annie Lowrey’s 2009 piece for Slate, “Where’s _why?.”

I read the first half on Monday night and most of the second half on my phone while I was on the train on Tuesday morning, which didn’t in any way do this book justice. I think I need to go back and reread two or three more times at least, preferably on a large screen so I can properly appreciate the sidebars and illustrations.

Jumping into Ruby on Tuesday morning after working with JavaScript for the past year and PHP for several years before that felt like the Barden Bellas felt when they first saw Das Sound Machine.

A few initial notes/impressions (please don’t use these to teach yourself anything about Ruby—this is all Day One knowledge that may or may not be accurate/correct):

  • You don’t need parentheses to call a method without parameters in Ruby. You also don’t need them, even if you’re passing arguments, unless you want to use the results of that call immediately and chain on additional methods.
  • Ruby uses symbols, which, depending on where you read about them, are “lightweight strings,” “a string and a number,” or “the name of the variable, not the value of that variable.” My best shot at describing them: symbols represent a unique spot in memory. They have the same value everywhere in your program. They’re often used in class definitions.
  • Ruby doesn’t have an increment (++) operator. Use += 1 instead.
  • Floats and fixed numbers (integers) are distinct types in Ruby. 7 / 2 will return 3 in Ruby, not 3.5. If you want 3.5, you have to attach .to_f to either the 7 or the 3 before dividing.
  • .to_i truncates, it doesn’t round.
  • Ruby hashes do not allow you to access their keys through a dot notation; you must use square braces.
  • Ruby lets you access values from the end of an array: array[-1] will be the last element in the array.
  • a.equal?(b) will return true if and only if a is the same object in memory as a. Use .eql? to test if the values of a and b are the same.
  • Along the same lines, == is used to test whether values are equal. === is not used to test equality at all, but rather to test for inclusion (is a value in a particular range?). See this Stack Overflow question for details.
  • puts vs p vs print:
    • puts calls .to_s on an object, appends a new line, and prints it.
    • print calls .to_s on an object and prints it without appending a new line.
    • p calls .inspect on an object, appends a new line, and prints it. This can be helpful for debugging because it doesn’t automatically convert everything to a string.
  • Remember my excitement about fat arrow functions in JavaScript? Ruby uses the same symbol (=>) in hash definitions, only it’s called a “hash rocket.”

Day 17

  • More on symbols: Always use symbols as keys when writing hashes. Symbols perform better because Ruby compares them using their object IDs, instead of comparing strings letter by letter.
  • You can search for symbols using Symbolhound. No more frustrating Googling for the Paamayim Nekudotayim!
  • Ruby uses blocks instead of callbacks.
  • In JavaScript, all arguments are optional. JS will try to run the function even if you don’t provide the correct number of arguments. In Ruby, all named arguments are required. In other words: Ruby checks arity (the number of arguments or operands that the function takes); JS does not.
  • The exclamation point after an enumerable method in Ruby means that the method alters the original array.
  • All operators in Ruby are methods. 2 + 2 is the same thing as 2.+(2).

Day 18

We started talking more seriously about enumerables today.

  • Ruby has three basic types of ordered lists: hashes, arrays, and ranges.
  • All of these lists are enumerable, meaning they can take advantage of Ruby’s enumerable methods.
  • In Ruby, hashes have order (in most programming languages, they don’t).
  • In order to use these methods, a class must include the Enumerable module (include Enumerable) and define an each method.
  • Other things—files, for example—are also enumerable. Anything you can iterate over is an enumerable.

We also talked about classes.

  • Ruby is a “classical” language; this means that Ruby uses classes to define and instantiate new objects. JavaScript is a “prototypal” (not prototypical) language; it uses prototypes.
  • Ruby classes have an initialize method that acts like a JS Constructor function. The instance variables set within this method are private by default; “getter” and “setter” methods defined in the class provide access to these variables outside the class definition.
  • Ruby convention is for “getter” and “setter” methods to be named, respectively, propertyName and propertyName=. We can also use attr_reader :varname (getter), attr_writer :varname (setter), and attr_accessor :varname (getter & setter) to create simple versions of these methods.

Day 19

A high-level view of Ruby (made by Artem S.):

Ruby Core Object Model by Artem S.

And a handdrawn version by Jerome Dalbert:

Ruby Core Object Model by Jerome Dalbert

We talked a bit more about enumerables today, and introduced comparables: like enumerables in Ruby, comparables are anything that can be compared, that uses the comparable methods defined in the Comparable module, and that defines a <=> method (aka the “spaceship operator,” apparently so named because it reminded PERL expert Randal L. Schwartz of the spaceship in a Star Trek game).

We also talked briefly about how defining <=> on a comparable class allows you to use the .sort method, which made me wonder what Ruby’s built-in sorting method is. Fun fact: .sort_by in Ruby uses a Schwartzian transform, a sorting algorithm named after the aforementioned Randal L. Schwartz.

A few other notes:

  • Ruby has implicit returns: the last line is always what’s returned.
  • Ruby also has an implicit receiver: you don’t have to use self when you’re calling a getter method on an instance from within a class (though you do have to use it when calling a setter method).
  • super will call the same method defined in the parent or superclass and give you the result.
  • .new is a Class method that calls the Instance method .initialize. .new allocates memory for a new object, creates that object, calls .initialize, and returns the object.
  • self will point to one of three runtime contexts: global context, object context, or class context.
  • In Ruby documentation, # indicates an instance method, while . indicates a class method.
  • def methodname inside a class is how you define an instance method. def self.methodname inside a class is how you define a class method

To sum up

Everyone I know who uses Ruby tells me it’s orders of magnitude better than PHP. I’ve people clap their hands in glee when I told them I’d be learning Ruby as part of GA. I’m hoping to feel some of that excitement soon, but for now: