Waffly unvanı için özür dilerim - kısa bir başlık bulabilirsem soruyu sormak zorunda kalmazdım.
Değişmez bir liste türüm olduğunu varsayalım. Sonunda Foo(x)
belirtilen bağımsız değişken ile yeni bir değişmez liste döndüren bir işlem var. Yani "Merhaba", "değişmez", "dünya" değerlerine sahip dizelerin bir listesini oluşturmak için şunu yazabilirsiniz:
var empty = new ImmutableList<string>();
var list1 = empty.Foo("Hello");
var list2 = list1.Foo("immutable");
var list3 = list2.Foo("word");
(Bu C # kodudur ve dilin önemli olduğunu düşünüyorsanız en çok C # önerisiyle ilgileniyorum. Temelde bir dil sorusu değil, ancak dilin deyimleri önemli olabilir.)
Önemli olan mevcut listeleri olmasıdır değil tarafından değiştirilmiş Foo
öylesine - empty.Count
hala 0 döndürecektir.
Son sonuca ulaşmanın bir başka (daha deyimsel) yolu:
var list = new ImmutableList<string>().Foo("Hello")
.Foo("immutable")
.Foo("word");
Sorum şu: Foo'nun en iyi adı nedir?
DÜZENLEME 3 : Daha sonra açıkladığım gibi ImmutableList<T>
, türün adı aslında olmayabilir , bu da konumu netleştirir. Bunun yerine TestSuite
ve bunun değişmez olduğunu hayal edin çünkü bir parçası olduğu çerçevenin tamamı değişmez ...
(Düzenleme sonu 3)
Şimdiye kadar bulduğum seçenekler:
Add
: .NET'te yaygındır, ancak orijinal listenin mutasyonunu ima ederCons
: Bunun işlevsel dillerde normal ad olduğuna inanıyorum, ancak bu dillerde deneyimi olmayanlar için anlamsızPlus
: şimdiye kadarki favorim, bana mutasyon demek değil . Görünüşe göre bu Haskell'de de kullanılıyor, ancak biraz farklı beklentilerle (bir Haskell programcısı, diğer listeye tek bir değer eklemek yerine birlikte iki liste eklemesini bekleyebilir).With
: diğer bazı değişmez sözleşmelerle tutarlı olmakla birlikte, IMO'ya tamamen aynı "katılıma" sahip değildir.And
: çok açıklayıcı değil.- + İçin operatör aşırı yükü: Gerçekten bu kadar sevmiyorum; Genel olarak operatörlerin yalnızca daha düşük seviye türlerine uygulanması gerektiğini düşünüyorum. Yine de ikna olmaya hazırım!
Seçim için kullandığım kriterler:
- Yöntem çağrısının sonucuna ilişkin doğru izlenimi verir (yani, fazladan bir öğeye sahip orijinal liste olduğu anlamına gelir)
- Mevcut listeyi değiştirmediğini olabildiğince netleştirir
- Yukarıdaki ikinci örnekte olduğu gibi birlikte zincirlendiğinde makul geliyor
Kendimi yeterince açıklamıyorsam lütfen daha fazla ayrıntı isteyin ...
DÜZENLEME 1: İşte tercih Plus
etme nedenim Add
. Şu iki kod satırını düşünün:
list.Add(foo);
list.Plus(foo);
(Ve bu benim görünümünde olan kişisel bir şey) ikincisi açıkça adamcağız - yazılı gibi "x + 5;" kendi başına bir ifade olarak. İlk satır, değişmez olduğunu hatırlayana kadar, tamam gibi görünüyor. Aslında, artı operatörün kendi başına işlenenlerini değiştirmemesi Plus
, benim favorimin başka bir nedenidir . Operatörün aşırı yüklenmesi gibi hafif bir rahatsızlık olmadan, yine de (benim için) işlenenleri mutasyona uğratmamayı (veya bu durumda yöntem hedefini) içeren aynı çağrışımları verir.
DÜZENLEME 2: Add'i beğenmeme nedenleri.
Çeşitli cevaplar etkili bir şekilde: "Add ile git. Bu , değişmezliği açık hale getirmeyen yöntemlere sahiptir DateTime
ve böyle." Katılıyorum - burada öncelik var. İnsanlar diyoruz Ancak, ben bol gördüm ya ve mutasyon bekliyoruz . Çok sayıda haber grubu sorusu var (ve eğer etrafta kazarsam muhtemelen SO olanlar).String
Replace
DateTime.Add
String.Replace
String.Replace
; dizeler değiştirilemez, yeni bir dize döndürülür."
Şimdi, soruya incelik açığa çıkarmalıdır - tipi olabilir değil aslında bir değişmez liste, ancak farklı bir değişmez tipte. Özellikle, bir pakete testler eklediğiniz ve bu yeni bir paket oluşturan bir karşılaştırma çerçevesi üzerinde çalışıyorum. Açıktır ki:
var list = new ImmutableList<string>();
list.Add("foo");
hiçbir şey başaramayacak, ancak şu şekilde değiştirdiğinizde çok daha karanlık oluyor:
var suite = new TestSuite<string, int>();
suite.Add(x => x.Length);
Tamam olmalı. Oysa bu benim için hatayı daha net hale getiriyor:
var suite = new TestSuite<string, int>();
suite.Plus(x => x.Length);
Bu sadece yalvarıyor:
var suite = new TestSuite<string, int>().Plus(x => x.Length);
İdeal olarak, kullanıcılarımın test paketinin değişmez olduğu söylenmemesini istiyorum. Onların başarı çukuruna düşmelerini istiyorum. Bu mümkün olmayabilir , ama denemek istiyorum.
Sadece değişmez bir liste türü hakkında konuşarak orijinal soruyu aşırı basitleştirdiğim için özür dilerim. Tüm koleksiyonlar kendileri kadar açıklayıcı değildir ImmutableList<T>
:)