새로운 프로그래밍 언어가 동적으로 입력된다는 이야기를 많이 들었지만 언어가 동적으로 입력된다고 말할 때 실제로 의미하는 것은 무엇입니까?
새로운 프로그래밍 언어가 동적으로 입력된다는 이야기를 많이 들었지만 언어가 동적으로 입력된다고 말할 때 실제로 의미하는 것은 무엇입니까?
답변:
컴파일 타임에 변수의 유형을 알면 언어는 정적으로 입력됩니다. 일부 언어의 경우 프로그래머가 각 변수의 유형을 지정해야합니다 (예 : Java, C, C ++). 다른 언어는 어떤 형태의 형태 추론 , 변수의 형태를 추론 할 수있는 형태 시스템의 기능을 제공합니다 (예 : OCaml, Haskell, Scala, Kotlin)
여기서 가장 큰 장점은 모든 종류의 검사가 컴파일러에 의해 수행 될 수 있기 때문에 매우 사소한 버그가 매우 초기 단계에서 발견된다는 것입니다.
예 : C, C ++, Java, Rust, Go, Scala
유형이 변수 / 필드 / 등이 아닌 런타임 값과 연관된 경우 언어는 동적으로 유형이 지정됩니다. 즉, 타입 추론 과 함께 정적으로 형식이 지정된 언어를 사용하지 않는 한 매번 유형을 지정할 필요가 없으므로 프로그래머가 조금 더 빨리 작성할 수 있습니다 .
예 : Perl, Ruby, Python, PHP, JavaScript
정적 타입 검사를 수행하는 컴파일러가 없기 때문에 대부분의 스크립팅 언어에는이 기능이 있지만, 인터프리터가 변수 유형을 잘못 해석하여 발생하는 버그를 스스로 찾을 수 있습니다. 운 좋게도 스크립트는 작기 때문에 버그가 숨길 곳이 많지 않습니다.
대부분의 동적 유형 언어를 사용하면 유형 정보를 제공 할 수 있지만 필수는 아닙니다. 현재 개발중인 언어 중 하나 인 Rascal 은 함수 내에서 동적 타이핑을 허용하지만 함수 시그니처에 정적 타이핑을 적용하는 하이브리드 방식을 사용합니다.
정적으로 유형이 지정된 프로그래밍 언어는 런타임 과 달리 컴파일 타임에 유형 검사 (즉, 유형의 제약 조건을 확인 및 적용하는 프로세스) 를 수행합니다 .
동적 타입 프로그래밍 언어는 컴파일 타임 과 달리 런타임에 타입 검사를 수행 합니다 .
정적으로 유형이 지정된 언어의 예는 다음과 같습니다 .- Java, C, C ++
동적 형식 언어의 예는 다음과 같습니다 .- Perl, Ruby, Python, PHP, JavaScript
다음은 Python (동적 형식)과 Go (정적 형식)가 형식 오류를 처리하는 방법과 대조되는 예입니다.
def silly(a):
if a > 0:
print 'Hi'
else:
print 5 + '3'
파이썬은 런타임에 타입 검사를하기 때문에 :
silly(2)
완벽하게 잘 실행되고 예상 출력을 생성합니다 Hi
. 문제가있는 줄에 도달 한 경우에만 오류가 발생합니다.
silly(-1)
생산
TypeError: unsupported operand type(s) for +: 'int' and 'str'
관련 라인이 실제로 실행 되었기 때문입니다.
반면에 컴파일 타임에는 유형 검사가 수행됩니다.
package main
import ("fmt"
)
func silly(a int) {
if (a > 0) {
fmt.Println("Hi")
} else {
fmt.Println("3" + 5)
}
}
func main() {
silly(2)
}
위의 오류는 다음 오류와 함께 컴파일되지 않습니다.
invalid operation: "3" + 5 (mismatched types string and int)
runhaskell
예를 들어 Haskell은로 해석 될 수 있습니다 .
정적 방식 으로 언어 변수의 유형은 정적 이므로 변수를 유형으로 설정하면 변경할 수 없습니다. 이는 타이핑이 참조하는 값이 아니라 변수와 연관되어 있기 때문입니다.
예를 들어 Java의 경우 :
String str = "Hello"; //variable str statically typed as string
str = 5; //would throw an error since str is supposed to be a string only
반면에 동적으로 유형이 지정된 언어 변수의 유형이 dynamic 인 경우 변수를 유형으로 설정하면 변수를 변경할 수 있습니다. 타이핑은 변수 자체가 아니라 가정하는 값과 관련이 있기 때문입니다.
예를 들어 파이썬에서 :
str = "Hello" # variable str is linked to a string value
str = 5 # now it is linked to an integer value; perfectly OK
따라서 동적으로 유형이 지정된 언어의 변수 를 유형이 지정된 값에 대한 일반적인 포인터 로 생각하는 것이 가장 좋습니다 .
요약하면, 유형 자체는 언어 자체가 아닌 언어로 변수를 설명하거나 설명해야합니다. 그것은 더 나은로 사용할 수 있었던 정적으로 입력 된 변수 언어 에 비해 동적으로 입력 변수와 언어 IMHO.
정적으로 형식화 된 언어는 일반적으로 컴파일 된 언어이므로 컴파일러는 형식을 확인합니다 (나중에 런타임에 형식을 변경할 수 없으므로 완벽하게 이해됩니까?).
동적으로 유형이 지정된 언어는 일반적으로 해석되므로 사용시 런타임에 유형 검사 (있는 경우)가 발생합니다. 물론 이것은 약간의 성능 비용을 가져오고 동적 언어 (예 : python, ruby, php)가 유형이 지정된 언어 (java, c # 등)만큼 확장되지 않는 이유 중 하나입니다. 다른 관점에서 볼 때 정적으로 형식이 지정된 언어는 시작 비용이 더 많이 듭니다. 일반적으로 더 많은 코드를 작성하고 더 어려운 코드를 작성합니다. 그러나 그것은 나중에 지불합니다.
좋은 점은 양쪽이 다른 쪽에서 기능을 빌리는 것입니다. 유형이 지정된 언어는 c #의 제네릭 및 동적 라이브러리와 같이 더 동적 인 기능을 통합하고 있으며, 동적 언어에는 더 많은 유형 검사 (예 : Python의 유형 주석 또는 PHP의 HACK 변형)가 포함되어 있습니다. 수요.
기술 선택과 관련하여 어느 쪽도 다른 쪽보다 본질적인 우월성을 가지고 있지 않습니다. 더 많은 제어를 시작하거나 유연성을 원하는지 여부는 선호의 문제입니다. 작업에 적합한 도구를 선택하고 스위치를 고려하기 전에 반대의 관점에서 사용 가능한 도구를 확인하십시오.
http://en.wikipedia.org/wiki/Type_system
정적 타이핑
프로그래밍 언어는 런타임과 달리 컴파일 타임 동안 유형 검사가 수행 될 때 정적 타이핑을 사용한다고합니다. 정적 타이핑에서 유형은 값이 아닌 변수와 연관됩니다. 정적으로 유형이 지정된 언어에는 Ada, C, C ++, C #, JADE, Java, Fortran, Haskell, ML, Pascal, Perl (스칼라, 배열, 해시 및 서브 루틴 구별과 관련하여) 및 스칼라가 포함됩니다. 정적 타이핑은 제한된 형태의 프로그램 검증입니다 (유형 안전 참조). 따라서 개발주기 초기에 많은 유형 오류가 포착 될 수 있습니다. 정적 타입 체커는 컴파일 타임에 결정될 수있는 타입 정보 만 평가하지만, 체크 된 조건이 프로그램의 모든 가능한 실행을 위해 유지되는지 확인할 수 있습니다. 따라서 프로그램이 실행될 때마다 유형 검사를 반복 할 필요가 없습니다. 런타임 유형 검사를 생략하고 다른 최적화를 활성화하여 프로그램 실행을보다 효율적으로 (즉, 더 빠르거나 메모리를 줄임) 수행 할 수 있습니다.
컴파일하는 동안 유형 정보를 평가하므로 런타임시에만 사용할 수있는 유형 정보가 없기 때문에 정적 유형 검사기는 보수적입니다. 런타임에 제대로 작동하지만 정적으로 유형이 정해지지 않은 일부 프로그램은 거부합니다. 예를 들어, 런타임에식이 항상 true로 평가 되더라도 코드가 포함 된 프로그램
if <complex test> then 42 else <type error>
정적 분석은 else 분기가 수행되지 않을 것이라고 판단 할 수 없기 때문에 잘못된 유형으로 거부됩니다. [1] 정적 유형 검사기의 보수적 인 동작은 자주 false로 평가 될 때 유리합니다. 정적 유형 검사기는 거의 사용되지 않는 코드 경로에서 유형 오류를 감지 할 수 있습니다. 정적 유형 검사가 없으면 100 % 코드 적용 범위의 코드 적용 범위 테스트에서도 이러한 유형 오류를 찾지 못할 수 있습니다. 값이 생성되는 모든 장소와 특정 값이 사용되는 모든 장소의 조합을 고려해야하므로 코드 적용 범위 테스트에서 이러한 유형 오류를 감지하지 못할 수 있습니다.
가장 널리 사용되는 정적 형식 언어는 형식적으로 안전하지 않습니다. 프로그래밍 언어 사양에는 "루프 홀 (loopholes)"이있어 프로그래머는 정적 유형 검사기에서 수행 한 확인을 우회하여 더 넓은 범위의 문제를 해결할 수있는 코드를 작성할 수 있습니다. 예를 들어 Java 및 대부분의 C 스타일 언어에는 유형이 punning이고 Haskell에는 unsafePerformIO와 같은 기능이 있습니다. 이러한 작업은 프로그램 실행시 값을 잘못 입력하여 원하지 않는 동작을 유발할 수 있으므로 런타임시 안전하지 않을 수 있습니다.
동적 타이핑
프로그래밍 언어는 대부분의 유형 검사가 컴파일 타임이 아닌 런타임에 수행 될 때 동적으로 유형이 지정되거나 '동적'이라고합니다. 동적 타이핑에서 유형은 변수가 아닌 값과 연관됩니다. 동적 유형 언어에는 Groovy, JavaScript, Lisp, Lua, Objective-C, Perl (사용자 정의 유형과 관련이 있지만 내장 유형은 아님), PHP, Prolog, Python, Ruby, Smalltalk 및 Tcl이 포함됩니다. 정적 타이핑과 비교할 때, 동적 타이핑은 (예를 들어 프로그램이 런타임 데이터를 기반으로 유형과 기능을 생성 할 수있게함으로써)보다 유연 할 수 있지만, 선험적 보장은 줄어 듭니다. 동적 유형 언어는 정적 유형 검사기에 의해 유효하지 않은 것으로 판명 될 수있는 일부 프로그램을 받아들이고 실행하려고하기 때문입니다.
동적 유형 지정으로 인해 런타임 유형 오류가 발생할 수 있습니다. 즉, 런타임시 값에 예기치 않은 유형이있을 수 있으며 해당 유형에 맞지 않는 조작이 적용됩니다. 이 작업은 프로그래밍 실수가 발생한 장소, 즉 잘못된 유형의 데이터가 가지고 있지 않은 장소로 전달 된 장소 이후에 오랫동안 발생할 수 있습니다. 이로 인해 버그를 찾기가 어렵습니다.
정적 유형의 사촌과 비교하여 동적 유형의 언어 시스템은 소스 코드에 대한 "컴파일 타임"점검 횟수를 줄입니다 (단, 프로그램이 구문 상 올바른지 확인합니다). 런타임 검사는 동적 정보와 컴파일 중에 있던 정보를 사용할 수 있으므로 잠재적으로 더 정교해질 수 있습니다. 반면에 런타임 검사는 특정 프로그램 실행에서 조건이 유지된다고 단언하며,이 검사는 프로그램이 실행될 때마다 반복됩니다.
동적 유형 언어의 개발은 종종 단위 테스트와 같은 프로그래밍 방식에 의해 지원됩니다. 테스트는 전문 소프트웨어 개발의 핵심 관행이며 특히 동적으로 입력되는 언어에서 중요합니다. 실제로 올바른 프로그램 작동을 보장하기 위해 수행 된 테스트는 정적 유형 검사보다 훨씬 넓은 범위의 오류를 감지 할 수 있지만 반대로 테스트 및 정적 유형 검사가 감지 할 수있는 오류를 종합적으로 검색 할 수는 없습니다. 테스트는 소프트웨어 빌드주기에 통합 될 수 있으며,이 경우 프로그램 사용자는 수동으로 테스트를 실행할 필요가 없다는 점에서 "컴파일 타임"검사로 간주 될 수 있습니다.
참고 문헌
- 피어스, 벤자민 (2002). 유형과 프로그래밍 언어. MIT Press. ISBN 0-262-16209-1.
myObject[remoteDataName]
. 그러면 어떤 속성을 선택하거나 유효한 속성인지 알 수있는 방법이 없습니다.
"동적 타입"이라는 용어는 불행히도 오해의 소지가 있습니다. 모든 언어는 정적으로 유형이 지정되며 유형은 표현식의 속성입니다 (일부 생각에 따라 값이 아님). 그러나 일부 언어에는 한 가지 유형 만 있습니다. 이것을 단일 유형 언어라고합니다. 이러한 언어의 한 예는 형식화되지 않은 람다 미적분입니다.
유형이 지정되지 않은 람다 미적분학에서 모든 항은 람다 항이며 항에 대해 수행 할 수있는 유일한 연산은 다른 항에 적용하는 것입니다. 따라서 모든 연산은 항상 무한 재귀 또는 람다 항을 초래하지만 오류를 나타내지 않습니다.
그러나 우리는 프리미티브 숫자와 산술 연산으로 타입이 지정되지 않은 람다 미적분을 보강해야했고, 두 개의 람다 항을 함께 추가하는 것과 같이 무의미한 연산을 수행 할 수있었습니다 (λx.x) + (λy.y)
. 이 일이 발생할 때 오류를 알리는 것이 유일한 제정신 일이라고 주장 할 수 있지만,이를 수행하려면 각 값에 용어가 람다 용어인지 숫자인지를 나타내는 표시기로 태그를 지정해야합니다. 덧셈 연산자는 실제로 두 인수가 모두 숫자로 태그되어 있는지 확인하고, 그렇지 않으면 오류를 표시합니다. 이러한 태그는 유형 이 아닙니다. 유형은 해당 프로그램에서 생성 된 값이 아니라 프로그램의 속성이기 때문입니다.
이를 수행하는 단일 유형 언어를 동적 유형이라고합니다.
JavaScript, Python 및 Ruby와 같은 언어는 모두 단일 유형입니다. 다시 한 번 typeof
JavaScript 의 연산자와 type
Python 의 함수에는 잘못된 이름이 있습니다. 타입이 아닌 피연산자와 관련된 태그를 반환합니다. 마찬가지로 dynamic_cast
C ++ 및 instanceof
Java 에서는 유형 검사를 수행하지 않습니다 .
"소스 코드가 번역 될 때"
"유형을 확인할 때"
5 + '3'
Go 및 Python과 같은 강력한 유형의 언어 에서 유형 오류의 예입니다. "유형 강제"-> 두 유형 병합과 같은 특정 컨텍스트에서 유형을 변경할 수있는 기능을 허용하지 않기 때문입니다. JavaScript와 같이 약한 유형의 언어는 유형 오류를 발생시키지 않습니다 (결과 '53'
).
"Static & Compiled"와 "Dynamic & Interpreted"의 정의는 매우 유사하지만 "유형을 확인할 때"와 "소스 코드가 번역 될 때"라는 것을 기억하십시오.
언어가 컴파일 또는 해석되는지에 관계없이 동일한 유형의 오류가 발생합니다 ! 이 용어들을 개념적으로 분리해야합니다.
동적, 해석
def silly(a):
if a > 0:
print 'Hi'
else:
print 5 + '3'
silly(2)
파이썬은 해석되고 동적으로 유형이 지정되므로 실행중인 코드 만 변환하고 유형을 확인합니다. else
실행하지 블록, 그래서 5 + '3'
도 보았다되지 않습니다!
정적으로 입력하면 어떻게 되나요?
코드가 실행되기 전에 유형 오류가 발생합니다. 해석 되기는하지만 런타임 전에 타입 검사를 수행합니다.
컴파일되면 어떻게 되나요?
else
블록은 / 번역 런타임 전에 보았다하지만, 동적 입력 있기 때문에이 오류가 발생하지 않을 것입니다! 동적 유형 언어는 실행 전까지 유형을 확인하지 않으며 해당 행은 절대 실행되지 않습니다.
정적, 컴파일
package main
import ("fmt"
)
func silly(a int) {
if (a > 0) {
fmt.Println("Hi")
} else {
fmt.Println("3" + 5)
}
}
func main() {
silly(2)
}
실행하기 전에 유형을 확인하고 (정적) 유형 오류가 즉시 포착됩니다! 해석 된 경우 런타임 전에 유형을 계속 점검하여 동일한 결과를 얻습니다. 동적 인 경우 컴파일 중에 코드를 보더라도 오류가 발생하지 않습니다.
컴파일 된 언어는 정적으로 유형이 지정되면 (동적 대) 런타임에 성능이 향상됩니다. 타입에 대한 지식은 머신 코드 최적화를 가능하게합니다.
정적으로 유형이 지정된 언어는 실행하는 동안 유형을 동적으로 확인할 필요가 없기 때문에 런타임시 본질적으로 성능이 향상됩니다 (실행하기 전에 확인).
마찬가지로, 컴파일 된 언어는 코드가 즉시 "통역"/ 번역 할 필요없이 이미 번역 되었기 때문에 런타임에 더 빠릅니다.
컴파일 된 언어와 정적으로 형식화 된 언어는 각각 번역 및 형식 검사를 실행하기 전에 지연이 발생합니다.
정적 타이핑은 실행 중에 오류를 찾는 대신 오류를 조기에 포착합니다 (특히 긴 프로그램에 유용함). 프로그램의 어느 곳에서나 유형 오류를 허용하지 않으며 종종 변수가 유형을 변경하지 못하게하여 의도하지 않은 오류를 방지하는 점에서 더 "엄격합니다".
num = 2
num = '3' // ERROR
다이나믹 한 타이핑이 더 유연하여 일부 사람들은 높이 평가합니다. 일반적으로 변수가 유형을 변경하여 예기치 않은 오류가 발생할 수 있습니다.
정적 유형 언어는 컴파일 타임에 유형 검사를 수행하며 유형을 변경할 수 없습니다. (타입 캐스팅 주석으로 귀여워하지 마십시오. 새로운 변수 / 참조가 생성됩니다).
동적 타입 언어는 런타임에 타입 검사를하고 변수 타입은 런타임에 변경할 수 있습니다.
정교하고 간단한 정의이지만 요구 사항에 적합 : 정적으로 형식이 지정된 언어는 형식을 전체 범위의 변수에 바인딩합니다 (예 : SCALA) 동적으로 형식이 지정된 언어는 변수가 참조하는 실제 값에 형식을 바인딩합니다.
C ++, Java와 같은 정적 유형 언어 및 Python과 같은 동적 유형 언어는 변수 유형의 실행 측면에서만 다릅니다. 정적으로 입력 된 언어는 여기에 데이터 형식 디버깅이 훨씬 간단 있도록 반면 ... 컴파일시 체크, 변수에 대한 정적 데이터 유형이 동적으로 입력 한 동일한 작업을 수행하지 않는 언어, 데이터 유형이 확인되는 따라서 프로그램과 프로그램을 실행 디버깅은 약간 어렵습니다.
더욱이 그것들은 매우 작은 차이를 가지고 있으며 강력하게 타이핑 되고 약한 타이핑 된 언어 와 관련 될 수 있습니다 . 강력한 형식의 언어를 사용하면 한 형식을 다른 형식으로 사용할 수 없습니다. C 및 C ++ ... 약한 유형의 언어는 예를 들어 python을 허용합니다.
정적으로 입력
런타임 전에 유형을 확인하여 실수를 조기에 발견 할 수 있습니다.
예 = c ++
동적 유형
실행하는 동안 유형이 확인됩니다.
예 = Python
정적 입력 : Java 및 Scala와 같은 언어는 정적 유형입니다.
변수는 코드에서 사용되기 전에 정의되고 초기화되어야합니다.
예를 들어. int x; x = 10;
System.out.println (x);
동적 입력 : Perl은 동적 유형 언어입니다.
코드에서 변수를 사용하기 전에 변수를 초기화 할 필요가 없습니다.
y = 10; 코드의 후반부에서이 변수를 사용하십시오.
$
), 배열 ( @
) 및 해시 ( %
)의 3 가지 유형이 있습니다 . Perl의 변수 유형은 컴파일 타임에 알려져 있으며 나머지 변수 수명 동안 동일하게 유지됩니다.