有没有一种编译型编程语言是动态的,甚至可能是弱类型的?(*compiled指编译型语言)

48

我想知道是否有一种编程语言可以编译成机器码/二进制代码(不是字节码,然后由虚拟机执行,考虑类型时完全不同),具有动态和/或弱类型的特性,例如:

想象一种编译语言,其中:

  • 变量不需要声明
  • 变量可以在运行时创建
  • 函数可以返回不同类型的值

问题:

  • 是否有这样一种编程语言?
  • 为什么没有呢?

我认为一种动态但强类型的编译语言真的很有意义,但这可能吗?


1
@Platinum:你可以使用 NGen 获取机器码。 - Robert Harvey
2
@Robert Harvey:噢,别这样,那不算数。那不是语言本身的特性。按照这个标准,我也可以声称Java也是一种编译语言,因为它也有.exe包装器可用。顺便说一下,如果有转换程序可以将脚本转换成二进制文件,那么为什么不把它归类为脚本语言呢? - Platinum Azure
1
@Platinum:不确定我理解你的观点。从C#和NGen获得的机器代码实际上可能比某些直接生成机器代码的本地代码编译器的质量更高。Jitter能够进行一些相当大的优化。将脚本转换为exe的黑客甚至无法被视为同一件事情。 - Robert Harvey
4
@Robert Harvey: 我有点受伤了,你会这样攻击我。仔细读:我没有说 NGen 不会生成机器代码。而且那也不是我的问题。我的问题是,你必须使用它作为多个步骤之一,将 C# 代码转换成机器语言。C# 编译成中间语言。编译的机器代码并不是该语言本质上固有的。从这个意义上说,它与脚本到 exe 工具完全相同,虽然这些工具可能很糟糕。 - Platinum Azure
2
每种编译型编程语言从源码到可执行文件都需要多个步骤,但你第二个说法中真正的问题在于使用了“解释型”这个词。在编程语言社区中,“解释型”有一个特定的含义,这对 Java 的早期版本是有效的,但对于任何版本的 C# 都无效。C# 是一种编译型语言,不管它经过哪些阶段最终变成什么样子。 - Jeffrey L Whitledge
显示剩余4条评论
11个回答

37

7
是的,这是可能的。请参考Julia,它是一种动态语言(您可以编写不带类型的程序),但它从不在虚拟机上运行。它会在运行时将程序编译为本地代码(JIT编译)。

编译时和解释型语言有什么不同? - Rahul Bhatnagar
这是一个苹果/橙子比较。运行时编译(JIT编译)是解释器在运行时使用的一种方法,以提高性能。解释型语言不一定要进行JIT编译,但基本上所有运行时都会进行。 - dQw4w9WyXcQ
Yaa Julia是一个很好的例子,它还具有多重分配。 - abhimanyuaryan

6

Objective-C可能具有您寻求的某些属性。类可以在运行时打开和更改,并且您可以向对象发送任何类型的消息,无论它通常是否会响应。通过这种方式,您可以实现鸭子类型,就像Ruby一样。类型id,大致相当于void*,可以赋予接口,指定(否则未知的)类型将遵守的合同。


6
C# 4.0具有许多(如果不是全部)这些特征。如果您真的想要本机机器码,可以使用实用程序将字节码编译为机器码
特别地,使用dynamic关键字允许在运行时动态绑定对象及其成员。
请查看Anders Hejlsberg的视频《C#的未来》进行入门:

http://channel9.msdn.com/pdc2008/TL16/


从技术上讲,这是不正确的。C# dynamic 所做的只是提供一种语法糖,以便使用 Object 作为类型。 - lassombra

4

Objective-C具有您提到的许多功能:它编译为机器代码,并且在对象实例方面是动态类型。 id类型可以存储任何类实例,Objective-C使用消息传递而不是成员函数调用。方法可以在运行时创建/添加。Objective-C运行时还可以在运行时合成类实例变量,但本地变量仍然需要声明(就像在C中一样)。

C# 4.0具有许多这些功能,只是它编译为IL(字节码),并使用虚拟机(CLR)进行解释。但这引出了一个有趣的问题:如果字节码被即时编译为机器代码,那算不算?如果是这样,它不仅打开了任何.NET语言的大门,还包括Python(请参见PyPyUnladed SwallowIronPython)和Ruby(请参见MacRubyIronRuby)以及许多其他动态类型语言,更不要提许多LISP变体了。


3
与Lisp类似,Factor也是一种连接式语言,其默认情况下没有变量,采用动态类型和灵活的对象系统。Factor代码可以在交互式解释器中运行,也可以使用其deploy函数编译为本机可执行文件。
* 无点函数式基于栈的

2

VB 6已经具备大部分功能


1
...但实际上并不编译成机器码(编译成p-code)。 - Robert Harvey
2
默认设置是编译为本地代码。(您可以在项目属性中更改此设置。) - Svante Svenson

1

我不知道有哪种语言具有完全相同的功能。但我可以想到两种具有重要子集的语言:

  • D 具有类型推断、垃圾回收和强大的元编程功能,但编译成高效的机器码。但它没有动态类型。
  • C# 可以通过mono项目直接编译成机器码。C# 与 D 具有类似的功能集,但同样没有动态类型。

1

C/C++ 都可以使用 void* 间接支持动态类型。C++ 示例:

#include <string>

int main() {
    void* x = malloc(sizeof(int))
    *(int*)x = 5;
    x = malloc(sizeof(std::string));
    *(std::string*x) = std::string("Hello world");
    free(x);
    return 0;
}

在C++17中,也可以使用std::any
#include <string>
#include <any>

int main() {
    std::any x = 5;
    x = std::string("Hello world");
    return 0;
}

当然,在C/C++中很少使用或需要鸭子类型,这两个选项都存在问题(void*不安全,std::any是巨大的性能瓶颈)。

你可能正在寻找的另一个例子是JavaScript的V8引擎。它是一个JIT编译器,意味着源代码在运行时被编译成字节码和机器码,尽管这对用户来说是隐藏的。


0

3
你不是在说所有这些“编译器”链接器只是将Python二进制文件与脚本打包到一个可执行文件中吗? - sub
“将二进制文件打包成一个可执行文件”不是编译器吗?请提供一些定义,以排除从源代码创建一个可执行文件的情况。顺便说一下,有些人在编译二进制文件之前会将其转换为C语言。 - S.Lott
2
不,这不是这样的。编译器将代码转换为计算机可读的二进制文件。Py2exe(和其他系统)仅仅是将Python可执行文件与Python脚本一起发布,因此原始代码仍然是Python,并且仅能通过Python可执行文件来执行。 但是存在一些变体的Python语言可以编译成C,但它从来都不是原始的Python(如Cython)。 - Manux
1
@Manux:在我运行py2exe之后,我有一个可以直接在Windows上执行的.exe文件。对吗?这与问题中所述的标准有什么不符之处?重要的不是你对编译的理解,而是问题本身含糊不清,因此有很多解决方案是可行的。 - S.Lott
1
@S.Lott 因为它是“打包”而不是“编译”。 - m4heshd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接