Putting a string and calling a method in the same line - ruby

I have a class called Fractions that takes in a numerator and a denominator. It has three methods- frac, redfrac, dec- that print out the fraction, its reduced version, and its decimal form respectively.
As an example, if the numerator is 12 and the denominator is 4, I want to print out the result as so:
Fraction: 12/4
Reduced Fraction: 3
Fraction as Decimal: 3.0
My current code after my Fractions class is as follows
a = Fractions.new(numer, denom)
puts "Fraction:"
a.frac
puts "Reduced Fraction:"
a.redfrac
puts "Fraction as a Decimal:"
a.dec
which prints out
Fraction:
12/4
Reduced Fraction:
3
Fraction as a Decimal:
3.0
How do I print the text as I want it? I tried doing
puts "Fraction:" + a.frac
but this does not work because I cannot interpolate a string with my calling of the method.

"Fraction:" + a.frac is not using string interpolation - it is using the + operator and trying to add a Fixnum to a String, which is impossible.
To use String interpolation, you can do it like this:
puts "Fraction: #{a.frac}"
You could also do this:
puts "Fraction: " + a.frac.to_s
Which converts the Fixnum to a string before adding them together
Do the same for the reduced version and the decimal form respectively.
See https://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Literals#Interpolation for more information (RubyMonk also has a good explanation of string interpolation, but appears to be down).

You couldn't do string concatenation with + operator because the return value of a.frac is not a string.
You could explicitly convert it to string with .to_s and change your line:
puts "Fraction:" + a.frac.to_s
or, you could use Ruby's string interpolation like this:
puts "Fraction: #{a.frac}"

Related

Type-Conversion in Ruby

Theoretical question
I'm trying to find new practical ways to convert integers into strings and the other way around.
I only know the .to_s ; .to_i ; .to_f methods and would like to know if there are other ways to do to it without writing + to put together the variables. For example:
var1 = 16
puts 'I\'m ' + var1.to_s + ' years old.'
In longer codes is getting tiring writing all this to just convert a integer to a string.
By the way I also found this Timer program here on Stack and the #{ is an example of what I'm trying to do. Adding an integer to a string without + and .to_s But I don't know how it works.
30.downto(0) do |i|
puts "00:00:#{'%02d' % i}"
sleep 1
end
Thank you in advance for the suggestions!
Ruby has a pretty powerful string interpolator feature using #{...} where that can contain fairly arbitrary Ruby code. The end result is always converted to a string using, effectively, to_s.
That is you can do this:
puts "00:00:#{'%02d' % i}"
Where that gets stringified and then interpolated.
This is roughly the same as:
i_str = '%02d' % i
puts "00:00:#{i_str}"
Where that is effectively:
i_str = '%02d' % i
puts "00:00:%s" % i_str
You could also combine that into a single operation:
puts "00:00:%02d" % i
Where you generally use interpolation or sprintf-style template strings, not both at the same time. It keeps your code cleaner since only one mechanism is in play.
The only reason .to_s is needed when doing concatenation is Ruby is very particular about "adding" together two things. x + y has a completely different outcome depending on what x and y are.
Consider:
# Integer + Integer (Integer#+)
1 + 2
# => 3
# Array + Array (Array#+)
[ 1 ] + [ 2 ]
# => [1,2]
# String + String (String#+)
"1" + "2"
# => "12"
Note that in each case it's actually a different method being called, and the general form of x + y is:
x.send(:+, y)
So it's actually a method call, and as such, each method may impose restrictions on what it can operate on by emitting exceptions if it can't or won't deal.
It's called string interpolation. For example:
puts "I\'m #{var1} years old."
The way it works is this:
You have to enclose the string in double quotes, not single quotes.
You put your variable inside this: #{}, e.g. "#{variable}".
This will always convert non-string variables into strings, and plug (i.e. interpolate) them into the surrounding string.

How can a fixnum be added to a string in ruby?

If I want a string of both words and numbers in ruby, such as "worda, wordb, 12, wordc, 10,"
do I need to first convert the number to a string ie.
a = 12.to_s?
Possible ways to mix strings and integers
It depends how you want to do it :
["worda", 10].join(', ')
"worda, #{10}"
"worda, %d" % 10
"worda" + ", " + 10.to_s
"worda" << ", " << 10.to_s
all return "worda, 10"
join and string interpolation will both call .to_s implicitely.
String + Integer
"worda" + 10
Is a TypeError, though, because there's no implicit conversion with +.
Otherwise "1" + 2 could be either "12" or 3. Javascript accepts it and returns "12", which is a mess IMHO.
String << Integer
Finally:
"worda, " << 10
is a valid Ruby syntax, but it appends the ASCII code 10 (a newline), not the number 10:
"worda, \n"
Ruby requires (approx.) strings to be of the same type, like most reasonable programming languages.
You have 1 solution.
"word" + 12.to_s
or
"word #{12}"
The second example is called string interpolation, and will call the method .to_s on any object passed in.
Yes, but you can do
"worda, wordb, #{num_1}, wordc, #{num_2},"

