Czy języki programowania powinny być surowe czy luźne? [Zamknięte]

14

W Pythonie i JavaScript średniki są opcjonalne.

W PHP cytaty wokół kluczy tablicowych są opcjonalne ( $_GET[key]vs $_GET['key']), chociaż jeśli je pominiesz, najpierw szuka stałej o tej nazwie. Pozwala również na 2 różne style dla bloków (dwukropek lub nawias klamrowy).

Tworzę teraz język programowania i próbuję zdecydować, jak rygorystyczny powinienem go uczynić. Istnieje wiele przypadków, w których dodatkowe postacie nie są tak naprawdę konieczne i można je jednoznacznie zinterpretować ze względu na priorytety, ale zastanawiam się, czy nadal powinienem je egzekwować, czy nie zachęcać do konsekwencji.

Co myślisz?


Okej, mój język to nie tyle język programowania, co wymyślny język szablonów. Coś w rodzaju skrzyżowania szablonów Haml i Django . Przeznaczony do użycia z moim frameworkiem C # i powinien być bardzo rozszerzalny.

mpen
źródło
22
To jest temat świętej wojny.
1
Pythoniści odradzają stosowanie średników. Szczerze mówiąc, nie jestem pewien, czy są one w ogóle potrzebne - tylko po to, aby pozwolić na wielokrotne stwierdzenia w wierszu, których można całkowicie uniknąć bez cierpienia. Więc ... Jestem za surowszymi językami. Czasami jednak można wymusić stosowanie elementów poza językiem za pomocą narzędzi do analizy kodu, takich jak StyleCop.
Job
1
Cytaty dla kluczy tablicy PHP nie są opcjonalne. Były w PHP2, ale późniejsze wersje automatycznie definiowały stałe. Są one jednak niedozwolone w podstawowej interpolacji łańcuchów "..$_GET[raw]..".
mario
1
@Ralph: zasady są nieco bardziej skomplikowane. Poprawne jest pisanie "xx$_GET[raw]xx"- jeśli zaczniesz używać nawiasów klamrowych, klucz musi być ujęty "xx{$_GET['raw']}xx"w cudzysłów. Jeśli używane są nawiasy klamrowe, wówczas zwykły parser PHP sprawdza to i obowiązuje surowa składnia. Chodzi o to, "$_GET[x]"że klucz jest traktowany jako nieprzetworzony ciąg znaków, i jest to również surowa zasada, na której PHP analizowałby błąd "$_GET['x']".
mario
2
@mario: Sam fakt, że prowadzimy nawet tę rozmowę, oznacza pewną dwuznaczność i zamieszanie w sposobie obsługi klawiszy tablicy. Wydaje się wewnątrz ciągów, jest jednoznaczny, ale niespójny (nie możesz używać cudzysłowów, gdy już jest w ciągu, chyba że używasz nawiasów klamrowych, musisz to zrobić, ale na zewnątrz powinieneś). A poza łańcuchami, w „normalnym” PHP ... cóż, robi to dziwne badziewie.
mpen

Odpowiedzi:

19

Różne typy języków mają różne zastosowania, więc odpowiedź na to pytanie naprawdę zależy od tego, do czego będziesz go używać.

Na przykład Perl jest bardzo luźnym językiem i uważam, że jest bardzo przydatny do pisania szybkich poprawek lub skryptów do łamania liczb. Do solidnych, solidnych projektów używam C #.

Musisz uzyskać równowagę odpowiednią do docelowego wykorzystania. Im bardziej rygorystyczny, tym dłużej trzeba poświęcić na pisanie kodu, ale zyskujesz większą niezawodność, możliwość ponownego użycia i łatwiejsze w utrzymaniu.

BG100
źródło
26

W języku programowania (w przeciwieństwie do języka skryptowego) szukam spójności i mocnego pisania.

W obecnych językach programowania można na przykład pomijać średnik w niektórych miejscach bez dwuznaczności (ostatnie wyrażenie w {}bloku to jedno). Jeśli język programowania pozwala na pomijanie znaków w takich przypadkach, programista ma teraz dodatkowy problem; oprócz ogólnej składni języka musi teraz wiedzieć, w których przypadkach wolno pominąć niektóre części składni.

Ta dodatkowa wiedza nie stanowi problemu dla programisty piszącego kod, ale staje się ciężarem dla każdego, kto musi później zinterpretować istniejący kod (w tym także oryginalnego autora).

