Clojure vadeli işlemleri ve vaatleri nasıl farklılık gösterir?


86

Hem vadeli işlemler hem de vaatler, değerlerini hesaplayana kadar bloke olur, peki aralarındaki fark nedir?


8
Sorudaki -1'in neden olduğundan emin değilim veya şimdi kötü şeyler sormadan önce cevabını bilmediğiniz sorular mı?
SADECE

Cevapların hiçbirini -1 yapmadım ?? Bir soruya veya yanıta kimin -1 koyduğunu nasıl anlayabiliriz?
yazz.com

Sen ve ben yapamayız, Zubair. Sormanızın son derece makul bir soru olduğu ve SO için kesinlikle konuya bağlı olduğu için sorunuza kimin -1 koyduğunu merak ediyorum.
SADECE DOĞRU GÖRÜŞÜM

Yanıtlar:


54

Clojure terimleriyle yanıtlayarak, Sean Devlin'in ekran video kaydından bazı örnekler :

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

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

Taahhütte, daha sonraki bir hesaplamada ( :fredbu durumda) seçtiğiniz bir değeri açıkça verdiğinizi unutmayın . Gelecek ise yaratıldığı yerde tüketiliyor. some-exprMuhtemelen perde arkasında başlatılan ve tandem (sonunda) hesaplanan, ancak zamanla unevaluated kalırsa mevcut olana kadar o iplik blokları erişilir edilir.


eklemek için düzenlendi

Bir vaat ile gelecek arasında daha fazla ayrım yapmaya yardımcı olmak için aşağıdakilere dikkat edin:

söz vermek

  1. Bir promise. Bu vaat nesnesi artık herhangi bir iş parçacığına aktarılabilir.
  2. Hesaplamalara devam edin. Bunlar, yan etkiler, veri indirme, kullanıcı girişi, veritabanı erişimi ve diğer vaatleri içeren çok karmaşık hesaplamalar olabilir - ne isterseniz. Kod, herhangi bir programdaki ana hat kodunuza çok benzeyecektir.
  3. Bitirdiğinizde, delivero vaat nesnesinin sonuçlarını alabilirsiniz .
  4. derefSiz hesaplamanız bitmeden sözünüzü yerine getirmeye çalışan herhangi bir öğe, siz bitirene kadar bloke edilecektir. İşiniz bittiğinde ve deliversözünüzü yerine getirdiğinizde, söz artık engellenmeyecektir.

gelecek

  1. Geleceğinizi siz yaratırsınız. Geleceğinizin bir kısmı hesaplama için bir ifadedir.
  2. Gelecek aynı anda yürütülebilir veya uygulanmayabilir. Muhtemelen bir havuzdan bir iş parçacığı atanabilir. Sadece bekleyebilir ve hiçbir şey yapmaz. Senin bakış açından anlayamazsın .
  3. Bir noktada siz (veya başka bir konu) derefgelecektesiniz. Hesaplama zaten tamamlandıysa, sonuçlarını alırsınız. Zaten tamamlanmadıysa, tamamlanana kadar bloke edersiniz. (Muhtemelen henüz başlamamışsa, derefçalışmaya başlaması anlamına gelir, ancak bu da garanti edilmez.)

Eğer iken olabilir bir söz oluşturulmasını aşağıdaki kodu gibi karmaşık gelecekte ifadesini yapmak, 's arzu şüphelidir. Bu, vadeli işlemlerin hızlı, arka planda yapılabilen hesaplamalar için gerçekten daha uygun olduğu, vaatlerin ise büyük, karmaşık yürütme yollarına gerçekten daha uygun olduğu anlamına gelir. Mevcut hesaplamalar açısından da vaatler biraz daha esnek ve işi yapan vaat yaratan kişiye ve hasadı biçen başka bir iş parçacığına yönelik görünüyor. Vadeli işlemler, otomatik olarak bir iş parçacığı başlatmaya (çirkin ve hataya açık genel giderler olmadan) ve siz - başlangıçtaki iş parçacığı - sonuçlara ihtiyacınız olana kadar başka şeylerle devam etmeye yöneliktir.


