점진적 타이핑 : "정적 유형 시스템을 가진 거의 모든 언어에는 동적 유형 시스템이 있습니다"


20

Aleks Bromfield의 주장 은 다음과 같습니다.

정적 유형 시스템을 가진 거의 모든 언어에는 동적 유형 시스템이 있습니다. C를 제외하고는 예외를 생각할 수 없습니다.

이것이 유효한 주장입니까? 런타임에 리플렉션 또는 로딩 클래스를 사용하면 Java가 약간 비슷하다는 것을 이해하지만 '점진적 타이핑'이라는 아이디어를 많은 언어로 확장 할 수 있습니까?


포트란, 에이다, 파스칼, 코볼 - 나는 어떤 언어 전문가입니다,하지만 즉시 온 것을 몇 내가 믿는 동적 유형이하지 않는 것이 마음에 (기본적를 당신에게 함께 이들의 자갈 뭔가를 수없는 말을하지 않음)
mattnz

4
저는 언어 전문가이며이 사람이 무엇을 주장하는지 잘 모르겠습니다. "정적"및 "동적"은 잘못된 값이며 일반적으로 유형 확인 / 분석 시간 (컴파일 타임 또는 런타임)을 나타냅니다. 일부 언어는 (예 : 컴파일 중 지원되지 않는 유형에 대한 작업을 허용하지 않고 런타임 동안 ClassCastException과 같은 예외를 발생시켜) 두 가지 모두를 조정하며, 이는 그가 의미하는 것일 수 있습니다. 그렇다면 C는 일반적으로 런타임 동안 유형 검사를 수행하지 않는 것이 사실입니다 . 랭 말하기. "동적 유형 시스템"이없는 것은 의미가 없습니다.
Thiago Silva

답변:


37

원래 트위터 여기에. :)

우선, 나는 내 트윗이 너무 심각하게 받아 들여지는 것에 대해 다소 즐겁고 충격을 받았습니다! 이것이 널리 보급 될 것이라는 것을 알았다면, 그것을 작성하는 데 30 초 이상이 걸렸을 것입니다!

Thiago Silva는 "정적"및 "동적" 이 유형 시스템이 아닌 유형 검사를 보다 정확하게 설명한다고 지적하는 것이 맞습니다 . 실제로 언어가 정적으로 또는 동적으로 입력되었다고 말하는 것은 실제로 정확하지 않습니다. 오히려 언어에는 형식 시스템이 있으며 해당 언어를 구현하면 정적 검사, 동적 검사 또는 둘 다 또는 둘 다를 사용하여 형식 시스템을 적용 할 수 있습니다 (매우 매력적인 언어 구현은 아니지만).

이와 같이 정적 검사에 더 적합한 특정 유형 시스템 (또는 유형 시스템의 기능)이 있으며 동적 검사에 더 적합한 특정 유형 시스템 (또는 유형 시스템의 기능)이 있습니다. 예를 들어, 언어에서 프로그램의 텍스트에서 특정 값이 항상 정수 배열이어야한다고 지정할 수 있으면 해당 속성을 확인하기 위해 정적 검사기를 작성하는 것이 합리적입니다. 반대로, 언어에 하위 유형이 있고 다운 캐스팅을 허용하는 경우 런타임에 다운 캐스트의 유효성을 확인하는 것이 합리적이지만 컴파일 타임에는 그렇게하기가 매우 어렵습니다.

내가 정말 내 트윗을 의미하는 것은 언어 구현의 대부분이 수행 단순히이다 일부 동적 타입 검사의 양을. 또는 대부분의 언어에는 정적으로 확인하기 어려운 (아직 불가능하지는 않지만) 일부 기능이 있습니다. 다운 캐스팅이 한 예입니다. 다른 예로는 산술 오버플로, 배열 범위 검사 및 null 검사가 있습니다. 이러한 상황 중 일부는 상황에 따라 정적으로 검사 할 수 있지만 대체로 런타임시 검사를 수행하지 않는 언어 구현을 찾기가 어려울 것입니다.

이것은 나쁜 것이 아닙니다. 우리의 언어로 적용 할 흥미로운 속성이 많으며 정적으로 확인하는 방법을 모른다는 것이 관찰에 불과합니다. "정적 유형"과 "동적 유형"과 같은 차이점은 일부 사람들이 생각하는 것만 큼 명확하지 않다는 것을 상기시킵니다. :)

