How this output is achieved? - ruby

I am new to Ruby.
I found this code while reading a tutorial
10.times { |i | print i, " " } # o/p => 0 1 2 3 4 5 6 7 8 9
I know times repeat a action number of times it's called.
I assume that i gets initialised to 0.
But, how it's getting incremented?

I assume that i gets initialised to 0. But, how it's getting incremented?
There's an internal variable, the integer itself doesn't change. Let's implement our own times method using a basic while loop:
class Integer
def my_times
i = 0 # initialize to 0
while i < self # self is the integer object, i.e. 10
yield i # pass i to the block
i += 1 # increment i
end
end
end
Usage:
10.my_times { |i| print i, " " } #=> 0 1 2 3 4 5 6 7 8 9
The Ruby method is more complex (returning an enumerator without a block), but you get the idea.

times creates an array of incrementing numbers (well an Enumerator actually, but it can be converted to an array with to_a)
$ irb
irb(main):001:0> 3.times.to_a
=> [0, 1, 2]
irb(main):002:0> 10.times.to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
See: http://www.ruby-doc.org/core-2.2.0/Integer.html#method-i-times
each is an Array/Enumerator method that yields each element.
See:
http://www.ruby-doc.org/core-2.2.0/Array.html#method-i-each
http://www.ruby-doc.org/core-2.0.0/Enumerator.html#method-i-each

In Ruby, everything is an object, including numbers. The integers are objects, meaning, they are defined from an Integer class that contains methods. Those methods can be called on an instance of the object. Thus, the number 10 is an instance object of the Integer class and you can call methods on it.
One of those methods is times. When you do:
10.times ...
You are calling the times method on the object 10. This method accepts a block parameter {...}:
10.times { |i| puts i }
Here, the i is the parameter for the block and the times method internally has a loop that runs that parameter from 0 to the object integer you called the times method on.
As #MarekLipka said in a comment, see the documentation for the Ruby Integer class.

Related

Is there a nicer way to call the current method recursively, without using its name?

