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

为什么急剧脱节?它是解释语言本质的一部分吗?面向对象编程?

有帮助吗?

解决方案

有趣的问题。顺便说一句,我是作者/维护者 PHC (PHP 编译器),我正在攻读动态语言编译器的博士学位,所以我希望我能提供一些见解。

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

Java 的第一个实现是解释型的,它是一种静态类型语言。静态语言确实存在解释器:Haskell 和 OCaml 都有解释器,并且曾经有一个流行的 C 解释器,但那是很久以前的事了。它们很受欢迎,因为它们允许 REPL, ,这可以让开发变得更容易。

也就是说,正如您所料,动态语言社区中存在对静态类型的厌恶。他们认为 C、C++ 和 Java 提供的静态类型系统很冗长,不值得付出努力。我想我在某种程度上同意这一点。Python 编程比 C++ 有趣得多。

针对其他人的观点:

  • 德兰布林 说: :“我从来没有强烈认为有关汇编与解释有什么特别的,这暗示了静态打字的动态。”好吧,你在那里错了。动态语言的编译是非常困难的。大部分有 eval 要考虑的语句,它在 Javascript 和 Ruby 中广泛使用。phc 提前编译 PHP,但我们仍然需要一个运行时解释器来处理 evals。 eval 也不能在优化编译器中进行静态分析,尽管有一个 酷技术 如果你不需要健全性。

  • 对于丹布林的回应 安德鲁·黑尔: :您当然可以在解释器中执行静态分析,并发现错误 运行时,这正是 Haskell 的 ghci 做。我希望函数式语言中使用的解释器风格需要这样。德兰布林说分析不是解释的一部分,这当然是正确的。

  • 安德鲁·黑尔的回答 是基于提问者错误的假设,同样也有错误的方式。然而,他提出了一个有趣的问题:“动态语言的静态分析有多难?”。非常非常难。基本上,你会因为描述它的工作原理而获得博士学位,这正是我正在做的事情。另请参阅上一点。

  • 迄今为止最正确的答案是 伊沃·韦策尔. 。然而,他描述的要点可以在编译器运行时处理,并且许多 Lisp 和 Scheme 编译器都具有这种类型的动态绑定。但是,是的,这很棘手。

其他提示

解释语言使用动态类型,因为没有编译步骤在其中进行静态分析。编译语言做静态分析的在编译时间的,这意味着他们工作的任何类型的错误报告给开发者。

这是比较容易,如果你认为这是一个静态类型语言中有一个编译器,强制执行类型的执行环境之外的规则理解。解释语言从不进行分析静态所以键入规则必须由执行的上下文中解释执行。

我想这是因为解释型语言的性质,他们希望是动态的,所以你可以在运行时改变的事情。由于这种编译器永远不会确切地知道什么是程序状态的下一行代码已经excecuted后。

想象以下情形(在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()

正如你可以看到希望,编译器会不会在这种情况下,任何意义。 NOTE:事实上它可以提醒你有关的可能性,“myvalue的”或许真的比别的号码。 但随后的JavaScript将失败,因为如果“myvalue的”是一个字符串,20将implictily转换为String过,因此不会发生错误。所以,你可能会得到成千上万的无用警告所有的地方,我不认为这是一个打算编译器。

灵活性始终是有代价的,你需要更仔细地看看你的程序从深层次看,还是程序呢,换句话说,你在的情况下,编译器类似上面的。

所以你的解决方案,因为编译器? - 一个 “:除了尝试”:修复它)

编译器静态+ =类型有效的机器代码,点击 编译器+动态类型=低效机器代码

考虑以下伪代码:

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

虽然你可能会产生更聪明的机器代码比,你会不会能够帮助产生大量的代码 - 这使得编译不是一个动态语言的一大胜利。

由于口译是写容易得多,而且编译不会做你多好,为什么不写一个解释?

(刚刚在即时编译器实际上有类型信息,并能编写一直到单个语句他们实际上比静态类型系统的更多信息,并在理论上可以做得更好所有汇编模拟;如有雷同可能真机上运行实际代码纯属巧合。)

也许是因为我的主要解释的语言之一,是Perl和我的汇编语言之一是Objective-C的,但我从来没有强烈地感觉到,有大约编译VS解释什么特别的东西,暗示动态在静态类型。