Twój przykład w PHP otwiera możliwość subtelnych błędów w programie, gdy stała keyzostanie dodana w tym samym kontekście. Kompilator nie ma możliwości dowiedzenia się, że nie o to chodziło, więc problem staje się widoczny dopiero w czasie wykonywania zamiast czasu kompilacji.

rsp
źródło
1
Zgadzam się, powinieneś ograniczyć możliwości programistów: więcej możliwości => musisz więcej myśleć (powinienem postępować w ten czy
inny
Nie rozumiem, co brak rzutowania typu niejawnego ma wspólnego ze składnią języka.
dan_waterworth
5
Ponadto, kiedy czytasz $_GET[key], nic nie wiesz. Ostatecznie przeszukujesz cały projekt, aby wiedzieć, czy keyjest on stały, czy nie. Takie rozwiązanie oszczędza 0,5 sekundy pisania i zajmuje 20 sekund czytania.
Moshe Revah,
Jeśli twój język daje ci opcje bez różnicy, styl kodowania - kodyfikowany czy nie - ma tendencję do standaryzacji na jednym z nich ...
Deduplicator
11

W każdym miejscu, w którym występuje pewna dwuznaczność, kompilator musi mieć sposób na odgadnięcie, co naprawdę miał na myśli programista. Za każdym razem, gdy tak się dzieje, jest szansa, że ​​programista naprawdę miał na myśli coś innego, ale nie miał reguły rozdzielania niejednoznaczności.

Pisanie poprawnego logicznie kodu jest już wystarczająco trudne. Dodanie dwuznaczności syntaktycznych może na pozór wydawać się „przyjazne”, ale jest to otwarte zaproszenie do wprowadzenia nowych, nieoczekiwanych, trudnych do debugowania błędów w bazie kodu. Podsumowując, bądź jak najbardziej rygorystyczny.

W swoim przykładzie wspomniałeś, że średniki są opcjonalne w Pythonie i JavaScript. Przynajmniej w przypadku Javascript nie jest to do końca prawdą. Średniki są tak samo wymagane w JS, jak w każdym innym języku rodziny C. Ale parser JavaScript jest wymagany przez specyfikację języka, aby wstawić brakujące średniki w określonych okolicznościach. Jest to powszechnie uważane za bardzo złą rzecz, ponieważ może źle wpłynąć na twoje intencje i zepsuć kod.

Mason Wheeler
źródło
6

Odpowiedź na to, jak luźno powinieneś uczynić swój język, jest równa odpowiedzi na pytanie zadane w teksańskim akcentie „Jak się czujesz, punku?”.

Henrik
źródło
Nie rozumiem
mpen
4
Moja zła próba żartu polegała na tym, że dynamiczne pisanie może cię ugryźć, gdy systemy stają się coraz większe, zwłaszcza gdy dodajesz niedoświadczonych programistów do miksu. Z mojego doświadczenia wynika, że ​​systemy o dowolnej wartości stają się coraz większe i mają coraz więcej programistów. Posiadanie „Znajdź wszystkie zastosowania symbolu” lub „Zmień nazwę wszystkich” lub „Bezpieczne usuwanie” lub „Znajdź błędy w rozwiązaniu” jest zatem absolutnie nieocenione. Pisanie dynamiczne w ograniczonym sensie, że VB jest opóźnione i powoduje szeroki przymus pisania, powodując wiele błędów na obecnym koncercie.
Henrik
Ergo, jeśli masz szczęście ze swojego projektu, na przykład masz szczęście, że masz dobrych i doświadczonych programistów lub masz szczęście w pisaniu poprawnego kodu; możesz używać pisania dynamicznego.
Henrik
2
Ach ... ale to pytanie nigdy nie dotyczyło dynamicznego pisania :)
mpen
1
Ach, bardzo prawdziwa Raplh. Po prostu myślę, że dynamiczne języki są bardziej luźne, ponieważ zwykle są bardziej luźne. Masz rację.
Henrik,
4

Wszyscy nie musieliby tak ciężko pracować nad spójnością kodowania, gdyby języki nie różniły się tak bardzo. Nie podoba nam się to, gdy użytkownicy składają niepotrzebne żądania, więc dlaczego warto pytać o nasze języki programowania?

JeffO
źródło
+1: całkowicie się zgadzam. Nie rozumiem, dlaczego zasady takie jak KISS i YAGNI nie powinny mieć zastosowania do projektowania języka.
Giorgio
2

