Ruby检查块是否为零

1.4*_*4mb 10 ruby yield

我用一个块调用一个方法;

method do
  "Hello"
end
Run Code Online (Sandbox Code Playgroud)

并且该方法被定义为;

def method
  yield
end
Run Code Online (Sandbox Code Playgroud)

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

method do
  ""
end
Run Code Online (Sandbox Code Playgroud)

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

def method
  if yield ? yield : "Empty block? Seriously?"
end
Run Code Online (Sandbox Code Playgroud)

我知道上面的内容不起作用.这就是我想要实现的目标.

另请记住block_given?将始终为"true",因为即使它是nil空字符串,也会给出块.

更新:由于大多数意见/答案都表明问题不明确; 这是@ndn简化的问题:

我想检查执行块的结果是否为"空"(nil或"")而不先调用它.

ndn*_*kov 15

目前还不清楚你在问什么,因为一个块本身不能为空.因此,您可能意味着一些不同的事情:

  1. 丢失的块.您可以检查是否给出了阻止

    block_given?
    
    Run Code Online (Sandbox Code Playgroud)
  2. 阻止空体(又名{}do end).这并非不可能,但需要一些先进的伏都教红宝石元编程魔法.一般来说,如果这是你正在寻找的,要么你正在写一些非常有趣的东西,要么你的方法是完全错误的.
  3. 您想要检查执行块的结果是否为"空"而不先调用它.这是不可能的.例如,请考虑以下块:

    { [nil, "", true].sample }
    
    Run Code Online (Sandbox Code Playgroud)

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

  4. 你可以调用块.然后,您可以将结果分配给变量并对其进行检查:

    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
    
    Run Code Online (Sandbox Code Playgroud)

    现在你调用的时候 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?"
    
    Run Code Online (Sandbox Code Playgroud)

编辑:案例#3的解决方法可能是创建两个proc,一个是你想要做的,如果块是"空",一个 - 如果不是,然后将它们传递到你将最终调用的端点块.根据您的具体情况,这可能适用也可能不适用.

EDIT2:另一种解决方法是重新定义Proc#callproc实例的方法.但是,这不起作用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
Run Code Online (Sandbox Code Playgroud)

EDIT3:另一种替代方案,就是作弊,是将给定的proc包装在另一个proc中.这样,它将起作用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
Run Code Online (Sandbox Code Playgroud)

现在使用结果,wrap将会得到类似的行为secure.


Wan*_*ker 6

更新答案最后的努力,根据评论简化答案..

你可以检查块空虚,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
Run Code Online (Sandbox Code Playgroud)

该计划的输出

"Hello"
"World"
"Empty block? Seriously?"
"Empty block? Seriously?"
Run Code Online (Sandbox Code Playgroud)


Jör*_*tag 6

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

换句话说:它无法完成.

不是"它不能在Ruby中完成",而不是"它很难",它根本无法完成,期间.它可以(并且已经)在数学上证明它无法完成.永远.