How can a fixnum be added to a string in ruby? - 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},"

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.

Why can't I print strings with integers?

num1 = 2
num2 = 4
op = num1 + num2
puts "enter a number would like to multiply with 6"
num3 = gets.to_i * op
print ("its " + num3 + " man")
Why doesnt this work? If i have it as 'print num3' alone itll work. What is going on?
The answers to this question, Concatenating string with number in ruby, outline two ways you can do it via either:
string interpolation
or, using .to_s to change the number to a string when constructing the result string
Using .to_s you can do this:
print ("its " + num3.to_s + " man")
Although using string interpolation may be a better approach.
Described here:
https://ruby-doc.org/core-2.5.0/doc/syntax/literals_rdoc.html
You can't concat Fixnum and string.
Please do it like this.
print ("its #{num3} man")
If i have it as print num3 alone it'll work. What is going on?
print can indeed print arbitrary objects using their to_s methods, even multiple objects.
But in order to do so, you have to pass them as separate arguments:
num = 42
print('its ', num, ' man')
# its 42 man
However, it's more idiomatic to use string interpolation:
print("its #{num} man")
# its 42 man
or printf which takes a template string: (%d means decimal number)
printf('its %d man', num)
# its 42 man
Note that none of the above will print a newline. If you want one, you have to append \n yourself, or use puts which adds it automatically.

String can't be coerced into Fixnum (TypeError)

I wrote the basic codes below
puts ' Hi there , what is your favorite number ? '
number = gets.chomp
puts number + ' is beautiful '
puts 1 + number.to_i + 'is way better'
But when I run it,I get the error "String can't be coerced into Fixnum (TypeError)". How do I correct this error please?
You cannot add a String to a number. You can add a number to a String, since it is coerced to a String:
'1' + 1
# => "11"
1 + 1
# => 2
1 + '1'
# TypeError!
Since I suspect you want to show the result of adding 1 to your number, you should explicitly cast it to string:
puts (1 + number.to_i).to_s + ' is way better'
or, use string interpolation:
puts "#{1 + number.to_i} is way better"
String can't be coerced into Integer usually happens, when you try to add a string to a number. since you want to add 1 to your number and concatenate it with a string "is way better". you have to explicitly cast the result you got from adding 1 to your number to a string and concatenate it with your string "is way better".
you can update your code to this:
puts (1 + number.to_i).to_s + " " + 'is way better'
Assuming that the numbers are natural numbers:
number = gets.chomp
puts "#{number} is beautiful ", "#{number.succ} is way better"
You might find the results of entering 'xyz' as an input surprising.
This discussion for determining if your input string is a number may be helpful.

What does interpolation mean in Ruby?

This is a simple Ruby code, but I am not getting how to understand and use it.
def string_length_interpolater(incoming_string)
"The string you just gave me has a length of #{incoming_string.length}"
end
Could somebody help me the process?
It returns a string with the phrase shown ("The string you...") plus the length of the string passed in, e.g.
string_length_interpolater('Hi')
=> "The string you just gave me has a length of 2"
string_length_interpolater('Hi There')
=> "The string you just gave me has a length of 8"
string_length_interpolater('123456789')
=> "The string you just gave me has a length of 9"
string_length_interpolater('Hello Ruby')
=> "The string you just gave me has a length of 10"
As you can see the method is just returning that text - "The string you just gave me has a length" with the length of the parameter that is passed in. The #{} within the DOUBLE quotes means work out the ruby value and then use that in the string.
It is also the same as
def string_length_interpolater(incoming_string)
"The string you just gave me has a length of " + incoming_string.length
end
When the output becomes comples - a string with 'ruby output at various points it becomes easier to use the doubles qoutes ('interpolation') method, for example this:
"From #{start} to #{end} the #{person} used a #{tool}"
is often easier to read/write/maintain than
"From " + start + " to " + end + " the " + person + " used a " + tool
Added: If you ALSO want to show the value of the string itself you could use:
def string_and_length(nm)
"Hello there #{nm}, did you know your name is #{nm.length} letters long?"
end

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}"

Resources