for 루프에서 세미콜론과 쉼표가 서로 바뀌는 이유는 무엇입니까?


49

많은 언어 (C에서 JavaScript까지 광범위한 목록) :

  • 쉼표 ,별도의 인수 (예 func(a, b, c)) 동안
  • 세미콜론 ;은 순차적 명령어를 분리합니다 (예 :) instruction1; instruction2; instruction3.

그래서 왜이 매핑이 for 루프대해 동일한 언어로 반전 되었습니까 ?

for ( init1, init2; condition; inc1, inc2 )
{
    instruction1;
    instruction2;
}

대신 (나에게 더 자연스러운 것)

for ( init1; init2, condition, inc1; inc2 )
{
    instruction1;
    instruction2;
}

?

물론, for(보통) 함수가 아닌,하지만 인수 (즉 init, condition, increment) 더 일련의 지시 명령보다 함수의 인자처럼 행동.

역사적 이유 / 관습 때문입니까, 아니면 루프 ,와 인터체인지에 대한 좋은 근거가 ;있습니까?


1
(여기서 나의 첫 번째 게시물입니다.이 질문이 프로그래머 나 SO에 더 많은 것인지 확실하지 않으므로 필요한 경우 마이그레이션하십시오.)
Piotr Migdal

8
이것은 확실히 프로그래머 게시물입니다. 어서 오십시오! :-)
Martijn Pieters

1
"왜 그렇지 않은가?"는 같은 대답을함으로써 답을 제공 할 것입니다- "누군가가 선택을해야했기 때문에 그것이 선택한 것입니다." "왜 그들은"{ "와"} "을 선택한 이유와 1000 개의 다른 선택 – "때문에"
mattnz

2
@mattnz 문제는 일관성에 관한 것입니다 ( "왜 우리가 사용 ;하지 |않습니까?"(또는 왜 우리는 '그렇지 않은가'아닌 'else'를 사용합니까? )가 아님). 예를 들어 "C에서 while 루프의 속기로 작성되었고 (나중에 inc에 대한 여러 문장은 나중에 생각할뿐) 사람들은 프로그래머의 자극을 피하기 위해 그것을 바꾸고 싶지 않았다"는 대답은 완벽 할 것입니다.
Piotr Migdal

아마도 K & R에서 쉼표 연산자가 for 문의 init-expression에서 하나 이상의 변수를 초기화 할 수 있도록 원래 언어 추가되었다는 것을 기억합니다 .
zwol

답변:


18

따라서 동일한 언어에서 이러한 매핑이 for 루프에 대해 반대 인 이유는 무엇입니까?

기술적으로 매핑은 "역전되지"않습니다.

  • 쉼표로 구분 된 것은 매개 변수가 아닙니다. (적어도) C ++ 및 Java에서는 선언이 될 수 있으므로 표현식도 아닙니다.
  • 세미콜론으로 분리 된 것은 (단일) 진술도 아닙니다.

실제로 우리가 여기있는 것은 동일한 기호가 다르게 사용되는 다른 구문 적 맥락입니다. 우리는 like와 비교하지 않기 때문에 의미 적 일관성에 기반한 일관된 매핑에 대한 매핑이 없으며 강력한 논증이 없습니다.

그렇다면 다른 방법으로는 어떻습니까?

잘 나는 이유는 "자연"의 의미에서 오는 생각 ,하고 ;. 영어로 작성된 언어에서 세미콜론은 쉼표보다 "강력한"중단이며 세미콜론의 글리프는 쉼표보다 더 잘 보입니다. 이 두 가지가 결합하여 현재의 배열을보다 자연스럽게 보이게합니다.

그러나 구문 선택이 왜 이루어 진지 확실하게 알 수있는 유일한 방법은 C 설계자가 ~ 1970 년에 생각했던 것을 우리에게 말해 줄 수있는 것입니다. 나는 그들이 과거에 한 기술적 결정에 대한 명확한 기억을 가지고 있다고 의심한다.


역사적인 이유 / 협약 때문입니까?

"for"루프에 대해 C와 유사한 구문을 사용한 C 이전의 언어는 알지 못합니다.

  • Donal Fellows는 BCPL과 B는 동등한 구성을 가지고 있지 않다고 지적했다.

  • FORTRAN, COBOL 및 Algol-60 (및 Pascal) 등가물은 표현력이 낮았으며 C "for"구문과 유사하지 않은 구문을 가졌습니다.

