왜 for-each는“in”대신에 콜론을 가지고 있습니까?


9

Java 5 언어 안내서에서 :

콜론 (:)이 보이면 "in"으로 읽습니다.

in그럼 처음부터 사용하지 않겠습니까?

이것은 몇 년 동안 나를 괴롭 혔습니다. 다른 언어와 일치하지 않기 때문입니다. 예를 들어, Java에는 C ++, Scala 또는 Ruby와 같은 기호 대신 유형 간 관계 에 대한 implements, 가 있습니다 .extendssuper

5 개의 문맥 에서 사용되는 Java 콜론 에서 . 그중 세 가지는 C에서 상속되었으며 다른 두 가지는 Joshua Bloch에 의해 승인되었습니다. 적어도, 그는 "폐쇄 논란" 대화 중에 그는 멍청했다 . 이것은 for-each 의미와 일치하지 않는 매핑을위한 콜론의 사용을 비판 할 때 발생합니다. 그것은 각각의 학대 예상 패턴이기 때문에 이상하게 보입니다. list_name/category: elements또는 처럼 laberl/term: meaning.

jcp와 jsr을 스누핑했지만 메일 목록의 흔적을 찾지 못했습니다. 이 문제에 대한 토론이 Google에 없습니다. 의 콜론의 의미로 혼란스러워하는 초보자들만 for있습니다.


in지금까지 제공되지 않은 주요 주장 :

  • 새로운 키워드가 필요합니다. 과
  • 렉싱이 복잡합니다.

관련 문법 정의를 살펴 보겠습니다 .

성명서
    : 'for' '('forControl ')'문
    | ...
    ;

forControl
    : enhancedForControl
    | forInit? ';' 표현? ';' 업데이트?
    ;

향상된 제어
    : variableModifier * 유형 variableDeclaratorId ':'표현식
    ;

더 복잡하지 않거나 새 키워드가 필요 :하도록로 변경하십시오 in.


1
언어 디자이너의 동기를 찾는 가장 좋은 방법은 종종 디자이너 자신입니다. 즉, 이것은 iterable에 대한 구문 설탕 일 것입니다. 참조 stackoverflow.com/questions/11216994/...
로버트 하비

답변:


8

일반적으로 파싱되는 일반적인 파서는 파서가 입력에 닿기 전에 렉서 단계를 갖습니다. 렉서 ( "스캐너"또는 "토큰 라이저")는 입력을 유형이 주석이 달린 작은 토큰으로 자릅니다. 이를 통해 주 파서는 각 문자를 터미널로 취급하지 않고 토큰을 터미널 요소로 사용할 수 있으므로 효율성이 현저히 향상됩니다. 특히, 어휘 분석기는 모든 주석과 공백을 제거 할 수 있습니다. 그러나 별도의 토크 나이저 단계는 키워드가 식별자로 사용될 수 없음을 의미합니다 (언어가 선호 하지 않는 스트로 핑 을 지원 하거나 모든 식별자 앞에시길이가 붙지 않는 경우 $foo).

왜? 다음 토큰을 이해하는 간단한 토크 나이저가 있다고 가정 해 봅시다.

FOR = 'for'
LPAREN = '('
RPAREN = ')'
IN = 'in'
IDENT = /\w+/
COLON = ':'
SEMICOLON = ';'

토크 나이 저는 항상 가장 긴 토큰과 일치하며 식별자보다 키워드를 선호합니다. 그래서 interesting으로 lexed됩니다 IDENT:interesting만, in같은 lexed되지 않습니다 IN으로, 결코 IDENT:interesting. 같은 코드 스 니펫

for(var in expression)

토큰 스트림으로 변환됩니다

FOR LPAREN IDENT:var IN IDENT:expression RPAREN

지금까지는 효과가 있습니다. 그러나 모든 변수 in는 변수 가 IN아닌 키워드로 표현되어 코드가 손상됩니다. 어휘 분석기는 토큰들 사이에 어떠한 상태도 유지하지 않으며, in우리가 for 루프에있을 때를 제외하고는 보통 변수 여야한다는 것을 알 수 없습니다 . 또한 다음 코드는 합법적이어야합니다.

for(in in expression)

첫 번째 in는 식별자이고 두 번째는 키워드입니다.

이 문제에 대한 두 가지 반응이 있습니다.

문맥 키워드가 혼동되기 때문에 대신 키워드를 다시 사용하겠습니다

Java에는 많은 예약어가 있으며, 그 중 일부는 C ++에서 Java로 전환하는 프로그래머에게 더 유용한 오류 메시지를 제공하는 것 외에는 사용되지 않습니다. 새 키워드를 추가하면 코드가 손상됩니다. 문맥 강조 표시 키워드를 추가하면 구문 강조 표시가 우수하지 않으면 코드 독자에게 혼란스러워지며 고급 구문 분석 기술을 사용해야하므로 툴링을 구현하기가 어렵습니다 (아래 참조).

우리가 언어를 확장하고 싶을 때, 유일한 건전한 접근법은 이전에는 그 언어에서 합법적이지 않은 기호를 사용하는 것입니다. 특히 이들은 식별자가 될 수 없습니다. foreach 루프 구문을 사용하여 Java는 기존 :키워드를 새로운 의미로 재사용했습니다 . 람다를 사용하여 Java는 ->이전에 어떤 법적 프로그램에서도 발생할 수 없었던 키워드를 추가했습니다 ( -->여전히 '--' '>'합법적 인 ->것으로 어휘 화되고 이전에는로 어휘 화 '-', '>'되었지만 파서가 해당 시퀀스를 거부합니다).

