What makes the Ruby language different from ColdFusion / CFML

I’m reading Why’s (Poignant) Guide to Ruby and I thought I’d jot down the language idioms that seem new or different to me, coming from a Java / ColdFusion background:

unless – the reverse if

A statement evaluated by unless will only execute if the statement evaluates to false:

operation_succeeded = false
unless operation_succeeded
   print "operation did not succeed" # will output to console!
end 

if statements can return a value:

at_hotel = true

email = if at_hotel
  "info@hotel.com"
else
  "info@home.ie"
end

print email << "\n"

The if statement will return the code that you run within the executed block, in this case info@hotel.com

Blocks are all over the shop

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

In this example each toy in turn in passed to the block (using |toy|) and the block replies to the method with a string, the shape (toy[:shape]) for that toy.
When this iteration is complete the sort_by method has seen all values and returns a new array – sorted!
In the example above, immediately after the sort block we’ve just done some method chaining to call a print statement on each item in the array using each.

Some new types and operators

Ranges for example, 100..200 is all the numbers between 100 and 200 inclusive. 100...200 is all the numbers between 100 and 199 (note the exclusion of the last number).

I’d seen === in JavaScript before where it used to check equality of value and type. But Ruby uses it as a not so strict comparison, such as in this example:

if 1894 === year
   "Born." 
 elsif 1895..1913 === year
   "Childhood in Lousville, Winston Co., Mississippi." 
 else
   "No information about this year." 
 end

In this case === will check to see if the year in the specified range. So it’s slightly different to JavaScript in this sense, but of course JavaScript doesn’t have built in ranges.

Collecting arrays – a more in depth example

This code in the guide had me perplexed for a while, but after a little bit of reading about the Array::shift method in the API docs, but becomes clear how this works. The cool stuff to note here is how we are extending the use of the String base class, using self to reference existing class methods, using class variables (@@) and of course using the collect method:

class String

   # The parts of my daughter's organ
   # instructor's name.
   @@syllables = [
     { 'Paij' => 'Personal',
       'Gonk' => 'Business',
       'Blon' => 'Slave',
       'Stro' => 'Master',
       'Wert' => 'Father',
       'Onnn' => 'Mother' },
     { 'ree'  => 'AM',
       'plo'  => 'PM' }
   ]

   # A method to determine what a
   # certain name of his means.
   def name_significance
     # create an array based on the - delimiter
     parts = self.split( '-' ) 
     # create a copy of the class variable - we will be modifying the copy
     syllables = @@syllables.dup 
     # for each part (and we presume there are two in total)...
     signif = parts.collect do |p| 
       # remove the first element (a hash) from the array 
       # and grab the value from that via the p key
       syllables.shift[p] 
     end
     # join the array into a list with a space between each element
     signif.join( ' ' ) 
   end

 end

I’ve added comments above, but the dumb thing I was doing was reading syllables.shift[p] as a method call with p as an argument! No, it is – of course – a call to the array method shift (which removes the first element from the array and returns it), and then we use p as the key to that returned element, which is of course a hash.

The difference between class and instance methods

This example shows the difference between creating an instance method (available for all instances of that class) and a class method which is invoked directly on the class:

class String

   #instance method
   def print_me
     puts self
   end

 end


class << String

   # class method
   def say_hi
     puts "hi!"
   end

end

#test

s = "Ireland win the rugby."

s.print_me     # prints "Ireland win the rugby."
s.say_hi       # error: undefined method 'say_hi'
String::say_hi # prints 'hi!'

While this is possible in Java, it’s not possible at all in ColdFusion.

Symbols, :these :strange :strings

:my_symbol # create a symbol

puts :my_symbol #it seems to be a string 

:my_symbol = "some_value" # error: can't assign like regular string

# symbols are created once and once only
puts :my_symbol.object_id.to_s #109218

# but a string of the same value can be created many times
string1 = "key"
string2 = "key"
puts string1.object_id.to_s #-607851318
puts string2.object_id.to_s #-607851328

# LESSON: symbols are not like regular strings!

def print_symbol

    puts :my_symbol #the symbol can be seen in here!

    :another_symbol # define another symbol
    puts :another_symbol
    puts :another_symbol.object_id.to_s

end

# print the symbol
print_symbol # symbols are global so the the value will be printed

puts :another_symbol # despite being created inside the method this symbol is available outside
puts :another_symbol.object_id.to_s # and it has the same id, i.e. it IS the same

# LESSON: symbols are global

The explanation of symbols is that they are lightweight string or labels for hash keys or method arguments. They are global and they cannot be changed at runtime. ColdFusion has nothing like this in the toolkit.
The benefit of symbols is that they can bring a performance benefit to larger applications as the symbols are reused by the entire application and treated as string labels. You’ll see this a lot in Ruby on Rails. More info and a more in-depth explanation can be found here.

Conclusion

There are some really different language idioms are work in Ruby when compared to ColdFusion. I really like some of the ‘syntactic sugar’ you get and we have seen some of these creeping into other languages (especially the idea of blocks – also called closures in other languages). Here is a discussion of closures for ColdFusion.

I think it’s really worthwhile exploring what other languages offer their developers – I think it makes you a more thoughtful and better programmer.

Advertisements
This entry was posted in Uncategorized and tagged , , , . Bookmark the permalink.

2 Responses to What makes the Ruby language different from ColdFusion / CFML

  1. Pingback: What makes the Ruby language different from ColdFusion / CFML … » WB Tips

  2. Cass Pei says:

    Thank you!
    Those are the things that I always forget to remember~~

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s