Clojure 선물과 약속은 어떻게 다릅니 까?


86

선물과 약속은 모두 가치를 계산할 때까지 차단됩니다. 그렇다면 이들의 차이점은 무엇입니까?


8
질문에 -1이 왜 있는지 잘 모르겠습니다. 또는 지금 나쁜 것을 묻기 전에 답을 모르는 질문입니까?
그냥 내 정확한 OPINION

나는 대답 중 -1하지 않았다 ?? 질문이나 답변에 -1을 넣은 사람을 어떻게 알 수 있습니까?
appshare.co 2011 년

너와 난 못해, Zubair. 질문하기에 완벽하게 합리적인 질문이고 분명히 주제에 부합한다는 점을 감안할 때 질문에 -1을 넣은 사람이 궁금합니다.
그냥 내 정확한 OPINION

답변:


54

Clojure 용어로 대답하면 다음은 Sean Devlin의 스크린 캐스트의 몇 가지 예입니다 .

(def a-promise (promise))
(deliver a-promise :fred)

(def f (future (some-sexp)))
(deref f)

promise에서는 나중에 계산 ( :fred이 경우)에서 선택한 값을 명시 적으로 제공합니다 . 반면에 미래는 창조되었던 곳에서 소비되고 있습니다. 은 some-expr아마도 뒤에서 출시 탠덤 (결국)에서 계산하지만 시간에 의해 평가되지 않은 남아있는 경우 사용할 수있을 때까지이 스레드 블록을 액세스 할 수있다.


추가하기 위해 편집 됨

약속과 미래를 더 잘 구별하려면 다음 사항에 유의하십시오.

약속

  1. 당신은을 만들 promise. 이제 약속 객체를 모든 스레드에 전달할 수 있습니다.
  2. 계산을 계속합니다. 이는 부작용, 데이터 다운로드, 사용자 입력, 데이터베이스 액세스, 기타 약속과 관련된 매우 복잡한 계산 일 수 있습니다. 코드는 모든 프로그램의 메인 라인 코드와 매우 유사합니다.
  3. 완료되면 deliver약속 객체에 대한 결과를 얻을 수 있습니다 .
  4. deref계산이 끝나기 전에 약속 을 시도하는 모든 항목 은 완료 될 때까지 차단됩니다. 완료 deliver하고 약속을 준수하면 약속이 더 이상 차단되지 않습니다.

미래

  1. 당신은 당신의 미래를 창조합니다. 미래의 일부는 계산을위한 표현입니다.
  2. 미래는 동시에 실행될 수도 있고 실행되지 않을 수도 있습니다. 풀에서 스레드를 할당 할 수 있습니다. 기다렸다가 아무것도하지 않을 수 있습니다. 당신의 관점에서 당신은 말할 수 없습니다 .
  3. 어느 시점에서 당신 (또는 다른 스레드) deref은 미래입니다. 계산이 이미 완료된 경우 결과를 얻을 수 있습니다. 아직 완료되지 않은 경우 완료 될 때까지 차단합니다. (아마도 아직 시작되지 않았다면 deref실행이 시작되었음을 의미하지만 이것도 보장되지는 않습니다.)

Promise 생성 이후의 코드만큼 복잡하게 표현할 있지만 , 그것이 바람직한지는 의심 스럽습니다. 즉, 미래는 빠르고 배경이 가능한 계산에 더 적합하고 약속은 크고 복잡한 실행 경로에 더 적합합니다. 또한 사용 가능한 계산 측면에서 약속은 작업을 수행하는 약속 생성자와 수확을 거두는 또 다른 스레드에 대해 조금 더 유연하고 지향적 인 것처럼 보입니다. 퓨처는 스레드를 자동으로 시작하고 (추악하고 오류가 발생하기 쉬운 오버 헤드없이) 원래 스레드가 결과를 필요로 할 때까지 다른 작업을 계속하는 방향으로 향합니다.


