Ruby is a fun language, but here are a few things that tripped up this n00b whilst stumbling along the learning curve.
Why does string[n] return an integer character code instead of the character? Well, Ruby has no such thing as a character (prior to 2.0, anyway?), so then why not a string of length 1?
>> a = "asdf" => "asdf" >> a[0] => 97
Either of these works, although they look a little funny:
>> a[0...1] => "a" >> a[0..0] => "a"
Also, a[0].chr works. The integer.chr method is described as follows:
int.chr => string Returns a string containing the ASCII character represented by the receiver‘s value.
It's non-obvious how to iterate through the characters of a string. The string.each_char is listed in the Ruby core 1.8.6 ruby-docs, but, confusingly, you have to require "jcode" for it to work. Maybe I'm just confused about whether core means "loaded by default" or "included in the Ruby distribution".
Two toString methods?In place of object.toString() Ruby has two methods: to_s and inspect. When coercion to a string is required, to_s is called. Docs for inspect say this:
Returns a string containing a human-readable representation of obj. If not overridden, uses the to_s method to generate the string.
If, then, else, elsif
If statements are confusing...
if x==123 then puts 'wazoo' end # then is optional, as long as you have the line break if x==123 puts 'wazoo' end
For one liners, then is required. Or colon, if you prefer.
if x==123 then puts 'wazoo' end if x==123 : puts 'wazoo' end
Curly braces seem not to work at all for if statements. For more curly brace related philosophy and WTFs see this issue. DON'T DO THIS:
if x==123 { puts 'qwer' }
Finally, would someone tell all these languages that crawl out of the primordial Bourne-shell ooze that neither elif nor elsif means jack shit in the english language?!?!?! (sputter... rant... fume...)
if x==123 puts 'wazoo' elsif x==456 puts 'flapdoodle' else puts 'foo' end
An if statement is an expression and returns a value, but ruby also offers the good old ternary operator.
Require vs. Load
There are two ways to import code in Ruby, require and load. See the ruby docs for Kernel (require and load).
Defined? and nil?
Ruby has nil instead of null. Ok, and unlike Java's null, nil is a real object. I appreciate the difference between nil and undefined, but I wouldn't have guessed that defined? nil would return "nil". Not to be confused with a truly undefined variable, in which case defined? asdf returns nil. The pickaxe book explains the other strange return values of defined?. Then, there's nil?.
>> asdf.nil? NameError: undefined local variable or method `asdf' for main:Object from (irb):47 from :0 >> asdf = nil => nil >> asdf.nil? => true
Command line arguments
Just the array ARGV. Not a quirk. Good.
Return
Return behaves oddly; to exit a script you use Kernel::exit(integer). Trying to return 1 instead causes a LocalJumpError whatever that means?? Trying to return from a code block returns from the surrounding context. That hurts my head.
Ruby Exception Handling
Ruby's equivalent of try-catch-finally is begin-rescue-ensure-end.
No Boolean
There's no Boolean class in Ruby. Instead, there's TrueClass and FalseClass. So, what type of value does the logical expression p ^ q produce? Everything has an implicit boolean value, which is true for everything except false and nil.
List operations
(see also Array and Enumerable)
Ruby 1.9 has addressed some of this. There is now some syntactic sugar that at least emulates true named parameters.
ReplyDeleteAlso, the list of what's changed says:
Strings are also no longer enumerable, and no longer support each, which is replaced by the each_line and each_byte methods.
This change also seems to have affected each_char, which does what it is supposed to do with no requires required.
And it has a new VM, new regex engine, and it's faster. Whoohoo.