Perbedaan Clojure antara Ref, Var, Agent, Atom, dengan contoh

110

Saya sangat baru mengenal Clojure, Bisakah kalian memberi saya penjelasan dengan skenario dunia nyata. Maksud saya, di mana menggunakan Ref, Var, Agent, Atom. Saya membaca buku, tetapi masih tidak bisa memahami contoh dunia nyata.

Mike
sumber

Jawaban:

174

Saya sangat merekomendasikan "The Joy of Clojure" atau "programming Clojure" untuk jawaban nyata atas pertanyaan ini, saya dapat mereproduksi cuplikan pendek motivasi untuk masing-masing:

mulailah dengan menonton video tentang pengertian Identitas dan / atau belajar di sini .

  • Referensi adalah untuk akses Sinkron Terkoordinasi ke "Banyak Identitas".
  • Atom adalah untuk akses sinkron tak terkoordinasi ke satu Identitas.
  • Agen ditujukan untuk akses asinkron tidak terkoordinasi ke satu Identitas.
  • Vars adalah untuk identitas terisolasi lokal utas dengan nilai default bersama.

Akses terkoordinasi digunakan ketika dua Identitas perlu diubah bersama-sama, contoh klasik adalah memindahkan uang dari satu rekening bank ke rekening bank lainnya, perlu dipindahkan sepenuhnya atau tidak sama sekali.

Akses tidak terkoordinasi digunakan ketika hanya satu Identitas yang perlu diperbarui, ini adalah kasus yang sangat umum.

Akses sinkron digunakan ketika panggilan diharapkan menunggu sampai semua Identitas diselesaikan sebelum melanjutkan.

Akses asinkron adalah "tembak dan lupakan" dan biarkan Identitas mencapai keadaan barunya pada waktunya sendiri.

Arthur Ulfeldt
sumber
Dalam akses terkoordinasi, jika saya hanya ingin mengubah state-a, tetapi mengacu state-bpada melakukannya, saya masih perlu yang refbenar? Jadi itu tidak mengubah banyak hal tetapi mengacu pada banyak hal sambil mengubah salah satunya?
event_jr
2
Ya, Anda tampaknya memahami dengan benar bahwa state-a dan state-b harus berupa ref. Jika Anda ingin nilai baru di state-a didasarkan pada kombinasi yang konsisten dari nilai di a dan b. Anda membutuhkan nilai baru tersebut untuk dihitung dalam konteks di mana state-a dan dan state-b konsisten satu sama lain. Jika keduanya adalah ref, jika b berubah di tengah jalan, maka transaksi akan dimulai ulang dan menggunakan nilai baru dari a dan b. pertimbangkan untuk menggunakan ensurefungsi: clojure.github.io/clojure/clojure.core-api.html#clojure.core/… untuk membuatnya eksplisit dan lebih efisien.
Arthur Ulfeldt
3
Mungkin penjelasan tentang apa arti Isolated with shared default bisa ditambahkan untuk melengkapi jawabannya?
Didier A.
1
"Akses terkoordinasi digunakan ketika dua Identitas perlu diubah bersama ...". Haruskah itu "diubah"?
Carcigenicate
40

Referensi adalah untuk keadaan yang perlu disinkronkan antar utas. Jika Anda perlu melacak sekumpulan hal yang berbeda dan terkadang Anda perlu melakukan operasi yang menulis ke beberapa hal sekaligus, gunakan referensi. Setiap kali Anda memiliki beberapa bagian yang berbeda, menggunakan referensi bukanlah ide yang buruk.

Atom adalah untuk keadaan independen yang perlu disinkronkan antar utas. Jika Anda tidak perlu mengubah status atom dan apa pun pada saat yang sama, menggunakan at atom aman (khususnya, jika hanya ada satu bagian status di seluruh program, Anda dapat memasukkannya ke dalam atom) . Sebagai contoh non-sepele, jika Anda mencoba untuk menyimpan nilai kembalian dari suatu fungsi (yaitu memoize), menggunakan atom mungkin aman - status tidak terlihat oleh semua yang ada di luar fungsi, jadi Anda tidak perlu khawatir tentang perubahan status di dalam fungsi yang mengacaukan apa pun.

