努谢尔的一年

2020-08-26 13:18:57

很难想象,Nu第一次上市已经一年了。当时,它在很大程度上是一种可能的演示,但仍需要做相当多的工作才能使其准备好用于日常使用。一年过去了,我们学到了很多,也犯了一些错误。在这篇文章中,我们回顾过去的一年,看看我们做得如何,以及我们未来可能会走向何方。

当Nu第一次启动时,它从一个简单的想法开始:ls、ps和sysinfo的输出应该都输出相同的内容。以PowerShell中的一页为例,我们探索了结构化数据的输出,并很快确定了一个表格设计,该表格设计将支持三个命令中的每一个命令的输出,并增加了在输出可用时流式传输输出的功能。

围绕这一想法,我们随后构建了一组“过滤器”,比如借用自SQL的WHERE子句,以及一组不断增长的我们本机支持的数据类型。很快,我们就能够编写更复杂的语句,比如ls|where size>;10kb。这就成了这个想法的核心-将一组核心数据类型的值输出到一个流中的命令,与传统的UNIX管道(|)一起组成,这样您就可以构建一组复杂的命令,在数据流经时对其进行处理。

在我们今天开始谈论Nushell之前,我们想给大家一个大大的“谢谢!”感谢每一位对NU做出贡献的人,让我们走到这一步。因为你的帮助,NU才是今天的样子。

1ntEgr8,AaronC81,AdminXVII,aeosynth,aeshirey,aidanharris,almindor,Aloso,Amanita-muscaria,amousa11,andrasio,Andrew-Webb,arashout,arnaldo2792,avandesa,avranju,bailey-layzer,BatmanAoD,bndbsh,Bocom,boisgera,Borimino,BradyBromley,BurNiinTRee,Byron,candostdagdeviren,casidiablo,charlespierce,chhetripradeep,cjpearce,coolshaurya,cristicismas,DangerFunPants,daschl,daveremy,davidrobertmason,Delapouite,dependabot[bot],Detegr,devnought,Dimagog,djc,drmason13,DrSensor,elichai,eltonlaw,EmNudge,eoinkelly,equal-l2,est31,fdncred,filalex77,Flare576,gilesv,gorogoroumaru,GuillaumeGomez,hdhoang,he4d,hilias,HiranmayaGundu,Hirschenberger,homburg,iamcodemaker,incrop,ineol,Jacobious52,jankoprowski,jCavallo,jdvr,jerodsanto,jesterornot,johnae,johnterickson,jonathandturner,jonny walker81,jonstodle,JosephTlyons,jzaefferer,k-brk,kelli314,clnusbaum,klun。Piotrek-szczygiel,piczafox,pka,pmeredit,pontaoski,Porges,Pulpdraw,q-b,quebin 31,rabisg0,ramonsnir,rimathia,ritobanrc,rnxpyke,romlevin,routrohan,rrichardson,rtlechow,rutrum,ryuichi1208,samball 218,samhedin,sandorex,sdfnz,sedfnz。

Nushell是一种交互式编程语言,用于以shell、笔记本等形式处理文件、系统和数据。

很容易把努谢尔想成一个空壳。它的名字里甚至还有“壳”。这可能是你与之互动的第一种也是最主要的方式。那么为什么说它“不仅仅是一个贝壳”呢?

事实上,努谢尔实际上同时是两样东西:努谢尔和努谢尔。NU是一种交互式语言,用于处理结构化数据流,这些数据流可能来自文件、系统、网址等。

Nushell正在将Nu语言放入shell中,并围绕它构建一组shell特性,使其能够舒适地用作登录shell。完成、严重的错误消息等等。

当我们说“Nu不仅仅是一个贝壳”时,这是否意味着Nu也可以在其他地方使用呢?绝对一点儿没错。我们还有两个允许您运行Nu的主机,一个是基于jupyter的主机,允许您在jupyter笔记本电脑上运行Nu,另一个是基于WebAssembly的主机,我们使用它来创建Nu游乐场。

Nu的想法不仅仅是外壳,它是一种相对容易学习的语言,但功能强大,足以与您的系统进行真正的工作,处理大量数据,交互地让您快速迭代一个想法,通过一次一段地建立管道来吸引探索。对于我们希望去的地方,确实不乏雄心壮志。

到目前为止,NU的原始设计被证明是出人意料的健壮。它的一些核心想法在一年后继续带来红利。让我们来看看那些感觉仍然正确的设计。

