Ruby Programming/Data types

Ruby Data Types
As mentioned in the previous chapter, everything in Ruby is an object. Ruby has 8 primary data types and 3 more data types derived from the Numeric superclass. Everything has a class. Don't believe me? Try running this bit of code: displays

See? Everything is an object. Every object has a method called class that returns that object's class. You can call methods on pretty much anything. Earlier you saw an example of this in the form of. (Technically when you call a method you're sending a message to the object, but I'll leave the significance of that for later.) Something that makes this extreme object oriented-ness very fun for me is the fact that all classes are open, meaning you can add variables and methods to a class at any time during the execution of your code. This, however, is a discussion of datatypes.

Constants
We'll start off with constants because they're simple. Two things to remember about constants: 1. Constants start with capital letters. Constant is a constant. constant is not a constant. 2. You can change the values of constants, but Ruby will give you a warning. (Silly, I know... but what can you do?) Congrats. Now you're an expert on Ruby constants.

Symbols
So did you notice something weird about that first code listing? "What the heck was that colon thingy about?" Well, it just so happens that Ruby's object oriented ways have a cost: lots of objects make for slow code. Every time you type a string, Ruby makes a new object. Regardless of whether two strings are identical, Ruby treats every instance as a new object. You could have "live long and prosper" in your code once and then again later on and Ruby wouldn't even realize that they're pretty much the same thing. Here is a sample irb session which demonstrates this fact:

irb> => -507772268 irb> => -507776538

Notice that the object ID returned by irb Ruby is different even for the same two strings.

To get around this memory hoggishness, Ruby has provided "symbols." s are lightweight objects best used for comparisons and internal logic. If the user doesn't ever see it, why not use a symbol rather than a string? Your code will thank you for it. Let us try running the above code using symbols instead of strings:

irb> => 150808 irb> => 150808 

Symbols are denoted by the colon sitting out in front of them, like so:

Hashes
Hashes are like dictionaries, in a sense. You have a key, a reference, and you look it up to find the associated object, the definition.

The best way to illustrate this, I think, is with a quick demonstration: displays

I could have also written this like so: This code cycles through each element in the hash, putting the key in the  variable and the value in the   variable, which is then displayed

I could have been more verbose about defining my hash; I could have written it like this:

If I felt like offing Luke, I could do something like this: Now Luke's no longer in the hash. Or lets say I just had a vendetta against farmboys in general. I could do this: This iterates through each key-value pair and deletes it, but only if the block of code following it returns. In the block I made the value lowercase (in case the farmboys decided to start doing stuff like "FaRmBoY!1!") and then checked to see if "farmboy" matched anything in its contents. I could have used a regular expression, but that's another story entirely.

I could add Lando into the mix by assigning a new value to the hash:

I can measure the hash with. I can look at only keys with the  method, which returns the hash's keys as an. Speaking of which...

Arrays
s are a lot like es, except that the keys are always consecutive numbers, and always starts at 0. In an  with five items, the last element would be found at   and the first element would be found at. In addition, all the methods that you just learned with es can also be applied to  s.

Here are two ways to create an : As you may have guessed, the  operator pushes values onto the end of an. If I were to write  after declaring those two  s the output would be. Of course, if I felt like simultaneously getting  and deleting it from the array, I could just   it off. The  method returns the last element in an array and then immediately removes it from that array: Then  would hold   and   would be an element shorter. If I kept doing this, array2 wouldn't hold any elements. I can check for this condition by calling the  method. For example, the following bit of code moves all the elements from one  to another: Here's something that really excites me: s can be subtracted from, and added to, each other. I can't vouch for every language that's out there, but I know that Java, C++, C# and perl would all look at me like I was a crazy person if I tried to execute the following bit of code:

After that code is evaluated, all of the following are true:
 * contains all of the elements that  did, except the ones that were also in.
 * All the elements of, minus the elements of  , are now contained within.
 * now contains all the elements of both  and.

You may search for a particular value in variable  with the   method:

If you just wanted to turn the whole  into a , you could: If array2 had the value that we declared in the last example, then  's value would be

We could have called the  method without any arguments: 's value would now be

Strings
I would recommend reading the chapters on strings and alternate quotes now if you haven't already. This chapter is going to cover some pretty spiffy things with s and just assume that you already know the information in these two chapters.