For example:
def recurse(value)
if value < 5
self.send(__method__, value + 1)
else
value
end
end
This works, but it's a bit ugly.
Basically I'm looking for a prettier way to call the currently executing method, without referring to it explicitly by name.
If there is a less-cryptic syntax for this, I would probably use it (to avoid the name duplication, reduce effort required for renaming a function, etc). If there isn't a nicer syntax for this, I'll just hard-code the name like normal.
It's a comment rather, as #sagarpandya82 mentioned, you can omit some redundant parts and use both variants. I would refactor it a bit:
def recurse(value)
return value unless value < 5 # return value if value >= 5
send(__method__, value + 1) # or just recurse(value + 1)
end
Non-recursion version with a block:
def non_recurse(value)
if value >= 5
yield value
else
(value..5).each do |i|
yield i
end
end
end
non_recurse(3) {|i| puts i}
#=> 3, 4, 5
non_recurse(6) {|i| puts i}
#=> 6
If you really want to use __method__, your method is correct and reasonably readable. To comply with usual Ruby guidelines, you could just remove returns and use 2 spaces as indent (as mentioned by #sagarpandya82 in the comments):
def recurse(value)
if value < 5
self.send(__method__, value + 1)
else
value
end
end
I don't see any reason to use self.send(__method__) here, so you could write :
def recurse(value)
if value < 5
recurse(value + 1)
else
value
end
end
Actually, I'd say that you don't need recursion at all. All your method does is to keep adding 1 to the value until it reaches 5. If the value is bigger than 5, it returns the value :
For integers:
def no_recurse(value)
[value, 5].max
end
no_recurse(4)
# 5
no_recurse(-3)
# 5
no_recurse(7)
# 7
no_recurse(-2**1000)
# 5
no_recurse(4.5)
# 5 # <- That's wrong
For floats, you'd just need to add the decimal part to 5. This will work for any number:
def no_recurse(value)
[value, 5 + value % 1].max
end
no_recurse(4.5)
# 5.5
no_recurse(5.5)
# 5.5
no_recurse(6)
# 6
no_recurse(-7)
# 5

I'm learning Ruby and I don't clearly understand what :* means in inject(:*) [duplicate]

This question already has answers here:
How does this ruby injection magic work?
(3 answers)
Closed 7 years ago.
I'm writing a method for calculating the factorial of a number and I found something similar to this in my search.
def factorial(number)
(1..number).inject(:*) || 1
end
It works and I understand what the inject function is doing, but I don't clearly understand what the (:\*) part really means.
I know it must be a shorthand version of writing {|num, prod| num*prod}, but I would love a clear explanation. Thanks!!
:* is simply the method name for * of the method for inject to execute. If you look at the documentation for inject http://ruby-doc.org/core-2.2.2/Enumerable.html#method-i-inject
It states that
If you specify a symbol instead, then each element in the collection will be passed to the named method of memo. In either case, the result becomes the new value for memo. At the end of the iteration, the final value of memo is the return value for the method.
So taken that inject { |memo, obj| block }
The following are equal
ary = [1,2,3]
ary.inject(:*)
#=> 6
ary.inject { |memo, obj| memo.*(obj) }
#=> 6
Short explanation
:* is a symbol. Symbols are immutable strings. :* is like "*" except it's immutable.
In ruby, multiplication is a method invocation too. It's equivalent invoking the .*(second) method of the first multiplier with the second multiplier as an argument. In fact, you can type 3.*(4) instead of 3*4. 3*4 is just syntactic sugar as far as ruby is concerned.
Method invocation in ruby can be invoked by public_sending symbol messages to objects. 3.public_send(:*, 4) will also work just like 3*4.
The argument to inject is interpreted as what type of message should be public_senT, that is, what method should be invoked from the internals of the inject method.
Longer explanation
You can think of
[ 1, 2, 3, 4 ].inject(:*)
as injecting '*' between each adjacent pair of each enumerable object that inject is invoked on:
[ 1, 2, 3, 4 ].inject(:*) == 1 * 2 * 3 * 4
Of course 1 * 2 * 3 * 4 is equivalent to going from left to right, and applying :* on your running tally and the next number to get your next tally, and then returning the final tally.
module Enumerable
def inject_asterisk
tally = first
rest = slice(1, length - 1)
rest.each do |next_num|
tally = tally * next_num
end
return tally
end
end
[2, 3, 5].inject_asterisk #=> 30
You can generalize this by making the operation that combines the tally and next_number to get your next tally an argument function. Blocks in ruby serve basically as argument functions that always have a reserved spot.
module Enumerable
def inject_block(&block)
tally = first
rest = slice(1, length - 1)
rest.each do |next_num|
tally = block.call(tally, next_num)
end
return tally
end
end
[2, 3, 5].inject_block {|tally, next_num| tally + next_num } #=> 10
If your block is always going to be of the form
{|tally, next_num| tally.method_of_tally(next_num) }
as it is in this case (remember tally + next_num <==> tally.+(next_num) <==> tally.public_send(:+,next_num), you can decide to only pass :method_of_tally as the argument and imply the block.
module Enumerable
def my_inject(method_of_tally_symbol, &block)
if method_of_tally_symbol
block = Proc.new { |tally, next_num|
tally.public_send(method_of_tally_symbol, next_num)
}
end
tally = first
rest = slice(1, length - 1)
rest.each do |next_num|
tally = block.call(tally, next_num)
end
return tally
end
end
[2, 3, 5].my_inject(:+) #=> 10
It's all about extracting repeated patterns into reusable components so that you don't have to type as much.
It means symbol to proc and it's a shortcut. Typically you would write something like
array.map { |e| e.join }
with symbol to proc, the shorthand would be
array.map(&:join)
inject and reduce are similar, but you don't need the & in those cases
For example, if you have an array of numbers called numbers
To sum the numbers, you could do
numbers.inject(&:+)
or you could leave off the ampersand
numbers.inject(:+)
http://ruby-doc.org/core-2.2.2/Enumerable.html#method-i-inject
Inject is a method on enumerable that combines the elements of said enumerable using a symbol (as in your case) or a block (as in your proposed longhand).
For example:
(5..10).reduce(:*) is equivalent to (5..10).inject { |prod, n| prod + n }

Iterating through a Hash while Updating a Counter

I have a hash:
students = {
class1: 11,
class2: 24,
class3: 38,
class4: 62
}
I want there to be four lines of output:
1) 11
2) 35 #11 + 24
3) 73 #35 + 38
4) 135 #73 + 62
It goes through each element, and adds a value to a counter, printing each iteration as it goes. I need something like:
students.each do |key, value|
value + counter = total
puts total
end
but I have no idea how to do it. Please advise.
There are many ways to do this, but I will suggest a way that will teach you a few different things about Ruby. This is also a very Ruby-like way to address this problem.
Code
students = {
class1: 11,
class2: 24,
class3: 38,
class4: 62 }
students.reduce(0) do |tot, (k,v)|
tot += v
puts k[/\d+/] + ") #{tot}"
tot
end
1) 11
2) 35
3) 73
4) 135
Explanation
I've used Enumerable#reduce (a.k.a. inject) because that method is convenient for totaling a collection of numbers, using a variable (here tot) that maintains the running total within the block. That's just what you need.
Aside: you will learn a lot be reading the documentation for Ruby methods. Methods are referenced like this: SomeClass#method or SomeModule#method. Here, reduce is an instance method of the module Enumerable. students is an instance of the class Hash, but that class "mixes-in" (includes) the instance methods of the module Enumerable.
The object tot is a Fixnum that is initialized to reduce's argument, which here is zero. (If no initial value were given, the initial value from student--11--would be assigned to tot). Each time the code in the block is executed the value at the end of the block is returned to the enumerator (which is why tot is there). After all the elements of the receiver students have been enumerated, the value of tot is returned by reduce (though you will not be making use of that).
The first time the block is called the block variables are as follows:
tot => 0
k => :class1
v => 11
To print
1) 11
I presume you want the label 1) to be the right end of :class1. To exact 1 from the symbol k => :class1, you can use the method Symbol#[] with the regex /\d+/, which extracts a string of one or more digits 0-9 (as many as there are).
In reading the documentation for the method Symbol#[], you will see that it converts the symbol :class1 to the string "class1" and then invokes the method String[] on that string.
Since Ruby 1.9+, many prefer to use Enumerable#each_with_object rather than reduce. That method would be used like this:
students.each_with_object(0) do |(k,v),tot|
tot += v
puts k[/\d+/] + ") #{tot}"
end
Notice that with this method it is not necessary to return the value of the object (tot) to the enumerator, and that tot is at the end of the list of block variables, whereas it is at the beginning for reduce.
You were actually fairly close. You need to define the total variable outside of your block, just assign 0 to it using
total=0
this will make it stay through all the iterations. Then you just need a small change in
students.each do |key, value|
total=total+value
puts total
end
and it will do what you want.
Switching the order of value + counter = total is important, as assignments (through =) always assign to the variable on the left.
Using your code, made some small change:-- Try this:--
total = 0
students.each do |key, value|
total += value
puts total
end

