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 Promise는 Future. 나는 당신이 a Promise와 a 의 차이점을 알고 싶다고 생각합니다 FutureTask.

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

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

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

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


약속은 미래입니까? 나는 그것이 인터페이스를 구현한다는 것을 찾을 수 없습니다. 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.