마지막으로, "강한"과 "약한"이라는 용어는 프로그래밍 언어 리서치 커뮤니티에서 실제로 사용되지 않으며 실제로 일관된 의미를 갖지 않습니다. 일반적으로, 누군가가 언어에 "강력한 타이핑"이 있고 다른 언어에 "약한 타이핑"이 있다고 말하면, 그들이 가장 좋아하는 언어 ( "강력한 타이핑"이있는 언어)가 언어를 방해한다고 말하는 것입니다. 다른 언어 ( "약한 타이핑"이있는 언어)가 그렇지 않거나 반대로 자신이 좋아하는 언어 ( "약한 타이핑"이있는 언어)가 다른 언어 ( "강력한 입력"을 가진 사람은 그렇지 않습니다.


9
"언어가 적용 할 흥미로운 속성이 많으며 정적으로 확인하는 방법을 모른다는 관찰 일뿐입니다." – 우리가 그것을하는 방법을 모른다는 것이 아닙니다. 우리가 확인하는 방법을 알고하지 않는 것이 흥미로운 속성입니다 "이 입력이 프로그램 중단합니까"하지만, 사실 우리는 알고는 불가능합니다 확인.
Jörg W Mittag

"다른 예로는 산술 오버플로, 배열 범위 검사 및 null 검사가 있습니다." 형식 시스템에 이러한 속성을 확인하는 몇 가지 언어가 있지만 가장 동적으로 형식이 지정된 언어의 경우에도 일반적으로 형식이 아닌 의 기능입니다 . ( "Null"검사는 정적 유형 시스템의 일반적인 기능입니다.)
porglezomp

입니다 동적 타입 시스템 및 정적 타입 시스템 . 둘 중 어느 것도 적용되지 않더라도 올바른 내용과 오류가 무엇인지 설명하는 여전히 존재합니다. 언어 / 구현은 둘 중 하나를 확인하거나 확인하지 않을 수 있습니다. BTW, 정적 및 동적 유형 시스템은 일관성이 있어야하지만 정의에 따라 다릅니다 .
Elazar

모든 언어에는 동적 유형 시스템이 있으며 이는 특정 작업 수행을 금지하는 일련의 규칙입니다.
Elazar

7

그래 정적 유형 언어로 속성 백을 가질 수 있습니다. 구문은 끔찍하지만 동시에 동적으로 유형이 지정된 시스템의 모든 단점을 얻게됩니다. 따라서 컴파일러가 C #과 같은 더 좋은 구문을 사용할 수 없다면 실제로 어떤 이점도 없습니다 dynamic.

또한 C에서도 그렇게 쉽게 할 수 있습니다.

다른 답변에 대한 반응으로 사람들은 강한 / 약한 타이핑으로 정적 / 동적 타이핑을 착각하고 있다고 생각합니다. 동적 타이핑은 런타임시 데이터 구조를 변경하고 코드에 필요한 데이터를 사용할 수있는 코드에 관한 것입니다. 이것을 오리 타이핑 이라고 합니다.

리플렉션은 기존 데이터의 구조를 변경할 수 없기 때문에 리플렉션을 언급하는 것은 전체 이야기를 말하지 않습니다. C, C ++, Java 또는 C #에서 클래스 또는 구조에 새 필드를 추가 할 수 없습니다. 동적 언어에서는 기존 클래스에 새 필드 또는 속성을 추가하는 것이 가능할뿐만 아니라 실제로는 일반적입니다.

예를 들어 Python-to-C 컴파일러 인 Cython을 보십시오 . 정적 C 코드를 작성하지만 유형 시스템은 여전히 ​​동적 특성을 유지합니다. C는 정적으로 입력 된 언어이지만 Python에서 동적 입력을 지원할 수 있습니다.


기술적으로 ExpandoObject는 JavaScript 또는 Ruby와는 달리 옵트 인 프로세스이지만 C #에서 버전 4부터 수행 할 수 있습니다 . 그래도 오리 타이핑 (개발자의 99 %가 "동적 유형"이라고 말할 때 실제로 의미하는 것)과 반사는 전혀 같은 것이 아니라는 점이 매우 중요합니다.
Aaronaught

파이썬에 실제 오리 타이핑이 없다고 덧붙일 수도 있습니다. 그것은 당신이 "자신의 구현"( True"이 미친 객체는 내가 정의하고있는 클래스의 인스턴스"라고 말하기 위해 반환 할 수있는 마술 방법을 가지고 있음)을위한 고리를 가지고 있습니다 . OCaml은 내가 이해하는 한이 기능을 가지고 있지만 실제로는 모른다.
vlad-ardelean

6

동적 언어는 정적 언어 입니다. 일반적으로 "동적 타이핑"이라고하는 것은 실제로 정적 타이핑의 특별한 경우입니다. 하나의 유형 만 사용하도록 제한 한 경우입니다. 생각의 실험으로 만 사용하여 Java 또는 C #에서 프로그램 작성 상상 Object변수 / 필드 / 매개 변수와 아래로 캐스팅 호출하기 전에 즉시 어떤 방법을. 파이썬이나 자바 스크립트와 같은 언어를 "유니 타입"이라고 부르는 것이 더 정확합니다. (이 주장은 Java 또는 C # 프로그램이 많은 하위 유형을 사용한다는 점을 고려하면 많은 사람들을 혼란스럽게하거나 혼동시킬 수 있지만 평균 OOP 언어가 유형과 클래스를 병합하기 때문입니다. 자세한 내용은 블로그 게시물을 읽으십시오.)

C조차도 "동적"타이핑이 있습니다. 포인터를 void(메모리가 나를 위해 제공하는 경우) 포인터로 캐스트 char하고 다시 되돌릴 수 있습니다. 또한 런타임 검사는 없습니다. 당신이 잘못되면 정의되지 않은 행동을 즐기십시오!


그러나 캐스트는 정적으로 수행됩니다. 이것이 어떻게 동적 타이핑의 예인지 알지 못합니다.
osa

@osa 단지 코드가 String foo = (String) bar그것이 bar실제로 a를 의미하는 것은 아니라고 말합니다 String. 런타임에 확실히 알 수 있으므로 캐스트가 "정적으로"수행되는 방법을 알 수 없습니다.
Doval

나는 이것에 동의하지 않습니다. 적어도 자바 스크립트에서는 런타임에 객체에 새로운 메서드와 속성을 추가 할 수 있습니다. C #에서는이를 위해 명시 적으로 dynamic개체를 사용해야합니다 . object...에 속성을 추가하려고 하면 할 수 없습니다.
Arturo Torres Sánchez

3

정적 및 동적 입력의 차이는 경우 컴파일 시간 대 실행 시간 : 값의 형식을 체크한다. 값에 유형이 있는 언어 (예 : Java 객체)에서는 언어가 실제로 정적 타이핑을 선호하는 경우에도 항상 동적 타이핑을 사용할 수 있습니다. 다음은 동적으로 유형이 지정된 메소드가있는 Java의 예입니다.

void horribleJava(List untypedList) {
  for (Object o : untypedList)
    ((SpecificType) o).frobnicate();
}

런타임에 각 항목의 유형을 확인하는 방법에 주목하십시오. 동일한 정적으로 형식화 된 방법은 다음과 같습니다.

void goodJava(List<SpecificType> typedList) {
  for (SpecificType o : typedList) {
    o.forbnicate();
  }
}

C에서 값 (특히 포인터)은 런타임 동안 유형을 유지하지 않습니다. 모든 포인터는 a와 같습니다 void *. 대신 변수 와 표현식에는 유형이 있습니다. 동적 타이핑을 달성하려면 타입 정보를 직접 전달해야합니다 (예 : 구조체의 필드).


1
캐스트가 실제로 실용적인 의미로 동적 타이핑으로 간주되지 않는다고 생각합니다. 여전히 컴파일 타임에 유형에 대한 지식이 필요하며 런타임까지 실제 유효성 검사를 연기합니다. 에 frobnicate대해 먼저 알지 않고 는 메소드를 호출 할 수 없습니다 SpecificType.
Aaronaught

2
@Aaronaught 그러나 이것은 이다 우리가 시간을 실행하는 유형 검사를 연기 한 후 동적 타이핑. 두 예제 모두 특정 유형 이름이 필요한 명목 입력 을 사용합니다. 구조적 타이핑을 생각하고 있습니다 . 예를 들어 오리 타이핑은 어떤 방법이 필요합니다. 축 구조 대 명목 및 정적 대 동적 타이핑은 서로 직교합니다 (자바는 명목적이고 대부분 정적이며 ML 및 Go는 구조적이며 정적이며 Perl, Python 및 Ruby는 (주로) 구조적이며 동적입니다).
amon

마지막 의견에서 말했듯이, 내가 만난 프로그래머가 실제로 신경 쓰지 않는 것은 이론상의 차이입니다. 당신은 사람들이 잘못된 용어를 사용하고 있다고 주장 할 수있다. (실제로 원래 트위터가 정확히 그런 종류의 냉담함을 추구 한 것으로 보인다) 그러나 실제로 참호에있는 사람들에게는 동적 타이핑 = 덕 타이핑이있다. 실제로 정의는 너무 일반적이므로 C #과 같은 언어로 실제로 정의되어 있습니다 (예 : dynamic키워드). 정적컴파일 타임에 , 동적런타임에 동일시 하는 것은 대부분 물을 흐릿하게 만듭니다.
Aaronaught

@Aaronaught : 인터페이스로 캐스트하고 의도 된 의미로 메소드를 구현하는 클래스가 동일한 인터페이스를 지속적으로 구현하는 경우 본질적으로 런타임 오리 타이핑입니다. 어떤 사람들은 "오리 타이핑"이 단지 메소드 이름을 사용해야한다고 주장 할 수도 있지만, "실제"메소드 이름을 인터페이스 이름과 메소드 이름으로 간주하는 것이 더 도움이 될 것이라고 생각합니다. 그렇지 않으면,해야 [1,2].Add([3,4])얻을 [1,2,3,4], [1,2,[3,4]]또는 [4,6]?
supercat

@supercat : 위의 어느 것도, Add배열에 수용하는 메소드 가 없기 때문에 실패해야 합니다. 그러한 메소드는 모호하기 때문입니다. 오리 타이핑은 이해하기 쉬운 유형과 기능을 작성하는 데있어서 변명하지 않습니다.
Aaronaught

2

정적 대 동적 입력은 기본적으로 유형을 확인하는 방법을 나타냅니다. 정적 유형 지정은 다양한 변수 또는 표현식 유형의 검증이 실제 코드 (일반적으로 컴파일러에 의해)를 기반으로 확인되는 반면 동적 유형 시스템에서는이 검증이 런타임 환경에서 런타임시에만 수행됨을 의미합니다.

텍스트가 참조하고 있다고 생각하는 것은 실제로 유형을 정적으로 확인하더라도 런타임에 동적으로 확인된다는 것입니다. Java Reflection을 올바르게 언급했습니다. 리플렉션은 런타임에서만 발생하며 JVM (Java Runtime Environment)은 리플렉션을 사용할 때 실제로 유형 확인을 수행합니다. 이는 기본적으로 동적 유형 확인을 의미합니다.


그런 다음 올바르지 않습니다. C ++, Pascal, Fortran --- 모든 컴파일 된 언어에서 --- 유형은 정적으로 만 확인되고 동적으로 확인되지 않습니다 (dynamic_cast를 사용하지 않는 한). 포인터를 사용하여 임의의 내용을 메모리에 쓸 수 있으며 아무도 유형을 알 수 없습니다. 따라서 정적 타이핑은 정적으로 만 검사를 의미하고 동적 타이핑은 런타임에만 검사를 의미합니다.
osa

-1

예외가 잘못되었습니다. C에도 중요한 동적 유형 시스템이 있습니다. 단순히 확인하지 않습니다 ( "C는 강력하게 형식화되어 있고 약하게 검사되어 있습니다"). 예를 들어, 구조체를 double( reinternpret_cast-style) 로 처리 하면 동적 유형 오류 인 정의되지 않은 동작이 생성됩니다.


(누구에게 공감 한 사람에게-@Thiago Silva의 의견은 같은 것에 대해 말합니다)
Elazar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.