为什么动态打字经常与口译语言相关联?

dav*_*lab 40 type-systems language-design static-typing typing dynamic-typing

简单的问题:我在编译语言(如C++/Java)和Python/Javascript等解释语言中进行了大量编程(专业和个人).我个人发现,当我使用静态类型语言编程时,我的代码几乎总是更强大.但是,我遇到的几乎所有解释语言都使用动态类型(PHP,Perl,Python等).我知道为什么编译语言使用静态类型(大多数时候),但我无法弄清楚解释语言设计中对静态类型的厌恶.

为什么陡峭断开?它是解释语言性质的一部分吗?OOP?

Pau*_*gar 48

有趣的问题.顺便说一句,我的作者/维护者PHC(编译器为PHP),和我做我的博士对编译器的动态语言,所以我希望我可以提供一些见解.

我认为这里有一个错误的假设.PHP,Perl,Python,Ruby,Lua等的作者没有设计"解释语言",他们设计了动态语言,并使用解释器实现了它们.他们这样做是因为解释器比编译器更容易编写.

Java的第一个实现被解释,它是一种静态类型语言.对于静态语言存在解释器:Haskell和OCaml都有解释器,并且过去常常是C的流行解释器,但这是很久以前的事了.它们很受欢迎,因为它们允许REPL,这可以使开发更容易.

也就是说,正如您所期望的那样,动态语言社区存在对静态类型的厌恶.他们认为C,C++和Java提供的静态类型系统是冗长的,不值得努力.我认为我在一定程度上同意这一点.使用Python编程比C++更有趣.

为了解决他人的观点:

  • dlamblin说:"我从来没有强烈地认为编译与解释有任何特殊之处,这表明动态的静态打字." 嗯,那里你错了.动态语言的编译非常困难.主要是eval要考虑的语句,它在Javascript和Ruby中广泛使用.phc提前编译PHP,但我们仍然需要一个运行时解释器来处理evals.eval也不能在优化编译器中静态分析,但如果你不需要健全,有一种很酷的技术.

  • 对于damblin对Andrew Hare的回应:您当然可以在解释器中执行静态分析,并运行时发现错误,这正是Haskell ghci所做的.我希望函数式语言中使用的解释器风格需要这样.dlamblin当然可以说分析不是解释的一部分.

  • 安德鲁·哈尔的回答是基于提问者错误的假设,同样也有错误的方法.然而,他提出了一个有趣的问题:"动态语言的静态分析有多难?".非常非常努力.基本上,你将获得一个博士学位来描述它是如何工作的,这正是我正在做的事情.另见前一点.

  • 到目前为止,最正确的答案是Ivo Wetzel.但是,他描述的要点可以在编译器中的运行时处理,并且Lisp和Scheme存在许多具有这种动态绑定的编译器.但是,是的,它很棘手.


Ivo*_*zel 5

我认为这是因为解释语言的本质,它们希望是动态的,所以你可以在运行时改变东西。因此,编译器永远无法确切知道执行下一行代码后程序的状态是什么。

想象一下以下场景(Python):

import random
foo = 1

def doSomeStuffWithFoo():
    global foo
    foo = random.randint(0, 1)

def asign():
    global foo
    if foo == 1:
        return 20
    else:
        return "Test"


def toBeStaticallyAnalyzed():
    myValue = asign()

    # A "Compiler" may throw an error here because foo == 0, but at runtime foo maybe 1, so the compiler would be wrong with its assumption
    myValue += 20


doSomeStuffWithFoo() # Foo could be 1 or 0 now... or 4 ;)
toBeStaticallyAnalyzed()
Run Code Online (Sandbox Code Playgroud)

正如您所希望看到的,编译器在这种情况下没有任何意义。实际上,它可能会警告您“myValue”可能不是数字的可能性。但在 JavaScript 中,这会失败,因为如果“myValue”是一个字符串,20 也会隐式转换为字符串,因此不会发生错误。因此,您可能会在各处收到数千个无用的警告,我认为这不是编译器的意图。

灵活性总是有代价的,你需要更深入地审视你的程序,或者更仔细地编程它,换句话说,在上述情况下你就是编译器。

那么你作为编译器的解决方案是什么呢?- 用“尝试:除了”修复它:)

  • 是的,很明显,如果您使用动态类型语言执行一些动态类型操作,编译器将无法确定类型。目前尚不清楚的是,如果该语言的设计使得每个函数的返回值和变量都是声明的类型,那么它可以检查该类型,为什么该语言应该是动态类型的。 (2认同)