동적 타이핑이란 무엇입니까? 동적 타이핑 Php 정적 타이핑.

모든 것이 매우 간단합니다. 호텔과 개인 아파트의 차이와 같습니다.

그곳에 등록된 사람들만 아파트에 거주합니다. 예를 들어 Sidorov 가족이 그 안에 살고 있다면 Pupkin 가족은 우리 삶을 위해 그곳에서 살 수 없습니다. 동시에 Petya Sidorov는이 아파트에 살 수 있고 Grisha Sidorov는 그곳으로 이사 할 수 있습니다 (때로는 동시에 거기에 살 수도 있습니다. 이것은 배열입니다). 이것은 정적 타이핑입니다.

Sidorov 가족은 한동안 호텔에 살 수 있습니다. 항상 거기에 등록할 필요도 없습니다. 그런 다음 그들은 그곳을 떠날 것이고 Pupkins는 그곳으로 이동할 것입니다. 그리고 Kuznetsovs. 그리고 다른 사람. 이것은 동적 타이핑입니다.

프로그래밍으로 돌아가면 첫 번째 경우(정적 타이핑)는 C, C++, C#, Java 및 기타 언어에서 발견됩니다. 처음으로 변수에 값을 할당하기 전에 변수에 저장할 내용(정수, 부동 소수점 숫자, 문자열 등)을 지정해야 합니다. ( Sidorovs는 이 아파트에 살 것입니다). 반면 동적 타이핑에는 이것이 필요하지 않습니다. 값을 할당하면 변수에 해당 유형( Pupkin 가족의 Vasya Pupkin이 이제 이 호텔 방에 살고 있습니다.). 이는 PHP, Python 및 JavaScript와 같은 언어에서 발견됩니다.

두 접근 방식 모두 장점과 단점이 있습니다. 어느 것이 더 좋고 더 나쁜지는 해결되는 문제에 따라 다릅니다. 예를 들어 Wikipedia에서 더 자세히 읽을 수 있습니다.

정적 타이핑을 사용하면 프로그램을 작성하고 알고리즘을 개발할 때 변수의 유형을 정확히 알고 이를 고려합니다. 저것들. 변수 G가 4바이트 부호 없는 정수라고 말하면 알고리즘에서는 항상 4바이트 부호 없는 정수가 됩니다(있는 경우 이를 명시적으로 변환하거나 변환기가 특정 형식으로 변환하는 방법을 알아야 합니다). 다양한 상황이 있지만 주로 유형 불일치가 있는 경우 이는 알고리즘의 오류이며 컴파일러는 최소한 경고합니다.) 정적 경우에는 "Vasya the Fool"이라는 문자열을 숫자에 넣을 수 없습니다. 변수를 사용하기 전에 "숫자가 있는지"를 결정하는 추가 검사가 필요하지 않으며 프로그램에 입력할 때 또는 알고리즘 자체에서 요구하는 대로 데이터의 모든 정확성을 수행합니다.

동적 타이핑을 사용하면 동일한 변수의 유형이 일반적으로 사용자에게 알려지지 않고 프로그램 실행 중에 이미 변경될 수 있으며 이를 고려하면 유형 불일치로 인한 알고리즘의 잠재적 오류에 대해 아무도 경고하지 않습니다. (알고리즘을 개발할 때 G가 정수라고 가정하고 사용자가 부동 소수점 숫자 또는 더 나쁜 문자열을 입력했거나 산술 연산 후에 정수 대신 부동 소수점이 있었다고 가정했습니다. , 그리고 다음 단계에서는 비트 연산을 사용해 볼 것입니다...) 반면에 많은 작은 것들에 대해 걱정할 필요가 없습니다.

  • 동적 타이핑(Dynamic Typing)은 프로그래밍 언어나 명세 언어에서 널리 사용되는 기술로, 변수를 선언하는 순간이 아닌 값을 할당하는 순간에 변수가 타입과 연관되는 방식이다. 따라서 프로그램의 다른 부분에서는 동일한 변수가 다른 유형의 값을 가질 수 있습니다. 동적 타이핑이 가능한 언어의 예로는 Smalltalk, Python, Objective-C, Ruby, PHP, Perl, JavaScript, Lisp, xBase, Erlang, Visual Basic이 있습니다.

    반대 기술은 정적 타이핑입니다.

    동적 타이핑이 약한 일부 언어에서는 값을 비교하는 데 문제가 있습니다. 예를 들어 PHP에는 비교 연산자 "==", "!=" 및 "===", "!=="가 있습니다. 한 쌍의 작업은 값과 변수 유형을 비교합니다. "===" 연산은 다음 표현식을 true로 간주하는 "=="와 달리 완전히 일치하는 경우에만 true를 제공합니다: (1=="1"). 이는 일반적인 동적 타이핑의 문제가 아니라 특정 프로그래밍 언어의 문제라는 점은 주목할 가치가 있습니다.

관련 개념

프로그래밍 언어는 컴퓨터 프로그램을 작성하기 위해 설계된 공식 언어입니다. 프로그래밍 언어는 프로그램의 모양과 실행자(보통 컴퓨터)가 제어 하에 수행할 작업을 결정하는 일련의 어휘, 구문 및 의미 규칙을 정의합니다.

프로그래밍 언어의 구문 설탕은 구문 기능으로, 이를 사용하면 프로그램 동작에 영향을 미치지 않지만 언어 사용이 인간에게 더 편리해집니다.

속성은 객체의 내부 상태에 액세스하여 일부 유형의 변수를 시뮬레이션하는 방법입니다. 객체의 속성에 액세스하는 것은 구조적 프로그래밍에서 구조 필드에 액세스하는 것과 동일해 보이지만 실제로는 함수 호출을 통해 구현됩니다. 특정 속성의 값을 설정하려고 하면 하나의 메서드가 호출되고, 이 속성의 값을 얻으려고 하면 다른 메서드가 호출됩니다.

EBNF(Extended Backus-Naur Form)는 일부 구문 범주가 다른 구문 범주를 통해 순차적으로 정의되는 구문 정의를 위한 공식 시스템입니다. 문맥 없는 형식 문법을 설명하는 데 사용됩니다. Niklaus Wirth가 제안했습니다. 이는 Backus-Naur 형식의 확장된 처리이며 BNF와 더 "대용량" 디자인이 다르므로 동일한 표현 능력으로 단순화할 수 있습니다...

응용 프로그래밍은 프로그램 작성이 하나의 개체를 다른 개체에 체계적으로 적용하는 것으로 구성된 선언적 프로그래밍의 한 유형입니다. 이러한 응용 프로그램의 결과는 함수와 인수 등으로 응용 프로그램에 참여할 수 있는 개체입니다. 이는 프로그램 표기법을 수학적으로 명확하게 만듭니다. 함수가 표현식으로 표시된다는 사실은 가치 함수(기능적...)를 사용할 가능성을 나타냅니다.

연결 프로그래밍 언어는 두 개의 코드 조각을 연결하여 그 구성을 표현한다는 아이디어를 기반으로 한 프로그래밍 언어입니다. 이러한 언어에서는 함수 인수의 암시적 표시가 널리 사용되며(무의미한 프로그래밍 참조), 새 함수는 함수의 구성으로 정의되며, 응용 프로그램 대신 연결이 사용됩니다. 이 접근 방식은 응용 프로그래밍과 대조됩니다.

변수는 일반적으로 숫자 값을 변경할 수 있는 물리적 또는 추상 시스템의 속성입니다. 변수의 개념은 수학, 과학, 공학, 프로그래밍 등의 분야에서 널리 사용됩니다. 변수의 예로는 공기 온도, 기능 매개변수 등이 있습니다.

언어학과 컴퓨터 과학의 구문 분석(또는 구문 분석, 전문 용어 구문 분석 ← 영어 구문 분석)은 자연어 또는 형식 언어의 어휘소(단어, 토큰)의 선형 시퀀스를 형식 문법과 비교하는 프로세스입니다. 결과는 일반적으로 구문 분석 트리(구문 트리)입니다. 일반적으로 어휘 분석과 함께 사용됩니다.

