Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Ruby for C# Geeks : Page 3

As good as C# is, it's not always the best language for simple tasks. Enter Ruby, an interpreted, dynamically typed language that enables simple tasks with simple code.


advertisement
The Ruby vs. C# Feature Rundown
The following is a simple example program in Ruby that demonstrates a variety of the features often seen in C# programs. (It's another "classic" example program used in many programming tutorials.) It is chock full of new stuff I haven't discussed yet, but I'll explain the entire program snippet by snippet afterwards. If it's still opaque after that, fear not because I provide a structurally similar C# version so you can compare lines for yourself:

#gessnum.rb class Game def initialize(maxNum) @num = rand(maxNum) puts ["\n\nMagic Number Game!\n", "------------------\n\n", "I'm thinking of a magic number between 0 and #{maxNum}\n", "Would you like to guess my number? (y/n) [n]:"] playNow = gets or "n" if playNow.chop == "y" play else puts "OK, Bye!" end end def play loop do # infinite loop! puts "\nNumber?!?" attempt = gets or break case attempt.to_i <=> @num when 1 # attempt > @num puts "Guess Lower!" when -1 # attempt < @num puts "Think Bigger, Mac." else # only have == left... so... puts "Spot on! That's it! Bye!" break # hop out of our loop! end end end end Game.new(100)

Here's a sample run:



C:\proj\ruby>ruby sample.rb Magic Number Game! ------------------ I'm thinking of a magic number between 0 and 100 Would you like to guess my number? (y/n) [n]: y Number?!? 50 Guess Lower! Number?!? 25 Think Bigger, Mac. Number?!? 37 Spot on! That's it! Bye!

At the very beginning of the code, I define a class. Notice how it's just the word "class" followed by the class name—no curly anything, and I haven't set a namespace.

The Game class contains two methods: initialize, the constructor, and play, the main body of the game. Methods are designated simply by the def keyword, and are terminated by the end keyword. In Ruby, all constructors are called initialize, and they are called when an object is instantiated (more on this in a minute).

The following snippet designated a variable called @num in the constructor. The variable was set to a random number between 0 and maxNum:

@num = rand(maxNum)

Any variable inside a class that starts with a @ sign is known as an instance variable (like a field in C#). Just like in C#, the default for an instance variable is to be private, meaning that folks outside the class cannot see it or read its value. Why would I bother putting it in a field instead of a local variable? Well, for the same reasons that I'd do so in C#; I need to access it from other methods, namely the play method.

This command printed an array as a string:

puts ["\n\nMagic Number Game!\n", "------------------\n\n", "I'm thinking of a magic number between 0 and #{maxNum}\n", "Would you like to guess my number? (y/n) [n]:"]

It's much easier to just declare an array of strings and issue a single puts command for it to make a puts for each one.

The #{maxNum} portion is a Ruby trick known as string interpolation. The value of maxNum will be substituted for the occurrence of #{maxNum} in the string. This is roughly analogous to the String.Format() idiom in C#.

I set the value of a local variable 'playNow' to the result of the gets function, which reads a string from the input stream:

playNow = gets if playNow.chop == "y" play else puts "OK, Bye!" end

I had to compare playNow to "y" (for yes) to make sure the user actually wants to play the game. But wait, you say, what's that .chop business? That extension will drop the last character from the value, which would be the newline character, because gets records the newline generated by the enter key when it reads the input stream. So, if the program gets a "y" it invokes the play method, otherwise it kindly says goodbye.

Normally, trying to run code from within the constructor may not be such a great idea or most objects, but for the sake of this paltry example game, it's no big deal:

def play loop do # infinite loop! puts "\nNumber?!?" attempt = gets or break case attempt.to_i <=> @num when 1 # attempt > @num puts "Guess Lower!" when -1 # attempt < @num puts "Think Bigger, Mac." else # only have == left... so... puts "Spot on! That's it! Bye!" break # hop out of our loop! end end end

The play method is an infinite loop, meaning that it will continue to execute until the process is terminated or something inside the loop issues a break statement. I prompt the user for a number and store it in the local variable attempt.

The next bit is a little strange for a C# fan, but it actually is not all that different from a switch statement. The expression it is case-ing on (switching on) is attempt.to_i <=> @num. The first part, attempt.to_I, converts the string value attempt to an integer. (The Ruby class of objects holding small integer values is actually called Fixnum.) It's a built-in method of the %(String) class, which itself is a built-in type. The <=> operator is analogous to the C# idiom of CompareTo(). If the values are equal, <=> returns the integer 0. If the left is less than the right, an integer value of -1 is returned, and a 1 is returned if the left side of the expression is greater than the right. Basically, this is a switch for the three possible values, but instead of the C# way (switch… case), it's the Ruby way (case…when):

The very last line is the actual body of the main program:

Game.new(100)

The only thing that happens here is that an instance of the Game class is created by calling the .new method with the parameter of 100. In Ruby, .new is a special method that will invoke the initialize method, the constructor of the object. Notice the object isn't assigned. Nobody needs to see the object, so it's not stored.



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap