【问题标题】:How do I do early return in ruby to reduce nested if?如何在 ruby​​ 中提前返回以减少嵌套 if?
【发布时间】:2019-05-21 18:10:25
【问题描述】:

我总是像这样使用提前返回来减少嵌套 if(使用其他语言编程):

//instead of nested if like this 
if (condition1) {
   if (condition2) {
     if (condition3) {
       //... finally meet all conditions 
       //do the job 
     }
   }
}
//return early 
if (!condition1) {
   //clean up resource in step #1
   return
}
if (!condition2) {
   //clean up resource in step #2
   return
}
if (!condition3) {
   //clean up resource in step #2
   return
}
...
//finally meet all conditions 

但是我如何在 ruby​​ 中提前返回?我无法在 Ruby 的 if 块内返回。我得到了错误

“未捕获的异常:意外返回 ... `block (2 levels) in ': 意外返回 (LocalJumpError)”

----更新-----

对不起,我忘了说,在这种简单的情况下它可以工作

def early(input)
  if (input <0)
    puts 'should >0'
    return
  end
  puts 'good'
end

我正在学习 Fiber,我使用来自 https://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers/ 的示例

def http_get(url)
  f = Fiber.current
  http = EventMachine::HttpRequest.new(url).get

  # resume fiber once http call is done
  http.callback { f.resume(1,http) }
  http.errback  { f.resume(2,http) }

  return Fiber.yield
end

EventMachine.run do
  Fiber.new{
    result = http_get('https://www.google.com/')
    if (result[0] ==2) 
      puts "error"
      return # using break has the error 'break from proc-closure (LocalJumpError)' too 
    end
    result = http_get('https://www.google.com/search?q=eventmachine')
    page = result[1]
    puts "Fetched page 2: #{page.response}"
  }.resume
end

我收到了错误。

---- 更新 2 ----

通过我得到的答案和 cmets,我找到了这个 How can I return something early from a block?

这个Why does the break statement in ruby behave differently when using Proc.new v. the ampersand sign? 解释了为什么 break 也不起作用。引用“break 应该让块的调用者返回,但 Proc.new 已经返回。”

return vs break vs next 绝对是 ruby​​ 新手的障碍

【问题讨论】:

  • “我不能在 Ruby 中的 if 块内返回”——当然可以。
  • 我现在得到“未捕获的异常:意外返回”
  • 您能说明您遇到问题的方法吗?只要您在方法中,提前返回通常应该有效。
  • 另外,我想说ifs 已经是代码异味了,但是as many ifs 是一个明确的信号,必须尽快重构代码。
  • @JörgWMittag 请查看我的更新问题。

标签: ruby coding-style guard-clause


【解决方案1】:

使用next而不是return提前退出内部块:

class A 
  def run 
    yield
  end
end

a = A.new
a.run do 
  puts "ola"
  next
  puts "hello"
end

为了使用return,它应该直接放在方法体内。

但是,当您使用EventMachine.run doFiber.new{ 将块传递给函数时,块内的代码并不直接在函数内部,而是作为参数传递给不同的函数。在区块内你不能调用return,但你可以使用next提前退出。

我猜设计师之所以决定这样做是因为块内的return 会导致块是否返回或整个方法的混淆。

【讨论】:

  • 嗯。和我的回答有什么不同?
  • @AlekseiMatiushkin:除非我误解了,否则你的回答建议使用tap,我的没有
  • 不管是taprun,还是foo;重要的是,ruby 中的块可以被break 打断。无论如何。
  • 您好,您能解释一下为什么 break 有效,而 return 无效,我什么时候应该使用一个而不是另一个?我现在正在学习 ruby​​,有些语法对我来说总是很奇怪(来自 C)。谢谢!
  • @Qiulang: return 从最近的词法封闭方法体返回。没有包含您的return 的方法主体。 next 从最近的词法封闭块返回。 break 从最近的词法封闭块返回,并向块发出信号yielding 方法以停止迭代。因此,如果您使用Enumerable#each 之类的方法,例如,next 将跳到下一次迭代,break 将完全中止迭代。
猜你喜欢
  • 2012-01-16
  • 1970-01-01
  • 2016-10-19
  • 2012-05-13
  • 1970-01-01
  • 2013-01-22
  • 2021-11-09
  • 1970-01-01
相关资源
最近更新 更多