GADT(Generalized Algebraic Data Type)는 대수 데이터 유형의 한 유형으로, 생성자가 연관된 유형이 아닌 다른 값을 반환할 수 있다는 특징이 있습니다. 의존적 유형의 연구자 중 귀납적 가족에 대한 작품의 영향을 받아 설계되었습니다.

프로그래밍의 의미론은 공식적인 수학적 모델의 구축을 통해 프로그래밍 언어 구조의 의미를 형식화하는 것을 연구하는 학문입니다. 이러한 모델을 구성하기 위한 도구로는 수학적 논리, 람다 미적분학, 집합 이론, 범주 이론, 모델 이론, 보편대수학 등 다양한 도구가 사용될 수 있습니다. 프로그래밍 언어의 의미 체계를 형식화하면 언어를 설명하고 언어의 속성을 정의하는 데 사용할 수 있습니다.

OOP(객체 지향 프로그래밍)는 프로그램을 객체 컬렉션으로 표현하는 데 기반을 둔 프로그래밍 방법론입니다. 각 객체는 특정 클래스의 인스턴스이고 클래스는 상속 계층 구조를 형성합니다.

동적 변수는 프로그램 실행 중에 할당되는 RAM 공간인 프로그램의 변수입니다. 본질적으로 프로그램이 실행되는 동안 시스템이 특정 목적을 위해 프로그램에 할당한 메모리 섹션입니다. 이것이 전역 정적 변수(프로그램 실행이 시작되기 전에 시스템이 특정 목적을 위해 프로그램에 할당한 메모리 조각)와 다른 점입니다. 동적 변수는 메모리 변수 클래스 중 하나입니다.

이 기사에서는 정적 유형 언어와 동적 유형 언어 간의 차이점을 설명하고, "강력한" 유형과 "약한" 유형 유형의 개념을 검토하고, 다양한 언어에서 유형 지정 시스템의 성능을 비교합니다. 최근에는 프로그래밍에서 더욱 엄격하고 강력한 타이핑 시스템을 향한 분명한 움직임이 있으므로, 타입과 타이핑에 관해 이야기할 때 우리가 말하는 내용을 이해하는 것이 중요합니다.



유형은 가능한 값의 모음입니다. 정수는 0, 1, 2, 3 등의 값을 가질 수 있습니다. 부울은 true 또는 false일 수 있습니다. 예를 들어 가능한 값이 "high"와 "5"인 "High Five"유형과 같이 자신 만의 유형을 생각해 낼 수 있습니다. 문자열이나 숫자가 아니라 새로운 별도의 유형입니다.


정적으로 유형이 지정된 언어는 변수 유형을 제한합니다. 예를 들어 프로그래밍 언어는 x가 정수라는 것을 알 수 있습니다. 이 경우 프로그래머는 x = true 를 수행하는 것이 금지됩니다. 이는 잘못된 코드가 됩니다. 컴파일러는 컴파일을 거부하므로 코드를 실행할 수도 없습니다. 정적으로 유형이 지정된 또 다른 언어는 표현 기능이 다를 수 있으며 널리 사용되는 유형 시스템 중 어느 것도 HighFive 유형을 표현할 수 없습니다(그러나 대부분은 다른 더 정교한 아이디어를 표현할 수 있습니다).


동적 유형 언어는 값을 유형으로 표시합니다. 언어는 1이 정수이고 2가 정수라는 것을 알고 있지만 변수 x가 항상 정수를 포함한다는 것을 알 수 없습니다.


언어 런타임은 다양한 시점에 이러한 레이블을 확인합니다. 두 개의 값을 더하려고 하면 그 값이 숫자인지, 문자열인지, 배열인지 확인할 수 있습니다. 그런 다음 유형에 따라 이러한 값을 추가하거나 서로 붙이거나 오류를 발생시킵니다.

정적으로 입력된 언어

정적 언어는 프로그램이 실행되기 전 컴파일 타임에 프로그램의 유형을 확인합니다. 유형이 언어 규칙을 위반하는 모든 프로그램은 잘못된 것으로 간주됩니다. 예를 들어, 대부분의 정적 언어는 "a" + 1이라는 표현을 거부합니다(C는 이 규칙의 예외입니다). 컴파일러는 "a"가 문자열이고 1이 정수라는 것을 알고 있으며 +는 왼쪽과 오른쪽이 동일한 유형일 때만 작동합니다. 따라서 문제가 있음을 깨닫기 위해 프로그램을 실행할 필요가 없습니다. 정적으로 유형이 지정된 언어의 각 표현식은 코드를 실행하지 않고도 확인할 수 있는 특정 유형입니다.


많은 정적으로 유형이 지정된 언어에는 유형 표시가 필요합니다. Java 함수 public int add(int x, int y)는 두 개의 정수를 취하고 세 번째 정수를 반환합니다. 다른 정적으로 유형이 지정된 언어는 유형을 자동으로 추론할 수 있습니다. Haskell의 동일한 덧셈 함수는 다음과 같습니다: add x y = x + y . 언어에 유형을 알려주지는 않지만 +는 숫자에만 작동하므로 x와 y는 숫자여야 하므로 add 함수는 두 숫자를 인수로 사용하므로 자체적으로 유형을 알아낼 수 있습니다.


이는 유형 시스템의 "정적" 특성을 감소시키지 않습니다. Haskell의 유형 시스템은 정적이고 엄격하며 강력한 것으로 유명하며 Haskell은 이러한 모든 면에서 Java보다 앞서 있습니다.

동적 유형 언어

동적 유형 언어는 유형을 지정할 필요가 없지만 자체적으로 정의하지는 않습니다. 변수 유형은 시작 시 특정 값을 가질 때까지 알 수 없습니다. 예를 들어, Python의 함수


def f(x, y): x + y를 반환합니다.

두 개의 정수를 추가하고 문자열, 목록 등을 연결할 수 있으며 프로그램을 실행하기 전까지는 정확히 무슨 일이 일어나고 있는지 이해할 수 없습니다. 함수 f가 어느 시점에서는 두 개의 문자열로 호출되고 다른 시점에서는 두 개의 숫자로 호출될 가능성이 있습니다. 이 경우 x와 y에는 서로 다른 시간에 서로 다른 유형의 값이 포함됩니다. 이것이 동적 언어의 값에는 유형이 있지만 변수와 함수에는 유형이 없다고 말하는 이유입니다. 값 1은 확실히 정수이지만 x와 y는 무엇이든 될 수 있습니다.

비교

대부분의 동적 언어는 유형이 잘못 사용되면 오류를 발생시킵니다(JavaScript는 주목할만한 예외입니다. 의미가 없는 경우에도 모든 표현식에 대해 값을 반환하려고 시도합니다). 동적 유형 언어를 사용하는 경우 프로덕션 환경에서는 "a" + 1과 같은 간단한 오류도 발생할 수 있습니다. 정적 언어는 이러한 오류를 방지하지만 물론 방지 정도는 유형 시스템의 강도에 따라 다릅니다.


정적 언어와 동적 언어는 프로그램 정확성에 대한 근본적으로 다른 아이디어를 기반으로 구축되었습니다. 동적 언어에서 "a" + 1은 유효한 프로그램입니다. 코드가 실행되고 런타임 환경에 오류가 나타납니다. 그러나 대부분의 정적인 유형의 언어에서는 "a" + 1이라는 표현이 프로그램이 아니다: 컴파일되지 않고 실행되지 않습니다. 이것은 임의의 문자 집합과 마찬가지로 잘못된 코드입니다!&%^@*&%^@*는 잘못된 코드입니다. 정확성과 부정확성에 대한 이 추가 개념은 동적 언어에서는 해당되지 않습니다.

강한 타이핑과 약한 타이핑

