W artykule Erica Lipperta Co słychać w notacji węgierskiej? , twierdzi, że celem notacji węgierskiej (dobrego rodzaju) jest:
rozwinąć pojęcie „typu”, tak aby obejmowało informacje semantyczne oprócz informacji o reprezentacji pamięci.
Prostym przykładem może być przedrostek zmiennej reprezentującej współrzędną X z „x” i zmiennej reprezentującej współrzędną Y z „y”, niezależnie od tego, czy zmienne te są liczbami całkowitymi, zmiennoprzecinkowymi lub czymkolwiek innym, tak aby podczas przypadkowego zapisu xFoo + yBar
, kod wyraźnie wygląda źle.
Ale czytałem również o systemie typów Haskell i wydaje się, że w Haskell można osiągnąć to samo (tj. „Rozszerzyć pojęcie typu, aby objąć informacje semantyczne”), używając rzeczywistych typów, które kompilator sprawdzi dla ciebie. Tak więc w powyższym przykładzie xFoo + yBar
w Haskell nie udało się skompilować, jeśli poprawnie zaprojektowałeś swój program, ponieważ zostałyby zadeklarowane jako typy niezgodne. Innymi słowy, wydaje się, że system typów Haskell skutecznie obsługuje sprawdzanie czasu kompilacji równoważne notacji węgierskiej
Czy zatem notacja węgierska jest jedynie pomocą dla języków programowania, których systemy typów nie mogą kodować informacji semantycznych? Czy też notacja węgierska oferuje coś więcej niż system statyczny, taki jak Haskell?
(Oczywiście używam Haskell jako przykładu. Jestem pewien, że istnieją inne języki z podobnie ekspresyjnymi (bogatymi? Silnymi?) Systemami typu, chociaż nie spotkałem żadnego.)
Żeby było jasne, nie mówię o adnotowaniu nazw zmiennych typem danych , ale raczej o informacji o znaczeniu zmiennej w kontekście programu. Na przykład zmienna może być liczbą całkowitą, liczbą zmiennoprzecinkową, podwójną lub długą, lub czymkolwiek, ale może znaczenie zmiennej jest takie, że jest to względna współrzędna x mierzona w calach. Tego rodzaju informacje mówię o kodowaniu za pomocą notacji węgierskiej (i typów Haskell).
źródło
Odpowiedzi:
Powiedziałbym tak".
Jak mówisz, celem notacji węgierskiej jest zakodowanie w nazwie informacji, których nie można zakodować w typie. Istnieją jednak zasadniczo dwa przypadki:
Zacznijmy od przypadku 2: jeśli ta informacja nie jest ważna, wówczas notacja węgierska jest po prostu zbędnym hałasem.
Bardziej interesującym przypadkiem jest liczba 1, ale argumentowałbym, że jeśli informacja jest ważna, należy ją sprawdzić, tzn. Powinna ona być częścią typu , a nie nazwą .
Co sprowadza nas z powrotem do cytatu Erica Lipperta:
W rzeczywistości nie jest to „rozszerzenie pojęcia typu”, to jest pojęcie typu! Głównym celem typów (jako narzędzia do projektowania) jest kodowanie informacji semantycznych! Reprezentacja przechowywania jest szczegółów wdrażania, które zwykle nie należą do typu w ogóle . (A konkretnie w języku OO nie może należeć do tego typu, ponieważ niezależność reprezentacji jest jednym z głównych warunków OO.)
źródło
S1
jest jedynym odniesieniem w dowolnym miejscu we wszechświecie dochar[]
, którego posiadacz może i zmieni go w dowolnym momencie, ale nigdy nie może narażać się na kod zewnętrzny, iS2
jest odniesieniem do takiego,char[]
którego nikt nigdy nie powinien zmieniać, ale który może być udostępniany z przedmiotami, które obiecują go nie zmieniać, czy należyS1
i należyS2
je traktować semantycznie jako ten sam „rodzaj”?Głównym celem typów (jako narzędzia do projektowania) jest kodowanie informacji semantycznych!
Podobała mi się ta odpowiedź i chciałem kontynuować tę odpowiedź ...
Nic nie wiem o Haskell, ale możesz osiągnąć coś takiego jak przykład
xFoo + yBar
w dowolnym języku, który obsługuje pewne formy bezpieczeństwa typu, takie jak C, C ++ lub Java. W C ++ można zdefiniować klasy XDir i YDir za pomocą przeciążonych operatorów „+”, które przyjmują tylko obiekty własnego typu. W C lub Javie trzeba będzie dodawać za pomocą funkcji / metody add () zamiast operatora „+”.Zawsze widziałem notację węgierską używaną do informacji o typie, a nie semantykę (z wyjątkiem przypadków, gdy semantyka może być reprezentowana przez typ). Wygodny sposób na zapamiętanie typu zmiennej w czasach sprzed „inteligentnych” edytorów programistycznych, które wyświetlają ten typ dla ciebie w taki czy inny sposób bezpośrednio w edytorze.
źródło
xFoo + yBar
na typy zdefiniowane przez użytkownika, a także aspekt OO C ++ niezbędny do działania tego przykładu.xFoo + yBar
błąd kompilacji (lub przynajmniej błąd czasu wykonywania) w prawie dowolnym języku. Czy jednak matematyka z klasami XDir i YDir w, powiedzmy, Javie lub C ++ byłaby wolniejsza niż matematyka z liczbami surowymi? Rozumiem, że w Haskell typy są sprawdzane w czasie kompilacji, a następnie w środowisku wykonawczym byłoby to po prostu surowa matematyka bez sprawdzania typów, a zatem nie wolniejsze niż dodawanie regularnych liczb.XCoordinate
na przykład traktować zwykłego int.Zdaję sobie sprawę, że wyrażenie „notacja węgierska” oznaczało coś innego niż oryginał , ale odpowiem „nie” na pytanie. Nazewnictwo zmiennych typu semantycznego lub obliczeniowego nie robi tego samego, co pisanie w stylu SML lub Haskell. To nawet nie jest bandaid. Biorąc jako przykład C, możesz nazwać zmienną gpszTitle, ale ta zmienna może nie mieć zasięgu globalnego, może nawet nie stanowić punktu do łańcucha zakończonego znakiem null.
Myślę, że bardziej współczesne notacje węgierskie mają jeszcze większą rozbieżność z silnym systemem dedukcyjnym, ponieważ łączą informacje „semantyczne” (takie jak „g” dla flagi globalnej lub „f” dla flagi) z typem obliczeniowym (wskaźnik „p”, „ i „liczba całkowita itp.). To kończy się jako bezbożny bałagan, w którym nazwy zmiennych mają jedynie niejasne podobieństwo do typu obliczeniowego (który zmienia się w czasie) i wszystkie wyglądają tak podobnie, że nie można użyć„ następnego dopasowania ”do znajdź zmienną w określonej funkcji - wszystkie są takie same.
źródło
Notacja węgierska została wymyślona dla BCPL, języka, który w ogóle nie miał typów. A raczej miał dokładnie jeden typ danych, słowo. Słowo może być wskaźnikiem lub może być znakiem, wartością logiczną lub zwykłą liczbą całkowitą, w zależności od tego, jak go użyłeś. Oczywiście bardzo ułatwiło to popełnienie okropnych błędów, takich jak dereferencja postaci. Tak więc wymyślono notację węgierską, aby programista mógł przynajmniej ręcznie sprawdzić typ, sprawdzając kod.
C, potomek BCPL, ma różne typy liczb całkowitych, wskaźników, znaków itp. To spowodowało, że podstawowa notacja węgierska stała się w pewnym stopniu zbędna (nie trzeba było kodować nazwy zmiennej, jeśli była to liczba całkowita lub wskaźnik), ale semantyka powyżej tego poziomu wciąż nie może być wyrażona jako typy. Doprowadziło to do rozróżnienia na tak zwane „systemy” i „aplikacje” węgierski. Nie trzeba było wyrażać, że zmienna jest liczbą całkowitą, ale można użyć liter kodowych, aby wskazać, czy wartość wewnętrzna była współrzędną x lub y lub indeksem.
Bardziej nowoczesne języki pozwalają na definiowanie typów niestandardowych, co oznacza, że możesz zakodować ograniczenia semantyczne w typach, a nie w nazwach zmiennych. Na przykład typowy język OO będzie miał określone typy dla par współrzędnych i obszarów, więc unikasz dodawania współrzędnej x do współrzędnej y.
Na przykład w słynnym artykule Joelsa, chwalącym Apps Hungarian, używa przykładu przedrostka
us
dla niebezpiecznego ciągu is
dla bezpiecznego (zakodowanego w HTML) ciągu, aby zapobiec wstrzykiwaniu HTML. Deweloper może zapobiec błędom wstrzykiwania HTML, po prostu dokładnie sprawdzając kod i upewniając się, że prefiksy zmiennych pasują do siebie. Jego przykład jest w VBScript, obecnie przestarzałym języku, który początkowo nie pozwalał na niestandardowe klasy. W nowoczesnym języku problem można rozwiązać za pomocą niestandardowego typu i tak właśnie robi Asp.net zHtmlString
klasą. W ten sposób kompilator automatycznie znajdzie błąd, który jest znacznie bezpieczniejszy niż poleganie na gałkach ocznych człowieka. Oczywiście język z niestandardowymi typami eliminuje w tym przypadku potrzebę używania „węgierskich aplikacji”.źródło
Tak, choć wiele języków, które w przeciwnym razie miałyby wystarczająco mocne systemy typów, nadal ma problem - możliwość wyrażenia nowych typów opartych na / podobnych do istniejących typów.
tzn. w wielu językach, w których moglibyśmy częściej korzystać z systemu typów, tego nie robimy, ponieważ narzut związany z tworzeniem nowego typu, który jest zasadniczo taki sam jak istniejący typ inny niż nazwa i kilka funkcji konwersji jest zbyt duży.
Zasadniczo potrzebujemy jakiegoś silnie wpisanego typedefa, aby zabić całkowicie węgierską notację w tych językach (UoM w stylu F # może to również zrobić)
źródło
Pamiętaj, że był czas, kiedy IDE nie miały wyskakujących podpowiedzi informujących o typie zmiennej. Był czas, gdy IDE nie rozumiały edytowanego przez siebie kodu, więc nie można było łatwo przejść od użycia do deklaracji. Był też czas, kiedy nie można było zmienić nazwy zmiennej bez ręcznego przeglądania całej bazy kodu, dokonywania zmian ręcznie i mając nadzieję, że żadnej nie przegapisz. Nie można użyć wyszukiwania i zamiany, ponieważ wyszukiwanie klienta również daje Ci nazwę klienta ...
W tamtych mrocznych dniach dobrze było wiedzieć, jakiego typu zmienna była tam, gdzie była używana. Jeśli odpowiednio utrzymany (DUŻY, jeśli z powodu braku narzędzi do refaktoryzacji) notacja węgierska dała ci to.
Koszt okropnych nazw, które produkuje w tych dniach, jest zbyt wysoki, ale to stosunkowo nowa sprawa. Nadal istnieje wiele kodów, które poprzedzają opisane przeze mnie zmiany IDE.
źródło
Poprawny!
Poza całkowicie nietypowymi językami, takimi jak asembler, notacja węgierska jest zbędna i irytująca. Podwójnie, jeśli weźmiesz pod uwagę, że większość IDE sprawdza bezpieczeństwo wpisywania podczas pisania.
Dodatkowe „i” „d” i „?” Przedrostki po prostu sprawiają, że kod jest mniej czytelny i może być naprawdę mylący - jak wtedy, gdy „krowa-orker” zmienia typ iaSumsItems z Integer na Long, ale nie przeszkadza w przefakturowaniu nazwy pola.
źródło