Ruby 检查块是否为零
Ruby check if block is nil
我用块调用一个方法;
method do
"Hello"
end
方法定义为;
def method
yield
end
和定义方法时;我想检查给定的块是否为空 (nil),因为方法中的变量可能会这样结束;
method do
""
end
所以在定义中,我想检查 yield 块是否为 nil。喜欢;
def method
if yield ? yield : "Empty block? Seriously?"
end
我知道上面的方法行不通。但这是我想要实现的。
还要记住,block_given? 将永远是 "true",因为即使它是 nil[,也会给出该块=36=] 或 空字符串.
UPDATE:由于大多数 comments/answers 表示问题不清楚;这是@ndn简化的问题:
I want to check if the result of executing a block is "empty"(nil or "") without
invoking it first.
更新答案
我的 last effort 根据评论简化答案..
您可以使用 block_given?
检查块是否为空并且您需要显式检查 yield
输出是否为空,如下所示
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
程序的输出
"Hello"
"World"
"Empty block? Seriously?"
"Empty block? Seriously?"
如果我没理解错的话,你想静态地确定一个块的运行时值是多少。这是由于停机问题的不确定性而导致的许多已知不可能的问题之一。
也就是说:做不到。
不是"it can't be done in Ruby",不是"it is hard",这根本做不到,句号。它可以(并且已经)在数学上证明它无法完成。曾经.
不清楚你在问什么,因为块本身不能为空。因此,您可能指的是一些不同的东西:
缺少块。你可以检查是否给了一个块
block_given?
- 块为空体(又名
{}
或 do end
)。这并非不可能,但需要一些高级巫术 ruby 元编程魔法。一般来说,如果这就是您要找的东西,要么您正在写一些非常有趣的东西,要么您的方法完全错误。
您想在不先调用块的情况下检查执行块的结果是否为 "empty"。这是不可能的。例如,考虑以下块:
{ [nil, "", true].sample }
很明显,没有办法提前知道。
您可以调用该块。然后你可以将结果分配给一个变量并对其进行检查:
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
现在当你调用 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?"
编辑:
案例 #3 的解决方法可能是创建两个过程,一个是如果块是 "empty" 你想做什么,另一个是 - 如果不是,则将它们传递到最终调用的端点堵塞。这可能适用也可能不适用,具体取决于您的具体情况。
EDIT2:
另一种解决方法是为您的 proc 实例重新定义 Proc#call
方法。但是,这不适用于 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:另一种替代方法,有点作弊,是将给定的过程包装在另一个过程中。这样,它也适用于 yield
。
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
现在使用 wrap
的结果,您的行为类似于 secure
。
我用块调用一个方法;
method do
"Hello"
end
方法定义为;
def method
yield
end
和定义方法时;我想检查给定的块是否为空 (nil),因为方法中的变量可能会这样结束;
method do
""
end
所以在定义中,我想检查 yield 块是否为 nil。喜欢;
def method
if yield ? yield : "Empty block? Seriously?"
end
我知道上面的方法行不通。但这是我想要实现的。
还要记住,block_given? 将永远是 "true",因为即使它是 nil[,也会给出该块=36=] 或 空字符串.
UPDATE:由于大多数 comments/answers 表示问题不清楚;这是@ndn简化的问题:
I want to check if the result of executing a block is "empty"(nil or "") without invoking it first.
更新答案 我的 last effort 根据评论简化答案..
您可以使用 block_given?
检查块是否为空并且您需要显式检查 yield
输出是否为空,如下所示
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
程序的输出
"Hello"
"World"
"Empty block? Seriously?"
"Empty block? Seriously?"
如果我没理解错的话,你想静态地确定一个块的运行时值是多少。这是由于停机问题的不确定性而导致的许多已知不可能的问题之一。
也就是说:做不到。
不是"it can't be done in Ruby",不是"it is hard",这根本做不到,句号。它可以(并且已经)在数学上证明它无法完成。曾经.
不清楚你在问什么,因为块本身不能为空。因此,您可能指的是一些不同的东西:
缺少块。你可以检查是否给了一个块
block_given?
- 块为空体(又名
{}
或do end
)。这并非不可能,但需要一些高级巫术 ruby 元编程魔法。一般来说,如果这就是您要找的东西,要么您正在写一些非常有趣的东西,要么您的方法完全错误。 您想在不先调用块的情况下检查执行块的结果是否为 "empty"。这是不可能的。例如,考虑以下块:
{ [nil, "", true].sample }
很明显,没有办法提前知道。
您可以调用该块。然后你可以将结果分配给一个变量并对其进行检查:
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
现在当你调用
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?"
编辑: 案例 #3 的解决方法可能是创建两个过程,一个是如果块是 "empty" 你想做什么,另一个是 - 如果不是,则将它们传递到最终调用的端点堵塞。这可能适用也可能不适用,具体取决于您的具体情况。
EDIT2:
另一种解决方法是为您的 proc 实例重新定义 Proc#call
方法。但是,这不适用于 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:另一种替代方法,有点作弊,是将给定的过程包装在另一个过程中。这样,它也适用于 yield
。
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
现在使用 wrap
的结果,您的行为类似于 secure
。