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.
In Ruby, you can check if an object is nil, just by calling the nil? on the object... even if the object is nil.
Well, nil is a special Ruby object used to represent an “empty” or “default” value. It's also a “falsy” value, meaning that it behaves like false when used in a conditional statement.
In Ruby, nil is a special value that denotes the absence of any value. Nil is an object of NilClass. nil is Ruby's way of referring to nothing or void.
A Proc object is an encapsulation of a block of code, which can be stored in a local variable, passed to a method or another Proc, and can be called. Proc is an essential concept in Ruby and a core of its functional programming features.
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?
{}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With