Bir programlama dilinde alt tip olması için bir sebep var mı?


49

Bir alt tip, öncelikle matematiksel tip teorisinde ortaya çıkan bir yapıdır. Ayrıca boş tip olarak da adlandırılır. Değeri olmayan bir türdür, ancak tüm türlerin bir alt türüdür.

Bir işlevin dönüş türü, alt tür ise, bu geri dönmediği anlamına gelir. Dönemi. Belki de sonsuza dek sürüyor, ya da bir istisna atıyor.

Bir programlama dilinde bu garip tipe sahip olmanın amacı nedir? O kadar yaygın değil, ancak Scala ve Lisp gibi bazılarında mevcut.


2
@SargeBorsch: Bundan emin misin? Tabii ki biri C void
dilinde

3
@BasileStarynkevitch türünde değer yoktur voidve birim türünün bir değeri olması gerekir. Ayrıca, belirttiğiniz gibi, bir tür değeri bile ilan edemezsiniz void, bu bir tür bile olmadığı anlamına gelir, dilin yalnızca özel bir köşe olması anlamına gelir.
Sarge Borsch

2
Evet, C, özellikle işaretçi ve işlev işaretçi türlerinin nasıl yazıldığına tuhaf geliyor. Ancak voidJava'da neredeyse aynı: gerçekten bir tip değil ve değerleri olamaz.
Sarge Borsch

3
Alt tipi olan dillerin anlambiliminde, alt tipin hiçbir değeri olmadığı kabul edilmez, bunun yerine, hiçbir zaman tamamlanmayan bir hesaplamayı (normalde) temsil eden bir değere sahip olduğu, alt değere sahip olduğu kabul edilir. Alttaki değer her türün değeri olduğundan, alttaki tür her türün alt türü olabilir.
Theodore Norvell

4
@BasileStarynkevitch Common Lisp , hiçbir değeri olmayan nil türüne sahiptir. Ayrıca , yalnızca bir değeri olan boş bir türe , birim tipi olan nil(aka ()) sembolüne de sahiptir .
Joshua Taylor

Yanıtlar:


33

Basit bir örnek alacağım: C ++ vs Rust.

C ++ 11'de bir istisna atmak için kullanılan bir işlev:

[[noreturn]] void ThrowException(char const* message,
                                 char const* file,
                                 int line,
                                 char const* function);

Ve işte Rust in eşdeğeri:

fn formatted_panic(message: &str, file: &str, line: isize, function: &str) -> !;

Tamamen sözdizimsel bir meselede, Rust yapısı daha mantıklıdır. C ++ yapısının, geri dönmeyeceğini de belirtmesine rağmen, bir dönüş türü belirlediğini unutmayın. Bu biraz garip.

Standart bir notta, C ++ sözdizimi yalnızca C ++ 11 ile ortaya çıktı (en üste yerleştirildi), ancak çeşitli derleyiciler bir süredir çeşitli uzantılar sağlıyordu, böylece üçüncü taraf analiz araçlarının çeşitli yolları tanımak için programlanması gerekiyordu. bu özellik yazılabilir. Standartlaştırılmış olması açıkça açıkça üstündür.


Şimdi, yararına olduğu gibi?

Bir fonksiyonun geri dönmemesi aşağıdakiler için yararlı olabilir:

  • optimizasyon: Biri daha sonra herhangi bir kodu budayabilir (geri dönmeyecek), kayıtları kaydetmeye gerek yoktur (geri yüklemek gerekmeyecektir), ...
  • statik analiz: bir dizi potansiyel uygulama yolunu ortadan kaldırır
  • bakım kolaylığı: (bkz. statik analiz, ancak insanlar tarafından)

6
voidC ++ örneğinizde fonksiyonun tipini (bir kısmını) tanımlar - dönüş tipini değil. Fonksiyonun izin verdiği değeri sınırlar return; boşluğa dönüştürebilecek herhangi bir şey (ki bu hiçbir şey değildir). İşlev returns ise bir değer tarafından takip edilmemelidir. Fonksiyonun tam türü void () (char const*, char const*, int, char const *). :-) char constyerine kullanmak için + 1const char
Daha net 24.05