그러나 약속 또는 미래가 완료 될 때까지 모든 계산 블록을 가질 수 있습니다. 즉 : (@a + @b)는 미래와 약속 모두에서 동일하게 작동합니다
appshare.co 2011 년

2
약속은 더 많은 유연성을 제공합니다. 나는 약속을 만든다. 나는 그 약속을 다른 스레드에 전달합니다. 그런 다음 I / O 대기, 인터넷에서 데이터 다운로드, 사용자 입력 대기 등 복잡한 계산을 많이 수행 할 수 있습니다. 모든 작업이 완료되면 결과 값으로 약속을 전달합니다. 미래는 하나의 S- 표현을 다룹니다. 제 생각에는 그것은 매우 매우 복잡한 S- 표현 일 수 있습니다. 또한 퓨처는 스레드 (또는 풀)에서 자동으로 작업을 수행합니다. 약속에서 똑같이하는 것은 더 많은 일을 의미 할 것입니다.
그냥 내 올바른 의견

FWIW 단일 s- 표현식은 임의의 코드 경로에 대한 호출이 될 수 있기 때문에 식에 얼마나 많은 코드를 넣을 수 있는지에 대한 것은 아닙니다. 그래서 약속이 "더 유연하다"고 말하는 대신 목적이 단순히 다르다고 말하고 싶습니다. 그렇지 않으면 왜 둘 다 있습니까?
Geoff

2
기록을 위해 future통화 본문 에는 N 개의 sexpr이 포함될 수 있습니다.
vemv dec

이 설명의 Clojure 문서의 일부가되어야합니다
Piyush Katariya

25

Future와 Promise는 모두 생산자에서 소비자에게 비동기 계산의 결과를 전달하는 메커니즘 입니다. Future

경우 계산 은 Future 생성시 정의되고 비동기 실행은 "ASAP"시작됩니다. 또한 비동기 계산을 생성하는 방법을 "알고"있습니다. 경우 약속 계산 , 그 개시 시간 및 [수] 비동기 호출이 전달기구로부터 분리된다. 경우 연산 결과 가능 프로듀서 호출해야 또한 생산자 제어 의미 명시 결과가 가능해진다.

deliver

들어 약속 Clojure의 동일한 오브젝트 (의 결과를 사용하여 설계 실수를 promise모두 생산 (에 호출) deliver) 및 소비 ( deref)의 결과를 계산 . 이는 매우 뚜렷한 두 가지 기능이므로 그렇게 취급해야합니다.


@oskarkv 약속을 작성하여 3 명의 고객에게 주었다고 가정합니다. 클라이언트 중 하나가 가짜 결과로 문제를 해결하고 다른 두 클라이언트에게 신호를 보내는 것을 막는 것은 없습니다. 또한 더 이상이 약속을 해결할 수 없습니다. 반대로 promise + resolver 쌍이 있고 고객에게 약속을주고 스스로 해결자를 유지했다면이 시나리오는 불가능 해집니다. 더 많은 정보를 위해 추천 검색어는 "기능 기반 액세스 제어"및 "기능 기반 보안"입니다.
Dimagog

1
보안을 간단한 참조 유형 (impl 확인)에 결합하는 promise것이 편리한 지 여부는 확실하지 않습니다 . '악한'소비자는 드뭅니다. 약속 위에 자신 만의 추상화를 구축하는 것을 막을 수있는 것은 없습니다.
vemv

8
보안에 관한 것이 아니라 기능 기반 프로그래밍이 보안과 관련하여 설명되는 경우가 많습니다. 여기에서는 코드 정확성에 관한 것입니다. 자주 사용되는 용어는 "정확한 구성"이며 ​​질문은 "잘못된 프로그램을 구성 할 수 있습니까?"입니다. 고의가 아니라 우연입니다. 하나의 Promise 객체로는 할 수 있지만 두 개의 개별 객체로는 할 수 없습니다.
Dimagog