Usage of Pipes in Ruby Loops

So, maybe I'm over-complicating something that isn't that hard, but here goes.
In Ruby, there's a method of looping called .each. I think that this is very cool--but what I'm finding less cool is the amount of stuff written about the pipe that comes after it (or any other do-type loop in Ruby, it would seem). Sometimes there is a single thing in the pipe:
basket.each do |fruit|
puts "This is a #{fruit}.\n"
end
But sometimes, there are two things in this pipe, like so:
contacts.each do |name, profession|
puts "#{name} is a #{profession}.\n"
end
So what I'm wondering now, is it possible to have more than two items in that pipe? Like if I have a huge, big, and ugly multi-dim array?
What if I add things to my pipe and they're not there? Will it give the value in the pipe nil? Or will it throw an error?
Again, sorry if this is obvious to long-time Rubyists, but I came from the land of strictly typed variables, and I'm now leaving PHP land, too. :)
EDIT
So what if I have something like this:
categories = [["Bathroom", "Bathroom Fixtures", "Plumbing"],
["Ceiling Fixtures", "Chandeliers", "Flush Mounts", "Mini Chandeliers", "Semi-Flush Mounts", "Pendants", "Track Lighting", "Mini Pendants", "Directional", "Island/Pool Table", "Recessed Lighting"],
["Outdoor", "Exterior", "Landscape Lighting"],
["Fans", "Fans", "Fan Accessories"],
["Lamps", "Lamps", "Shades"],
["Wall Fixtures", "Sconces", "Foyer/Hall Lanterns"],
["Specialty", "Undercabinet", "Light Bulbs", "Lighting Controls", "Glass", "Specialty Items", "Utility"],
["Home Decor", "Decor/Home Accents", "Furniture"]]
Can I loop through it like this?
categories.each do |category, subcats|
puts "The main category is #{category} and the sub categories are: "
subcats.each do |subcat|
puts "#{subcat}, "
end
end
Lets start with a break down of the each method.
a = [1,2,3,4,5]
a.each do |num|
puts num
end
# 1
# 2
# 3
# 4
# 5
The do ... end portion is called a block
This block accepts one parameter (an element in the array)
The way you pass parameters to a block is with |'s
If you supply more than one argument to the block:
a.each do |num, x|
puts num
puts x
end
# 1
#
# 2
#
# 3
#
# 4
#
# 5
#
x is nil for each iteration.
Lets write a method of our own that uses blocks so you can see how they work.
def my_each(a=[])
a.each do |x|
yield x if block_given?
end
end
my_each(a) do |num|
puts num
end
Here yield x is saying, execute the supplied block and pass x to it.
If you pass another parameter to your block, it is nil. Why?
Our implementation of my_each doesn't know anything about a second parameter so it does not yield anything so it remains nil.
When you have a simple array, the following things happen:
arr = [1,2,3,4]
arr.each do |x|
p x
end
1
2
3
4
=> [1,2,3,4]
arr.each do |x,y|
p x
p y
end
1
nil
2
nil
3
nil
4
nil
=> [1,2,3,4]
so if ruby doesn't know what to put into the block argument, it simply sets it to nil. Now consider a nested array:
arr = [[1,2],[3,4],[5,6]]
arr.each do |x|
p x
end
[1, 2]
[3, 4]
[5, 6]
=> [[1,2],[3,4],[5,6]]
arr.each do |x,y|
p x
p y
end
1
2
3
4
5
6
=> [[1,2],[3,4],[5,6]]
In this case, ruby assumes that you want to assign the two elements of the inner arrays to the block variables x and y. The same thing applies to hashes, where Ruby assigns the key and value to x and y:
hash = {1 => 2, 3 => 4, 5 => 6}
hash.each do |x,y|
p x
p y
end
1
2
3
4
5
6
=> {1=>2,3=>4,5=>6}
When you don't have enough elements in the nested arrays, the block variables are assigned nil, indeed. When there are too many of them, they are simply discarded:
arr = [[1,2,3],[4,5],[6]]
arr.each do |x,y|
p x
p y
end
1
2
4
5
6
nil
=> [[1,2,3],[4,5],[6]]
pretty straightforward!
EDIT:
As for your edited question: no, you cannot apply this 1:1 to Ruby code, you would have to manually apply the splat operator (*) to subcats. This way, ruby assigns all remaining elements to the 'splatted' block variable:
categories.each do |category,*subcats|
puts "The main category is #{category} and the sub categories are: "
subcats.each do |subcat|
puts "#{subcat}, "
end
end
although i would generate a comma-separated list of subcategories like this:
categories.each do |category,*subcats|
puts "The main category is #{category} and the sub categories are: "
puts subcats.join(', ')
end
EDIT 2:
Oh, and you would not handle a huge ugly evil multidimensional array by defining a lot of block parameters for its elements. You probably would iterate through it using nested loops as in almost every other language, if only because you never know how many elements it contains.
The pipes you are talking about is a parameter list of a block "variable". Actually that is some kind of a function pointer, and the pipes marks the parameter list.
Check the description of array.each.
This is not magic, the number of parameters is defined in the block, you can't add more than that, if you do, they won't get a value. The reason is for "sometime" there can be more than one, is that it's probably a hash.each, which has two parameters, a key and a value.
You can create your own functions with block parameters, read this.
For your iteration problem, you can use a hash, or you can write your own iterator.
Multiple Arguments to a Block
Array#each iterates over an array object, and passes either a single object into the block or returns an enumerator. You can redefine this behavior, but #each is the wrong method if you want multiple values at a time; see Enumerator#each_slice for an alternative.
Data Structures
Your problem would be easier to solve with the right data structure. Instead of an array, you should consider using a hash. For example:
categories =
{"Bathroom"=>["Bathroom Fixtures", "Plumbing"],
"Ceiling Fixtures"=>["Chandeliers", "Flush Mounts", "Mini Chandeliers"]}
categories.each do |key, value|
puts "#{key}:"
value.each { |v| puts "\t%s" % v }
end
This returns:
Bathroom:
Bathroom Fixtures
Plumbing
Ceiling Fixtures:
Chandeliers
Flush Mounts
Mini Chandeliers

