“贝尔,夏娃”和一段无聊的VR咆哮的回顾

2020-08-15 16:39:14

这位精灵乞求爬上网络过圣诞节,最初是一封私人电子邮件,是对保罗·格雷厄姆的“小里斯普·贝尔”的评论。他伸出胳膊和腿,穿着姜黄色的衣服跑开了。手臂代表符号,腿代表双腿:这些原语是Lisp语言的标志--甚至比括号更重要。当我们移除这些基石时,我们得到了什么:命名和配对?

没有配对。没有坏处。没有结构。无序的。一片混乱。Eve,一个漂亮的不完整的面向方面的三元组存储。当你可以毫不费力地运送到目的地时,就不需要腿了。懒惰。纯洁。此时此刻,一场回顾展。

没有符号。没有名字。没有变数。组合器。第四点。当你可以毫不费力地推动和弹出你的堆叠时,就不需要手臂了。没什么好说的。一个没有语言的世界。虚拟世界。虚拟现实。太空。时间到了。动议。开始吧。动态编程,一个提议。

我提前道歉。看了看我的怀表,我发现我还没有时间去理解这份白象赠送的姜饼精灵无稽之谈。他的方式是疯狂的。警告你。

我在形成时期就读过保罗·格雷厄姆关于Lisp的文章,我努力认真研究他的贝尔语言。让我们乘直升机旅行吧。我观察到了很多具体的东西(重写后可能会运行得更好的函数),但还是让它停留在丛林之上吧。

我认为高级语言的意义在于使你的程序更短。..。LISP方言通常擅长缩短程序。贝尔的用意和以前的方言一样,但更重要的是。它也意味着简单明了。如果你想理解Bel';的语义,你可以阅读源代码。

回首几十年来,PG的美学给人们带来的切牙乐趣,趣味是如何变化的,这是一件有趣的事情。

令人惊讶,令人惊讶的是,我同意乔纳森·布罗(Jonathan Blow)的观点,他认为简洁性比所有这些(可调试性、编译时错误检查、可读性、消除繁忙工作、士气(对正确性的信心与永久的半混乱状态))都更重要,可能还有其他几个我没有列出的东西。我可能会同意乔纳森·布罗(Jonathan Blow)的观点,他认为简洁性比所有这些(可调试性、编译时错误检查、可读性、消除繁忙工作、士气)更重要。

在我看来,Blow‘s Jai是一种丑陋、冗长的系统语言,其中Blow似乎非常高效。由于“见证者”在成为杰作(Do@Me)之前多年来一直很丑陋,而且Jai还在坚定地前进,Blow最终可能需要一个漂亮的表面语法-或者不需要。这取决于他。他谈到JAI编译速度快,接近相关硬件,比C++(低级但重要的标准)更简单,宏更好(最灵活的方面),并且有一定的动态范围。

贝尔也有动态范围。虽然只是偶尔有用,但我编写的每个大小的程序最终都需要动态变量。我主要通过训练全局变量来管理,但是一种语言中的标准支持可能会被证明是变革性的。例如,使用动态作用域可以更好地管理Rails视图/控制器中的实用程序方法和实例变量管道。实际上,任何场景--场景图、解释器--都可以传递上下文对象。需要一定的文化:显然,Scala的含义无处不在。

PG回应说,他不关心编译时类型,因为它会阻碍探索。Blow被难住了:

我做的大多数编程也都是探索性的。..。(带着类型)我不需要太多地考虑我在做什么,如果我犯了错误,我会撞到护栏。人们曾向我表示,没有声明类型的函数更强大、更具杠杆性,但我从未体验过这是真的,我也真的不明白这怎么可能是真的(特别是在2019年有很多带有泛型的静态语言的时候)。

有些类型系统确实会以一种方式出现。泛型可能是无法推理的,运行时元编程会带来好运。(可以更轻松地键入编译时宏。)。但我们现在谈论的是2019年的艺术水平!打字孔提供了时髦的好打字现场编程所需的额外自由。我们只是让一个糟糕的类型程序定义得很好,这样你就可以问计算机,当我改变这个定义时,我在类型上打破了什么?当然,制定一个好的类型系统是棘手的,而且以简单、清晰的方式做到这一点更棘手。让我们回到那个问题上来。

作为一个合适的Lisp语言,Bel中任何经常出现的笨拙模式都可以宏化掉。把所有的方形钉子都刮掉!在不把木屑弄得到处都是的情况下做这件事?好的领域特定语言需要很高的概念成本。

