繁体   English   中英

当块比函数(ruby)更有用时?

[英]When blocks are more useful than functions (ruby)?

我有两个例子给出相同的结果。

带块:

def self.do_something(object_id)
  self.with_params(object_id) do |params|
    some_stuff(params)
  end
end

def self.with_params(object_id, &block)
  find_object_by_id
  calculate_params_hash
  block.call(params_hash)
end

并与方法:

def self.do_something(object_id)
  some_stuff(self.get_params(object_id))
end

def self.get_params(object_id)
  find_object_by_id
  calculate_params_hash
  params_hash
end

第二个解决方案似乎更直接,但我在应用程序代码中找到了第一个解决方案的一些用法。 我的问题是:在哪种情况下推荐第一个? 每个人的利弊是什么?

通常人们在想要在另一段代码中运行一段代码时使用块。 例子:

DB.with_shard_for_user(user_id) do |db|
  # perform operations on a user's shard

end # shard is reverted back to original value

File.new(filename) do |file|
  # work with file
end # file is closed automatically

User.transaction do
  # run some operations as a single transaction
end

这些块在它们的词汇上下文中被关闭(它们从块的声明位置捕获变量,并在调用块时将它们带到该位置)。

接受块的方法的示意结构。

def transaction
  open_transaction # pre- part

  yield if block_given? # run provided code

  commit_transaction # post- part
rescue
  rollback_transaction # handle problems
end

在您的第一个示例中,使用块可能是不合理的(恕我直言)。 太复杂了,没有明显的理由。

根据您的示例,块和函数之间的主要区别在于块在调用函数的上下文中运行

所以如果你的例子如下:

def self.do_something(object_id)
  x = "boogy on"
  self.with_params(object_id) do |params|
    some_stuff(params)
    puts x
  end
end

块中的代码可以访问在块外部定义的变量x。 这称为闭包。 如果您只是按照第二个示例调用函数,则无法执行此操作。

关于块的另一个有趣的事情是它们可以影响外部函数的控制流。 所以有可能做到:

def self.do_something(object_id)
  self.with_params(object_id) do |params|
    if some_stuff(params)
        return
    end
  end

  # This wont get printed if some_stuff returns true.
  puts "porkleworkle"
end

如果块中的some_stuff调用返回true值,则块将返回。 这将退出块并退出dosomething方法 porkleworkle不会得到输出。

在您的示例中,您不依赖于其中任何一个,因此使用函数调用可能更清晰。

但是,在许多情况下,使用块来让您利用这些东西是非常宝贵的。

当您调用with_params()时,您不仅要发送数据,还要提供一些代码来运行。 查看是否将不同的块发送到with_params()调用:

...
self.with_params(object_id) do |params|
  some_other_stuff()
  some_stuff(params)
end
...

和其他地方:

...
self.with_params(object_id) do |params|
  even_more_stuff(params)
end
...

如果块都是相同的,或者只是从一个地方调用with_params(),那么您可以考虑消除块。

总结一下:如果你想将不同的代码(块)和数据传递给方法,请使用块:hey with_params,获取此数据(object_id),顺便说一句,运行此代码(块)重新开始吧。

顺便说一句,你在两个例子中做了不同的事情:with_params()返回

some_stuff(params_hash)

在评估块之后。 而get_params()只是返回

params_hash

块完全依赖于您的代码,但函数有自己的代码。

因此,如果您的代码因情况而异,请使用block。 如果没有,请构建一个函数并将其用作块框。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM