Why is the method output printed first? - ruby

I wrote the following:
greeting="i am awesome"
puts("I was saying that #{greeting}")
# => I was saying that i am awesome
When I change it to this:
def showman
print("I am awesome ")
end
puts("I was saying that #{showman}")
# => I am awesome I was saying that
why is the method output printed first, and then the string? Why is it not printing like "I was saying that I am awesome"? What can I do to make the output be as such?
If I modify the showman function to:
def showman
return ("I am awesome ")
end
then it gives the desired output. Why is the use of return in this way making difference to the output?

In first output why method output is printed first and then the string.
In order to evaluate the string, showman is evaluated before the whole string is evaluated, which prints "I am awesome ".
Why its not printing like "I was saying that I am awesome"
Because print returns nil, and interpolating nil in a string evaluates to an empty string ("#{showman}" → "#{nil}" → ""). Without print, the showman method returns the string "I am awesome ".
Why is the use of return in this way making difference to the output?
It is not the use of return that is making the difference. It is the absence of print that is making the difference.

Related

Ruby: String interpolation prints the function first when called second

Here is my short program
def def1()
x = 1
puts x
end
def def2()
y = 2
puts y
end
puts "some text #{def1}"
puts "some text #{def2}"
The outcome of this example...
1
some text
2
some text
I don't understand why this puts in this order and not "sometext" first.
Because the string is created first, which means calling def1, and then the whole string is passed into puts.
We can expand puts "some text #{def1}" out to understand.
string = "some text " + def1.to_s
puts string
As you can see, def1 is called to create the string. def1 prints out 1 itself, it does not return anything (it returns nil). Then the whole string is printed.
That's how all function calls work. The arguments are evaluated, the the function is called.
You'd need to call def1 after printing the prefix.
print "some text "
def1
This is a reason why it's often better to have a function return a value rather than print it itself.
In order to print the string, puts has to know what the string is. In order to know what the string is in this particular line:
puts "some text #{def1}"
Ruby has to call def1 first. def1, in turn, calls puts to print something.

Ruby `downcase!` returns `nil`

With this code:
input = gets.chomp.downcase!
puts input
if there is at least one uppercase letter in the input, the input will be put on screen, freed of its uppercases. But if the input has no uppercase letter, it will put nil, like if nothing was written.
I want my input to be fully downcased; if it is a string with no uppercase letter, it should return the same string.
I thought about something like this:
input = gets.chomp
if input.include(uppercase) then input.downcase! end
But this doesn't work. I hope someone has an idea on how I should do this.
According to the docs for String:
(emphasis is mine added)
downcase
Returns a copy of str with all uppercase letters replaced with their lowercase counterparts. The operation is locale
insensitive—only characters “A” to “Z” are affected. Note: case
replacement is effective only in ASCII region.
downcase!
Downcases the contents of str, returning nil if no changes were made. Note: case replacement is effective only in ASCII
region.
Basically it says that downcase! (with exclamation mark) will return nil if there is no uppercase letters.
To fix your program:
input = gets.chomp.downcase
puts input
Hope that helped!
This will work:
input = gets.chomp.downcase
puts input
String#downcase
Returns a modified string and leaves the original unmodified.
str = "Hello world!"
str.downcase # => "hello world!"
str # => "Hello world!"
String#downcase!
Modifies the original string, returns nil if no changes were made or returns the new string if a change was made.
str = "Hello world!"
str.downcase! # => "hello world!"
str # => "hello world!"
str.downcase! # => nil
! (bang) methods
It's common for Ruby methods with ! / non-! variants to behave in a similar manner. See this post for an in-depth explanation why.
The reason that downcase! returns nil is so you know whether or not the object was changed. If you're assigning the modified string to another variable, like you are here, you should use downcase instead (without the bang !).
If you're not familiar, the standard library bang methods typically act on the receiver directly. That means this:
foo = "Hello"
foo.downcase!
foo #=> "hello"
Versus this:
foo = "Hello"
bar = foo.downcase
foo #=> "Hello"
bar #=> "hello"

