프로그래밍 언어의 구문은 구현에 따라 달라 집니까?


12

내 질문은 전적으로 관련이 없지만 대부분의 프로그래밍 언어와 공식 구현 사이의 패턴을 느꼈습니다.

Python, Lua 등과 같은 해석 된 (바이트 해석 된) 언어는 일반적으로 매우 관대하고 쉬운 구문을 가지며 일반적으로 유형이 없거나 개발자가 소스 코드에 변수 유형을 명시 적으로 작성할 필요가 없습니다.

C, C ++, Pascal 등과 같은 컴파일 된 언어는 일반적으로 엄격한 구문을 가지며 일반적으로 유형이 있으며 대부분 더 많은 코드 / 개발 시간이 필요합니다

Java / C #과 같이 JIT 컴파일 된 공식 구현 언어는 일반적으로 위의 두 가지 기능 중 가장 뛰어난 기능을 갖춘 위의 두 언어 사이에서 고유 한 절충안입니다.

D 및 Vala (및 GNU GJC Java 구현)와 같은 최신 컴파일 된 프로그래밍 언어 중 일부는이 규칙에서 예외 일 수 있으며 Java 및 C #과 같은 JIT 컴파일 언어의 구문 및 기능과 유사합니다.

내 첫 번째 질문은 이것이 정말로 관련이 있습니까? 또는 이것은 대부분의 해석 언어가 쉬운 구문을 가지고 있으며 JIT 컴파일 언어는 적당한 구문과 기능 등을 가지고 있다는 우연의 일치 일뿐입니다.

둘째, 이것이 우연의 일치가 아니라면 왜 그렇습니까? 예를 들어, JIT 컴파일과 같은 일부 기능은 프로그래밍 언어로만 구현할 수 있습니까?


@YannisRizos 죄송합니다. 견적이 아닙니다. 나는 그것을 강조하고 싶었다. 편집하겠습니다.
ApprenticeHacker

1
쿨, 나는 인용이 아니지만 응답자가 그것이 하나라고 생각하고 반박하려고 시도하지 않거나 (맹목적으로 동의하지 않음) ... 유사한 패턴을 보았지만 불행히도 좋은 점은 없습니다 대답.
yannis

@ R.MartinhoFernandes 죄송합니다, 나는 그것을 몰랐습니다. 다시 편집하겠습니다.
ApprenticeHacker

4
Perl은 사용자 정의 유형에 대해 동적으로 유형이 지정되고, 배열, 해시, 스칼라 및 서브 루틴을 구별하는 것과 관련하여 정적으로 유형이 지정되며 엄격하고 해석되며 JIT 컴파일 을 사용하여 강력하게 유형이 지정됩니다 (물론 동시에 아님). 언어 디자인을 이해하기 위해 펄을 던지는 것은 언제나 재미있다 ...
yannis

3
"관심있는 구문"과 "엄격한 구문"의 의미는 무엇입니까? 그것들은 모두 공식적인 언어이며 구문 오류로 소스 코드를 실행하지 않습니다.
니키

답변:


17

시맨틱과 구문 간에는 아무런 관련이 없습니다. Scheme과 같은 Homoiconic 컴파일 언어에는 최소한의 구문이 있습니다. Forth와 같은 저수준 컴파일 메타 언어는 그보다 훨씬 간단합니다. 매우 엄격하게 형식화 된 컴파일 된 언어는 간단한 구문 (ML, Haskell)을 기반으로합니다. OTOH, 파이썬 구문은 많은 구문 규칙 측면에서 매우 무겁습니다.

그렇습니다. 타이핑은 구문과 아무 관련이 없습니다. C ++처럼 변질 된 것이 아니라면 모든 타이핑 정보를 사용할 수 없으면 구문 분석 할 수없는 한 언어의 의미 론적 측면에 있습니다.

일반적인 추세는 너무 오랫동안 진화하고 구문 편차에 대한 디자인 보호 기능을 포함하지 않은 언어는 조만간 구문 어 보미 네이션으로 발전한다는 것입니다.