그건 경우 비록 배달 할 수없는 약속을 반환에서 당신을 중지 아무것도 당신이 원하는, 없습니다 : (defn undeliverable-promise [] (let [p (promise)] (reify clojure.lang.IDeref (deref [_] (deref p)) clojure.lang.IBlockingDeref (deref [_ ms val] (deref p ms val)) clojure.lang.IPending (isRealized [_] (.isRealized p)) clojure.lang.IFn (invoke [_ _] nil))))
tapichu

계산 메커니즘이 분리되는 방식의 차이점을 지적하면서이 게시물은 정말 간결한 설명이되었습니다. 감사!
synthomat

3

이미 훌륭한 답변이 있으므로 "사용 방법"요약 만 추가하면됩니다.

양자 모두

promise 또는 future를 생성하면 즉시 참조가 반환됩니다. 이 참조는 다른 스레드에서 계산 결과를 제공 할 때까지 @ / deref에서 차단됩니다.

미래

미래를 만들 때 수행 할 동기 작업을 제공합니다. 제한되지 않은 전용 풀의 스레드에서 실행됩니다.

약속

약속을 만들 때 아무런 주장도하지 않습니다. 참조는 deliver결과 가 될 다른 '사용자'스레드로 전달되어야합니다 .


1

Clojure의에서 promise, future그리고 delay약속과 같은 개체입니다. 이들은 모두 클라이언트가 deref(또는 @) 을 사용하여 기다릴 수있는 계산을 나타냅니다 . 클라이언트는 결과를 재사용하므로 계산이 여러 번 실행되지 않습니다.

계산이 수행되는 방식이 다릅니다.

  • future다른 작업자 스레드에서 계산을 시작합니다. deref결과가 준비 될 때까지 차단됩니다.

  • delay첫 번째 클라이언트가 deref, 또는을 사용할 때 계산을 느리게 수행합니다 force.

  • promise를 사용하여 사용자 지정 방식으로 결과를 제공하므로 가장 큰 유연성을 제공합니다 deliver. 둘 다 사용하지 future않거나 delay사용 사례와 일치 할 때 사용합니다 .


-4

첫째, a PromiseFuture. 나는 당신이 a Promise와 a 의 차이점을 알고 싶다고 생각합니다 FutureTask.

A Future는 현재 알려지지 않았지만 앞으로 알려질 값을 나타냅니다.

A FutureTask는 미래에 발생할 계산의 결과를 나타냅니다 (일부 스레드 풀에서). 결과에 액세스하려고 할 때 계산이 아직 발생하지 않으면 차단됩니다. 그렇지 않으면 결과가 즉시 반환됩니다. 계산은 귀하가 미리 지정하므로 결과 계산에 관여하는 다른 당사자가 없습니다.

A Promise는 약속자가 향후 약속 자에게 전달할 결과를 나타냅니다. 이 경우에 당신은 약속 자이고 약속자는 당신에게 Promise물건 을 준 사람 입니다. 와 유사하게 FutureTask,가 처리되기 전에 결과에 액세스하려고 Promise하면 약속자가 Promise. 일단 Promise충족 되면 항상 동일한 가치를 얻습니다. 와 달리 FutureTask여기에 다른 당사자가 참여하여 Promise. 다른 당사자는 계산을 수행하고 Promise.

그런 의미에서 a FutureTaskPromise당신이 만든 것입니다.


약속은 미래입니까? 나는 그것이 인터페이스를 구현한다는 것을 찾을 수 없습니다. github.com/richhickey/clojure/blob/…
Mikael Sundberg

죄송합니다. 입력을 놓쳤습니다. 내 질문은 변경
미카엘 Sundberg을

내 대답은 Clojure 특정 것이 아니라 일반적인 의미입니다.
Abhinav Sarkar 2011 년

9
Java 코드로 Clojure에 대한 질문에 대답하는 것은 약간 기발한 것 같습니다.
그냥 내 정확한 OPINION
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.