在Ruby中使用什么是|| = begin .... end block?

时间:2016-01-06 08:08:46

标签: ruby-on-rails ruby

这两个代码段有什么区别:

String p = "Value1:100,Value2:2000,Value3:30000:";
int firstComma = p.indexOf(',');
if(firstComma >= 0) {
    p = p.substring(0, firstComma);
}
String tuple[] = p.split(":");

   def config
    @config ||= begin
      if config_exists?  
        @config = return some value
      else
        {}
      end
    end
  end

我与" def config @config ||= method end def method if config_exists? return some value else {} end end ... begin"混淆了块。输出有什么不同吗?如果没有,那么end ... begin块的使用方法是什么?

4 个答案:

答案 0 :(得分:14)

首先,您需要知道定义的方法本身就包含begin ... end块的功能。

在异常处理的上下文中,def method_name ... end在功能上等同于begin ... end。例如,两者都可以包含rescue语句。

您共享的两个代码块实际上是相同的,并且一个代码中没有任何好处......除非您在多个地方需要method。在这种情况下,您可以通过将逻辑放入单个方法并从多个其他位置调用来干掉代码。

答案 1 :(得分:5)

在您的情况下,您甚至可以省略begin ... end块:

@config ||=
  if config_exists?  
    return_some_value
  else
    {}
  end

或使用ternary if

@config ||= config_exists? ? return_some_value : {}
  

输出有什么不同吗?

可以有所作为,因为与def ... end不同,begin ... end块不会创建新的变量范围。

这是一个人为的例子:

def foo
  a = 456  # doesn't affect the other a
end

a = 123
b = foo

p a: a, b: b #=> {:a=>123, :b=>456}

对战:

a = 123
b = begin
  a = 456  # overwrites a
end

p a: a, b: b #=> {:a=>456, :b=>456}

答案 2 :(得分:5)

使用||= begin...end可以memoize begin...end中运行的结果https://pypi.python.org/pypi/pyGeoTile。这对于缓存资源密集型计算的结果非常有用。

答案 3 :(得分:-1)

唯一不同的是,如果引发异常。例如,我们假设config_exists?方法调用中存在问题。如果它在第一个示例中引发异常,则@config var将设置为{}。在第二个例子中,如果同样的事情发生,你的程序将崩溃。

作为旁注,此处不需要return关键字。实际上,该示例应如下所示。这是假设我理解意图。

def config
  @config ||= 
    begin
      if config_exists?    
        some_value
      else
        {}
      end
    rescue
      {}
    end
end

def config
  @config ||= method
end

def method
  if config_exists?
    some_value
  else
    {}
  end
end

两个示例完全相同,除非在第一个示例中引发异常@config仍将设置为= some_value

此外,应该注意的是,如果@config已经有值,则不会发生任何事情。 ||=运算符与:

相同
@config = some_value if @config.nil?

如果当前为零,则仅将变量设置为此值。

希望这有用,我正确理解你的问题。