Apa nama terbaik untuk metode “tambahkan” yang tidak bermutasi pada koleksi yang tidak berubah?


229

Maaf untuk judul waffly - jika saya bisa menghasilkan judul yang ringkas, saya tidak perlu mengajukan pertanyaan.

Misalkan saya memiliki tipe daftar yang tidak dapat diubah. Ini memiliki operasi Foo(x)yang mengembalikan daftar abadi dengan argumen yang ditentukan sebagai elemen tambahan di akhir. Jadi untuk membangun daftar string dengan nilai "Hello", "immutable", "world" Anda bisa menulis:

var empty = new ImmutableList<string>();
var list1 = empty.Foo("Hello");
var list2 = list1.Foo("immutable");
var list3 = list2.Foo("word");

(Ini adalah kode C #, dan saya paling tertarik dengan saran C # jika Anda merasa bahasanya penting. Ini bukan pertanyaan bahasa yang mendasar, tetapi idiom bahasa mungkin penting.)

Yang penting adalah bahwa daftar yang ada tidak diubah oleh Foo- jadi empty.Countmasih akan mengembalikan 0.

Cara lain (yang lebih idiomatis) untuk mencapai hasil akhir adalah:

var list = new ImmutableList<string>().Foo("Hello")
                                      .Foo("immutable")
                                      .Foo("word");

Pertanyaan saya adalah: apa nama terbaik untuk Foo?

EDIT 3 : Seperti yang saya ungkapkan kemudian, nama tipe mungkin sebenarnya tidak ImmutableList<T>, yang membuat posisi jelas. Bayangkan sebaliknya bahwa itu TestSuitedan itu tidak dapat diubah karena seluruh kerangka itu bagian dari itu tidak dapat diubah ...

(Akhir pengeditan 3)

Opsi yang saya buat sejauh ini:

  • Add: umum di .NET, tetapi menyiratkan mutasi dari daftar asli
  • Cons: Saya percaya ini adalah nama normal dalam bahasa fungsional, tetapi tidak berarti bagi mereka yang tidak berpengalaman dalam bahasa tersebut
  • Plus: favorit saya sejauh ini, itu tidak menyiratkan mutasi kepada saya . Rupanya ini juga digunakan di Haskell tetapi dengan harapan yang sedikit berbeda (seorang programmer Haskell mungkin berharap untuk menambahkan dua daftar bersama daripada menambahkan nilai tunggal ke daftar lainnya).
  • With: konsisten dengan beberapa konvensi tidak berubah lainnya, tetapi tidak memiliki "penambahan" yang sama persis untuk itu IMO.
  • And: tidak terlalu deskriptif.
  • Kelebihan operator untuk +: Saya benar-benar tidak suka ini; Saya biasanya berpikir operator hanya boleh diterapkan pada tipe level yang lebih rendah. Saya bersedia dibujuk!

Kriteria yang saya gunakan untuk memilih adalah:

  • Memberikan kesan yang benar dari hasil pemanggilan metode (yaitu bahwa itu adalah daftar asli dengan elemen tambahan)
  • Buat sejelas mungkin bahwa itu tidak mengubah daftar yang ada
  • Kedengarannya masuk akal ketika dirantai bersama seperti pada contoh kedua di atas

Silakan tanyakan lebih detail jika saya tidak membuat diri saya cukup jelas ...

EDIT 1: Berikut alasan saya untuk memilih Plusuntuk Add. Pertimbangkan dua baris kode ini:

list.Add(foo);
list.Plus(foo);

Dalam pandangan saya (dan ini adalah hal pribadi) yang terakhir jelas buggy - itu seperti menulis "x + 5;" sebagai pernyataan sendiri. Baris pertama sepertinya tidak apa-apa, sampai Anda ingat itu tidak berubah. Sebenarnya, cara operator plus itu sendiri tidak mengubah operan adalah alasan lain mengapa Plusfavorit saya. Tanpa sedikit kekuatiran operator overloading, masih memberikan konotasi yang sama, yang termasuk (bagi saya) tidak bermutasi operan (atau target metode dalam kasus ini).

EDIT 2: Alasan untuk tidak menyukai Tambahkan.

Berbagai jawaban secara efektif: "Pergilah dengan Add. Itulah yang DateTimedilakukannya, dan Stringmemiliki Replacemetode dll yang tidak membuat kekekalan menjadi jelas." Saya setuju - ada yang diutamakan di sini. Namun, saya telah melihat banyak orang menelepon DateTime.Addatau String.Replacedan mengharapkan mutasi . Ada banyak pertanyaan newsgroup (dan mungkin SO yang saya gali) yang dijawab oleh "Anda mengabaikan nilai pengembalian String.Replace; string tidak berubah, string baru akan dikembalikan."

Sekarang, saya harus mengungkapkan kehalusan pertanyaan - jenisnya mungkin sebenarnya bukan daftar yang tidak dapat diubah, tetapi jenis yang tidak bisa diubah. Secara khusus, saya sedang mengerjakan kerangka tolok ukur di mana Anda menambahkan tes ke suite, dan itu menciptakan suite baru. Mungkin jelas bahwa:

var list = new ImmutableList<string>();
list.Add("foo");

tidak akan mencapai apa-apa, tapi itu menjadi banyak murkier ketika Anda mengubahnya ke:

var suite = new TestSuite<string, int>();
suite.Add(x => x.Length);

Sepertinya itu harus baik-baik saja. Bagi saya, ini membuat kesalahan lebih jelas:

var suite = new TestSuite<string, int>();
suite.Plus(x => x.Length);

Itu hanya memohon untuk:

var suite = new TestSuite<string, int>().Plus(x => x.Length);

Idealnya, saya ingin pengguna saya tidak perlu diberi tahu bahwa test suite tidak dapat diubah. Saya ingin mereka jatuh ke dalam lubang kesuksesan. Ini mungkin tidak mungkin, tetapi saya ingin mencoba.

Saya minta maaf karena terlalu menyederhanakan pertanyaan asli dengan hanya berbicara tentang jenis daftar yang tidak dapat diubah. Tidak semua koleksi cukup deskriptif seperti ImmutableList<T>:)


2
@ Adam: Tidak, yang terakhir ini jelas buggy. Mereka berdua sebenarnya buggy (karena mereka tidak melakukan apa-apa dengan hasilnya) - tetapi yang pertama tidak terlihat buggy bagi saya.
Jon Skeet

36
Apakah anjing yang tidak rapi?
Michael Myers

7
Concat / Condog ... bekerja untuk saya! ;)
gnovice

11
Uncat - itu akan menjadi kucing zombie.
Erik Forbes

2
@Trap: Itu menyebalkan dalam hal membuat cairan API.
Jon Skeet

Jawaban:


130

Dalam situasi seperti itu, saya biasanya ikut Concat. Itu biasanya menyiratkan kepada saya bahwa objek baru sedang dibuat.

var p = listA.Concat(listB);
var k = listA.Concat(item);

3
Inilah yang saya gunakan, karena itulah System.Linq. Penggunaan yang dapat dihitung - keputusan sudah dibuat. :) Saya tidak bisa menjadi satu-satunya orang yang telah menetapkan kelebihan sendiri dari ekstensi Concat di IEnumerable untuk menerima nilai tunggal untuk ditambahkan.
Daniel Earwicker

9
1 ini adalah yang jawaban yang benar untuk menjaga konsistensi penamaan dalam kerangka.
Sam Harwell

Kecuali saya melewatkannya, System.Linq.Enumerable (dan Linq secara umum) hanya menggunakan Concat () untuk "sequence + sequence", tidak pernah "item + sequence". Masalah bahwa seseorang "mungkin mengharapkannya untuk menambahkan dua daftar bersama daripada menambahkan nilai tunggal ke daftar lain" secara eksplisit diberikan sebagai alasan untuk tidak menggunakan salah satu opsi asli lainnya.
Ssswift

119

Saya akan menggunakan Cons, karena satu alasan sederhana: artinya persis seperti yang Anda inginkan.

  1. Saya penggemar berat mengatakan apa yang saya maksud, terutama dalam kode sumber. Seorang pemula harus melihat definisi Cons hanya sekali, tetapi kemudian membaca dan menggunakannya seribu kali. Saya menemukan bahwa, dalam jangka panjang, lebih baik bekerja dengan sistem yang membuat kasus umum lebih mudah, bahkan jika biaya di muka sedikit lebih tinggi.

  2. Fakta bahwa itu akan menjadi "tidak berarti" bagi orang-orang yang tidak memiliki pengalaman KB sebenarnya merupakan keuntungan besar. Seperti yang Anda tunjukkan, semua kata lain yang Anda temukan sudah memiliki makna, dan makna itu sedikit berbeda atau ambigu. Konsep baru harus memiliki kata baru (atau dalam hal ini, yang lama). Saya lebih suka seseorang harus mencari definisi Cons, daripada menganggap secara salah dia tahu apa yang dilakukan Add.

  3. Operasi lain yang dipinjam dari bahasa fungsional sering kali menggunakan nama aslinya, tanpa bencana yang jelas. Saya belum melihat adanya dorongan untuk membuat sinonim untuk "peta" dan "mengurangi" yang terdengar lebih akrab bagi orang yang tidak menggunakan FPers, dan saya juga tidak melihat manfaat dari melakukannya.

(Pengungkapan penuh: Saya seorang programmer Lisp, jadi saya sudah tahu apa artinya Cons.)


16
Jangan lupa bahwa kemampuan menemukan itu penting - jika saya mengetik "testSuite." dan lihat daftar metode, saya ingin melihat metode yang menyarankan hal yang benar. Saya mungkin tidak akan mencari nama (bagi saya) yang tidak masuk akal pada kesempatan itu yang saya inginkan.
Jon Skeet

33
Jika saya merasa snarky, saya akan membuat metode Add yang hanya melemparkan pengecualian dengan message = "Gunakan Kontra untuk menambahkan ke ImmutableList". :-)
Ken

2
Tidak akan membunuh siapa pun untuk membaca beberapa baris komentar yang menjelaskan mengapa nama itu apa adanya, dan merujuknya kepada, katakanlah, "Struktur dan Interpretasi Program Komputer" dari Abelson & Sussman.
John R. Strohm

16
Secara tradisional, kontra menambahkan di awal daripada akhir. Jadi itu adalah nama yang berpotensi menyesatkan untuk metode yang dijelaskan.
walkytalky

16
Hanya untuk menyimpan programmer non-fungsional berikutnya satu klik atau 3 ... en.wikipedia.org/wiki/Cons dari kata "construct", ungkapan "to cons x on y" berarti membangun objek baru dengan ( kontra xy)
Myster

59

Sebenarnya saya suka And, terutama dengan cara idiomatis. Saya terutama suka jika Anda memiliki properti baca statis untuk daftar Kosong, dan mungkin membuat konstruktor pribadi sehingga Anda selalu harus membangun dari daftar kosong.

var list = ImmutableList<string>.Empty.And("Hello")
                                      .And("Immutable")
                                      .And("Word");

Saya suka ide Kosong. Masih tidak yakin tentang Dan. Hanya sedikit bla.
Jon Skeet

Sepertinya lebih seperti bagaimana saya berpikir tentang membangun daftar hal-hal dalam bahasa alami. Jika Anda membacanya dengan keras sepertinya lebih intuitif daripada Tambah atau Plus. "list" adalah daftar kosong dan "Hello" dan "Immutable" dan "Word". Saya setuju bahwa itu kurang jelas dalam isolasi.
tvanfosson

52

Setiap kali saya berada dalam kemacetan dengan nomenklatur, saya memukul jalinan.

thesaurus.com mengembalikan ini untuk "tambah":

Definisi: berdampingan, meningkat; buat komentar lebih lanjut

Sinonim: membubuhkan, lampiran, taruhan, menambahkan, menambah, menambah, menambah, membangun, mengisi, melanjutkan, memberi isyarat, menyempurnakan, memanaskan, mendaki, mendaki, menyambung, memasang, menghubungkan, menghubungkan, menghubungkan dengan, termasuk, mendongkrak, meramaikan, bergabung bersama, pad, parlay, dukung, pasang, tuangkan, balas, jalankan, katakan lebih lanjut, tampar, bola salju, sup naik, percepat, lonjakan, naikkan, suplemen, pemanis, tempelkan, beri tag

Saya suka suara Adjoin, atau lebih sederhana Join. Itu yang kamu lakukan, kan? Metode ini juga dapat diterapkan untuk bergabung dengan orang lain ImmutableList<>.


1
Saya agak suka 'Gabung' juga, tetapi dalam banyak kasus, ketika Anda bergabung dengan 2 objek, Anda berakhir dengan 1. Dalam hal ini, jika Anda bergabung dengan 2 objek, Anda sebenarnya membuat objek baru.
Outlaw Programmer

1
Saya tidak tahu ada kasus di .NET, Perl, PHP, atau bahkan VBScript di mana Bergabung menyiratkan mutasi. Desainnya sedemikian rupa sehingga A dan B bergabung untuk membuat C, di mana C selalu merupakan entitas baru.
spoulson

Saya suka Bergabung, dan saya sangat setuju dengan thesaurus.com :) Gunakan sepanjang waktu ketika ragu tentang nama.
Skurmedel

var suite = TestSuite <string, int> () .Join (x => x.Length) baru;
Sly Gryphon

3
Pergilah dengan Piggyback, imo. Atau HookUpWith.
Chris Marasti-Georg

48

Secara pribadi, saya suka .With (). Jika saya menggunakan objek, setelah membaca dokumentasi atau komentar kode, akan jelas apa fungsinya, dan terbaca ok di kode sumber.

object.With("My new item as well");

Atau, Anda menambahkan "Seiring" dengan itu .. :)

object.AlongWith("this new item");

+1. "WITH" adalah operator infiks di SETL yang melakukan hal yang sama. Jika SETL menggunakannya maka itu pasti benar :-)
finnw

1
Bah ... Siapa yang menggunakan VB lagi? :) Uh .. Opps .. Apakah itu keras? heh .. Tapi, tidak, dengan sangat serius, itu sebabnya saya menganggap "Seiring Dengan", itu akan menghapus masalah VB. Hanya ada sekitar satu juta cara berbeda yang bisa ia lakukan dengan yang satu ini ... Maksudku, bahkan yang gila seperti: object.Plus (), atau Object.ExistingPlus () ... dll ... Ini pertanyaan yang sangat bagus ya diposting, namun ... heh ..
LarryF

33

Saya akhirnya menggunakan Add untuk semua Koleksi Immutable saya di BclExtras . Alasannya adalah karena itu nama yang mudah diprediksi. Saya tidak terlalu khawatir tentang orang yang membingungkan Tambah dengan tambahan yang bermutasi karena nama tipe diawali dengan Immutable.

Untuk sementara saya mempertimbangkan Cons dan nama gaya fungsional lainnya. Akhirnya saya mengabaikan mereka karena mereka hampir tidak dikenal. Tentu programmer fungsional akan mengerti tetapi mereka bukan mayoritas pengguna.

Nama lain: Anda sebutkan:

  • Plus: Saya plin / mencuci yang ini. Bagi saya ini tidak membedakannya sebagai operasi yang tidak bermutasi lagi daripada Add
  • Dengan: Akan menyebabkan masalah dengan VB (pun intended)
  • Overloading operator: Keterjangkauan akan menjadi masalah

Opsi yang saya pertimbangkan:

  • Concat: String's Immutable dan gunakan ini. Sayangnya itu hanya sangat bagus untuk ditambahkan ke akhir
  • CopyAdd: Salin apa? Sumbernya, daftarnya?
  • AddToNewList: Mungkin yang bagus untuk Daftar. Tapi bagaimana dengan Koleksi, Stack, Antrian, dll ...

Sayangnya sepertinya tidak ada kata yang tepat

  1. Jelas merupakan operasi yang tidak berubah
  2. Dapat dimengerti oleh sebagian besar pengguna
  3. Diwakili dalam kurang dari 4 kata

Itu menjadi lebih aneh ketika Anda mempertimbangkan koleksi selain Daftar. Ambil contoh Stack. Bahkan programmer tahun pertama dapat memberi tahu Anda bahwa Stacks memiliki metode Push / Pop pair. Jika Anda membuat ImmutableStack dan memberikannya nama yang sama sekali berbeda, sebut saja Foo / Fop, Anda baru saja menambahkan lebih banyak pekerjaan agar mereka dapat menggunakan koleksi Anda.

Sunting: Respons terhadap Sunting Plus

Saya melihat ke mana Anda pergi dengan Plus. Saya pikir kasus yang lebih kuat sebenarnya adalah Minus untuk dihapus. Jika saya melihat yang berikut ini saya pasti akan bertanya-tanya apa yang dipikirkan programmer itu

list.Minus(obj);

Masalah terbesar yang saya miliki dengan Plus / Minus atau pasangan baru adalah rasanya seperti berlebihan. Koleksinya sendiri sudah memiliki nama yang membedakan, awalan yang tidak dapat diubah. Mengapa melangkah lebih jauh dengan menambahkan kosa kata yang tujuannya adalah untuk menambahkan perbedaan yang sama seperti awalan Immutable lakukan.

Saya bisa melihat argumen situs panggilan. Itu membuatnya lebih jelas dari sudut pandang satu ekspresi. Namun dalam konteks seluruh fungsi sepertinya tidak perlu.

Edit 2

Setuju bahwa orang-orang pasti bingung oleh String.Compat dan DateTime.Add. Saya telah melihat beberapa pemrogram yang sangat cerdas mengalami masalah ini.

Namun saya pikir ImmutableList adalah argumen yang berbeda. Tidak ada apa pun tentang String atau DateTime yang menetapkannya sebagai Tidak Berubah untuk seorang programmer. Anda harus tahu bahwa itu tidak dapat diubah melalui sumber lain. Jadi kebingungan itu tidak terduga.

ImmutableList tidak memiliki masalah itu karena namanya mendefinisikan perilaku itu. Anda bisa berargumen bahwa orang tidak tahu apa itu Immutable dan saya pikir itu juga valid. Saya tentu tidak tahu sampai sekitar tahun 2 di perguruan tinggi. Tetapi Anda memiliki masalah yang sama dengan nama apa pun yang Anda pilih alih-alih Tambah.

Edit 3: Bagaimana dengan tipe-tipe seperti TestSuite yang tidak berubah tetapi tidak mengandung kata?

Saya pikir ini mendorong gagasan bahwa Anda tidak boleh menemukan nama metode baru. Yaitu karena jelas ada drive untuk membuat jenis tidak berubah untuk memfasilitasi operasi paralel. Jika Anda fokus pada mengubah nama metode untuk koleksi, langkah selanjutnya adalah nama metode yang bermutasi pada setiap jenis yang Anda gunakan yang tidak dapat diubah.

Saya pikir ini akan menjadi upaya yang lebih berharga daripada fokus pada membuat jenis yang dapat diidentifikasi sebagai Tidak Berubah. Dengan begitu Anda dapat memecahkan masalah tanpa memikirkan kembali setiap pola metode yang bermutasi di luar sana.

Sekarang bagaimana Anda dapat mengidentifikasi TestSuite sebagai Tidak Berubah? Di lingkungan todays saya pikir ada beberapa cara

  1. Awalan dengan Immutable: ImmutableTestSuite
  2. Tambahkan Atribut yang menggambarkan tingkat Immutablitiy. Ini tentu kurang dapat ditemukan
  3. Tidak banyak lagi.

Tebakan / harapan saya adalah alat pengembangan akan mulai membantu masalah ini dengan membuatnya mudah untuk mengidentifikasi tipe yang tidak dapat diubah hanya dengan melihat (warna berbeda, font yang lebih kuat, dll ...). Tapi saya pikir itu jawabannya meskipun mengubah semua nama metode.


Telah menambahkan alasan preferensi saya untuk Plus daripada Tambahkan ke pertanyaan. Akan menerima komentar tentang alasan itu. Saya benar - benar terbuka pada gagasan bahwa saya bodoh.
Jon Skeet

@JaredPar: Bagaimana kalau tipe ini disebut TestSuite?
Jon Skeet

Ingin memberi +1 lainnya untuk edit 3, tetapi jelas tidak bisa. (Dalam kasus saya, saya tidak mencoba untuk mendapatkan paralelisme - saya percaya bahwa ketidakmampuan mengarah pada kode yang lebih mudah untuk dipikirkan.) Saya masih tidak cukup yakin bahwa Add adalah cara untuk pergi, tetapi dukungan untuk jawaban di sini persuasif.
Jon Skeet

Jika Anda bisa memasukkan pertanyaan ini ke dalam percakapan di tempat kerja, itu juga akan luar biasa, btw. Saya memulai diskusi pada daftar C #, jadi beberapa rekan mungkin sudah terlibat. Mungkin bertanya internal di Google terlalu ...
Jon Skeet

@ Jon, saya pikir saya tahu tempat yang baik untuk menjatuhkan pertanyaan ini di tempat kerja :)
JaredPar

27

Saya pikir ini mungkin salah satu situasi langka di mana itu dapat diterima untuk membebani +operator. Dalam terminologi matematika, kita tahu bahwa +tidak menambahkan sesuatu pada akhir dari sesuatu yang lain. Itu selalu menggabungkan dua nilai bersama dan mengembalikan nilai hasil baru.

Sebagai contoh, secara intuitif jelas ketika Anda mengatakannya

x = 2 + 2;

nilai x yang dihasilkan adalah 4, bukan 22.

Demikian pula,

var empty = new ImmutableList<string>();
var list1 = empty + "Hello";
var list2 = list1 + "immutable";
var list3 = list2 + "word";

harus menjelaskan apa yang masing-masing variabel akan pegang. Seharusnya jelas bahwa list2tidak diubah di baris terakhir, tetapi sebaliknya yang list3ditugaskan hasil menambahkan "kata" ke list2.

Kalau tidak, saya akan beri nama fungsi Plus ().


Bagaimana jika Anda memiliki daftar generik, yang dapat Anda tambahkan bilangan bulat (katakanlah) atau daftar bilangan bulat lainnya secara ? Maka penggunaan + ini akan bertentangan dengan penggabungan.
finnw

@finnw: Saya tidak mengerti maksud Anda. Dengan daftar saya selalu berharap + untuk berarti menambahkan, apakah Anda menambahkan satu elemen atau banyak.
Bill the Lizard

4
Untuk API yang dapat digunakan kembali, ada baiknya juga memiliki metode bernama, seandainya seseorang menggunakan kelas Anda dari bahasa tanpa operator berlebih.
Neil

"apakah Anda menambahkan satu elemen atau banyak" - bagaimana jika Anda ingin menambahkan daftar sebagai elemen tunggal? yaitu, [1] + 2 = [1,2]tetapi [1] + [2] = [1,[2]]. Apa yang Anda sarankan adalah perilaku yang tidak konsisten. Ini mungkin mengapa Python tidak memungkinkan Anda untuk menambahkan satu elemen dengan cara ini.
Mpen

Nah, dalam bahasa yang diketik secara statis seperti C # Anda dapat mengetahui apa jenis elemen daftar, apakah daftar daftar atau daftar elemen, sehingga Anda dapat menggunakan jenis untuk memutuskan apakah akan menambahkan satu elemen yang merupakan daftar atau gabungan. dua daftar.
Dobes Vandermeer

22

Agar sejelas mungkin, Anda mungkin ingin pergi dengan wordier CopyAndAdd, atau yang serupa.


Tidak semua koleksi yang tidak dapat diubah memerlukan salinan untuk ditambahkan. Pikirkan pohon abadi, mereka hanya perlu simpul baru dan dapat menggunakan pohon yang ada sebagai daun.
JaredPar

BTW, saya membaca profil Anda, lalu menua sesuai urutan dan kagum secara singkat pada usia Anda. Sanity menendang sesaat setelahnya.
JaredPar

Komentar pertama saya: Saya jarang menggunakan pohon sehingga pikiran itu tidak pernah terpikir oleh saya. Itu poin yang bagus.
Michael Myers

Komentar kedua: Saya akui, saya melakukannya untuk lencana! Saya hanya tidak suka memberikan umur saya. (Saya sebenarnya lebih muda dari Anda, tetapi saya bisa memainkan permainan tua yang cukup bagus jika saya perlu. Dan saya bukan satu-satunya yang usianya terdaftar 89).
Michael Myers

Argumen pohon abadi adalah yang kuat, poin bagus. Jadi EquivalentReferenceWithAdded (x) akan melawan argumen itu, tetapi terdengar bodoh, dan sulit untuk disimpulkan.
TheBlastOne

21

Saya akan menyebutnya Extend () atau mungkin ExtendWith () jika Anda merasa benar-benar bertele-tele.

Extends berarti menambahkan sesuatu ke sesuatu yang lain tanpa mengubahnya. Saya pikir ini adalah terminologi yang sangat relevan dalam C # karena ini mirip dengan konsep metode ekstensi - mereka "menambahkan" metode baru ke kelas tanpa "menyentuh" ​​kelas itu sendiri.

Kalau tidak, jika Anda benar-benar ingin menekankan bahwa Anda sama sekali tidak memodifikasi objek asli, menggunakan beberapa awalan seperti Get- sepertinya tidak dapat dihindari oleh saya.


1
Masih agak menyiratkan melakukan sesuatu ke objek dasar.
kekacauan

18

Ditambahkan (), ditambahkan ()

Saya suka menggunakan bentuk lampau untuk operasi pada objek yang tidak dapat diubah. Ini menyampaikan gagasan bahwa Anda tidak mengubah objek asli, dan mudah dikenali saat Anda melihatnya.

Juga, karena nama metode yang bermutasi seringkali merupakan kata kerja present-tense, ini berlaku untuk sebagian besar kasus metode-nama-diperlukan yang tidak dapat diubah yang Anda temui. Sebagai contoh, stack yang tidak dapat diubah memiliki metode "push" dan "popped".


1
Python juga menggunakan konvensi ini. Misalnya fungsi bawaan dibalik () dan diurutkan ().
Joe

18

Saya suka saran saya dari CopyAndAdd . Sesuai dengan tema "mutasi", mungkin Anda bisa menggunakan Bud (reproduksi aseksual), Grow , Replicate , atau Evolve ? =)

EDIT: Untuk melanjutkan dengan tema genetik saya, bagaimana dengan Procreate , menyiratkan bahwa objek baru dibuat yang didasarkan pada yang sebelumnya, tetapi dengan sesuatu yang baru ditambahkan.


14

Ini mungkin peregangan, tetapi di Ruby ada notasi yang umum digunakan untuk perbedaan: addtidak bermutasi; add!bermutasi. Jika ini adalah masalah yang meluas di proyek Anda, Anda bisa melakukannya juga (tidak harus dengan karakter non-alfabet, tetapi secara konsisten menggunakan notasi untuk menunjukkan metode mutasi / non-mutasi).