与Common Lisp、Scheme、Sracket和Clojure相比,我发现Bel避免了一些偶然的复杂性。BEL没有多种CONS单元格或多余的数据类型。贝尔没有一个复杂但动力不足的卫生宏观系统。贝尔没有大量的并发机制。Bel坚持使用符号和对,以这些术语建模世界的其他部分,包括闭包。

我之所以说相似,是因为所有的口音都是可变的;因此,在贝尔,平等和身份通常是不同的。一个熟悉的世界。

贝尔模特儿的世界真是太棒了!当一段代码可以运行时,可变状态和命令式执行是理所当然的,不少于五次:

让我们直接抛出线程,因为尽管Bel的解释器对它们进行了建模,但Bel的定义从来没有使用过它们,任何人都不应该使用它们。与进程之间的通道一样,派生进程是另一回事。贝尔不走那条路,尽管它有溪流。

PG还包括完整的延续,但仅将其用于异常处理。在堆栈深处迷路了吗?调用续集以立即弹出。但是等等,还有更多!您可以将续集留到以后使用。在返回并做更多工作之后,继续并及时返回到您抓住续集的时候。让回溯和异国情调的时间旅行循环变得容易!然而,完整的延续通常不是一个人想要的:你可以回到过去;但除非你提前计划,否则你将无法回到未来。带分隔符的延续(要求您标明要追溯到多远)和可克隆协程(当您希望能够往回复制时显式克隆)都更安全,功能也同样强大。请注意,延续与动态作用域的交互方式可以将动态变量与跟踪全局变量的堆栈区分开来。区别对应于相对于状态单体排序延续单体的方式。

在多年的接触和提炼之后,我以某种方式将延续语义内在化,我在想,如果我试图将它们用于实际工作,我会受到多大的伤害。鲁比拿着它们。让我想想……。在构成我当前工作项目的依赖关系的131个gem中,调用了callcc...。0次!纤维呢?Ruby对协程的称呼是什么?9个文件中有26个匹配。其中一半是我自己的!其他几个只是测试,以确保如果有人有心情使用纤维,东西不会破裂。这些构造是否缺乏内在效用?这是编程约定的问题吗?Ruby有异常、专用的捕获/抛出机制和其他快速返回关键字,因此剩余的用例是有限的。是否有深层次的原因来避免这些构造呢?让我们回到那个问题上来。

线程和延续在很大程度上使解释器变得难以理解-但也更加明确。尽管Lisp将程序的源代码具体化为一种数据结构,但很少有自我解释的Lisp通常不会在程序运行时做同样的事情。相反,解释器在递归计算中隐藏上下文:解释器的堆栈包括正在解释的程序的堆栈。

为了支持线程,Bel实现了执行状态。(不是整个执行,而是每时每刻。整个执行过程仍然隐藏在解释器的执行过程中。)。您有一堆明确的事情要做,有些事情要回去处理。它被线程缠绕在一起,数据结构隐含在你们如何将列表组合在一起,我很难知道发生了什么。例如:

(def evcall(E A S R M)(mev(cons(list(Car E)a)(fu(S R M)(evcall2(Cdr E)a s r m))s)r m)。

此函数开始评估调用。这些论据相当于口译员的状态。它会稍微忽略它们,并最终调用MEV,由MEV挑选出下一步要处理的线程。Evcall主要是evcall2的代理:

(def evcall2(es a s(op.。R)m)(if((ISA';Mac)op)(Applym Op Es A S R M)(mev(append(map[list_a]es)(cons(fu(S R M)(let(Args R2)(Snap Es R)(applyf op(Rev Args)a s r2 m)。

它告诉我们,如果操作是宏,则应用应用程序;否则,操作是函数,您将应用应用程序f。我无法理解这些参数的形状或返回值的形状。我当然不可能在不自杀的情况下改变这一点。请给我护栏!

来吧,加时捷!你制作了一种具有动态作用域的语言,然后你就有了17个不同的函数,它们围绕着a s r m上下文!动态作用域版本不是会更简洁吗--即使您拼写单词而不是使用单个字母的名称?当单字母变量的作用域是本地时,我都支持它们,但在其余时间,人们不应该查阅键。

撕裂比拼合容易。这么多年来,我付出了这么多努力,我要表现出什么呢?几乎什么都没有!我希望我学到了一些东西,但我离令人满意的答案还差得远。让我在点子自助餐的贝尔附近分享一些美味的点心吧。我有不少于162个链接,而且还指望着我的积压,我确信我错过了很多好的最近的发展。

Lisp的美妙之处在于,您可以构建一个完整的世界,从将原子符号组合成对、列表和树等等。你可以通过拥有一个仅仅是(能指)列表的环境来引用符号。表示)配对。沿着这条路走下去。如果所指的值不是直接值,而是一个表达式,那么您就得到了一种大小写表达式,而该表达式又将被求值。如果意符是您测试所依据的模式或表达式,而不是检查是否相等,则会得到一种if表达式。如果该模式随后添加到您在其中查找所表示的表达式的环境中,那么您现在就有了一个函数定义。这一切都有助于在抽象的阶梯上温和地攀登。例如,我喜欢巴里·杰伊探索梯子的方式。

当我们到达顶端时,我们拥有如此强大的模式力量(统一和后备),以至于我们可以解决其中一些棘手的问题:

攀登感觉直接、直观,但我们会引入意外的复杂性吗?符号和铃声看起来很简单。他们隐瞒了什么?每个概念都有什么前提呢?

以海燕为例。他们干些什么?把东西整理好。首先,休息一下。车,CDR。积木。订货是否等同于一种时间感,甚至是变化无常?时间:先看这里,然后看这里,最后再看那里。易变性?两者之间有真正的区别吗?

当然,顺序是编程的本质,源是字符序列,执行是步骤序列(大致),而人类是时间和空间的生物。然而,在故事中,秩序不是源于混乱吗?

在最近的记忆中,夏娃人试图认真对待集合语义学。他们希望秩序独立能减少人们的担忧。我紧跟着他们。把他们的软件推过几个悬崖,看看它能飞多远。光荣的残骸。

当我在日常编程生活中步履蹒跚时,大部分工作都围绕着组织:将数据放好,再次取出,将信息从保持整洁的地方运送到需要使用的地方。我的夏娃朋友们认识到这种做法无处不在,而且可能毫无意义。让一个像样的数据库保持整洁,这样您就可以专注于处理数据,而不是将其存放起来。

EVE的核心最终是实体-属性-值三元组。将属性直接附加到具有它们的对象。这样的财产清单几乎和反对者一样松散。Eve';的查询语言使得挑选东西变得很容易。Eve';的规则使派生属性易于定义,从而完成了循环。事实上,夏娃很像索尔。

很久以前,我就想象面向方面的编程会证明自己。在Java变得怪异的时候被固定在Java上可能无济于事。Eve证明了一个可爱的方面实验,而不是广泛使用的一种类似方面的语言:级联样式表。有意可悲的是,选择器从固定的集合中挑选出一些HTML文档,将属性和值附加到这些文档上。只有当增加的价值是你可以选择的东西时,才会出现令人惊叹的东西。请注意,使用CSS的困难来自(1)不知道属性是做什么的,特别是在浏览器多种多样的情况下,以及(2)复杂的优先规则-士气低落的不可预测性。Soar通过一个消除歧义的步骤解决了这个问题,EVE通过搜索不动点模型解决了这个问题。秩序独立意味着从何时何地的担忧中解脱出来。时间和空间在柏拉图领域是无关紧要的。

如果夏娃真的那么漂亮,为什么会失败呢?让我们谈谈技术原因吧。(我对创业公司一无所知。)。EVE的技术问题:(1)键控、(2)检查、(3)反射、(4)事件处理。

(1)在尝试使用EVE时,键控被证明是我最常见的问题。我希望每个东西的东西是复杂的实体:就像每个投标人出价,每个产品每轮。每个投标也有不可识别的属性:价格、输入的时间、输入的人等等。在常规软件中,每增加一个额外的&34;是一个很大的时间沉淀物。我真心希望伊芙能帮上忙。尽管Eve在内部处理钥匙,但他们从未完成理论,也没有承诺披露细节。

(2)如果没有很好的方法来检查数据库,我就看不到发生了什么,钥匙是如何发挥作用的。

(3)因为EVE模式可以匹配任何东西,所以我发现检查不变量很容易,但是很难确定违反它们的原因。人们无法思考规则是如何产生派生属性的。这一直是一个目标,只是从来没有发生过。

(4)虽然EVE有一个很好的理论基础,可以随着时间的推移进行可控的变化,但它从来没有以一种人们容易推理的方式暴露出来。主要的挑战是您希望一个事件在数据库中出现,影响更改,然后消散。尽管命令式语言允许您编写第一步、第二步、第三步,但Eve从来没有这样的观点。变化是通过错综复杂的规则相互作用来管理的,这些规则总是隐藏的。Dijkstra提出了一个很好的观点:

我们的智力相当适合于掌握静态关系,而我们想象随时间演变的过程的能力发展相对较差。因此,我们应该尽最大努力(明智的程序员意识到我们的局限性)来缩小静态程序和动态过程之间的概念鸿沟,使程序(分布在文本空间中)和过程(分布在时间上)之间的对应关系尽可能微不足道。

考虑到思考、时间和实践,这些问题本来是可以解决的-但只有在认真对待订单的情况下才能解决。为什么(2)检查、(3)反射和(4)动态被可视化?要展示一样东西,它不可能是无形的。它必须放在,安排在空间里。和夏娃在一起,他们一直在玩平底船,无视有秩序的人和无序的人之间的相互影响。即使在(1)键控方面的困难也相当于泄露了必要的实现细节。

具有讽刺意味的是,懒惰为弟子提供了在秩序和混乱之间导航的必要通道。我的意思是懒惰的执行,纯粹的函数式编程。当操作可以安全地重新排序时,不再是非正式地知道(或猜测)什么时候是状态重要的,而是不允许平底船。类型牧师确保将清理与不清理分开,否则他们足够聪明的编译器无法进行必要的重写以获得可容忍的性能。请记住,编译器编写一度是纯函数式程序员的主要工作。

除了这一切的仪式,我们今天可能都在给哈斯克尔写信。功能核心凝聚在一起。类型-类打开了Pandora的可能性。把一些语言扩展放入其中,开始时写成的神圣法则会让人感觉不完整、偶然、堕落。我等待弥赛亚在两个伟大的构思中实现律法的精神。谁知道呢?也许他们终究会成为象征和缺点!或者不是符号。让我们来考虑一下。

在计算机科学中有两件棘手的事情:缓存失效、命名对象和Off-by-one错误。

除了选择一个好的名字,诀窍是保持它的意思,保持上下文清晰。难道经验不表明,隐藏的变量是λ演算的主要复杂因素,特别是当递归开始发挥作用时?如果我们去掉变量呢?滑雪组合体微积分!用第四个!尝试串联编程。做。只要把一件事和另一件事连在一起就行了。

如果你想用两样东西怎么办?把一样东西放在一边,把另一样东西准备好,然后结合起来。你可能需要把一堆东西放在一边:一堆。当然,堆栈维护是笨重的;然而,好处是任何序列都可以很容易地分解到一个新的定义中-没有本地绑定需要担心,只有定义单词的字典。连结语言通过将局部变量放在附近的堆栈中来消除它们。

或者,不是通过一根管子把一堆东西推进去,而是用多根管子立管。这里我们介绍了经典可视化编程的精髓--数据流框线。尽管弗雷德·布鲁克斯(Fred Brooks)1987年的评论在最数学层面上取得了一些进展,但总体来说,这些努力还没有产生令人信服的东西,更没有什么令人兴奋的东西。我相信什么都不会发生。有何不可?

今天的屏幕太小了,以像素为单位,无法显示任何非常详细的软件图表的范围和分辨率。..。在我们的范围足以完成软件设计任务之前,硬件技术必须有相当大的进步。更根本的是,正如我上面所说的,软件是很难可视化的。无论一个图是控制流、变量范围嵌套、变量交叉引用、数据流、分层数据结构,还是其他什么,人们只能感受到错综复杂的相互关联的软件大象的一个维度。如果叠加由许多相关视图生成的所有图,则很难提取任何全局概览。

当我第一次尝试VR进行信息可视化时,我并不感到惊讶,因为闪电击中了:房间里的空间比屏幕上的空间大得多,大得多,多得多。所以。很多。太空。但你不能使用文本:不是很多,不是很近,不舒服,不是在目前的技术下。多好的机会啊!一个诵读困难症的天堂:一个可以无限延展的世界,在这个世界里,最好还是放逐文字。

盒子线路图不会那么容易缠绕在一起。稍微歪一下头对消除歧义有很大的帮助。那远处的电线呢?在一个下午,一个解决方案突然出现。看着窗外的丛林树叶,我分不清一棵树的终点和下一棵树的起点。然后,一丝丝微风就让百万节点网络成为焦点--一阵微风和一个优化的树形几何识别引擎。对于灵长类动物的大脑来说,丛林是什么?

还是这样。电线只是连接相关事物的一种手段。为什么不直接把它们连接起来呢?把它们放在一起就行了。如果这头大象是三维的,六维的,二十维的又怎么样呢?为了直观,折叠起来,把多余的收起来。

.