当我们第一次开始编写Nu时,我们选择了几条捷径,使我们可以一次处理管道中的所有数据。很快,我们意识到这是行不通的。外部命令(比如cat/dev/Random)可以输出无限数据流,系统需要能够处理它。理解了这一点,我们过渡到一个不同的模型:命令之间的数据流就像无限的结构化数据流。在处理数据时,我们尽可能避免收集数据,以允许发生这种流。

因为流可以是无限的,所以即使是表的打印也是一次批量完成。

来自其他shell的想法是,运行echo或ls的想法与向终端打印一些东西是齐头并进的。很难看出有两个步骤在幕后进行:创建信息,然后将其显示在屏幕上。

在怒族,这两个步骤是截然不同的。ECHO命令使数据准备好输出到流中,但不执行任何将其打印到屏幕上的工作。同样,ls准备输出文件和目录条目流,但实际上并不显示此信息。

这是因为echo和ls都是惰性命令。只有当数据从流中拉出时,他们才会做这项工作。因此,查看数据的步骤与创建数据的步骤是分开的。

在幕后,Nu将独立的ls转换为管道ls|autoview。查看工作来自Autoview,它处理数据并调用适当的查看器。通过这种方式,我们能够尽可能长时间地将内容作为结构化数据保存,并且仅将其转换为在显示给用户之前作为最后一步显示。(注意:基于wasm的demo和jupyter执行类似的步骤,但它们不是添加autoview,而是添加到html)。

与处理结构化数据(而不仅仅是纯文本)的方式类似,Nu对数据类型也采取了不同的方法。NU采用传统的基本类型集,如字符串和数字,并将它们扩展为更丰富的基本数据原语集。

数字在内部表示为大数字和大小数,而不是整数和基于浮点机的表示。这为我们提供了更大的灵活性,使我们可以更精确地进行数学计算,并且通常不会担心您要处理的数字是否适合您现有的整数或浮点数大小。

我们还通过表示现代计算机使用中常见的值来进一步说明这一点:URL、文件路径、文件大小、持续时间和日期都是内置数据类型的示例。通过内置它们,NU可以在使用它们时进行更好的语法和类型检查。

例如,在Nu中,可以写=1分钟+1秒来创建1分1秒长的持续时间。您还可以使用文件大小,比如能够根据文件ls|的大小过滤目录列表,其中>;10kb。

如果您尝试混合不应该的类型,NU也可以提供帮助。例如,如果您编写了:=1min+1kb,您似乎不是有意将时间和文件大小加在一起,如果您这样做,Nu会给您一个错误:

错误:强制错误┌─外壳:1:3│1│=1min+1KB│^-文件大小(字节)│││持续时间

Nu中的数据也不仅仅是值,它还是值附带的一组元数据。例如,如果您使用OPEN命令从文件加载数据,我们将跟踪它与加载的数据一起加载的位置。我们可以使用TAG命令查看此元数据:

Open Package.json|tags───┬─┬────#│SPAN│锚───┼───。─┼────0/home/jonathan/Source/servo/tests/wpt/web-platform[│[│End Start]行结束开始]。-───┴─┴────/webrtc/Tools/Packag││e.json测试。

这些额外的信息让我们知道如何查看内容,甚至可以在使用save命令时节省您的时间,因为默认情况下它将使用原始位置。

我们很早就认为NU应该是有趣的。它应该是有趣的工作,它应该是有趣的贡献,它应该是有趣的使用。

NU实际上是关于玩耍的。你玩弄你的数据,你玩弄构成你的文件和文件系统的结构,你玩弄Web服务返回给你的东西。关于NU的一切都是为了邀请您探索事物是如何工作的,以及数据是如何组合在一起的。当你玩的时候,你会学到更多关于Nu作品的知识,以及如何更好地使用它。我们坚信学习不会有什么坏处。在最好的情况下,随着时间的推移,探索的乐趣会产生专业知识,而不会在一路上惩罚你。当我们喜欢日复一日地拿起某件东西,边走边试验时,人类就会变得更好。有了Nu,我们可以问这样的问题:“如果我这样做怎么办?”因为这个系统是为了让我们自己问问题和回答问题而建立的。

NU将这一步更进一步。错误报告系统来自于Rust错误消息的设计,具有清晰的消息来帮助您引导您走向成功。