Moją osobistą preferencją jest umiejętność zachowania wystarczającej surowości, aby złapać moje literówki, ale przy jak najmniejszej dodatkowej płycie grzewczej, jak to możliwe. Mówię o tym problemie na stronie http://www.perlmonks.org/?node_id=755790 .

To powiedziawszy, projektujesz swój język dla siebie. Powinieneś sprawić, że będzie to, co chcesz.

btilly
źródło
+1: ... Zdolność do wystarczającej surowości, aby złapać moje literówki, ale przy jak najmniejszej dodatkowej płycie kotłowej, jak to możliwe. - Tak. Czy znasz plan Andersa Hejlsberga dla C #? Podejmuje świadomą decyzję, aby podkreślić „esencję nad ceremonią”. channel9.msdn.com/Blogs/matthijs/…
Jim G.
@ jim-g: Dzięki za myśl. Nie znam się na niczym z C #. Od wielu lat nie pracuję w świecie Microsoft.
btilly
1

Lubię swoje języki, aby robić to, co mam na myśli. Zasadniczo to dość mocno skłania się w kierunku poluzowania. Chciałbym również móc oznaczyć element „ścisły” na elemencie lub bloku, aby móc debugować / analizować ten ograniczony obszar.

Paul Nathan
źródło
1

Zwykle wpadam na stronę „Co ułatwiłoby mi jako programistę”. Oczywiście może to oznaczać więcej niż jedną rzecz. W JavaScript nie ma prawie żadnego sprawdzania typów, co działa świetnie, dopóki nie trafisz na dziwny błąd. Z drugiej strony w Haskell jest dużo sprawdzania typów, co stawia więcej pracy z przodu, ale blokuje niektóre klasy błędów.

Szczerze mówiąc sprawdziłbym kilka języków, aby zobaczyć, co robią, i spróbować znaleźć niszę, w której żaden z nich nie trafił!

Nie sądzę, aby istniał jeden oczywisty właściwy sposób, a przynajmniej jeśli nie ma czegoś, na co ludzie nie osiągnęli jeszcze konsensusu. Uczymy się zatem, tworząc języki z różnymi systemami typów.

Powodzenia.

Zachary K.
źródło
1

Sugerowałbym, że dobry język programowania powinien mieć ścisłe reguły, których implementacje powinny konsekwentnie egzekwować, ale reguły powinny być napisane w taki sposób, aby były pomocne. Sugerowałbym ponadto, że należy rozważyć zaprojektowanie języka, aby uniknąć przypadków, w których „odległość Hamminga” między dwoma zasadniczo różnymi programami jest tylko jedna. Oczywiście nie da się tego osiągnąć za pomocą literałów numerycznych lub łańcuchowych (jeśli programista, który miał na myśli 123 zamiast 1223 lub 13, kompilator nie bardzo wie, co znaczy program). Z drugiej strony, jeśli język miałby być używany :=do przydziału i ==do porównywania równości, a nie używać jednego= w jakimkolwiek celu prawnym, to znacznie zmniejszyłoby możliwości zarówno przypadkowych zleceń, które miały być porównaniami, jak i przypadkowych porównań bezczynności, które miały być zleceniami.

Sugerowałbym, że chociaż istnieją miejsca, w których kompilatory są przydatne do wnioskowania, takie wnioskowanie jest często najcenniejsze w najprostszych przypadkach, a mniej wartościowe w bardziej skomplikowanych przypadkach. Na przykład, zezwalając na zastąpienie:

  Słownik <skomplikowaneTyp1, skomplikowaneTyp2> pozycja =
    nowy słownik <skomplikowaneTyp1, skomplikowaneTyp2 ()>;

z

  var item = new Dictionary <skomplikowaneTyp1, skomplikowaneTyp2 ()>;

nie wymaga żadnego skomplikowanego wnioskowania o typie, ale sprawia, że ​​kod jest znacznie bardziej czytelny (między innymi, stosowanie bardziej szczegółowej składni tylko w scenariuszach, w których jest to potrzebne, np. ponieważ typ miejsca przechowywania nie pasuje dokładnie do typu wyrażenia jego utworzenie pomoże zwrócić szczególną uwagę na miejsca, które mogą tego wymagać).

