Dziesiąta zasada Greenspun, czy każdy duży projekt zawiera tłumacza Lisp? [Zamknięte]


12

Dziesiąta zasada Greenspun (właściwie jedyna reguła) mówi, że:

Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.

Pamiętam, że jest kilka artykułów na ten temat, być może dla projektu Quattro (arkusza kalkulacyjnego) Borlanda i być może innych. Google nie jest pomocny, być może nie przychodzą mi do głowy odpowiednie wyszukiwane hasła. Szukam ewentualnych artykułów lub artykułów na poparcie tego roszczenia.


8
Czy przeczytałeś wyjaśnienie znaczenia reguły w artykule na Wikipedii? Wątpię, by podjęto poważny wysiłek w celu potwierdzenia lub obalenia roszczenia, tak naprawdę nie należy go traktować poważnie .
yannis

3
Zabawne jest to, że chociaż reguła Greenspun była tylko żartem, faktycznie pracowałem nad oprogramowaniem do symulacji, które miało wbudowany interpreter LISP. Konfiguracja oprogramowania została przeprowadzona za pomocą S-Expressions i można było napisać kod LISP do robienia różnych rzeczy w konfiguracji.
wkl

@YannisRizos - Dosłownie żaden z twoich linków nie twierdzi, że Reguła jest żartem. Prawo Morrisa jest jednak jako takie sformułowane. Teraz w przenośni ....
casualcoder


Czy nie było podobnego cytatu dotyczącego Erlanga i współbieżnych programów?
Giorgio

Odpowiedzi:


15

Stwierdzenie to hiperbola. Ale są oczywiste oznaki zazdrości Lisp w innych językach. Spójrz na C # i jak staje się on bardziej funkcjonalny z natury. Spójrz na różne platformy zarządzania procesami biznesowymi, workflow i EAI, które robią wszystko, aby umożliwić programowanie systemu bez zmiany programu.

Jest książka na temat języków specyficznych dla domeny autorstwa Martina Fowlera, która mówi o tym, jak robić metaprogramowanie w językach zorientowanych obiektowo. Hiperbola zawiera pewną prawdę.

Paul Graham nazwał Lisp najpotężniejszym językiem, patrząc na listę nowości, które pojawiły się w Lisp , łatwo zrozumieć, dlaczego wiele języków jest bladych w porównaniu.

Sposób na dziesiątą zasadę to programowanie w poliglocie. Uświadomienie sobie, że jeden język / środowisko nie jest złotym młotem. Następnie zamiast tworzyć słabą implementację Lisp ad hoc, możesz po prostu użyć Lisp.


4
Moc i wiek są niezależne. To naprawdę nie ma znaczenia, jak dobry lub zły był LISP w momencie jego tworzenia, ma znaczenie, jak się ma w porównaniu z dzisiejszymi językami. Pierwsze są zupełnie nieważne.
DeadMG

2
@DeadMG, te „nowości” są niczym w porównaniu z rzeczami, które nie zostały jeszcze przeniesione z Lisp na inne języki.
SK-logic

1
@DeadMG, masz rację. Jedną z rzeczy, które ludzie uwielbiają w Ruby po tym, jak zaczynają się w niego zagłębiać, jest aspekt Metaprogramowania. Lisp ma to wbudowane. Programiści C # uwielbiają LINQ (nie bez powodu) i konsekwencje, jakie deklaratywne programowanie ma dla współbieżności. Lisp ma to w pikach. W miarę, jak systemy stają się coraz bardziej złożone, bardziej skupiają się na węzłach reagujących na wiadomości, a mniej na obiektach. Tam zaczyna się Lisp, większość innych języków musi się nim zająć ad hoc (stąd reguła) lub za pomocą frameworka (np. Biztalk, Tibco itp.).
Michael Brown

2
„zamiast tworzyć słabą implementację Lisp ad hoc, możesz po prostu użyć Lisp”, ale następstwo Morrisa oznacza, że ​​nadal używasz słabej implementacji ad hoc;)
jk.

1
Idealny skrót do tego wpisu: „cała kultura hakerów jest często postrzegana przez samych hakerów jako poważna ha-ha-poważnie; wzięcie jej zbyt lekko lub zbyt poważnie oznacza osobę jako osobę z zewnątrz, wampira lub w stadium larwalnym . „
Michael Brown

10

„Dziesiąta reguła” Greenspuna była trochę nieuczciwym warknięciem. Jeśli rozciągnie się wystarczająco daleko, jeśli sprawisz, że obejmie on „dowolny system skryptowy lub konfiguracyjny”, wtedy odpowiedź na to pytanie będzie musiała brzmieć „tak”, ponieważ konfiguracja jest czymś, co w pewnym stopniu wymaga każdy nietrywialny program i skryptowanie jest tylko nieco mniej powszechny, gdy przesuwasz się w górę skali złożoności.

