我只是不知道,有什么技术原因吗?为弱键入的语言实现编译器是否更难?它是什么?
问题背后的前提有点狡猾.解释性语言大多是鸭形的,这是不正确的.编译语言大多数都具有强类型,这是不正确的.该型系统是一种语言的属性. 编译与解释是的财产实施.
例子:
编程语言计划是动态类型(又名鸭类型的),并且它有许多几十解释实现的,但也有一些细微的本地代码编译器,包括盗窃,开局和PLT计划(包括两者的解释和JIT编译器制作无缝过渡).
编程语言Haskell是静态类型的; 两个最着名的实现是解释器HUGS和编译器GHC.在编译到本机代码(yhc)和解释(Helium)之间,还有其他几个可敬的实现.
编程语言标准ML是静态类型的,它有许多本机代码编译器,其中最好和最主动维护的是MLton,但最有用的实现之一是解释器莫斯科ML
编程语言Objective Caml是静态类型的.它配备了只有一个(在法国INRIA从)实现,但这实现包括既译员和本机代码的编译器.
编程语言Pascal是静态类型的,但它在20世纪70年代开始流行,因为在UCSD上构建了优秀的实现,它基于P代码解释器.在以后的几年中,可以使用精细的本机代码编译器,例如370系列计算机的IBM Pascal/VS编译器.
编程语言C是静态类型的,今天几乎所有的实现都是编译的,但在20世纪80年代,我们幸运地使用Saber C的人正在使用解释器.
然而,你的问题背后有一些真相,所以你应该得到一个更周到的答案.事实上,动态类型语言似乎与解释的实现相关.为什么会这样?
许多新语言由实现定义.构建解释器比构建编译器更容易.动态检查类型比静态检查更容易.如果您正在编写解释器,静态类型检查几乎没有性能优势.
除非您正在创建或调整非常灵活的多态类型系统,否则静态类型系统可能会以程序员的方式进入.但是如果你正在编写一个解释器,一个原因可能是创建一个小的,轻量级的实现,不受程序员的影响.
在一些解释型语言中,许多基本操作非常昂贵,以至于在运行时检查类型的额外开销无关紧要. 一个很好的例子就是PostScript:如果你要在帽子上跑掉并光栅化Bezier曲线,你就不会在这里或那里检查一个类型标签.
顺便说一句,请注意"强"和"弱"类型的术语,因为它们没有普遍认可的技术含义.相比之下,静态类型意味着在执行之前检查程序,并且程序在启动之前可能会被拒绝. 动态类型意味着在执行期间检查值的类型,并且类型不佳的操作可能导致程序在运行时停止或以其他方式发出错误信号.静态类型的主要原因是排除可能具有此类"动态类型错误"的程序.(这是编写解释器的人通常对静态类型不太感兴趣的另一个原因;在类型检查后立即执行,因此保证的区别和性质不那么明显.)
强类型通常意味着类型系统中没有漏洞,而弱类型意味着类型系统可以被破坏(使任何保证无效).这些术语经常被错误地用于表示静态和动态类型.为了看到差异,想想C:语言在编译时被类型检查(静态类型),但是存在很多漏洞; 你几乎可以将任何类型的值转换为相同大小的另一种类型 - 特别是,你可以自由地转换指针类型.Pascal是一种旨在强类型的语言,但着名的是有一个无法预料的漏洞:一个没有标签的变体记录.
强类型语言的实现通常会随着时间的推移而获得漏洞,通常是因为部分运行时系统可以用高级语言实现.例如,Objective Caml有一个函数调用Obj.magic
,它具有简单地返回其参数的运行时效果,但在编译时它将任何类型的值转换为任何其他类型的值.我最喜欢的例子是Modula-3,其设计师称他们的类型转换结构LOOPHOLE
.
综上所述:
静态与动态是语言.
编译与解释是实现.
原则上,这两种选择可以是正交的,但是出于合理的技术原因,动态类型通常与解释相关.
你做早期绑定(强类型)的原因是性能.通过早期绑定,您可以在编译时找到方法的位置,以便在运行时它已经知道它的位置.
但是,对于后期绑定,您必须搜索一个看起来像客户端代码调用的方法的方法.当然,在程序中有许多方法调用,这就是动态语言"慢"的原因.
但是可以肯定的是,你可以创建一个静态编译的语言来进行后期绑定,这会否定静态编译的许多优点.