+ "호모 닉"을 찾아주는 +1 ... 그리고 PHP에 대한 미묘한 끄덕임 ...
yannis

1
+1, 너무 오랫동안 발전해 왔으며 디자인 보호 기능이없는 언어는 델파이 / 오브젝트-파스칼과 관련이 있습니까?
ApprenticeHacker

1
@ThomasEding, 당신은 틀렸다. 구문이없는 언어 (Lisp 또는 Forth와 같은)를 사용하더라도 광범위한 구문 스타일 위에 동일한 의미를 구현할 수 있습니다. 매우 다양한 종류의 시맨틱과 동일한 구문을 사용할 수 있습니다. 예를 들어 C 및 Verilog 표현식의 구문은 거의 동일하지만 의미는 크게 다릅니다.
SK-logic

1
@ SK-logic-단지 복잡하고 Turing-complete가 프로그램 구문의 적어도 일부가 아니라는 것을 의미하지는 않습니다. 다양한 언어를 파싱하는 것은 Turing-complete이며, "구문과 관련이없는"것을 마술 적으로 파싱하지 않습니다. 구문은 "범위"에 관한 것이 아니라 언어의 문장 구조에 대한 규칙에 관한 것입니다. 타입 검사와 타입 추론은 실행하지 않고 프로그램의 구문 트리에서 작동합니다. 그들은 아무 말도하지 않고 프로그램의 구조에 대해 결정합니다.
Jack

1
@ 잭, 구문이 무엇인지 재정의하려고합니다. Turing-complete 파서가 필요한 실용적인 언어는 없으며 대부분 문맥이없는 언어입니다. 그리고 이것이 구문을 유지해야하는 곳입니다. 이 (이미 너무 뻗어있는) 개념을 다른 곳으로 확장하지 마십시오. 그리고 저는 Curry-Howard isomorphism에 대해 이미 언급했습니다. 이는 단순한 정확성 규칙을 훨씬 뛰어 넘는 의미론에 관한 것입니다. " type checking" 라는 용어 는 매우 비생산적이며 사용되어서는 안되며, 오해의 소지가 있으며 유형 시스템의 특성을 반영하지 않습니다.
SK-logic

6

대부분 이것은 우연의 일치입니다.

프로그래밍 언어는 시간이 지남에 따라 발전했으며 컴파일러와 인터프리터의 기술이 향상되었습니다. 기본 처리 플랫폼의 성능이 향상됨에 따라 기본 처리의 효율성 (예 : 컴파일 시간, 해석 오버 헤드, 실행 시간 등)도 덜 중요합니다.

언어 구문 영향을 미칩니다. 예를 들어, Pascal은 매우 신중하게 디자인되어 단일 패스 컴파일러를 사용할 수 있습니다. 즉, 소스를 통과하는 패스와 실행 가능한 머신 코드가 있습니다. 반면에 Ada는 이것에주의를 기울이지 않았으며, Ada 컴파일러는 쓰기 어려운 것으로 악명 높으며, 대부분 하나 이상의 패스가 필요합니다. (수년 전에 사용했던 아주 좋은 Ada 컴파일러는 8 패스 컴파일러였습니다. 상상할 수 있듯이 매우 느 렸습니다.)

Fortran (컴파일) 및 BASIC (통역 또는 컴파일)과 같은 오래된 언어를 보면 매우 엄격한 구문과 의미 규칙이 있습니다. [BASIC의 경우, Bills old BASIC이 아니라면, 그 전에 원래로 돌아 가야합니다.]

반면에 APL (재미 있음)과 같은 다른 오래된 것들을 살펴보면 역동적 인 타이핑이있었습니다. 또한 일반적으로 해석되었지만 컴파일 될 수도 있습니다.