+1. ini tidak dipaksakan oleh bahasa, tetapi disepakati sebagai konvensi. Aku suka itu.
oma


13

Mungkin kebingungan berasal dari kenyataan bahwa Anda menginginkan dua operasi dalam satu. Mengapa tidak memisahkan mereka? Gaya DSL:

var list = new ImmutableList<string>("Hello");
var list2 = list.Copy().With("World!");

Copy akan mengembalikan objek perantara, itu salinan daftar asli yang bisa diubah. Withakan mengembalikan daftar baru yang tidak dapat diubah.

Memperbarui:

Tetapi, memiliki koleksi perantara yang dapat berubah-ubah bukanlah pendekatan yang baik. Objek perantara harus terkandung dalam Copyoperasi:

var list1 = new ImmutableList<string>("Hello");
var list2 = list1.Copy(list => list.Add("World!"));

Sekarang, Copyoperasi membutuhkan delegasi, yang menerima daftar bisa berubah, sehingga dapat mengontrol hasil salinan. Itu bisa melakukan lebih dari sekadar menambahkan elemen, seperti menghapus elemen atau mengurutkan daftar. Ini juga dapat digunakan dalam ImmutableListkonstruktor untuk mengumpulkan daftar awal tanpa daftar perantara yang tidak dapat diubah.

public ImmutableList<T> Copy(Action<IList<T>> mutate) {
  if (mutate == null) return this;
  var list = new List<T>(this);
  mutate(list);
  return new ImmutableList<T>(list);
}

Sekarang tidak ada kemungkinan salah tafsir oleh pengguna, mereka secara alami akan jatuh ke dalam lubang kesuksesan .

Namun pembaruan lainnya:

Jika Anda masih tidak suka menyebutkan daftar yang dapat diubah, bahkan sekarang yang sudah termuat, Anda bisa mendesain objek spesifikasi, yang akan menentukan , atau skrip , bagaimana operasi penyalinan akan mengubah daftar. Penggunaannya akan sama:

var list1 = new ImmutableList<string>("Hello");
// rules is a specification object, that takes commands to run in the copied collection
var list2 = list1.Copy(rules => rules.Append("World!"));

Sekarang Anda dapat berkreasi dengan nama aturan dan Anda hanya dapat mengekspos fungsionalitas yang Anda inginkan Copy dukung, bukan seluruh kemampuan suatuIList .

Untuk penggunaan chaining, Anda dapat membuat konstruktor yang masuk akal (yang tentu saja tidak akan menggunakan chaining):

public ImmutableList(params T[] elements) ...

...

var list = new ImmutableList<string>("Hello", "immutable", "World");

Atau gunakan delegasi yang sama di konstruktor lain:

var list = new ImmutableList<string>(rules => 
  rules
    .Append("Hello")
    .Append("immutable")
    .Append("World")
);

Ini mengasumsikan bahwa rules.Append metode kembalithis .

Ini akan terlihat seperti dengan contoh terbaru Anda:

var suite = new TestSuite<string, int>(x => x.Length);
var otherSuite = suite.Copy(rules => 
  rules
    .Append(x => Int32.Parse(x))
    .Append(x => x.GetHashCode())
);

@Jordao: Karena komposisi seperti ini mengarah ke bentuk inisialisasi yang jauh lebih sederhana. Mengapa memiliki dua variabel terpisah ketika saya hanya ingin satu? Saya juga tidak ingin membuat salinan yang dapat diubah - Saya ingin semuanya tidak berubah sepanjang, karena itu mengarah pada kode yang lebih mudah untuk dipikirkan, IMO.
Jon Skeet

Semua ini masih lebih sulit daripada "Plus" dll. Terima kasih atas ide-ide yang melibatkan mutasi, tapi saya lebih suka pendekatan "menjaganya agar tetap".
Jon Skeet

Mungkin kemudian akan selalu ada salah tafsir tentang apa sebenarnya semantik operasi itu. Jika Anda mengikuti rute objek spesifikasi, tidak ada mutasi yang terjadi (setidaknya tidak secara eksternal), objek hanya menentukan seperti apa objek yang tidak berubah itu nantinya. Apa yang Anda miliki adalah operasi yang bergerak dari satu objek yang tidak dapat diubah ke objek lain, dan karena itu disebut Salin, tidak ada ruang untuk kesalahpahaman.
Jordão

Satu-satunya nama yang akan bekerja untuk Anda tampaknya nama senyawa, seperti CopyAndAppend, CopyAndAdd, dll
Jordão

1
Saya sebenarnya semakin menyukai pendekatan ini (dengan semua suntingan) sebagai API untuk koleksi yang tidak dapat diubah. Namun, saya berpendapat bahwa menggabungkan pendekatan ini dengan metode pembantu untuk spesifikasi standar, seperti Concat, menawarkan yang terbaik dari kedua dunia.
rami

11

Beberapa pemikiran acak:

  • ImmutableAdd ()
  • Menambahkan()
  • ImmutableList <T> (ImmutableList <T> originalList, T newItem) Konstruktor

1
+1 untuk ImmutableAdd; tidak tertarik pada Append (terlalu banyak seperti StringBuilder.Append yang bermutasi) dan versi konstruktor adalah sakit dalam hal chaining.
Jon Skeet

10

DateTime di C # menggunakan Tambah. Jadi mengapa tidak menggunakan nama yang sama? Selama pengguna kelas Anda memahami kelas tidak akan berubah.


