Transduser adalah resep yang harus dilakukan dengan urutan data tanpa mengetahui urutan yang mendasarinya (bagaimana melakukannya). Ini bisa berupa saluran seq, async, atau mungkin bisa diamati.
Mereka dapat disusun dan polimorfik.
Manfaatnya adalah, Anda tidak perlu menerapkan semua kombinator standar setiap kali sumber data baru ditambahkan. Lagi dan lagi. Akibatnya, Anda sebagai pengguna dapat menggunakan kembali resep tersebut di berbagai sumber data.
Pembaruan Iklan
Clojure versi 1.7 sebelumnya, Anda memiliki tiga cara untuk menulis kueri dataflow:
- panggilan bersarang
(reduce + (filter odd? (map #(+ 2 %) (range 0 10))))
- komposisi fungsional
(def xform
(comp
(partial filter odd?)
(partial map #(+ 2 %))))
(reduce + (xform (range 0 10)))
- makro threading
(defn xform [xs]
(->> xs
(map #(+ 2 %))
(filter odd?)))
(reduce + (xform (range 0 10)))
Dengan transduser Anda akan menulisnya seperti:
(def xform
(comp
(map #(+ 2 %))
(filter odd?)))
(transduce xform + (range 0 10))
Mereka semua melakukan hal yang sama. Perbedaannya adalah Anda tidak pernah memanggil Transduser secara langsung, Anda meneruskannya ke fungsi lain. Transduser tahu apa yang harus dilakukan, fungsi yang membuat transduser tahu caranya. Urutan kombinator seperti Anda menulisnya dengan makro penguliran (urutan alami). Sekarang Anda dapat menggunakan kembali xform
dengan saluran:
(chan 1 xform)
Transduser meningkatkan efisiensi, dan memungkinkan Anda menulis kode yang efisien dengan cara yang lebih modular.
Ini adalah latihan yang layak .
Dibandingkan dengan menyusun panggilan ke yang lama
map
,filter
,reduce
dll Anda mendapatkan kinerja yang lebih baik karena Anda tidak perlu membangun koleksi penengah antara setiap langkah, dan berulang kali berjalan koleksi mereka.Dibandingkan dengan
reducers
, atau secara manual menyusun semua operasi Anda menjadi satu ekspresi, Anda akan lebih mudah menggunakan abstraksi, modularitas yang lebih baik, dan penggunaan kembali fungsi pemrosesan.sumber
map
/reduce
menggunakan koleksi perantara karena semuanya membangun rantai iterator. Dimana saya salah disini?map
danfilter
buat koleksi perantara saat bersarang.Transduser adalah alat kombinasi untuk mengurangi fungsi.
Contoh: Fungsi pereduksi adalah fungsi yang mengambil dua argumen: Hasil sejauh ini dan masukan. Mereka mengembalikan hasil baru (sejauh ini). Misalnya
+
: Dengan dua argumen, Anda dapat menganggap yang pertama sebagai hasil sejauh ini dan yang kedua sebagai masukan.Transduser sekarang dapat menggunakan fungsi + dan menjadikannya fungsi dua kali lebih banyak (menggandakan setiap input sebelum menambahkannya). Seperti inilah tampilan transduser itu (dalam istilah paling dasar):
Sebagai ilustrasi, gantikan
rfn
dengan+
untuk melihat bagaimana+
diubah menjadi dua kali plus:Begitu
sekarang akan menghasilkan 12.
Fungsi pereduksi yang dikembalikan oleh transduser tidak bergantung pada bagaimana hasil diakumulasikan karena mereka terakumulasi dengan fungsi pereduksi yang diteruskan kepadanya, tanpa diketahui caranya. Di sini kami menggunakan
conj
sebagai pengganti+
.Conj
mengambil koleksi dan nilai dan mengembalikan koleksi baru dengan nilai yang ditambahkan.akan menghasilkan [2 4 6]
Mereka juga tidak tergantung pada jenis sumber inputnya.
Beberapa transduser dapat dirangkai sebagai resep (dapat dirantai) untuk mengubah fungsi pengurangan.
Pembaruan: Karena sekarang ada halaman resmi tentang itu, saya sangat menyarankan untuk membacanya: http://clojure.org/transducers
sumber
double
dantransduce
?Katakanlah Anda ingin menggunakan serangkaian fungsi untuk mengubah aliran data. Shell Unix memungkinkan Anda melakukan hal semacam ini dengan operator pipa, misalnya
(Perintah di atas menghitung jumlah pengguna dengan huruf r baik dalam huruf besar atau kecil pada nama pengguna mereka). Ini diimplementasikan sebagai sekumpulan proses, yang masing-masing membaca dari keluaran proses sebelumnya, jadi ada empat aliran perantara. Anda dapat membayangkan implementasi berbeda yang menyusun lima perintah menjadi satu perintah agregat, yang akan membaca dari masukannya dan menulis keluarannya tepat satu kali. Jika aliran perantara mahal, dan komposisinya murah, itu mungkin trade-off yang bagus.
Hal yang sama berlaku untuk Clojure. Ada beberapa cara untuk mengekspresikan pipeline transformasi, tetapi bergantung pada cara Anda melakukannya, Anda dapat berakhir dengan aliran perantara yang meneruskan dari satu fungsi ke fungsi berikutnya. Jika Anda memiliki banyak data, lebih cepat untuk menyusun fungsi-fungsi tersebut menjadi satu fungsi. Transduser memudahkan untuk melakukan itu. Inovasi Clojure sebelumnya, pereduksi, memungkinkan Anda melakukannya juga, tetapi dengan beberapa batasan. Transduser menghapus beberapa batasan tersebut.
Jadi untuk menjawab pertanyaan Anda, transduser tidak akan selalu membuat kode Anda lebih pendek atau lebih mudah dimengerti, tetapi kode Anda mungkin tidak akan lebih panjang atau kurang dapat dimengerti, dan jika Anda bekerja dengan banyak data, transduser dapat membuat kode Anda lebih cepat.
Ini adalah ikhtisar transduser yang cukup bagus.
sumber
pmap
, yang sepertinya tidak mendapatkan cukup perhatian. Jika Anda melakukanmap
ping ke fungsi yang mahal melalui suatu urutan, membuat operasi paralel semudah menambahkan "p". Tidak perlu mengubah apa pun dalam kode Anda, dan itu tersedia sekarang - bukan alfa, bukan beta. (Jika fungsinya membuat urutan perantara, maka transduser mungkin lebih cepat, saya kira.)Rich Hickey memberikan ceramah 'Transduser' di konferensi Strange Loop 2014 (45 menit).
Dia menjelaskan dengan cara sederhana apa itu transduser, dengan contoh dunia nyata - memproses tas di bandara. Dia dengan jelas memisahkan berbagai aspek dan membandingkannya dengan pendekatan saat ini. Menjelang akhir, dia memberikan alasan untuk keberadaan mereka.
Video: https://www.youtube.com/watch?v=6mTbuzafcII
sumber
Saya sudah menemukan membaca contoh-contoh dari transduser-js membantu saya memahami mereka secara konkret bagaimana saya bisa menggunakannya dalam kode sehari-hari.
Misalnya, pertimbangkan contoh ini (diambil dari README di tautan di atas):
Pertama, menggunakan
xf
terlihat jauh lebih bersih daripada alternatif biasa dengan Underscore.sumber
t.into([], t.comp(t.map(inc), t.filter(isEven)), [0,1,2,3,4])
Transduser adalah fungsi (menurut pemahaman saya!) Yang mengambil satu fungsi reduksi dan mengembalikan yang lain. Fungsi pereduksi adalah salah satunya
Sebagai contoh:
Dalam hal ini transduser-saya mengambil fungsi pemfilteran input yang diterapkan ke 0 lalu jika nilainya genap? dalam kasus pertama filter meneruskan nilai itu ke penghitung, lalu memfilter nilai berikutnya. Alih-alih memfilter terlebih dahulu, lalu meneruskan semua nilai tersebut untuk dihitung.
Ini adalah hal yang sama pada contoh kedua ia memeriksa satu nilai pada satu waktu dan jika nilainya kurang dari 3 maka itu memungkinkan menghitung tambahkan 1.
sumber
Definisi transduser yang jelas ada di sini:
Untuk memahaminya, mari kita perhatikan contoh sederhana berikut:
Bagaimana kalau kita ingin tahu ada berapa anak di desa itu? Kita dapat dengan mudah menemukannya dengan peredam berikut:
Berikut cara lain untuk melakukannya:
Selain itu, ini juga sangat berguna saat memperhitungkan subkelompok. Misalnya, jika kita ingin mengetahui berapa jumlah anak di Brown Family, kita dapat mengeksekusi:
Saya harap contoh-contoh ini bermanfaat bagi Anda. Anda dapat menemukan lebih banyak di sini
Semoga membantu.
Clemencio Morales Lucas.
sumber
Saya membuat blog tentang ini dengan contoh clojurescript yang menjelaskan bagaimana fungsi urutan sekarang dapat diperluas dengan dapat menggantikan fungsi reduksi.
Inilah inti dari transduser saat saya membacanya. Jika Anda memikirkan tentang operasi
cons
atauconj
yang memiliki kode keras dalam operasi sepertimap
,filter
dll., Fungsi pengurangan tidak dapat dijangkau.Dengan transduser, fungsi pereduksi dipisahkan dan saya dapat menggantinya seperti yang saya lakukan dengan array javascript asli
push
berkat transduser.filter
dan teman-teman memiliki 1 operasi arity baru yang akan mengembalikan fungsi transduksi yang dapat Anda gunakan untuk memasok fungsi reduksi Anda sendiri.sumber
Inilah (kebanyakan) jargon dan kode jawaban gratis saya.
Pikirkan data dalam dua cara, aliran (nilai yang muncul dari waktu ke waktu seperti peristiwa) atau struktur (data yang ada pada suatu titik waktu seperti daftar, vektor, larik, dll).
Ada operasi tertentu yang mungkin ingin Anda lakukan pada aliran atau struktur. Salah satu operasi tersebut adalah pemetaan. Fungsi pemetaan mungkin menaikkan setiap item data (dengan asumsi itu adalah angka) sebesar 1 dan Anda diharapkan dapat membayangkan bagaimana hal ini dapat diterapkan pada aliran atau struktur.
Fungsi pemetaan hanyalah salah satu dari kelas fungsi yang terkadang disebut sebagai "fungsi pereduksi". Fungsi reduksi umum lainnya adalah filter yang menghapus nilai yang cocok dengan predikat (mis. Menghapus semua nilai yang genap).
Transduser memungkinkan Anda "membungkus" urutan satu atau lebih fungsi pereduksi dan menghasilkan "paket" (yang juga merupakan fungsi) yang bekerja pada aliran atau struktur. Misalnya, Anda dapat "mengemas" urutan fungsi pengurangan (mis. Memfilter angka genap, lalu memetakan angka yang dihasilkan untuk menambahnya dengan 1) dan kemudian menggunakan "paket" transduser tersebut pada aliran atau struktur nilai (atau keduanya) .
Jadi apa yang spesial dari ini? Biasanya, fungsi pereduksi tidak dapat disusun secara efisien untuk bekerja pada aliran dan struktur.
Jadi, manfaatnya bagi Anda adalah Anda dapat memanfaatkan pengetahuan Anda seputar fungsi-fungsi ini dan menerapkannya pada lebih banyak kasus penggunaan. Biaya yang harus Anda tanggung adalah Anda harus mempelajari beberapa mesin tambahan (misalnya transduser) untuk memberi Anda kekuatan ekstra ini.
sumber
Sejauh yang saya mengerti, mereka seperti blok bangunan , dipisahkan dari implementasi input dan output. Anda tinggal menentukan operasinya.
Karena implementasi operasi tidak ada dalam kode input dan tidak ada yang dilakukan dengan output, transduser sangat dapat digunakan kembali. Mereka mengingatkan saya pada Flow di Akka Streams .
Saya juga baru mengenal transduser, maaf atas jawaban yang mungkin tidak jelas.
sumber
Saya menemukan posting ini memberi Anda pandangan yang lebih luas tentang transduser.
https://medium.com/@roman01la/understanding-transducers-in-javascript-3500d3bd9624
sumber