Ruby - Last value of a isn't printed - ruby

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.

Related

What is the difference between each and any to find a prime number in Ruby

There are two completely identical methods, only one uses each and the other any, so what is the difference between each and any?
first program code (each using):
def is_prime?(num)
Math.sqrt(num).floor.downto(2).each {|i| return false if num % i == 0}
true
end
number = gets.chomp.to_i;
puts is_prime?(number);
second program code (any using):
def is_prime?(num)
Math.sqrt(num).floor.downto(2).any? {|i| return false if num % i == 0}
true
end
number = gets.chomp.to_i;
puts is_prime?(number);
The .each method iterates through all elements of a data structure, most commonly an array or a hash, and calls the given block once for each element. If no block is given, it returns an enumerator, i.e. an instance of the Enumerator class that can then be used to "manually" iterate through the data structure.
The .any? method tests every element of a data structure against the given condition and returns true if one or more of them match or pass the test. Otherwise, it returns false. There are more details to it, so please check it from the official documentation.
General tips using Ruby
Based on this code, there are a couple of suggestions. First, you should not use return in a block as it makes the method return that value, too, and might not execute the block for more iterations.
Second, you don't need trailing semicolons at the ends of lines.
Short analysis of your code
Both your functions seem to work, at least for some numbers, but it seems that you might not exactly know why. Let's take a closer look at it.
Let's assume num = 5, for example.
First function, the block variable i gets assigned to a value of 2, meaning the block does not use the return false because the test num % i == 0 fails. Instead, the function returns true from the next line.
Second function, the block variable i also gets assigned to a value of 2, but again, as the test num % i == 0 fails the result of .any? is false, and the function returns true from the next line.
Now, let's assume num = 4.
First function, the block variable i gets again assigned to a value of 2, and since this time the test num % i == 0 passes, the return false inside the block is executed making the function return false.
Second function, the block variable i also gets again assigned to a value of 2, and since the test num % i == 0 passes here as well, the return false inside the block is executed making the function return false.
Without the return false in your second function, the function would always return true because you would not check the value returned by .any?, and the function's next line would be executed returning true.
Mechnicov offers simpler alternatives how to make your function more understandable.
each is the iterator that go through the array from beginning to end
Its main purpose is just to pass through the array (or other collection) and perform some actions that were specified in the block. For example, it can be a rendering of HTML partial or making HTTP requests or something else
There are also many other iterators that have specific tasks. These are such as map, select, any? and others
You used it wrong way. You're not using the full power of a specific iterator
But you can do it like this:
def prime?(num)
!Math.sqrt(num).floor.downto(2).any? { |i| num % i == 0 }
end
or like this
def prime?(num)
Math.sqrt(num).floor.downto(2).all? { |i| num % i != 0 }
end

Beginner Ruby - about Objects

Beginner on Ruby here...below are two similar codes, I understand the procedures of this very basic code but I'd like to understand the theory behind it...
First
def stats(ppg)
if ppg > 20
puts "The PG is considered elite"
else
puts "The PG is not considered elite"
end
end
stats(28)
Second
def stats(ppg)
if ppg > 20
"The PG is considered elite"
else
"The PG is not considered elite"
end
end
puts stats(28)
So the first piece automatically writes out the strings whereas the second piece does not - is stats(ppg) from the first piece considered an object or a method with the variable as the argument?
def stats(ppg) in both cases is the same thing, i.e. the beginning of a method definition for a method named stats that takes one argument or parameter that will be named ppg inside the method body.
stats(28) in both cases is the same thing, i.e. a call to a method named stats with the literal Fixnum 28 passed as its argument, whereupon it will be assigned to the variable ppg inside the method body from the definition.
In Ruby, every expression involves two distinct phenomena: side effects, and return values. The expression a = 1 has a side effect of assigning the value of 1 to the variable a, and a return value of 1. Not every method in Ruby has a side effect, but every method does have a return value — either an explicit return value (by using return), or else the return value of the last expression evaluated in the method body.
puts is an unfortunate method in Ruby, because it is used in so many beginner examples, yet its behavior is confusing. It has a side effect of printing its argument to stdout, but its return value is nil (which often confuses beginners, who expect it to return the value of its argument).
The difference between your first method and second method is that the first method, because it uses puts internally, has the side effect of printing a string to stdout and a return value of nil, while the second method has no side effect, but a return value of the string itself.
Therefore, when you call your first method without puts in front, the side effect of printing the string occurs and you see the output. When you call your second method, there is no printing side effect, so in order to have the string printed to stdout, you have to call puts. The argument to puts is the return value of your stats method, i.e. the string you wanted to print.

