자료형 체계
컴퓨터 과학에서, 자료형 체계()는 값, 표현식, 함수, 모듈 등을 분류하는 규칙의 집합이다. 보다 형식적으로는, "계산될 값을 분류하여 특정한 종류의 프로그램 오류가 일어나지 않음을 증명하는 계산 가능한 방법"으로 정의된다.
자료형 체계에서 각각의 계산된 값은 "자료형"을 갖는다. 자료형 체계는 프로그램 안에서 값의 흐름을 검토하여 자료형에 맞지 않는 값이 할당되는 것을 막는다. 자료형에 맞지 않는 값이 할당되는 것을 "자료형 오류"라고 부른다. 논리적으로 맞지 않는 자료형 사이의 연산이나 잘못된 메모리에 접근하는 경우가 이에 해당한다. 구체적으로 어떤 연산이 자료형 오류인지는 자료형 체계에 따라 다르다.
컴파일러는 정적 자료형을 통해 각 변수에 필요한 저장 용량과 연산 알고리즘을 최적화할 수 있다. 예를 들어 다수의 C 컴파일러의 "부동소수점" 자료형은, 단일 정밀도 부동 소수점 숫자에 대한 IEEE 표준에 따라 32 비트로 표시된다. 따라서 C 컴파일러는 부동소수점 자료형을 갖는 변수의 연산에는 그에 맞는 기계어 명령을 사용할 수 있다.
형식 제약의 깊이와 그 평가의 방법은 언어의 "정형"에 영향을 미친다. 프로그래밍 언어 추가 자료형 다형성의 경우 각 자료형에 대한 다양한 구체적인 알고리즘과 함께 작업을 연결할 수 있다. 형 이론은 컴퓨터 아키텍처, 컴파일러 구현 및 언어 디자인의 실용적인 문제에서 발생하는 자료형 체계의 연구이다.
값에 자료형을 할당하는 것을 "정형"이라고 한다. 정형은 메모리 상의 비트의 나열에 의미를 부여한다. 컴퓨터 상에서 모든 값은 단순히 비트 나열로 구성되어 있기 때문에, 하드웨어는 메모리 주소, 명령어 코드, 문자, 정수, 부동소수점을 서로 구분할 수 없다. 나열된 비트들과 형을 연결해줌으로써, 프로그래머는 프로그램이 어떻게 이 비트의 순서를 이해해야 하는지 알려준다.
자료형 체계가 제공하는 주 기능은 다음과 같다:
프로그램이 자료형의 제약 조건을 지키는지 검증하는 것을 "자료형 검사"라고 한다. 자료형 검사는 컴파일 타임 (정적 검사) 또는 런타임 (동적 검사) 에 실행될 있다. 만약 언어 명세가 엄격한 분류 규칙을 요구할 경우 (즉, 더 많거나 적은 정보를 잃지 않는 것만 자동 자료형 전환을 허용한다), "강력한 정형"으로, 그렇지 않다면, "약한 정형"으로 분류할 수 있다. 그러나 이 분류는 학술적으로 엄격한 분류는 아니다.
자료형 검사가 실행 시간이 아닌 컴파일 타임 동안 수행될 경우, 이를 정적 정형이라고 한다. 정적으로 정형된 언어는 액션스크립트 3, 에이다, C, C++, C#, D, Eiffel, F#, 포트란, Go, 하스켈, JADE, 자바, ML, 오브젝티브-C, OCaml, 파스칼, 펄 (스칼라, 배열, 해시 및 서브루틴의 구별에 대하여) 그리고 스칼라 등이 있다.
정적 정형은 프로그램 검증의 제한된 형태이다 (형 안전 참조): 따라서, 많은 자료형 오류가 개발주기의 초기에 잡힐 수 있다. 정적 형 검사기는 오직 컴파일 타임에 결정될 수 있는 자료형 정보만을 평가하지만, 프로그램의 가능한 모든 입력에 대해 검사 조건을 확인할 수 있고, 프로그램이 실행될 때마다 매번 자료형 검사를 반복할 필요가 없다. 또한 정적 형 검사가 이루어질 경우 실행 자료형 검사를 생략하고 다른 최적화를 수행할 수 있어, 프로그램 실행도 보다 효율적으로 (즉, 빠르게 또는 감소된 메모리를 사용) 만들 수 있다.
어떤 자료형 정보는 오직 실행 시간에만 정해지기 때문에, 정적 형 검사기는 보수적이다. 실행 시간에는 자료형 오류가 일어나지 않는 일부 프로그램이 정적 형 검사기에서는 거부될 수 있다. 예를 들어, 표현식 codice_2가 항상 실행 시간에서 codice_3를 평가한다고 할 경우:
codice_4
는 자료형 오류를 일으키며 거부될 것이다. 왜냐하면 정적 분석은 codice_5 분기가 실행되지 않는다는 사실을 확인할 수 없기 때문이다. 반면, 정적 형 검사기의 보수적인 동작은 가끔씩 codice_2를 codice_7로 평가할 때 유익하다: 정적 자료형 검사기는 드물게 사용되는 코드 경로에서 자료형 오류를 감지할 수 있다. 정적 형 검사를 하지 않을 경우, 코드 범위 테스트는 100% 범위에서도 이러한 자료형 오류를 발견하지 못할 수 있다.
자료형 검사의 대부분이 컴파일 타임이 아닌 실행 시간에 수행될 경우 "동적 정형"이라고 한다. 동적 정형에서, 값은 자료형을 가지고 있지만 변수는 그렇지 않다. 즉, 변수는 모든 자료형의 값을 가질 수 있다. 동적으로 정형된 언어로는 APL, 얼랭, 그루비, 자바스크립트, 리스프, 루아, MATLAB/GNU 옥타브, 펄 (사용자 정의를 위한 자료형이지만 기본이 아닌 자료형), PHP, 프롤로그, 파이썬, 자이썬, 루비, 스몰토크, 클로저 그리고 Tcl 등이 있다.
동적으로 정형된 언어는 일반적으로 모든 런타임 개체가 자료형 정보를 함께 갖고 있다. 이런 런타임 자료형 정보는 함수 오버로드, 동적 디스패치, 게으른 바인딩, 다운캐스팅 등에도 사용될 수 있다.
더 넓게, 아래에서 설명한 것처럼, 동적 정형은 동적 프로그래밍 언어 기능에 대한 지원을 향상시킬 수 있고, 런타임 데이터를 기반으로 한 기능과 자료형을 창출하는 것 등이 있다. (그럼에도 불구하고, 동적으로 정형된 언어는 일부 또는 전부 같은 기능을 지원하지 않아도, 일부 "동적 프로그래밍 언어"는 정적으로 정형되어 있다.) 한편, 동적 정형은 적은 "선천적" 보장을 제공한다: 동적으로 정형된 언어는 정적 자료형 검사기에 의해 무효로 지배될 일부 프로그램을 실행하려고 허용 및 시도하는데, 프로그램의 오류 때문이거나 정적 자료형 검사가 너무 보수적으로 되기 때문이다. 동적 정형은 런타임 자료형 오류가 발생할 수 있다—즉, 런타임에서, 값은 예상치 못한 유형이 있을 수 있고, 그 자료형에 대한 무의미한 작업이 적용된다. 이런 오류가 프로그래밍 실수 구문에서 오랜 시간 후에 발생할 수 있다—즉, 데이터의 잘못된 자료형의 장소로 전달되는 구문은 작성하지 않아야 한다. 이것은 버그를 찾기 어려울 수도 있다.
동적 정형 언어 체계들의 런타임 검사는 잠재적으로 정적으로 정형된 언어의 경우보다 더 정교할 수 있고, 그들은 동적인 정보뿐만 아니라 소스 코드로부터 정보를 사용할 수 있다. 한편, 런타임 검사는 오직 프로그램의 특정 실행에서 조건을 잡는 것을 주장하고, 검사는 매번 프로그램을 실행하는 동안 반복된다.
동적으로 정형된 언어의 개발은 자주 단위 테스트와 같은 프로그래밍 정책에 의해 지원된다. 테스트는 전문 소프트웨어 개발에서 핵심 방법이고, 동적으로 정형된 언어의 경우에 특히 중요하다. 실제로, 올바른 프로그램이 작동을 보장하기 위해 했던 테스트는 정적 자료형 검사보다 훨씬 넓은 오류 범위를 감지할 수 있지만, 반대로 정적 자료형 검사가 감지할 수 있는 오류를 종합적으로 검색할 수 없다.
프로그래밍 언어의 정적 정형의 존재는 반드시 모든 동적 정형 구조가 없는 상태를 의미하는 것은 아니다. 예를 들어, 자바와 다른 표면에서 정적으로 정형된 언어의 경우, 하위 형변환 및 런타임 자료형 검사에 따라 다른 종류의 작업을, 동적 정형의 형태로 지원한다. 더 일반적으로, 대부분의 프로그래밍 언어는 데이터를 서로 다른 '종류'를 통해, 서로소 합집합과, 변형 자료형 및 다형성 개체와 같은 파견에 대한 방식을 포함한다: 자료형 주석 또는 자료형 검사와 상호 작용조차 하지 않을 때 이러한 방식은 동적 정형 구현에서 실질적으로 유사하다. 정적 및 동적 정형 사이의 상호 작용에 대한 자세한 내용을 보려면 프로그래밍 언어를 참조한다.
특정 언어, 예를 들어 클로슈어는, 기본적으로는 동적으로 정하지만, 이 동작을 허용하는 것은 정적 정형에서의 결과로 명시적인 자료형의 사용 힌트를 통해 무시한다. 이러한 힌트를 사용하는 이유 중 하나는 코드의 성능에 민감한 부분에서 정적 정형의 성능 이점을 달성하는 것이다.
4.0의 출시로, 닷넷 프레임워크 '동적' 자료형의 '정적' 개체는 개체 참조를 해결하기 위해 동적 설비를 심문하는 닷넷 런타임에 대한 자리표시자에 의하여 System.Dynamic 이름공간 을 통해 동적 정형의 정의 변종을 지원한다.
정적 및 동적 정형 사이의 선택은 트레이드오프를 필요로 한다.
정적 정형은 컴파일 타임에 안정적으로 자료형 오류를 찾을 수 있다. 이것은 제공되는 프로그램의 신뢰성이 증가할 것이다. 그러나, 프로그래머는 일반적으로 자료형 오류가 발생하는 방법을 통해 반대하고, 따라서 적절하게 코드에서 설계된 자료형을 대표해서 잡은 것으로 코딩한 이 버그의 비율을 통해 반대한다. 정적 정형 지지자들은 자료형 검사가 잘 되어있을 때 프로그램이 더 신뢰할 수 있다고 믿고, 동적 정형 지지자들은 안정적이고 작은 데이터베이스 버그가 증명된 배포 코드를 가리킨다. 자료형 체계의 강도가 증가된 다음에 정적 정형의 값은 아마도 증가할 것이다. 만약 프로그램에 사용되는 자료형이 프로그래머에 의해 제대로 선언되거나 정확하게 컴파일러에 유추되는 경우, 이러한 종속 ML과 에피그램으로 의존적으로 정형된 언어의 지지자들은 거의 모든 버그가 자료형 오류로 간주될 수 있는 제안을 한다.
정적 정형은 보통 더 빠르게 실행하는 컴파일된 코드에서 발생한다. 컴파일러가 사용하는 정확한 자료형을 알고있을 때, 그것은 최적화된 기계 코드를 생성할 수 있다. 더 나아가, 정적으로 정형된 언어를 위한 컴파일러는 어셈블러보다 쉽게 ​​단축키를 찾을 수 있다. 일부 동적으로 정형된 언어와 같은 커먼 리스프는 매우 합리적인 최적화를 위한 옵션 정형을 허용한다. 정적 정형은 이것을 보급한다. 최적화를 참조한다.
반대로, 동적 정형은 컴파일러가 더 빠르게 실행할 것과 인터프리터가 동적으로 새로운 코드를 불러오는 것을 허용할 수 있고, 동적으로 정형된 언어에서의 소스 코드에 대한 변경 사항 때문에 수행하기 위해 덜 검사한 것과 코드를 되짚는 것에서 발생할 수 있다. 이것도 편집 - 컴파일 - 테스트 - 디버그 주기를 줄일 수 있다.
정적으로 정형된 언어의 경우 부족한 자료형 추론 (예: C와 Java 등)은 프로그래머들이 메서드나 함수를 사용하고자 하는 자료형을 선언할 것을 요구한다. 이것은 어느 컴파일러가 프로그래머가 동기화 중에 표류할 것을 무시하거나 허용하도록 허가하지 않을 것을 프로그램을 위한 추가 문서로 검색할 수 있다. 그러나, 언어는 정적으로 자료형 선언 없이 정형될 수 있다 (예시는 하스켈, 스칼라 그리고 낮은 정도의 C#를 포함한다), 그래서 명시적인 자료형 선언은 모든 언어에서 정적 정형을 위한 요구 사항을 필요로 하지 않는다.
동적 정형은 몇몇 정적 자료형 검사가 불법으로 거부할 것이라는 구조를 허용한다. 예를 들어, 코드로 임의의 데이터를 실행하는 "eval" 함수가 가능하게 된다. "eval" 함수는 정적 자료형으로 가능하지만, 고급 대수적 데이터 자료형의 사용이 필요하다. 또한, 동적 정형이 자리 표시자 데이터 구조 본격적인 자료 구조 (보통 실험 및 시험의 목적) 대신에 투명하게 사용된 (모의 객체)를 허용하는 등 전환 코드와 프로토 타입을 수용하는 것보다 낫다.