블록이 함수보다 유용 할 때 (Ruby)?
-
16-12-2019 - |
문제
동일한 결과를주는 두 가지 예제가 있습니다.
블록 :
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
.
두 번째 솔루션은 더 간단 해 보이지만 응용 프로그램 코드에서 첫 번째 사용을 발견했습니다.내 질문은 다음과 같습니다. 첫 번째 첫 번째 상황은 권장됩니까?각각의 장단점은 무엇입니까?
해결책
블록과 함수의 주요 차이점은 블록이 호출 함수의 컨텍스트 내에서 을 실행한다는 것입니다.
다음과 같은 예 :
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 호출이 실제 값을 반환하면 블록이 반환됩니다. 이것은 블록 및 DoSomething 방법 에서 벗어날 것입니다. Porkleworkle 은 출력되지 않습니다.
예제에서는 이들 중 하나에 의존하지 않으므로 함수 호출을 사용하면 훨씬 깨끗합니다.
그러나 이러한 일들을 이용할 수 있도록 블록을 사용하는 것이 많은 상황이 있습니다.
다른 팁
일반적으로 사람들은 다른 코드 내부의 코드 조각을 실행하려는 경우 블록을 사용합니다.예 :
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
.
첫 번째 예에서 블록의 사용은 아마도 부적절하지 않을 것입니다 (IMHO).명백한 이유가 없어도 너무 복잡합니다.
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_params,이 데이터 (object_id)를 취하고,이 코드를 실행하십시오 (블록)당신이 그것에있는 동안.
btw 두 예제에서 다른 작업을 수행 중입니다. with_params ()는
를 반환합니다.some_stuff(params_hash)
.
블록을 평가 한 후 .get_params ()
를 반환합니다.params_hash
. 블록은 코드에 완전히 의존하지만 함수에는 자체 코드가 있습니다.
그래서, 코드가 상황에 따라 상황을 변화 시키면 블록을 사용하십시오. 그렇지 않은 경우 함수를 작성하고 블록 상자로 사용하십시오.