簡體   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