그러나 C 다음에 나온 C, C ++ 및 Java와 같은 언어는 모두 C에서 "for"구문을 분명히 빌려줍니다.


따라서 ( ,vs ;) 의 철학은 ( 튜플 대 시퀀스 스플리터)보다는 (약한 대 강한 브레이크) 맞습니까? 아직도 나에게 논쟁이나 문장이 더 강한 나누기를 필요로하는지 여부는 분명하지 않지만 (문장 시퀀스의 경우 많은 경우와 같이 나누기가 암시 적입니다 (예 : JavaScript (예 :) i++[line break]j++참조)) 적어도 지금은 현재의 규칙에 대한 이유를 얻습니다 "분명히 반대로"되지 않습니다.
Piotr Migdal

@PiotrMigdal 쉼표를 구분 기호로 사용하면 쉼표 피연산자를 사용할 수 없으며 for 루프의 구성 요소가 표현식이 아니라 명령문임을 암시 할 수 있습니다. 이것은 중요한 의미를 갖습니다.

마지막 의견은 BCPL이 한 일에 대해 궁금해했지만 분명히 FOR i = e1 TO e2 BY e3 DO c(e1..e3 표현식, c 명령) BASIC의 구문과 더 닮았습니다. 출처
CVn

1
@PiotrMigdal- "철학"은 K & R과 1970 년에 다른 사람들이 생각했던 모든 것입니다. 나는 그것이 당신이 상상하는 생각의 깊이에 갔다고 생각하지 않습니다. (어셈블러에서 대량의 전화 스위치 소프트웨어를 작성하지 않아도되도록 "고수준"언어를 구현하려고했습니다.)
Stephen C

방금 확인했습니다. for구문 (이 아니었다 C에 도입 된 B 또는 BCPL).
Donal Fellows

60

우리는 다음과 같은 루프를 작성합니다.

 for(x = 0; x < 10; x++)

루프가 다음과 같이되도록 언어를 정의 할 수 있습니다.

 for(x = 0, x < 10, x++)

그러나 while 루프를 사용하여 구현 된 동일한 루프를 생각해보십시오.

 x = 0;
 while(x < 10)
 {
     x++;
 }

것을 주목 x=0하고 x++세미콜론으로 종료 문이다. 함수 호출에서와 같은 표현식이 아닙니다. 세미콜론은 명령문을 구분하는 데 사용되며 for 루프의 세 가지 요소 중 두 가지가 명령문이므로 여기에서 사용됩니다. for 루프는 그러한 while 루프에 대한 지름길입니다.

또한 인수는 실제로 함수에 대한 인수처럼 작동하지 않습니다. 두 번째와 세 번째는 반복적으로 평가됩니다. 그것들이 시퀀스가 ​​아니라는 것은 사실이지만 함수 인수도 아닙니다.

또한 쉼표를 사용하여 for 루프에 여러 명령문을 가질 수 있다는 사실은 실제로 for 루프 외부에서 수행 할 수있는 작업입니다.

x = 0, y= 3;

for 루프 외부에서도 완벽하게 유효한 명령문입니다. 그래도 for 루프 외부에서 실제로 사용하는 방법을 모르겠습니다. 그러나 요점은 쉼표는 항상 문장을 세분화한다는 것입니다. for 루프의 특별한 기능은 아닙니다.


물론, "while"루프가 "더 근본적"이라는 것을 알고 있습니다. 그러나 "짧은 표기법"은 x = 0; y = 0;(중괄호 안에서) 시작할 수 있기 때문에 (적어도 나에게는) 의미가 없습니다 x++; y++;...
Piotr Migdal

2
@PiotrMigdal, 당신은 할 수 있습니다. 내 요점은 for 루프 내부의 부분은 쉼표로 구분 된 표현이 아닌 문장 (세미콜론으로 구분)이며
Winston Ewert

1
나는 차이점을 얻는다. 나는 단지 진술;순서에 자연스럽고 어떤 진술도 분리 필요 는 없다 (따라서 맛이 다르다는 것입니까?) 그리고 현재 컨벤션에서 어쨌든 쉼표로 문장 시퀀스 를 분리하는 경우가 있습니다 .
Piotr Migdal

