Czy węgierska notacja stanowi obejście dla języków z niewystarczająco ekspresyjnym pisaniem statycznym? [Zamknięte]


28

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 + yBarw 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).


Pascal - chociaż jeśli spróbujesz dodać XCood i YCoord zdefiniowane w Pascalu, dostaniesz tylko ostrzeżenie kompilatora IIRC
mcottle,

1
blog.moertel.com/articles/2006/10/10/18/... to artykuł o robieniu czegoś bardzo podobnego do „węgierskich aplikacji” w systemie pisma w Haskell.
Logan Capaldo,

1
F # ma również tę funkcję stylu.
Rangoric

To naprawdę fajny link do artykułu (ten moertel.com) pokazujący dokładnie to, o czym myślałem: wykorzystanie systemu typów do przekształcenia luk w zabezpieczeniach interpolacji łańcuchów i takie błędy w błędy kompilacji. Dzięki za link.
Ryan C. Thompson,

Myślę, że OO nadrabia zaległości w węgierskiej notacji semantyki, ponieważ dziś prawdopodobnie napisalibyście: Foo.Position.X + Bar.Position.Y.
Pieter B

Odpowiedzi:


27

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:

  1. Ta informacja jest ważna.
  2. Ta informacja nie jest ważna.

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:

rozwinąć pojęcie „typu”, tak aby obejmowało informacje semantyczne oprócz informacji o reprezentacji pamięci.

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.)


C, gdzie notacja węgierska była najczęściej używana AFAIK, nie jest jednak językiem OO.
Péter Török,

4
@ PéterTörök: OO jest wzorcem projektowym, a nie cechą języka, chociaż współczesne języki mają na celu ułatwienie, podczas gdy C nie.
Jan Hudec

3
@ PéterTörök: Napisałem całkiem sporo kodu obiektowego w zwykłym C. Wiem o czym mówię.
Jan Hudec

1
Chociaż może być prawdą, że ważne informacje powinny być osadzone w typie zmiennej, a nie w jej nazwie, istnieje wiele ważnych rzeczy, które należy powiedzieć, ale których systemów typów nie można wyrazić. Na przykład, jeśli S1jest jedynym odniesieniem w dowolnym miejscu we wszechświecie do char[], którego posiadacz może i zmieni go w dowolnym momencie, ale nigdy nie może narażać się na kod zewnętrzny, i S2jest 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ży S1i należy S2je traktować semantycznie jako ten sam „rodzaj”?
supercat

1
@ superupcat - Opisujesz typy unikatowości.
Jack

9

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 + yBarw 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.


Bycie zorientowanym obiektowo nie jest ani konieczne, ani wystarczające, aby język pozwalał xFoo + yBarna typy zdefiniowane przez użytkownika, a także aspekt OO C ++ niezbędny do działania tego przykładu.
Luc Danton

Masz rację, to nie OO, to bezpieczeństwo typu. Zredagowałem swoją odpowiedź.
BHS

Hmm Dobrze, że możesz popełnić xFoo + yBarbłą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.
Ryan C. Thompson,

W C ++ sprawdzanie typu będzie również wykonywane w czasie kompilacji, a konwersja i takie zostaną zoptymalizowane w większości przypadków. Java również tego nie robi, ponieważ nie pozwala na przeciążanie operatora i tym podobne - więc nie można XCoordinatena przykład traktować zwykłego int.
cHao

5

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.


4

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 usdla niebezpiecznego ciągu i sdla 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 z HtmlStringklasą. 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”.


2

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ć)


2

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.


1
Jeśli się nie mylę, jest to kolejna odpowiedź, która dotyczy innego rodzaju notacji węgierskiej niż ta, o którą prosi OP.
MatrixFrog,

2
Ta odpowiedź opisuje tak zwaną „Systems węgierską”, gdzie przedrostek oznacza „typ” języka. Pytanie dotyczy „Apps Hungarian”, w których słowo „typ” nie zostało źle zrozumiane i oznacza typ semantyczny . System węgierski jest obecnie prawie powszechnie potępiany (i słusznie; jest to przekłamanie prawdziwego celu węgierskiej notacji). Aplikacje węgierskie mogą jednak być dobrą rzeczą.
cHao

Edytory zdolne do wyszukiwania sCustomer bez wybierania sCustomerName (vi i emacs to 2 przykłady) istniały od lat 70-tych.
Larry Coleman

@ Larry, być może, ale nie udało ci się uruchomić ich na systemach, które programowałem w latach 80
Mcottle

@ cHAo, nie, nie ma - chciałem wyjaśnić, dlaczego ludzie umieszczają dodatkowe informacje w nazwach zmiennych ogólnie. Starannie unikałem wymieniania jakiejkolwiek wersji węgierskiej notacji. Być może przykład, który podałem w sekcji „Dlaczego wyszukiwanie i zamiana nie działa na kodzie źródłowym” wygląda jak „System węgierski”, ale tak nie było. Usunąłem początkowe „s”, aby uniknąć zamieszania.
Mcottle,

0

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.


9
Twoja odpowiedź sugeruje, że nie rozumiesz różnicy między oryginalnym, inteligentnym węgierskim „Apps” a głupim sukinsynem zwanym węgierskim „Systems”. Przeczytaj joelonsoftware.com/articles/Wrong.html
Ryan Culpepper,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.