Hem 'boş' hem de 'Belki' kavramına sahip olmak mantıklı mı?


11

C # bir web API için bir istemci oluştururken , nulliki farklı şeyi temsil edecek bir değer olarak ilgili bir sorunla karşılaştım :

  • hiçbir şey , örneğin bir foomayın olabilir veya olmayabilirbar
  • bilinmiyor : Varsayılan olarak API yanıtı yalnızca bir özellik alt kümesi içerir, hangi ek özellikleri istediğinizi belirtmeniz gerekir. Yani bilinmeyen özelliği API talep edilmemiştir anlamına gelir.

Bazı aramalardan sonra, belki de (veya Option) tipini, fonksiyonel dillerde nasıl kullanıldığını ve kullanıcıyı bir değerin bulunmaması hakkında düşünmeye zorlayarak boş dereferencing sorunlarını nasıl "çözdüğünü" öğrendim. Ancak, tüm kaynakları ı yerine bahsettik karşılaşılan null adlı ile Belki . Üç değerli mantıktan bahsetmiştim , ama tam olarak anlayamıyorum ve çoğu zaman sözü "kötü bir şey" bağlamındaydı.

Şimdi hem boş hem de Belki kavramının, bilinmeyen ve hiçbir şeyi temsil etmenin mantıklı olup olmadığını merak ediyorum . Bu okuduğum üç değerli mantık mı yoksa başka bir adı var mı? Ya da belki bir Belki bir Belki iç içe geçmenin yolu mu?


9
Sahip olmak sanse yapmaz null. Tamamen kırılmış bir fikir.
Andrej Bauer

7
Belki-foo'dan farklı anlambilime sahip belki-belki-foo yapmayın. Belki bir monad , ve monad yasalarından biri de aynı semantiğe sahip olması M M xve M xolması gerekir.
Eric Lippert

2
Hiçbir şey (hiçbir nesneye başvuru), Null (veritabanı null semantics), Empty (başlatılmamış bir değişken) ve Eksik (isteğe bağlı bir parametre iletilmedi) olan Visual Basic'in önceki sürümlerinin tasarımına bakmayı düşünebilirsiniz. Bu tasarım karmaşıktı ve birçok açıdan tutarsızdı, ancak bu kavramların birbiriyle karıştırılmamasının bir nedeni var.
Eric Lippert

3
Evet, belki de kullanmam. Ancak, aslında, bir + 1 ileMaybe a aynı , anlamsal olarak , + 1 + 1 ile aynıdır ve @Andej cevabından yazmak için izomorfiktir . Bu tür için kendi monad örneğinizi de tanımlayabilir ve bu nedenle farklı monad birleştiriciler kullanabilirsiniz. bir+1Maybe Maybe abir+1+1UserInput a
Euge

12
@EricLippert: " M (M x)ve M xaynı anlambilime sahip olması" yanlıştır . Al M = Listörneğin: listelerinin listeleri listeleri gibi aynı şey değildir. Ne zaman Mbir monad, orada bir olan dönüşüm dan (yani monad çarpma) M (M x)için M xhangi aralarındaki ilişkiyi açıklar, ancak "aynı semantik" yok.
Andrej Bauer

Yanıtlar:


14

Her nullyerde varsayılan hediye olarak değer sadece gerçekten kırık bir fikirdir , bu yüzden unutun.

Her zaman gerçek verilerinizi en iyi tanımlayan konsepte sahip olmalısınız. "Bilinmeyen", "hiçbir şey" ve "değer" i gösteren bir türe ihtiyacınız varsa, tam olarak buna sahip olmalısınız. Ancak gerçek ihtiyaçlarınıza uymuyorsa, yapmamalısınız. Başkalarının ne kullandığını ve önerdiklerini görmek iyi bir fikirdir, ancak körü körüne takip etmek zorunda değilsiniz.

Standart kütüphaneler tasarlayan insanlar ortak kullanım modellerini tahmin etmeye çalışırlar ve genellikle bunu iyi yaparlar, ancak ihtiyacınız olan belirli bir şey varsa, kendiniz tanımlamanız gerekir. Örneğin, Haskell'de şunları tanımlayabilirsiniz:

data UnknownNothing a =
     Unknown
   | Nothing
   | Value a

Hatırlanması daha kolay olan daha açıklayıcı bir şey kullanmanız bile söz konusu olabilir:

data UserInput a =
     Unknown
   | NotGiven
   | Answer a

Farklı senaryolar için kullanılacak bu tür 10 tür tanımlayabilirsiniz. Dezavantajı, önceden var olan kütüphane işlevlerine (bunun gibi Maybe) sahip olmamanızdır , ancak bu genellikle bir ayrıntıdır. Kendi işlevselliğinizi eklemek o kadar zor değil.


Böyle hecelendiğini gördüğünüzde mantıklı geliyor. Çoğunlukla fikirlerle ilgileniyorum, mevcut kütüphane desteği sadece bir bonus :)
Stijn

Sadece bu tür türlerin oluşturulmasındaki engel birçok dilde daha düşük olsaydı. : /
Raphael

Sadece insanlar 1960'lardan itibaren dil kullanmayı bıraktıysa (veya 1980'lerden reenkarnasyonları).
Andrej Bauer

@AndrejBauer: ne? ama teorisyenlerin şikayet edecek bir şeyleri olmazdı!
Yttrill

Şikayet etmiyoruz, tepedeyiz.
Andrej Bauer

4

Bildiğim kadarıyla null, C # değeri türüne bağlı olarak bazı değişkenler için olası bir değerdir (doğru miyim?). Örneğin, bazı sınıf örnekleri. Diğer türler için (gibi int, boolvb.) Değişkenleri bildirerek int?veya bool?bunun yerine bildirerek bu istisna değerini ekleyebilirsiniz (bu, bir Maybesonraki adımda açıklayacağım gibi yapıcı tam olarak bunu yapar).

MaybeFonksiyonel programlama gelen tip yapıcısı belirli bir veri türü için bu yeni durum değer katar. Yani Inttamsayıların türü veya Gamebir oyunun durumunun türü ise, o Maybe Intzaman tüm tamsayıların artı null (bazen hiçbir şey olarak adlandırılır ) değerine sahiptir. Aynısı Maybe Game. Burada, nulldeğerle gelen hiçbir tür yoktur . İhtiyacınız olduğunda ekleyin.

IMO, bu son yaklaşım herhangi bir programlama dili için daha iyidir.


Evet, C # anlayışınız doğrudur. Peki cevabınızdan iç içe Maybegeçmeyi ve nulltamamen düşmeyi önerdiğinizi çıkarabilir miyim ?
Stijn

2
Benim düşüncem bir dilin nasıl olması gerektiğiyle ilgili. Gerçekten C # programlama en iyi uygulamaları bilmiyorum. Sizin durumunuzda, en iyi seçenek @Andrej Bauer'ın tanımladığı gibi bir veri tipini tanımlamak olacaktır, ancak bence bunu C # ile yapamazsınız.
Euge

@Euge: Cebirsel Toplam Türleri (kabaca) klasik OO tarzı alt tipleme ve alt tip polimorfik mesaj gönderimi ile yakınlaştırılabilir. Scala'da böyle yapılır, örneğin kapalı tiplere izin vermek için ek bir bükülme . Tip soyut bir üst sınıfa dönüşür, tip yapıcılar somut alt sınıfa dönüşür, konstrüktörler üzerinde desen eşleşmesi ya vakaları somut alt sınıflarda veya isinstancetestlerde aşırı yüklenmiş yöntemlere taşıyarak tahmin edilebilir . Scala da "uygun" desen eşleşmesine sahiptir ve C♯ aslında son zamanlarda basit desenler de kazanmıştır.
Jörg W Mittag

"Ek büküm" Ben Scala için belirtilen "standart" değiştiricileri (miras edilebilir bir sınıf için) "sanal" ve ek olarak olmasıdır final(miras edilemez bir sınıf için), aynı zamanda sahip sealeda için, yalnızca aynı derleme birimi içinde genişletilebilen sınıf . Bu, derleyicinin tüm olası alt sınıfları statik olarak bilmesi anlamına gelir (hepsi ya kendileri sealedya da kendileri olduğu finalsürece) ve böylece çalışma zamanı kodu yüklenen ve sınırsız kalıtıma sahip bir dil için statik olarak mümkün olmayan desen eşleşmeleri için kapsamlılık kontrolleri yapabilir.
Jörg W Mittag

