首页 文章

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

提问于
浏览
40

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

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

7 回答

  • 48

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

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

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

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

    为了解决他人的观点:

    • dlamblin says:"I never strongly felt that there was anything special about compilation vs interpretation that suggested dynamic over static typing."嗯,那里你错了 . 动态语言的编译非常困难 . 主要有 eval 语句要考虑,它在Javascript和Ruby中广泛使用 . phc提前编译PHP,但我们仍需要一个运行时解释器来处理 eval . eval 也无法在优化编译器中静态分析,但如果您不需要稳健性,则会有cool technique .

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

    • Andrew Hare's answer是基于提问者的错误假设,同样也有错误的方法 . 然而,他提出了一个有趣的问题:"how hard is static analysis of dynamic languages?" . 非常非常努力 . 基本上,你在做什么 . 另见前一点 .

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

  • 1

    解释语言使用动态类型,因为没有编译步骤可以进行静态分析 . 编译语言在编译时进行静态分析,这意味着任何类型的错误都会在开发人员工作时报告 .

    如果您认为静态类型语言具有在执行上下文之外强制执行类型规则的编译器,则更容易理解 . 解释语言永远不会静态分析,因此类型规则必须由执行环境中的解释器强制执行 .

  • 2

    我认为这是因为解释语言的本质,他们希望是动态的,所以你可以在运行时改变一些东西 . 由于这个原因,编译器永远不会确切地知道在下一行代码被激活之后程序的状态是什么 .

    想象一下以下场景(在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()
    

    正如您所希望的那样,编译器在这种情况下没有任何意义 . 它可能会警告你“myValue”可能不是一个数字 . 但是在JavaScript中会失败,因为如果“myValue”是一个String,那么20也会被隐含地转换为String,因此不会发生错误 . 因此,您可能会在整个地方收到数千个无用的警告,我认为这不是编译器的意图 .

    始终具有灵活性有一个价格,你需要深入了解你的程序,或更仔细地编程,换句话说,你是上述情况下的编译器 .

    所以你的解决方案作为编译器? - 使用“try:except”修复它:)

  • -1

    编译器静态类型=高效的机器代码
    编译器动态类型=低效的机器代码

    考虑以下伪代码:

    function foo(a, b) {
        return a+b
    }
    

    静态语言将能够(通过声明或推断)知道a和b是整数,并且将编译为

    %reg = addi a,b
    

    或类似的东西,无论如何 .

    动态语言的编译器必须发出代码
    1.检查它们的类型a和b
    2.处理每个案件或案件组合

    %reg1 = typeof a
    beq %reg1, int, a_int_case
    beq %reg1, float, a_float_case
    beq %reg1, string, a_string_case
    
    label a_int_case
    %reg1 = typeof b
    beq %reg1, int, a_int_b_int_case
    beq %reg1, float, a_int_b_float_case
    beq %reg1, string, a_int_b_string_case
    
    label a_int_b_int_case
    %out = addi a,b
    goto done
    
    label a_int_b_float_case
    %tmp = mkfloat a
    %out = addf %tmp,b
    goto done
    
    ... Etc. I can't finish
    

    虽然您可以生成比这更智能的机器代码,但您无法帮助生成大量代码 - 这使得编译不是动态语言的主要胜利 .

    由于解释器更容易编写,编译对你没有多大好处,为什么不写一个解释器呢?

    (实时编译器实际上有类型信息,可以编译到单个语句 . 它们实际上比静态类型系统有更多的信息,理论上可以做得更好 . 所有汇编程序都是模拟的;与实际代码有任何相似之处可以在真机上运行纯属巧合 . )

  • 4

    也许是因为我的主要解释语言之一是Perl而我的编译语言之一是Objective-C,但我从来没有强烈地感觉到编译与解释之间有任何特殊之处,这表明动态的静态类型 .

    我认为很明显,双方都在关注对方,并在思考,“这有一些优势 . ”在多个应用程序中,更容易获得一些动态类型的灵活性,同时可以更容易地维护静态类型和强制执行的内容 .

    我不同意Andrew Hare's explanation . 虽然纯粹解释的语言必须在预处理步骤中添加,因此不能纯粹解释为了在执行静态类型错误之前警告程序员,但它并不像在编译时或在预检检查期间获得一样有用 . ,我可以看到在这种情况下静态打字的情况如何看起来更像是一种麻烦,因此被抛弃以支持动态打字带来的优势 .

    如果你从一开始就知道你希望保持你的类型是静态的,因为你亲自编写了更好的可维护代码,并且你正在设计你的解释语言,没有什么能阻止你将这种语言设计为静态类型 .

    引用interpreted languages wiki article "Theoretically, any language may be compiled or interpreted, so this designation is applied purely because of common implementation practice and not some underlying property of a language."
    打字时有一个不错的wiki article .

  • 4

    动态类型的解释语言为您提供了更多编程方式的自由 . 它允许元编程可行 . 它允许在运行时创建变量 . 允许在运行时的任何给定时间创建匿名哈希和匿名数组,而无需事先声明任何内容 . 它允许将未确定的信息输入到散列中,而无需事先声明所有密钥 . 您可以从未确定的随机输入创建子例程 . 您也可以提供可以动态运行的程序代码 . 解释语言释放了一般限制编程的链 . 您仅限于使用静态类型语言在源文件中键入的内容 . 您可以使用动态类型语言以更少的资源完成更多工作 .

    今天制造的大多数机器人更多地处理解释语言,因为需要在运行时确定信息,并且需要在运行时存储新信息以存储该信息 . 机器学习基于被解释的信息 . 我们自己作为人类是解释者,这就是机器人以这种方式设计的原因 . 未来真的被解释了 . 当然,您需要静态类型语言来构建解释器,因此静态类型语言永远不会消失,除非将来使用汇编代码构建解释器 . 如今,大多数口译员都是基于静态类型语言构建的 .

    口译语言在动态环境中表现出色 . 如果您可以在运行时解释新的代码/信息,那么为什么不呢 . 如果您真的擅长动态编程,那么您可以创建可以创建变量和哈希的代码,而无需输入任何内容 . 如果您使用大量的线路,您可以大幅减少线路数量数据 . 您可以使用数据转储器打印出所有信息,因为解释型语言通常会在运行时跟踪变量的类型,从而实现这一点 . 你不能在准系统中这样做 . 唯一一次c和c知道发生了什么是在编译时 . 除非你自己实施一些东西,否则你自己就可以了 .

    这些天谁想要与源文件捆绑在一起,特别是当你在动态环境中工作时 . 你所做的一切都限制了你的潜力 . 一旦你的脖子深入动态解释代码,你回到任何静态类型的语言,你会发现你的代码更难以愚蠢,因为你仍然在思考无限的心态 . 你的思想需要回到再次受限于源文件中输入的内容 .

    编程样式的方式:静态类型代码产生静态结果 . 动态类型代码生成动态或静态结果 .

    如果你要编程的东西永远不会改变已知的东西,那么静态类型的语言就是很好的 . 如果您处理动态行为,那么动态类型语言更适合这些情况 . 一切都取决于大多数情况 .

    每种语言都有起伏 . 只需明智地选择和选择 .

  • 0

    我认为静态类型使编译器更容易,这是它在编译语言中存在的主要原因(如果不是唯一的原因) .

    对于解释型语言,更容易假设变量没有类型(只有值),因为它们被认为不是必须适合内部数据的放置器,而是标记为浮动在堆上某处的数据 .

    如果程序员想要的话,他总是可以断言该变量包含给定类型的值(例如在赋值时) . 没有理由将它构建成语言 . 当然,这与编译语言的控制方式不同 .

    您可能拥有必须明确声明每个变量类型的语言,但如果不这样做,则更容易做有趣的事情,静态类型需要程序员非常精心设计的复杂泛型类型 .

    另一方面 . 你知道任何动态类型编译(静态,不是JIT)语言吗?

相关问题