Underscore: Kesalahan metode rantai array pada nilai non-array

Dibuat pada 20 Mar 2016  ·  6Komentar  ·  Sumber: jashkenas/underscore

Kesalahan metode rantai array pada nilai non-array yang tidak seperti metode kategori array lainnya.

_().pop(); // error
_('').pop(); // error
_().first() // undefined

Komentar yang paling membantu

Ini memunculkan masalah lain, haruskah kita menggunakan array-like ke array?

_('hello').first() // 'h'
_('hello').pop() // ?

Semua 6 komentar

Ini memunculkan masalah lain, haruskah kita menggunakan array-like ke array?

_('hello').first() // 'h'
_('hello').pop() // ?

Ini sepertinya masih menjadi masalah - kami menemukannya setelah menabrak versi kami dari 1.8.3 t0 1.9.0

Sunting: Sepertinya ini telah diperbaiki di 1.9.1, jika demikian, apakah masalah ini harus tetap terbuka?

Perilaku ini masih ada di 1.10.2.

Kontras yang sedikit lebih meyakinkan dalam opsi saya, karena keduanya melibatkan modifikasi nilai di tempat:

Object.assign(undefined, {a: 1})  // error
_().extend({a: 1})  // undefined

Array.prototype.push.call(undefined, 1)  // error
_().push(1)  // error

Saya agak setuju ini tidak konsisten.

Perlu dipertimbangkan dalam situasi dunia nyata seperti apa ini kemungkinan besar akan ditemui dan apa yang diharapkan dari objek yang dibungkus dalam kasus seperti itu.

Di tengah rantai, objek yang dibungkus dapat diprediksi. Misalnya, dalam rantai di bawah ini, objek yang dibungkus yang diteruskan ke push akan berupa Array atau undefined . Untuk alasan ini, saya berpendapat bahwa metode pembungkus Array harus menerapkan pemeriksaan nol. Ini mudah.

_.chain(something).map(f).push(x)  // hoping to push x to an array

Jika objek terbungkus yang diprediksi lebih cenderung menjadi sesuatu selain array, maka itu bisa dibilang kesalahan programmer. Saya tidak keberatan melemparkan pengecualian dalam kasus itu.

_.chain(something).map(f).join('').push(x)  // hoping to push x to a string??

Pada awal rantai, ceritanya mungkin tampak sedikit berbeda pada pandangan pertama, tetapi saya akan berpendapat bahwa itu sama dan bahwa kita harus membiarkannya di cek nol. Setidaknya harus terjadi bahwa programmer memiliki beberapa alasan untuk mengharapkan something menjadi seperti array yang bisa berubah, karena jika tidak, tidak akan ada alasan untuk memanggil push :

function giveMeAMutableArraylike(something) {
    _.chain(something).push(x)
}

Harapan bahwa something adalah seperti array yang dapat berubah dapat tidak terpenuhi karena berbagai alasan:

  1. giveMeAMutableArraylike akhirnya dipanggil dengan null atau undefined untuk alasan apa pun. Ini sebanding dengan contoh chain-in-the-middle pertama dan dapat diatasi dengan pemeriksaan nol yang sama.
  2. Penelepon mencoba membuat giveMeAMutableArraylike melakukan sesuatu yang jelas-jelas tidak dapat dilakukan, yaitu melanggar kontrak. Ini sebanding dengan contoh rantai di tengah kedua. Sekali lagi, saya pikir tidak apa-apa untuk membuat kesalahan dalam kasus ini.
  3. something adalah nilai kosong alih-alih array dengan elemen tunggal, yaitu v alih-alih [v] . Ini adalah situasi umum di banyak API JavaScript. Jika kontrak giveMeAMutableArraylike memungkinkan hal ini, jelas salah untuk membuat kesalahan terlepas dari apa yang terjadi v .