Ruby one liner lazy string evaluation

I'd like to create ruby one liner that prints some information to stdout and gets data from stdin. I've got some code:
["This should be shown first", "This second: #{gets.chomp}"].each{|i| puts "#{i}"}
...but apparently, get.chomp is evaluated in the same time when whole array is evaluated, before iteration of each element.
In result, I'm first prompted for input, and then each element is printed.
Can I somehow evaluate it lazily, print array in order and still have whole thing in one line?
One way to achieve lazy evaluation is to use procs. Something like this (multiple lines for readability):
[
-> { puts "This should be shown first" },
-> { print "This second: "; puts gets.chomp },
].each(&:call)
I don't really see the advantage of making this a one-liner since it becomes pretty unreadable, but nevertheless:
[ ->{ "This should be shown first" },
->{ "This second: #{gets.chomp}" }
].each {|line| puts line.call }
P.S. Never do "#{foo}". Use string interpolation (#{...}) when you want to, well, interpolate strings, as on the second line above. If you want to turn a non-string into a string, do foo.to_s. If you know it's already a string (or don't care if it is) just use it directly: foo. But puts automatically calls to_s on its arguments, so just do puts foo.
If you dont mind the repetiton of puts:
['puts "This should be shown first"', 'puts "This second: #{gets.chomp}"'].each{|i| eval i}
This is just to show you could use a method rather than a proc.
def line2
"#{["cat","dog"].sample}"
end
["Line 1", :line2, "line 3"].each { |l| puts (l.is_a? Symbol) ? method(l).call : l }
#=> dog

Why the newline char does not work here?

def say(arg)
"Hello, #{arg}.\n"
end
say("ABC") # => "Hello, ABC.\n"
Why here \n is printed instead of a newline?
because say returns a String. it doesn't print anything.
If you want to print something you should try:
def say(arg)
puts "Hello, #{arg}.\n"
end
You're most likely trying this in irb which displays the Ruby representation of a string. Compare:
irb(main):007:0> puts say("ABC") + say("ABC")
Hello, ABC.
Hello, ABC.
=> nil
irb(main):008:0> puts "ABC" + "ABC"
ABCABC
=> nil
It is actually never printed to stdio or anything like that, you are simply returning a string from a function.
I'll make the assumption that you are evaluating this in IRB, IRB prints out the result of every expression.
use puts or similar.

Ruby 1.9 prints strings twice

class Test
def printsomething
p "lol"
end
end
teet = Test.new
p "#{teet.printsomething}"
Output for above code is "lol"\n"lol"
why is this happening? I am running ruby 1.9.2 Archlinux x86_64
p is an inspect not really meant to be used to output text string. What it does is prints out the literal content of an object not an escaped string.
Just replace p with puts
You can see what I mean if you do this:
p "#{teet}"
=> "#<Test:0x00000100850678>"
Notice how it's inside quotes.
First thing that Ruby does when it sees a double-quoted string is replacing the #{expr} parts with the result of evaluated expr. For example, "#{2+2}" becomes "4". So, let's see what happens here. Ruby evaluates teet.printsomething. During this evaluation it executes the method and it prints "lol" in the 3-rd line. Note that although the method printsomething doesn't have a return statement, it nevertheless returns some value: it's the value returned by the last statement of that method. The return value of p object is the object itself, so the result of the method printsomething is "lol". This result now replaces the #{} part in the string, and the string becomes "lol" instead of "#{teet.printsomething}". Now the p method in the 7-th line is executed and outputs "lol" again.
What happens if you replace p with puts? The difference is that the return value of puts is nil. When the result of expr is nil, the whole expression #{} is replaced by empty string. So the 7-th line becomes puts "". As a result, the whole program outputs "lol" followed by an empty line.

Resources