동적 유형 언어는 단일 유형입니다
타입 시스템을 비교할 때 동적 타이핑에는 이점이 없습니다. 동적 타이핑은 정적 타이핑의 특별한 경우입니다 . 모든 변수가 동일한 유형을 갖는 정적 타입 언어입니다. 모든 변수를 유형 Object
으로하고 "객체"값을 유형으로 하여 Java에서 동일한 것을 달성 할 수 있습니다 (간결함) Map<String, Object>
.
void makeItBark(Object dog) {
Map<String, Object> dogMap = (Map<String, Object>) dog;
Runnable bark = (Runnable) dogMap.get("bark");
bark.run();
}
따라서 리플렉션이 없어도 거의 정적으로 유형이 지정된 언어에서 구문상의 편의성을 제외하고 동일한 효과를 얻을 수 있습니다. 추가적인 표현력을 얻지 못하고 있습니다. 반대로, 동적으로 유형이 지정된 언어에서는 변수를 특정 유형으로 제한하는 기능 이 거부 되므로 표현력 이 떨어 집니다.
정적으로 입력 된 언어로 오리 껍질 만들기
또한 정적으로 형식이 좋은 언어를 사용하면 작업이있는 모든 유형에서 작동하는 코드를 작성할 수 있습니다 bark
. Haskell에서 이것은 유형 클래스입니다.
class Barkable a where
bark :: a -> unit
이는 어떤 유형 a
이 Barkable로 간주 되려면 bark
해당 유형의 값을 가져오고 아무것도 반환하지 않는 함수 가 있어야 한다는 제약 조건을 나타냅니다.
그런 다음 Barkable
제약 조건 에서 일반 함수를 작성할 수 있습니다 .
makeItBark :: Barkable a => a -> unit
makeItBark barker = bark (barker)
이것은 요구 사항을 makeItBark
충족시키는 모든 유형에 적용 Barkable
됩니다. 이것은 유사 보일 수 있습니다 interface
자바 나 C #에서하지만 하나의 큰 장점이 있습니다 - 유형은 지정하지 않아도 앞까지 그들이 만족 형 클래스를. 필자가 작성하지 않은 타사 유형 이라도 언제든지 유형 Duck
이 있다고 말할 수 있습니다 . 실제로 작성자가 함수를 작성하지 않았다는 것은 중요하지 않습니다 . 만족 하는 언어를 말할 때 사실을 제공 할 수 있습니다 .Barkable
Duck
Duck
bark
Duck
Barkable
instance Barkable Duck where
bark d = quack (punch (d))
makeItBark (aDuck)
이것은 Duck
s가 짖을 수 있으며, 짖는 소리를 내기 전에 오리 를 펀칭하여 짖는 기능을 구현합니다 . 그 길 makeItBark
에서 오리를 부를 수 있습니다 .
Standard ML
그리고 OCaml
훨씬 더 유연 당신이 만족 수 있다는 점에서입니다 같은 하나 이상의 방법으로 형 클래스를. 이 언어에서는 정수를 기존 순서를 사용하여 순서 를 정한 다음 뒤집을 수 있고 나눌 수도 있음을 말할 수 있습니다 (예 : 10 > 5
10은 5로 나눌 수 있기 때문에). Haskell에서는 유형 클래스를 한 번만 인스턴스화 할 수 있습니다. (이 하스켈은 자동으로 전화를해도 괜찮은지 것을 알 수 있습니다 bark
오리에, SML 또는 OCaml의에서 당신에 대해 명시 될 필요가 있는 bark
하나 이상이있을 수 있기 때문에, 당신이 원하는 기능을 수행합니다.)
간결
물론, 구문상의 차이가 있습니다. 제시 한 파이썬 코드는 내가 작성한 Java 코드보다 훨씬 간결합니다. 실제로, 간결함은 동적 유형 언어의 매력에 큰 부분을 차지합니다. 그러나 형식 유추를 사용하면 모든 변수 의 형식을 명시 적으로 작성하지 않아도되므로 정적으로 형식이 지정된 언어로 간결한 코드를 작성할 수 있습니다 . 정적으로 유형이 지정된 언어는 동적 입력에 대한 기본 지원을 제공하여 모든 캐스팅 및 맵 조작 (예 : C # dynamic
) 의 상세 정보를 제거합니다 .
정확하지만 잘못된 유형의 프로그램
공평하게, 정적 타이핑은 타입 체커가 그것을 확인할 수 없더라도 기술적으로 올바른 일부 프로그램을 배제해야합니다. 예를 들면 다음과 같습니다.
if this_variable_is_always_true:
return "some string"
else:
return 6
if
else 분기가 발생하지 않더라도 대부분의 정적으로 유형이 지정된 언어는이 문장을 거부 합니다. 실제로이 유형의 코드를 사용하는 사람은없는 것 같습니다. 유형 검사기에 너무 영리한 것은 미래의 코드 관리자가 당신과 당신의 친척을 저주하게 할 것입니다. 예를 들어 누군가가 4 개의 오픈 소스 Python 프로젝트를 Haskell로 성공적으로 변환했습니다 . 즉, 정적 형식이 좋은 언어로는 컴파일 할 수없는 작업을 수행하지 않았습니다. 또한 컴파일러는 단위 테스트에서 포착하지 못한 몇 가지 유형 관련 버그를 발견했습니다.
동적 타이핑에서 본 가장 강력한 주장은 Lisp의 매크로입니다. 언어의 구문을 임의로 확장 할 수 있기 때문입니다. 그러나 Typed Racket 은 매크로가있는 정적으로 유형이 지정된 Lisp의 방언이므로 정적 입력과 매크로는 상호 배타적이지 않지만 동시에 구현하기는 더 어렵습니다.
사과와 오렌지
마지막으로, 유형 시스템보다 언어에 큰 차이가 있다는 것을 잊지 마십시오. Java 8 이전에는 Java에서 모든 종류의 기능 프로그래밍을 수행 하는 것이 사실상 불가능했습니다. 간단한 람다는 4 줄의 상용구 익명 클래스 코드가 필요합니다. Java는 콜렉션 리터럴 (예 :)도 지원하지 않습니다 [1, 2, 3]
. 툴링 (IDE, 디버거), 라이브러리 및 커뮤니티 지원의 품질과 가용성에 차이가있을 수도 있습니다. 누군가가 Java보다 Python이나 Ruby에서 더 생산적이라고 주장 할 때, 그 기능 불일치를 고려해야합니다. 포함 된 모든 배터리 , 언어 코어 및 유형 시스템 과 언어를 비교하는 것에는 차이가 있습니다 .
makeItBark(collections.namedtuple("Dog", "bark")(lambda x: "woof woof"))
. 그 주장은 클래스 가 아니며 익명의 튜플입니다. 오리 타이핑 ( "...처럼 떨리면 ...")을 사용하면 본질적으로 제한이없고 구문 적 오버 헤드가없는 임시 인터페이스를 수행 할 수 있습니다. Java와 같은 언어 로이 작업을 수행 할 수는 있지만 많은 혼란을 겪습니다. Java의 함수에 ArrayList가 필요하고 다른 컬렉션 유형을 제공하려는 경우 SOL입니다. 파이썬에서는 올 수조차 없습니다.