What do c == self and yield do? - ruby

Can you help me understand what this class does and how we can make use of it?
class Integer
def myt
c=0
until c == self
yield(c)
c+=1
end
self
end
end
Thank you.
x = Integer.new
x.myt
I tried to test it but it doesn't work. Error is: "no block given (yield)"
Also, in my book it says to test like this:
5.myt (|| puts "I'm on iteration #{i}! "} but it also gives an error - not sure why or what this line of code means.

allonhadaya and PNY did a good job explaining the purpose (enumeration) of the myt method.
Regarding your two questions mentioned in the title:
1.) What does 'c == self' do?
The '==' operator checks whether the integer c and Integer object you instantiate, are equal in value. If they are, the expression evaluates to true.
2.) What does 'yield' do?
The 'yield' statement passes control from the current method to a block which has been provided to the method. Blocks are ruby's implementation of a closure which, simple put, means that a method can be "extended" by calling the method with a block of additional code as long as the method supports a block (ie. incorporates yield statements)

The method seems to be a times implementation.
Basically 5.times { |i| puts i } and 5.myt { |i| puts i } will do exactly the same thing.
First, it sets a counter to 0, c = 0. Then you have a conditional where it checks if c is equal with self which will always be the integer attached to the method myt. It, then yields the counter and return self when is done.

Looks like it enumerates the values between zero inclusively and self exclusively.
allon#ahadaya:~$ irb
irb(main):001:0> class Integer
irb(main):002:1> def myt
irb(main):003:2> c=0
irb(main):004:2> until c == self
irb(main):005:3> yield(c)
irb(main):006:3> c+=1
irb(main):007:3> end
irb(main):008:2> self
irb(main):009:2> end
irb(main):010:1> end
=> nil
irb(main):011:0> 5.myt { |i| puts i }
0
1
2
3
4
=> 5
irb(main):012:0>

Using the example your book gave --
5.myt {|i| puts "I'm on iteration #{i}! "}
#You were missing an object in the pipes and a curly bracket before the pipes (not parentheses)
Allows you to see the internal workings of your myt method. Initializing variable c with a value of 0 the method executes an until look until the condition "c == self" is satisfied. Self references the object, here 5, which the method is acting on.
Therefore ...
def myt
until c == 5 #Until this is true
yield(c) #Do this .. here yield will do whatever the block specified
c+=1 #Increment on each iteration the value of variable c by 1
end #closing the until loop
self #return self
end
The yield within the method passes control from your method to the parameter, a block, back to the method.
Yield therefore allows you to build methods which can have similar patterns but with block you customize it to do your particular need.
If instead of putting each number maybe all you want to do is put the odd integers between 0 and the integer you call the method on --
5.myt {|i| puts i if i.odd?} # returns I am odd: 1 and I am odd: 3
I would suggest that you write your own blocks here to see how yield works and how you can keep the same method but pass in different blocks and create different method outputs!

Related

Why does this block not run when it is stored in a proc?

