Rust语言介绍
Rust语言是一个极其讲究精致的系统级别语言,它瞄准的是取代C/C++,语言的发展和变化很快, 本文介绍Rust语言的优缺点以及与其他语言的大概比较。优点 首先是没有GC的内存安全型,对于低级系统级的编程语言,直接内存操作是允许的,在运行时出现内存错误如use-after-free或内存泄漏的代价是昂贵的,虽然C++提供很好的工具来处理它,但是这还是需要工程师的纪律,在大型系统中就不难很好解决这个问题。垃圾回收GC是解决内存安全的最普通方式,但是Rust系统并不依靠GC,而是在编译时通过RAII(Resource Acquisition Is Initialization)实现资源自动释放,这样不但能提供内存安全,还提供数据和资源安全。这样能降低开发者手工管理内存的必要,能够自动确保清理工作总是在运行,甚至当任务出现崩溃恐慌时。 动态语言如Python和Ruby也提供类似能力,但是没有Rust这样强大。 第二个优点是无需竞争的并发,Rust能够确保在并发编程中的数据安全,某个时间点同时只能有多个读操作或一个写操作被允许访问共享数据。 第三个优点是提供代数数据类型,除了tuple struct类型以外,Rust还提供enum和模式匹配,这些都是高级类型系统才拥有的功能如今出现在系统级的编程语言中。 第三个优点是基于继承的组合,Rust能基于继承实现组合,Trait是Rust泛型中重要角色。缺点 水至清则无鱼,对于Rust编译器,每件事都必须得清清楚楚,当遇到灰色情况它会拒绝编译,直至你搞清楚它,这对于代码质量是一个好事情,但是对于讲究开发效率的项目来说就是有点苛刻了。 第二个缺点是GC是二等公民,Rust提供基本的GC(RC),如引用计数 自动计数(Arc),并没有循环检测,它们并不是语言中第一等公民,你最终只能使用Rust的内存管理(stack 和Box)。 第三个缺点是富有表现力不是其目标,充满像动态语言那样富有表现力和优雅不是Rust的目标。 第四个缺点是门槛高,Rust并不是你能在几周内捡起学习马上就精通的那种语言,Rust也许小于C++,但是它的定义比很多语言要大,它不一定适合大多数人群,从另外方面看,门槛高也是过滤器,可以保证代码高质量。与其他语言比较 与动态语言或脚本语言比较,它们的目标是不同的,动态语言适合快速原型或立即完成实现的任务,而Rust适合大型团队,需要很长的产品周期,长期不断进行维护重构的项目。 动态语言让你起步很快,代价会在后期偿还,而Rust编译器一开始就强迫你正确细节地做事,时间长了效率会不断提高。 与Go语言比较,Go语言相比Rust太简单,太小型化了,Go适合企业软件开发,类似以前的java,另外Go语言是由Google推动的,如果以后公司利益与社区利益冲突如何处理?而Rust则是由非营利组织Mozilla 推动的。 与Nim (正式名称 Nimrod)比较,Nim能编译到C,这样它的性能很好,它非常酷似Python,它是GC语言,但是实时提供对GC行为更多预测,最大的问题是生态系统和成熟度,有待发展和健全。 与 Julia 和D语言比较,Julia是一个拥有好的性能的动态语言,提供REPL和平滑的C调用,它在数字和科学领域比较受欢迎,不是一个通用目标的语言。D语言目标是一个更好的C++,但是其实使用范围不广,几个原因: 早期的Phobos/Tango分离,内存安全完全依赖垃圾回收GC,只不过是一个更好的C++。 Rust语言是一个系统级的语言,未来也许发展对Web的支持。如何看待 Rust 的应用前景?
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:卢旺杉
链接:http://www.zhihu.com/question/30407715/answer/48032883
来源:知乎
工作上写C++,从去年底开始关注Rust,至今用Rust写了一些和交易相关的小程序。总体感觉是如果有一门语言能够取代C++,那么它只可能是Rust。
为什么这么说呢?首先我们来说一下为什么很多情况下人们会选择C++。
很多人用C++的不是因为C++有多好,只是因为如果想要写一个接近实时高性能,稳健,并有足够开发效率的大程序,通常只有C++可选。这有如下几个原因:
[*]要写接近实时,就不要能有垃圾回收(GC)。GC对于一些类型的程序几乎是致命的。想像一个低延时交易程序在看到一个交易机会之后因为某种原因触发长达100ms的GC,这个机会铁定就没了。要想达到接近实时且高性能就需要接近底层,即所谓bare-metal。
[*]高性能可以用C达到,但考虑足够的开发效率,C的语言特性缺乏就是一个明显问题。我们也不想在组一个小组开始开发的时候还要来写一遍数据结构基础设施。C++的多语言范式提供了这样一些基础的组件,多数情况下你不需要再去写一个hashmap或者查找算法。
[*]从开发效率和可读可维护性上来说,足够的抽象能力是必须的,但这种抽象必须是没有运行时开销的(runtime cost)。零开销抽象(zero cost abstraction)是C++的设计原则之一。inline函数,constexpr程序,template,都是遵循这一原则,编译器如果发现虚类(virtual class)没有真正被用到甚至会优化掉虚表(virtual table)。
[*]稳健的大程序则意味着程序要尽量把错误消灭在进生产环境之前,要达到这个目标,我可以牺牲一点开发效率。这就意味着我需要一个静态类型最好同时是强类型的语言,使得编译器能够早发现问题。<Effective C++>会强调一些诸如单参数构造函数最好加explicit之类的"技巧"来加强类型检查。C++11在这个基础上加了如enum class。各种override,final等都是加强编译器在编译时查出错误的能力。
总体上来说,就是一个高性能的静态强类型多范式语言。
但同时,C++问题很多,这些问题不是语言设计者能力不够,而多数是历史原因与当时抉择所看重的东西导致的。C++一开始的时候一个目标是与C兼容,即使C当年算是极其天才的设计(和Unix一样),它毕竟是1972年的语言,当时设计导致的问题虽然我们现在已经很清楚,C++也因为兼容性而把它保留了下来。大家都知道Python 2和Python 3的故事,甚至IA64和x86_64的故事,所以也很容易理解C++为什么要一直保持向前兼容。
Rust由于是一个新语言,所以它完全没有历史包袱。甚至在今年之前的五年中,社区一直完全肆无忌惮的做和之前完全不兼容的改动。如果发现有个新设计确实公认更好,语言作者们不会为了向前兼容而放弃改变。近30年的语言理论研究和实际软件工程的经验有足够多的优秀设计可以直接拿来使用。Rust作为一个新语言显然不会放过这个机会。在可以完全重来的前提下,Rust相对C++有哪些新特性呢?
[*]无data-race的并发。使用类似golang的channel-based并发非常易用。在不用lockfree的情况下,开发和运行效率都足够高,逻辑简单,加上下面的杀手特性避免data-race。
[*]函数式语言的pattern matching。网站首页就提供了一个简单的例子,用惯指令式和面向对象的朋友可能需要一段时间发挥它的强大之处。实际上Rust还提供非常多的函数式语言特性,包括强大的closure,由于下面要提到的杀手级特性的保证,Rust的closure十分安全。
[*]Generics和Trait粗看起来是zero cost abstraction的编译时多态(compile-time polymorphism),类似于C++中的template和C++17里的Concept。但实际上它设计的精巧已经远不是C++中template的同类了。其中一点就是统一了compile-time和run-time polymorphism,编译时多态叫trait,运行时多态叫trait object,省去了不少程序语义方面的复杂性。Trait这个特性这也是很多把golang看成是静态类型系统语言而又发现它竟然没有编译时多态的同学震惊而无奈的离它而去的原因。(golang作为服务器语言仍然是相当不错的选择,不过现在已经没有多少人还把它看成是系统语言了。)
[*]灵活的enum系统,以及衍生的错误处理机制。Rust没有exception,错误是通过enum返回的。与golang在正确时也会返回错误代码不同,Rust错误代码只有在错误时才返回。这不仅仅只是方便,而有更重要的好处。
[*]简单易用的与C语言的互通性。因为没有runtime,与C语言的互通简单是很自然的。这篇文章讲得很详细。
[*]灵活的module系统。module系统以及pub和use关键字让你灵活的控制所有的访问许可关系。
[*]强大的管理系统Cargo和中心化的库管理crates.io。Cargo的依赖管理遵循最新的Semantic Versioning。只需要适当选择库的依赖版本,一个cargo update会自动完成所有版本匹配和下载加载。被C++依赖摧残的小朋友们可以开心了。
[*]其它的诸如,缺省可使用的直接打印数据的内容状态,更好用的宏,更漂亮的条件编译,语言自带的简单测试系统,rustdoc的自动文档生成,都让开发的效率和快感大增。一些小的改动,如缺省是不可变而不是mut的声明,match的exhaustive checking,都使人更容易写出更正确的代码。
当然,如果只有这些小改进,C++程序员可能看了看觉得,“不错哟”,然后就接者回去写C++了(比如D)。新语言必须有杀手级的特性,这才是转语言的关键动力。
这一杀手级的特性就是Ownership和Lifetime。Rust首页宣称的"prevents nearly all segfaults, and guarantees thread safety"是超级诱人的,因为这是在没有GC和runtime的情况下实现的。
C语言的野指针,和线程安全问题会导致很多极难发现,诊断和修复的bug。C++,尤其是C++11费心思去缓和了这一问题,但这仍然是没有GC讲求性能语言的核心劣势。Rust这个特性具体是如何的呢?
[*]Rust里每一个引用和指针都有一个lifetime,对象则只不允许在同一时间有两个和两个以上的可变引用。出了lifetime编译器在编译时就会静止它被使用。这样,如果一个操作使另一个引用不再可用,编译器就会发现它。C++里面的使用to_string().c_str()导致crash的bug应该不止一个人见过,这种bug在rust里是不会被编译通过的。
[*]这种特性使得原来在C++里不敢使用的一些优化做法变得完全可能。比如把一个c_string分割成不同分,并在不同的地方使用。如果项目较大,为了完全起见,通常我们会把分割的结果拷贝一份单独处理,这样不需要害怕处理的时候那个c_string已经不存在。而使用Rust我们可以不用拷贝,而直接使用原来的c_string而不用担心野指针,lifetime设定可以让compiler去做这一繁琐的检查,如果有任何的c_string在处理分割结果之前被使用,编译器会告诉你。
这一特性所导致的编程可以衍生很多新的优化可能,而这都是在保证完全的前提下。实际上,催生Rust的浏览器Servo项目一个目标就是安全问题,Rust在安全性让heartbleed问题出现的可能大大减小。
最后,Rust是一个脚踏实地(Practical)的语言。这意味着它不遵循某一个范式(paradigm)或者是为计算机科学教学而生的语言。这是一个写给开发者的语言,如果特性经过权衡发现对开发有益,语言作者不会因为它破坏了某种范式而不去加它。这种哲学有些类似于当年Linux相对Mimix选择monolithic kernel而不是结构上更干净的micro kernel,因为Linux需要性能。这样的选择会让语言更接近使用者,让使用者更开心。
所以用C++的那些人的那些要求,Rust都能达到或者甚至改善。
[*]无GC实时控制,接近底层没有overhead。在达到同样安全性的情况下,Rust不会比C++慢。
[*]足够多的语言特性保证开发效率,比C++吸收了更多的现代优秀语言特性。
[*]与C++一致的Zero cost abstraction
[*]杀手级的ownership和lifetime,加上现代语言的类型系统,这是比C++强最多的地方。
在语言层面上Rust无疑比C++优秀得多的一个高性能静态强类型多范式语言。
如Rust 1.0 Announcement所说,1.0标志着Rust已经稳定。你能在1.0编译器上使用的特性都会保证继续存在,除非重大正确性(soundness)问题出现。现在已经没有“下一个版本出来,之前的代码就不能用”的顾虑了。
1.0的发布是Rust发展的一个动力。当然真正长时间的采纳率还要看语言本身质量和社区环境。对这两点我是相当看好的。要想取代C++绝不是一件容易和快速的事,这不紧只是语言的问题,而有很多不可控的其他因素,让我们拭目以待吧。
页:
[1]