I found following code at the internet
class Test
def value
'string'
end
def inspect
'value'
end
end
def test(arg)
arg.tap { |i| i.value }
end
p test(Test.new)
Could anyone explain why it returns
p test(Test.new)
# >> value
Because arg.tap returns arg itself, and p prints arg.inspect, since you have overwritten theinspect method of Test, it returns a string 'value', so you the print result is value
see also:
- p vs puts in Ruby
- tap method
tap used for chain of methods. It runs the passed blocked and returns the input without any change.
It means
arg.tap { |i| i.value } will return arg
p method runs inspect method of passed object
Related
I've got some code:
def my_each_with_index
return enum_for(:my_each_with_index) unless block_given?
i = 0
self.my_each do |x|
yield x, i
i += 1
end
self
end
It is my own code, but the line:
return enum_for(:my_each_with_index) unless block_given?
is found in solutions of other's. I can't get why they passed the function to enum_for as a parameter. When I invoke my function without a block, it won't return anything with or without enum_for. I could left sth like:
return unless block_given?
and it has the same result. Or am I wrong?
Being called without a block, it will return an enumerator:
▶ def my_each_with_index
▷ return enum_for(:my_each_with_index) unless block_given?
▷ end
#⇒ :my_each_with_index
▶ e = my_each_with_index
#⇒ #<Enumerator: main:my_each_with_index>
later on you might iterate on this enumerator:
▶ e.each { |elem| ... }
This behavior is specifically useful in some cases, like lazy iteration, passing block to this enumerator later etc.
Just returning nil cuts this ability off.
Think you for very precise answer. I recived also very good example to understand this issue for other new developers:
def iterator
yield 1
yield 2
yield 3
puts "koniec"
end
iterator { |v| puts v }
it = enum_for(:iterator)
puts it.next
puts it.next
puts it.next
puts it.next
Just run and analyze this code.
For any method that accepts a block, a good method implementation should have a well-defined behavior when the block is not given.
In the example shared by you, each_for_index is being re-implemented by author, may be to provide additional semantics or may be just for academic purpose given that its behavior is same as Ruby's Enumerable#each_with_index.
The documentation has following for Enumerable#each_with_index.
Calls block with two arguments, the item and its index, for each item
in enum. Given arguments are passed through to each().
If no block is given, an enumerator is returned instead.
In order to stay consistent with highlighted line indicating what should be the behavior if block is not given, one has to use something like
return enum_for(:my_each_with_index) unless block_given?
enum_for is interesting method
enum_for creates a new Enumerator which will enumerate by calling method on obj.
Below is an example reproduced from documentation:
str = "xyz"
enum = str.enum_for(:each_byte)
enum.each { |b| puts b }
# => 120
# => 121
# => 122
So, if one does not pass block to my_each_with_index, they have a chance to pass it later - just like one would have done with each_with_index.
e = obj.my_each_with_index
...
e.each { |x, i| # do something } # `my_each_with_index` executed later
In summary, my_each_with_index tries to be consistent with each_with_index and tries to be a well-behaved API.
I call a method with a block;
method do
"Hello"
end
and the method is defined as;
def method
yield
end
and when defining method; i want to check if given block is empty (nil) or not, because the variable in the method may end up like this;
method do
""
end
So in definition, i want to check if the yield block is nil or not. Like;
def method
if yield ? yield : "Empty block? Seriously?"
end
I know the above does not work. Bu it is what i want to achieve.
Also keep in mind that block_given? will always be "true" since the block is given even if it is nil or empty string.
UPDATE: As most of the comments/answers state that the question is unclear; here is the problem simplified by #ndn:
I want to check if the result of executing a block is "empty"(nil or "") without
invoking it first.
It is unclear what you are asking, because a block itself can not be empty. Therefore, you might mean a few different things:
A missing block. You can check if a block is given
block_given?
Block with empty body (aka {} or do end). This is not impossible, but requires some advanced voodoo ruby metaprogramming magic. Generally, if this is what you are looking for, either you are writing something very interesting or your approach is completely wrong.
You want to check if the result of executing a block is "empty" without invoking it first. This is impossible. For example, consider the following block:
{ [nil, "", true].sample }
Obviously, there is no way to know in advance.
You are ok with calling the block. Then you can assign the result to a variable and make checks on it:
def some_method
evaluation_result = yield if block_given?
if evaluation_result.nil? or evaluation_result == ""
# do something if the block was not given or the result is nil/empty
puts "Empty block? Seriously?"
else
# do something if the block was given and the result is non nil/empty
puts evaluation_result
end
end
Now when you invoke some_method:
some_method { "something" } # => "something"
some_method { 3 + 5 } # => 8
some_method { nil } # => "Empty block? Seriously?"
some_method { "" } # => "Empty block? Seriously?"
some_method { } # => "Empty block? Seriously?"
some_method # => "Empty block? Seriously?"
EDIT:
A workaround for case #3 might be to create two procs, one with what you want to do if the block is "empty" and one - if it is not, then pass them around to the endpoint where you will finally invoke the block. This might or might not be applicable depending on your exact situation.
EDIT2:
Another workaround can be to redefine the Proc#call method for your proc instances. However, this doesn't work for yield:
def secure(&block)
insecure_call = block.method(:call)
block.define_singleton_method(:call) do
insecure_call_result = insecure_call.call
if insecure_call_result.nil? or insecure_call_result == ""
"<b>Bummer! Empty block...</b>"
else
insecure_call_result
end
end
end
x = proc { }
y = proc { "" }
z = proc { nil }
a = proc { 3 + 5 }
b = proc { "something" }
u = proc { [nil, "", true].sample }
[x, y, z, a, b, u].each { |block| secure &block }
# some method that uses the block
def user(&block)
"What I got is #{block.call}!"
end
user &x # => "What I got is <b>Bummer! Empty block...</b>!"
user &y # => "What I got is <b>Bummer! Empty block...</b>!"
user &z # => "What I got is <b>Bummer! Empty block...</b>!"
user &a # => "What I got is 8!"
user &b # => "What I got is something!"
user &u # => Different each time
EDIT3: Another alternative, which is sort of cheating, is to wrap the given proc in another proc. This way, it will work for yield too.
def wrap(&block)
proc do
internal_proc_call_result = block.call
if internal_proc_call_result.nil? or internal_proc_call_result == ""
"<b>Bummer! Empty block...</b>"
else
internal_proc_call_result
end
end
end
Now using the result of wrap and will get you behavior similar to secure.
If I understand correctly, you want to statically determine what the runtime value of a block is. This is one of the many known impossible problems resulting from the undecidability of the Halting Problem.
In other words: it can't be done.
Not "it can't be done in Ruby", not "it is hard", it simply can't be done, period. And it can be (and has been) mathematically proven that it can't be done. Ever.
UPDATED Answer
My last effort to simplify the answer based on comments..
You can check for block emptiness with block_given? and you need to explicitly check for yield output for emptiness like below
def method(&block)
# Below if condition is to prove that block can be accessed
if block_given?
p block
p block.yield
end
b = yield if block_given?
(b.nil? || b.empty?) ? "Empty block? Seriously?" : b
end
p method {"Hello"} # inline block
result = method do
"World"
end
p result
p method # No blocks provided
p method {""} # Block that returns empty string
Output of the program
"Hello"
"World"
"Empty block? Seriously?"
"Empty block? Seriously?"
There are many examples how to pass Ruby block as an argument, but these solutions pass the block itself.
I need a solution that takes some variable, executes an inline code block passing this variable as a parameter for the block, and the return value as an argument to the calling method. Something like:
a = 555
b = a.some_method { |value|
#Do some stuff with value
return result
}
or
a = 555
b = some_method(a) { |value|
#Do some stuff with value
return result
}
I could imagine a custom function:
class Object
def some_method(&block)
block.call(self)
end
end
or
def some_method(arg, &block)
block.call(arg)
end
but are there standard means present?
I think, you are looking for instance_eval.
Evaluates a string containing Ruby source code, or the given block, within the context of the receiver (obj). In order to set the context, the variable self is set to obj while the code is executing, giving the code access to obj’s instance variables. In the version of instance_eval that takes a String, the optional second and third parameters supply a filename and starting line number that are used when reporting compilation errors.
a = 55
a.instance_eval do |obj|
# some operation on the object and stored it to the
# variable and then returned it back
result = obj / 5 # last stament, and value of this expression will be
# returned which is 11
end # => 11
This is exactly how #Arup Rakshit commented. Use tap
def compute(x)
x + 1
end
compute(3).tap do |val|
logger.info(val)
end # => 4
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.
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 }