Tabii ki C # bu semantik ile türleri tasarlayabilirsiniz. C #, yerleşik türün (C # içinde Nullable olarak adlandırılır) yuvalanmasına izin vermediğini unutmayın. int??C # 'da yasadışı.
Eric Lippert

3

Eğer böyle tip birlikler, tanımlayabilir varsa X or Yve siz adında bir türü varsa Nullsadece temsil nulldeğeri (ve başka bir şey), sonra her türü için T, T or Nullaslında çok farklı değilMaybe T . Tek sorun null, dilin bir türü örtük Tolarak ele alması ve her tür için geçerli bir değer oluşturmasıdır (bunlara sahip dillerdeki ilkel türler hariç). Örneğin Java'yı alan bir işlevi de kabul eden bir şey budur .T or NullnullStringnull

Türleri değer kümesi ve orkümelerin birleşimi olarak ele alırsanız , aynı (T or Null) or Nulldeğer kümesini temsil eder . Bu tür analizleri yapan derleyiciler vardır (SBCL). Yorumlarda belirtildiği gibi, kolayca ayırt edemezsinizT ∪ {null} ∪ {null}T or NullMaybe TMaybe Maybe T türleri ve ne zaman alan olarak görüntülediğinizde (diğer yandan, bu görünüm dinamik olarak yazılan programlar için oldukça yararlıdır). Ama türleri aynı zamanda (T or Null) or Nullbirden fazla Maybes seviyesini temsil eden cebirsel ifadeler olarak da tutabilirsiniz .


2
Aslında, bununla Maybe (Maybe X)aynı şey olmaması önemlidir Maybe X. Nothingile aynı şey değildir Just Nothing. Conflating Maybe (Maybe X)ile Maybe Ximkansız tedavi yapar Maybe _polymorphically.
Gilles 'SO- kötü olmayı bırak'

1

Neyi ifade etmek istediğinizi ve sonra bunu nasıl ifade edeceğinizi bulmanız gerekir.

İlk olarak, sorunlu alanınızda (sayılar, dizeler, müşteri kayıtları, booleans vb.) Değerler var. İkinci olarak, sorun etki alanı değerlerinizin üstünde bazı ek, genel değerler vardır: Örneğin, "hiçbir şey" (bir değerin bilinen yokluğu), "bilinmeyen" (bir değerin varlığı veya yokluğu hakkında bilgi yok), " "(kesinlikle bir değer vardır, ama hangisini bilmiyoruz). Belki diğer durumları düşünebilirsiniz.

Tüm değerleri artı bu üç ek değeri temsil edebilmek isterseniz, "hiçbir şey", "bilinmeyen", "bir şey" ve "değer" durumlarıyla bir numaralandırma oluşturabilir ve oradan gidersiniz.

Bazı dillerde bazı durumlar daha basittir. Örneğin, Swift'te her T türü için, olası değerleri nil artı T'nin tüm değerlerine sahip olan "isteğe bağlı T" türüne sahipsiniz. Bu , birçok durumu kolayca ele almanızı sağlar ve "hiçbir şey" ve " değer". Eğer "bilinmeyen" ve "değer" varsa kullanabilirsiniz. Yapabilirsin değil sen "hiçbir şey", "bilinmeyeni" ve "değer" işlemek için gerekiyorsa bunu kullanın. Diğer diller "boş" veya "belki" kullanabilir, ancak bu yalnızca başka bir sözcüktür.

JSON'da anahtar / değer çiftlerine sahip sözlükleriniz vardır. Burada, bir anahtar sözlükten eksik olabilir veya değeri null olabilir. Dolayısıyla, şeylerin nasıl saklandığını dikkatlice açıklayarak, genel değerleri artı iki ek değeri temsil edebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.