대부분의 프로그래밍 언어가 블록 주석을 중첩하지 않는 이유는 무엇입니까?


18

내가 아는 한 인기있는 것은 아니지만 몇 가지 있습니다. 주석을 중첩시키는 데 나쁜 점이 있습니까?

나는 작업중 인 (작은) 언어로 블록 주석을 중첩 할 계획이지만 이것이 나쁜 생각인지 알고 싶습니다.


몇 가지 답변을 다시 : 오, 그건 말이됩니다 =) 나는 완전히 중첩 된 블록 주석을하고 있습니다; 별도의 렉싱 단계가 있지만 SK-logic이 설명하는 제한적인 종류는 아닙니다.

@Vuntic : 정규식보다 복잡한 것을 사용하는 별도의 렉싱 단계가있는 경우 성능 문제가있을 수 있습니다. RE는 DFA를 구현하여 빠르고 사용하기 쉽습니다.
David Thornley

중첩을 허용하지 않기 위해 더 많은 오류가 발생합니다.

4
@David : ... 아직 아닙니다. 실제로 정말 빠릅니다.
amara

중첩 된 주석을 허용하려면 시작 주석 태그에 토큰을 표시 할 수 있으며 시작 주석 태그가 표시된 경우 종료 주석 태그를 동일하게 표시해야합니다. 이렇게하면 불균형 시작 / 종료 태그를 신속하게 식별 할 수 있으며 감지되지 않은 불균형 태그로 인한 버그 가능성을 피할 수 있습니다.
supercat

답변:


6

아무도 언급하지 않은 한 가지 사항에 대해 언급하겠습니다. 주석을 중첩하려는 욕구는 종종 프로그래머가 잘못하고 있음을 나타냅니다.

먼저, 프로그래머가 "중첩"또는 "중첩하지 않음"을 볼 수있는 유일한 시간은 프로그래머가 다음과 같은 구조적으로 무언가를 작성할 때입니다.

do_something();
/* comment /* nested comment */ more comment */
do_something_else();

이제 언제 그런 일이 실제로 발생합니까? 분명히 프로그래머는 문자 그대로 위의 스 니펫처럼 보이는 중첩 된 주석을 작성하지 않을 것입니다 ! 아니요, 실제로 주석을 중첩 할 때 (또는 중첩 할 수 있기를 원하는 경우) 다음과 같이 작성하기 때문입니다.

do_something();  /* do a thing */
/* [ajo] 2017-12-03 this turned out to be unnecessary
do_something_else(); /* do another thing */
*/

그리고 이것은 나쁜 것입니다. 이것은 (언어 디자이너로서) 우리가 권장하고 싶은 패턴이 아닙니다! 올바른 위의 코드 조각을 작성하는 방법은 다음과 같습니다

do_something();  /* do a thing */

"잘못된"코드, 잘못된 시작 또는 코드가 코드베이스에 속하지 않습니다. 소스 제어 히스토리에 속합니다. 이상적으로는 시작하기에 잘못된 코드를 작성하지 않아도됩니다. 그리고 잘못된 코드가 거기에 목적을 제공했다면 어떤 이유로 든 유지 보수 관리자에게 코드를 복원하지 말라고 경고함으로써 잘 작성된 의도적 코드 주석에 대한 작업 일 것입니다 . X를 수행하지만 주석 처리 된 일부 오래된 코드를 남겨 두어 "X를 수행하지 않음"을 표현하는 것은 사람들이 X를하지 못하게하는 가장 읽기 쉽고 효과적인 방법이 아닙니다.

이 모든 것은 이전에 들었던 간단한 경험 법칙으로 요약됩니다 . 코드를 주석 처리하지 마십시오. (업집니다이 구절을 검색 하시나요 많은 의견 계약을 .)

