Języki takie jak C, Java i C ++ wszystko wymaga nawiasów wokół całego wyrażenia stosowane w sposób if
, while
lub switch
.
if (true) {
// Do something
}
w przeciwieństwie do
if true {
// Do something
}
Wydaje mi się to dziwne, ponieważ nawiasy są zbędne. W tym przykładzie true
jest pojedynczym wyrażeniem. Nawiasy nie zmieniają jego znaczenia w żaden znany mi sposób. Dlaczego istnieje ta dziwna składnia i dlaczego jest tak powszechna? Czy jest to jakaś korzyść, której nie jestem świadomy?
THEN
).if
instrukcji, po prostu tworzą instrukcję złożoną.Odpowiedzi:
Musi być jakiś sposób na określenie, gdzie kończy się warunek, a zaczyna gałąź. Można to zrobić na wiele różnych sposobów.
W niektórych językach istnieją żadne warunkowe w ogóle , na przykład w Smalltalk, Self, nowomowy, Io, Ioke, Seph, i ozdobne. Rozgałęzianie warunkowe jest po prostu implementowane jako normalna metoda, jak każda inna metoda. Metoda jest implementowana na obiektach boolean i zostaje wywołana na boolean. W ten sposób warunek jest po prostu odbiorcą metody, a dwie gałęzie są dwoma argumentami, np. W Smalltalk:
Jeśli znasz język Java, jest to równoważne z następującymi:
W rodzinie języków Lisp sytuacja jest podobna: warunkowe są zwykłymi funkcjami (właściwie makrami), a pierwszy argument jest warunkiem, drugi i trzeci argument to gałęzie, więc są to zwykłe argumenty funkcji, i jest nic specjalnego nie jest potrzebne do ich rozgraniczenia:
Niektóre języki używają słów kluczowych jako ograniczników, np. Algol, Ada, BASIC, Pascal, Modula-2, Oberon, Oberon-2, Active Oberon, Component Pascal, Zonnon, Modula-3:
W Ruby możesz użyć słowa kluczowego lub separatora wyrażeń (średnik lub znak nowej linii):
Go wymaga, aby gałęzie były blokami i nie dopuszcza wyrażeń ani instrukcji, co sprawia, że nawiasy klamrowe są obowiązkowe. Dlatego nawiasy nie są wymagane, chociaż możesz je dodać, jeśli chcesz; Perl6 i Rust są podobne pod tym względem:
Niektóre języki używają innych znaków niealfanumerycznych do określenia warunku, np. Python:
Najważniejsze jest to: trzeba jakiś sposób mówienia gdzie stan kończy się i zaczyna się gałąź. Można to zrobić na wiele sposobów, nawiasy są tylko jednym z nich.
źródło
Nawiasy są niepotrzebne tylko w przypadku użycia nawiasów klamrowych.
Bez nich staje się na przykład dwuznaczny.
źródło
if
w: podstawowym, asemblerowym, pythonowym, bash / zsh, tcl, wsadowym, bzdurnym lub kodzie maszynowym. Brak nawiasów sprawia, żeif
dwuznaczność staje się dwuznaczna tylko wtedy, gdy język został zaprojektowany tak, aby na nich polegać.if Condition then ...
.{}
obowiązkowe i dlatego nie wymagają parens wokół wyrażenia. Nie tylko pareny nie są wymagane, ale jeśli dobrze pamiętam, dodawanie parens spowodowałoby błąd kompilacji - są zabronioneNawiasy w
if
instrukcji nie mają tego samego znaczenia, co nawiasy używane w wyrażeniu arytmetycznym. Nawiasy w wyrażeniu arytmetycznym służą do grupowania wyrażeń razem. Nawiasy wif
instrukcji służą do rozgraniczenia wyrażenia boolowskiego; to znaczy, aby odróżnić wyrażenie boolowskie od resztyif
instrukcji.W
if
instrukcji nawiasy nie wykonują funkcji grupowania (jednak wif
instrukcji można nadal używać nawiasów do grupowania wyrażeń arytmetycznych. Zewnętrzny zestaw nawiasów służy następnie do ograniczenia całego wyrażenia boolowskiego). Wymaganie ich upraszcza kompilator, ponieważ kompilator może polegać na tych nawiasach, które zawsze tam są.źródło
IF primary_expression statement
. Zauważ, że ta ostatnia jest równie jednoznaczna.primary_expression
nie może być odróżniony od operatora prefiksu w wyrażeniu-wyrażeniu. Aby skopiować odpowiedź Telastyn, wif true ++ x;
. Ponadto, jeśli istnieją puste instrukcje,if a & f;
może to być albo pusta instrukcja i plik binarny&
wewnątrz warunku, albo jednoargumentowy&
na początku instrukcji. Ale podczas dopasowywania nawiasów jest dokładnie jedno dopasowanie do otwarcia (IDENTIFIER
,CONSTANT
,STRING_LITERAL
i'(' expression ')'
.Jak inni już częściowo zauważyli, wynika to z faktu, że wyrażenia są również prawidłowymi instrukcjami, aw przypadku bloku z jedną instrukcją można upuścić nawiasy klamrowe. Oznacza to, że następujące są niejednoznaczne:
Ponieważ można to interpretować jako:
zamiast:
Wiele języków (np. Python) pozwala uniknąć nawiasów, ale nadal ma znacznik stanu końcowego:
Jednak masz rację, że mógłby określić język, w którym nigdy nie są wymagane nawias: język gdzie wyrazem jest nie ważny oświadczenie nie ma tego problemu.
Niestety oznacza to, że takie rzeczy jak:
by nie być ważne oświadczenia, więc trzeba by wprowadzić pewne dziwne składni, aby móc wykonywać takie działania, bez tworzenia wyrażeń. Prostym sposobem na to jest po prostu poprzedzenie wyrażenia znacznikiem, takim jak
[statement]
:Teraz dwuznaczność znika, ponieważ będziesz musiał napisać:
Ale jak widać, nie widzę, aby taki język był rozpowszechniony, ponieważ umieszczenie nawiasu wokół
if
warunku (lub:
jego końca) jest znacznie lepsze niż umieszczenie takiego znacznika dla każdej instrukcji wyrażenia.Uwaga : użycie
[statement]
znacznika jest po prostu najprostszą składnią, jaką mogłem wymyślić. Jednak ty mógł mieć dwie całkowicie odrębne składnie dla wyrażenia i instrukcje bez dwuznaczności między nimi, które nie wymagają takiego znacznika. Problem polega na tym, że język byłby bardzo dziwny, ponieważ aby robić te same rzeczy w wyrażeniu lub instrukcji, musiałbyś użyć zupełnie innej składni.Jedną rzeczą, która przychodzi do głowy, aby mieć dwa oddzielne składnie bez takiej wyraźnej markera byłoby, na przykład: sprawozdanie siły użyć symboli Unicode (więc zamiast
for
ciebie by wykorzystać jakąś odmianę unicode literf
,o
ir
), natomiast wyrażenia się Tylko ASCII.źródło
discard
jego wartość w Nim . Jest to jednak zrobione dla bezpieczeństwa typu, a nie ze względów składniowych.?
na przykład simbol w rzeczywistości jest funkcją po PP). Nie ma;
. Jasne, potrzebuje znacznika linii kontynuacji, ale jest to odradzane. harbour.github.io/doc/clc53.html#if-cmd . Kompilator jest szybki i prosty (stworzony za pomocą Bison / Flex).if
,while
ecc są ograniczone w porównaniu do ogólnych określeń stosowanych w innych językach. Jasne: jeśli masz więcej niż dwie kategorie składniowe (takie jak wyrażenie, wyrażenie, wyrażenie logiczne, ekspres do kawy, ...), możesz wymienić trochę swobody.Języki z rodziny C często wymagają tych nawiasów, ale nie są uniwersalne.
Jednym z bardziej zauważalnych zmian składniowych Perl 6 jest to, że oni gramatykę zmodyfikowany tak, aby nie dać nawiasy wokół
if
,for
i warunki podobne wypowiedzi. Więc coś takiego jest doskonale poprawne w Perlu 6:jak jest
Ponieważ jednak są to tylko wyrażenia, możesz je nawiasować, jeśli chcesz, w takim przypadku są to zwykłe grupowania zamiast wymaganej części składni, jak w C, C #, Java itp.
Rust ma podobną składnię jak Perl 6 w tym dziale:
Wydaje mi się, że cechą bardziej nowoczesnych języków inspirowanych językiem C jest patrzeć na takie rzeczy i zastanawiać się nad ich usunięciem.
źródło
if
lub pętli z BLOKAMI wymagane są pareny, np. Wif ( $x == 4 ) { ... }
lubforeach my $foo ( @bar ) { ... }
. Gdy używana jest notacja postfiksowa, pareny są opcjonalne, tak jak wreturn unless $foo;
lub++$x while s/foo/bar/g;
.Dziwi mnie jeden aspekt, który nie przyniósł żadnej z istniejących odpowiedzi.
C, a także wiele pochodnych C i podobnych, ma tę cechę szczególną, że wartość przypisania jest wartością przypisaną. Konsekwencją tego jest to, że przypisanie może być użyte tam, gdzie oczekiwana jest wartość.
To pozwala ci pisać takie rzeczy jak
lub
lub
(co jest domyślnie traktowane tak,
while (n < m && *p1++ = *p2++ != 0) { n++; }
ponieważ C traktuje wartość niezerową jako prawdziwą; nawiasem mówiąc, myślę, że to tylko o strncpy () w standardowej bibliotece C)lub nawet
i to wszystko jest ważne. Nie wszystkie kombinacje poprawne pod względem składniowym są z konieczności przydatne (a współczesne kompilatory szczególnie ostrzegają o przypisaniach wewnątrz warunkowych, ponieważ jest to częsty błąd), ale niektóre z nich są w rzeczywistości przydatne.
Analiza takich stwierdzeń byłaby prawdopodobnie znacznie trudniejsza, gdyby nie było jednoznacznego sposobu ustalenia, gdzie wyrażenie warunkowe zaczyna się i kończy.
Nawiasy były już używane do oddzielania nazw funkcji od argumentów funkcji, więc myślę, że wydawały się naturalnym wyborem do oddzielania słów kluczowych od argumentów słów kluczowych.
Oczywiście można zdefiniować alternatywne składnie, aby zrobić to samo. Ale zrobienie tego zwiększyłoby złożoność, szczególnie w parserze, który musiałby wówczas poradzić sobie z dwoma różnymi zestawami składni dla zasadniczo tej samej rzeczy. Kiedy projektowano C, moc obliczeniowa (zarówno pod względem zdolności do kruszenia liczb, pamięci roboczej i pojemności pamięci) była bardzo ograniczona; wszystko, co zmniejszało złożoność przy niskim lub zerowym koszcie czytelności, było prawie na pewno pożądaną zmianą.
Używanie nawiasów może dziś wydawać się nieco archaiczne, ale nie jest tak, że biorąc pod uwagę kogoś znającego język, pogarsza czytelność w porównaniu z inną składnią, która jest w stanie wyrazić te same rzeczy.
źródło
Powodem jest głównie historia.
W czasie, gdy pierwszy kompilator C został napisany, komputery mają bardzo ograniczoną pamięć RAM, procesor i kompilatory pisane „ręcznie” za pomocą kilku narzędzi, które pomagają twórcom kompilatorów. Dlatego skomplikowane reguły były kosztowne do wdrożenia w kompilatorze. C ++, C #, Java itp. Zostały zaprojektowane tak, aby programiści C mogli łatwo się uczyć, dlatego nie wprowadzono żadnych „niepotrzebnych” zmian.
W językach „c like” warunkowe (
if, while, etc
) nie wymagają jawnegoblock
wyłączenia kodu, wystarczy użyć prostej instrukcji.lub możesz połączyć instrukcje razem w jeden
compound statement
, wstawiając je za pomocą{}
Lubimy kompilator, aby znaleźć błąd, który popełniamy i dać jako komunikat błędu, który możemy zrozumieć.
źródło
Zarówno Java, jak i C ++ zostały opracowane po tym, jak C stał się bardzo popularnym językiem programowania. Jedną z kwestii przy projektowaniu każdego z tych języków było to, że spodobałoby się programistom języka C i zachęciło tych programistów do korzystania z nowego języka. (Byłem jednym z programistów C, którym udało się uzyskać.) C ++ został dodatkowo zaprojektowany tak, aby był (prawie) wymienny z kodem C. W celu wsparcia tych celów, zarówno C ++ i Java przyjęła wiele składni C, łącznie z nawiasami wokół warunków
if
,while
orazswitch
sprawozdania.Stąd powodem, dla którego wszystkie te języki wymagają nawiasów wokół warunków tych stwierdzeń, jest to, że C tak, a pytanie jest tak naprawdę, dlaczego C wymaga tych nawiasów.
Początki języka C opisano w tym artykule Dennis Ritchie, jeden z głównych autorów jego rozwoju (niektórzy mogą nawet powiedzieć, że główny autor jego rozwoju). Jak powiedziano w tym artykule, C został pierwotnie opracowany na początku lat 70. XX wieku jako systemowy język programowania dla komputerów o wyjątkowo ograniczonej przestrzeni w pamięci głównej. Pożądane było posiadanie języka wyższego poziomu niż język asemblera, ale biorąc pod uwagę zasoby dostępne do pracy, łatwość jego analizy była również ważna. Wymaganie nawiasów ułatwiłoby identyfikację kodu warunkowego.
Można również wnioskować, że umiejętność pisania programów przy użyciu mniejszej liczby znaków została uznana za zaletę, a dwa nawiasy zajmują mniej miejsca niż słowo kluczowe
THEN
używane w FORTRAN i innych językach wysokiego poziomu w tym czasie; w rzeczywistości, ponieważ nawiasy mogą również zastępować spacje jako ograniczniki symboli,if(a==b)
były o cztery całe znaki krótsze niżIF a==b THEN
.W każdym razie trzeba było zachować równowagę między tym, jak łatwo ludzie będą w stanie czytać, pisać i rozumieć programy napisane w C, jak łatwo kompilator może analizować i kompilować programy napisane w C, a liczbą kilobajtów (!) byłoby wymagane zarówno dla źródła programu, jak i samego kompilatora. I nawiasy wokół warunków
if
,while
orazswitch
wypowiedzi było to, jak ludzie zdecydowali się uderzyć tej równowagi w projektowaniu C.Jak wykazano w kilku innych odpowiedziach, po usunięciu szczególnych okoliczności, w których C został opracowany, w warunkach różnych języków programowania zastosowano wszelkiego rodzaju alternatywne formy składni. Tak więc nawiasy naprawdę sprowadzają się do decyzji projektowej podjętej przez kilka osób pod pewnymi ograniczeniami w pewnym momencie historii.
źródło
Wielu tutaj twierdzi, że bez nawiasów składnia byłaby dwuznaczna i sugerowałaby po cichu, że byłaby to jakaś zła, a nawet niemożliwa sytuacja.
W rzeczywistości języki mają wiele sposobów radzenia sobie z dwuznacznościami. Pierwszeństwo operatorów jest tylko jednym z przykładów tego tematu.
Nie, dwuznaczność nie jest przyczyną nawiasów. Wydaje mi się, że można po prostu stworzyć wersję C, która nie wymaga nawiasów wokół warunku (czyniąc je opcjonalnymi) i która nadal tworzy poprawny kod we wszystkich przypadkach. Przykład
if a ++ b;
może być interpretowany jako równoważnyif (a) ++b;
lubif (a++) b;
, cokolwiek wydaje się bardziej odpowiedni.Pytanie, dlaczego Dennis Ritchie postanowił uczynić () obowiązkowym (a więc wymyślając ten mem dla wielu języków pochodnych) jest raczej językowe. Myślę, że ojcem tej myśli było stwierdzenie, że warunek jest raczej wyrażeniem niż rozkazem .
W rzeczywistości C został zaprojektowany do analizowania przy użyciu parsera jednoprzebiegowego. Zastosowanie składni z obowiązkowymi nawiasami wokół warunku obsługuje ten aspekt.
źródło
Nawiasy wokół
if
warunków nie są wymagane w Fortran, Cobol, PL / 1, Algol, Algo-68, Pascal, Modula, XPL, PL / M, MPL, ... lub w innym języku zethen
słowem kluczowym.then
służy do rozgraniczeniacondition
następujących elementówstatement
.Nawias zamykający w C itp. Działa jako
then
, a otwierający jest formalnie redundantny.Powyższe uwagi dotyczą tradycyjnie analizowanych języków.
źródło