Learning Ruby in a Day

1334338573000 » Tagged as: religion , Ruby , Wordpress

I've made two previous attempts and learning Ruby and both attempts were total failures. This time I was determined to succeed and set myself a rather lofty goal of learning it in a day. Reading the Humble Little Ruby Book seemed like the way to go.  It's very generous of Jeremy McAnally to make this book available for free online reading. The book's got only 125 pages and I read novels of that length in an hour or two. So this should be easy.   In the end (well the day is not finished yet) I only got to page 35 before getting stuck on what appeared to me to be a weird way of threading. Consider what follows to be my %Qshort note. Hopefully someone coming to ruby from PHP, Javascript or Java might find it useful too.  

Strings

intersting is that “#{‘hello’ * n}” will result in hellohellohellohello. The only time that anyone can possibly find this sort of thing usefull is when creating horizontal lines in shell scripts (where they serve little purpose).

More useful is the fact that you can put complete expressions inside those curly braces which is going a bit beyond what you can do with PHP strings.

You can start a string with %q instead of single quotes, %Q is a substitute for double quotes, that might come in usefull if you are blogging about Ruby code with wordpress; which has a tendency to mess with your quotation marks.

A curious operation on strings is chop. It chops off the last character from the end. Whats curious isn't the operation but how it works. chop doesn’t modify the string unless you use chop!  The exclamation is not because I am surprised (I am), it's part of the code. More on this later

Collections

Arrays and Ranges

Ranges are defined like rng = 9..18 or 9...18 the second form the last number is not included in the range

=== is a comparision for ‘included in’  for example (rng === 10) asks the question 'is 10 included in the range'

Array indexing is C like but everything in the array need not be of the same type. Notation is javascript like. Which means you can create an empty array with [ ] or Array.new . To create an array filled with some elements try  a = [‘a’,’b’,5]

%w and %W are interesting ways for splitting strings into words eg  %W(you must be #{crazy*2}) produces 'you must be crazycrazy' as it's output. That's because upper case W is "double quote like  behavior", while lower case w is 'single quote like behaviour'

arrays have the .each method you find in jQuery hell, yeah!

You can convert a range to an array with the range.to_a method. This to_something is a recurring theme and even more forgettable than things like atoi, atol, strtol etc that you find in other languages.

Adding to an array is pretty much like the way it's done in javascript or PHP. However push can be used to add more than one element at a time. While a push of a single element is also equal to my_array << element

values_at() or using a range as the index can get you more than one item of the array. What interesting is fetch(elementNumber, ‘default value’) which can return a default value if the item is not in the array. This can lead to much shorter code since you don't need to check for the existence before hand.

Other useful functions like the ubiquitous pop() and shift() can be found in Ruby as well.

delete() takes a value and not an index unlike the others. That is the element that has the value is deleted. On the other hand delete_at() does take an index.

Hashes

Hashes use the ‘=>’ operator like in php associative arrays. For example myhash = {“key1”=>”value1”, “key2”=>value2, 3 => value5 } create a hash. Once  defined their behavior is like their PHP or javascript counterparts.

Deleting items from a hash is a bit different; it goes like this myhash.delete[‘key’] . If you are in a hurry, clear the whole thing with clear() . How to find out if a hash is empty? Well the question is the answer! What you don't get it? use the empty? method.

variables

Variable are references if you write var1= “bada” and var2 = var1 then both var1 and var2 point to the same item in memory. Like pointers in C. If you call any method on var1 or var2 (like chop! ) that makes a change, you will see that change effects both var1 and var2

if this is not the behaviour you wish for, you will have to use var2 = var1.dup instead

Interestingly though ‘!’ is not an operator here, it’s just that the ‘!’ is used as a convention by library developers to identify methods that modify the object itself. The same goes for ‘?

You can assign values in parallel like this a, b , c = 1, 2, 3

you can use #{variable} inside a double quoted string and the variables value will be substituted like the {$variable} in PHP

The ++ and -- operators are missing in ruby but no big loss I suppose. Also you can't do things like puts “foo” + bar + 123 instead you have to puts “bada” + bar.to_s + 123.to_s

Constants

Constants in Ruby, are identified by the fact that the variable name is made up of upper case letters. But constants are not really constants. Ruby only gives a warning and not an error if you try to change a constant! However you can use myvar.freeze to make anything into a constant. A real constant this time. It's unlike the ‘final’ declaration in Java cause you can do this at anytime but why anyone would want to do so for anything other than debugging is a mystery.

Blocks, Methods and Conditionals

blocks like in SQL have a begin and End, but then you don’t need to have a begin when you are declaring a method. Method declarions look like:

def my_method(param1, param2, …)

      some code

 end

Note that the elipsis here does not mean you can use variable number of arguments C style that’s just a notation I used. Ruby does however have variable number of arguments and it looks like this

def my_method(var1, var2, *var3)

The * here is not like the * in C but indicates variable args, call it like my_method(“val1”,”val2”,val3, 4, 9,12, 19) and so on . THe method seems var3 as an array

A method name should start with a lower case letter, not sure if that is a rule or merely a convention.

Ruby’s If looks like the if in most languages (parentheis optional). However if not is really ‘if not’ or you can call it unless. That’s right folks if(!variable) that you see often in C like languages  becomes ‘unless variable’

For assignment If, unelss can be collapsed eg: var = newval if var2 - var gets the new value only if var2 evaluates to true

The while has an opposite too, it’s until. But it’s until followed by end where as in other languages like SQL it’s Repeat followed by Until. In Ruby until really means while (not true)

Did I tell you that in Ruby Parenthesis are optional? well it goes for calling methods.

If a method modifies the object that called it, you need a ! (recall chop vs chop!) for example bada.setValue!(40) but there is more to it than that.

 If a method is querying an attribute, needs to end with ? (I suppose this is like the isValue() convention in beans)

Ruby has default values for parameters exactly like you get in PHP

Ruby methods can return multiple values like return 1,2,3 (ref parallel asignment above). If you don’t return a value the last value asigned is returned automatically!  so instead of ‘return value’ you can have ‘value’  !

Anonymous functions are allowed and you can use one where ever a parameter ca be used! for example myfunction.each { |this| some code here } and now curly braces is king! this is not predefined. Instead of {} you can use do / end if you want to

myvar = ["abc","cde","vde","qei"]

myvar.each begin |element|

  puts "A #{element}\n"

end

Proc is an object that is actually a method! you can do Proc.new { |param| some code with param } and pass it around! I suppose we could say this is akin to passing a pointer to a function in C. You need to call it with .call!

the lambda function apears to be same as Proc.new;  mymethod = lambda { |param1, param2| some code with param1 , param2 } but there is a big difference. Lambda does strict checking on the number of parameters.

It is always better to use Lambda instead of Proc.new because if you return from a Proc.new, you will actually be returning from the outer block as well! So the rest of the code in the outer method will not get executed. Both are said to be low on performance

Pointers to functions in C was bad enough but then often there is no other way of doing it. You can't say the same about Ruby so I wonder why things like this are even included (unless (I am already using unless (but can't quite give up the parenthesis)) the objective is to encourage unreadable code )

To borrow heavily from James McAnally's style of writing, I choked on 'implicit block usage' that seems like a pretty undigestable and hard to chew chicken bone but the night is still young.

If you are a die hard rubyist, please accept my appologies if what's written here (or the indentation (or the use of parenthesis)) made you puke.

comments powered by Disqus