我觉得很显然,双方都在寻找其他与思考“有一定的优势了这一点。”这在一些应用中更容易得到一些动态类型的灵活性,同时它可以更容易维护的东西是静态类型和执行。

我不同意安德鲁·黑尔的解释虽然。虽然纯粹的解释型语言必须在预处理步骤中添加,因此不能以静态警告输入错误的执行之前的程序员是纯解释,这并不排除,因为它发生在运行时抛出类型错误。所以缺乏编译并不意味着可能会出现没有静态类型检查。但是,由于在运行时得到一个错误类型是不是有用,因为让一个在编译时,或在飞行前检查,我可以看到在这种情况下静态类型的“优势”,如何能似乎更讨厌的,因而有利于的优点动态类型带来得到抛出。

如果您从您希望将自己的各类静态的,因为个人你写出更好更易于维护的代码作为一个结果,而你在设计你的解释语言一开始就知道,也不应该设计语言作为一种静态类型的一个阻止你

要引用解释语言维基文章“从理论上讲,任何语言可以被编译或解释的,所以这种指定方式纯粹是应用,因为共同实施的做法和语言不是一些相关物业的。“结果 有一个体面的维基文章只是打字

动态类型语言解释给你在你的程序的方式更自由。它允许元编程是可行的。它允许在运行时创建的变量。允许在任何给定时间内的运行时间而没有事先宣布的手的事情之前创建匿名哈希和匿名数组。它允许未确定信息进行inputed到一个哈希而没有申报的所有按键提前。您可以从不确定的随机输入创建的子程序。您也可以养活的程序代码,可以动态地运行。解释型语言摆脱这限制了总体规划的枷锁。您仅限于您与静态类型语言的源文件中输入的内容。您可以在动态类型语言事半功倍。

大多数的机器人正在取得今天处理解释型语言更因为在运行时确定的信息需求,并需要进行存储在运行时,这个信息新的变数。机器学习被解释为基于周围信息。我们自己作为人类解释这是为什么机器人被设计的方式。未来真正地解释。当然,你需要静态类型语言来构建口译所以静态类型语言永远不会消失,除非解释是建立在汇编代码的未来。大多数口译员在静态类型语言中内置的这些日子。

解释语言擅长于动态环境。如果你能解释在运行时,新的代码/信息又何尝不是。如果您在动态编程,那么你可以创建代码,可以创建变量和散列而没有输入所有的东西真的很不错。你可以,如果有大量数据你的工作大大减少线的数量。您可以使用数据自卸车打印出所有的信息,因为解释型语言通常在运行时允许这是可能保持的变量类型的轨道。你不能在准系统C ++做到这一点。唯一的一次,C ++和C都知道发生了什么事情是在编译时。之后,你对你自己,除非你自己实现的东西。

谁想尤其是这几天绑这么多的源文件,当你在动态环境中工作。所有你做的是限制你的潜力。一旦你的脖子深的动态解释的代码,你回去任何静态类型语言,你将很难找到哑下来你的代码,因为你仍然在一个无限的心态思考。你的大脑需要返回到再次被限于什么是源文件中键入。

在编程风格的方法: 静态类型的代码生成静态的结果。动态类型代码产生动态或静态的结果。

如果您要被编程的东西,永远不会改变比已知,那么静态类型语言是伟大的其他行为。如果您处理动态行为则动态类型语言的更适合的那些情况。一切都取决于大多是这种情况。

每一种语言都有自己的酸甜苦辣。只是爱选择并挑选明智。

我觉得静态类型更容易为编译器和这是最主要的(如果不只)的原因,它的出现在编译语言。

有关解释型语言更容易假设变量不具有类型(只值有),因为它们被认为不是作为一个用于数据的砂矿必须装进而是标注为某处漂浮在堆数据。

如果程序员想的,他可以总是断言变量保存(上分配例如)给定类型的值。没有理由将其建成的语言。当然,这不是同一种控制的,你有编译语言。

您也许可以在其中你必须明确地声明每个变量的类型,但如果你不这样做是很容易做的有趣的事情,与静态类型将需要从程序员非常精心打造的复仿制类型的语言。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top