些人会说语言学到最后不都差不多吗?其实可以这样讲,也可以不这样讲。虽然每种语言的表达能力大部分是重合的,只是语法表现形式不一样,但是由于历史发展的原因,每种语言形成了自己的支撑环境,所以都有其主要的适用范围。
C、C++、Python和Java四种是通用编程语言,JavaScript和PHP算是Web环境的专用编程语言。
由于其底层操作特性和历史的积累,在嵌入式领域是当之无愧的王者。
是一种支持最广泛编程范式的复杂语言,在高级语言当中,处理运行速度是最快的,大部分的游戏软件,系统都是由C++来编写的。
作为一种灵活的轻便的通用型脚本语言,使用范围比较广,从应用软件到Web开发都有它的身影,由于其解释语言的特点,比较适合轻量级或原型开发;
Java由于其跨平台可移植性,在Web开发领域大放异彩,特别是在企业级Web开发,同时由于Android系统采用Java来开发应用程序,所以也随着Android的发展而应用越发广泛;
JavaScript语言由于其是浏览器内置的脚本语言,是Web前端开发的主流,近年来由于google的V8引擎开源,出现了Node.js之类JavaScript后台开发框架,把JavaScript的应用领域扩展到了Web后台。
独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页;还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。
理清不同语言间主要语法特性的差异,才能更好的在合适的领域或场景下去应用合适的编程语言,以满足我们所面对的需求。这六种语言都是从C语言发展而来,所以它们的语法都比较像C语言,下面我就主要语法特性对各个语言做一个对比。
1、常量定义
C:#define TEST 0
C++:#define TEST 0
或者
const test = 0;
Python:test = 0
C#:不支持
PHP:define('test', 1);
Java:final int test = 0;
分析:JavaScript不支持常量,C、C++都用特有的预定义宏,PHP用特殊的define语法,其它的都用定义不变变量的方式。
2、变量定义
C:int test = 0;
C++:int test = 0;
Python:test = 0
JavaScript:val test = 0;
PHP:$test = 0;
Java:int test = 0;
分析:这个最基本的都支持了。
3、函数定义
C:int test(int param){}
C++:int test(int param){}
Python:def test(param):
JavaScript:function test(param){}
PHP:function test($param){}
Java:public class test{
public int test(int param){} }
分析:这个也是最基本的了,只是Java比较特殊,不支持定义类之外的函数。
4、类定义(含继承)
C:不支持
C++:class test2: public test1{}
Python:class test2(test1):
JavaScript:function test2(){}
test2.prototype =inherit(test1.prototype){}
PHP:class test2 extend test1{}
Java:class test2 extends test1{}
分析:C由于是传统面向过程的语言不支持类,其他的都支持了,只是JavaScript的类模型比较特殊,把函数作为类来使用。
5、对象定义
C:不支持
C++:test2 obj = new test2();
Python:obj = test2()
JavaScript:var obj = new test2();
PHP:$obj = new test2();
Java:test2 obj = new test2();
分析:除了C外其它语言都是通过new一个对象。
6、数组定义
C:int a[] = {1, 2, 3};
C++:int a[] = {1, 2, 3};
Python:a = [1, 2, 3]
JavaScript:var a = [1, 2, 3];
PHP:$a = array("1", "2", "3");
Java:int a[] = {1, 2, 3};
分析:数组是语言的基本特性,都支持了,只是PHP通过类似函数调用的语法来完成。
7、条件语句
C:if (test > 0){}
else if (test < 0){}
else{}
C++:if (test > 0){}
else if (test < 0){}
else{}
Python:if test > 0:
elif test < 0:
else:
JavaScript:if (test > 0){}
else if (test < 0){}
else{}
PHP:if ($test > 0){}
elseif ($test < 0){}
else{}
Java:if (test > 0){}
else if (test < 0){}
else{}
分析:这是最基本的语句,都支持了。
8、循环语句
C:for (idx=0; idx<num; idx++){}
C++:for (idx=0; idx<num; idx++){}
Python:for idx in range(1,10):
JavaScript:for (var idx=0; idx<num; idx++){}
PHP:for ($idx=0; $idx<$num; $idx++){}
Java:for (idx=0; idx<num; idx++){}
分析:这个也是基本的语句,都支持了。
9、foreach语句
C:不支持
C++:不支持
Python:for i in a:
或者
for key in d:
d[key]
JavaScript:for(i in a){}
PHP:foreach($a as $i){}
Java:for(int i : a){}
分析:foreach算是循环语句的一个变种,在操作顺序容器的时候非常有用,可以看到C和C++不支持,其它的都语言内置支持了。
10、打印语句
C:printf("test: %d", val);
C++:cout<<"test: "<<val<<endl;
Python:print "test: "+val
JavaScript:不支持
PHP:echo "test: $val";
Java:System.out.println("test :"+val);
分析:打印算是语言所运行环境的支持库功能,除了JavaScript外都支持了,因为JavaScript主要使用来操控DOM树的,没有自己的输出窗口所以也没必要支持。
11、字符串定义
C:char test[] = {"helloworld"};
C++:String test = "helloworld";
Python:test = "helloworld"
JavaScript:var test = "helloworld";
PHP:$test = "helloworld";
Java:String test = "helloworld";
分析:这个都支持了,其中C++、Java都是用标准库来现实的。
12、字符串串接
C:test = strcat(test1, test2);
C++:test = test1 + test2;(STL库)
Python:test = test1 + test2
JavaScript:var test = test1 + test2;
PHP:$test = $test1 .= $test2;
Java:test = test1 + test2;
分析:很有用的功能,除了C是用标准库函数来实现,其它都是语言内置支持了。
13、字符串分割
C:不支持
C++:test.substr(3, 8);
Python:test[3:8]
JavaScript:test.slice(3, 5);
PHP:substr($test, 3, 5);
Java:test.substring(3, 8);
分析:常用的功能,C不支持,Python是语言内置支持,其他的都依靠库来完成。
14、字符串正则表达式
C:不支持
C++:不支持
Python:test.replace("test1", "test2")
JavaScript:test.replace(/test1/gi, "test2");
PHP:str_replace($test, "test1", "test2");
Java:test.replaceAll("test1", "test2");
分析:常用的功能,可惜C、C++不支持,其他都有标准库来支持。
15、内置容器类型
C:数组
C++:数组
顺序容器 Vector
关联容器 Pair MapSet
Python:列表/元组
字典
JavaScript:数组
对象
PHP:数组(含关联数组)
Java:数组
序列 Collection
映射表 Map
分析:C最简单只支持数组,其他都支持容器,不过主要还是顺序容器和关联容器两大类。
16、注释方式
C:/* */
C++://
Python:#
JavaScript:/* */
//
PHP:/* */
//
#
Java:/* */
//
分析:大概就/**/、//、#三种方式,各自支持情况不一。
17、多线程支持
C:支持
C++:支持
Python:支持
JavaScript:不支持
PHP:不支持
Java:支持
分析:四种通用编程语言都支持了,两种专用编程语言都不支持。
18、socket支持
C:支持
C++:支持
Python:支持
JavaScript:不支持
PHP:支持
Java:支持
分析:除了JavaScript以外都支持,这也是JavaScript的应用领域限制所决定的。
19、垃圾回收机制
C:不支持
C++:不支持
Python:支持
JavaScript:支持
PHP:支持
Java:支持
分析:这是现代语言的重要机制,C和C++不支持,其他的都支持了。
20、引入其他文件中的函数
C:export int test();
C++:export int test();
Python:from test import *
JavaScript:<script language='javascript' src="test.js"charset="utf-8"></script>
PHP:require_once('test.php');
或者
include_once('test.php');
Java:import java.util.test.*;
分析:都支持,C和C++用export,Python和Java用import,JavaScript依靠HTML脚本,PHP用自己的函数调用。
21、将字符串作为指令执行
C:不支持
C++:不支持
Python:eval("port=5060")
JavaScript:eval("port=5060;");
PHP:eval("port=5060;");
Java:Porcess proc = new ProcessBuilder(“test”).start();
分析:很有用的一个动态语言特性,C和C++都不支持,Java要类库来支持,其它的语言内置eval关键字.
C/C++资料分享:
需要的小伙伴们可以【点击下方】链接哦~
近日,来自多伦多大学和 YScope 公司(为软件系统提供创新的日志管理和故障排除工具。由一群计算机工程教授和博士创立)的 David Lion、多伦多大学 Adrian Chiu 和 Michael Stumm、多伦多大学和 YScope 公司 Ding Yuan 共同发布了一份《调查托管语言的运行时性能:为什么 JavaScript 和 Python 比 C++ 慢了 8 倍和 29 倍,而 Java 和 Go 却能更快》(https://www.usenix.org/system/files/atc22-lion.pdf)的论文分析报告,深度剖析了不同编程语言运行时在代码开发中真实的性能情况,由此方便开发者可以精确地测量执行任何字节码指令所花费的时间等。
性能是系统软件不得不面对的挑战
在报告中,研究人员指出,自 2015 年以来,具有集成运行时环境的编程语言越来越受欢迎,其中,全球知名的代码托管平台 GitHub 上最受欢迎的三种语言分别是 JavaScript、Java 和 Python。
作为开发利器,编程语言帮助开发者快速构建各种应用程序和服务,也极大地提高了生产力。同时,这些语言自身也提供了各种功能,如动态类型检查、带有垃圾收集的内存管理,以及动态内存安全检查等等。为此,研究人员用「托管语言」(managed languages)专业术语来指代这些类型的编程语言。
现实来看,托管语言越来越多地被用于实现性能至关重要的系统软件上,如Hadoop 和 Spark 都在 Java 虚拟机(JVM)上运行,因为它们分别用 Java 和 Scala 实现;Kubernetes、etcd(分布式键值存储)和 M3(由 Uber 建立的分布式时间序列数据库和查询引擎)都是用 Go 实现的。
当前,甚至连操作系统(OS)的内核 Biscuit 也是用 Go 实现的 。Openstack、Paypal、Instagram 和 Dropbox 都大量使用 Python,其中,Python 是 Dropbox "在后台服务和桌面客户端应用中使用最广泛的语言",在一个存储库中就有近 400 万行 Python 代码;JavaScript 也被用于 Facebook 的 Bladerunner pub/sub 系统的性能关键路径中。
在开发过程中,编程语言的性能在一开始很少会被考虑到项目中,部分原因是不少开发者认为性能问题可以在以后慢慢去解决,也许可以通过简单地增加硬件来进行横向扩展。
不过,随着代码产品或服务使用规模的扩大,服务变得越来越慢或者硬件成本变高,性能成为一个不容忽视的问题。这也是为什么 Stream 要放弃了 Python 而改用 Go、 Discord 从 Go 切换到 Rust、Twitter 从 Ruby on Rails 切换到 Scala 和 Java 的主要原因。
不少开发者往往为了提升性能,想破脑袋,但现实只有两条路,一条是从现有的代码中想尽办法尽可能地做优化,另一条是思考使用的编程语言是否已经达到了性能极限,看看有没有必要将旧的代码移植到一个新的性能更高的语言上。
为了彻底解开系统软件中不同编程语言导致的性能问题,研究人员决定以 C++ 为极限,对 Java、Go、JavaScript 和 Python 四种编程,还有应用最广泛的运行时系统 CPython、OpenJDK。Node.js 与 JavaScript 的 V8 引擎进行深入的定量性能分析。
同时,研究人员还从头开始建立了 6 个应用程序,并创建了一个名为
者 | Nicholas Yang
译者 | 核子可乐
策划 | 褚杏娟
假如大家正在编写前端代码,那么会选择哪种编程语言?目前来看,最有希望的选手主要有三个:首先是最常规的 JavaScript,然后是能编译为 WebAssembly(Wasm)的语言,最后则是能编译成 JavaScript 的语言。
常规 JavaScript 需要的配套工具最少,但代价是调试起来相当麻烦,代码可读性也差。虽然选择 JS 确实门槛较低,不过除了一味痴迷“极简主义”的铁粉以外,我个人觉得这个选项只能说一般。
能编译为 Wasm 的语言虽然越来越多,但总体上还是新生事物。这些语言往往带有大量的二进制文件,因为其中大多需要配合额外的运行时。Interop 距离发展成熟还差得远。另外,即使两种语言都能编译成 Wasm,也不代表它们之间就能良好实现互操作。再有,这个阵营的生态储备还远远比不上积累了几十年的 JavaScript DOM 库。在 Wasm 这边,React 和 Svelte 应该是最好的选项了。大家千万别误会,我可不是在唱衰 Wasm。它已经拥有专属于自己的表现舞台,如果大家想要在浏览器中运行高计算量原生代码,但 Wasm 就是最完美的选项。可如果不是这种情况,我个人不太推荐用它进行日常前端开发。
最后剩下的就是能编译成 JavaScript 的语言了。但这个阵营形成了一家独大的局面,其中的老大我们稍后会具体讨论。相比之下,ClojureScript、Elm、ReScript、Dart 等语言都形成了颇具体量的社区,但未来市场份额还能不能进一步扩大尚未可知。这就很尴尬了,毕竟能编译成 JavaScript 的语言代表的基本就是浏览器上的最佳编程体验。在它们的支持下,我们既能享受 JS 所不具备的良好功能,比如静态类型、强类型、不变性、宏等,同时也能通过 bindings 支持 JS 及其广泛的生态系统。而且,它们还不需要笨拙的大型运行时。
由于 Wasm 的存在,我怀疑 JS 编译阵营会有所保留,毕竟很多人觉得前者才是浏览器上的最佳编译目标。我其实并不同意这种观点,能编译成 JavaScript 的语言还是越多越好。总之,我想借这篇文章跟大家聊聊现有及未来可能出现的前端语言,应该朝着哪个方向发展。
这就是我前文提到的 JS 编译阵营中的“老大”——TypeScript。TypeScript 是种很棒的语言,显著改善了开发者体验。它还新增了安全层,促进工具质量提升,并大大降低了使用门槛。考虑到生态系统的繁荣现状以及对 JS 类型检查难题的妥善解决,TypeScript 确实取得了非凡的成就。
当然,也有不少针对 TypeScript 的非议值得关注。首先就是这门语言的性能和健全性问题。需要注意的是,TypeScript 团队其实很清楚这两大顽疾,而其根源是开发团队在项目之初做出的明确权衡。在我看来,这些权衡是当时为了提高执行效率而做出的正确选择。
话虽如此,但性能确实是 TypeScript 最受诟病的问题。TypeScript 是自实现的,而且这种实现非常复杂。它的类型系统本身可以算是种迷你编程语言,这导致类型检查的速度极其缓慢。
第二个问题就是健全性。这事的讨论热度没那么高,但在编程爱好者群体内部还挺受关注。概括来讲,TypeScript 一身都是“缺陷”——allwJs 配置选项、any 类型和 intersection 类型,其类型系统根本无法保证代码的类型安全。换言之,我们编写的 TypeScript 很可能会触发运行时 bug。另外,除了极其简单的场景之外,TypeScript 还缺乏可靠的类型推断,所以开发者在很多地方都得明确标出类型注释。
但同样的,这两点也是项目权衡的结果。
引导编译器的存在对于 TypeScript 的内部测试至关重要,这能帮助项目开发者理解 TypeScript 这种语言用起来的真实感受。具体来讲,项目团队要体验如何编写大型 JS 代码库,再逐步采用代码库中的类型。在健全性方面放松一点,开发者才能在现有 JS 代码库中逐步引入 TypeScript,也能轻松使用 any 类型来直接摆脱类型系统的束缚。
光是这部分就够单独写篇文章了。在我看来,TypeScript 可能是第一种更多关注开发者体验、而非自身语义的编程语言。它并没有添加任何运行时结构、不插手性能,而是添加了一套类型系统,并让整个语言社区接纳了这种不用类型也行、没高质量工具也行,还不强调正确性的生态氛围。这简直是个不可思议的壮举。
所有这一切都表明,TypeScript 早在十年前就做出了一众对自身产生巨大影响的权衡。而随着时间推移,我觉得是时候通过新语言再做一轮权衡了。确切来讲,我们需要一种具备健全性、类型推断和更快编译速度的语言。
要求明确了,但我们该拿什么来换?
先从健全性说起。下一代语言不再努力对各种 JS 模式进行类型检查,而是以独立语言的形态通过更简单的类型系统将代码编译成 JS。它会将现有 JS 代码视频外部互操作对象,对 JS 代码执行显式运行时类型检查,而且依靠不同的原生语言来实现。
为什么要这样?首先,我个人特别喜欢具备既健全、又相对简单的类型系统的语言。我希望这种语言能够在浏览器中运行良好,而且能顺畅适配现有 Web 生态系统。那些能编译成 Wasm 的语言经常忽略 Web 生态系统中的其余部分,总想在浏览器中建立起基于像素的原生 UI。我觉得这个想法不错,只是跟我的观念相悖。我只想用下一代语言开发常规网站;我不想要纯函数式语言,而更倾向于跟 C 的老派风格相似的语言(对不起了,Elm!);我希望这种语言能体现出我在工具设计上的想法。
那为什么下一代前端语言应该诞生在现在这个时间点?俗话说得好,种一棵树最好的时机是十年前,其次是现在。这十年来,JS 社区已经发生了很大变化。人们开始学习 TypeScript,也习惯于关注编译器并通过类型进行数据建模。现在,很多开发者开始使用 Rust、Swift 和 Kotlin 等语言,也意识到高质量工具的重要性。我不是说十年前的人们会抵抗强调类型安全的语言,但那时候的普及难度确实更高。
明确表达了需求,有些朋友可能觉得这说的不就是 ReScript/ReasonML 吗?没错,确实有几分相像。但在理想情况下,我期待的下一代语言应该能对 JS 代码和特性进行显式运行时类型检查。运行时类型检查是达成良好互操作性的前提,这样我们就能更轻松地随意使用 JS 库。
同样地,我觉得 traits 对用户来说也很重要,它们可以跟其他语言特性映射起来,比如 Java 接口和 C++ 概念。这可太方便了,比如轻松通过 Display trait 输出任意类型。这类需求听起来简单,但确实能大大提升语言的可用性,消除“我该怎么输出这个?”或者“为什么 + 代表整数加法,而 +. 代表浮点加法?”之类特别劝退的问题。再有,我还想去掉一些没用的东西,比如对象、链表、多态变体等。这些都是 ReScript/ReasonML 做不到的,而且我上次试用的时候,ReScript 的开发体验和错误消息也没给我留下深刻印象。
也就是说,我不排除 ReScript 代表着正确方向的可能性。毕竟上次尝试已经是几年之前了,也许是我记错了、也许它已经变得更好了。而且随着同 OCaml 的剥离,ReScript 确实成了很好的前端语言选项,我有必要再确认一下。
对于下一代前端语言,我希望能用一种更系统的方法实现类型安全。具体来说,我觉得用 Rust 处理非安全代码块的方式实现 JS 互操作性的好办法。基本上,在调用 JS 的过程中,我们需要将代码打包在一个非安全代码块中。这会是个明确的标志,提醒开发者要认真阅读这段代码。接下来的目标,就是在这些指向 JS 库的非安全代码块上实现 bindings。起初这个过程需要手动完成,但后续应该会有类似 bindgen 和 cxx 的工具出现。
在 JS 中使用非安全代码块好像有点反直觉,毕竟 JS 的安全性又不像 C 那么糟糕。但很多人似乎没意识到,安全的意义并不仅限于安全本身。所谓安全,是指可以任意使用一个值、而不必担心其是否为 null 的保障能力。所谓安全,是在不致引入 Bug 或混乱的前提下保证可变性的能力。Rust 的非安全块概念允许用户既维护自己的安全区,又能与大量非安全代码交互。下一代浏览器语言也该做到这一点。
至于运行时检查,我觉得它仍然物有所值。我们已经在 JS 当中进行过大量模式验证,只是以往只能通过 zod 这类临时性机制完成。在下一代前端语言中,这类功能也许是在运行时出错时对语言类型执行自动转换,也许能对 JS 值进行模式匹配。
对于 WebAssembly,我还是很看好它的发展前景的。但要说它一定能成为浏览器的通用运行时,我个人还是持怀疑态度。也许未来我的态度会有转变,但目前我更多是将 Wasm 看作一种硬件加速器。
当用户的高强度计算任务要求调用固定宽度整数和静态函数时,大家就会使用 Wasm;这就像在需要执行并行计算时,大家会选择 GPU 一样。在这样的模型中,我看到了支持异构编译的潜力——其中部分代码可以被编译成 JS,另一部分代码则可编译为 Wasm。这项工作可以由用户显式完成,由分析自动完成,甚至可以即时完成。通过对 JS 和 Wasm 代码的同时控制,编译器就能最大限度减少跨越语言边界的次数,从而提高性能水平。我觉得未来甚至可以有某种机制将部分代码发送给 WebGPU。
在这样的模型之上,也许我们可以更轻松地编写计算密集型程序,比如机器学习模型、电子游戏和渲染软件。
这种对 Wasm 和 JS 进行分别编译的概念,可以在下一代前端语言中体现出来。我希望其中能有显式整数和浮点类型,最好还能有 Rust 中 usize 那样的显式索引类型。这样如果需要把代码编译成 Wasm,新语言就能利用 Wasm 的固定宽度整数。
还有另一种可能性,就是为语言创建一个子集,在这里整合闭包、垃圾收集等动态特性以提升 Wasm 编译质量。要跟这个子集交互,开发者需要使用 unsafe 代码块,比如 strict 块,或者让该子集通过 dynamic 块跟外部代码交互。这些都是假设,但我觉得其中确有探究的价值。
这种新语言可能会用 Rust 来实现。毕竟我个人是 Rust 的粉丝,而且相信代数数据类型、相对更高的代码性能、受限但可用的可变性,以及比较丰富的库组合足以支撑起一套优秀的编译器。
如果 Wasm 后续发展得够好、性能几乎逼近原生水平,那我也会考虑使用由编译为高速 Wasm 代码的语言子集来引导编译器。但这应该不着急,毕竟一个 Rust 编译器应该就够用好多年了。
大家可能已经注意到,类型安全和 Wasm 部分其实就是在从系统语言(例如非安全概念和硬件加速)中汲取灵感,再把它们应用到基于浏览器的语言当中。这是设计使然,毕竟不少最有趣的编程语言都是从系统层面衍生出来的。我只希望这些好点子也能在浏览器上有所体现。
这里我要澄清一下,我所指的下一代前端语言绝不是单一语言,我希望能有多种语言齐头并进、朝着前面提到的方向共同探索。我想激励更多朋友在浏览器语言领域不断创新。当然,我个人也会参与其中,目前正在研究的是名叫 vicuna 的实现方案,但还处于非常早期的阶段。
原文链接:
https://uptointerpretation.com/posts/the-next-browser-language/
*请认真填写需求信息,我们会在24小时内与您取得联系。