gpt4 book ai didi

Ruby 检查 block 是否为零

转载 作者:数据小太阳 更新时间:2023-10-29 06:47:50 25 4
gpt4 key购买 nike

我用 block 调用一个方法;

method do
"Hello"
end

方法定义为;

def method
yield
end

以及在定义方法时;我想检查给定的 block 是否为空 (nil),因为方法中的变量可能会像这样结束;

method do
""
end

所以在定义中,我想检查 yield block 是否为 nil。喜欢;

def method
if yield ? yield : "Empty block? Seriously?"
end

我知道上面的方法行不通。但这正是我想要实现的目标。

另外请记住,block_given? 将始终为“true”,因为即使 block 是 nil空字符串 也已给出.

更新:由于大多数评论/答案都表示问题不清楚;这是@ndn 简化的问题:

I want to check if the result of executing a block is "empty"(nil or "") without invoking it first.

最佳答案

不清楚你在问什么,因为 block 本身不能为空。因此,您可能指的是一些不同的东西:

  1. 缺失的 block 。你可以检查是否给了一个 block

    block_given?
  2. 包含空主体的 block (又名 {}do end)。这并非不可能,但需要一些高级的 voodoo ruby​​ 元编程魔法。一般来说,如果这就是您要寻找的东西,要么您正在写一些非常有趣的东西,要么您的方法完全错误。
  3. 您想在不首先调用 block 的情况下检查执行 block 的结果是否为“空”。这是不可能的。例如,考虑以下 block :

    { [nil, "", true].sample }

    显然,没有办法提前知道。

  4. 您可以调用该 block 。然后您可以将结果分配给一个变量并对其进行检查:

    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 的解决方法可能是创建两个过程,一个是如果 block 为“空”时您想执行的操作,另一个是如果不是,则将它们传递到您最终将调用该 block 的端点。这可能适用也可能不适用,具体取决于您的具体情况。

编辑 2:另一种解决方法是为您的 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 的行为。

关于Ruby 检查 block 是否为零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31772146/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com