문맥 키워드는 언어를 단순화하고 구현합니다

Lexers는 틀림없이 유용합니다. 그러나 파서 전에 렉서를 실행하는 대신 파서와 함께 실행할 수 있습니다. 상향식 파서는 항상 특정 위치에서 사용할 수있는 일련의 토큰 유형을 알고 있습니다. 그런 다음 파서는 현재 위치에서 이러한 유형과 일치하도록 어휘 분석기를 요청할 수 있습니다. for-each 루프에서 파서는 ·변수가 발견 된 후 (단순화 된) 문법으로 표시된 위치에 있습니다 .

for_loop = for_loop_cstyle | for_each_loop
for_loop_cstyle = 'for' '(' declaration · ';' expression ';' expression ')'
for_each_loop = 'for' '(' declaration · 'in' expression ')'

그 위치에서, 법적 토큰은 SEMICOLON또는 IN,하지만 IDENT. 키워드 in는 전적으로 모호하지 않습니다.

이 특정 예에서 위의 문법을 다음과 같이 다시 작성할 수 있으므로 하향식 파서는 문제가 없습니다.

for_loop = 'for' '(' declaration · for_loop_rest ')'
for_loop_rest =  · ';' expression ';' expression
for_loop_rest = · 'in' expression

결정에 필요한 모든 토큰은 역 추적없이 볼 수 있습니다.

사용성 고려

자바는 항상 의미 론적 및 구문 적 단순성으로 향했다. 예를 들어, 언어는 코드를 훨씬 더 복잡하게 만들므로 연산자 오버로드를 지원하지 않습니다. 사이에 결정할 때 그래서 in:A에 대한-각 루프 구문, 우리는 덜 혼란과 사용자에게 더 분명하다 고려해야합니다. 극단적 인 경우는 아마도

for (in in in in())
for (in in : in())

(참고 : Java에는 유형 이름, 변수 및 메소드에 대한 별도의 네임 스페이스가 있습니다. 이것이 대부분 실수라고 생각합니다. 이것은 나중에 언어 디자인이 더 많은 실수 를 추가해야한다는 의미는 아닙니다 .)

어떤 대안이 반복 변수와 반복 컬렉션 사이에 명확한 시각적 분리를 제공합니까? 코드를 살펴보면 어떤 대안을 더 빨리 인식 할 수 있습니까? 이러한 기준에서 기호를 분리하는 것이 단어의 문자열보다 낫다는 것을 알았습니다. 다른 언어는 다른 값을 갖습니다. 예를 들어 파이썬은 자연스럽게 읽을 수 있고 이해하기 쉽도록 많은 연산자를 영어로 설명하지만, 동일한 속성으로 인해 한 조각의 파이썬을 한눈에 이해하기가 매우 어려울 수 있습니다.


17

를위한 각 루프 구문은 수 있도록해야 할 것 자바 5에 추가 된 in이 기존 코드를 나누기 때문에 언어 키워드를 나중에 언어에 키워드를 추가하는 모든 비용 피하기 뭔가 - 이름이 갑자기 모든 변수 in 구문 분석 원인을 오류. enum그 점에서 충분히 나빴습니다.


2
불편한 것 같습니다. 언어 디자이너가 처음부터 필요한 키워드를 대부분 예측할 수있을 정도로 훌륭하다고 가정합니다. 나는 그것이 심지어 필요한지 확신하지 못한다. 괜찮은 컴파일러는 문맥에 따라 키워드가 변수인지 여부를 결정할 수 있습니다.
Robert Harvey

2
Java에 C #과 같은 문맥 키워드가 있다고 생각하지 않습니다. 따라서을 사용 in하면 새로운 키워드를 System.in도입하여 이전 버전과의 호환성 ( , 누구?) 을 깨뜨 리거나 이전에 알려지지 않은 새로운 개념 (문맥 키워드)을 도입 할 수있었습니다. 무슨 이익을 얻으려면?
Jörg W Mittag

2
문맥 키워드에 어떤 해가 있습니까?
user2418306

5
@ user2418306 언어를 별도의 어휘 분석기 단계로 구문 분석하지 않으면 키워드를 추가해도 기존 코드를 깨지 않아도됩니다. 특히 "in" for(variable in expression)을 변수에 사용할 수 있더라도 "in"은 법적인 코드로 모호 할 수 없습니다. 그러나 많은 컴파일러 툴 체인에서 별도의 렉서 단계가 일반적입니다. 이로 인해 일반적인 파서 생성기로 Java를 구문 분석하는 것이 불가능하거나 훨씬 더 어려워집니다. 언어의 구문을 단순하게 유지하는 것은 일반적으로 모든 관련자에게 좋습니다. 모든 사람이 C ++이나 Perl과 같은 문법적인 괴물을 필요로하는 것은 아닙니다.
amon

1
@RobertHarvey는 : 음주 잊지 constgoto자바에서 모두 예약어가 있지만 (아직) 사용되지 않습니다.
TMN
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.