3
@PiotrMigdal, 구조체 / 연합의 멤버는 세미콜론으로 구분되지만 실제로는 순차적이지 않습니다. 따라서 그것은 사용중인 일련의 진술에 국한되지 않습니다. 하루가 끝날 무렵에는 문법이 맛으로 떨어집니다.
Winston Ewert

그래도 난 루프에 대한 외부의 어떤 실제 사용 모르겠어요 --- 방법에 대해 (foo)?bar++, qux++:bletch당신이 원하는 경우 --- ?:표현이 두 가지보다는 하나를 수행합니다. 경우 반환 값 foo사실입니다 qux만, 모두 bar와는 qux증가 얻을.

15

C 및 C ++에서 이것은 쉼표 만이 아니라 쉼표 연산자입니다.

for루프 문법 은 다음과 같습니다

for ([pre-expression]; [terminate-condition]; [increment-expression]) body-expression

질문이있는 경우 :

pre-expression -> init1, init2
terminate-condition -> condition
increment-expression -> inc1, inc2

쉼표 연산자를 사용하면 하나의 명령문에서 여러 작업을 수행 할 수 있습니다 (컴파일러가 보는 것처럼). 제안이 구현되면 프로그래머가 쉼표 연산자 문이나 구분 기호를 쓰려고 할 때 문법에 모호성이 있습니다.

한마디로, ;진술의 끝을 나타냅니다. for루프에 둘러싸여 옵션 문의 목록 다음에 키워드입니다 (). 쉼표 연산자 문을 사용하면 ,단일 문에서 사용할 수 있습니다 .


3
for 루프는 세미콜론으로 구분 된 표현식 세트입니다. 명령문은 표현식보다 훨씬 더 많을 수 있습니다. case 문이나 if 문을 for 루프 부분에 넣을 수 없습니다. for 루프의 bnf 형식을 for 루프의 형태로

@MichaelT : 그러나 C ++에서 for루프 구문은 명령문 (선언)을 첫 번째 부분으로 명시 적으로 허용합니다. (C ++은 이전 C89와 달리 함수 중반 선언을 허용했습니다). C 및 C ++에 가까운 2 개 언어의 경우에도 언어별로 이러한 문을 일반화 할 수 없습니다.
MSalters

@MichaelT '같은 것'부분을 놓치셨습니까?
James

@ 제임스 당신의 실제 BNF를 사용하여 "같은"을 피할 수 for ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>에 대한 Cfor ( for-init-statement; conditionopt ; expressionopt ) statement대한 C ++ --- ';' 명령문 종결자를 의미 할뿐입니다. for 루프 다음에는 ()로 묶인 명령문이 없습니다.

8

개념적 반전은 없습니다.

C의 세미콜론은 쉼표보다 더 큰 구분을 나타냅니다. 그들은 진술과 선언을 분리합니다.

for 루프의 주요 부분은 세 개의 표현식 (또는 선언과 두 개의 표현식)과 본문이 있다는 것입니다.

C for 루프에 표시되는 쉼표는 구체적으로 for 루프 구문의 일부가 아닙니다. 그것들은 단지 콤마 연산자의 표현 일뿐입니다.

쉼표는 함수 호출의 인수와 함수 선언의 매개 변수 사이의 주요 구분 기호이지만 세미콜론은 사용되지 않습니다. for 루프는 특별한 구문입니다. 함수 또는 함수 호출과 관련이 없습니다.


2

어쩌면 이것은 C / C ++에 특정한 것일 수도 있지만,이 답변을 게시합니다. 설명한 lagnuages의 구문은 대부분 C 구문에 영향을 받기 때문입니다.

이전에 답변 된 질문 외에도 기술적 인 관점에서 볼 때 C (및 C ++)에서는 쉼표가 실제로 연산자 이기 때문에 오버로드 할 수 있기 때문 입니다. operator;()세미콜론은 axiomatic expression terminator이므로 세미콜론 연산자 ( )를 사용하면 컴파일러를 작성하기가 더 어려워 질 수 있습니다.

이것이 intersting을 만드는 것은 쉼표가 널리 사용되는 것이 사실이다 구분자 모든 언어 이상. 쉼표 연산자가 예외 인 것처럼 보입니다. 주로 for여러 조건이 작동하는 루프 를 얻는 데 사용 되므로 거래는 무엇입니까?

