文 / 小乐
11月8日,对于网红仲尼的家人来说,无疑是极具悲痛的一天。因为仲尼不幸在巴厘岛海上游玩时溺亡了,原本幸福的一家人,如今却遭遇如此横祸,实在令人痛心不已。
据悉,仲尼带着乌克兰妻子卡琳娜,特意赶赴巴厘岛庆祝自己的34岁生日,没想到就这样一去不复返了。很多粉丝听闻这样的消息时,感觉真假难辨,并没有放在心上。直到8日晚间多个媒体皆发布了仲尼溺亡的新闻后,才知仲尼真的遇难了,不禁为其惋惜不已。
只能感叹意外来得总是那么突然,明明当时海上风平浪静,然而恰巧在仲尼身边出现了一股海流,直接将仲尼和另一位名字缩写为KM的乌克兰公民被海浪卷走,事发后不久,只有KM被救起,并被转到最近的诊所接受治疗。
而仲尼则消失在了茫茫大海上,一直到了次日搜救队终于在沛提恩洁海滩(Petitenget beach)附近海面上发现了仲尼发尸体。
从现场传出来的照片来看,经过一夜海水的浸泡后,仲尼的头部皮肤已经被泡白了,看到这一幕,妻子卡琳娜再也控制不住自己的情绪,抱着仲尼的遗体痛哭不已。
毕竟,两人的结合可以说是一段佳话,郎才女貌,十分般配。来自乌克兰的卡琳娜,无论是颜值身材皆很出挑,完全不输娱乐圈的女明星们。
卡琳娜与仲尼所入住度假村的酒店管理者随后接受红星新闻采访时透露:
两个人看起来关系很好,在一起很开心。他们俩6号晚上来的,7号去的海滩,卡琳娜的朋友一起去了海滩,然后就发生了失踪事件。
而据目击者表示:“事发当时他们去海滩游泳,但是后来越游越离海滩越远,幸运的是他的妻子没有失踪,当时也是非常难受被吓到了!”
如今,仲尼的生命永远定格在了34岁,留下了老婆孩子,可谓让人遗憾不已。目前,国内的亲属得悉这个噩耗,正紧急赶赴巴厘岛接仲尼回家。
网红仲尼不幸去世的消息,也引起了网友们热议。很多网友纷纷觉得他的名字取得不好,表示这个名字起得太大了,承受不起。
原来,儒家学派创始人孔子,子姓,孔氏,名丘,字仲尼,两者重名了。不过,这些只是网友们天马行空的想象而已。
毕竟,意外随时降临,有时候你根本防不胜防。只能说,生死有命富贵在天。
网红仲尼的离开,无疑给了妻子卡琳娜沉重一击,因为她的中文很差,此前在中国的工作都是仲尼帮忙接洽的。希望卡琳娜早日从悲伤中走出来,因为还有孩子需要她照顾。
我绝不是 Rust 的粉丝,但感觉这篇咆哮并不完全知情。比如
> 只要给我一个垃圾回收器,让我做我想做的事!
和
> 但与其他语言(如 Go)相比,它的 “安全性 “对我来说更像是一种损害。
听起来作者并不清楚什么是 “内存安全”。很多语言都是内存安全的。不同之处在于,Rust 以零成本(实际上是 “非常低 “的成本)实现了内存安全。如果垃圾回收语言可以在不牺牲其简洁性的前提下做到这一点,那么它们就会这么做。
这是一种权衡。如果你觉得 Kotlin 在性能方面没问题,那就用它吧!Rust 更像是 C/C++ 的替代品,因为性能很重要。如果你喜欢 Rust,可以在任何地方使用它,但如果你讨厌它,就不要在性能不重要的时候使用它!
问题出在 Rust 的营销上。他们把这种语言卖得太好,让它适用于那些不需要同等安全性或速度的用例,而 Java(或 Go,或 C#)会是更实用的选择。
如果你正在编写操作系统或浏览器,Rust 会是一个不错的选择。基本上,C++ 可以替代任何其他语言。
我有一种模糊的直觉,之所以选择 Rust,是因为它支持高质量的抽象,而这正是现代语言所缺乏的。我一直在开玩笑,但不变性对于一般的软件开发来说非常重要。主流语言都不支持这一点,但 Rust 实现了同样的优势(即使方式不同)。Rust 的类型系统是健全的,而现代语言还在处理有问题的空值和缺乏高级类型(比如 typescript 可以做到的)。
100%.我担心的是,这种反弹会像炒作(关于 rust 最适合一切)那样传播开来,突然之间 rust 就成了无用之选。我的经验是非常积极的,但我的工作主要是在 Rust 所设计的 C、C++ 和系统领域的狭义情况下。
> 我最担心的是,反弹会像炒作一样(关于 Rust 最适合一切的说法)传播开来,突然之间 Rust 就成了无用之选。
我完全可以想象,在那些垃圾语言盛行的地方,它的受欢迎程度会下降,但是……难道你不认为它在那些需要 C/C++ 的地方(比如你提到的系统领域)会有前途吗?
要想让 Rust 在所有地方都失利,就必须让 C++ 战胜 Rust。不知道这是否可能。
垃圾回收并不是唯一的优势。
得益于和类型、枚举和 Rust 的其他特性,程序的直接正确性得到了大幅提高。
这些都需要一定的前期成本。在使用 Rust 多年之后,我认为这些成本往往被夸大了。它们对新手的影响更大(这本身就是个问题!),尤其是那些不关心学习如何习语化编写新语言的人。尽管如此,从零开始到完全投入使用,通常至少要慢一点。
不过,根据我的经验,Rust 程序所需的持续维护要少得多,而这正是软件开发中花费时间最多的地方。新功能的添加往往更加容易,而且类型系统可以完全避免各种类型的错误(不仅仅是内存安全问题)。即使是大型重构,通常也相对容易,而且一旦编译成功,很可能也能通过测试。
在某些情况下,每延迟一天上线都是灾难性的。但当情况并非如此时,由于无需追查运行时错误、nil 取消引用、未处理异常、新枚举变体和部分处理枚举变体引起的问题等,所节省的时间最终会十倍地收回前期成本。
前期成本确实会降低 Rust 在需求快速变化领域的竞争力。这是完全合理的,没有一种语言在所有方面都是完美的。但是,越是远离以销售为导向的用户,越是接近移动速度较慢的核心基础架构,降低的维护成本就越有回报。
在这方面,你将 Rust 与哪些语言进行比较?Swift?Kotlin?Go?
我认为下滑的程度会比人们预想的要深。回到非常小众的情况。事实上,Linux 和 Windows 正在使用越来越多的 Rust(尽管使用得很谨慎),我认为这将确保 Rust 在未来成为 C/C++ 的系统增强工具。
大型 C/C++ 领域还没有真正采用 Rust,而我希望他们在此之前会采用 Rust:汽车、航空航天、机器人、桌面、嵌入式。对于其中的一些领域来说,它非常适合,但他们正在与没有生态系统支持的现任者作战,因此这需要很长的时间。这不像重写 sudo 或 ls,你必须重写一切才能从 C RTOS 转向 Rust 嵌入式 HAL。
Rust 甚至还没有标准。C和C++(还有Ada!任何内存安全爱好者还记得Ada吗?
Ada 也有完整的正式指定语言、方法论和工具:SPARK https://www.adacore.com/about-spark
我一直在想,为什么 Ada 没有引起更多的兴趣。
人们没有用它来建造东西。你做得越多,它就越受欢迎。
我认识的目前用 Ada 制作东西的人比用 C 制作东西的人还多(从专业角度讲,因为我认识的几乎所有 Ada 开发人员都至少有一个 arduino)。
老实说,这与其说是语言的问题,不如说是我认识的人的问题。
是啊,不幸的是,全世界都超级喜欢 c 和 c++,以至于花费了数十亿美元通过 frama-c、astree 和朋友们来提高其安全性,而不是资助真正安全的语言。
语言的 ISO 标准并不是必要条件,Rust 在这些行业,尤其是汽车行业正在取得进展。
> 要想让 Rust 在所有领域都败下阵来,就必须让 C++ 战胜 Rust。不知道这是否可能。
或者一种新的类 C 语言,比如 Zig。
没错。Go 在当时也是如此。他们的营销听起来就像其他人都做错了垃圾回收,而他们的方法最适合所有用例和利基市场。
对
> 只要给我一个垃圾收集器,让我做我想做的事!
这句话完美地说明了作者根本不知道自己在说什么。
请作者注意:Rust 是专门为无法使用垃圾回收器的情况而设计的。
> 是最安全的
这似乎是一个严重的误解,基本上所有类型化的纯函数式语言都更安全:Haskell、SML、Ocaml 等。
没有垃圾回收器也很安全,这就是它的核心优势。
我认为,当人们说最安全时,他们指的是最安全的 “类似 C 语言 “的零成本抽象语言。
我对此不以为然。我认为,很多人都是通过 Rust 才发现 “内存安全 “这一概念的,并认为只有 Rust 才能提供内存安全。祖父母说得没错:Rust 以低成本实现了内存安全,这才是关键所在。
是啊,但作者从 typescript 转到 Rust……他们还能指望什么呢。
讽刺的是,typecript(以及 Javascript)具有完全的内存安全性。当他改用 rust 时,segfaults 的变化才会增加。
从昨天开始,各种 reddits 上都在热烈讨论这篇文章。
作者说
> 我想尝试用煽动性的文体来写这篇文章,以吸引读者。
但我还是想对一些说法做出回应,供好奇的人参考:
> 只要给我一个垃圾收集器,让我做我想做的事!
这绝对是一个合理的观点,但这意味着 Rust 并不是一个正确的选择。这并不意味着 Rust 是糟糕的。
> 也许我只是个白痴,不知道如何启用堆栈跟踪。但当我的程序出现错误时,我却不知道为什么!
Panics 有一个环境变量,可以设置为打印堆栈跟踪。您也可以使用 std::backtrace 中的工具自行获取堆栈跟踪,而且许多错误库(如 anyhow)也会让您获取回溯结果。不过,作者在这里感到痛苦的部分原因是,他们的示例代码没有直接使用错误对象,而是将其转换为字符串,然后以这种方式返回。这将使事情变得更难弄清,但这是因为你没有使用所提供的工具。
是的,但这种语言让人很难使用给出的工具。说这是技能问题很容易,说他们应该发现 RUST_BACKTRACE=1,但当你在学习语言并试图找出如何使用错误对象时,首先给出的工具不起作用,只是给我一个字符串,说我做了一个哑巴不应该这么难。
当遇到恐慌时,运行时输出会告诉您如何获取回溯:
的确,rustc 和 clippy 都没有抱怨有一个 `Result<_, String>` 返回类型。也许他们应该这样做。实现这样的提示并不难,但我希望人们会因此而烦恼。
我认为,在 18 个月内,我们有很多机会接触到任何解释这一点的文档和博文,或者在 https://users.rust-lang.org 上提问。
我希望我们的工具链尽可能简单易用,成为同类产品中的佼佼者。我有一长串希望在 Rust 中得到改进的地方。文章中的批评既没有建设性,也没有实质内容。
> 确实,rustc 和 clippy 都没有抱怨有一个 `Result<_, String>` 返回类型。
我很想知道原作者是从哪里得到这个不幸的想法的。我从未见过有人这么做,而且通过将错误信息转换为字符串,它非常明确地丢弃了所有额外的错误信息。难怪你搞不清楚错误从何而来!
如果让我猜一个完全陌生的人,他们似乎是一个 printf 调试器。不瞒你说,我也是。但是,”我处理错误的方法是将它们打印到屏幕上,而你将字符串打印到屏幕上,所以字符串作为错误条件是有意义的”,这并不是一个巨大的飞跃。
此外,他们似乎很喜欢 Go,而 Go 版本的 Rust Error 特质提供了一个返回字符串的方法 Error。虽然我没有写过有意义的 Go 语言,对它的习语也无从谈起(不过据我所知,”把它变成字符串就可以了 “并不是 Go 的习语),但这是另一个指向 “处理错误最简单的方法就是把它们变成字符串 “的信号,尤其是当你只是想发布一些东西而不关心细节的时候。
> 虽然据我所知,”将其转化为字符串 “并不是围棋的惯用语)。
遗憾的是,虽然我看到很多人争辩说这不是成语围棋,但我还没见过有几个项目不是简单地 “return nil, err”,因为任何给定项目中这样的行数多到令人难以忍受。
我无法引用我的资料来源,但我最近开始学习 Rust,并一直在做这件事。我猜我是从 Rust 书中学习的,因为那是我学习的主要来源。
我知道我_可以_定义自己的错误类型,但这很乏味,尤其是在有许多错误类型需要处理的情况下。对我(非生产)来说,这很好。
处理错误的惯用方法是什么?是否有办法在不使用过多模板的情况下收集更详细的错误信息?
常见的建议是 “在应用程序中使用 anyhow,在库中使用 thiserror”,但实际上,anyhow 适合处理错误,而 thiserror 适合定义自己的错误类型。
文档中有很好的基本用法示例: https://docs.rs/anyhow/latest/anyhow/
我就直说了吧,Rust 社区并不是一个让人感到温暖的地方,你可以在这里问一些愚蠢的问题,然后走的时候不觉得自己是个傻逼。寄希望于人们会到正确的地方去问 Rust 问题是不切实际的。
你无法控制 Stack Overflow 或 Reddit,也无法控制任意数量的 slack/discords,所以我不知道该如何解决这个问题,但这确实是事实。
> 希望人们在正确的地方提出rust的问题是不可能的。
https://users.rust-lang.org 由该项目主持。https://www.rust-lang.org/ 的页脚链接了该论坛,而 https://www.rust-lang.org/community 的链接更为显眼。搜索 “rust 论坛”,首先出现的就是它。
Reddit 也有版主,但整个网站的文化问题以及 StackOverflow 的文化问题现在已众所周知。
只要有可能,我都会尽力定下基调,以身作则。在我看到的大多数情况下,线程变坏通常是由于人们不愿意倾听,一开始就表现得很激烈。我曾在 r/rust 讨论中看到,所讨论的文章对语言/工具链的批评远比这篇要严厉得多,但交流风格和实质性分析却更有建设性。这种情况下的对话质量要好得多。
请随时向我指出有毒的社区行为,我会尽我所能通过一切可用的方式来解决这些问题。我不能保证会有翻天覆地的变化,但我一定会尽我所能指出不良行为,并努力营造一个让我引以为豪的空间。话又说回来,我在你提到的任何一个网站上花费的时间都不多,所以我很容易错过不良行为。
我还想说的是,即使你不想与人交流(无论出于什么原因),这也不能成为你不寻找官方或非官方文档的借口。https://www.rust-lang.org/learn 上有一个不全面的列表。
OP 有可用的资源来学习如何以比他更习惯的方式处理错误:
– https://doc.rust-lang.org/book/ch09-02-recoverable-errors-wi…
– https://doc.rust-lang.org/rust-by-example/error/multiple_err…
– https://doc.rust-lang.org/rust-by-example/error/multiple_err…
真的吗?我感觉 Rust 社区对新手比一般人更友好。并不是说平均水平很高,但还是有的。
在本例中,”RUST_BACKTRACE “在本书第 9 章中有所描述:
https://doc.rust-lang.org/book/ch09-01-unrecoverable-errors-…
我认为这具有很好的可发现性。如果您要学习这门语言,并用它来编写算法交易平台,那么《书》可能应该是您查阅的第一份文档。
我同意只说 “技能问题 “不是最好的办法,但同样,寻求帮助而不是写一篇博文说 “这是一个有缺陷的语言设计 “也是完全可以的。
我同意你的看法,作者应该为此付出代价。使用调试器可以解决这个问题,但有时调试器无法使用,而且以正确的方式传递 Result<Option <String>,Box<dyn Error>>(结果<选项<字符串>,方框<dyn 错误>>)或其他东西来处理错误是非常困难的。我最终还是想通了,但与 Python 相比,学习曲线还是很陡峭的。有些人可以胜任,有些人则不行。我个人认为这没什么,并不是所有东西都必须像 Python 一样简单。把关并不一定是坏事。现实的尴尬在于,并不是每个人都有那种推理能力来真正理解它,而因为他们不懂或无法理解它而把他们拒之门外并不一定是坏事。不过,当有人对此抱怨时,我们也不应该感到惊讶。
我确实认为 “项目不挑选优胜者 “的一个不幸的副作用是,让新人知道 “无论如何 “的存在肯定会有所帮助。这可以让最初的步骤变得更容易。
我用 Python 构建了一个算法交易平台,并使用 Cython 加速热点。无怨无悔。
不是 pypy?
我对生命周期注解很好奇。这基本上是语言设计者的意图,即 “在该数据字段上放置一个标记,以便编译器可以跟踪该字段的使用情况,确保在内存释放之前或之后不会访问该字段”。
因此,生命周期是通过额外的抽象表达的,需要相关的语言语法、编译器设计、额外的规则集等。
为什么同样的概念不能表达为自己的数据类型,然后作为数据传递呢?在这种情况下,你就去掉了额外的抽象。看来 Jai 正在走这条路,即传递一个竞技场类型实例并与之交互。
数据是在运行时产生的,而类型(也就是生命周期)是在编译时产生的。
你可以去掉一个抽象概念,但也会失去效率。
我认为这里遗漏了一个可能相关的项目。它谈到了 Rust 的快速性。Rust 的编译速度可能相当慢。如果开发速度与此有关,那么 Rust 的 “快 “可能还不如编译速度快。当然,有些人不惜一切代价追求速度(并为此花费 18 个月重写代码)。Rust 可能很适合这种情况。
我不明白为什么要花这么长时间才能得出这些结论。如果它们对你造成困扰,每一个都会很快给你一记响亮的耳光,所以在决定它们是否值得一试之前投入这么多时间是很奇怪的。
> 如果与 C++ 相比,显然它是更好的语言。
这取决于 “更好 “的含义是什么。我喜欢 C++ 的地方在于它的问题是众所周知的,如何解决这些问题也是众所周知的。而 Rust 让我担心的是,在实践中我们并不了解它的所有问题。当然,我们最终会知道的。
有时候,我觉得我们没有足够重视我们在一种语言上的集体经验有多重要。
我们意识到了 C++ 的问题,但如何解决其中的许多问题仍是一个悬而未决的难题(直到我们发现或发明出完美的人类)。
我们并不是没有解决方法,我们只是没有普遍接受和认同的解决方法。你有选择。例如,在 C++ 中就没有公认的手动内存管理解决方案。你可以开发自己的策略,但你可能无法在不创建垫片(或 monads)的情况下使用开箱即用的库,但问题是:我们知道如何做这些事情。生产中的大部分代码都已经完成了这些工作,很少有人有兴趣将这笔巨额投资重构为 Rust 代码。
我讨厌 Rust,但我认为这篇文章有失公允,因为作者搞错了预期。
我的意思是,他把 rust 与 pythons 和 typescript 相提并论?
> 只要给我一个垃圾回收器,让我做我想做的事!
是的–这清楚地表明您还没有找到安全、保障和底层控制与开发人员速度之间的最佳应用。系统、安全关键型、嵌入式等。
除了炒作和陷入分布式系统开发的空白之外,我不清楚它为什么会扩展到这一领域,而围棋出于某种原因从未填补过这一空白。
关于 Rust 社区不友好的评论(好吧,用词比这更严厉)可能是 Reddit 子站特有的。
如果有一个友好的 Rust 社区,请提供链接,否则我们只能认为它不存在。
编辑:坎宁安法则:)
https://users.rust-lang.org
https://internals.rust-lang.org
https://rust-lang.zulipchat.com
我以前用 C++ 编程,主要是做高性能方面的工作。和其他用过一段时间 C++ 的人一样,我对这种语言也有意见。以下是我不喜欢它的原因:
1.编译时间。从点击 “编译 “到得到关于你犯了什么错误的反馈,这之间的时间从 <10 秒到 >30 秒,用户体验差别很大。
超过 15-20 秒,我就会把注意力转移到其他事情上。这意味着当我读到错误信息时,我必须将上下文切换回任务。根据我的经验,快速构建(说实话,Go、D 甚至 Python)带来的生产力提升是巨大的。
2.语法不好。很少有少于 70-90 个字符的有意义的代码行。你的眼睛会横着看,也会竖着看。因为是模板或语言的特殊性,你需要花费大量的时间去了解哪些内容可以跳过不读。
3.构建 C++ 是个无稽之谈,每个人都有自己不同的解决方案,因此在项目中引入非头文件的外部库简直就是地狱。而只有头文件的库会让问题 1 变得更糟。
C++ 不安全不是我的问题。Rust 专注于解决不安全问题,但 Rust 很少关注问题 1 和问题 2。他们确实解决了第 3 个问题,他们有一个包管理器,这很好,但其他语言也都这么做了,所以这对我来说并不是什么竞争优势。
我严重怀疑,如果大多数人列出他们对语言的优先级,他们是否会与 Rust 保持一致。实际上,很少有人在编写可能会暴露危险内存错误的 Linux 内核代码或核心系统库。
关于 #1,在编写 Rust 时,可以考虑使用 cargo check 而不是 cargo build。它能在代码生成前的几个阶段停止,因此能更快地给你反馈。它对运行测试没有帮助,但会加快代码编译的周期。
我认为,如果能有一个资源,针对不同的用例,以平衡的方式对不同的编程语言进行这样的评估,将会非常有用。
我能想到的唯一类似的东西就是 “你的编程语言糟透了 “的主题,这更像是一种幽默的夸张。
作者显示为不可读的示例对我来说完全可读。
一样,然后他们又提供了一个 Go 的例子,……基本相同?然后他们抱怨 Rust 不提供错误的堆栈信息,但与此同时,Go 的等价实例只是在所有地方都 “return nil, err”,也丢弃了堆栈跟踪。
他们正确地指出,在 Go 中你可以用 `errors.Wrap(…)` 封装错误。但在 Rust 中,你也可以使用 `std::backtrace`、`failure` 或 `anyhow` crate 做同样的事情。
是啊,我觉得他只是来自一个完全不同的操作领域。我甚至无法想象从 Typescript 到 C/C++/Rust 的转变。我甚至对 OP 能做到这一步感到佩服……
在无穷无尽的构建器模式和 let if/match 语法之间,相对于 C 或其他语言,它确实变得相当宽泛和丑陋。但它绝对有它的优点。