I'm learning ruby and trying to get a better understanding of Blocks, Yield, Procs and Methods and I stumbled upon this example on using yield.
def calculation(a, b)
yield(a, b)
end
x = calculation(5,6) do|a,b|
a + b
end
puts "#{x}"
From what I understand Procs are object that holds a pointer to Blocks. And Blocks need a method to work in the first place. Also, from the way yield is used, I assume yield jumps to the block immediately after the method call.
I assume the code runs this way: calculation(5,6) calls the method calculation(). when the yield instruction executes, a and b are passed to the block after calculation(5,6). To experement and get a better understand I tried doing this.
def calculation(a, b)
yield(a, b)
end
ankh = Proc.new do |a,b|
a + b
end
x = calculation(5,6) *ankh
The error says that no block is given to calculation(). But aren't we giving calculation(5,6) the block ankh? Hopefully my question isn't too confusing.
You have a syntax error in the line x = calculation(5,6) *ankh. To pass a method as a block, you use the &-operator.
x = calculation(5,6,&ankh)
First off: what you wrote doesn't make any sense. Think about it: what does
calculation(5, 6) * ankh
mean? Or, more abstractly, what does
foo * bar
mean? Does 2 * 3 really mean "call 2 and pass 3 as a block"?
The error says that no block is given to calculation(). But aren't we giving calculation(5,6) the block ankh?
No, ankh is not a block, it's a Proc. A block is a purely syntactic construct. Most importantly, a block is not an object, so you simply cannot store it in a variable at all. You also cannot pass it as a normal argument to a method, you have to pass it as a separate "special" block argument. Blocks do not exist independent from method calls.
There is, however, a way of "converting" a Proc into a block: the & ampersand unary prefix operator:
x = calculation(5, 6, &ankh)
# => 11
This tells Ruby to take the Proc ankh and turn it into a block. In fact, this mechanism is much more general than that, because you can even pass an object which is not a Proc and Ruby will first call to_proc on that object to allow it to convert itself to a Proc.
For example, Method implements to_proc, so you can pass Methods as blocks:
def ankh(a, b) a + b end
x = calculation(5, 6, &method(:ankh))
# => 11
Also, Symbol implements to_proc:
x = calculation(5, 6, &:+)
# => 11
Lastly, Hash implements to_proc as well.
And, of course, you can write your own objects that implement to_proc:
def (ankh = Object.new).to_proc
-> *args { "I was called with arguments #{args.inspect}!" }
end
x = calculation(5, 6, &ankh)
# => 'I was called with arguments [5, 6]!'

defining my_each in terms of my_times