Nu的目标是它不需要您成为命令行或复杂编程实践的高手。取而代之的是,你从你觉得舒服的地方开始,一次发展一条线。使用Nu,随着您舒适度的增加,单行很容易增长到多行,并(最终)增长到更大的程序。您不需要在实验时使用不同的思维方式,而在构建应用程序时需要另一种思维方式。在怒族,这些都是(或将会是)相同的。

我们在制作Nu时做出的第一个决定之一是,它不仅应该是跨平台的,而且应该尽可能地感觉到跨平台的原生性。无论您使用的是哪种平台,命令的工作方式都应该相同,如果您从一个操作系统切换到另一个操作系统,则不会丢失任何功能。这意味着当有人提供一个很酷的功能时,会说几次“不”,结果发现它在一个受支持的系统上不能很好地工作。不过,好处是Nu用户可以在不同操作系统之间轻松移动。

NU还允许您使用常用快捷键。在Windows中,您可以使用通用的D:速记来更换驱动器。您也可以使用cd~和cd-作为简单的缩写在主目录和以前的目录之间跳转。

早些时候,当我们第一次集思广益地讨论像Nushell这样的东西如何工作时,我们重新发现了迭代有自己的特殊变量的想法。迭代变量、Item变量或简单的“it”变量为我们提供了一种谈论流经管道的当前数据行的方法。当我们可以讨论当前行时,就更容易说出如何处理当前行了。

回显$,它实际上并没有做任何有趣的事情,它只是传递传递给它的值。当我们将其与变量路径相结合时,事情就变得更有趣了:

现在,我们已经用4个字要求Nu列出当前目录中的所有文件,并且只输出名称。如果有上百个数以千计的文件,这条管道在找到新文件时会很高兴地流出它的结果。如本例所示:

一旦您有了使用$it的心理模型,在一次处理一行数据时获取它就变得很常见了。

对于那些想知道这是如何在幕后工作的人,请注意:如果发现$it是参数的一部分,而不是在块中,那么它就是“it展开的”。我们将该命令替换为对每个和块的调用。

Each命令负责遍历每行并每次调用块,将变量$it设置为当前行值。

在Nu中,命令的形式为<;cmd>;<;arg1>;<;arg2>;。对于你们当中的口齿不清爱好者来说,这应该看起来很眼熟。再加上一对花括号,你就有了一个s-表达式。

您可能想知道-如果选择cmd-arg-arg表单,如何编写如下内容:

这就是Nu的解析器的用武之地。我们使用的解析器是类型驱动的递归下降解析器。如果您查看Rust代码中WHERE命令的签名,您会看到它是这样写的:

也就是说,WHERE命令接受单个参数(条件),该参数的语法形状为Math。此形状驱动解析器使用不同的解析器逻辑。

在数学模式下,我们现在可以使用运算符优先来解析表达式。WHERE命令告诉解析器将所有自由参数视为单个表达式,解析该表达式,并将其作为单个参数传递。规范形式更精确,虽然有点繁琐:

您还可以看到一些其他步骤,比如使用$it将快捷路径扩展到完整的变量路径。

能够在命令的名称中使用,有时称为“烤肉串案例”,这是一个方便的功能,也是我们喜欢的功能。在Nu中,无论何时需要传递标识符,都可以使用它。烤肉串-案例-规则。

除了烤肉盒,你还可以用吗?作为标识符的一部分,允许您使用Ruby样式的名称。我们在命令EMPTY?中使用它。

Nushell目前拥有略多于55k行的代码,由近1300个合并的Pull请求构建而成。

有趣的是,当您开始处理shell时,很容易想到“它会像REPL一样”。事实上,它更接近于为终端创建交互式IDE。当人们从其他shell(包括像鱼这样的shell)来到Nu时,有一个很强的假设,即完成工作将非常出色,它将与现有的工作流很好地集成,并且它将支持配置提示符、键绑定等。

事实也证明,让一个外壳正确需要更多的实验,而遵循教科书上的话要少得多。在实践中,像‘stdout’和‘stderr’这样的东西有多种用法,程序输出的退出代码也是如此。我们最初的设计开始于对这些想法的更严格的看法,随着时间的推移,随着时间的推移,我们发现现实世界比我们意识到的要模糊得多,所以我们的设计变得软化了。