'강함'과 '약함'의 개념은 매우 모호합니다. 다음은 그 사용에 대한 몇 가지 예입니다.

    때때로 "강함"은 "정적"을 의미합니다.
    간단하지만 대부분의 사람들이 사용하고 이해하기 때문에 "정적"이라는 용어를 사용하는 것이 더 좋습니다.

    때때로 "강함"은 "암시적 유형 변환을 수행하지 않음"을 의미합니다.
    예를 들어 JavaScript를 사용하면 "a" + 1을 쓸 수 있는데, 이는 "약한 타이핑"이라고 할 수 있습니다. 그러나 거의 모든 언어는 정수에서 1 + 1.1과 같은 부동 소수점 숫자로 자동 변환할 수 있는 일정 수준의 암시적 변환을 제공합니다. 실제로 대부분의 사람들은 허용 가능한 개종과 허용할 수 없는 개종 사이의 경계를 정의하기 위해 "강한"이라는 단어를 사용합니다. 일반적으로 인정되는 경계는 없습니다. 모두 부정확하며 특정 사람의 의견에 따라 다릅니다.

    때때로 "강하다"는 것은 언어의 엄격한 타이핑 규칙을 우회하는 것이 불가능하다는 것을 의미합니다.

  • 때때로 "강함"은 메모리 안전을 의미합니다.
    C는 메모리에 안전하지 않은 언어의 예입니다. xs가 4개 숫자의 배열이면 C는 xs 또는 xs를 실행하여 xs 바로 뒤의 메모리에서 일부 값을 반환합니다.

그만하자. 일부 언어가 이러한 정의를 충족하는 방법은 다음과 같습니다. 보시다시피 Haskell만이 모든 면에서 일관되게 "강하다". 대부분의 언어는 그다지 명확하지 않습니다.



("암시적 변환" 열의 "언제"는 강한 것과 약한 것의 구분이 우리가 허용 가능한 것으로 간주하는 변환에 따라 달라진다는 것을 의미합니다.)


종종 "강함"과 "약함"이라는 용어는 위의 다양한 정의와 여기에 표시되지 않은 정의의 모호한 조합을 나타냅니다. 이러한 모든 혼란으로 인해 "강함"과 "약함"이라는 단어가 거의 의미가 없게 됩니다. 이러한 용어를 사용하려면 정확히 무엇을 의미하는지 설명하는 것이 좋습니다. 예를 들어, "JavaScript는 숫자가 포함된 문자열을 추가하면 값을 반환하지만 Python은 오류를 반환합니다."라고 말할 수 있습니다. 이 경우, 우리는 "강하다"라는 단어의 다양한 의미에 대해 합의하려고 노력하는 데 에너지를 낭비하지 않을 것입니다. 또는 더 나쁜 것은 용어로 인해 해결되지 않은 오해로 끝날 것입니다.


대부분 인터넷에서 '강하다', '약하다'는 말은 특정 개인의 모호하고 제대로 정의되지 않은 의견이다. 그들은 언어를 "나쁜" 또는 "좋은"이라고 부르는 데 사용되며 이러한 의견은 기술적인 전문 용어로 변합니다.



강력한 타이핑(Strong Typing): 제가 좋아하고 편안하게 느끼는 유형 시스템입니다.

약한 타이핑: 나를 귀찮게 하거나 불편하게 만드는 유형 시스템입니다.

점진적인 타이핑

동적 언어에 정적 유형을 추가할 수 있습니까? 어떤 경우에는 - 그렇습니다. 다른 경우에는 어렵거나 불가능합니다. 가장 명백한 문제는 eval 및 기타 동적 언어의 유사한 기능입니다. Python에서 1 + eval("2")를 수행하면 3이 생성됩니다. 하지만 1 + eval(read_from_the_network())는 무엇을 생성합니까? 실행 당시 온라인 상태에 따라 다릅니다. 숫자를 얻으면 표현이 정확합니다. 문자열이라면 아니요입니다. 실행하기 전에 알 수 있는 방법이 없으므로 유형을 정적으로 구문 분석하는 것은 불가능합니다.


실제로 만족스럽지 못한 해결책은 eval() 표현식을 Any 유형으로 설정하는 것입니다. 이는 일부 객체 지향 프로그래밍 언어의 Object 또는 Go의 인터페이스()와 유사합니다. 이는 어떤 값으로도 만족할 수 있는 유형입니다.


Any 유형의 값은 제한이 없으므로 평가 코드에 도움이 되는 유형 시스템의 기능이 사라집니다. eval과 타입 시스템을 모두 갖춘 언어는 eval을 사용할 때마다 타입 안전성을 포기해야 합니다.


일부 언어에는 선택적 또는 점진적 입력이 있습니다. 기본적으로 동적이지만 일부 정적 주석을 추가할 수 있습니다. Python은 최근 선택적 유형을 추가했습니다. TypeScript는 선택적 유형이 있는 JavaScript의 상위 집합입니다. Flow는 오래된 JavaScript 코드의 정적 분석을 수행합니다.


이러한 언어는 정적 타이핑의 일부 이점을 제공하지만 진정한 정적 언어에 대한 절대적인 보장은 제공하지 않습니다. 일부 함수는 정적으로 유형이 지정되고 일부는 동적으로 유형이 지정됩니다. 프로그래머는 항상 차이점을 인식하고 주의해야 합니다.

정적으로 유형이 지정된 코드 컴파일

정적으로 유형이 지정된 코드를 컴파일할 때 모든 컴파일러에서와 마찬가지로 구문을 먼저 확인합니다. 그런 다음 유형을 확인합니다. 이는 정적 언어가 처음에는 하나의 구문 오류에 대해 불평할 수 있으며 이를 수정한 후에는 100개의 입력 오류에 대해 불평할 수 있음을 의미합니다. 구문 오류 수정으로 인해 100개의 입력 오류가 발생하지 않았습니다. 컴파일러는 구문이 수정될 때까지 유형 오류를 감지할 방법이 없었습니다.


정적 언어용 컴파일러는 일반적으로 동적 언어용 컴파일러보다 더 빠른 코드를 생성할 수 있습니다. 예를 들어 컴파일러가 add 함수가 정수를 허용한다는 것을 알고 있으면 CPU의 기본 ADD 명령어를 사용할 수 있습니다. 동적 언어는 유형에 따라 다양한 추가 함수(정수 또는 부동 소수점 추가, 문자열 또는 목록 연결) 중에서 선택하여 런타임에 유형을 확인하거나 오류가 발생했고 유형이 일치하지 않는지 결정해야 합니다. . 이 모든 확인에는 시간이 걸립니다. 동적 언어는 필요한 모든 유형 정보를 얻은 후 런타임에 코드를 다시 컴파일하는 JIT 컴파일(Just-In-Time)과 같은 최적화를 위해 다양한 트릭을 사용합니다. 그러나 어떤 동적 언어도 Rust와 같은 언어로 깔끔하게 작성된 정적 코드의 속도를 따라올 수 없습니다.

정적 및 동적 유형에 대한 인수

정적 유형 시스템을 지지하는 사람들은 유형 시스템이 없으면 단순한 오류로 인해 생산 시 문제가 발생할 수 있다고 지적합니다. 물론 이것은 사실이다. 동적 언어를 사용해 본 사람이라면 누구나 이런 일을 직접 경험해 본 적이 있을 것입니다.


동적 언어를 지지하는 사람들은 그러한 언어가 코드를 작성하기 더 쉽다고 지적합니다. 이는 평가 코드와 같이 우리가 때때로 작성하는 일부 종류의 코드에는 확실히 해당됩니다. 이는 정규 작업에 대한 논란의 여지가 있는 솔루션이며 여기서 "쉬움"이라는 모호한 단어를 기억하는 것이 합리적입니다. Rich Hickey는 "쉬움"이라는 단어와 "단순함"이라는 단어와의 연관성에 대해 훌륭하게 설명했습니다. 이 보고서를 보고 나면 '쉬움'이라는 단어를 올바르게 사용하는 것이 쉽지 않다는 것을 이해하게 될 것입니다. "쉬움"을 조심하세요.


정적 및 동적 타이핑 시스템의 장단점은 아직 잘 이해되지 않았지만 언어와 해결하려는 특정 문제에 따라 확실히 달라집니다.