In Ruby, there are some pretty cool built-in functions where s are concerned. For example, you can multiply them: yields

s may also be compared: yields

The preceding evaluation is actually comparing the ASCII values of the characters. But what, I hear you ask, is the ASCII value of an given character? With ruby versions prior to 1.9 you can find the ASCII value of a character with: However, With Ruby version 1.9 or later that no longer works. Instead, you can try the  method: Either approach will display which is the ASCII value of A. Simply replace A with whichever character you wish to inquire about.

To perform the opposite conversion (from 65 to <tt>A</tt>, for instance), use the  method: displays

Concatenation works the same as most other languages: putting a  character between two  s will yield a new   whose value is the same as the others, one after another: yields

For handling pesky  variables without using the concatenate operator, you can use interpolation. In the following chunk of code,  , and   are identical:

If you need to iterate through (that is, step through each of) the letters in a  object, you can use the   method: Displays each letter in  (puts automatically adds a newline after each call): But what's with that weird " " thing in the parameter? That, my friend, is called a regular expression. They're helpful little buggers, quite powerful, but outside the scope of this discussion. All you need to know for now is that  is "regex" speak for "any one character." If we had used  then ruby would have iterated over each group of two characters, and missed the last one since there's an odd number of characters!

Another use for regular expressions can be found with the <tt>=~</tt> operator. You can check to see if a  matches a regular expression using the match operator,  : displays

The  method works much the same way, except it can accept a   as a parameter as well. This is helpful if you're getting regular expressions from a source outside the code. Here's what it looks like in action: Alright, that's enough about regular expressions. Even though you can use regular expressions with the next two examples, we'll just use regular old s. Lets pretend you work at the Ministry of Truth and you need to replace a word in a   with another word. You can try something like: Now  contains. But what if the  contains lots of lies like the one you just corrected? only replaces the first occurrence of a word! I guess you could iterate through the  using   method and a   loop, but there's a much more efficient way to accomplish this: Big Brother would be so proud! is the "global substitute" function. Every occurrence of " " has now been replaced with "<tt>Long live</tt>" so now <tt>winston</tt> is only proclaiming its love for Big Brother, not its disdain thereof. On that happy note, lets move on to s and  s. If you want to learn more about methods in the   class, look at the end of this chapter for a quick reference table.

Numbers (Integers and Floats)
You can skip this paragraph if you know all the standard number operators. For those who don't, here's a crash course. <tt>+</tt> adds two numbers together. <tt>-</tt> subtracts them. <tt>/</tt> divides. <tt>*</tt> multiplies. <tt>%</tt> returns the remainder of two divided numbers. Alright, integers are numbers with no decimal place. Floats are numbers with decimal places. <tt>10 / 3</tt> yields <tt>3</tt> because dividing two integers yields an integer. Since integers have no decimal places all you get is <tt>3</tt>. If you tried <tt>10.0 / 3</tt> you would get <tt>3.33333...</tt> If you have even one float in the mix you get a float back. Capisce? Alright, let's get down to the fun part. Everything in Ruby is an object, let me reiterate. That means that pretty much everything has at least one method. Integers and floats are no exception. First I'll show you some integer methods. Here we have the venerable <tt>times</tt> method. Use it whenever you want to do something more than once. Examples: This will print out the numbers 0 through 99, print out <tt>Guess what?</tt> five times, then say <tt>I'm done!</tt> It's basically a simplified <tt>for</tt> loop. It's a little slower than a <tt>for</tt> loop by a few hundredths of a second or so; keep that in mind if you're ever writing Ruby code for NASA. ;-) Alright, we're nearly done, six more methods to go. Here are three of them: Alright, that should make sense. In case it didn't, <tt>upto</tt> counts up from the number it's called from to the number passed in its parameter. <tt>downto</tt> does the same, except it counts down instead of up. Finally, <tt>step</tt> counts from the number its called from to the first number in its parameters by the second number in its parameters. So <tt>5.step(25, 5) {|x| puts x}</tt> would output every multiple of five starting with five and ending at twenty-five.  Time for the last three: <tt>to_s</tt> converts floats and integers to strings. <tt>to_i</tt> converts floats to integers. <tt>to_f</tt> converts integers to floats. There you have it. All the data types of Ruby in a nutshell. Now here's that quick reference table for string methods I promised you.