Powszechnie przyjmuje się, że niektóre rodzaje Java zawiodły w ważnych sprawach. Połączenie symboli wieloznacznych i granic spowodowało powstanie poważnie nieczytelnego kodu.
Jednak gdy patrzę na inne języki, naprawdę nie mogę znaleźć ogólnego systemu typów, z którego programiści są zadowoleni.
Jeśli weźmiemy pod uwagę następujące cele projektowania takiego systemu typów:
- Zawsze tworzy czytelne deklaracje typu
- Łatwy do nauczenia (nie trzeba odkurzać kowariancji, kontrawariancji itp.)
- maksymalizuje liczbę błędów czasu kompilacji
Czy jest jakiś język, który dobrze to zrozumiał? Jeśli google, jedyne, co widzę, to skargi na to, jak system typów zasysa język X. Czy tego rodzaju złożoność jest nieodłącznym elementem typowego pisania? Czy powinniśmy po prostu zrezygnować z próby sprawdzenia bezpieczeństwa typu 100% w czasie kompilacji?
Moje główne pytanie dotyczy tego, który język najlepiej „poprawił” te trzy cele. Zdaję sobie sprawę, że to subiektywne, ale jak dotąd nie mogę nawet znaleźć jednego języka, w którym nie wszyscy programiści zgadzają się, że ogólny system typów jest bałaganem.
Dodatek: jak wspomniano, kombinacja podtypu / dziedziczenia i ogólnych jest tym, co tworzy złożoność, więc naprawdę szukam języka, który łączy oba te elementy i pozwala uniknąć eksplozji złożoności.
źródło
easy-to-read type declarations
? Trzecie kryterium jest również niejednoznaczne: na przykład mogę przekształcić indeks tablicy poza wyjątkami granic w błędy czasu kompilacji, nie pozwalając na indeksowanie tablic, chyba że będę mógł obliczyć indeks w czasie kompilacji. Również drugie kryterium wyklucza podtypowanie. To niekoniecznie zła rzecz, ale powinieneś zdawać sobie sprawę z tego, o co pytasz.Foo<T> where SiameseCat:T
) i że nie ma możliwości posiadania typu ogólnego, na który nie można zamienićObject
. IMHO, .NET skorzystałby na typach agregatów, które były podobne do struktur, ale jeszcze bardziej pozbawione kości. GdybyKeyValuePair<TKey,TValue>
taki był, toIEnumerable<KeyValuePair<SiameseCat,FordFocus>>
można by rzucić naIEnumerable<KeyValuePair<Animal,Vehicle>>
, ale tylko wtedy, gdy tego typu nie można było spakować.Odpowiedzi:
Podczas gdy Generics jest głównym nurtem społeczności programistów funkcjonalnych od dziesięcioleci, dodawanie generics do obiektowych języków programowania oferuje pewne unikalne wyzwania, w szczególności interakcję podtypów i generics.
Jednak nawet jeśli skupimy się na obiektowych językach programowania, w szczególności na Javie, można zaprojektować znacznie lepszy system generyczny:
Typy ogólne powinny być dopuszczalne wszędzie tam, gdzie są inne typy. W szczególności, jeśli
T
jest parametrem typu, następujące wyrażenia powinny zostać skompilowane bez ostrzeżeń:Tak, wymaga to weryfikacji ogólnych, tak jak każdego innego typu w języku.
Kowariancja i kontrawariancja typu ogólnego powinny być określone w jej deklaracji (lub wywnioskowane z), a nie za każdym razem, gdy używany jest typ ogólny, abyśmy mogli napisać
zamiast
Ponieważ typy ogólne mogą być dość długie, nie powinniśmy musieć ich określać nadmiarowo. To znaczy, powinniśmy móc pisać
zamiast
Każdy typ powinien być dopuszczalny jako parametr typu, a nie tylko typy referencyjne. (Jeśli możemy mieć
int[]
, dlaczego nie możemy miećList<int>
)?Wszystko to jest możliwe w C #.
źródło
Korzystanie z podtypów powoduje wiele komplikacji podczas programowania ogólnego. Jeśli nalegasz na używanie języka z podtypami, musisz zaakceptować, że wraz z nim towarzyszy pewna złożoność programowania ogólnego. Niektóre języki robią to lepiej niż inne, ale możesz to zrobić tylko do tej pory.
Porównaj to na przykład z lekami generycznymi Haskella. Są one na tyle proste, że jeśli używasz typu wnioskowania, można napisać poprawną funkcję rodzajowe przez przypadek . W rzeczywistości, jeśli podasz jeden typ, kompilator często mówi do siebie: „No, I był zamiar zrobić to uniwersalne, ale poprosił mnie, aby go tylko za wskazówki, więc cokolwiek.”
Trzeba przyznać, że ludzie używają systemu czcionek Haskell w zaskakująco skomplikowany sposób, co sprawia, że jest zmorą każdego początkującego, ale sam system typów jest elegancki i bardzo podziwiany.
źródło
a
musi być jakąś liczbą całkowitą”.Około 20 lat temu przeprowadzono sporo badań nad połączeniem leków generycznych z subtyfikacją. Język programowania Thor opracowany przez grupę badawczą Barbary Liskov z MIT miał pojęcie klauzul „gdzie”, które pozwalają określić wymagania dotyczące rodzaju, który parametryzujesz. (Jest to podobne do tego, co C ++ próbuje zrobić z Concepts .)
Artykuł opisujący leki generyczne Thora i ich interakcje z podtypami Thora to: Dzień, M; Gruber, R; Liskov, B; Myers, AC: Podtypy vs. klauzule where: ograniczanie polimorfizmu parametrycznego , ACM Conf na Obj-Oriented Prog, Sys, Lang i Apps , (OOPSLA-10): 156-158, 1995.
Wierzę, że oni z kolei oparli się na pracach wykonanych na Emerald pod koniec lat osiemdziesiątych. (Nie czytałem tej pracy, ale referencja to: Black, A; Hutchinson, N; Jul, E; Levy, H; Carter, L: Distribution and Abstract Types in Emerald , _IEEE T. Software Eng., 13 ( 1): 65–76, 1987.
Zarówno Thor, jak i Emerald byli „językami akademickimi”, więc prawdopodobnie nie mieli wystarczającego wykorzystania, aby ludzie naprawdę mogli zrozumieć, czy gdzie klauzule (pojęcia) naprawdę rozwiązują jakiekolwiek rzeczywiste problemy. Interesujące jest przeczytanie artykułu Bjarne Stroustrup o tym, dlaczego pierwsza próba Koncepcji w C ++ nie powiodła się: Stroustrup, B: Decyzja C ++ 0x „Usuń koncepcje” , Dr Dobbs , 22 lipca 2009 r. (Więcej informacji na stronie głównej Stroustrup . )
Kolejnym kierunkiem, który ludzie wydają się próbować, jest coś, co nazywa się cechami . Na przykład język programowania Rust w Mozilli wykorzystuje cechy. Jak rozumiem (co może być całkowicie błędne), deklarowanie, że klasa spełnia pewną cechę, jest bardzo podobne do powiedzenia, że klasa implementuje interfejs, ale mówisz „zachowuje się jak„ raczej niż „jest”. Wydaje się, że nowe języki programowania Swift firmy Apple wykorzystują podobną koncepcję protokołów w celu określenia ograniczeń parametrów w stosunku do ogólnych .
źródło