NU并不是没有几个怪癖。就像任何令人尴尬的突飞猛进的增长一样,我们也经历了尴尬的时期,但仍有一些“好奇”的领域。

如果你有一台时光机,一年前告诉我们,我们今天仍然不会有变数,我们可能不会相信你。这不是一门语言的重要组成部分吗?

是的,这绝对很重要。但我们也很惊讶,没有它们你能走多远。当你思考如何处理一段数据时,你可能会把它拆分开来,也许你会越过线条,或者你会在其中进行搜索。它们中的每一个都有在Nu中执行任务的内置方式,并且都不需要用户定义的变量。

当然,这也有其局限性。在某些情况下,您希望获取一批命令的结果,并将其存储起来以备以后使用。我们正在考虑如何做到这一点,归根结底是几个基本问题:

变量应该以传统方式工作吗?也就是说,我们是否应该充分评估在赋值期间传递给变量的内容?

或者,Nu是否应该“保留”您在赋值期间使用的管道,这样您就可以在需要变量的值的时候运行它(如果可能的话,可能会缓存结果)?这不那么传统,但更符合一种懒惰地处理可能无穷无尽的数据流的语言。

我们还需要回答其他问题,比如变量和函数定义是如何协同工作的?变量如何相互隐藏(或者即使它们是允许的)?

Nushell是一种专注于处理结构化数据的语言,在如何以及何时查看数据方面有一些怪癖。首先,Nushell有多种类型的数据,不同类型的数据可能有不同的查看需求。为了帮助实现这一点,我们创建了autoview,这是一个可以查看数据并检测各种不同情况的命令。一旦确定了数据的形状,它就会调用处理查看该特定类型数据的查看命令。

自动查看适用于直接输出给用户的任何数据,管道的最后一步就是这种情况。例如,管道ls实际上是后台的ls|autoview。Ls命令输出与目录中的文件相对应的每行数据,从而创建一个表。这些行被传递给Autoview,它检测到我们需要查看一个表,调用table命令,然后它查看数据。这通常感觉很自然,嗯,大多数时候。

Ls|where size>;10kb不输出在两个命令之间流动的数据是有道理的。如果我们这么做了,我们就不清楚实际的答案是什么了。但在这种情况下怎么办:LS;Echo&34;Done&34;?我们是否输出ls的结果?

在当前版本的Nu中,我们不这样做。我们把左边的任何东西都当作“做这件事,完成它,但不要运行‘autoview’”。这让您可以进行一系列不同类型的处理,然后才能查看最终结果。

这似乎是合理的,直到您看到类似ECHO&34;hello&34;;ECHO&34;world的内容,并且只看到输出“world”,然后必须停下来仔细考虑导致该输出的所有步骤。

事实证明,航站楼很小。想看几个专栏吗?一般来说不成问题。想要从工作中打开具有30列的随机CSV文件吗?现在我们可能有麻烦了。当您使用绘制精美表格在终端中打印出30列文件时,它实际看起来是什么样子?

在某些情况下,我们发现旋转桌子会有所帮助,这样列就可以沿侧面而不是顶部移动。当只有一行数据时,这特别方便,因为它读起来更像是一条记录。

话虽如此,但这并不是没有权衡。对于一些人来说,在他们意想不到的时候旋转桌子可能会让他们非常迷失方向。我们仍在努力找出最佳的默认值和启发式方法。

Nushell正处于这个项目的阶段,我们仍在试验这种语言应该是什么,它在实践中是如何工作的,并找出它最重要的核心价值是什么。努谢尔所用的语言“铁锈”也经历了类似的阶段。当它发现自己最重要的价值时,它就试着去尝试其他人。一旦人们开始用Rust创建真正的项目,并展示了使用该语言的这个核心部分可以实现的功能,设计就开始凝聚,然后在1.0版本中得到巩固。作为其中的一部分,早期的想法被修改或完全抛弃。

努谢尔将经历类似的阶段。随着它的成长,它会找到它的甜蜜点,这是它自然填充的利基。设计将来自为解决实际问题而构建的功能,我们将完善这些功能,改进它们的实用性、错误消息、文档和整体流程。最终的结果将是一个更锐利、更专注的Nushell,它感觉就像您工具箱中想要的工具。一些早期采用者已经给我们反馈说,Nushell正在很好地满足这一角色,我们很高兴能在不断探索和完善的过程中继续探索和完善。

有一些非常有趣的公开探险。

.