JavaScript는 의미 없는 변환(예: "a" + 1을 입력하면 "a1"이 됨)을 의미하더라도 계속하려고 합니다. 반면에 Python은 "a" + 1 의 경우처럼 보수적으로 노력하고 오류를 반환하는 경우가 많습니다.


보안 수준에 따라 접근 방식이 다르지만 Python과 JavaScript는 모두 동적 형식 언어입니다.



하스켈은 먼저 명시적인 변환 없이 정수와 부동 소수점을 추가하는 것을 허용하지 않습니다. C와 Haskell은 이러한 큰 차이점에도 불구하고 둘 다 정적으로 유형이 지정됩니다.


동적 언어와 정적 언어에는 다양한 변형이 있습니다. "X에 관해서는 정적 언어가 동적 언어보다 낫다"와 같은 포괄적인 진술은 거의 말도 안 되는 것이 보장됩니다. 특정 언어의 경우에는 그럴 수도 있지만, "X에 관해서는 Haskell이 Python보다 낫다"고 말하는 것이 더 좋습니다.

다양한 정적 타이핑 시스템

정적으로 유형이 지정된 언어의 두 가지 유명한 예인 Go와 Haskell을 살펴보겠습니다. Go 타이핑 시스템에는 일반 유형, 즉 다른 유형의 "매개변수"가 있는 유형이 없습니다. 예를 들어, 필요한 데이터를 저장할 수 있는 MyList 목록에 대한 자체 유형을 만들 수 있습니다. 우리는 MyList 소스 코드를 변경하지 않고도 정수의 MyList, 문자열의 MyList 등을 생성할 수 있기를 원합니다. 컴파일러는 입력을 감시해야 합니다. 정수로 구성된 MyList가 있고 실수로 거기에 문자열을 추가한 경우 컴파일러는 프로그램을 거부해야 합니다.


Go는 MyList와 같은 유형을 정의할 수 없도록 특별히 설계되었습니다. 할 수 있는 최선의 방법은 "빈 인터페이스"의 MyList를 생성하는 것입니다. MyList는 객체를 포함할 수 있지만 컴파일러는 해당 유형을 알지 못합니다. MyList에서 객체를 검색할 때 컴파일러에 객체 유형을 알려주어야 합니다. "문자열을 받고 있습니다"라고 말했지만 실제로 값이 숫자인 경우 동적 언어의 경우처럼 런타임 오류가 발생합니다.


Go에는 현대의 정적 유형 언어(또는 1970년대 일부 시스템)에서 볼 수 있는 다른 기능도 많지 않습니다. Go를 만든 사람들은 이러한 결정을 내린 데에는 나름의 이유가 있었지만, 이 문제에 대한 외부인의 의견은 때때로 가혹하게 들릴 수 있습니다.


이제 매우 강력한 유형 시스템을 갖춘 Haskell과 비교해 보겠습니다. 유형을 MyList로 설정하면 "숫자 목록"의 유형은 단순히 MyList Integer 입니다. Haskell은 실수로 목록에 문자열을 추가하는 것을 방지하고 목록의 요소를 문자열 변수에 넣지 않도록 보장합니다.


Haskell은 훨씬 더 복잡한 아이디어를 유형으로 직접 표현할 수 있습니다. 예를 들어 Num a => MyList a는 "동일한 유형의 숫자에 속하는 값의 MyList"를 의미합니다. 정수, 부동 소수점 또는 고정 정밀도 소수의 목록일 수 있지만 컴파일 타임에 확인되는 문자열 목록은 절대 아닙니다.


모든 숫자 유형에서 작동하는 추가 함수를 작성할 수 있습니다. 이 함수의 유형은 Num a => (a -> a -> a) 입니다. 그 뜻은:

  • a는 모든 숫자 유형일 수 있습니다(Num a =>).
  • 이 함수는 a 유형의 두 인수를 사용하고 a 유형(a -> a -> a)을 반환합니다.

마지막 예입니다. 함수 유형이 String -> String 이면 문자열을 허용하고 문자열을 반환합니다. 그러나 String -> IO String 이면 일부 I/O도 수행합니다. 여기에는 디스크 액세스, 네트워크 액세스, 터미널에서 읽기 등이 포함될 수 있습니다.


함수에 유형이 있는 경우 아니요 IO, 그러면 I/O 작업을 수행하지 않는다는 것을 알 수 있습니다. 예를 들어 웹 애플리케이션에서는 함수의 유형만 보면 함수가 데이터베이스를 수정하는지 여부를 알 수 있습니다. 동적 언어나 정적 언어는 거의 없습니다. 이것은 가장 강력한 타이핑 시스템을 갖춘 언어의 특징입니다.


대부분의 언어에서 우리는 데이터베이스를 변경하는 것을 찾으려고 함수와 거기에서 호출되는 모든 함수 등을 헤쳐나가야 합니다. 이는 지루한 과정이며 실수하기 쉽습니다. 그리고 Haskell 유형 시스템은 이 질문에 간단하고 안정적으로 답할 수 있습니다.


이 힘을 "숫자와 동일한 유형의 두 인수를 취하여 I/O를 수행하는 함수"는 물론 MyList의 간단한 아이디어를 표현할 수 없는 Go와 비교해 보세요.


Go 접근 방식을 사용하면 Go 프로그래밍 도구를 더 쉽게 작성할 수 있습니다(특히 컴파일러 구현이 간단할 수 있습니다). 게다가 배워야 할 개념도 적습니다. 이러한 이점을 중요한 제한 사항과 비교하는 방법은 주관적인 질문입니다. 그러나 Haskell이 Go보다 배우기가 더 어렵고 Haskell의 유형 시스템이 훨씬 더 강력하며 Haskell이 컴파일할 때 더 많은 유형의 버그를 예방할 수 있다는 점에는 이의가 없습니다.


Go와 Haskell은 용어가 올바르게 사용되더라도 동일한 클래스의 "정적 언어"로 그룹화하는 것은 오해의 소지가 있을 수 있는 서로 다른 언어입니다. 실질적인 보안 이점을 비교할 때 Go는 Haskell보다 동적 언어에 더 가깝습니다.


반면에 일부 동적 언어는 일부 정적 언어보다 안전합니다. (Python은 일반적으로 C보다 훨씬 더 안전한 것으로 간주됩니다.) 정적 또는 동적 언어를 그룹으로 일반화하려는 경우 언어 간의 엄청난 차이점을 잊지 마십시오.

타이핑 시스템의 기능 차이에 대한 구체적인 예

더 강력한 타이핑 시스템은 더 작은 수준에서 제약 조건을 지정할 수 있습니다. 여기에 몇 가지 예가 있지만 구문이 명확하지 않더라도 너무 매달리지 마십시오.


Go에서는 "add 함수는 두 개의 정수를 취하고 정수를 반환합니다"라고 말할 수 있습니다.


func add(x int, y int) int ( x + y 반환)

Haskell에서는 "함수는 다음을 수행합니다. 어느숫자 유형이며 동일한 유형의 숫자를 반환합니다.":


f:: Num a => a -> a -> a 더하기 x y = x + y

Idris에서는 "함수는 두 개의 정수를 취하고 정수를 반환하지만 첫 번째 인수는 두 번째 인수보다 작아야 합니다"라고 말할 수 있습니다.


add: (x: Nat) -> (y: Nat) -> (자동 작아짐: LT x y) -> Nat add x y = x + y

첫 번째 인수가 두 번째 인수보다 큰 add 2 1 함수를 호출하려고 하면 컴파일러는 프로그램을 거부합니다. 컴파일 타임에. 첫 번째 인수가 두 번째 인수보다 큰 프로그램을 작성하는 것은 불가능합니다. 언어에 이러한 기능이 있는 경우는 거의 없습니다. 대부분의 언어에서 이 검사는 런타임에 발생합니다. if x >= y: raise SomeError() 와 같은 내용을 작성합니다.


위 Idris 예제의 유형에 해당하는 Haskell이 없으며 Haskell 또는 Idris 예제에 해당하는 Go도 없습니다. 결과적으로 Idris는 Haskell이 방지할 수 없는 많은 버그를 방지할 수 있고, Haskell은 Go가 알아차리지 못하는 많은 버그를 방지할 수 있습니다. 두 경우 모두 언어를 더욱 복잡하게 만들려면 추가적인 타이핑 시스템 기능이 필요합니다.