Ancak bir söz VEYA gelecek bitene kadar herhangi bir hesaplama bloğuna sahip olabilirsiniz. yani: (@a + @b) hem bir gelecek hem de bir söz için aynı şekilde çalışacak
yazz.com

2
Bir söz bana benzediği gibi daha fazla esneklik sağlar. Bir söz veriyorum. Bu sözü başka bir konuya aktarıyorum. Daha sonra, G / Ç beklemek, İnternetten veri indirmek, kullanıcı girdisini beklemek vb. Dahil olmak üzere birçok karmaşık hesaplama yapabilirim. Hepsi bittiğinde, elde edilen değerle sözümü teslim ederim. Bir gelecek, bir S ifadesini kapsar. Sanırım çok, çok karmaşık bir S ifadesi olabilir, ama orada biraz ... sert olurdu. Ek olarak, gelecek bir iş parçacığı (veya havuz) içinde işini otomatik olarak yapar. Bir sözde aynısını yapmak, daha da fazla çalışma anlamına gelir.
SADECE DOĞRU GÖRÜŞÜM

FWIW Tek bir s-ifadesi rastgele bir kod yoluna bir çağrı olabileceğinden, bu ifadeye ne kadar kod sığdırabileceğinizle ilgili değildir. Yani bir sözün "daha esnek" olduğunu söylemek yerine, amacının tamamen farklı olduğunu söyleyebilirim. Aksi takdirde, neden ikisi birden var?
Geoff

2
Kayıt için, bir futurearamanın gövdesi N sexpr içerebilir.
vemv

Bu açıklama Clojure Doc
Piyush Katariya

25

Hem Gelecek hem de Vaat, zaman uyumsuz hesaplamanın sonucunu Üretici'den Tüketiciye / Tüketicilere iletmek için kullanılan mekanizmalardır . Gelecek

durumunda , hesaplama Gelecek oluşturma sırasında tanımlanır ve zaman uyumsuz yürütme "ASAP" başlar. Aynı zamanda eşzamansız bir hesaplamanın nasıl başlatılacağını da "bilir". Promise durumunda , hesaplama , başlangıç ​​zamanı ve [olası] eşzamansız çağrı dağıtım mekanizmasından ayrıştırılır. Hesaplama sonucu mevcut olduğunda , Üretici bunu açıkça aramalıdır, bu aynı zamanda Üreticinin sonucun ne zaman hazır olduğunu kontrol edeceği anlamına gelir.

deliver

İçin Promises Clojure aynı nesneyi (sonucu kullanarak bir tasarım hata yaptığında promisehem üretmek () çağrısından deliver) ve tüketmek ( deref) sonucu hesaplama . Bunlar çok farklı iki yetenektir ve bu şekilde ele alınmalıdır.


@oskarkv Bir söz oluşturduğunuzu ve bunu 3 müşteriye verdiğinizi varsayalım. İstemcilerden birinin yanlış sonuçla çözmesini ve diğer iki istemciye sinyal göndermesini hiçbir şey engellemez. Üstelik bu sözü artık çözemeyeceksiniz. Buna karşılık, bir söz + çözümleyici çiftiniz varsa, müşterilerinize söz verdiyseniz ve kendiniz için çözücü tuttuysanız, bu senaryo imkansız hale gelir. Daha fazla bilgi için önerilen arama terimleri, "yeteneklere dayalı erişim kontrolü" ve "yeteneklere dayalı güvenlik" dir.
Dimagog

1
Güvenliği bu kadar basit bir referans tipine bağlamanın (impl'sini kontrol edin) promiseuygun olup olmayacağından emin değilim . "Kötü" tüketiciler nadirdir; Hiçbir şey sizi vaatler üzerine kendi soyutlamanızı inşa etmekten alıkoyamaz.
vemv

8
Konu güvenlikle ilgili değil, yetenek tabanlı programlama genellikle güvenlikle ilgili olarak tanımlanıyor. Burada her şey kod doğruluğu ile ilgili. Sık kullanılan terim "yapı gereği doğrudur" ve soru "yanlış bir program oluşturabilir misin"? Bilerek değil, tesadüfen. Tek Promise nesnesiyle yapabilirsiniz, iki ayrı nesne ile yapamazsınız.
Dimagog

Sizi, teslim edilemeyecek bir sözü geri vermekten (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))))
alıkoyan