관용구 문은 어려운 표현입니다. 만약 선택 사항이거나 추론 할 수있는 것들이 있다면 언어가 다듬을 수있을만큼 풍부함을 의미합니다. 그리고 다시, 베이직은 몇 년 전에 "LET"문장이 선택 사항이되었을 때였습니다!

현재보고있는 많은 아이디어 (예 : 무형식 또는 동적 타이핑)는 실제로 매우 오래되었습니다. 1970 년대 또는 1980 년대 초에 처음 등장했습니다. 그것들이 사용되는 방식과 이러한 아이디어가 사용되는 언어가 바뀌고 성장했습니다. 그러나 근본적으로 새로운 것의 많은 부분은 실제로 새로운 옷을 입은 오래된 것들입니다.

내 머리 꼭대기에 몇 가지 예가 있습니다.

  • APL : 동적 타이핑. 일반적으로 해석됩니다. 1960 년대와 1970 년대에왔다.
  • 기본 : 강력하거나 동적 인 타이핑. 해석되거나 컴파일되었습니다. 1970 년대와 그 이후의 많은 사람들.
  • 포트란 : 강력한 타이핑. 컴파일되었습니다. 1960 년대 또는 그 이전
  • Algol68 : 강력한 타이핑. 컴파일되었습니다. 1960 년대
  • PL / 1 : 강력한 타이핑. 컴파일되었습니다. 1960 년대
  • 파스칼 : 강력한 타이핑. 컴파일되었습니다. 1970 년대 (하지만 1980 년대에는 JIT 컴파일러와 매우 유사한 P- 시스템 컴파일러가있었습니다!)
  • 초기에 DEC에 의한 일부 포트란 및 일부 구현은 부분적으로 컴파일되고 부분적으로 해석되었다.
  • 스몰 토크 : 동적 타이핑. 해석되는 바이트 코드로 컴파일되었습니다. 1980 년대
  • 프롤로그 : 더 이상합니다. 기능의. 컴파일 (터보 프롤로그, 누구?). 1980 년대
  • C : 강한 (ha ha) 타이핑. 컴파일되었습니다. 1960 년대 .. 오늘.
  • 에이다 : 엄청나게 강한 타이핑. 컴파일되었습니다. 1980 년대
  • Perl : 동적 타이핑. (강한 구문). 해석되었습니다. 1990 년대 (?)

계속할 수있었습니다.

  • Nitpickers 코너 : 많은 인터프리터 언어는 소스를로드 / 읽을 때 토큰 화되거나 "바이트 컴파일"됩니다. 따라서 인터프리터의 후속 작업이 훨씬 간단 해집니다. 때로는 바이트 컴파일 버전의 코드를 저장할 수 있습니다. 때때로 당신은 할 수 없습니다. 여전히 해석됩니다.

업데이트 : 내가 명확하지 않았기 때문에.

타이핑은 크게 다를 수 있습니다.

컴파일 타임 고정 정적 타이핑이 일반적입니다 (예 : C, Ada, C ++, Fortan 등). 여기에서 TYPE의 THING을 선언하고 영원히 그렇게합니다.

할당 된 유형을 선택하는 동적 입력이 가능합니다. 예를 들어, PHP와 초기 BASIC 및 APL은 정수를 변수에 할당 한 다음 정수 유형이었습니다. 나중에 문자열을 할당 한 경우 문자열 유형입니다. 등등.

그런 다음 느슨한 입력 (예 : PHP)을 사용하여 변수에 숫자 정수 (따옴표로 묶은 문자열)를 할당 한 다음 숫자를 추가하는 것과 같은 기괴한 작업을 수행 할 수 있습니다. (예 : '5'+ 5는 10이됩니다). 이것은 기괴한 땅이지만 때로는 매우 유용합니다.

그러나 이것들은 언어로 설계된 기능입니다. 구현만으로도 가능합니다.