Returning a value of ruby is strange

could anyone tell me the return value of this function give the parameter listed blew:
def sequence(*enumerables)
enumerables.each do |enumerable|
print "#{enumerable},"
end
end
a,b,c = [1,2,3],4..6,'a'..'e'
value = sequence(a,b,c)
print value
why the value is evaluated to be:
[[1,2,3],4..6,"a".."e"]
Remember that the last thing left on the stack is the return value of your method. This is always the case. If the return value is important, you must pay close attention to how you exit from your method.
The each method returns what it has been iterating over. Since the each is the last statement in your method, stack-wise, that value gets returned.
You can fix this by returning nothing:
def sequence(*enumerables)
enumerables.each do |enumerable|
print "#{enumerable},"
end
return
end
This approach is generally frowned on as the return method seems out of place. If the caller of this method is not expecting any particular return value, then it's not necessary.
The alternative is to return something useful:
def sequence(*enumerables)
enumerables.join(",")
end
puts sequence(a,b,c)
It's often the case that methods which do not set an expectation for a particular return value may return an arbitrary one.
enumerables is an array. The splat (*) operator causes this.
The return value of sequence is the return value of enumerables.each which is enumerables
A simple example:
def foo(*args)
args
end
foo(1,2,3,4) == [1,2,3,4] # true
You're returning enumerables, which is an array containing all the arguments to the method.
What did you expect value to contain? You haven't made any explicit attempt to return anything, so whatever value the last statement in the method resolves to "falls off" the method to become its return value.

Why am I getting objects printed twice?

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

Ruby how does this inject code work?

I am new to Ruby and I am trying to write a method that groups an array of words into anagram groups. Here is the code:
def combine_anagrams(words)
dict = words.inject(Hash.new(0)) do |list,ws|
key = sort_word(ws)
if !list.has_key?(key)
list[key] = []
end
list[key].push(ws)
list #What is this
end
return dict.values
end
My question is what the statement list is for. If I take it out list becomes an array instead of hash.
Every method/block/etc. in Ruby returns something, and unless there is an early return statement, whatever the last statement in the method/block/etc. is, is what is returned.
In your case, having list be the last line in the block passed to inject ensures that list is returned by the block. When you remove it, the return value of list[key].push(ws) is returned, which obviously isn't what you want.
Note that this behavior also makes using the return keyword when it is the last statement that would be executed otherwise is unnecessary (this includes the return you have at the end of your method). Though some prefer to be explicit that they intend to return something and use them even when not needed.
On an unrelated note: your if !list.has_key?(key) can be rewritten unless list.has_key?(key).
inject works like this:
final = enumerable.inject(initial_value) do |current_value, iteration|
# calculations, etc. here
value # next iteration, current_value will be whatever the block returns
end
So, in your case, initial_value is Hash.new(0), or an empty Hash with 0 as the default value for a key that doesn't exist instead of nil. This is passed into the inject block for the first element in enumerable.
Inside the inject block, you check to see if key already exists as a key on the hash. If it does not, set it equal to an empty array. In either case, take the current iteration of words (ws) and push it onto the array.
Finally, the block returns the current version of list; it becomes current_value (the first parameter to the inject block) the next time the loop processes an element from enumerable.
As a more simple example, check out this sample:
numbers = [1, 2, 3, 4]
sum = inject(0) do |total, number| # first time, total will be 0
total + number # set total next time to be whatever total is now plus the current number
end
Take a look at http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-inject
In the inject method if you pass two arguments into it (in your case list and ws) the first one - list - is so-called accumulator value. The value which is returned by the inject block at each iteration step is assigned to the list variable. So the line with the only word "list" which you commented as "#What is this" is used for assigning the value of the list in the block to the "list" accumulator variable.
the statement "list" is the return value of the whole block. The line: "list[key] = []" has a return value of "list", therefore it doesnt need another line to set the return value of the if condition to 'list', but the return value of list[key].push(ws) is list[key]. we want to get the updated value of list in the end, therefore we need to return that value from the block each time, so that further processing acts of the updated list, and not something else.
As a background, each ruby line also has a return value, so if that were the last line of a block, or a function, it automatically becomes the return value of the whole block or the function respectively.
To understand this further, try some code like this in irb:
a = [1,2,3,4,5]
b = a.inject(0) {|sum, val| puts sum; puts val; sum + val}
the inner block comprises of three statememts; the last statement returns the value of sum+val to the block, which get stored in sum, to be used in next iterations.
Also, try some code like this:
h = {:a => []}
b = h[:a].push 6
See what b evaluates to; in your code, you need 'b' to be the accumulated hash, and not the array that is stored in h[:a]

Resources