질문하기 전에 : 그렇습니다. C, C # 및 C ++와 같은 언어는 이미 프로그래머에게 큰 코드 블록을 주석 처리하는 다른 도구를 제공합니다 #if 0. 그러나 이것은 C 전 처리기의 특정 응용 프로그램이며, 그 자체로는 크고 유용한 도구입니다. 언어가 조건부 컴파일을 지원 #if하지만 아직 지원 하지 않는 것은 실제로 매우 어렵고 특별한 경우 #if 0입니다.


따라서 우리는 중첩 된 주석이 프로그래머가 코드를 주석 처리 할 때만 관련이 있다는 것을 확인했습니다. 우리는 코드를 주석 처리하는 것이 나쁜 것임을 (많은 숙련 된 프로그래머의 합의를 통해) 확립했습니다.

실로를 완성하려면 언어 디자이너가 좋은 것을 홍보하고 나쁜 것을 억제하는 데 관심이 있음을 인정해야합니다 (다른 모든 것이 동일하다고 가정).

중첩 된 주석의 경우 다른 모든 항목 동일합니다. 중첩 된 구문 분석이 구문 /*분석기에 대해 "어려울 것" 이라고 주장하는 투표가 적은 답변은 무시 해도됩니다. (Nested /*는 nested보다 어렵지 않으며 (, 세계의 거의 모든 파서가 이미 처리해야합니다.)

언어 디자이너가 주석을 쉽게 중첩 시키거나 (코드 주석 처리) 어렵게해야합니까? 코드 주석 처리는 나쁜 것임을 상기하십시오.

QED


각주. 중첩 된 주석을 허용하지 않으면

hello /* foo*/bar.txt */ world

오해의 소지가있는 "댓글"입니다.

hello bar.txt */ world

(구문 오류 일 수 있음). 당신이한다면 중첩 된 댓글은 허용

hello /* foo/*.txt */ world

오해의 소지가있는 "댓글"입니다.

hello

그러나 주석은 파일 끝까지 계속 열어 둡니다 (이것은 구문 오류 일 것입니다). 따라서 의도하지 않은 구문 오류가 발생하기 쉽습니다. 유일한 차이점은 주석 처리 된 코드 의 의도적 인 반 패턴을 처리하는 방법 입니다.


1
나는 단순한 사실에 근거하여 다른 의견을 가지고 있습니다. 나는 모든 것을 보지 못했습니다 (그리고 당신도 보지 못했습니다). 따라서 "코드 주석 처리 안 함"과 같은 황금률 규칙은 멋지게 보이지만 인생에는 고유 한 경로가 있습니다. 이 특별한 경우, 나는 새로운 기능을 테스트하고 점차적으로 코드를 소개해야 할 때 스위치처럼 자주 사용하므로 코드를 주석 처리 한 다음, 더 적고 덜 작게하고 마지막으로 작업 조각을 가지고 있습니다. 모든 주석을 제거 할 수 있습니다 (코드 이상). 내 완벽한 언어는 물론 중첩 된 주석을 지원할 것입니다 :-).
greenoldman

@greenoldman : 대부분의 언어에는 중첩 가능한 주석이 없지만 "코멘트 남기기"기능보다 덜 사용되는 "코드 블록 제거"에 대한 실제 기능이 있습니다. C #if DEAD는 정식적이고 가장 잘 설계된 예입니다. 많은 언어에서 데드 코드를와 동등한 것으로 감쌀 수 있습니다 if (DEAD). 그리고 많은 IDE에서 실제로 죽은 코드를 제거하고 원하는 경우 Ctrl + Z 및 / 또는 버전 제어를 사용하여 다시 가져올 수 있습니다. 텍스트가 많은 데드 코드 인 주석을 남기는 것은 여전히 가독성에 대한 최악의 옵션입니다.
Quuxplusone

11

