Ruby检查块是否为nil

Ruby检查块是否为nil,ruby,yield,Ruby,Yield,我用一个块调用一个方法 method do "Hello" end 该方法定义为: def method yield end 定义方法时;我想检查给定的块是否为空(nil),因为方法中的变量可能会这样结束 method do "" end 因此,在定义中,我想检查屈服块是否为零。喜欢 def method if yield ? yield : "Empty block? Seriously?" end 我知道上述方法不起作用。但这是我想要实现的 还请记住,块\u给定?将始

我用一个块调用一个方法

method do
  "Hello"
end
该方法定义为:

def method
  yield
end
定义方法时;我想检查给定的块是否为空(nil),因为方法中的变量可能会这样结束

method do
  ""
end
因此,在定义中,我想检查屈服块是否为零。喜欢

def method
  if yield ? yield : "Empty block? Seriously?"
end
我知道上述方法不起作用。但这是我想要实现的

还请记住,块\u给定?将始终为“true”,因为该块即使是nil或空字符串也会被给定

更新:因为大多数评论/回答都表示问题不清楚;以下是@ndn简化的问题:

我想检查执行一个块的结果是否为“空”(nil或“”),而不显示 首先调用它


更新的答案 我的建议是根据评论简化答案

您可以使用
block\u gived?
检查块的空性,您需要明确检查
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?"

如果我理解正确,您希望静态地确定块的运行时值。这是由于停止问题的不可判定性而导致的许多已知不可能的问题之一

换句话说,这是不可能做到的


不是“用Ruby做不到”,也不是“很难”,就是说根本做不到。从数学上可以(并且已经)证明这是不可能的。永远。

不清楚你在问什么,因为块本身不可能是空的。因此,您可能指的是几件不同的事情:

  • 丢失的街区。您可以检查是否给定了块

    block_given?
    
  • 块体为空(aka
    {}
    do end
    )。这并非不可能,但需要一些先进的voodoo ruby元编程魔法。一般来说,如果这就是你想要的,要么你正在写一些非常有趣的东西,要么你的方法完全错误
  • 您希望检查执行块的结果是否为“空”,而不首先调用它。这是不可能的。例如,考虑下面的块:

    { [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
    
    现在,当您调用某个\u方法时:

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

    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
    

    现在使用
    wrap
    的结果,并将使您的行为类似于
    secure

    这与
    block\u given有何不同?
    OP说这不能解决他的问题?(尽管从这个问题上还不清楚OP的问题是什么。)@JörgWMittag似乎都在做同样的事情。我错过了block_given?部分,除了我自己是个新手。如果我使用
    block\u给定而不是
    块?
    -获得相同的输出。也许我误解了这个问题。OP询问如何检查收益率的输出是否为空白string@J对不起,我的问题不清楚。我试着尽我所能的具体点。@WandMaker我刚刚检查了这个,b=如果给出块_,收益率?实际上,它会产生块。因此,yield是在调用时产生块(如果没有给出块,则抛出错误),即使调用它是为了赋值。所以没有帮助。但是谢谢。@1.44mb我在我的解决方案中提供了4个测试用例。您能告诉我您运行的是哪个附加测试用例吗?如果我理解正确,您希望在屈服之前知道块返回的值是
    nil
    还是
    。这是不可能的。如果不是这样,您可以将
    yield
    的结果分配给一个变量,并对其进行
    nil?
    empty?
    检查。是的,您是正确的。是的,如果我像@WandMaker的答案中那样分配它,如果未给出块,则会给出错误。所以你说在屈服之前没有可能知道块内容是nil还是“”。这篇文章是关于这个话题的来源还是讨论等,以便我了解更多?谢谢。好的,让我写一个答案……谢谢你的详细解释。我的情况是3。我正在为rails开发一个helper类,一个空变量可能会出现在一个块中。(特别是当块通过变量动态发送时,该变量恰好为nil或“”)。所以在我的助手中,我必须检查块是否为空,并根据这一点构建正确的html输出。如果我确实喜欢第四种方法(也是@WandMaker的答案),则在我对评估结果进行赋值时输出收益结果。但我只想检查一下,然后在其他地方输出收益率。请不要使用“空变量”或“空块”作为表达式(如果很清楚您指的是#2情况,则后者可能可以)。如我所说,如果你真的是指3,那是不可能的。为了证明这一点,简单的健全性检查将是一个随机返回结果的块(如上面的答案所示)或一个永远不会返回的块(例如,无止境循环)。正如@Jörg所说,这就是所谓的停顿问题,是无法解决的。我接受这个答案,因为这是对这个问题最详细、最直接的解释。谢谢。@1.44mb,还有另一种选择。:)我明白了,一个包含10000行返回
    nil
    的代码的块是“空的”。谢谢Jörg的清晰解释。我很满意,但我渴望更多地阅读背后的技术原因(从编程和数学方面)。这是一个很好的起点。
    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