Dalam kasus terakhir, Garis Bawah tidak dapat mengetahui apakah giveMeAMutableArraylike mengizinkan elemen telanjang tunggal atau tidak, jadi terserah kepada pemrogram giveMeAMutableArraylike untuk mengimplementasikan kontrak khususnya. Tidak ada perpustakaan seperti Underscore yang dapat melakukan hal yang benar untuk semua kemungkinan kontrak:

| Perilaku saat ini | Bungkus dalam array elemen tunggal
---|---|---
Kontrak memungkinkan elemen tunggal kosong | _Programmer perlu campur tangan_ | Garis bawah melakukan hal yang benar secara otomatis
Kontrak tidak mengizinkan elemen tunggal kosong | Garis bawah melakukan hal yang benar secara otomatis | _Programmer perlu campur tangan_

Juga, bagaimana Anda memutuskan apakah suatu nilai harus dibungkus? Beberapa kontrak mungkin ingin membungkus apa pun yang bukan Array , sementara yang lain mungkin ingin meneruskan arguments dan objek biasa apa adanya. Sekali lagi, ini adalah sesuatu yang tidak dapat ditebak oleh perpustakaan seperti Underscore atas nama pengguna.

Situasi yang lebih eksotis juga dapat dibayangkan, misalnya kontrak yang mengizinkan objek seperti array yang tidak dapat diubah seperti string dan yang akan mengubahnya menjadi Array terlebih dahulu. Tidak mungkin untuk mencakup semua variasi yang mungkin. Dengan prinsip perubahan terkecil, tidak ada argumen yang meyakinkan untuk mendukung beberapa kontrak dengan mengorbankan kontrak yang sudah didukung. Ada juga alasan kuat untuk menjaga implementasi seminimal mungkin.

Jadi saya pikir solusi yang tepat adalah dengan memasukkan cek nol saja dan berhenti di situ. Ini adalah satu-satunya perubahan pada perilaku Garis Bawah yang tampaknya dapat dipertahankan dalam semua situasi yang mungkin dan juga konsisten dengan perilaku _.extend . Pemeriksaan nol masih bisa dianggap sebagai perbaikan bug, saat melakukan lebih dari itu akan dengan cepat mengubahnya menjadi perubahan yang melanggar sewenang-wenang.

@jashkenas bisakah Anda menyinari ini? Jika Anda setuju, saya akan menyiapkan permintaan tarik yang mengimplementasikan cek nol.

@jgonggrijp — Bisakah Anda menguraikan satu atau dua kalimat dengan perilaku yang ingin Anda terapkan dengan cek nol?

Apakah metode array akan secara eksplisit mengeluarkan pengecualian ketika dipanggil pada nilai nol? Atau mereka akan noop ketika dipanggil dengan nilai nullish?

@jashkenas Ya. Perilaku yang akan saya terapkan adalah no-op, mengikuti gaya fungsi array Garis Bawah:

https://github.com/jashkenas/underscore/blob/4cf715f593805ba8d7c5685cd06c82b3cd9b55ae/modules/index.js#L495

Kecuali bahwa cek length tidak diperlukan, jadi saya hanya akan memasukkan

if (obj == null) return chainresult(this, obj);

antara dua garis ini:

https://github.com/jashkenas/underscore/blob/4cf715f593805ba8d7c5685cd06c82b3cd9b55ae/modules/index.js#L1654 -L1655

Tes plus tentu saja, dan jika tes itu menunjukkan kebutuhan, mungkin juga pemeriksaan nol yang mengubah metode menjadi no-op sebelum baris ini:

https://github.com/jashkenas/underscore/blob/4cf715f593805ba8d7c5685cd06c82b3cd9b55ae/modules/index.js#L1665

Kedengarannya bagus untuk saya!

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

zackschuster picture zackschuster  ·  5Komentar

umarfarooq125 picture umarfarooq125  ·  8Komentar

marcalj picture marcalj  ·  5Komentar

dmaicher picture dmaicher  ·  9Komentar

haggholm picture haggholm  ·  8Komentar