Saya baru saja membaca bahwa waktu pelaksanaan operasi append untuk List
(: +) tumbuh secara linear dengan ukuran List
.
Menambahkan ke operasi List
sepertinya cukup umum. Mengapa cara idiomatis untuk melakukan ini adalah dengan menambahkan komponen dan kemudian membalik daftar? Itu juga tidak bisa menjadi kegagalan desain karena implementasi dapat diubah pada titik mana pun.
Dari sudut pandang saya, baik prepending dan appending harus O (1).
Apakah ada alasan yang sah untuk ini?
List[T]
mengasumsikan Anda menggunakannya seperti yang Anda lakukan dalam bahasa fungsional murni - umumnya bekerja dari kepala dengan dekonstruksi dan prepends.Jawaban:
Saya akan sedikit memperluas komentar saya. The
List[T]
struktur data, dariscala.collection.immutable
dioptimalkan untuk bekerja dengan cara yang daftar kekal di lebih murni fungsional karya bahasa pemrograman. Hal ini telah sangat cepat tambahkan kali, dan diasumsikan bahwa Anda akan bekerja di kepala untuk hampir semua akses Anda.Daftar yang tidak dapat diubah memiliki waktu prependensi yang sangat cepat karena fakta bahwa mereka memodelkan daftar tertaut mereka sebagai serangkaian "sel kontra". Sel mendefinisikan nilai tunggal, dan penunjuk ke sel berikutnya (gaya daftar tunggal-tertaut klasik):
Saat Anda menambahkan ke daftar, Anda benar-benar hanya membuat satu sel baru, dengan sisa daftar yang ada diarahkan ke:
Karena daftar ini tidak dapat diubah, Anda aman untuk melakukan ini tanpa menyalin yang sebenarnya . Tidak ada bahaya perubahan daftar lama dan menyebabkan semua nilai dalam daftar baru Anda menjadi tidak valid. Namun, Anda kehilangan kemampuan untuk memiliki pointer yang bisa berubah ke akhir daftar Anda sebagai kompromi.
Ini cocok untuk bekerja secara rekursif pada daftar. Katakanlah Anda mendefinisikan versi Anda sendiri
filter
:Itu adalah fungsi rekursif yang bekerja dari kepala daftar secara eksklusif, dan memanfaatkan pencocokan pola melalui :: extractor. Ini adalah sesuatu yang Anda lihat banyak dalam bahasa-bahasa seperti Haskell.
Jika Anda benar-benar ingin menambahkan cepat, Scala menyediakan banyak struktur data yang bisa berubah dan tidak dapat diubah untuk dipilih. Di sisi bisa berubah, Anda mungkin melihat ke dalam
ListBuffer
. Atau,Vector
dariscala.collection.immutable
memiliki waktu penambahan cepat.sumber
else
loop tak terbatas? Saya pikir itu harus sepertix::deleteIf(xs)(f)
.head
dantail
akses dengan daftar seperti ini sangat cepat - lebih cepat daripada menggunakan peta atau array berbasis hash - ini adalah tipe yang sangat baik untuk fungsi rekursif. Ini adalah salah satu alasan mengapa daftar adalah tipe inti dalam sebagian besar bahasa fungsional (mis. Haskell atau Skema)List
s dan menambahkan / menambahkan).