Books / Ruby for Beginners / Chapter 7

Type Casting (type conversion) in Ruby

Let’s write a program to calculate your age in months. We’ll ask for the age in years, and our program will do calculation by multiplying this number by 12. Based on our knowledge from previous chapters we should have something like this:

puts "Your age?"
age = gets
age_months = age * 12
puts "Your age is " + age_months

What’s happening here? We defined age_months variable, which represents the age in years multiplied by 12. It should work, but something is not right. Can you spot the mistake? Here is the result of running this program:

Your age?
30
Your age is 30
30
30
30
30
30
30
30
30
30
30
30

Uh-oh! There definitely must be some mistake. It turns out that we multiply String by a number (Integer). Try to run this program again and type blabla:

Your age?
blabla
Your age is blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla
blabla

The type of age variable is String. And when we multiply String by Integer, the result is the very long string (short string of “blabla” repeated 12 times). To fix this program we should multiply Integer by Integer. We already did it before, when had calculated the number of milliseconds in a day, everything was correct. This time we just need to convert (or “cast”) type String into Integer.

How we can do that? Quick documentation search for gets function (or “method”, do you remember that words “function” and “method” are synonyms?) shows that this function returns results with a type of String. And it’s understandable, because gets is “get string”. What we need now is “get integer” function. And if we believe in Ruby’s principle of a least surprise, it should be geti, let’s check that:

$ irb
geti
NameError (undefined local variable or method `geti' for main:Object
Did you mean?  gets)

Oops! It didn’t work. But it was a nice try. There is no such method geti, but something tells it will be implemented one day. Let’s think what else we can do to fix our program?

There is one way to convert string into a number in JavaScript language (and every Ruby programmer should think about JavaScript a little bit). The trick is to multiply string by 1 (node below is JavaScript interpreter, it works if Node.js is installed on your computer):

$ node
> "123" * 1
123

Can we do the same trick in Ruby? Let’s try in REPL:

> "123" * 1
 => "123"
> ("123" * 1).class
 => String

No luck, it’s still String. But there should be other ways. Open up “String” class documentation to see the whole bunch of methods starting with to. There is to_i among these methods, which means “to Integer”, and it’s exactly what we need. to_i is not something obvious, but in this case Ruby developers wanted to stay lean, and we have to_i instead of to_integer.

So, to convert a string into number we should use to_i function:

> "123".to_i
 => 123
> "123".to_i.class
 => Integer

By the way, there is similar method with the name to_s - “to string”, with this method you can convert Integer (and other types) into String.

Let’s try to rewrite our program to calculate age in months:

puts "Your age?"
age = gets
age_months = age.to_i * 12
puts "Your age is " + age_months

Run it one more time and… Error again!

app.rb:4:in `+': no implicit conversion of Integer into String (TypeError)

As you can see, Ruby shows that error is happening in file app.rb on the line 4. Error says that we can’t sum up two different types: String and Integer. Let’s go ahead and fix it, using type casting for the second time:

puts "Your age?"
age = gets
age_months = age.to_i * 12
puts "Your age is " + age_months.to_s

Try to run:

$ ruby app.rb
Your age?
30
Your age is 360

Finally it works! We did a great job and used type casting two times, on lines 3 and 4. There are some other ways to write this program, and often it’s just up to a programmer to decide which approach is better. For example, we can do type casting on line 2, without touching line 3 (still keeping type casting on line 4):

puts "Your age?"
age = gets.to_i
age_months = age * 12
puts "Your age is " + age_months.to_s

Or we can redefine variable age by adding one more line:

puts "Your age?"
age = gets
age = age.to_i
age_months = age * 12
puts "Your age is " + age_months.to_s

Or we can do the same trick, but without age_months variable. Try do it yourself.


Licenses and Attributions


Speak Your Mind

-->