Poin utama agen adalah mereka berjalan di utas yang berbeda. Anda bisa mendapatkan nilai agen dan memintanya untuk menerapkan fungsi ke nilainya, tetapi Anda tidak tahu kapan fungsi akan berjalan atau nilai fungsi yang akan diterapkan.

Vars digunakan saat Anda perlu menyimpan sesuatu dengan basis per utas. Jika Anda memiliki program multi-utas dan setiap utas membutuhkan status privatnya sendiri, letakkan status itu di var.

Sejauh contoh dunia nyata berjalan, jika Anda memberikan contoh tentang apa yang Anda coba lakukan, kami dapat memberi tahu Anda apa yang harus digunakan.

Retief
sumber
32

Ketika saya pertama kali membaca tentang jenis-jenis ini, saya juga berjuang untuk memahami di mana saya dapat atau harus menggunakan masing-masing jadi inilah jawaban bahasa Inggris saya yang sederhana:

Gunakan var jika data tidak berubah. Ini terjadi setiap kali Anda menggunakan defatau sebagian besar fungsi yang dimulai dengan defsuka defn.

Gunakan atom ketika Anda memiliki satu item yang berubah. Contohnya mungkin penghitung atau vektor yang ingin Anda tambahi item.

Gunakan referensi jika Anda memiliki dua atau lebih hal yang harus berubah pada saat bersamaan. Pikirkan "transaksi database" jika Anda sudah terbiasa. Contoh kanonik dari ini adalah mentransfer uang dari satu akun ke akun lain. Setiap akun dapat disimpan dalam ref sehingga perubahan dapat dibuat agar tampak atomic.

Gunakan agen ketika Anda ingin sesuatu berubah tetapi Anda tidak peduli kapan. Ini mungkin komputasi yang panjang atau menulis sesuatu ke file atau soket. Perhatikan bahwa dengan yang terakhir Anda harus menggunakan send-off.

Catatan: Saya menghargai bahwa ada lebih banyak dari masing-masing ini tetapi semoga ini memberi Anda titik awal.

optevo
sumber
1
Terima kasih banyak atas tanggapan Anda yang jelas :-) Banyak membantu pemula Clojure seperti saya.
gosukiwi
27

Saya menulis artikel dengan ringkasan perbedaan di antara mereka dan membantu memilih kapan menggunakan yang mana.

Bagikan status - kapan menggunakan vars, atom, agen, dan referensi?

Saya berharap ini akan membantu orang mencari jawaban dalam topik itu.

Beberapa jalan pintas dari artikel setelah saran @tunaci:

Vars

Variasi bersifat global untuk setiap utas.

Jangan ubah vars setelah membuat. Secara teknis mungkin, tetapi itu ide yang buruk karena berbagai alasan.

Atom

Bagikan akses ke status yang dapat berubah untuk setiap utas. Perubahan terjadi secara serempak. Coba lagi saat utas lain mengubah status selama dijalankan.

Jangan gunakan fungsi dan fungsi idempoten dengan eksekusi lama

Agen

Bagikan akses ke status yang dapat berubah untuk setiap utas. Perubahan terjadi secara asinkron.

Referensi

Ref bekerja mirip dengan transaksi database. Menulis dan membaca dilindungi dalam dosync. Anda dapat beroperasi pada banyak referensi aman dalam bertransaksi.

Dan diagram alur saat menggunakan yang mana: diagram alir

Silakan lihat gambar di situs web, karena beberapa pembaruan selalu memungkinkan.

Ini rumit dan topik panjang untuk memberikan jawaban lengkap tanpa salinan & artikel sebelumnya, jadi maafkan saya, saya mengarahkan Anda ke situs web :)

kabra
sumber