Jedną z głównych trudności przy próbie bardziej wyrafinowanego wnioskowania na temat typu jest możliwość wystąpienia niejednoznacznych sytuacji; Sugerowałbym, że dobry język powinien pozwolić programiście na dołączenie informacji do kompilatora, którego mógłby użyć do rozwiązania takich dwuznaczności (np. Poprzez uznanie niektórych typów czcionek za preferowane od innych), stwierdzenia, że ​​nie mają one znaczenia (np. Ponieważ chociaż dwa możliwe przeciążenia mogą uruchamiać inny kod, programista wskazał, że powinny zachowywać się identycznie w tych przypadkach, w których można użyć jednego z nich, lub oznaczać te (i tylko te), których nie można obsłużyć w żaden z powyższych sposobów.

supercat
źródło
1

Dla mnie najważniejsza jest czytelność.

Dla osoby doświadczonej w języku znaczenie fragmentu kodu powinno być jasne bez konieczności głębokiej analizy kontekstu.

Język powinien być w stanie oznaczać błędy tak często, jak to możliwe. Jeśli każda losowa sekwencja znaków tworzy poprawny składniowo program, nie jest to pomocne. A jeśli zmienne są tworzone automatycznie przy ich pierwszym użyciu, to popełnisz błąd clientw pisowni, ponieważ cleintnie spowoduje to błędu kompilacji.

Oprócz składni język powinien mieć jasno zdefiniowaną semantykę, a może to nawet trudniejsze niż decydowanie o przyzwoitej składni ...

Dobre przykłady:

  • W Javie "1"jest ciągiem, 1jest liczbą całkowitą, 1.0jest podwójnym i 1Ldługim. Jedno spojrzenie i wiesz co to jest.

  • W Javie =jest to zadanie. Przypisuje wartość typom pierwotnym i odwołanie do typów referencyjnych. Nigdy nie kopiuje skomplikowanych danych ani nie porównuje.

  • W Javie wywołanie metody wymaga nawiasów, w ten sposób wyraźnie odróżnia się od zmiennych - więc jeśli nie ma nawiasów, nie trzeba szukać definicji metody, to po prostu odczyt danych.

Złe przykłady:

  • W Javie takim symbolem clientmoże być prawie wszystko: element ścieżki pakietu, nazwa klasy lub interfejsu, nazwa klasy wewnętrznej, nazwa pola, nazwa metody, zmienna lokalna i jeszcze więcej. Od użytkownika zależy wprowadzenie lub przestrzeganie konwencji nazewnictwa.

  • W Javie kropka .jest nadmiernie używana. Może to być separator w nazwie pakietu, separator między pakietem a klasą, separator między klasą zewnętrzną i wewnętrzną, łącznik między wyrażeniem instancji a metodą, która ma zostać wywołana w instancji, i wiele innych.

  • W wielu językach nawiasy klamrowe ifbloków są opcjonalne, co prowadzi do okropnych błędów, jeśli ktoś doda jeszcze jedno zdanie do (nieistniejącego) bloku.

  • Operatory Infix: czasami muszę zatrzymać się na wyrażeniu liczbowym i zastanowić się, co to znaczy, krok po kroku. Wszyscy jesteśmy przyzwyczajeni do pisania wyrażeń matematycznych w notacji infix a * b / c * d + e. Przez większość czasu pamiętamy pierwszeństwo mnożenia i dzielenia nad dodawaniem i odejmowaniem (ale czy zdawałeś sobie sprawę, że nie dzielimy przez c*d, ale dzielimy tylko przez, ca następnie mnożąc przez d?). Ale jest tak wielu dodatkowych operatorów infix z własnymi regułami pierwszeństwa i w niektórych językach przeciążeniem, że trudno jest je śledzić. Może wymuszenie użycia nawiasów było lepszym podejściem ...

Ralf Kleberhoff
źródło
Mówiłeś głównie o dwuznaczności, ale może istnieć wiele sposobów zrobienia tego samego bez tworzenia niejasności. Może możemy mieć dwóch operatorów mnożenia *i ×. Zarówno 5*35 × 3 'oznaczają to samo, a doświadczony programista wie dokładnie, co mają na myśli, bez konieczności rozglądania się wokół otaczającego kontekstu. Problem polega jednak na tym, że istnieją teraz dwa sposoby robienia tego samego i ktoś może się między nimi wymieniać w trakcie programu. Uważam, że o to bardziej martwiłem się, gdy zadałem pytanie.
mpen
-2

Możesz rozważyć analogię z językiem naturalnym. Czy w e-mailu jesteś nazistą z gramatyki? Czy jesteś w porządku z niektórymi błędami gramatycznymi, takimi jak podzielone bezokoliczniki, brakujące spójniki lub źle umieszczone modyfikatory. Odpowiedź sprowadza się do osobistych preferencji.

emallove
źródło