13
강력한 타이핑은 동적 타이핑의 대응이 아닙니다. 약한 타이핑의 대응입니다. 동적 타이핑의 반대 부분은 정적 타이핑입니다. 하나에서, 프로그램의 표현식 유형을 정적으로 알 수 있습니다 (즉, 프로그램을 실행하지 않고). 다른 유형에서는 유형을 동적으로 만 알 수 있습니다 (예 : 프로그램을 실행해야 함).
R. Martinho Fernandes

그렇습니다. 그리고 BASIC과 APL의 일부 변종은 1970 년대 후반에이 작업을 수행했습니다. APL 타입은 오늘날 우리가 이해하는 것과는 다릅니다 (범용 타입 정수 / 부동과 같은 것이지만 벡터, 문자열 및 다차원 매트릭스 일 수도 있습니다).
quick_now

포트란 해석기는 여전히 널리 사용됩니다 (Cernlib 및 PAW 참조). 그리고 그 자손 인 ROOT는 C ++ 인터프리터를 기반으로합니다.
SK-logic

솔직히 말해서, 강하고 약하고 정적 / 동적 타이핑이 구문과 어떤 관련이 있는지는 확실하지 않습니다. 그러나 답변의 질은 꽤 좋았 기 때문에 공짜를 피하고 있습니다. 클래스 C를 "정적 / 약한"으로 입력하는 클래스를 사용했습니다 (저장된 값이 다른 유형 인 것처럼 보이면 값이 잘못 될 수 있음).
Vagin

@Vatine-실제로 컴파일 타임에 강하고 런타임에는 존재하지 않는다고 말하고 싶습니다. 많은 언어에서 포인터와 그와 동등한 것을 사용하여 그렇게 할 수 있습니다. 변형 레코드를 사용하는 클래식 파스칼과 UNCHECKED_CONVERSION을 사용하는 Ada에서도 가능합니다 (어려울지라도 가능합니다).
quick_now

2

나는 그것이 다른 방법이라고 생각합니다 : 구현은 구문에 달려 있습니다. 예를 들어, 구문이 리플렉션을 허용하는 경우 구현시이를 지원하는 런타임을 제공해야합니다.


@IntermediateHacker :하지만 자바로되어있어서 정말 멋져요
sehe

2

나는 일반적으로 당신의 관찰이 주로 역사의 결과라는 점에서 quick_now에 동의합니다. 즉, 근본적인 추론은 다음과 같이 요약됩니다.

The more modern a language is, the more comfortable it should be to use.

(실제로 인용문이 아니라 내 자신의 공식입니다.) comfortable여기에 글을 쓸 때 나는 당신이 무엇을 부른 지 언급합니다 best features of both. 더 정확하게 말하면, 정적 / 동적 타이핑 또는 엄격하고 관용적 인 구문을 말하거나 반대하고 싶지 않습니다. 대신에, 언어로 작업 할 때 개발자에게 초점을 맞추고 편안함 수준을 높이는 것이 중요합니다.

이전 답변에서 언급되지 않은 몇 가지 이유가 있습니다. 이러한 이유는 이러한 것들을 관찰하는 이유에 대한 아이디어를 제공 할 수 있습니다 (그리고 프로그래밍 언어 개발의 역사를 기반으로 모든 종류).

  • 요즘에는 수백 개의 프로그래밍 언어가 있습니다. 새로운 사람이 나오면 어떻게 광범위한 청중을 찾을 수 있습니까? 이것이 새로운 언어가 항상 개발자의 안락함을 높이려고하는 주된 이유입니다. 언어가 이전 언어와 동일하게 할 수 있지만 훨씬 쉽고 간단하고 우아하게 할 수 있습니다. 실제로 전환하는 것을 고려할 수도 있습니다.

  • 학습 곡선은 그와 밀접한 관련이 있습니다. 과거에는 언어가 거의 없었으며 배우는 데 시간이 투자되었습니다. 비록 그것이 많은 시간을 투자하는 것을 의미하더라도. 개발자가 매우 빠르게 배울 수있는 언어를 생각해 내면 편안함이 다시 높아집니다. 모든 종류의 복잡성 (f.ex., 복잡한 관련 구문)은 이것에 해롭고, 따라서 새로운 언어에서는 점점 줄어 듭니다.

  • 기술 발전 (여기서 직접적인 역사적 이유)은 컴파일러 빌더가 이제 개발자 편의에 더 집중할 수있게하는 책임이 있습니다. 초기에, 우리는 컴파일러를 전혀 만들 수있어서 기뻤습니다. 그러나 이는 종종 엄격한 제한이 이루어지고 있음을 암시합니다. 기술 노하우가 증가함에 따라 이러한 제한을 다시 해제 할 수있었습니다.