Z drugiej strony, spójrz na GOAL , wariant Lisp wymyślony przez Naughty Dog do programowania gier. W ogóle nie przypomina bardzo „klasycznego” Lispa. Jest to bardzo imperatywny system z funkcjami zorientowanymi obiektowo, bez interpretera, minimalną obsługą zbierania elementów bezużytecznych (zamiast tego polegającą na ułatwieniach czyszczenia na poziomie środowiska wykonawczego) oraz szeroką obsługą wbudowanego montażu.

Innymi słowy, kiedy próbowali wykorzystać Lisp do wystarczająco złożonego projektu, odkryli, że aby zrobić coś pożytecznego, musieli zmienić język w ad-hoc, nieformalnie określoną implementację połowy C ++! ;) (I ostatecznie musieli przestać go używać po tym, jak odszedł facet, który zaprojektował GOAL, ponieważ nikt nie rozumiał jego kodu.)


Wydaje mi się, że moje pytanie dotyczy konkretnych części dużego systemu. Ostatecznie system będzie miał części, które są lepiej zakodowane w innym języku ze względu na procesy myślowe lub techniki związane z używaniem tego języka, a nie nieodłączną szybkość lub wyższość. Historia pana Lenaghana jest jednym z przykładów.
casualcoder

Właściwie przestali używać GOAL, ponieważ zostali kupieni przez firmę, której baza kodów była w C ++. Również GOAL był dość seplenieniem. Nie zakładaj, że samouczki online i wykłady uniwersyteckie o najniższym mianowniku są poprawne :)
p_l

9

Co ciekawe, jedna odpowiedź na to pytanie jest już w Programmers SE .

Aby zacytować odpowiednią część:

Punkt Greenspun był (częściowo) taki, że wiele złożonych programów ma wbudowanych tłumaczy. Sugerował, że zamiast budowania interpretera na język, lepiej byłoby użyć takiego języka jak Lisp, który ma już wbudowany interpreter (lub kompilator).

W tym czasie pracowałem nad dość dużą aplikacją, która wykonywała obliczenia zdefiniowane przez użytkownika przy użyciu niestandardowego interpretera dla niestandardowego języka. Postanowiłem spróbować przepisać jego rdzeń w Lisp jako eksperyment na dużą skalę.

Zajęło to około sześciu tygodni. Oryginalny kod zawierał ~ 100 000 linii Delphi (wariant Pascal). W Lisp zostało to zredukowane do ~ 10.000 linii. Jeszcze bardziej zaskakujący był fakt, że silnik Lisp był 3-6 razy szybszy. I pamiętaj, że było to dzieło neofity z Lisp! Całe to doświadczenie było dla mnie dość odkrywcze; po raz pierwszy zobaczyłem możliwość połączenia wydajności i ekspresji w jednym języku.
- Michael Lenaghan

Aby wyjaśnić tę część, Michael odpowiedział na komentarz:

Wow, to musiał być naprawdę okropny kod Delphi, jeśli w jakiś sposób udało mu się wykonać 3-6x wolniej niż implementacja Lisp! ”Tak, liczę to jako moją porażkę, ponieważ nie wyjaśniłem go lepiej. Implementacja Lisp była w stanie się przekształcić wyrażenia użytkownika w wyrażenia Lisp - prosty proces - a następnie skompiluj wyrażenia Lisp do kodu natywnego (z pełną optymalizacją). Takie jest znaczenie dziesiątej reguły Greenspun.
--– Michael Lenaghan

Biorąc pod uwagę, że ta odpowiedź składa się z odpowiedzi innej osoby w innym miejscu, jest to wiki społeczności.


2

Zasada jest żartem, ale jest w tym trochę prawdy. Każdy złożony system zawierałby wiele interpretowanych części (patrz, w jaki sposób „wzorzec interpretatora” jest popularny wśród tych, którzy wierzą we wszystkie te wzorce mumbo-jumbo). Każdy złożony system musi zapewniać pewne środki konfiguracji, często ustrukturyzowane, często interpretowane.

Każdy złożony system najprawdopodobniej będzie miał kilka przebiegów generowania kodu i różne niestandardowe preprocesory w procesie kompilacji (pomyśl o rzeczach takich jak mocw Qt lub tablegenw LLVM).

Wiele systemów żongluje złożonymi, podobnymi do drzew strukturami danych, używając zestawu (prawie zawsze) źle zaprojektowanych narzędzi do chodzenia i przekształcania drzew, bardzo przypominających funkcje bibliotek z Common Lisp.

Wszystkie te rzeczy są dostarczane za darmo z Lisp, aw większości przypadków wszystkie te ad hoc, nieplanowane, nie przemyślane wystarczająco dokładnie implementacje byłyby całkowicie gorsze.


2

Każdy wystarczająco złożony system będzie miał specyficzne dla domeny koncepcje i wymagania, które są niezwykle trudne do wyrażenia za pomocą abstrakcji języka, w którym pracujesz. To przypadkowo zmusza programistów do tworzenia abstrakcji specyficznych dla domeny, aby zmniejszyć ciężar wypełniania semantycznej luki między językiem programowania i konkretna domena. Kiedy jest już wystarczająco tych abstrakcji, w zasadzie masz tłumacza języka specyficznego dla domeny. Jest to nieunikniona część tworzenia oprogramowania.