I'm reading The Well-Grounded Rubyist and have come across an extra credit challenge to which there is no answer.
class Array
def my_each
c = 0
until c == size
yield(self[c])
c += 1
end
self
end
end
An example is given of creating a my_each with my_times
class Array
def my_each
size.my_times do |i|
yield self[i]
end
self
end
end
With the point that many of Ruby's iterators are built on top of each and not the other way around.
Given the above my_each, how could I use it in an implementation of my_times?
To make it clear, an example of a my_times implementation was given before:
class Integer
def my_times
c = 0
until c == self
yield(c)
c += 1
end
self
end
end
5.my_times { |e| puts "The block just got handed #{e}." }
So it would seem that the question most certainly implies using my_each in an implementation of my_times.
To implement my_times using my_each, all you need to do is call my_each on an array that looks like [0, 1, ..., (x - 1)], where x is self (the Integer):
class Integer
def my_times(&block)
(0...self).to_a.my_each do |n|
yield n
end
self
end
end
P.S. If you defined my_each on Enumerable instead of Array (like the "real" each), you could remove to_a from the third line above and iterate directly over the Range, instead of converting the Range to an Array first.
In order to implement my_times we need an array to send my_each message to. At that point of the book I don't think range is covered so I implemented without using a range. Here is the solution:
require_relative "my_each"
class Integer
def my_times
array = Array.new(self)
c = 0
array.my_each do
array[c] = c
yield(c)
c += 1
end
self
end
end
Edit: I just noticed Jordan used ... instead of .. which generates the correct output; See this answer for more detail on the difference for ranges. I've updated my answer below.
My account is too new and I can't comment on Jordan's solution; I see this was posted about a year ago but I am currently reading through The Well-Grounded Rubyist and wanted to comment on the solution.
I had approached it the same in a similar way as Jordan but found that the output is off compared to; The Well-Grounded Rubyist implementation of my_times which produces:
puts 5.my_times { |i| puts "I'm on iteration # {i}!" }
I'm on iteration 0!
I'm on iteration 1!
I'm on iteration 2!
I'm on iteration 3!
I'm on iteration 4!
Jordan's solution outputs:
puts 5.my_times { |i| puts "I'm on iteration # {i}!" }
I'm on iteration 0!
I'm on iteration 1!
I'm on iteration 2!
I'm on iteration 3!
I'm on iteration 4!
I'm on iteration 5!
I used a magic number to match The Well-Grounded Rubyist output [See Jordan's solution, using ... instead of .. which removes the need for the magic number]
class Integer
def my_times
(0..(self-1)).to_a.my_each do |n|
yield n
end
self
end
end
I shortened dwyd's implementation to supply a block rather than using the do..end.
class Integer
def my_times
(0...self).to_a.my_each { |i| yield i }
end
end
Also, I don't think you need to do self-1.

Short hand way to evaluate args in ruby

I am currently using the following code in a ruby program to evaluate variable length arguments that are passed to a method. The program is running however I'm wondering if there is a short hand way to write this.
Should have been more specific in my original description, trying to rewrite the Inject method for the Array class (hence the witty name...)
Therefore it needs to be able to accept a maximum of two args, and a minimum 0 if a block is given.
array.inject(:+)
array.inject{ |output, num| output + num }
array.inject(arg, :+)
array.inject(arg) { |output, num| output + num }
The most difficult case/s to handle are the first and forth where the 1 arg can be either a Fixnum or a Symbol. As mentioned, the code works, just looking for ways to tidy it up.
class Array
def enjict(*args)
if args.length == 2 && args[0].is_a?(Fixnum) && args[1].is_a?(Symbol)
start, symbol = args
elsif args.length == 1
raise ArgumentError unless args.first.is_a?(Symbol) || args.first.is_a?(Fixnum)
symbol = args.first if args.first.is_a?(Symbol)
start = args.first if args.first.is_a?(Fixnum)
else
raise ArgumentError unless block_given?
end
copiedArray = dup
start = copiedArray.shift unless start
if block_given?
copiedArray.each { |num| start = yield(start, num) }
else
copiedArray.each { |num| start = start.send(symbol, num) }
end
start
end
end
The sad truth is: it's messy, and there's nothing you can do about it. Almost all Ruby implementations implement Enumerable#inject with privileged access to the interpreter internals, including introspection of the arguments. MRI, YARV, MRuby implement it in C, MacRuby and RubyMotion in Objective-C, XRuby and JRuby in Java, Ruby.NET and IronRuby in C#, Topaz in RPython, Cardinal in PIR, and so on.
This is something that is simply not available to Ruby code.
Only Rubinius implements it in Ruby.
You can use a similar trick by (ab)using the fact that the default argument expression for an optional parameter can be any arbitrarily complex Ruby expression and that local variables of those expressions become local variables of the method. This is a common trick for figuring out whether an argument was passed or not:
def inject(initial=(no_initial = true; nil), sym=(no_sym = true; nil))
sym, initial = initial, nil if !block_given && no_sym
# and so on …
end
Judging from the conditions, how about refactoring your method arguments to:
def enjict(start, symbol, *options, &block)
e = proc{ raise ArgumentError if options.length > 0 && !block_given? }
e.call
if start.is_a?(Fixnum) && symbol.is_a?(Symbol)
# do something you want
else
e.call
end
end

Use of yield and return in Ruby

Can anyone help me to figure out the the use of yield and return in Ruby. I'm a Ruby beginner, so simple examples are highly appreciated.
Thank you in advance!
The return statement works the same way that it works on other similar programming languages, it just returns from the method it is used on.
You can skip the call to return, since all methods in ruby always return the last statement. So you might find method like this:
def method
"hey there"
end
That's actually the same as doing something like:
def method
return "hey there"
end
The yield on the other hand, excecutes the block given as a parameter to the method. So you can have a method like this:
def method
puts "do somthing..."
yield
end
And then use it like this:
method do
puts "doing something"
end
The result of that, would be printing on screen the following 2 lines:
"do somthing..."
"doing something"
Hope that clears it up a bit. For more info on blocks, you can check out this link.
yield is used to call the block associated with the method. You do this by placing the block (basically just code in curly braces) after the method and its parameters, like so:
[1, 2, 3].each {|elem| puts elem}
return exits from the current method, and uses its "argument" as the return value, like so:
def hello
return :hello if some_test
puts "If it some_test returns false, then this message will be printed."
end
But note that you don't have to use the return keyword in any methods; Ruby will return the last statement evaluated if it encounters no returns. Thus these two are equivelent:
def explicit_return
# ...
return true
end
def implicit_return
# ...
true
end
Here's an example for yield:
# A simple iterator that operates on an array
def each_in(ary)
i = 0
until i >= ary.size
# Calls the block associated with this method and sends the arguments as block parameters.
# Automatically raises LocalJumpError if there is no block, so to make it safe, you can use block_given?
yield(ary[i])
i += 1
end
end
# Reverses an array
result = [] # This block is "tied" to the method
# | | |
# v v v
each_in([:duck, :duck, :duck, :GOOSE]) {|elem| result.insert(0, elem)}
result # => [:GOOSE, :duck, :duck, :duck]
And an example for return, which I will use to implement a method to see if a number is happy:
class Numeric
# Not the real meat of the program
def sum_of_squares
(to_s.split("").collect {|s| s.to_i ** 2}).inject(0) {|sum, i| sum + i}
end
def happy?(cache=[])
# If the number reaches 1, then it is happy.
return true if self == 1
# Can't be happy because we're starting to loop
return false if cache.include?(self)
# Ask the next number if it's happy, with self added to the list of seen numbers
# You don't actually need the return (it works without it); I just add it for symmetry
return sum_of_squares.happy?(cache << self)
end
end
24.happy? # => false
19.happy? # => true
2.happy? # => false
1.happy? # => true
# ... and so on ...
Hope this helps! :)
def cool
return yield
end
p cool {"yes!"}
The yield keyword instructs Ruby to execute the code in the block. In this example, the block returns the string "yes!". An explicit return statement was used in the cool() method, but this could have been implicit as well.