Fixnum String conversion

I want to get a string of the current time in Ruby:
"Time is " + Time.new.month + "/" + Time.new.day + "/" + Time.new.year
But it says "can't convert Fixnum into String". How can I fix this?
Or you could just use right tool for the job: time formatting.
Time.new.strftime "Time is %m/%d/%Y" # => "Time is 11/13/2012"
You could use to_s
"Time is " + Time.new.month.to_s + "/" + Time.new.day.to_s + "/" + Time.new.year.to_s
But event better is to use strftime
Time.new.strftime("Time is %-m/%e/%Y")
Ruby can only add string to string, so conversion is required. As a note, elements interpolated in double-quoted strings are automatically converted:
now = Time.new
"Time is #{now.month}/#{now.day}/#{now.year}"
It's also possible to combine them from an array where they are also automatically converted:
now = Time.new
"Time is " + [ now.month, now.day, now.year ].join('/')
You can also use sprintf-style interpolation:
now = Time.new
"Time is %d/%d/%d" % [ now.month, now.day, now.year ]
The second one gives you more control over formatting. For example %02d will pad with 0 to two places.
As Sergio points out, there's a special-purpose function for this formatting that is probably a better idea. Also Time.now is the traditional method for now, whereas Time.new is for creating arbitrary times.
Whenever possible, prefer string interpolation over concatenation. As you can clearly see in that (thread), using string interpolation would have automatically called to_s for you.
Using string interpolation :
"Time is #{Time.new.month}/#{Time.new.day}/#{Time.new.year}"

Adding a number to a phrase

I can print a raw number with this code:
puts 'Please enter your favorite number'
favNumber = gets.chomp
betterNumber = favNumber.to_i
puts betterNumber + 1
but I need to set a message including the number. I changed the last two lines to this, but it's wrong.
betterNumber = favNumber.to_i + 1
puts 'Your favorite number sucks, a better number is '+ betterNumber + '!'
Help me.
betterNumber is of class Fixnum and your string is of course of class String. You can't add a String and a Fixnum, you need to cast your Fixnum into a String using to_s.
"Your favorite number sucks, a better number is " + betterNumber.to_s + "!"
Also, using interpolation calls to_s on any objects being interpolated. So this works, too (and is more common):
"Your favorite number sucks, a better number is #{betterNumber}!"
Also, in Ruby we usually use snake_case variables as opposed to camelCase variables. So I recommend using better_number
You need to convert betterNumber to a string when printing it, like this: betterNumber.to_s.

What is the meaning of i.to_s in Ruby?

I want to understand a piece of code I found in Google:
i.to_s
In the above code i is an integer. As per my understanding i is being converted into a string. Is that true?
Better to say that this is an expression returning the string representation of the integer i. The integer itself doesn't change. #pedantic.
In irb
>> 54.to_s
=> "54"
>> 4598734598734597345937423647234.to_s
=> "4598734598734597345937423647234"
>> i = 7
=> 7
>> i.to_s
=> "7"
>> i
=> 7
As noted in the other answers, calling .to_s on an integer will return the string representation of that integer.
9.class #=> Fixnum
9.to_s #=> "9"
9.to_s.class #=> String
But you can also pass an argument to .to_s to change it from the default Base = 10 to anything from Base 2 to Base 36. Here is the documentation: Fixnum to_s. So, for example, if you wanted to convert the number 1024 to it's equivalent in binary (aka Base 2, which uses only "1" and "0" to represent any number), you could do:
1024.to_s(2) #=> "10000000000"
Converting to Base 36 can be useful when you want to generate random combinations of letters and numbers, since it counts using every number from 0 to 9 and then every letter from a to z. Base 36 explanation on Wikipedia. For example, the following code will give you a random string of letters and numbers of length 1 to 3 characters long (change the 3 to whatever maximum string length you want, which increases the possible combinations):
rand(36**3).to_s(36)
To better understand how the numbers are written in the different base systems, put this code into irb, changing out the 36 in the parenthesis for the base system you want to learn about. The resulting printout will count from 0 to 35 in which ever base system you chose
36.times {|i| puts i.to_s(36)}
That is correct. to_s converts any object to a string, in this case (probably) an integer, since the variable is called i.

Resources