현대식 프로그래밍 언어에서 왜 타입이 변수 이름 뒤에 오는가?


57

거의 모든 현대 프로그래밍 언어 (Go, Rust, Kotlin, Swift, Scala, Nim, Python last version)에서 유형이 항상 변수 선언에서 변수 이름 뒤에 오는 이유는 무엇입니까?

왜 x: int = 42그렇지 int x = 42않습니까?
후자는 전자보다 더 읽기 쉽지 않습니까?
트렌드 일까, 아니면이 솔루션 뒤에 정말 의미있는 이유가 있습니까?


10
가능한 중복 Kotlin
— 8bittree

3
그래, 그게 속임수 야. 코 틀린 언어를 구체적으로 언급하고 있지만, 질문과 답변은이 연습을하는 모든 언어에 적용됩니다.
— Robert Harvey


2
죄송합니다. 인터넷 검색을 할 때 Kotlin에 대한 질문을 보았지만 "Kotlin (Go, Rust, ...) dev 팀이 이와 같이 결정했기 때문에"와 같은 답변을받지 않기 위해 다시 질문했습니다. 나는 더 일반적인 대답에 관심이있었습니다. 왜 전염병이됩니까?
— Andre Polykanine

2
Hihi, 그래서 (Object) Pascal이며 Delphi는 창세기 이래로 변수 이름 뒤에 유형 을 가졌습니다 . 이전 세기의 어두운 시대에 다시 현대적입니다.) 사용. var 이름 앞에 C #이있는 델파이에서 C #을 사용하면 꽤 오랫동안 내 머리를 두들 겼습니다.
— Marjan Venema

답변:


64

언급 한 모든 언어는 형식 유추를 지원 합니다. 즉 , 유형이 쉽게 결정되는 유형의 초기화 표현식을 제공 할 때 자체적으로 입력 할 수 있기 때문에 유형이 해당 언어로 선언의 선택적 부분입니다 .

표현식의 선택적 부분을 오른쪽으로 더 멀리 배치하면 구문 분석 모호성이 줄어들고 해당 부분을 사용하는 표현식과 사용하지 않는 표현식 사이의 일관성이 향상되기 때문에 중요합니다. var선택 사항에 도달하기 전에 키워드와 변수 이름이 모두 필수 인 것을 알면 선언을 구문 분석하는 것이 더 간단합니다 . 이론적으로, 컴퓨터가보다 쉽게 분석 할 수 있도록 그 모든 것들을 해야 너무 인간에 대한 전반적인 가독성을 향상,하지만 더 많은 논쟁의 여지가있다.

당신과 같은 C ++와 같은 "비 현대적인"언어가 모든 옵션 유형 수정, 고려할 때이 인수는 특히 강력한 얻는다 *포인터를 들어 &, 참조를 들어 const, volatile등등. 여러 선언에 쉼표를 넣으면 포인터를 int* a, b;만들지 않는 것과 같은 이상한 모호한 점이 생깁니다 b.

심지어 C ++는 지금의 형태로 선언 "오른쪽 유형"을 지원 auto x = int{ 4 };하고, 그것은 몇 가지 장점을 가지고있다 .


2
+1 var구문 분석 단순화를 제공하는 것과 같은 필수 키워드의 존재를 인정하여 +1 .
— 8bittree

2
var키워드 의 존재가 이름 우선 표기법의 목적을 무효화 하지 않습니까? 나는 쓰기의 장점이 표시되지 않습니다 var userInput: String = getUserInput()이상을 String userInput = getUserInput(). 이점은 userInput = getUserInput()허용되는 경우에만 관련 이 있지만 범위 변수의 암시 적 선언을 의미합니다.
— kdb

2
C # 및 C ++와 같은 언어에서 @kdb는 var userInput = getUserInput()또는입니다 auto userInput = getUserInput(). 컴파일러는 getUserInput()반환 값을 알고 String있으므로 type deduction 키워드로이를 지정할 필요가 없습니다. userInput = getUserInput()물론 선언하기 전에 사용됩니다.
— Wes Toleman

