今年10月22日,在华为开发者大会上,华为表示在2022年推出自研的编程语言仓颉,将鸿蒙和欧拉在应用开发生态上进行打通。这么多年的开发生涯,使用了包括C/C++,Java、Python、Kotlin、JavaScript、C#等开发语言,不同的场景使用不同的语言,但是没有想过为什么要用该语言。对于新出的仓颉语言我们该有哪些期待呢?
我们知道除了上述用过的,还有其他PHP、GO等都是国外企业研发的,仓颉除了打上国货的标签,可能有人会期待是不是以后编程可以用中文了?这个我认为基本没有可能性,编程语言要考虑到的一点是简洁高效,目前的编程语言里的关键词都可以理解成是符号,如果这些符号都是中文会是一种怎样的景象? if 关键词改成如果,从输入两个字符改成输入六个字符,这成了开倒车了。
当然,编程语言除了本身的语法,还有API以及文档等,仓颉的中文文档我们倒是可以期待的。那么除了国产,还有什么是我们可以期待的?要解答这个问题我们明白我们选择一种编程语言是要考虑的因素。我们先来看看热门编程语言各自的优劣势。
1. 热门编程语言对比
Python
优势:简单易学,身面向对象语言,具有丰富和强大的库,轻松地使用C语言、C++、Cython来编写扩充模块,所以很多称它为“胶水语言”。
劣势:速度较慢,且有一些特定情况下才会出现(无法重现)的 bug
C/C++
优势:可以被嵌入任何现代处理器中,几乎所有操作系统都支持 C/C++,跨平台性非常好
劣势:学习难度大。
Java
优势:世界上使用范围最广的语言Java,具有高度的跨平台兼容性或平台无关性。由于你可以在任何地方进行编码,因此可以编译为低级机器代码,最后,可以使用JVM – Java虚拟机(取决于平台)在任何平台上执行。
劣势:占用大量内存,并且启动时间较长
JavaScript
优势:学习难度低,并且掌握了 JavaScript 语言就等于成为能同时开发网页、后台、移动端的全栈工程师
劣势:过于依赖浏览器,且代码在用户电脑上运行,容易被别有用心的坏人恶意利用
PHP
优势:社区庞大而活跃,易于快速上手
劣势:运行速度慢,且错误处理机制比较糟糕,需要支持大量旧版本的功能
Objective-C
优势:拥有丰富的工具和库
劣势:拥有自己独特的编程思路,与其他编程语言思路差别较大
Kotlin
优势:和 Java的互操作性极佳
劣势:继承了 Java 劣势内容
2. 选择编程语言考虑因素
2.1 外部因素
2.1.1 平台支持
首先平台支持是我们选择语言的首要考虑因素,我们要做Web开发,我们可以选Java,选PHP,选GO,但是有时候一些平台性的限制导致我们”没得选“,比如我们要做Android开发首先考虑Java,要做iOS开发首先考虑OC,要做网页开发,首先考虑JavaScript。
2.1.2 待开发系统的应用领域
不同的应用领域我们也必须使用想匹配的语言:
- 科学工程计算。需要大量的标准库函数,以便处理复杂的数值计算,可供选用的语言有FORTRAN语言、C语言等。
- 数据处理与数据库应用。SQL为IBM公司开发的数据库查询语言,4GL称为第4代语言。
- 实时处理。实时处理软件一般对性能的要求很高,可选用的语言有汇编语言、Ada语言等。
- 系统软件。如果编写操作系统、编译系统等系统软件时,可选用汇编语言、C语言、Pascal语言和Ada语言。
- 人工智能。如果要完成知识库系统、专家系统、决策支持系统、推理工程、语言识别、模式识别等人工智能领域内的系统,应选择Prolog、Lisp语言。
2.1.3 开发效率
在上面两项的前提下,开发效率是接下来要考虑的第三方面,最直观的表达就是可以用一行代码实现的不要让我用十行代码实现。这里面又设计到几点:
- 该语言支持的开发框架:有多少轮子可以供你直接使用,省去我们直接造轮子的成本,结果就是我们可以少写代码;
- 语法的简洁性:比如让我少写一个分号也算,比如Kotlin相比Java,生了new,省了分号,还提供了默认函数等;
- 跨平台性:跨平台也是可以提升效率的一种手段,我一份代码运行两个平台,变相省下一半人力。比如移动端的Flutter,小程序框架等。
2.1.4 开发生态
再下来就是要考虑生态了,这里面包含下面几点:
- 受欢迎程度:收欢迎程度一定程度决定了该语言开发者的人数,人数多了,可以降低招聘成本。当时公司要做全平台项目,在PC上考虑用Node或者Flutter方案,我当时说用QT的方案就是因为市面上人员太少了,招聘困难;
- 社区活跃度:优秀的入门引导可以降低该语言的进入门槛,活跃的社区可以极大的帮助同行解决问题,行程良性循环;
- 薪资水平:在一个公司,同样的级别可能不同的语言栈对应不同的薪资水平,薪资水平也是吸引开发者进入关键因素。
2.2 内在因素
上面介绍的都是外在的因素,内在因素是一门语言有哪些吸引人的特性,举个例子,谷歌推出Kotlin来替代Java,它带来哪些优势呢?
2.2.1 Kotlin&Java
- null安全性:它可以让编译器系统地标记潜在的空指针解引用,避免运行时错误。
- 字符串插值:就好像
String.format()
这个语言内置了一个更智能,更可读的Java版本:
val x = 4
val y = 7
print(“$ x和$ y之和为$ {x + y}”)// 4和7之和为11
- 智能的类型推断和类型转换:
val a =“abc”//类型推断为String
val b = 4 //类型推断为Int
-
直观的等式,没有了
equals()
和==的混淆:val john1 =Person(“John”) val john2 =Person(“John”) john1 == john2 // true(结构相等) john1 === john2 // false(引用相等)
-
没有多余的分号,没有分号可以更快的编写代码。
-
没有new关键字,省去不必要的代码。
-
支持默认参数,不需要用不同的参数定义几个类似的方法:
fun doSomething(title:String,width:Int = 800,height:Int = 600){ }
-
Lambdas表达式
val sum = { x: Int, y: Int -> x + y } // type: (Int, Int) -> Int val res = sum(4,7) // res == 11
-
扩展函数:允许将方法添加到类中,而无需修改其源代码。这意味着再也不用写utils了。
-
协程。
-
将语言特性的发展与jvm虚拟机脱钩。Kotlin基于jvm,但不依赖高版本jvm,在工业界依然还是jvm1.8天下的情况下,升级jvm某种程度上是奢望。而kotlin可以在保持jvm1.8前提下不断迭代新的语言特性,跟进现代的编程语言发展之步伐。
-
新语言可以避免背上历史包袱。kotlin语言的应用范围并不广泛。但正因为它的应用范围不广泛,所以kotlin语言的发展不会有过多的历史包袱,我们知道Java跟C++增加任何特性都需要考虑与旧版本的兼容性。而他们已经存在了二三十年,需要兼容的特性越来越多,历史包袱越来越多就会导致进步越来越困难。
上面提到的很多特性在其他语言已经应用的很广泛,比如python也没有分号,C++也可是不使用new,python和C++都支持默认函数,Kotlin可以理解成是吸收了其他语言的精华版本的Java。
2.2.2 Go&C++
近几年比较火的Go语言,是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言,它用批判吸收的眼光,融合C语言、Java等众家之长,将简洁、高效演绎得淋漓尽致。
Go语言起源于2007年,当时Google的技术大神们备受C++越来越臃肿的困扰,决心开发一种新的语言来取代C++。他们认为:与其在臃肿的语言上不断增加新的特性,不如简化编程语言。于是,Golang这门新语言应运而生。
在十年多的时间里,Go语言发展势头强劲,凭借其简洁、高效的特性,在竞争激烈的编程语言市场中占据了一席之地。Google、腾讯、阿里等大公司纷纷选择使用Go语言来开发服务应用项目。
优势
1.自动垃圾回收降低了开发难度
内存和资源管理一直是一个让人非常抓狂的难题。在其他语言(如C或C++)中,使用内存前要先分配这段内存,使用完毕后再将其释放掉,一个小疏忽就可能引发内存泄漏,导致程序甚至系统崩溃。而Go语言的现代化垃圾回收机制显著地降低了开发难度,把无趣的内存管理交给专业的编译器去做,而让程序员专注于更有趣的事情。
2.更丰富的内置类型
Go语言是一种典型的实战派语言,它内置了一个其他静态语言通常用库方式来支持的字典类型(map),理由很简单:既然绝大多数开发者都需要用到这个类型,为什么还非要每个人都写一行import语句来包含一个库?
Go语言还新增了一个数据类型:数组切片(Slice)。我们可以将数组切片看作是一种可动态增长的数组,其功能与C++标准库中的vector类似,但有效地消除了反复写以下几行代码的工作量:
#include <vector>
#include<map>
#include<algorithm>
using namespace std;
使用Go语言,开发者不用再费事添加依赖的包,既减少了输入工作量,又可以让代码更简洁。
3.支持函数多返回值
目前的主流语言中除Python外基本都不支持函数的多返回值功能,但很多情况下开发者非常需要这个功能。比如,我们要定义一个函数,用于返回个人的名字信息,而名字信息包含多个部分——姓氏、名字、中间字,在不支持多返回值的语言中有两种做法来实现名字信息的返回:
专门定义一个结构体:
struct name
{
char first_name[20];
char middle_name[20];
char last_name[20];
};
extern name get_name();//函数原型
name n = get_name();//函数调用
或以传出参数的方式返回:
extern void get_name(
char* first_name,
char* middle_name,
char* last_name);//函数原型
//先分配内存
char first_name[20];
char middle_name[20];
char last_name[20];
//函数调用
get_name(first_name,middle_name,last_name);
Go语言的多返回值功能让开发者既不用再只为了返回多个值而专门定义一个数据结构,也不用再区分参数列表中哪几个用于输入,哪几个用于输出。
使用Go语言返回名字信息可以这样写:
func getName(firstName,middleName,lastName string){
return "May","M","Chen"
}
fn,mn,ln,nn := getName()//函数调用
4.漂亮的错误处理
漂亮的错误处理规范是Go语言最大的亮点之一。Go语言引入了defer关键字用于标准的错误处理流程,并提供了内置函数panic、recover完成异常的抛出与捕获。与C++和Java等语言中的异常捕获机制相比,Go语言的错误处理机制可以大量减少代码量,开发者无需再仅为了程序安全而添加大量一层套一层的try-catch语句。
5.匿名函数和闭包
在Go语言中,所有的函数也是值类型,可以作为参数传递。Go语言支持常规的匿名函数和闭包,比如下列代码就定义了一个名为f的匿名函数,开发者可以随意对该匿名函数变量进行传递和调用:
f := func(x,y,int) int{
return x+y
}
6.简洁的类型和“非侵入式”接口
Go语言的类型定义非常接近C语言中的结构(struct),甚至直接沿用了struct关键字。为了保持简洁,Go语言没有直接沿袭C++和Java的传统去设计一个超级复杂的类型系统,不支持继承和重载,而只是支持最基本的类型组合功能。虽然看起来过于简洁,但Go语言依然能够实现C++和Java使用复杂的类型系统才能实现的功能。
而引入强大的“非侵入式”接口让开发者从以往对C++和Java开发中的接口管理问题中解脱了出来。
7.并发编程更轻盈更安全
Go语言引入了goroutine概念。goroutine是一种比线程更加轻盈、更省资源的协程。通过使用goroutine而不是裸用操作系统的并发机制,以及使用消息传递来共享内存而不是使用共享内存来通信,并发编程变得更加轻盈和安全。
当然,和其他的编程语言一样,Go语言也有其自身的缺陷。
劣势
1.软件包版本管理不完善
Go语言的软件包版本管理一直被开发人员吐槽。Go语言没有制定特定版本的依赖库,在不同时间构建时,创建的生成可能会基于不同版本的包。在这方面,Go语言还无法与Python、Java等语言的软件包管理系统相媲美。
2.错误信息难获得
Go语言的错误处理最被人所诟病的一点是,开发者不能从函数上知道下层函数可能返回哪些类型的错误,很容易丢失错误发生的范围,难以提供有效的错误信息。
2.3 底层技术
上面还是基于语法层面的,基于底层的实现方面的呢?
我们计算机是不能理解高级语言的,更不能直接执行高级语言,它只能直接理解机器语言,所以使用任何高级语言编写的程序若想被计算机运行,都必须将其转换成计算机语言,也就是机器码。而这种转换的方式有两种:编译和解释。由此高级语言也分为编译型语言和解释型语言。主要区别在于,前者源程序编译后即可在该平台运行,后者是在运行期间才编译。所以前者运行速度快,后者跨平台性好。
编译型
编译型语言因为一次性的编译成平台相关的机器语言文件,运行时脱离开发环境,所以运行效率高,同时由于与特定平台相关,一般无法移植到其他平台,现有的C、C++、Objective等都属于编译型语言。
解释型
对应的解释型语言每次运行都需要将源代码解释称机器码并执行,效率较低,只要平台提供相应的解释器,就可以运行源代码,所以可以方便源程序移植,Python就是典型的解释型语言。
Java
我们看到Java语言介绍的是跨平台,一处编译到处运行;C/C++也是号称跨平台,他们的跨平台有什么不同呢?
C/C++的跨平台是同一份源码可以在不同平台编译成字节码后运行,是基于它的编译型特定;而Java是基于Java虚拟机,首先把代码编译成Java字节码,再在真正运行的时候将Java字节码”翻译“成平台操作系统字节码,所以其实Java底层上说还是”解释型“语言。
其他
高级编程语言从另一个角度又可以分为强类型语言和弱类型语言:
- 强类型语言(静态语言):是编译时变量的数据类型就可以确定的语言,大多数静态语言要求在使用变量之前必须生命数据类型。比如Java、C、C++、C#等。
- 弱类型语言(动态语言):是运行时才确定数据类型的语言,变量在使用之前无需申明类型,通常变量的值是被赋值的那个值的类型。比如Php、Asp、JavaScript、Python、Perl等等。
静态语言由于强制声明数据类型,让开发工具(IDE)对代码有很强的判断能力,在实现复杂的业务逻辑和开发大型商业系统、以及那些声明周期很长的应用中,开发者可以依托强大的IDE来更高效、更安全地开发。
动态语言思维不受约束,可以任意发挥,把更多的精力放在产品本身上;集中思考业务逻辑实现,思考过程就是实现过程。
总结
文章分析了几种编程语言优劣特征,以及选择编程语言常见的因素,从这些因素考虑,我们对仓颉语言应该有哪些期待呢?
- 中文文档;
- 效率与性能兼顾;
- 成熟的开发生态(包括包管理等);
- …