Saya berpendapat bahwa DateTime. Menambahkan telah diketahui membingungkan orang ... tapi saya setuju itu menunjukkan diutamakan.
Jon Skeet

1
Sama seperti metode untuk memutasi string membingungkan bagi pengembang baru. Tetapi segera semua orang mengetahui bahwa "string tidak dapat diubah"
Tundey

9

Saya pikir hal utama yang Anda coba dapatkan yang sulit diungkapkan adalah nonpermutasi, jadi mungkin sesuatu dengan kata generatif di dalamnya, sesuatu seperti CopyWith () atau InstancePlus ().


9

Saya tidak berpikir bahasa Inggris akan membiarkan Anda menyiratkan ketidakmampuan dengan cara yang salah saat menggunakan kata kerja yang artinya sama dengan "Tambah". "Plus" hampir melakukannya, tetapi orang masih bisa membuat kesalahan.

Satu-satunya cara Anda akan mencegah pengguna salah mengartikan objek untuk sesuatu yang bisa berubah adalah dengan membuatnya eksplisit, baik melalui nama objek itu sendiri atau melalui nama metode (seperti dengan opsi verbose seperti "GetCopyWith" atau "CopyAndAdd").

Jadi pergilah dengan favorit Anda, "Plus."


9

Pertama, titik awal yang menarik: http://en.wikipedia.org/wiki/Naming_conventions_(programming) ... Secara khusus, periksa tautan "Lihat Juga" di bagian bawah.

Saya mendukung Plus atau Dan, secara efektif setara.

Plus dan Dan keduanya berbasis matematika dalam etimologi. Dengan demikian, keduanya berkonotasi operasi matematika; keduanya menghasilkan ekspresi yang dibaca secara alami sebagai ekspresi yang dapat berubah menjadi nilai, yang cocok dengan metode yang memiliki nilai balik. Andmengandung konotasi logika tambahan, tetapi kedua kata tersebut berlaku secara intuitif pada daftar. Addberkonotasi tindakan yang dilakukan pada objek, yang bertentangan dengan semantik abadi metode.

Keduanya pendek, yang sangat penting mengingat keutamaan operasi. Operasi sederhana dan sering dilakukan layak mendapatkan nama yang lebih pendek.

Mengekspresikan semantik abadi adalah sesuatu yang saya lebih suka lakukan melalui konteks. Yaitu, saya lebih baik menyiratkan bahwa seluruh blok kode ini memiliki nuansa fungsional; menganggap semuanya tidak berubah. Tapi itu mungkin aku saja. Saya lebih suka kekekalan untuk menjadi aturan; jika dilakukan, itu dilakukan banyak di tempat yang sama; mutabilitas adalah pengecualian.


8

Bagaimana dengan Chain () atau Attach ()?


1
Melampirkan pastinya terdengar seperti bermutasi. Mungkin WithAttached akan lebih bijaksana, tetapi sangat dekat dengan WithAdded, yang telah dibahas di atas.
TheBlastOne

Sungguh lucu berapa kali "rantai" disebutkan dalam menggambarkan apa yang coba dilakukan dengan ini. (5 kali), tetapi tidak ditawarkan sebagai saran! Ini adalah hal pertama yang muncul visualthesaurus.com(tidak ada afiliasi) ketika saya mencari concatenate.
cod3monk3y

7

Saya lebih suka Plus (dan Minus). Mereka mudah dimengerti dan memetakan langsung ke operasi yang melibatkan tipe-tipe yang tidak dapat diubah (angka-angka). 2 + 2 tidak mengubah nilai 2, ia mengembalikan nilai baru yang juga tidak berubah.

Beberapa kemungkinan lain:

Sambatan()

Korupsi()

Accrete ()


6

Bagaimana dengan jodoh , jodoh , atau senggama , bagi mereka yang tinggal. Dalam hal mereproduksi mamalia umumnya dianggap tidak berubah.

Akan membuang Union di luar sana juga. Dipinjam dari SQL.


2
+1 untuk Union. Namun, saya meminjamnya langsung dari teori himpunan. :-)
Christoffer Lette

Bukankah SQL mendapatkan banyak terminologinya dari teori himpunan?
Jason D

1
Juga, Union menyiratkan perbedaan .. Jika Anda ingin menyertakan duplikat (setidaknya dalam TSQL), Anda harus menggunakan Union All secara eksplisit.
rami

6

Tampaknya saya orang Obj-C / Kakao pertama yang menjawab pertanyaan ini.

NNString *empty = [[NSString alloc] init];
NSString *list1 = [empty stringByAppendingString:@"Hello"];
NSString *list2 = [list1 stringByAppendingString:@"immutable"];
NSString *list3 = [list2 stringByAppendingString:@"word"];

Tidak akan memenangkan permainan golf kode apa pun dengan ini.


Memberi +1 [object]By[Verb]ing[Object]:awalan ke metode menyiratkan bahwa string baru akan dikembalikan sebagai lawan sederhana [verb][Object]:, yang akan bermutasi objek di tempat.
Dave DeLong

3
+1. Saya tidak mengerti penolakan orang terhadap kata-kata kasar (alias dokumentasi diri).
hatfinch

5

Saya pikir "Tambah" atau "Plus" kedengarannya bagus. Nama daftar itu sendiri harus cukup untuk menyampaikan keabadian daftar itu.


Tidak ada daftar, ini adalah test suite.
tstenner

5

