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


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.