일부 정적 언어의 타이핑 시스템

다음은 파워가 증가하는 순서대로 일부 언어의 타이핑 시스템을 대략적으로 나열한 것입니다. 이 목록은 시스템의 힘에 대한 일반적인 아이디어를 제공하므로 이를 절대적인 진실로 취급하지 마십시오. 한 그룹에 모인 언어는 서로 매우 다를 수 있습니다. 모든 타이핑 시스템에는 고유한 특징이 있으며 대부분은 매우 복잡합니다.

  • C(1972), 고(2009): 이러한 시스템은 일반 유형을 지원하지 않으면 전혀 강력하지 않습니다. "정수 목록", "문자열 목록" 등을 의미하는 MyList 유형을 정의하는 것은 불가능합니다. 대신 '지정되지 않은 값 목록'을 작성해야 합니다. 프로그래머는 목록에서 문자열을 검색할 때마다 "이것은 문자열 목록입니다"라고 수동으로 보고해야 하며 이로 인해 실행 오류가 발생할 수 있습니다.
  • 자바(1995), C#(2000): 두 언어 모두 일반 유형을 지원하므로 MyList라고 말할 수 있습니다. 컴파일러가 알고 있고 유형 규칙을 적용할 수 있는 문자열 목록을 가져옵니다. 목록의 요소는 문자열 유형이며 컴파일러는 평소와 같이 컴파일 규칙을 강제하므로 런타임 오류가 발생할 가능성이 줄어듭니다.
  • 하스켈(1990), 러스트(2010), 스위프트(2014): 이러한 모든 언어에는 일반 유형, 대수 데이터 유형(ADT), 유형 클래스 또는 이와 유사한 것(각각 클래스 유형, 특성 및 프로토콜)을 포함한 여러 가지 고급 기능이 있습니다. Rust와 Swift는 Haskell보다 더 인기가 높으며 대규모 조직(각각 Mozilla와 Apple)에서 홍보합니다.
  • 아그다(2007), 이드리스(2011): 이러한 언어는 종속 유형을 지원하므로 "y가 x보다 큰 두 정수 x와 y를 취하는 함수"와 같은 유형을 만들 수 있습니다. 컴파일 중에는 "y가 x보다 큼" 제약 조건도 강제 적용됩니다. 실행되면 무슨 일이 일어나더라도 y는 x보다 작거나 같을 수 없습니다. 시스템의 매우 미묘하지만 중요한 속성을 이러한 언어에서 정적으로 확인할 수 있습니다. 이를 연구하는 프로그래머는 거의 없지만 이러한 언어는 그들 사이에서 큰 열정을 불러일으킵니다.

특히 단순히 언어가 존재한다는 사실보다는 언어의 인기로 측정할 때 더욱 강력한 타이핑 시스템을 향한 분명한 움직임이 있습니다. 주목할만한 예외는 Go입니다. 이는 많은 정적 언어 지지자들이 Go를 한 단계 퇴보하는 것으로 간주하는 이유를 설명합니다.