Mungkin ada beberapa kata yang mengingat saya lebih dari membuat salinan dan menambahkan hal-hal itu daripada mengubah contoh (seperti "Concatenate"). Tapi saya pikir memiliki beberapa simetri untuk kata-kata itu untuk tindakan lain juga baik untuk dimiliki. Saya tidak tahu kata yang sama untuk "Hapus" yang saya pikirkan dari jenis yang sama seperti "Gabungan". "Plus" terdengar agak aneh bagiku. Saya tidak berharap itu digunakan dalam konteks non-numerik. Tapi itu juga bisa berasal dari latar belakang non-Inggris saya.

Mungkin saya akan menggunakan skema ini

AddToCopy
RemoveFromCopy
InsertIntoCopy

Ini memiliki masalah mereka sendiri, ketika saya memikirkannya. Orang bisa berpikir mereka menghapus sesuatu atau menambahkan sesuatu ke argumen yang diberikan. Tidak yakin sama sekali. Kata-kata itu tidak bermain bagus dalam rantai juga, kurasa. Terlalu bertele untuk mengetik.

Mungkin saya hanya akan menggunakan polos "Tambah" dan teman-teman juga. Saya suka bagaimana ini digunakan dalam matematika

Add 1 to 2 and you get 3

Yah, tentu saja, 2 tetap menjadi 2 dan Anda mendapatkan nomor baru. Ini tentang dua angka dan bukan tentang daftar dan elemen, tetapi saya pikir ini memiliki beberapa analogi. Menurut saya, addtidak lantas berarti Anda bermutasi. Saya tentu melihat maksud Anda bahwa memiliki pernyataan kesepian berisi hanya adddan tidak menggunakan objek baru yang dikembalikan tidak terlihat buggy. Tapi saya sekarang juga sudah memikirkan ide menggunakan nama lain selain "tambah" tetapi saya tidak bisa membuat nama lain, tanpa membuat saya berpikir "hmm, saya perlu melihat dokumentasi untuk mengetahui apa ini tentang "karena namanya berbeda dari yang saya harapkan disebut" add ". Hanya beberapa pemikiran aneh tentang ini dari litb, tidak yakin itu masuk akal sama sekali :)


Tetapi salinan tidak selalu diperlukan dalam koleksi yang tidak berubah. Ambil pohon biner misalnya. Menambahkan root baru tidak memerlukan penyalinan, hanya nilai baru di mana salah satu daunnya adalah pohon tua
JaredPar

KISS - Jika penamaan mulai menyertakan detail implementasi, semua nama metode akan menjadi terlalu panjang. "tambah" cukup sederhana dan berhasil.
mP.

1
@ MP: Sekali lagi Anda menggunakan frasa "detail implementasi" dengan cara yang saya yakini tidak cocok. Apakah itu daftar tertaut atau array di bawah tenda adalah detail implementasi . Saya bisa mengubah implementasinya tanpa mengubah API. Aspek abadi bukanlah detail implementasi.
Jon Skeet

1
Baik. JaredPar, tetapi saya pikir itu juga tidak penting apakah itu benar - benar menyalin pohon atau hanya menggunakan pohon yang ada dan menggunakannya sebagai daun untuk pohon baru yang dikembalikan. Maksud saya, itu hanya detail implementasi. itu sama untuk (saya percaya) operasi substring untuk kelas string java.
Johannes Schaub - litb


5

Saya berpikir bahwa Plus()dan Minus()atau sebaliknya, Including(), Excluding()wajar di menyiratkan perilaku berubah.

Namun, tidak ada pilihan penamaan yang akan membuatnya sangat jelas bagi semua orang, jadi saya pribadi percaya bahwa komentar xml doc yang bagus akan sangat membantu di sini. VS melempar ini tepat di wajah Anda ketika Anda menulis kode di IDE - mereka sulit untuk diabaikan.


4

Append - karena, perhatikan bahwa nama System.String metode menyarankan bahwa mereka mengubah instance, tetapi tidak.

Atau saya cukup suka AfterAppending:

void test()
{
  Bar bar = new Bar();
  List list = bar.AfterAppending("foo");
}

Seperti DateTime argumen sebelumnya, saya setuju dengan didahulukan jika bukan karena fakta bahwa begitu banyak programmer yang berharap metode string untuk melakukan hal-hal. Mereka harus diberi tahu (kadang-kadang berulang kali) bahwa string tidak dapat diubah. Saya ingin memikat pengembang klien saya ke dalam lubang sukses :)
Jon Skeet

Saya suka Tambah lagi dan lagi. Ini membedakan bahwa Anda tidak memutasikan koleksi tetapi bergabung dengannya.

4

list.CopyWith(element)

Seperti halnya Smalltalk :)

Dan itu juga list.copyWithout(element)menghapus semua kemunculan elemen, yang paling berguna saat digunakan list.copyWithout(null)untuk menghapus elemen yang tidak disetel.


3

Saya akan memilih Add, karena saya dapat melihat manfaat dari nama yang lebih baik, tetapi masalahnya adalah menemukan nama yang berbeda untuk setiap operasi yang tidak dapat diubah lainnya yang mungkin membuat kelas cukup asing jika itu masuk akal.


Ya, saya mengerti maksud Anda. Saya pikir saya masih lebih suka Plus, tapi itu layak dipertimbangkan.
Jon Skeet

Terima kasih, Jon. Saya menantikan untuk menggunakan kerangka kerja Anda. Saya baru saja membaca tentang itu dan itu terlihat sangat bagus. Terima kasih lagi.
Joan Venge
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.