Why am I getting objects printed twice? - ruby

When I am in irb or in rails and I create some iteration with each, I am getting the whole struct printed again in my terminal or inside the browser. Example:
a = [1,2,3,4]
a.each do |number|
puts n
end
The result in irb terminal or inside the browser:
1
2
3
4
=> [1,2,3,4]
Why does this => [1,2,3,4] appear inside the browser? I can't create a single list in my page because the whole structure appears.

Every expression in Ruby returns a value; in irb, the value returned by the expression you've just executed is displayed after =>.
The return value of Enumerable::each is the object that called each - in this case, the array [1,2,3,4]

You see them printed twice: once as side effect, second time as the return value. irb always puts the last return value. The return value for each is its receiver. You cannot avoid that when using irb, but they will not show up when you run the script as standalone software. The First 1, ..., 4 are the outputs of your puts. They are called side effects.

Because ruby returns in everything even blocks. So your each statement is returning. You're seeing it output because irb shows you the return of everything. In a script it would only output once.

Run it outside irb, and you shall be enlightened.
ruby -e `[1,2,3,4].each {|ele| puts ele}`

Related

How to test for stdout that is inside a .each iteration block, using rspec?

I have a sample code:
def print_stuff(first_num, second_num)
puts 'hello'
(first_num..second_num).to_a.each do |num|
puts 'The current number is: '
puts "#{num}"
end
end
I and using rspec, I would like to test to see if the output is correct or not. My attempt are as follows:
expect(initialize_program(1, 3)).to output(
"The current number is:
1
The current number is:
2
The current number is:
3").to_stdout
But instead, I get a expected block to output to stdout but not a block error since the initialize_program(1,3) is outputting the texts, but it is done inside a .each block thus the method itself returns the array of range of numbers.
How can I test for the texts inside the block, to see if the outputted texts are correct?
Thanks!
Todd's answer is fine and I'd strongly recommend you read it carefully: refactor your app in a way that UI (CLI in your case) is minimal and easy to test. But when you want full coverage you'd need to test that std output eventually.
The way you're using it now:
expect(initialize_program(1, 3)).to output("whatever").to_stdout
Means that initialize_program(1, 3) is evaluated immediately when the matcher is called, and it's too soon - it has to do it's magic(*) first, and then run your code. Try like this:
expect { initialize_program(1, 3) }.to output("whatever").to_stdout
Now, instead passing results of calling initialize_program(1, 3) into the matcher, you pass a block that "knows how" to call initialize_program(1, 3). So what the matcher does:
saves the block for later
does it magic to capture whatever goes to the STDOUT (see below)
calls the block, calling the initialize_program(1, 3), capturing whatever was supposed to go to STDOUT
compares it with what you've set up in your expectation (the output("whatever") part)
https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/output-matcher
The mentioned magic is not that magical anyway:
https://github.com/rspec/rspec-expectations/blob/44d90f46a2654ffeab3ba65eff243039232802ce/lib/rspec/matchers/built_in/output.rb#L49
and
https://github.com/rspec/rspec-expectations/blob/44d90f46a2654ffeab3ba65eff243039232802ce/lib/rspec/matchers/built_in/output.rb#L141
It just creates StringIO, and replaces global var $stdout with it.
Refactor to Inspect a String, Not Standard Output
This type of code is why you should write your tests first. You're essentially testing Kernel#puts, which always returns nil, rather than validating that you've constructed the String you expect. Don't do that. Instead, refactor like so:
def print_stuff(num1, num2)
str =
(num1..num2).map { |num|"The current number is: #{num}" }
.join "\n"
puts str
str
end
print_stuff 1, 3
#=> "The current number is: 1\nThe current number is: 2\nThe current number is: 3"
This will not only print what you expect on standard output:
The current number is: 1
The current number is: 2
The current number is: 3
but will also use the implicit return of the last line of your method to return a value that you can use to compare to the expectations in your spec.
You might also refactor the method to return an Array of String objects, or whatever else you might explicitly want to test. The more your real method reflects what you plan to test, the better.
RSpec Examples
RSpec.describe '#print_stuff' do
it 'prints the expected message' do
expected_string = <<~EOF
The current number is: 1
The current number is: 2
The current number is: 3
EOF
expect(print_stuff 1, 3).to eql(expected_string.chomp)
end
# Even without the collection matchers removed in RSpec 3,
# you can still validate the number of items returned.
it 'returns the expected number of lines' do
lines = print_stuff(1, 3).split("\n").count
expect(lines).to eql(3)
end
end
Testing RSpec Examples in IRB
In irb, you can validate your specs like so:
require 'rspec'
include RSpec::Matchers
expected_string = <<~EOF
The current number is: 1
The current number is: 2
The current number is: 3
EOF
# String#chomp is needed to strip the newline from the
# here-document
expect(print_stuff 1, 3).to eql(expected_string.chomp)
# test the returned object in other ways, if you want
lines = print_stuff(1, 3).split("\n").count
expect(lines).to eql(3)

Ruby - Last value of a isn't printed

I write a ruby program that prints 3 different values of variable a with different data types:
a = 5
puts a
a = true
puts a
a = 1.325
return a
puts a
In this case, last value didn't print. When i remove return a, program prints a last value, 1.325.
But how?
return controls program flow, calling it will exit the current method and pass the value of a into whatever expression called it.
Usually you would not write a method with an unconditional return and more code afterward, because that code is not reachable. The puts in your example will never be called. Just move it to before the return expression if you want it to run.

Why is the => symbol appearing in my code?

I just started learning how to code and I tried running some basic instructions.
To start, I have the following:
print 'hello'
v= "yes"
["test","words","okay"].
each do |v|
puts "This is the test word #{v}"
end
which gives me the following out put
irb(main):053:0> print 'hello'
hello=> nil
irb(main):054:0> v= "yes"
=> "yes"
irb(main):055:0> ["test","words","okay"].
irb(main):056:0* each do |v|
irb(main):057:1* puts "This is the test word #{v}"
irb(main):058:1> end
This is the test word test
This is the test word words
This is the test word okay
=> ["test", "words", "okay"]
Why exactly is the => symbol appearing at the end of my code which references back to my array of strings? From what I understand so far, I know that => can be used to assign Strings to symbols in hashes (I think), but what other purpose does the symbol serve and why is it in my code?
The => you are seeing is an indicator of the return value of whatever command you run using irb.
So for instance the command print 'hello' results in hello=> nil because the string 'hello' is output to the console (with no new line), and the return value of the print method is nil.
When you invoke the each method on an array, after your output text is printed you see => ["test", "words", "okay"] because that is the return value of the each method (this can be convenient because it allows for chaining methods together).
As an experiment, try running different commands to see what their return values are. What is the return value of an assignment? (E.G. a = 3). Can you think of any useful ways to use return values?

Range is printed at the end of the "each" iteration

What I'll show is a fulish function, but it's only to explain my problem in a simple way. If I solve the problem in this function, I solved the problem in the original code too.
The problem is simple, and probably the solution too, but I'm new in Ruby and have this doubt. I want to print the values in a range:
def test
(0...5).each do |i|
puts i
end
end
When I call the function, the result that I want is
0
1
2
3
4
but the result that I have is
0
1
2
3
4
0...5
Why this 0...5 is printed together? How can I avoid that?
i don't think the 0..5 is being produced as part of the puts call. Rather, when you call this in your REPL (irb, pry, rails console, etc), you're seeing because it's the last returned value in your code.
Let me show you an example.
Say I save a file called test.rb with the following content:
1.upto(5).each { |i| puts i }
If I call ruby test.rb, I see the expected output,
0
1
2
3
4
If I open irb and run require("./test.rb"), I see the same output.
It's only when I paste the code into irb that I see the additional output (=> 0...5). So I would just ignore this.
In addition to #Max's answer
Whenever any expression is executed in IRB sessions, it will also print the value returned by every expression executed.
In case of method definition it returns the method_name just defined.
> def my_method
?> puts 'this is my method'
?> end
=> :my_method
You see, the :my_method is printed
When the method is invoked, it should print the value returned by the method execution i.e. response of the last expression in the method i.e. puts
> my_method
this is my method
=> nil
but it printed nil because puts always returns nil. I mentioned this because normally developers are astonished when they see their methods returning nil unexpectedly.

What does 'yield called out of block' mean in Ruby?

I'm new to Ruby, and I'm trying the following:
mySet = numOfCuts.times.map{ rand(seqLength) }
but I get the 'yield called out of block' error. I'm not sure what his means. BTW, this question is part of a more general question I asked here.
The problem is that the times method expects to get a block that it will yield control to. However you haven't passed a block to it. There are two ways to solve this. The first is to not use times:
mySet = (1..numOfCuts).map{ rand(seqLength) }
or else pass a block to it:
mySet = []
numOfCuts.times {mySet.push( rand(seqLength) )}
if "numOfCuts" is an integer,
5.times.foo
is invalid
"times" expects a block.
5.times{ code here }
You're combining functions that don't seem to make sense -- if numOfCuts is an integer, then just using times and a block will run the block that many times (though it only returns the original integer:
irb(main):089:0> 2.times {|x| puts x}
0
1
2
map is a function that works on ranges and arrays and returns an array:
irb(main):092:0> (1..3).map { |x| puts x; x+1 }
1
2
3
[2, 3, 4]
I'm not sure what you're trying to achieve with the code - what are you trying to do? (as opposed to asking specifically about what appears to be invalid syntax)
Bingo, I just found out what this is. Its a JRuby bug.
Under MRI
>> 3.times.map
=> [0, 1, 2]
>>
Under JRuby
irb(main):001:0> 3.times.map
LocalJumpError: yield called out of block
from (irb):2:in `times'
from (irb):2:in `signal_status'
irb(main):002:0>
Now, I don't know if MRI (the standard Ruby implementation) is doing the right thing here. It probably should complain that this does not make sense, but when n.times is called in MRI it returns an Enumerator, whereas Jruby complains that it needs a block.
Integer.times expects a block. The error message means the yield statement inside the times method can not be called because you did not give it a block.
As for your code, I think what you are looking for is a range:
(1..5).map{ do something }
Here is thy rubydoc for the Integer.times and Range.

Resources