그룹 2(Java 및 C#)는 성숙하고 널리 사용되는 주류 언어입니다.


그룹 3은 Mozilla(Rust)와 Apple(Swift)의 전폭적인 지원을 받아 주류 진입을 앞두고 있습니다.


그룹 4(Idris 및 Agda)는 주류와는 거리가 멀지만 시간이 지나면 바뀔 수 있습니다. 3군 언어는 10년 전만 해도 주류와는 거리가 멀었다.

이 기사에는 동적 타이핑을 나쁘게, Lisp를 유형 없는 언어, C를 강력한 유형의 언어라고 부르지 않기 위해 타이핑에 대해 알아야 할 최소한의 사항이 포함되어 있습니다.

정식 버전에는 모든 유형의 타이핑에 대한 자세한 설명, 코드 예제, 인기 있는 프로그래밍 언어에 대한 링크 및 예시 사진이 포함되어 있습니다.

먼저 기사의 짧은 버전을 읽어보고 원하시면 전체 버전을 읽어 보시기 바랍니다.

짧은 버전

타이핑에 따라 프로그래밍 언어는 일반적으로 타입이 있는 언어와 타입이 없는(타입이 없는) 두 개의 큰 캠프로 나뉩니다. 첫 번째에는 C, Python, Scala, PHP 및 Lua가 포함되고 두 번째에는 어셈블리 언어인 Forth 및 Brainfuck이 포함됩니다.

"무타입 타이핑"은 본질적으로 플러그처럼 단순하기 때문에 더 이상 다른 유형으로 분류되지 않습니다. 그러나 입력된 언어는 몇 가지 더 겹치는 범주로 나뉩니다.

  • 정적/동적 타이핑. 정적은 변수와 함수의 최종 유형이 컴파일 타임에 설정된다는 사실로 정의됩니다. 저것들. 컴파일러는 이미 어떤 유형이 어디에 있는지 100% 확신합니다. 동적 타이핑에서는 프로그램 실행 중에 모든 유형이 발견됩니다.

    예:
    정적: C, 자바, C#;
    동적: Python, JavaScript, Ruby.

  • 강한/약한 타이핑(때때로 강한/느슨한 타이핑이라고도 함). 강력한 유형 지정은 언어가 표현식에 서로 다른 유형을 혼합하는 것을 허용하지 않고 자동 암시적 변환을 수행하지 않는다는 점에서 구별됩니다. 예를 들어 문자열에서 집합을 뺄 수 없습니다. 약한 유형의 언어는 정밀도 손실이 발생하거나 변환이 모호하더라도 자동으로 많은 암시적 변환을 수행합니다.

    예:
    강력함: Java, Python, Haskell, Lisp;
    약함: C, JavaScript, Visual Basic, PHP.

  • 명시적/암시적 유형 지정. 명시적 유형 언어는 새 변수/함수/해당 인수의 유형을 명시적으로 지정해야 한다는 점에서 다릅니다. 따라서 암시적 타이핑을 사용하는 언어는 이 작업을 컴파일러/인터프리터에게 맡깁니다.

    예:
    명시적: C++, D, C#
    암시적: PHP, Lua, JavaScript

예를 들어 C 언어에는 정적 약한 명시적 유형 지정이 있고 Python 언어에는 동적 강한 암시적 유형 지정이 있습니다.

그러나 정적 타이핑과 동적 타이핑이 동시에 가능한 언어는 없습니다. 앞을 내다 보면 내가 여기에 누워 있다고 말할 것입니다. 실제로 존재하지만 이에 대해서는 나중에 자세히 설명합니다.

상세 버전

짧은 버전이 충분하지 않다면 괜찮습니다. 내가 자세하게 쓴 게 괜히 있는 게 아니지? 가장 중요한 것은 모든 유용하고 흥미로운 정보를 짧은 버전에 넣는 것이 불가능했으며 자세한 정보는 모든 사람이 긴장하지 않고 읽기에는 너무 길다는 것입니다.

무형식 타이핑

유형이 없는 프로그래밍 언어에서 모든 엔터티는 단순히 다양한 길이의 비트 시퀀스로 간주됩니다.

유형 없는 타이핑은 일반적으로 저수준 언어(어셈블리 언어, Forth)와 난해한 언어(Brainfuck, HQ9, Piet)에 내재되어 있습니다. 그러나 단점과 함께 몇 가지 장점도 있습니다.

장점
  • 매우 낮은 수준에서 작성할 수 있으며 컴파일러/인터프리터는 유형 검사를 방해하지 않습니다. 모든 유형의 데이터에 대해 자유롭게 작업을 수행할 수 있습니다.
  • 결과 코드는 일반적으로 더 효율적입니다.
  • 지침의 투명성. 언어를 알고 있다면 일반적으로 이 코드나 해당 코드가 무엇인지 의심할 여지가 없습니다.
결함
  • 복잡성. 목록, 문자열, 구조체 등 복잡한 값을 표현해야 하는 경우가 많습니다. 불편을 끼칠 수 있습니다.
  • 수표가 부족합니다. 기호에서 배열에 대한 포인터를 빼는 것과 같은 의미 없는 작업은 완전히 정상적인 것으로 간주되며 미묘한 오류가 발생합니다.
  • 낮은 수준의 추상화. 복잡한 데이터 유형으로 작업하는 것은 숫자로 작업하는 것과 다르지 않으며, 이는 물론 많은 어려움을 야기합니다.
강력한 무형식 타이핑?

예, 존재합니다. 예를 들어, 어셈블리 언어(x86/x86-64 아키텍처의 경우 다른 것은 모르겠습니다)에서 rax 레지스터(64비트)의 데이터를 cx 레지스터(16비트)로 로드하려고 하면 프로그램을 어셈블할 수 없습니다. .

mov cx, eax ; 조립시간 오류

그럼 어셈블러에는 여전히 타이핑이 있다는 것이 밝혀졌나요? 나는 이러한 수표만으로는 충분하지 않다고 생각합니다. 물론 귀하의 의견은 귀하에게만 달려 있습니다.

정적 및 동적 타이핑

정적 유형 지정과 동적 유형 지정을 구별하는 가장 중요한 점은 모든 유형 검사가 런타임이 아닌 컴파일 타임에 수행된다는 것입니다.

어떤 사람들은 정적 타이핑이 너무 제한적이라고 생각할 수도 있습니다(사실 그렇습니다. 그러나 이것은 일부 기술의 도움으로 오랫동안 제거되었습니다). 어떤 사람들은 동적 타이핑 언어가 불장난을 하고 있다고 말하는데, 어떤 특징이 이 언어를 돋보이게 할까요? 두 종 모두 실제로 존재할 가능성이 있습니까? 그렇지 않다면 정적 및 동적으로 유형이 지정되는 언어가 왜 그렇게 많습니까?

그것을 알아 봅시다.

정적 유형 지정의 이점
  • 유형 검사는 컴파일 단계에서 한 번만 발생합니다. 즉, 숫자를 문자열로 나누려고 하는지(그리고 오류가 발생하는지 변환을 수행하는지) 끊임없이 알아낼 필요가 없습니다.
  • 실행 속도. 이전 시점에서 정적으로 유형이 지정된 언어는 거의 항상 동적으로 유형이 지정된 언어보다 빠르다는 것이 분명합니다.
  • 일부 추가 조건에서는 컴파일 단계에서 이미 잠재적인 오류를 감지할 수 있습니다.
동적 타이핑의 이점
  • 범용 컬렉션 생성 용이성 - 모든 것과 모든 사람의 힙(이러한 필요성은 거의 발생하지 않지만 동적 타이핑이 발생하면 도움이 될 것입니다).
  • 일반화된 알고리즘 설명의 편의성(예: 정수 목록뿐만 아니라 실수 목록, 심지어 문자열 목록에서도 작동하는 배열 정렬)
  • 배우기 쉬움 - 동적 유형 언어는 일반적으로 프로그래밍을 시작하는 데 매우 좋습니다.

일반화된 프로그래밍

좋아요, 동적 타이핑에 대한 가장 중요한 주장은 일반 알고리즘을 설명하는 편리함입니다. 문제를 상상해 봅시다. 정수 배열, 실수 배열, 문자 배열 등 여러 배열(또는 목록)을 검색하는 함수가 필요합니다.

어떻게 해결할까요? 3가지 다른 언어로 문제를 해결해 보겠습니다. 하나는 동적 타이핑이고 두 개는 정적 타이핑입니다.

가장 간단한 검색 알고리즘 중 하나인 무차별 대입을 사용하겠습니다. 이 함수는 검색 중인 요소, 배열(또는 목록) 자체를 수신하고 요소의 인덱스를 반환하거나 요소를 찾을 수 없는 경우 - (-1)을 반환합니다.

동적 솔루션(Python):

Def find(required_element, list): for (index, element) in enumerate(list): if element == 필수_element: return index return (-1)

보시다시피 모든 것이 간단하며 목록에 숫자, 목록 또는 기타 배열이 포함될 수 있다는 사실에는 문제가 없습니다. 매우 좋은. 더 나아가서 C에서 동일한 문제를 해결해 보세요!

정적 용액(C):

Unsigned int find_int(int 필수_요소, int 배열, unsigned int 크기) ( for (unsigned int i = 0; i< size; ++i) if (required_element == array[i]) return i; return (-1); } unsigned int find_float(float required_element, float array, unsigned int size) { for (unsigned int i = 0; i < size; ++i) if (required_element == array[i]) return i; return (-1); } unsigned int find_char(char required_element, char array, unsigned int size) { for (unsigned int i = 0; i < size; ++i) if (required_element == array[i]) return i; return (-1); }

글쎄, 각 함수는 개별적으로 Python 버전과 유사하지만 왜 세 개가 있습니까? 정적 프로그래밍이 실제로 손실되었습니까?

예, 아니오. 여러 가지 프로그래밍 기술이 있는데, 그 중 하나를 이제 살펴보겠습니다. 이를 일반 프로그래밍이라고 하며 C++ 언어는 이를 매우 잘 지원합니다. 새 버전을 살펴보겠습니다.

정적 솔루션(일반 프로그래밍, C++):

주형 unsigned int find(T 필수 요소, std::벡터 배열) ( for (unsigned int i = 0; i< array.size(); ++i) if (required_element == array[i]) return i; return (-1); }

괜찮은! Python 버전보다 훨씬 더 복잡해 보이지 않으며 많은 작성이 필요하지 않습니다. 또한 문제를 해결하는 데 필요한 3개 어레이뿐만 아니라 모든 어레이에 대한 구현을 얻었습니다!

이 버전은 우리에게 꼭 필요한 것 같습니다. 정적 타이핑의 장점과 동적 타이핑의 장점 중 일부를 모두 얻습니다.

이것이 가능하다는 것은 좋은 일이지만, 더 좋을 수도 있습니다. 첫째, 일반화된 프로그래밍이 더 편리하고 아름다울 수 있습니다(예: Haskell 언어 사용). 둘째, 일반화된 프로그래밍 외에도 다형성(결과가 더 나쁠 수 있음), 함수 오버로딩(유사) 또는 매크로를 사용할 수도 있습니다.

역학의 정적

또한 많은 정적 언어가 동적 타이핑을 허용한다는 점도 언급해야 합니다. 예를 들면 다음과 같습니다.

  • C#은 동적 의사 유형을 지원합니다.
  • F#은 동적 유형 지정을 모방할 수 있는 ? 연산자 형식의 설탕 구문을 지원합니다.
  • Haskell - 동적 타이핑은 Data.Dynamic 모듈에서 제공됩니다.
  • Delphi - 특별한 Variant 유형을 통해.

또한 일부 동적 유형 지정 언어를 사용하면 정적 유형 지정을 활용할 수 있습니다.

  • Common Lisp - 유형 선언.
  • Perl - 버전 5.6 이후로는 상당히 제한적입니다.

강한 타이핑과 약한 타이핑

강력한 유형의 언어는 서로 다른 유형의 엔터티가 표현식에 혼합되는 것을 허용하지 않으며 자동 변환을 수행하지 않습니다. "강력한 형식의 언어"라고도 합니다. 이에 대한 영어 용어는 강한 타이핑입니다.

반대로 약한 유형의 언어는 프로그래머가 하나의 표현식에 다양한 유형을 혼합하도록 권장하며 컴파일러 자체는 모든 것을 단일 유형으로 줄입니다. "느슨한 형식의 언어"라고도 합니다. 이에 대한 영어 용어는 약한 타이핑입니다.

약한 타이핑은 종종 완전히 잘못된 동적 타이핑과 혼동됩니다. 동적 유형 언어는 약한 유형 또는 강력한 유형일 수 있습니다.

그러나 엄격한 타이핑을 중요시하는 사람은 거의 없습니다. 언어가 정적으로 입력되면 컴파일할 때 많은 잠재적인 오류를 발견할 수 있다고 흔히 말합니다. 그들은 당신에게 거짓말을 하고 있습니다!

언어에는 강력한 타이핑도 있어야 합니다. 실제로 컴파일러가 오류를 보고하는 대신 단순히 숫자에 문자열을 추가하거나 더 나쁜 경우 한 배열에서 다른 문자열을 뺀다면 유형의 모든 "검사"가 컴파일 시에 수행된다는 것이 우리에게 무슨 소용이 있습니까? 단계? 맞습니다. 약한 정적 타이핑은 강력한 동적 타이핑보다 더 나쁩니다! (뭐, 그건 내 생각이다)

그렇다면 약한 타이핑에는 전혀 이점이 없습니까? 이렇게 보일 수도 있지만, 내가 강한 타이핑을 열렬히 지지한다는 사실에도 불구하고 약한 타이핑에도 장점이 있다는 점에는 동의해야 합니다.

어떤 것을 알고 싶으십니까?

강력한 타이핑의 이점
  • 신뢰성 - 잘못된 동작 대신 예외 또는 컴파일 오류가 발생합니다.
  • 속도 - 비용이 많이 들 수 있는 숨겨진 변환 대신 강력한 타이핑을 사용하여 명시적으로 작성해야 하며, 이로 인해 프로그래머는 최소한 이 코드 조각이 느릴 수 있다는 것을 알 수 있습니다.
  • 프로그램 작동 방식 이해 - 다시 말하지만, 프로그래머는 암시적 유형 캐스팅 대신 모든 것을 직접 작성합니다. 즉, 문자열과 숫자를 비교하는 일은 마술이 아니라 저절로 발생하지 않는다는 것을 대략적으로 이해합니다.
  • 확실성 - 손으로 변환을 작성할 때 무엇을 변환하고 무엇으로 변환하는지 정확히 알 수 있습니다. 또한 이러한 변환으로 인해 정밀도가 떨어지고 잘못된 결과가 발생할 수 있다는 점도 항상 알고 있어야 합니다.
약한 타이핑의 이점
  • 혼합 표현식 사용의 편리성(예: 정수와 실수)
  • 타이핑을 추상화하고 작업에 집중합니다.
  • 항목의 간결함.

좋아요, 우리는 그것을 알아냈습니다. 약한 타이핑에도 장점이 있다는 것이 밝혀졌습니다! 약한 타이핑의 장점을 강한 타이핑으로 전환할 수 있는 방법이 있나요?

두 개도 있다는 것이 밝혀졌습니다.

명확한 상황에서 데이터 손실 없이 암시적 유형 캐스팅

와... 꽤 긴 말이군요. "제한된 암시적 변환"으로 더 줄여보겠습니다. 그러면 명확한 상황과 데이터 손실은 무엇을 의미합니까?

모호하지 않은 상황은 본질이 즉각적으로 명확한 변형이나 작업입니다. 예를 들어 두 개의 숫자를 추가하는 것은 명확한 상황입니다. 그러나 숫자를 배열로 변환하는 것은 그렇지 않습니다. 아마도 한 요소의 배열이 생성될 것입니다. 아마도 이러한 길이의 배열은 기본적으로 요소로 채워지고 숫자는 문자열로 변환된 다음 배열로 변환될 것입니다. 문자).