Hesaplama mekanizmasının nasıl ayrıştırıldığına işaret etmek, bu yazıyı gerçekten kısa bir açıklama yaptı. Teşekkürler!
synthomat

3

Zaten mükemmel yanıtlar var, bu nedenle yalnızca "nasıl kullanılır" özetini ekleyerek:

Her ikisi de

Söz veya gelecek yaratmak, hemen bir referans verir. Bu referans, hesaplamanın sonucu başka bir iş parçacığı tarafından sağlanana kadar @ / deref üzerinde engeller.

Gelecek

Geleceği yaratırken, senkronize bir işin yapılmasını sağlarsınız. Adanmış sınırsız havuzdan bir iş parçacığında yürütülür.

Söz vermek

Söz verirken hiçbir argüman vermiyorsunuz. Referans deliver, sonuçlanacak diğer 'kullanıcı' dizisine aktarılmalıdır .


1

Clojure yılında promise, futureve delaysöz benzeri nesneler vardır. Hepsi, istemcilerin deref(veya @) kullanarak bekleyebilecekleri bir hesaplamayı temsil eder . İstemciler sonucu yeniden kullanır, böylece hesaplama birkaç kez çalıştırılmaz.

Hesaplamanın gerçekleştirilme biçiminde farklılık gösterirler:

  • futurehesaplamayı farklı bir işçi iş parçacığında başlatır. derefsonuç hazır olana kadar engellenecektir.

  • delayderefveya ilk müşteri kullandığında hesaplamayı tembel olarak gerçekleştirecektir force.

  • promisesonucu herhangi bir özel şekilde kullanılarak teslim edildiğinden en fazla esnekliği sunar deliver. Hiçbiri olmadığında futureveya delaykullanım durumunuzla eşleşmediğinde kullanırsınız.


-4

İlk olarak, a Promisebir Future. Sanırım a Promiseve a arasındaki farkı bilmek istiyorsunuz FutureTask.

A Future, şu anda bilinmeyen ancak gelecekte bilinecek bir değeri temsil eder.

A FutureTask, gelecekte gerçekleşecek bir hesaplamanın sonucunu temsil eder (belki bir iş parçacığı havuzunda). Sonuca erişmeye çalıştığınızda, hesaplama henüz gerçekleşmediyse, bloke olur. Aksi takdirde sonuç hemen iade edilir. Hesaplama önceden sizin tarafınızdan belirtildiğinden, sonucun hesaplanmasına dahil olan başka bir taraf yoktur.

A Promise, gelecekte söz verene vaat edene iletilecek bir sonucu temsil eder. Bu durumda siz söz verensiniz ve söz veren de size Promisenesneyi verendir . Şuna benzer şekilde, FutureTasksonuca ulaşılmadan önce erişmeye çalışırsanız Promise, sözcü yerine getirene kadar bloke edilir Promise. Bir kez Promiseyerine getirildiğinde, her zaman ve anında aynı değeri alırsınız. A'dan farklı olarak FutureTask, burada başka bir taraf daha var, biri Promise. Hesaplamanın yapılmasından ve yerine getirilmesinden başka bir tarafın sorumlu olduğunu Promise.

Bu anlamda a FutureTask, Promisekendinize yaptığınız bir şeydir .


Bir Sözün Gelecek Olduğundan Emin Misiniz? Arayüzü uyguladığını bulamıyorum. github.com/richhickey/clojure/blob/…
Mikael Sundberg

üzgünüm, girişi kaçırdım. Sorum değişti
Mikael Sundberg

Cevabım genel anlamda, Clojure'e özgü değil.
Abhinav Sarkar

9
Clojure ile ilgili bir soruyu Java koduyla yanıtlamak biraz tuhaf görünüyor.
SADECE
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.