대부분의 구현은 별도의 렉싱 및 구문 분석 단계를 사용하고 렉싱에는 일반 오래된 정규 표현식을 사용합니다. 주석은 공백으로 처리됩니다. 즉, 무시 된 토큰이므로 완전히 렉싱 패스에서 해결해야합니다. 이 방법의 유일한 장점은 구문 분석 속도입니다. 다수의 단점은 구문에 대한 심각한 제한 (예를 들어, 문맥에 독립적 인 고정 된 키워드 세트를 유지해야 할 필요성)을 포함한다.


3
나는 요즘 '가장 많이'에 동의하지 않을 것입니다. 확실히 그것은 전통적인 방법이지만, C의 경우 EDG는 전 처리기, 렉싱 및 파싱을 결합한다는 것을 알고 있으며 GCC와 Microsoft도 마찬가지입니다. 필요한 경우 별도로 구현할 수 있다는 이점이 있습니다.
Andrew Aylett

Clang도 마찬가지입니다. 그러나 그것은 여전히 ​​기존의 인기있는 언어 컴파일러의 작은 비율입니다.
SK-logic

@ Neil Butterworth는 mcs, javac, gcc (여기서는 lexer를 다시 패치하지만 여전히 전용 lexing pass입니다), clang (gcc와 동일), dmd, fpc 등을 살펴보십시오.
SK-logic

사소한 컴파일러에 대해 정규 표현식을 사용하는 사람은 없습니다.
Nuoji

@Nuoji-사소하지 않습니다. 그러나 플렉스 및 유사한 도구에 의존하는 사람들은 그렇게합니다.
SK-logic

7

중첩 된 주석을 처리 할 수있는 어휘 분석기를 만드는 것이 가능합니다. 공백을 먹으면 /*깊이 카운터를 늘리고을 볼 때 감소 */시키고 깊이가 0이면 멈출 수 있습니다. 즉, 나는 많은 파서를 수행했으며 주석이 중첩되어야하는 좋은 이유를 찾지 못했습니다.

주석이 중첩 될 수 있다면 단점은 균형을 잡기가 쉽습니다. 멋진 편집기가 없으면 보이지 않는 코드를 보이지 않게 숨길 수 있습니다.

중첩되지 않은 주석의 장점은 다음과 같습니다.

/*
some code
more code
blah blah blah
/**/

첫 줄 (1 줄 편집)을 제거하거나 추가하여 코드에 쉽게 주석을 달거나 넣을 수 있습니다. 물론 코드 자체에 주석이 포함되어 있으면 C ++ 스타일 주석 도 허용 하지 않으면 중단 //됩니다. 그래서 제가하는 경향이 있습니다.


1
//주석도 C99 스타일입니다.
JAB

또는 언어에서 주석 시작을 지정할 수 있습니다 /*$token. 여기서 identifier영숫자 토큰은 어디에 있고 주석은입니다 token$*/. 토크 나이저가 모든 종료 주석 표시에 일치하는 시작 주석 블록에 적합한 토큰이 포함되어 있는지 확인하는 코드를 포함하는 것은 비교적 간단합니다.
supercat

5

아무도 언급하지 않았기 때문에 중첩 된 주석을 지원하는 몇 가지 언어 (Rexx, Modula-2, Modula-3, Oberon)를 나열하겠습니다. 난이도와 속도 문제에 대한 모든 불만 사항에도 불구하고 큰 문제는없는 것으로 보입니다.


4
내가 추가하는 것 : Haskell, Frege
Ingo

스칼라도 지원합니다.
Matt R

4

블록 주석을 중첩시키는 좋은 점은 코드의 많은 부분을 쉽게 주석 처리 할 수 ​​있다는 것입니다 (문자열 상수에 블록 주석 종료 시퀀스가없는 한).

다른 방법은 라인 주석 시작 시퀀스를 지원하는 편집기가있는 경우 라인 주석 시작 순서로 여러 줄을 추가하는 것입니다.