데이터를 잃는 것이 훨씬 더 쉽습니다. 실수 3.5를 정수로 변환하면 데이터의 일부가 손실됩니다(사실 이 연산도 모호합니다. 반올림은 어떻게 수행됩니까? 위로? 아래로? 분수 부분을 버리나요?).

모호한 상황에서의 변환과 데이터 손실이 있는 변환은 매우 나쁩니다. 프로그래밍에서 이보다 더 나쁜 것은 없습니다.

내 말을 믿을 수 없다면 PL/I 언어를 공부하거나 사양을 찾아보세요. 모든 데이터 유형 간 변환에 대한 규칙이 있습니다! 이건 그냥 지옥이야!

좋아요, 제한된 암시적 변환에 대해 기억해 봅시다. 그런 언어도 있나요? 예, 예를 들어 Pascal에서는 정수를 실수로 변환할 수 있지만 그 반대는 불가능합니다. C#, Groovy 및 Common Lisp에도 유사한 메커니즘이 있습니다.

좋아, 나는 강력한 언어에서 약한 타이핑의 몇 가지 장점을 얻을 수 있는 방법이 아직 있다고 말했습니다. 그리고 그렇습니다. 그것은 존재하며 생성자 다형성이라고 불립니다.

훌륭한 하스켈 언어의 예를 들어 설명하겠습니다.

다형성 생성자는 숫자 리터럴을 사용할 때 안전한 암시적 변환이 가장 자주 필요하다는 관찰에서 탄생했습니다.

예를 들어, pi + 1 표현식에서 pi + 1.0 또는 pi + float(1) 을 쓰고 싶지 않을 것입니다. 나는 단지 pi + 1을 쓰고 싶습니다!

그리고 이것은 리터럴 1에 구체적인 유형이 없기 때문에 Haskell에서 수행됩니다. 그것은 전체도 아니고 실제도 아니며 복잡하지도 않습니다. 그것은 단지 숫자일 뿐입니다!

결과적으로 간단한 함수 sum x y 를 작성하고 x에서 y까지의 모든 숫자(1씩 증분)를 곱하면 한 번에 여러 버전을 얻게 됩니다. 정수의 합, 실수의 합, 유리수의 합, 복소수의 합 그리고 여러분이 직접 정의한 모든 숫자 유형의 합계도 계산할 수 있습니다.

물론 이 기술은 숫자 리터럴이 포함된 혼합 표현식을 사용할 때만 비용을 절감하며 이는 빙산의 일각에 불과합니다.

