rust编程
这篇文章是关于我通过解决Twitch上尚未解决的所有CtCI问题来学习Rust的经验。
Rust是一种现代系统级编程 语言 ,在设计时考虑了安全性。 它提供了零成本的抽象,泛型,功能特性以及更多其他功能。 我最近开始努力正确地学习Rust,我想分享一些想法。
直到最近,我只在Rust中编写了一些小程序,在阅读了“ Programming Rust”的一半内容之后,我真的不了解 Rust。 我认为了解该语言的一种好方法是解决“破解编码面试”一书中的所有189个问题 。 我不仅会用Rust来解决问题,而且决定在Twitch上进行开发 。 在技术讲座或在观众面前编码的过程中,我并不陌生,但是尝试学习一种编程语言,并解释自己的所作所为-对世界来说是真实的-对我来说是新事物。
事情开始有些粗糙:技术问题,流问题,工具问题,而且我一开始就很难理解内存范例。 试图做到这一点,同时还向人们解释我在做什么,这很棘手 。
我花了大约8个小时来实现一个链表:我记录了两个4个小时的自我流,试图弄清楚如何正确使用Rc,RefCell和Box。 有一段时间,我觉得我只是在敲击键盘尝试随机组合,直到卡住了。 令人惊奇的是,人们收看了。 我一定做对了。
在脱机阅读了一些之后(并阅读了非常有帮助的“ 使用太多的链表来学习Rust ”),这些概念开始为我所用。 完成链接列表的实现后,事情变得简单了。
我现在已经进入本书的第4章,觉得自己已经取得了长足的进步。 编译后,Rust感觉自然,高效并且令人非常满意。 Rust是强类型的,并提供出色的编译器消息:如果您设法安抚了编译器,那么您的代码很有可能会工作-除非存在任何逻辑缺陷。
Rust的一个可爱的功能是编译器有多有用。 例如,众所周知,C ++代码的编译器消息很难解密。 尽管Clang的错误消息已取得了长足的进步,但Rust的编译器的帮助又高了一个数量级。
到目前为止,我将总结一些发现。 这是基于我最初的React,我承认我缺乏Rust的专业知识,但是对于其他人来说,看看他们的经验与我的经验相比可能仍然很有趣。 我很遗憾地承认,我没有对下面的每个问题进行彻底的研究,因此我的信息可能过时或不准确。
语言:善良
首先,对Rust团队以及为该项目做出贡献的每个人都表示敬意。 这是我有过的最有趣的编程语言学习经历之一。 我不知道Rust是否会像其他语言一样吸引开发人员的注意力,但是我认为它会持续存在。 详细介绍:
- Rust代码非常易于阅读,并且不会因为难以解析C ++或Scala等语言的语法而受苦。 它似乎具有我期望的功能,而挑战仅在于确定要调用的函数。
- 具有诸如
map()
, filter()
, find()
类的功能特性很令人高兴。 定义高阶函数并将闭包传递给它们很容易。 它并没有使函数式编程像Ruby这样的语言那么容易,但是很接近。 实际上,令人惊讶的是,与C / C ++相比,这种语言的性能是如此轻松。 - Rust迫使您必须认真考虑内存分配,因为您别无选择。 最后,这意味着草率的代码难以编写,而好的代码则易于编写。 这些抽象也直接映射为编写安全的并发代码。
- Rust的零成本抽象使编写良好的代码变得容易而又不增加开销。 特性可以提供现代的编程抽象,而不会降低性能。
- Rust代码是安全的(前提是您不使用
unsafe
关键字,或调出不安全的C库) - Rust的
Result
和Option
提供了一种处理可能返回值的函数或可能包含值的变量的好方法。 在C,C ++甚至Java中,一种常见的模式是函数在没有任何返回值的情况下返回空指针。 在大多数情况下,当这种情况意外发生时,会导致某人的时间不好。
语言:不好
- 我发现
as_ref()
需要as_ref()
unwrap()
, as_ref()
和borrow()
有点冗长。 我希望可以使用一些语法糖来减少必须以不同方式将这些调用链接在一起的次数。 我发现自己经常编写类似于option.as_ref().unwrap().borrow()
代码,感觉很讨厌。 - 为了能够在合理的时间内编译代码,需要对编译器进行一定的权衡。 结果,在某些情况下,
rustc
无法推断类型,或者需要一些人工帮助才能编译代码。 对我来说,我发现有时很难弄清编译器需要什么,以及为什么它对我来说不容易解决。 - 有些事情有时会觉得太冗长。 例如,在
str
和String
之间进行转换,或者将引用而不是值传递给函数,似乎编译器可以为我解决。 我敢肯定有一个很好的理由说明为什么它是如此,但是有时感觉rustc
太正确了 。 - 必须处理每个函数的每个
Result
都是好的; 这意味着程序员必须考虑每个函数调用的情况。 有时会感到乏味。 ?
操作员可以减少一些冗长的细节,但是没有很好的概括方法来处理故障类型。 诸如故障和错误链之类的条板箱使此操作变得容易,但是您仍然需要为可能发生的每种错误类型明确定义一个案例。
语言:丑陋
- 巨集:WTF? 与其他语言相比,Rust宏感觉像是向左拐。 公平地讲,我还无法理解它们,但是它们感觉就像是一些奇怪的螺栓附件,这种附件只是在Perl的启发下设计出来的。 我最终会花一些时间来将来正确地理解它们,但是现在我想避免它们。 像瘟疫。
工具:好
- Rust提供了不错的工具,并通过RLS与VSCode等IDE集成。 RLS提供了lint,代码完成,语法检查和即时格式化的支持。
- Cargo是Rust强大的包裹管理器:如果您尝试Rust,您可能会熟悉它。 在大多数情况下,与Cargo合作是一种乐趣。 已经有大量用于Cargo的插件,可提供其他功能,例如代码覆盖率 。
- Cargo还是一个构建系统,可用于运行单元和集成测试。 通过某种程度的声明性TOML语法,可以轻松配置构建和依赖项。
- Cargo与crates.io集成, crates.io是开源Rust项目的权威资源。 就像PyPi或RubyGems一样,您会在crates.io上找到几乎所有其他Rust软件包。
- rustup是用于管理Rust安装的首选工具。 您可以选择稳定,测试版或夜间频道,并安装所有以前版本中的特定内部版本。 它还可以让您安装clippy和rustfmt等组件
- 如果您是像我这样的完美主义者,那么clippy是必不可少的代码专家。 它将帮助您学习Rust的方式,并且可以捕获许多您可能不会注意到的常见错误。 对我来说,当我知道解决问题的方法时,clippy会有所帮助,但我不知道正确的方法 。
- rustfmt是Rust的自以为是的代码格式化程序。 我认为,自以为是的格式化程序是可行的方法。 当所有内容都遵循相同的标准时,就无需争论代码格式。
- sccache是编译器缓存,它将通过减少编译时间来加快处理速度。 但是,请注意,sccache不适用于RLS,因此您不能在IDE中使用它。
工具:不好
好的,好的,在继续讨论Rust的问题之前,我们都应该承认这是一项正在进行的工作。 Rust工具的发展非常Swift,但是我认为它还有很长的路要走。 我将重点介绍一些需要改进的地方:
- 编译感觉很慢。 它不仅速度慢,而且我发现我经常不得不重新编译软件包。 我了解必要性,但有时仍然很烦人。 sccache有帮助,但仍然感觉很慢。 有一些方法可以减轻这种情况,例如使用
cargo check
代替cargo build
。 - RLS使用racer来完成代码,我发现它充其量只能是命中注定的(至少是在VSCode中)。 通常,我希望为其完成的功能不存在,而不存在的功能会显示为完成选项。 我尚未进行详尽的分析,但是这些建议似乎只有大约75%的时间是正确的。 其原因可能仅仅是由于RLS的速度较慢。
- 没有REPL:这可能是不公平的,因为也没有不错的C ++ REPL,但是如今,REPL附带了许多语言。 GitHub上有一个关于此的公开问题 。 良好的REPL不是必需的,但会有所帮助。
工具:丑陋
- RLS速度慢,越野车和崩溃。 至少对我来说,我发现我经常需要在VSCode中重新启动RLS。 RLS是一个很棒的工具,但它的确充其量是Beta版。 我发现自己不得不暂停并等待RLS赶上来,这样我才能确保自己不会编写错误的代码。 有时候,我认为最好禁用RLS,编写代码,然后像在旧时代那样在Vim中进行所有编码一样尝试对其进行编译。 就像RLS变得太多了拐杖,更多的是分心。
图书馆:好
- Rust生态系统中大量可用的库令人惊讶。 似乎有一种淘金热来耗尽并实现所有Rust库,并使您的名字在Rust历史上永垂不朽。 您可以在crates.io或GitHub上找到大部分期望的内容。 每次搜索都会为我要找的东西提供2或3种不同的实现方式时,我常常会感到惊讶。
- 我使用的大多数库都按预期工作,其中许多超出了预期。 这与替代方法(不能使用的库)有一个细微而重要的区别。
图书馆:坏人
- 尽管有很多库,但我发现它们中有很多是不完整,不成熟或完全废弃的。 Rust社区似乎仍处于起步阶段,但它每天都在进步。
- 有时候,…… 选择太多了 。 例如,我想使用一个日志记录库,我发现有一长串可供选择的选项 。 有很多选择是可以的,但是对于这样的事情,我只想被告知要使用什么。 Java生态系统在java.util.logging,log4j,logback,log4j2,slf4j和tinylog中也存在类似的问题。 到目前为止,我仍然不知道哪个Java日志记录库是最适合使用的。 对于Rust,我只是决定使用
env_logger
因为它是列表中的第一个选项。 - 尽管不如Node.js生态系统那么糟糕,但每个库的依赖项列表已经相当长。 我写了一个名为LabHub的GitHub小型机器人 ,但我仍然为引入了多少依赖项感到惊讶(181条装箱,如果您想知道的话)。 对我来说,这意味着碎片化和重复,可以通过将一些广泛需要的功能缓慢地移植到标准库中来改进(C ++做得很慢)。
图书馆:丑陋
- 我注意到,除了一个相对简单的应用程序的大量依赖关系之外,我还多次编译同一库的不同版本。 我认为Cargo为了保持向后兼容性而试图变得更聪明。 它正在根据语义版本来猜测要包括哪些库。 让我担心的是,当您拥有一个依赖于某个古老的,破碎的版本的图书馆而该图书馆也存在漏洞时,会发生什么。 毫无疑问,Rust的作者已经考虑过这一点,但是看起来还是很奇怪。 公平地说,处理依赖项的依赖项是一个非常棘手的问题。 值得庆幸的是,有一个适用于Cargo的树形工具 ,可以帮助您解决这些问题,然后您可以强制依赖项升级其依赖项。
最后的想法
Rust是一门很棒的语言。 如果您热衷于编程,请尝试一下。 我希望你喜欢它。
关于我:我从12岁起就一直在编写代码,为许多不同的开源项目做出了贡献,并在Airbnb,Mesosphere和Citadel等多家公司工作。 在 github.com/brndnmtthws的 GitHub上找到我 ,在 twitch.tv/brndnmtthws的 Twitch 上找到我 ,或在 twitter.com/brndnmtthws的 Twitter上 找到我 。
翻译自: https://hackernoon.com/programming-in-rust-the-good-the-bad-the-ugly-d06f8d8b7738
rust编程