Understanding Ruby Enumerable#map (with more complex blocks)

Let's say I have a function
def odd_or_even n
if n%2 == 0
return :even
else
return :odd
end
end
And I had a simple enumerable array
simple = [1,2,3,4,5]
And I ran it through map, with my function, using a do-end block:
simple.map do
|n| odd_or_even(n)
end
# => [:odd,:even,:odd,:even,:odd]
How could I do this without, say, defining the function in the first place? For example,
# does not work
simple.map do |n|
if n%2 == 0
return :even
else
return :odd
end
end
# Desired result:
# => [:odd,:even,:odd,:even,:odd]
is not valid ruby, and the compiler gets mad at me for even thinking about it. But how would I implement an equivalent sort of thing, that works?
edit
In reality, the solution to my problem matters to me a lot less than the motivation/reasoning behind it, to help me understand more how ruby blocks work :)
You're so close. Just remove the returns and you're golden.
This is because the block passed to map is a proc (i.e. created with Proc.new), and not a lambda. A return within a proc doesn't just jump out of the proc- it jumps out of the method that executed (i.e. called call on) the proc. A return within a lambda, on the other hand, jumps out of only the lambda.
The proc method returns a lambda in Ruby 1.8, and a Proc in Ruby 1.9. It's probably best to just not use this method and be explicit with which construct you want to use.
I'm guessing you were either in IRB or a plain ruby script when you were trying this out.
a = Proc.new { return }
a.call # fails. Nothing to return from.
def foobar
a = Proc.new { return }
a.call
puts 'hello' # not reached. The return within the proc causes execution to jump out of the foobar method.
end
foobar # succeeds, but does not print 'hello'. The return within the proc jumps out of the foobar method.
b = lambda { return }
b.call # succeeds. The return only returns from the lambda itself.
def bazquux
b = lambda { return }
b.call
puts 'hello' # this is reached. The lambda only returned from itself.
end
bazquux # succeeds, and prints 'hello'
The lesson to learn from this is to use implicit returns unless you can't, I guess.
I suspect this may be a duplicate question, but to give a value out of a block, use next
simple.map do |n|
if n%2 == 0
next :even
else
next :odd
end
end
Shortest variant using Andrew's answer:
simple.map { |n| next :even if n % 2 == 0; :odd }

Resources