따라서 가장 좋은 해결책은 강한 타이핑과 약한 타이핑 사이의 경계에서 균형을 맞추는 것이라고 말할 수 있습니다. 하지만 아직 완벽한 균형을 이루는 언어는 없기 때문에 약한 유형의 언어(예: C, JavaScript, Lua, PHP)보다는 강력한 유형의 언어(예: Haskell, Java, C#, Python)에 더 의지합니다.

명시적 및 암시적 입력

명시적으로 유형이 지정된 언어에서는 프로그래머가 선언하는 모든 변수 및 함수의 유형을 지정해야 합니다. 이에 대한 영어 용어는 명시적 타이핑입니다.

반면에 암시적으로 유형이 지정된 언어는 유형을 잊어버리고 유형 추론 작업을 컴파일러나 해석기에 맡기도록 권장합니다. 이에 대한 영어 용어는 암시적 타이핑입니다.

처음에는 암시적 유형 지정이 동적과 동일하고 명시적 유형 지정이 정적과 동일하다고 생각할 수 있지만 나중에는 그렇지 않다는 것을 알게 됩니다.

각 유형마다 장점이 있나요? 그리고 또 이들의 조합이 있나요? 두 가지 방법을 모두 지원하는 언어가 있나요?

명시적 입력의 이점
  • 각 함수에 서명(예: int add(int, int))이 있으면 함수가 수행하는 작업을 쉽게 확인할 수 있습니다.
  • 프로그래머는 특정 변수에 어떤 유형의 값을 저장할 수 있는지 즉시 기록하므로 이를 기억할 필요가 없습니다.
암시적 유형 지정의 이점
  • 약식 표기법 - def add(x, y) 는 int add(int x, int y) 보다 분명히 짧습니다.
  • 변화에 대한 저항. 예를 들어, 함수에서 임시 변수가 입력 인수와 동일한 유형인 경우 명시적으로 유형이 지정된 언어에서는 입력 인수의 유형을 변경할 때 임시 변수의 유형도 변경해야 합니다.

좋습니다. 두 접근 방식 모두 장단점이 있다는 것은 분명합니다(누가 또 예상했겠습니까?). 따라서 이 두 접근 방식을 결합하는 방법을 찾아보겠습니다!

선택에 의한 명시적 입력

기본적으로 암시적 타이핑이 가능한 언어와 필요한 경우 값 유형을 지정할 수 있는 기능이 있습니다. 번역기는 실제 유형의 표현식을 자동으로 출력합니다. 이러한 언어 중 하나는 Haskell입니다. 명확성을 위해 간단한 예를 들어 보겠습니다.

명시적 유형 지정 없이 add (x, y) = x + y -- 명시적 유형 지정 add:: (Integer, Integer) -> Integer add (x, y) = x + y

참고: 저는 의도적으로 커링되지 않은 함수를 사용했으며 더 일반적인 add::: (Num a) -> a -> a -> a 대신 의도적으로 개인 서명을 작성했습니다. 하스켈 구문을 설명하지 않고 아이디어를 보여주고 싶었습니다.

흠. 보시다시피 매우 훌륭하고 짧습니다. 함수를 작성하려면 공백을 포함하여 한 줄에 18자만 입력하면 됩니다!

그러나 자동 유형 추론은 상당히 복잡한 일이며 Haskell과 같은 멋진 언어에서도 때때로 실패합니다. (예는 단형성 제약 조건입니다)

기본적으로 명시적 타이핑이 있고 필요한 경우 암시적 타이핑이 있는 언어가 있나요? 범죄자
확신하는.

선택에 따른 암시적 입력

C++11(이전에는 C++0x라고 함)이라는 새로운 C++ 언어 표준에는 컴파일러가 컨텍스트를 기반으로 형식을 추론할 수 있도록 하는 auto 키워드가 도입되었습니다.

비교해 보겠습니다. // unsigned 유형을 수동으로 지정 int a = 5; 부호 없는 int b = a + 3; // unsigned int a = 5 유형의 자동 출력; 자동 b = a + 3;

나쁘지 않다. 하지만 기록은 크게 줄지 않았다. 반복자가 포함된 예를 살펴보겠습니다(이해하지 못하더라도 걱정하지 마세요. 가장 중요한 점은 자동 출력 덕분에 녹음이 크게 줄어든다는 것입니다).

// std::Vector 유형을 수동으로 지정 vec = 무작위벡터(30); for (std::Vector::const_iterator it = vec.cbegin(); ...) ( ... ) // 자동 유형 추론 auto vec = randomVector (서른); for (auto it = vec.cbegin(); ...) ( ... )

우와! 이것이 약어입니다. 좋아, 하지만 반환 유형이 인수 유형에 따라 달라지는 Haskell과 같은 작업을 수행하는 것이 가능합니까?

그리고 대답은 '예'입니다. auto와 결합된 decltype 키워드 덕분입니다.

// 수동 유형 int Divide(int x, int y) ( ... ) // 자동 유형 추론 auto Divide(int x, int y) -> decltype(x / y) ( ... )

이러한 형태의 표기법은 별로 좋아 보이지 않을 수 있지만 일반 프로그래밍(템플릿/제네릭)과 결합하면 암시적 유형 지정 또는 자동 유형 추론이 놀라운 효과를 발휘합니다.

이 분류에 따른 일부 프로그래밍 언어

나는 인기있는 언어의 작은 목록을 제공하고 "타이핑"의 각 범주로 어떻게 나누어지는지 쓸 것입니다.

JavaScript - 동적 / 약함 / 암시적 Ruby - 동적 / 강력 / 암시적 Python - 동적 / 강력 / 암시적 Java - 정적 / 강력 / 명시적 PHP - 동적 / 약 / 암시적 C - 정적 / 약 / 명시적 C++ - 정적 / 준강함 / 명시적 Perl - 동적 / 약함 / 암시적 Objective-C - 정적 / 약함 / 명시적 C# - 정적 / 강력 / 명시적 Haskell - 정적 / 강력 / 암시적 Common Lisp - 동적 / 강력 / 암시적

특히 CL, PHP 및 Obj-C에서 실수를 저질렀을 수도 있습니다. 일부 언어에 대해 다른 의견이 있으면 의견을 적어주세요.

결론

좋아요. 곧 가벼워질 것이고 타이핑에 대해서는 더 이상 할 말이 없다는 느낌이 듭니다. 아 어떻게요? 주제가 끝이 없나요? 말하지 않은 것이 많이 남아 있습니까? 댓글로 유용한 정보를 공유해주세요.

전제 조건

엄격한 입력은 다음 필수 조건이 충족됨을 의미합니다.

  1. 언어의 모든 데이터 객체(변수, 상수, 표현식)는 항상 엄격하게 정의된 유형을 가지며, 이는 프로그램 컴파일 시 고정되거나(정적 유형 지정) 런타임 시 결정됩니다(동적 유형 지정).
  2. 변수와 정확히 동일한 데이터 유형을 가진 값만 변수에 할당할 수 있으며, 매개변수 전달 및 함수 결과 반환에도 동일한 제한이 적용됩니다.
  3. 각 작업에는 엄격하게 정의된 유형의 매개변수가 필요합니다.
  4. 암시적 유형 변환은 허용되지 않습니다. 즉, 변환기는 변수, 매개변수, 함수 또는 연산에 대해 선언된 유형 값이 아닌 유형의 값을 사용하려는 모든 시도를 구문 오류로 처리합니다.

엄격한 입력 요구 사항을 엄격하게 준수하면 값 구성과 허용되는 작업이 동일한 데이터 유형이라도 호환되지 않습니다. 프로그램이 한 데이터 유형의 값을 다른 유형의 변수에 할당해야 하는 경우 이를 수행할 수 있지만 이는 일반적으로 프로그래밍 언어의 일부인 특별한 유형 변환 작업을 명시적으로 적용해야만 가능합니다. 공식적으로는 아니지만 표준 라이브러리에서 제공됩니다).

프로그래밍 언어로 입력하기

연결

또한보십시오


위키미디어 재단. 2010.

다른 사전에 "강력한 타이핑"이 무엇인지 확인하십시오.

    데이터 유형은 프로그래밍 이론의 기본 개념입니다. 데이터 유형은 값 집합, 해당 값에 적용될 수 있는 작업 집합, 값 저장 및 작업 수행을 구현하는 방법을 정의합니다. 뭐든... ... 위키피디아

    데이터 타이핑 유형 안전성 유형 추론 동적 타이핑 정적 타이핑 강력한 타이핑 소프트 타이핑 종속 유형 오리 타이핑 주요 기사: 강력한 타이핑 동적 타이핑은 널리 사용되는 기술입니다... ... Wikipedia

    데이터 타이핑 유형 안전성 유형 추론 동적 타이핑 정적 타이핑 강력한 타이핑 소프트 타이핑 종속 유형 오리 타이핑 주요 기사: 강력한 타이핑 정적 타이핑은 널리 사용되는 기술입니다... ... Wikipedia

    동적 타이핑(Dynamic Typing)은 프로그래밍 언어나 명세 언어에서 널리 사용되는 기술로, 변수를 선언하는 순간이 아닌 값을 할당하는 순간에 변수가 타입과 연관되는 방식이다. 따라서 다양한 분야에서 ... Wikipedia

    데이터 타이핑 유형 안전성 유형 추론 동적 타이핑 정적 타이핑 강력한 타이핑 소프트 타이핑 종속 유형 오리 타이핑 프로그래밍의 유형 추론은 컴파일러 기능입니다... ... Wikipedia

    데이터 타이핑 유형 안전성 유형 추론 동적 타이핑 정적 타이핑 강력한 타이핑 소프트 타이핑 종속 유형 덕 타이핑 종속 유형, 컴퓨터 과학 및 논리에서 값에 의존하는 유형입니다. 부양가족... ... 위키피디아

    - (데이터 유형이라는 용어도 발견됨)은 프로그래밍 이론의 기본 개념입니다. 데이터 유형은 값 집합, 해당 값에 적용될 수 있는 작업 집합, 값 저장을 구현하는 방법 및... ... Wikipedia를 정의합니다.

    데이터 유형 내용 1 역사 2 정의 3 데이터 유형 사용의 필요성 ... Wikipedia

    이 용어에는 다른 의미도 있습니다. ML(의미)을 참조하세요. ML 의미: 다중 패러다임: 기능적, 명령형, 모듈형 등장: 1973년 저자: Robin Milner et al. University of Edinburgh ... Wikipedia