32

거의 모든 현대 프로그래밍 언어 (Go, Rust, Kotlin, Swift, Scala, Nim, 심지어 Python 마지막 버전)에서 유형이 항상 변수 선언 이후에 오는 이유는 무엇입니까?

전제는 두 가지 측면에서 결함이 있습니다.

  • 식별자 앞에 유형이있는 새로운 프로그래밍 언어가 있습니다 . 예를 들어 C♯, D 또는 실론입니다.
  • 식별자 뒤에 유형이있는 것은 새로운 현상이 아니며, 적어도 Pascal (1968-1969 년에 발표 된 1970 년에 발표)로 돌아가지만 실제로는 수학 유형 이론에 사용되어 ~ 1902에서 시작합니다. ML (1973), CLU (1974), Hope (1970s), Modula-2 (1977–1985), Ada (1980), Miranda (1985), Caml (1985), Eiffel (1985), Oberon에서도 사용되었습니다. (1986), Modula-3 (1986-1988) 및 Haskell (1989).

Pascal, ML, CLU, Modula-2 및 Miranda는 모두 매우 영향력있는 언어 였으므로 이러한 유형의 선언이 인기를 유지 한 것은 놀라운 일이 아닙니다.

왜 x: int = 42그렇지 int x = 42않습니까? 후자는 전자보다 더 읽기 쉽지 않습니까?

가독성은 친숙한 문제입니다. 개인적으로 중국인은 읽을 수 없지만 중국인은 읽을 수없는 것으로 보입니다. 학교에서 파스칼을 배우고, 에펠, F♯, 하스켈, 스칼라를 습격하고 TypeScript, Fortress, Go, Rust, Kotlin, Idris, Frege, Agda, ML, Ocaml 등을 살펴보면… .

그것은 단지 추세일까요, 아니면 그러한 해결책 뒤에 정말로 의미있는 이유가 있습니까?

그것이 추세라면, 그것은 꽤 영속적입니다. 제가 언급했듯이, 수학에서 백 년 전으로 거슬러 올라갑니다.

식별자 다음에 유형을 갖는 주요 이점 중 하나는 유추하려는 경우 유형을 쉽게 제외 할 수 있다는 것입니다. 선언이 다음과 같은 경우 :

val i: Int = 10

그런 다음 유형을 생략하고 다음과 같이 추론하는 것이 쉽지 않습니다.

val i = 10

반면에 타입이 식별자 앞에 오는 경우 :

Int i = 10

그런 다음 구문 분석기가 표현식을 선언과 구별하기가 어려워집니다.

i = 10

언어 디자이너가 일반적으로 생각하는 해결책은 유형 대신 작성해야하는 "유형을 작성하고 싶지 않습니다"키워드를 소개하는 것입니다.

var  i = 10; // C♯
auto i = 10; // C++

그러나 이것은 실제로 의미가 없습니다. 기본적으로 유형을 쓰지 않는다는 유형을 명시 적으로 작성해야합니다. 응? 그냥 빼는 것이 훨씬 쉽고 합리적이지만 문법이 훨씬 복잡해집니다.

(그리고 C의 함수 포인터 타입 에 대해서도 이야기하지 않겠 습니다.)