하스켈은 블록 주석을 내포하고 있지만 대부분의 사람들은 이에 대해 눈치 채거나 불평하지 않는 것 같습니다. 중첩 된 주석을 기대하지 않는 사람들은 다른 언어의 어휘 오류 일 수 있으므로 주석을 피하는 경향이 있기 때문입니다.


3

중첩 된 블록 주석을 지원하면 구문 분석기가 복잡해 지므로 더 많은 작업이 수행되고 컴파일 시간이 늘어날 수 있습니다. 언어에 필요한 기능은 아니지만 다른 개선 및 최적화에 시간과 노력을 사용하는 것이 좋습니다.

내 생각에 단순성은 항상 디자인하는 데 좋은 것입니다. 기능을 제거하는 것보다 기능을 추가하는 것이 더 쉽다는 점에 유의하십시오. 중첩 된 주석을 허용하고 해당 주석을 사용하는 프로그램이 있으면 호환성을 손상시키지 않으면 서 주석을 제거 할 수 없습니다.


1
"기능을 제거하는 것보다 더 쉽게 추가 할 수 있음"+1
R ..

3
중첩 된 주석을 허용하지 않으면 해당 주석을 깨뜨리기 때문에이를 허용 할 수 없습니다./*/**/
RiaD

2

어휘 분석기에서 일반적으로 사용되는 정규 표현식의 풍미가 재귀를 지원하지 않기 때문에 중첩 된 주석은 구문 분석기가 처리해야하는 이유 중 하나입니다. 간단한 것들은 렉서에 의해 공백으로 제거 될 수 있으므로, 그렇게 구현하는 것이 더 간단합니다.


3
"맛"이 아닙니다. 정규식에서 "일반"이라는 단어는 본질적으로 재귀를 제외합니다.
R ..

3
@R : 수학 에서요. 그러나 프로그래밍에는 재귀를 지원하는 정규식이라고하는 것이 있습니다.
amara

문제는 이것입니다. 심지어 문제입니까? 대부분의 언어는 이미 중첩 괄호를 처리해야합니다. Lisp, C, Java, Python, Ruby, Perl 등이 있습니다.
Thomas Eding

괄호 안에있는 것은 외부 토큰과 동일하기 때문에 중첩 된 괄호는 좋습니다. 일반 토큰. 주석에는 토큰이 없으며 텍스트 만 있습니다. 'int'가 주석의 유형인지 또는 단어의 단어인지 알 수 있도록 시작 및 종료 주석 토큰과 일치시킬 수 있어야합니다. (특히 어휘 분석기에서 주석을 제거하는 경우)
Alan Shutko

2
@ThePopMachine : 내가 말한 것이 확실합니다. 정규식에는 사용하는 의미가 아닌 정의 된 형식적 의미가 있으며, "정규 표현"의 "정규"는이 의미로 선택되었습니다. 비 재귀 적이라는 것은 그 정의의 결과 중 하나입니다.
R ..

-1

누가 알아? 중첩 된 주석을 지원하는 것이 더 효과적이기 때문에 추측 할 것입니다. 어떤 종류의 스택을 유지해야하고 언어 문법이 복잡하기 때문입니다.


-1

중첩 된 주석은 파서에 대한 추가 작업을 의미합니다. 일반적으로 주석의 시작을 보면 끝 주석 표시까지 모든 것을 무시합니다. 중첩 된 주석을 지원하려면 주석의 텍스트도 구문 분석해야합니다. 그러나 가장 큰 문제는 프로그래머가 중첩 된 모든 주석을 올바르게 닫을 때주의해야하며 그렇지 않으면 컴파일 오류가 발생한다는 것입니다. 컴파일러를 올바르게 구현하는 것은 수행 할 수 있지만 프로그래머로서 중첩 된 주석을 추적하는 것은 오류가 발생하기 쉽고 자극적입니다.


3
-1 : 사실이 아닙니다. Sane 파서는 그렇게 작동하지 않습니다.
amara
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.