How can I get a lazy array in Ruby?

How can I get a lazy array in Ruby?
In Haskell, I can talk about [1..], which is an infinite list, lazily generated as needed. I can also do things like iterate (+2) 0, which applies whatever function I give it to generate a lazy list. In this case, it would give me all even numbers.
I'm sure I can do such things in Ruby, but can't seem to work out how.
With Ruby 1.9 you can use the Enumerator class. This is an example from the docs:
fib = Enumerator.new { |y|
a = b = 1
loop {
y << a
a, b = b, a + b
}
}
p fib.take(10) #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
Also, this is a nice trick:
Infinity = 1.0/0
range = 5..Infinity
p range.take(10) #=> [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
This one only works for consecutive values though.
Recently Enumerable::Lazy has been added to ruby trunk. We'll see it in ruby 2.0.
In particular:
a = data.lazy.map(&:split).map(&:reverse)
will not be evaluated immediately.
The result is instance of Enumerable::Lazy, that can be lazy chained any further. If you want to get an actual result - use #to_a, #take(n) (#take is now lazy too, use #to_a or #force), etc.
If you want more on this topic and my C patch - see my blog post Ruby 2.0 Enumerable::Lazy
Lazy range (natural numbers):
Inf = 1.0/0.0
(1..Inf).take(3) #=> [1, 2, 3]
Lazy range (even numbers):
(0..Inf).step(2).take(5) #=> [0, 2, 4, 6, 8]
Note, you can also extend Enumerable with some methods to make working with lazy ranges (and so on) more convenient:
module Enumerable
def lazy_select
Enumerator.new do |yielder|
each do |obj|
yielder.yield(obj) if yield(obj)
end
end
end
end
# first 4 even numbers
(1..Inf).lazy_select { |v| v.even? }.take(4)
output:
[2, 4, 6, 8]
More info here:
http://banisterfiend.wordpress.com/2009/10/02/wtf-infinite-ranges-in-ruby/
There are also implementations of lazy_map, and lazy_select for the Enumeratorclass that can be found here:
http://www.michaelharrison.ws/weblog/?p=163
In Ruby 2.0.0, they were introduced new method "Lazy" in Enumerable class.
You can check the lazy function core and usage here..
http://www.ruby-doc.org/core-2.0/Enumerator/Lazy.html
https://github.com/yhara/enumerable-lazy
http://shugomaeda.blogspot.in/2012/03/enumerablelazy-and-its-benefits.html
As I already said in my comments, implementing such a thing as lazy arrays wouldn't be sensible.
Using Enumerable instead can work nicely in some situations, but differs from lazy lists in some points: methods like map and filter won't be evaluated lazily (so they won't work on infinite enumerables) and elements that have been calculated once aren't stored, so if you access an element twice, it's calculated twice.
If you want the exact behavior of haskell's lazy lists in ruby, there's a lazylist gem which implements lazy lists.
This will loop to infinity:
0.step{|i| puts i}
This will loop to infinity twice as fast:
0.step(nil, 2){|i| puts i}
This will go to infinity, only if you want it to (results in an Enumerator).
table_of_3 = 0.step(nil, 3)
I surprised no one answered this question appropriately yet
So, recently I found this method Enumerator.produce which in conjunction with .lazy does exactly what you described but in ruby-ish fashion
Examples
Enumerator.produce(0) do
_1 + 2
end.lazy
.map(&:to_r)
.take(1_000)
.inject(&:+)
# => (999000/1)
def fact(n)
= Enumerator.produce(1) do
_1 + 1
end.lazy
.take(n)
.inject(&:*)
fact 6 # => 720
The right answer has already identified the "lazy" method, but the example provided was not too useful. I will give a better example of when it is appropriate to use lazy with arrays. As stated, lazy is defined as an instance method of the module Enumerable, and it works on EITHER objects that implement Enumerable module (e.g. arrays - [].lazy) or enumerators which are the return value of iterators in the enumerable module (e.g. each_slice - [].each_slice(2).lazy). Note that in Enumerable module, some of the instance methods return more primitive values like true or false, some return collections like arrays and some return enumerators. Some return enumerators if a block is not given.
But for our example, the IO class also has an iterator each_line, which returns an enumerator and thus can be used with "lazy". The beautiful thing about returning an enumerator is that it does not actually load the collection (e.g. large array) in memory that it is working on. Rather, it has a pointer to the collection and then stories the algorithm (e.g. each_slice(2)) that it will use on that collection, when you want to process the collection with something like to_a, for example.
So if you are working with an enumerator for a huge performance boost, now you can attach lazy to the enumerator. So instead of iterating through an entire collection to match this condition:
file.each_line.select { |line| line.size == 5 }.first(5)
You can invoke lazy:
file.each_line.lazy.select { |line| line.size == 5 }.first(5)
If we're scanning a large text file for the first 5 matches, then once we find the 5 matches, there is no need to proceed the execution. Hence, the power of lazy with any type of enumerable object.
Ruby Arrays dynamically expand as needed. You can apply blocks to them to return things like even numbers.
array = []
array.size # => 0
array[0] # => nil
array[9999] # => nil
array << 1
array.size # => 1
array << 2 << 3 << 4
array.size # => 4
array = (0..9).to_a
array.select do |e|
e % 2 == 0
end
# => [0,2,4,6,8]
Does this help?

Resources