4
Bu, bir alt tipe sahip olmanın daha mantıklı olduğu anlamına gelmez, sadece dilin bir parçası olarak geri dönüp dönmeme konusundaki işlevleri açıklamak anlamlıdır. Aslında, işlevler farklı nedenlerden dolayı geri dönemediğinden, yan etkilerine bağlı olarak göreceli olarak yakın zamandaki not alma işlevleri kavramını kullanmak gibi, her şeyi yakalama terimini kullanmak yerine, nedeni bir şekilde kodlamak daha iyi görünmektedir.
GregRos

2
Aslında, "geri dönmemek" ve "X geri dönüş tipi" bağımsız olmak için bir neden vardır: çağıran kurallar geri dönüş türüne bağlı olabileceğinden, kendi kodunuz için geriye dönük uyumluluk.
Deduplicator

olduğu [[noreturn]] sözdizimi ya da işlevsellik bir ilave par?
Zaibis

1
[devamı] Sonuç olarak, sadece ⊥'nın avantajları üzerine bir tartışmanın what'nin bir uygulaması olarak neyi tanımladığını tanımlaması gerektiğini söyleyebilirim; ve ( a → ⊥) ≤ olmayan bir tip sistemin ≤ ( ab ) 'nin kullanışlı bir uygulama olduğunu sanmıyorum. Yani bu anlamda SysV x86-64 C ABI (diğerleri arasında) sadece allow uygulamasına izin vermiyor.
Alex Shpilkin

26

Karl'ın cevabı iyidir. İşte kimsenin bahsetmediğini sanmadığım ilave bir kullanım. Türü

if E then A else B

tipine tüm değerleri içeren bir tür olmalı Ave tipi tüm değerleri B. Eğer tür Bise Nothing, o zaman ififadenin tipi de olabilir A. Sık sık rutin ilan edeceğim

def unreachable( s:String ) : Nothing = throw new AssertionError("Unreachable "+s) 

bu koda ulaşılmasının beklenmeyeceğini söylemek için. Türü olduğundan Nothing, sonuç türünü etkilemeden unreachable(s)herhangi bir ifveya daha sık kullanılabilir switch. Örneğin

 val colour : Colour := switch state of
         BLACK_TO_MOVE: BLACK
         WHITE_TO_MOVE: WHITE
         default: unreachable("Bad state")

Scala böyle bir şey yok.