따라서 일반적으로 프로그래밍 언어와 컴파일러는 일반적인 최종 사용자 응용 프로그램과 유사한 개발을 보았습니다.

  1. 초기 단계 : 멋진 기능이지만 최첨단 기술로 인해 편의성 / 사용성 / 불필요한 비용으로 작동하는 경우는 거의 없습니다.
  2. 기술 개선 : 이러한 것들을보다 강력하고 빠르고 쉽게 구축 할 수 있습니다.
  3. 사용자에게 초점을 맞 춥니 다. 사용자 경험에 중점을 둔 Web2.0 운동과 유사하게 새로운 프로그래밍 언어는 개발자의 관점에 중점을 둡니다.

(Not a quote really, just my own formulation.)글쎄, 당신은 인용 부호가 아닌 코드로 형식을 지정 했으므로 인용 한 사람이라고 생각하지 않습니다. :)
yannis

3
편의는 분명히 맛에 달려 있습니다 (항상 주관적 임). 내가 가장 편한 언어는 1959 년에 설계되었으며, 금세기에 등장한 일부 언어를 다루는 것은 불가능합니다.
SK-logic

1
편의는 또한 목적에 달려 있습니다. 세탁기 컨트롤러를 위해 8k 내장 마이크로에서 PHP 또는 Prolog를 실행하는 것은 "편리한"프로그램 일 수 있지만 실제로는 수용하기 쉬운 성능으로 적합하고 실행하기가 어렵습니다.
quick_now

0

주어진 프로그래밍 언어는 컴파일러가 런타임 결정을 추가하지 않고 실행 코드로 줄이는 방법을 추론 할 수있는 충분한 의미 정보를 노출하거나 제한하지 않을 수 있습니다 ( "이 변수는 어떤 유형입니까?"등). 일부 언어는 명시 적으로 만들어 지도록 설계되었습니다. 이 제약 조건은 필수이거나 결정하기 쉽습니다.

컴파일러가 더 똑똑 해짐에 따라 의사 결정을 폭로하거나 제한하도록 명시 적으로 설계되지 않은 언어의 경우에도 가장 가능성이 높은 경로에 대한 실행 코드를 생성하기에 충분한 정보를 추측하거나 프로파일 링 할 수 있습니다.

그러나 런타임에 코드 (evalString ())를 만들거나 입력 할 수있는 언어 (및 컴파일러가 추론하거나 추측 할 수없는 기타 언어)는 사전에 시도하더라도 런타임에 인터프리터 또는 JIT 컴파일러를 사용할 수 있어야합니다. 그것들을 컴파일하십시오.

과거에는 프로그래밍 언어와 그 구현이 인터프리터가 4k 또는 16k에 맞는지 또는 컴파일러가 1 분 미만의 CPU 시간 내에 완료되는지 여부와 같은 일부 하드웨어 제약 조건에 맞도록 발전했을 수 있습니다. 기계가 빨라질수록 프로그래머가 리턴 키를 누르거나 이전에 컴파일 된 프로그램 소스 코드를 약간 오래된 하드웨어가 최적화 된 컴파일 된 실행 파일을 실행할 수있는 것보다 빠르게 해석 할 수있을 정도로 이전에 해석 된 일부 프로그램을 (재) 컴파일 할 수있게되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.