앞서 언급 한 여러 언어의 설계자들이이 주제에 무게를 두었습니다.

  • Go FAQ (참조 : Go 's Declaration Syntax ) :

    왜 선언이 거꾸로됩니까?

    C에 익숙하다면 그것들은 거꾸로되어 있습니다. C에서, 변수는 타입을 나타내는 표현식처럼 선언됩니다. 좋은 생각이지만, 타입과 표현식 문법은 잘 섞이지 않습니다. 결과는 혼란 스러울 수 있습니다. 함수 포인터를 고려하십시오. Go는 대부분 식과 형식 구문을 분리하며 사물을 단순화합니다 ( *포인터에 접두사 를 사용 하는 것은 예외입니다). C에서 선언

    int* a, b;
    

    a포인터로 선언 하지만 그렇지 않습니다 b. 이동 중

    var a, b *int
    

    둘 다 포인터로 선언합니다. 이것은 더 명확하고 규칙적입니다. 또한, :=짧은 고지서 전체 변수 선언과 같은 순서를 제시한다고 주장 :=때문에

    var a uint64 = 1
    

    같은 효과가 있습니다

    a := uint64(1)
    

    또한 표현 문법이 아닌 유형에 대해 고유 한 문법을 ​​사용하여 구문 분석을 단순화 할 수 있습니다. 같은 키워드 func와는 chan명확하게하기.

  • 코 틀린 FAQ :

    왜 타입 선언이 오른쪽에 있습니까?

    코드를 더 읽기 쉽게 만든다고 생각합니다. 게다가, 그것은 좋은 구문 기능을 가능하게합니다. 예를 들어, 타입 주석을 남기기 쉽습니다. 스칼라는 또한 이것이 문제가되지 않는다는 것을 잘 증명했다.

  • 스칼라 프로그래밍 :

    Java와의 주요 편차는 유형 주석의 구문과 관련이 있습니다. Java에서 " variable: Type"대신 " Type variable"입니다. 스칼라의 접미사 유형 구문은 Pascal, Modula-2 또는 Eiffel과 유사합니다. 이 편차의 주된 이유는 유형 유추와 관련이 있으며, 종종 변수의 유형 또는 메소드의 반환 유형을 생략 할 수 있습니다. " variable: Type"구문을 사용하면 이 작업이 쉬워집니다. 콜론과 유형은 그대로 두십시오. 그러나 C 스타일 " Type variable"구문에서는 단순히 유형을 생략 할 수 없습니다. 더 이상 정의를 시작하기위한 마커가 없습니다. 누락 된 유형 (일부 유형 유추를 수행하는 C♯ 3.0, var이 목적으로 사용)에 대한 자리 표시자가 되려면 대체 키워드가 필요합니다 . 이러한 대안 키워드는 스칼라의 접근 방식보다 임시적이고 덜 규칙적입니다.

참고 : Ceylon의 설계자들은 접두사 유형 구문을 사용하는 이유를 문서화했습니다 .

접미사 유형 주석 대신 접두사

왜 파스칼과 ML 대신 선언 이름 뒤에 주석을 달 때 C와 Java를 따라 유형 주석을 먼저 넣습니까?

우리는 이것을 생각하기 때문에 :

shared Float e = ....
shared Float log(Float b, Float x) { ... }

이것보다 훨씬 쉽게 읽을 수 있습니다.

shared value e: Float = .... 
shared function log(b: Float, x: Float): Float { ... }

그리고 우리는 다른 사람이 어떻게 다르게 생각할 수 있는지 이해하지 못합니다!

개인적으로, 나는 그들의 "인수"가 다른 사람들보다 훨씬 더 설득력이 있다고 생각합니다.


4
유형을 생략 할 수있는 능력이 보인다 여전히 간단한 구문 분석의 추가에 의해 부여가 var, auto, let없는 유형 선언이 켜져 변수의 어느면으로,, 등이있다. var Int x = 5또는 Int var x = 5둘 다 단축 될 수 있습니다 var x = 5.
— 8bittree

5
일단 익숙해지면 선택 가능한 유형 인수가 강력하면 IDE가 유형을 기반으로 변수 이름을 자동으로 제안 할 수 없다는 것을 지적하고 싶습니다. TypeScript를 작성할 때 나는 그것을 그리워합니다.
— Pierre Henry

"Your premise is flawed on two fronts" 이 모든 것이 C # 또는 D보다 최신입니다.
— Det

3
"그러나 이것은 실제로 의미가 없습니다. 기본적으로 타입을 쓰지 않는다는 타입을 명시 적으로 작성해야합니다." 글쎄, 올바른 형식의 버전은 귀하의 예에서 정확히 동일합니다 ... 또한 이해가되지 않는다는 것에 동의하지 않습니다. funcGo에서 와 똑같이 의미가 있습니다.
— 소펠

4

파스칼도 그렇게하고 새로운 언어는 아닙니다. 그것은 처음부터 고안된 학문 언어였습니다.

변수 이름으로 시작하는 것이 의미 적으로 더 명확하다고 말하고 싶습니다. 유형은 기술적 인 세부 사항입니다. 실제 모델과 같은 클래스를 읽고 싶다면 엔티티의 이름을 먼저 지정하고 기술적 구현을 ​​마지막에 배치하는 것이 좋습니다.

C #과 Java는 C에서 유래하므로 "선행 기술"을 존중해야하므로 숙련 된 프로그래머를 혼동하지 마십시오.


3
Ada도 그렇게했지만 Ada는 "학문적 언어"가 아닙니다.
— John R. Strohm

Ada는 Pascal과 Modula 2에서 심하게 구부 렸기 때문에 그렇게했습니다.
— 로봇 Gort 로봇

2
@StevenBurnap의 빠른 검색에 따르면 Wirth의 Modula-2에 관한 첫 번째 책은 1982 년 중반에 나왔습니다. Ada는 그 전에 몇 년 전에 (DoD1은 1977 년에 기억했듯이) 개발 중에 있었고 1983 년에는 ANSI 표준과 MIL-STD로 표준화되었습니다. Ada 후보자를 제출 한 4 개의 팀 모두 PASCAL을 인수했습니다. 그들의 출발점으로. (Bell Labs는 DoD에 의해 C를 기반으로 한 후보 언어를 제출하도록 초청되었습니다. 그들은 C가 당시 DoD 미션 크리티컬 한 소프트웨어를 위해 충분히 강력하지 않을 것이라고 말하면서 이의를 제기했습니다.
— John R. Strohm

내가 잘못 기억해야합니다. Wirth가 Ada에 관여했다고 생각했습니다.
— 로봇

Pascal은 학술 언어로 시작했지만 90 년대 말에는 델파이를 통해 Windows 앱을 작성 하는 언어가되었습니다. Borland가 가격으로 상어를 뛰어 넘고 Java와 C #의 문을 열었습니다. 와서 상을 훔치십시오. 그래도 레거시 Windows 앱 세계에서 여전히 많은 톤의 델파이를 볼 수 있습니다.
— Shayne

1

왜 x: int = 42그렇지 int x = 42않습니까? 후자는 전자보다 더 읽기 쉽지 않습니까?

이러한 간단한 예에서는 큰 차이가 없지만 조금 더 복잡하게 만들어 봅시다. int* a, b;

이것은 C에서 실제로 유효한 선언이지만 직관적으로 보이는 것처럼 행동하지 않습니다. 우리는 type의 두 변수를 선언하는 것처럼 int*보이지만 실제로는 one int*과 one을 선언 하고 int있습니다.

언어가 선언에서 변수 이름 뒤에 유형 을 넣으면 그 문제를 해결할 수 없습니다.


4
왜 형식 선언을 이동 한 후에 이것이 영향을 받는지 잘 모르겠습니다. 가 x, y *int;두 개 *int또는 하나 *int하나 int? 두 개 대신에 하나 int*또는 *int하나의 토큰을 만들면 문제가 해결되거나 또는와 같은 추가 구문 요소를 사용하여 :어느 방향 으로든 작동 할 수 있습니다.
— 8bittree

@ 8bittree 내가 그와 알고 있어요 모든 언어가 이름 첫번째 선언과 같은 추가 토큰을 사용하여 사용 :하거나 as이름과 유형 사이.
— 메이슨 휠러


2
그리고 Go에서 x, y *int"pointer-to-int 형식으로 두 개의 변수 x와 y를 선언합니다"를 의미합니다.
— Vatine

10
C #은 접두사 구문을 사용하지만 int[] x, y두 배열로 취급 합니다. 문제를 일으키는 변수 (및 접두사와 접미사 조합)에서 이러한 수정자를 단항 연산자로 처리하는 것은 어리석은 C 구문입니다.
— 코드 인 카오스
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.