명시 적 수익이 왜 Proc에 차이를 만드는가?
-
07-07-2019 - |
문제
def foo
f = Proc.new { return "return from foo from inside proc" }
f.call # control leaves foo here
return "return from foo"
end
def bar
b = Proc.new { "return from bar from inside proc" }
b.call # control leaves bar here
return "return from bar"
end
puts foo # prints "return from foo from inside proc"
puts bar # prints "return from bar"
나는 생각했다 return
키워드는 루비에서 선택 사항이며 항상 return
요청 여부에 관계없이. 그 점을 감안할 때, 나는 그것이 놀랍습니다 foo
그리고 bar
사실에 의해 다른 출력을 결정합니다 foo
명시 적으로 포함됩니다 return
안에 Proc f
.
왜 이것이 왜 그런지 아는 사람이 있습니까?
해결책
루비에는 세 가지 구성이 있습니다.
- ㅏ 차단하다 대상이 아니며에 의해 만들어집니다
{
...}
또는do
...end
. - ㅏ Proc a
Proc
생성 된 개체Proc.new
또는proc
. - ㅏ 람다 a
Proc
만들어졌습니다lambda
(또는proc
루비 1.8).
Ruby에는 세 가지 키워드가 있습니다.
return
방법이나 람다가 종료됩니다.next
블록, Proc 또는 Lambda를 종료합니다.break
블록에 양보 된 방법을 종료하거나 Proc 또는 Lambda를 호출 한 방법을 종료합니다.
람다에서 return
처럼 행동합니다 next
, 이유가 무엇이든지. next
그리고 break
그들이 다음과 같은 방법으로 가장 일반적으로 사용되기 때문에 그 방식으로 명명되었습니다. each
, 블록을 종료하면 반복이 다음 컬렉션의 요소 및 종료 each
당신을 초래할 것입니다 부서지다 루프 밖으로.
사용하는 경우
return
정의 내부 foo
, 당신은에서 돌아올 것입니다 foo
, 블록이나 Proc 내부에 있더라도. 블록에서 돌아 오려면 next
대신 키워드.
def foo
f = Proc.new { next "return from foo from inside proc" }
f.call # control leaves foo here
return "return from foo"
end
puts foo # prints "return from foo"
다른 팁
이것은 의미론입니다 Proc
에스; 반드시 모든 블록의 의미론은 아닙니다. 나는 이것이 약간 혼란 스럽다는 데 동의한다. 유연성이 추가 될 수 있습니다 (아마도 루비는 구현을 제외하고는 사양이 없을 것입니다).
동작은 다음에 정의됩니다 Proc
구현. Lambda
S는 다르게 행동하므로 원한다면 return
에스 종료하지 마십시오 둘러싸는 방법에서 사용하십시오 람다. 또는 생략하십시오 return
귀하의 키워드 Proc
.
Rubys 폐쇄에 대한 깊은 조사 여기에. 환상적인 엑스포입니다.
그래서:
def foo
f = Proc.new {
p2 = Proc.new { return "inner proc"};
p2.call
return "proc"
}
f.call
return "foo"
end
def foo2
result = Proc.new{"proc"}.call
"foo2 (proc result is: #{result})"
end
def bar
l = lambda { return "lambda" }
result = l.call
return "bar (lambda result is: #{result})"
end
puts foo
# inner proc
puts foo2
# foo (proc result is: proc)
puts bar
# bar (lambda result is: lambda)
이런 식으로 생각하십시오 : Proc.new 단지 호출 함수의 일부인 코드 블록을 만듭니다. Proc/Lambda는 특별한 바인딩이있는 익명 기능을 만듭니다. 작은 코드 예제가 도움이됩니다.
def foo
f = Proc.new { return "return from foo from inside Proc.new" }
f.call # control leaves foo here
return "return from foo"
end
동일합니다
def foo
begin
return "return from foo from inside begin/end" }
end
return "return from foo"
end
따라서 반품이 'foo'함수에서 돌아올 것임이 분명합니다.
대조적으로 :
def foo
f = proc { return "return from foo from inside proc" }
f.call # control stasy in foo here
return "return from foo"
end
(이 예에서 사용되지 않으므로 바인딩을 무시하는 것과 같습니다) : :
def unonymous_proc
return "return from foo from inside proc"
end
def foo
unonymous_proc()
return "return from foo"
end
FOO에서 돌아 오지 않고 다음 진술로 계속 진행하지 않습니다.