1

Reguła mogłaby być prawdopodobnie dokładniejsza (i mniej zabawna), ponieważ „każdy duży system oparty na oprogramowaniu będzie wymagany do wdrożenia dynamicznego zachowania”.

Można to zrobić na dwa sposoby -

  1. Duży złożony plik konfiguracyjny z dziesiątkami parametrów i setkami definicji.

  2. Język skryptowy AD-HOC.

„sendmail” jest prawdopodobnie kanonicznym przykładem typu „1”. Nie mogę wymyślić żadnych dobrych przykładów typu „2”, które nie obejmowałyby osadzenia „prawdziwego” języka skryptowego np. Warcraft / LUA, a nawet Netscape / JavaScript.

Problem polega na tym, że dla kilku parametrów można to szybko i łatwo zrobić za pomocą pliku konfiguracyjnego, ale to rozwiązanie tak naprawdę nie skaluje się. Jednak w żadnym momencie nie będzie ekonomicznie zrzucać pliku konfiguracyjnego na korzyść podejścia skryptowego podczas dodawania jednej lub dwóch opcji do pliku konfiguracyjnego. Tak więc kod, który interpretuje plik konfiguracyjny, jest naprawdę źle napisanym interpretatorem.


0

To może być prawda, jak stwierdzili inni, wiele programów wymaga konfigurowalności, dlatego zawierają różne interpretery podobne do seplenienia.

Jednak stwierdzenie sugeruje również z uśmieszkiem, że wszystko, czego potrzebujesz, aby stworzyć program, to Lisp i że wszystkie inne języki są gorsze od niego.

Ale to źle, Lisp może być wyrazisty, ale jest też zbyt abstrakcyjny, próbuje ukryć szczegóły platformy i udawać, że w świecie komputerów istnieją tylko listy.

Rzeczywistość programowania o wysokiej wydajności polega na tym, że czasami musimy mieszać się z bitami i bajtami i robić rzeczy specyficzne dla systemu operacyjnego, więc nie jest możliwe zrobienie wszystkiego za pomocą Lisp, jak sugeruje to instrukcja.

Jest raczej na odwrót, bez względu na to, jak skomplikowany, sprytny lub wyrafinowany jest język, który wymyślisz, wszystko to ostatecznie jest po prostu innym sposobem na pisanie asemblera.


Wydaje się, że odnosi się to tylko do najstarszych środowisk seplenieniowych z końca lat 50. Osobiście znalazłem funkcje Common Lisp do radzenia sobie z bitami, prawdopodobnie jedną z najlepszych (z główną konkurencją jest Erlang). Tablice, tablice skrótów, struktury są wspólne.
p_l

Łatwo jest pisać kompilatory dla Lisp, ponieważ nie trzeba go analizować. Można tworzyć funkcje Lisp i kompilator makr (który jest jak ewaluator Lisp tylko jedna do połowy strony kodu na początku), który zamienia te wyrażenia List w C, a ty piszesz w C w Lisp, ale z całą mocą makr i rachunku lambda, jeśli chcesz.
aoeu256

0

Niezależnie od tego, czy miał być traktowany poważnie, tak jest w przypadku największych projektów C i C ++, nad którymi pracowałem.

Nieprawdą jest to, że niestandardowe języki skryptowe przypominają Common Lisp. Pozytywne przykłady przypominają Scheme (ponieważ mądrzejsi projektanci zintegrowali Guile, SpiderMonkey i Lua zamiast wynaleźć własny język). Najbardziej godnymi DailyWTF przykładami był język podobny do Fortha i język podobny do MUMPSA.

Innym przykładem (nie jestem pewien, czy liczy się jako Greenspunning, ale z pewnością WTF) był interpreter XSLT używany do skryptów ogólnego zastosowania. Było to bardziej podobne do Lisp, ponieważ dodali pętlę sprzężenia zwrotnego, w której dane wyjściowe zostałyby przekształcone XSLT po raz drugi - więc teraz skutecznie masz makra.
Motywem tutaj nie było jednak uzyskanie dostępu do funkcji lispy, ale ominięcie procedur kontroli jakości kodu firmy (co dodawało 3 tygodnie opóźnienia do każdej poprawki błędu. XML uznano za „dane” i wyłączono z procesu).


-1

Niestety nie!

Podczas gdy najlepiej jest po prostu osadzić prawdziwego interpretera lisp (y) (javascript lub lua alos wykonuje dobrą robotę), dodanie homebrew 4gl do projektu zmniejsza ogólny rozmiar przy jednoczesnym zwiększeniu elastyczności.

Projekty, które „kodują wszystko”, mają znacznie większą liczbę modułów i stają się nieporęczne i nieelastyczne.

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.