실제로는 operator,정의, 인수 목록 등에서와 동일한 작업을 수행하도록 작성되었습니다. 구문 을 분리 하기 위해 작성되었습니다 . 구문 구문이 ,할 수없는 것입니다. 표준에 정의 된 내용 만 분리 할 수 ​​있습니다.

그러나 세미콜론은 분리되지 않으며 종료됩니다 . 그리고 이것은 또한 우리를 원래의 질문으로 되돌려 놓는 것이기도합니다.

for (int a = 0, float b = 0.0f; a < 100 && b < 100.0f; a++, b += 1.0f)
    printf("%d: %f", a, b);

쉼표는 세 개의 루프 부분에서 표현식을 분리하지만 세미콜론은 루프 정의의 일부 (초기화, 조건 또는 사후 고려)를 종료합니다.

C #과 같은 최신 프로그래밍 언어는 쉼표 연산자 오버로드를 허용하지 않을 수 있지만 구문을 변경하는 것은 부자연 스럽습니다.


이 주장에 문제가 있습니다. A의 for선언문 ;심볼 명백히 세퍼레이터로서 사용된다. 성명서의 세 가지 구문 부분을 구분합니다. 점진적 표현 목록을 "종료"하는 세 번째 세미콜론은 없습니다. 다른 토큰 (-)으로 종료됩니다 ).
Stephen C

0

저에게는 언어 적 의미와 덜 유사한 의미로 사용됩니다. 쉼표는 목록과 세미콜론과 함께 별도의 부품으로 사용됩니다.

여기에는 func(a, b, c)인수 목록이 있습니다.

instruction1; instruction2; instruction3 어쩌면 별도의 독립적 인 명령 목록 일 수도 있습니다.

에있는 동안 for ( init1, init2; condition; inc1, inc2 )초기화, 조건의 목록과 증가 표현의리스트 - 우리는 별도의 세 가지 부분이있다.


0

가장 쉽게 볼 수있는 방법은 다음과 같습니다.

for(x = 0; x < 10; x++)

입니다 :

for(
x = 0;
x < 10;
x++
)

다시 말해서, x = 0 인 것은 실제로 매개 변수가 아닌 설명 / 명령입니다. 거기에 진술을 삽입하십시오. 따라서 세미콜론으로 구분됩니다.

실제로 쉼표로 구분되는 방법은 없습니다. x <10과 같은 것을 매개 변수로 언제 마지막으로 삽입합니까? x <10을 한 번 컴퓨터에 넣고 해당 작업의 결과를 매개 변수로 삽입하려는 경우에 수행합니다. 따라서 쉼표 세계에서는 x <0 값을 함수에 전달하려면 x <10을 넣습니다.

여기서 루프가 전달 될 때마다 프로그램이 x <10을 확인하도록 지정합니다. 그것은 지시입니다.

x ++는 확실히 또 다른 지침입니다.

이것들은 모두 지침입니다. 그래서 그들은 세미콜론으로 구분됩니다.


진술이 아닙니다. 세미콜론으로 구분 된 표현식입니다. 진술은 완전히 다릅니다.

x <10은 표현식 일 수 있습니다 (일반적으로 세미콜론으로 구분됨). x = 0은 분명히 진술 / 지시입니다.
user4951

상기 봐 C에 대한 BNF - (가) 루프이었다 문에, 하나는 서로 다른 문을 사용할 수있는 경우 for switch또는 return 내부 (가) 루프 정의 (IE 용 for(int i = 0; if(i > 1024) { return; } ; switch (i % 3) { case 0; case 1: i++; case 2: i++; } ) { ... }) --- 당신은 할 수 있습니다. 진술이 아닙니다. 대신 다음과 같이 정의됩니다for ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>

이상한. int i = 0은 괜찮은 식이지만, 주로 int 즉, i를 선언하고 0을 할당하기 위해 수행합니다 (0도 반환하지만 부작용은 없습니다. for ({int i = 0; j = i}; j <0; cout << "Hello world") 할 수 있습니까?
그렇습니다

1
@JimThio : 당신은 아마 그것을 알지 못하지만 "statement"와 "expression"은 언어 표준에서 매우 정확한 의미를 갖습니다. int i = 0분명히 표현이 아닙니다. 표현식을 설명 할 수있는 규칙 세트는 표현식을 구성 할 수있는 항목을 고려하면 상당히 복잡하지만 구성 TYPE NAME = EXPRESSION은 해당 규칙과 일치하지 않습니다.
MSalters
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.