Nothing(Karl'ın cevabında da belirtildiği gibi) için bir başka kullanım örneği Liste [Hiçbir şey], her birinin üyeleri Nothing tipindeki listelerin tipidir. Böylece boş listenin türü olabilir.

Anahtar özelliği Nothingolduğunu bu kullanım durumları işlerimizi kolaylaştırır değil o onu her türde bir alt tipi olmasıdır values-- Scala, örneğin, hiç var --although hiçbir değer olduğunu.

Her türün aynı değeri içerdiği bir dilin olduğunu varsayalım - hadi diyelim (). Böyle bir dilde, ()tek değeri olan birim tipi, her tipin bir alt tipi olabilir. Bu OP'nin kastettiği anlamda bir alt tip yapmaz; OP, alt tipin değer içermediği konusunda açıktı. Ancak, her türün alt türü olan bir tür olduğundan, alt türle aynı rol oynayabilir.

Haskell işleri biraz farklı yapar. Haskell'de, hiçbir zaman değer üretmeyen bir ifade, tip düzenine sahip olabilir forall a.a. Bu tür bir şema örneği, başka herhangi bir türle birleşecektir, bu nedenle (standart) Haskell'in alt tipleme nosyonu olmasa da, etkili bir şekilde alt tip olarak davranır. Örneğin error, standart prelüdden gelen fonksiyon tip düzenine sahiptir forall a. [Char] -> a. Yani yazabilirsin

if E then A else error ""

ve ifadenin türü A, herhangi bir ifade için türüyle aynı olacaktır A.

Haskell'deki boş liste tip düzenine sahiptir forall a. [a]. Eğer Akimin tip bir liste türü olan bir ifade, daha sonra ise

if E then A else []

ile aynı tipte bir ifadedir A.


Haskell'deki forall a . [a]tip ile tip arasındaki fark nedir [a]? Yazım değişkenleri zaten Haskell tipi ifadelerde evrensel olarak ölçülmemiş midir?
Giorgio

@Giorgio Haskell'de, bir tip şemasına baktığınızdan emin olduğunuzda evrensel nicelik örtüktür. forallStandart Haskell 2010'da bile yazamazsınız . Miktarı açıkça yazdım çünkü bu bir Haskell forumu değil ve bazı insanlar Hask'ın sözleşmelerine aşina olmayabilir. Öyleyse bunun forall a . [a]standart olmadığı dışında hiçbir fark yoktur [a].
Theodore Norvell

19

Tipler birlikte bir semiring yaparak iki şekilde bir monoid oluşturur . Buna cebirsel veri tipleri denir . Sonlu tipler için, bu seming doğrudan doğal sayıların kesilmesiyle (sıfır dahil) ilgilidir, bu, türün kaç olası değerinin olduğunu (“kesin olmayan değerler” hariç) saymanız anlamına gelir.

  • Alt tür (onu arayacağım Vacuous) sıfır değerine sahiptir .
  • Birim tipi bir değere sahiptir. Hem türü hem de tek değerini çağıracağım ().
  • Kompozisyon (çoğu programlama dilinin doğrudan kamuya açık alanlara sahip kayıtlar / yapılar / sınıflar aracılığıyla doğrudan desteklediği) bir ürün işlemidir. Örneğin, (Bool, Bool)dört olası değerleri, yani var (False,False), (False,True), (True,False)ve (True,True).
    Birim tipi, kompozisyon işleminin kimlik elemanıdır. Örn ((), False)ve ((), True)türün tek değerleridir ((), Bool), bu nedenle bu tür kendi için izomorfiktir Bool.
  • Alternatif türler çoğu dilde bir miktar ihmal edilir (OO dilleri onları kalıtımla destekler), ancak daha az işe yaramazlar. İki tip arasındaki bir alternatif Ave Btemelde toplam Adeğerin B, dolayısıyla toplam değerin tüm değerlerine sahiptir . Örneğin, Either () Boolüç değeri vardır, ben onları arayacağım Left (), Right Falseve Right True.
    Alt tür toplamın özdeşliğidir: sadece formun değerlerine Either Vacuous Asahiptir , çünkü mantıklı değildir ( değeri yoktur).Right aLeft ...Vacuous

Ya bu Monoids ilginç olan sen tanıtmak zaman, yani fonksiyonları dilinize, kategori Morfizm olarak fonksiyonları ile bu tür bir olduğunu monoidal kategori . Diğer şeylerin yanı sıra, bu, genel olarak tamamen işlevsel terimlerle genel hesaplamalar için (muhtemelen yan etkiler içeren vb.) Mükemmel bir soyutlama olarak ortaya çıkan, uygulayıcı işlev ve monarileri tanımlamanıza izin verir .

Şimdi, aslında konunun sadece bir tarafını (kompozisyon monoid) endişelendikten sonra oldukça uzağa gidebilirsiniz, o zaman gerçekten alt tipe gerçekten ihtiyacınız yok. Mesela Haskell bile uzun süredir standart bir alt tipe sahip değildi. Şimdi, denir Void.

Ancak, tam resmi düşündüğünüzde, kapalı bir kategori olarak , o zaman tür sistemi aslında tüm lambda matematiğine eşdeğerdir, bu nedenle temelde Turing tamamlanmış bir dilde mümkün olan her şey üzerinde mükemmel bir soyutlamaya sahipsiniz. Gömülü alana özgü diller için harika, örneğin elektronik devreleri bu şekilde doğrudan kodlayan bir proje var .

Tabii ki, bunun tüm teorisyenlerin genel saçmalıkları olduğunu söyleyebilirsiniz . İyi bir programcı olmak için kategori teorisi hakkında hiçbir şey bilmenize gerek yok, ancak bunu yaptığınızda, size kod hakkında mantıklı olmanız ve değişmezleri ispat etmeniz için güçlü ve gülünç genel yollar sunuyor.


mb21, bunun düşük değerlerle karıştırılmaması gerektiğini hatırlattı . Haskell gibi tembel dillerde, her tür, bir "değer" ifadesini içeren bir alt değer içerir . Bu, açıkça açıkça geçebileceğiniz somut bir şey değildir; bunun yerine, örneğin bir işlev sonsuza dek döndüğünde “geri döndürülen” şeydir. Haskell'in bile Voidtürü, en alt değeri, yani adını “içerir”. Bu ışığında Haskell'in en alt tipi gerçekten bir değere sahip ve birim tipi iki değere sahip ancak kategori teorisi tartışmalarında bu genellikle göz ardı ediliyor.


Haskell'deki herhangi bir türün üyesi olan değerleVoid karıştırılmaması gereken " alt tür (onu arayacağım )" . bottom
mb21

18

Belki de sonsuza dek sürüyor, ya da bir istisna atıyor.

Bu gibi durumlarda faydalı bir tür gibi gözükse de, nadir de olsa.

Ayrıca, Nothing(Scala'nın alt tipin adı) hiçbir değere List[Nothing]sahip olmasa da, boş bir listenin türü olarak faydalı kılan bu kısıtlamaya sahip değildir. Çoğu dil, boş bir dizgi listesini boş bir tamsayı listesinden farklı bir tür yaparak, bunun anlamı bir anlam ifade eder, ancak boş bir listeyi, listeye dayalı bir dilde büyük bir dezavantaj olan daha ayrıntılı olan bir tamsayı listesinden yaparak geçer.


12
“Haskell'ın boş liste bir tür yapıcı olduğunu”: kesinlikle bu konuda ilgili şey burada olduğunu daha polimorfik, veya aşırı - yani, farklı türde boş listeleri ayrı değer vardır, ama []hepsi temsil eder ve hiç instanatiated edilecektir Gerektiğinde belirli tip.
Peter LeFanu Lumsdaine

İlginçtir: Eğer Haskell yorumlayıcı boş bir dizi oluşturmak için çalışırsanız, çok belirsiz tipiyle çok kesin bir değer elde: [a]. Benzer şekilde, :t Left 1verim Num a => Either a b. Gerçekte ifadeyi değerlendirmek, türünü zorlar a, ancak bşunları yapmaz :Either Integer b
John Dvorak

5
Boş liste bir değer yapıcıdır. Biraz kafa karıştırıcı, dahil olan tip kurucusu aynı isme sahip ama boş listenin kendisi bir tip değil (yani, tip seviyesi listeleri de var, ama bu tamamen başka bir konu). Herhangi bir liste türü için boş liste iş yapar kısmı zımni olduğunu forall, onun tipinde forall a. [a]. Düşünmek için güzel yollar var forall, ama gerçekten anlamak biraz zaman alıyor.
David,

@PeterLeFanuLumsdaine Bir tür kurucu olmanın tam olarak anlamı budur. Sadece farklı bir tür olduğu anlamına gelir *.
GregRos

2
Haskell'de []bir tür kurucu ve []boş bir listeyi temsil eden bir ifadedir. Ancak bu, "Haskell'in boş listesinin bir tür kurucu olduğu" anlamına gelmez. Bağlam, []bir tür olarak mı yoksa bir ifade olarak mı kullanıldığını açıkça belirtir. Diyelim ki beyan ederim data Foo x = Foo | Bar x (Foo x); Şimdi Foobir tür kurucu veya bir değer olarak kullanabilirsiniz, ancak her ikisi için de aynı ismi seçtiniz.
Theodore Norvell

3

Statik analizin, belirli bir kod yolunun erişilemez olduğunu belgelemesi yararlıdır. Örneğin, aşağıdakini C # ile yazarsanız:

int F(int arg) {
 if (arg != 0)
  return arg + 1; //some computation
 else
  Assert(false); //this throws but the compiler does not know that
}
void Assert(bool cond) { if (!cond) throw ...; }

Derleyici, Fen az bir kod yolunda hiçbir şey döndürmeyen şikayette bulunacaktır . İade Assertedilmeyen olarak işaretlenmiş olsaydı derleyiciyi uyarmaya gerek kalmazdı.


2

Bazı dillerde, nullalt tipi vardır, çünkü her türün alt tipi, hangi dillerin null kullandığını iyi tanımlar ( nullhem kendisinin hem de kendi başına dönen bir fonksiyona rağmen, neden botıssız olması gerektiğine dair ortak tartışmalardan kaçınılmasına rağmen ).

Ayrıca any -> botters giden gönderimi işlemek için işlev türlerinde ( ) tümünü yakalama olarak da kullanılabilir .

Bazı diller bot, özel derleyici hataları sağlamak için kullanılabilecek bir hata olarak çözmenize izin verir .


11
Hayır, alt tip birim tipi değildir. Bir alt tipi, hiç değeri yoktur, bu nedenle bir alt türü döndüren bir işlev dönüş (yani süresiz bir istisna ya da döngü atmak) olmamalıdır
Basile Starynkevitch

@BasileStarynkevitch - Birim türünden bahsetmiyorum. Birim türü void, ortak dillerde eşleşir (aynı kullanım için biraz farklı anlambilimiyle de olsa) null. Yine de haklı olsanız da, çoğu dil alt tür olarak boş değil.
Telastyn

3
@TheodoreNorvell - erken versiyonları Teğet yaptım - Bunu belki aldatıyor yüzden, yazar olduğunu duyuyorum ama. Başkaları için linklerim yok ve bu araştırmayı yaptığımdan bu yana bir süre geçti.
Telastyn

1
@Martijn Ancak null, örneğin nullBoolean sonuç almak için bir işaretçi karşılaştırmasını kullanabilirsiniz . Bence cevaplar iki farklı türde dip tipi olduğunu gösteriyor. (a) Her türün alt türü olan türün, sonuç sağlamayan hesaplamaları temsil ettiği diller (örneğin Scala). Temel olarak, teknik olarak çoğu zaman zayiatı temsil etmeyen işe yaramaz bir alt değerle doldurulmuş olmasına rağmen, boş bir türdür. (b) Alt türün diğer her türün alt kümesi olduğu Tangent gibi diller, çünkü diğer her türde de bulunan yararlı bir değer içerir - null.
Theodore Norvell

4
Bazı dillerin, bildiremeyeceğiniz bir tür değerine sahip olması (boş değer için ortaktır) ve diğerlerinin de ilan edebileceğiniz bir türünün olması ancak hiçbir değerinin olmaması (geleneksel bir alt tür) ve biraz benzer rolleri doldurması ilginçtir. .
Martijn

1

Evet bu oldukça kullanışlı bir tür; Rolü çoğunlukla tip sistemine iç olurken, alt tipin açıkça görüneceği bir durum vardır.

Koşulların ifadeler olduğu statik olarak yazılmış bir dil düşünün (bu nedenle eğer öyleyse inşaat C ve arkadaşlarının üçlü operatörü olarak ikiye katlanır ve benzer bir çok yönlü durum ifadesi olabilir). İşlevsel programlama dili buna sahiptir, ancak bazı zorunlu dillerde de geçerlidir (ALGOL 60'tan beri). O zaman tüm dal ifadeleri sonuçta tüm koşullu ifadenin türünü üretmelidir. Biri basitçe türlerinin eşit olmasını gerektirebilir (ve bunun, C'deki üçlü operatör için geçerli olduğunu düşünüyorum), ancak özellikle koşullu koşullu deyim olarak kullanılabildiğinde (yararlı herhangi bir değer döndürmüyorsa) bu aşırı kısıtlayıcıdır. Genel olarak, her dal ifadesinin (dolaylı olarak) dönüştürülebilir olmasını ister. tam ifadenin türü olacak ortak bir türe (muhtemelen bu ortak türün complier tarafından etkili bir şekilde bulunmasını sağlamak için daha az veya daha az karmaşık kısıtlamalarla), bkz. C ++, ancak bu ayrıntılara girmeyeceğim).

Genel bir dönüşüm türünün bu tür koşullu ifadelerin gerekli esnekliğini sağlayacağı iki tür durum vardır. Birinden daha önce bahsedilir, burada sonuç tipi birim tipidirvoid; bu doğal olarak diğer tüm türlerin süper bir türüdür ve herhangi bir türün (önemsiz şekilde) dönüştürülmesine izin vermek koşullu ifadeyi koşullu ifade olarak kullanmayı mümkün kılar. Diğeri ifadenin yararlı bir değer döndürdüğü durumları içerir, ancak bir veya daha fazla dal bir tane üretemez. Genellikle bir istisna oluşturacaklar veya bir sıçrama içereceklerdir ve onlardan (ayrıca) tüm ifadenin türünün (ulaşılmaz bir noktadan) bir değer üretmesini istemek anlamsız olacaktır. İstisna arttırıcı maddeler, atlamalar ve böyle bir etkiye sahip olacak çağrılar vererek, alt tipte (trivally) herhangi bir diğer tipe dönüştürülebilen bir tip vererek zarifçe ele alınabilecek bu tür bir durumdur.

*İsteğe bağlı bir yazıya dönüştürülebilirliği önerecek bir alt yazı yazmayı öneririm. Dahili olarak, örneğin, herhangi bir bildirimde bulunmayan bir özyinelemeli işlev için bir sonuç türü çıkarmaya çalışırken, türden bir inatçı, *tavuk ve yumurta durumundan kaçınmak için türü herhangi bir özyinelemeli çağrıya atayabilir ; gerçek tür özyinelemeli olmayan dallar tarafından belirlenir ve özyinelemeli olanlar özyinelemeli olmayanların ortak türüne dönüştürülür. Eğer özyinelemeli olmayan dallar yoksa , tür kalacaktır *ve fonksiyonun özyinelemeden geri dönüşü mümkün olmadığını doğru bir şekilde gösterecektir. Bunun dışında ve sonuçta istisna atma işlevlerinin türü olarak, biri kullanabilir*0 uzunluğundaki bileşenlerin bileşen türü olarak, örneğin boş listenin; Yine, eğer bir öğe, bir ifadenin türünden [*](mutlaka boş liste) seçildiyse , sonuçta ortaya çıkan tür, bunun *bir hata olmadan asla geri dönemeyeceğini doğru şekilde gösterecektir.


Yani fikir var foo = someCondition() ? functionReturningBar() : functionThatAlwaysThrows()türünü ortaya çıkarabileceği olabilir fooolarak Barifade başka bir şey verim asla beri,?
Supercat

1
Birim türünü yeni tanımladınız - en azından cevabınızın ilk bölümünde. Birim türü döndüren bir işlev dönen olarak bildirilmiş aynıdır voidC. hiçbir Parçaların ile döner asla bir işlev için bir türüne veya bir listeden söz Cevabınız, ikinci bölümünü ise gerçekten alt tip! (Genellikle olarak yazıldığı _|_ziyade *emin değil neden) bir (insan gibi alt :) görünüyor Belki de..
andrewf

2
Şüpheden kaçınmak için: 'işe yarar bir şey getirmez' 'geri dönmemekten' farklıdır; ilk Birim tipi ile temsil edilir; alt türüne göre ikinci.
andrewf

@ andrewf: Evet, farkı anlıyorum. Cevabım biraz uzunca bir süredir, fakat yapmak istediğim nokta, birim tipinin ve alt tipin, bazı ifadelerin daha esnek (ama yine de güvenli bir şekilde) kullanılmasına izin vermede (farklı ama) karşılaştırılabilir rol oynaması.
Marc van Leeuwen

@supercat: Evet bu fikir. Eğer geçerli olacak olsa Halen C olduğu, yasadışı ++ functionThatAlwaysThrows()açık değiştirildi thrownedeniyle Standard özel diline,. Bunu yapan bir tür olması bir gelişmedir.
Marc van Leeuwen

0

Bazı dillerde, hem derleyiciye hem de geliştiricilere bu işleve yapılan bir çağrının geri dönmeyeceğini söyleyen bir işlev ekleyebilirsiniz (ve işlev dönebilecek şekilde yazılırsa derleyici buna izin vermez) ). Bu bilmek yararlı bir şey, ama sonunda buna benzer bir fonksiyon diyebilirsin. Derleyici, ölü kod hakkında uyarılar vermek, vb. İçin bilgileri optimizasyon için kullanabilir. Bu yüzden bu tipe sahip olmak için çok zorlayıcı bir sebep yoktur, ama onu önlemek için çok zorlayıcı bir sebep yoktur.

Birçok dilde, bir işlev "void" değerini döndürebilir. Bunun tam olarak anlamı, dile bağlı. C'de fonksiyonun hiçbir şey döndürmediği anlamına gelir. Swift'de, işlevin yalnızca bir olası değeri olan bir nesneyi döndürdüğü anlamına gelir ve bu değerin yalnızca bir değeri olması nedeniyle sıfır bit alır ve gerçekte herhangi bir kod gerektirmez. Her iki durumda da, "alt" ile aynı değildir.

"alt", olası hiçbir değeri olmayan bir tür olur. Asla var olamaz. Eğer bir fonksiyon "alt" döndürürse, aslında döndüremez, çünkü "alt" türünün döndürebileceği bir değer yoktur.

Eğer bir dil tasarımcısı böyle hissediyorsa, o zaman böyle olmaması için hiçbir sebep yoktur. Uygulama zor değil (onu tam olarak boşa döndüren ve "geri dönmüyor" olarak işaretlenmiş bir işlev gibi uygulayabilirsiniz). İşaretçileri, altta dönen işlevlere, işaretçileri boş bırakan işlevlere karıştıramazsınız, çünkü aynı tür değildirler).

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.