为什么在基于 Lisp 的语言中习惯上将许多右括号放在一行上?

2024-04-15

通常代码如下所示:

(one-thing
    (another-thing arg1 (f arg5 r))
    (another-thing arg1 (f arg5 r)))

为什么不喜欢这样?:

(one-thing
    (another-thing arg1 (f arg5 r))
    (another-thing arg1 (f arg5 r))
)

它允许更轻松地添加和删除“另一件事”行(无需删除和重新添加尾随右括号)。您还可以在那个单独的右括号上添加一些注释(例如“;循环结束”)。

当我将使用第二种样式的代码与使用第一种样式的现有代码混合时,情况有多糟糕?


在 Lisp 和其他使用 S 表达式作为语法的语言中,括号主要是为了编译器的利益,而布局和缩进(编译器会忽略)则是为了程序员的利益。

因此,无需在自己的行上放置右括号:精心选择的换行符和缩进足以使结构清晰。

例如,

(defun clone-indirect-buffer-other-window (newname display-flag &optional norecord)
  "Like `clone-indirect-buffer' but display in another window."
  (interactive
   (progn
     (if (get major-mode 'no-clone-indirect)
         (error "Cannot indirectly clone a buffer in %s mode" mode-name))
     (list (if current-prefix-arg
               (read-buffer "Name of indirect buffer: " (current-buffer)))
           t)))
  (let ((pop-up-windows t))
    (clone-indirect-buffer newname display-flag norecord)))

从缩进来看,结构很清晰(对于经验丰富的 Lisp 程序员来说)。将一些右括号放到新行上不会添加任何内容:

(defun clone-indirect-buffer-other-window (newname display-flag &optional norecord)
  "Like `clone-indirect-buffer' but display in another window."
  (interactive
   (progn
     (if (get major-mode 'no-clone-indirect)
         (error "Cannot indirectly clone a buffer in %s mode" mode-name)
       )
     (list (if current-prefix-arg
               (read-buffer "Name of indirect buffer: " (current-buffer))
             )
           t)
     )
   )
  (let ((pop-up-windows t))
    (clone-indirect-buffer newname display-flag norecord)
    )
  )

I should add that nearly all Lisp programmers use an editor that displays matching parentheses, performs automatic indentation, and provides a user interface for working direcly with balanced expressions. In Emacs, for example, there's M-( for inserting a new expression, M-) for moving past the end of the current expression, C-M-k for deleting the expression after point, and so on.

因此,Lisp 程序员永远不必用手计算括号来找出哪些匹配。


泰勒·R·坎贝尔 http://mumble.net/~campbell/scheme/style.txt雄辩地表达了这个道理:

实际的括号字符只是词汇标记,不应赋予其任何意义。 Lisp 程序员不会单独检查括号,或者(阿撒托斯禁止)计算括号的数量;相反,他们查看程序中表达的高层结构,尤其是缩进所呈现的结构。 Lisp 并不是要编写一系列串行指令;而是要编写一系列串行指令。它是通过对各个部分求和来构建复杂的结构。从各个部分组成复杂结构是 Lisp 程序的重点,这一点从 Lisp 代码中应该显而易见。在演示文稿中随意放置括号会让 Lisp 程序员感到不舒服,否则他们在大多数情况下都不会看到它们。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么在基于 Lisp 的语言中习惯上将许多右括号放在一行上? 的相关文章

  • 为什么使用分号? [复制]

    这个问题在这里已经有答案了 除了主观视觉感知和同一行有多个语句的情况之外 是否有任何理由在 JavaScript 中的语句末尾使用分号 看起来有大量证据表明分号的使用是高度可选的 并且只有少数特定情况需要使用分号 因为当 JavaScrip
  • clojure 中的反转哈希映射

    我在 clojure 中有哈希映射 key1 value1 key2 value2 key3 value1 我需要将其转换为哈希映射 value1 key1 key3 value2 key2 有 Clojure 方法可以做到这一点吗 clo
  • clojure 的 emacs slime-connect 版本不会查找 $CLASSPATH

    我需要将 clojure 函数与 slime connect 一起使用 我将所有库都放在 CLASSPATH 中 据我了解这个问题 https stackoverflow com questions 3376840 clojure clas
  • fn 和 fn* 有什么区别?

    在 Clojure 中 fn 和 fn 有什么区别 当我在语法中引用使用 宏创建的函数时 我看到 fn 例如 在 REPL 中 user gt inc fn p1 342 343 auto clojure core inc p1 342 3
  • 如何在 Clojure 中更新原子的向量元素?

    我有一个矢量原子 我想更新一个本身就是地图的条目 def vector atom atom swap vector atom conj id 1 name myname 我该如何只更新该成员 在可变的 Java 领域的思维方式中 我会做这样
  • 枚举是单数还是复数?

    枚举时使用单数还是复数 我认为声明中使用复数最有意义 enum Weekdays Monday Tuesday Wednesday Thursday Friday Saturday Sunday 但我认为在使用类型时使用单数更有意义 例如
  • 什么时候应该在 Clojure 中使用临时重新绑定特殊变量这一习惯用法?

    我注意到一些库 例如 clojure twitter 使用特殊的变量 用于动态绑定的变量 被星号包围 进行 oauth 身份验证 您将身份验证保存在 var 中 然后使用 with oauth myauth 我认为这是解决此类问题的一个非常
  • 从 JVM 线程本地空间卸载 Clojure 变量

    我正在 Clojure 中为 BaseX 编写一个插件 通过 lein uberjar 构建 并包含 Clojure 解释器 在大多数情况下 这效果很好 然而 当通过 BaseX HTTP 实例运行时 评估在 Jetty 的线程池内进行 而
  • 在 .NET 中可以将数组或列表作为属性返回吗?

    我正在阅读 MSDN 上的一些文档 了解有关某些内容是否应该作为属性或方法实现的注意事项 我特别遇到了一条规则 对此我有疑问 如果 操作返回一个数组 请使用方法 而不是属性 页面在这里 在属性和方法之间进行选择 https msdn mic
  • 修改功能;保存到 Lisp 中的新函数

    所以我认为 lisp 在其他语言中 的优点之一是它能够实现函数工厂 接受函数作为参数 返回新函数 我想使用此功能对函数进行小的更改并将其保存为新函数 这样如果对原始函数进行更改 它们也会反映在它所基于的新函数中 注意 我不是编写原始函数的人
  • 在 Light Table 中使用 Datomic 时出现“无读取器功能”错误

    当我在 lighttable 中评估这段代码时 ns app core require datomic api refer q as d reload all defn add person conn id d transact conn
  • 使用 ProGuard 混淆 clojure uberjar

    我想知道是否有人有使用 proguard 混淆他们的 leiningen 编译的 uberjar 的经验 我已经尽力在谷歌上寻找解决方案 但找不到真正的答案 我想知道这是否可能 我一直在尝试混淆默认的 lein 项目 这是 core clj
  • 这两个 clojure 函数之间有什么区别和问题?

    对于课程项目的一部分 我正在实现一个函数来从文件中读取一些数据并根据该文件创建图形结构 一整天我问了几个问题 结果就是这样 下面是一个可以正常工作的函数 它首先以惰性序列的形式读入文件 然后循环解析每一行并将其打印出来 defn print
  • 适用于具有不同数量数据字段的用户的功能

    这个问题是我练习的时候产生的教程中的观察者主题 http mishadoff com blog clojure design patterns episode 10 observer我试图将该功能应用于用户 但无法使用用户的数据字段 例如姓
  • 使用循环计算 Python 字典中元素的有效方法

    我有一个值列表 我希望在循环期间计算每个类的元素数量 即 1 2 3 4 5 mylist 1 1 1 1 1 1 2 3 2 2 2 2 3 3 4 5 5 5 5 mydict dict for index in mylist mydi
  • 将向量作为绑定传递给 for 宏时出现问题

    我有任意数量的列表 我想使用 for 宏来处理它们 我想创建一个传递向量作为绑定的函数 因为列表的数量各不相同 如果我对绑定进行硬编码 它会按我的预期工作 gt def list1 pink green gt def list2 dog c
  • gensym 在 Lisp 中做什么?

    我听到一些同学谈论他们如何使用该功能gensym为此 我问他们它做了什么 甚至在网上查了一下 但我真的无法理解这个函数的作用是什么两者都不为什么或何时最好使用它 特别是 我对它在 Lisp 中的作用更感兴趣 谢谢你们 独特且未被拘禁的符号
  • 在 Clojure 中退出 Recur 循环

    我想跳出下面的循环 并在第 10 行计算结果为 true 时返回最佳最小移动 我查看了 print 语句的输出 当第 10 行的计算结果为 true 时 它 找到了我正在查找的数据 但仍然重复出现 在 Clojure 中 有没有办法在语句计
  • 可以混合使用 JVM 语言吗?即:Groovy 和 Clojure

    我知道你可以轻松地混合groovy java clojure java 无论什么JvmLang java 这是否也意味着我也可以让 clojure 和 groovy 代码进行交互 如果我使用 Grails 或 jRoR 我也可以在该环境中使
  • 获取调用表单的名称空间

    我想要一个宏this ns这样它就会返回调用它的位置的名称空间 例如 如果我有这段代码 ns nstest main require nstest core as nstest defn ns str x gt x getName name

随机推荐

  • Python:如何获取仅出现在一组列表中的一组中的项目?

    我想创建一个函数 它接受一个或多个集合的列表 并查找列表中所有集合的对称差异 即结果应该是一组值 每个值仅包含在其中一个值中套 如果我对对称差异的理解是错误的 请纠正我 例如 gt gt gt s1 set 1 2 3 gt gt gt s
  • 如何将Java项目导入到Eclipse中?

    我试图导出一个 Java 项目 我可以使用选项 Export gt Java gt JAR file 创建 JAR 文件 我无法将此 jar 文件导入到 Eclipse 中 没有 java 的导入选项 我在这里做错了什么吗 使用面向 Web
  • 使用系列查找表替换 Pandas DataFrame 列中的值

    我想用我准备的系列形式的查找表生成的更准确 完整的一组值替换 DataFrame 中的一列值 我以为我可以这样做 但结果并不如预期 这是我要修复的数据框 In 6 df normalised head 10 Out 6 code name
  • 我的代码中某处存在无限循环

    我有这个 Java 游戏服务器 最多可处理 3 000 个 tcp 连接 每个玩家或每个 tcp 连接都有自己的线程 每个线程的运行情况如下 public void run try String packet char charCur ne
  • 使用 Linq 按可变整数范围进行分组

    我试图根据整数的范围对一组数据进行分组 范围不以固定间隔增加 例如我有 商品编号 价格1 102 303 504 120 我想将价格为 0 10 11 100 和 100 500 的商品分组 因此 项目 1 在 A 组中 项目 2 3 在
  • tkinter 中从右到左的文本

    我使用的是 RTL 语言 并且我需要我的文本为 RTL 有办法做到吗 我怎样才能证明我的文字合理 例子 from tkinter import from tkinter constants import root Tk text Text
  • 使用 Fetch API 来 POST XML

    我正在尝试使用 Fetch API 来处理 XML 数据的 POST 以避免 XmlHttpRequest 的跨域问题 我面临的问题是 尽管将我的 Content Type 设置为 text xml 在本例中这是唯一受支持的内容类型标头 但
  • 如何从 jar 文件中排除属性文件?

    我有一个具有以下项目结构的java应用程序 myProject src main resources userConfig properties log4j properties target 我在用Maven构建我的项目 我在用maven
  • 使用 Google BigQuery 作为 Django 的后端

    我正在考虑使用 Google BigQuery 作为 Django 的后端 但无法确定这是否可行 以及如果可行 将应用哪些设置 目前 我的Django应用程序使用Postgresql settings py中的代码如下 DATABASES
  • 如何通过层序遍历创建二叉树?

    Given a level order列表 其中可以包括None值 如何构建二叉树 None列表中的值即None节点不能有任何子节点 left or right值 from typing import List Optional class
  • Google Plus 单点登录服务器流程 - Google_AuthException 获取 OAuth2 访问令牌时出错,消息:“invalid_grant”

    2013 年 1 月 27 日更新 听起来您可能多次发送相同的授权代码 在 Android 上 GoogleAuthUtil getToken 会缓存它检索到的所有令牌 包括授权代码 如果您请求第二个代码而不使前一个代码无效 GoogleA
  • 未捕获的类型错误:angular.lowercase 不是函数

    未捕获的类型错误 angular lowercase 不是函数 我的 angularjs 应用程序中出现此错误 并且整个应用程序未运行 这是它的表现textAngular sanitize js 413 无法调试 我尝试使用与 angula
  • BASH - 使用 Loop 和 If 语句总结唯一字段中多个字段的信息

    我有以下制表符分隔的文件 A1 A1 0 0 2 1 1 1 1 1 1 1 2 1 1 1 A2 A2 0 0 2 1 1 1 1 1 1 1 1 1 1 1 A3 A3 0 0 2 2 1 1 2 2 1 1 1 1 1 1 A5 A5
  • 网站是否有可能欺骗引用标头

    显然 请求标头可以通过客户端 任何扩展 AV 防火墙 浏览器设置等进行欺骗 我的问题是 网站所有者可以吗bad com可以创建一个 iframemywidget php 我会看到一个欺骗性的引用标头good com 欺骗将由站点所有者 例如
  • NetStream.appendBytes

    我有一个连接到 Flash Media Server 的 netConnection 我正在尝试使用 Flash Player 10 1 中的新appendBytes 函数将本地FLV 文件流式传输到FMS 但是我遇到了问题 我在网上获取的
  • 如何为ubuntu创建永久“别名”? [复制]

    这个问题在这里已经有答案了 例如 如果您创建别名 alias cls clear 它一直存在 直到您终止终端会话为止 当您启动新的终端窗口时 别名不再存在 如何创建 永久 别名 该别名存在于每个终端会话中 您可以将此类别名放入 bash a
  • 查询与空字段的比较

    我的 Firestore 集合包含带有字符串字段的文档 该字段可以是null 我期望如果我查询 Collection products Where producedDate lt 2018 01 15 我将获取 生产日期 早于 2018 1
  • UITableView 滚动时重复单元格

    当我向下滚动 UITableView 时 它开始向我显示我已经看到的相同单元格 并且稍微滚动一下继续将单元格放在错误的位置 这是我正在使用的代码 如果需要任何其他信息 请告诉我 h interface HomeViewController
  • MediaStore.Playlists.Members.moveItem 的替代方案

    我一直在使用以下代码从 Android 应用程序的播放列表中删除项目 private void removeFromPlaylist long playlistId int loc ContentResolver resolver getA
  • 为什么在基于 Lisp 的语言中习惯上将许多右括号放在一行上?

    通常代码如下所示 one thing another thing arg1 f arg5 r another thing arg1 f arg5 r 为什么不喜欢这样 one thing another thing arg1 f arg5