Common Lisp 中的 LET 与 LET*

2024-03-24

我理解 LET 和 LET*(并行绑定与顺序绑定)之间的区别,并且作为理论上的问题,它非常有意义。但有没有什么情况你曾经真正需要过 LET?在我最近查看的所有 Lisp 代码中,您可以将每个 LET 替换为 LET* 而无需进行任何更改。

编辑:好的,我明白了why很久以前,有人发明了 LET*,大概是作为一个宏。我的问题是,鉴于 LET* 存在,LET 是否有理由继续存在?你是否写过任何实际的 Lisp 代码,其中 LET* 的效果不如普通的 LET?

我不相信效率的说法。首先,认识到 LET* 可以编译成与 LET 一样高效的东西似乎并不那么困难。其次,CL 规范中有很多东西看起来根本不是围绕效率而设计的。 (您最后一次看到带有类型声明的 LOOP 是什么时候?这些太难理解了,我从未见过它们被使用过。)在 1980 年代末 Dick Gabriel 的基准测试之前,CLwas非常慢。

看起来这是向后兼容的另一种情况:明智的是,没有人愿意冒险破坏像 LET 这样基本的东西。这是我的预感,但令人欣慰的是,没有人有一个我错过的愚蠢简单的案例,其中 LET 使很多事情比 LET* 更容易。


LET本身并不是一个真正的原语函数式编程语言,因为它可以替换为LAMBDA。像这样:

(let ((a1 b1) (a2 b2) ... (an bn))
  (some-code a1 a2 ... an))

类似于

((lambda (a1 a2 ... an)
   (some-code a1 a2 ... an))
 b1 b2 ... bn)

But

(let* ((a1 b1) (a2 b2) ... (an bn))
  (some-code a1 a2 ... an))

类似于

((lambda (a1)
    ((lambda (a2)
       ...
       ((lambda (an)
          (some-code a1 a2 ... an))
        bn))
      b2))
   b1)

你可以想象哪个是更简单的事情。LET并不是LET*.

LET使代码理解更容易。人们会看到一堆绑定,并且可以单独读取每个绑定,而无需了解“效果”(重新绑定)的自上而下/左右流动。使用LET*向程序员(读取代码的程序员)发出信号,表明绑定不是独立的,而是存在某种自上而下的流程 - 这使事情变得复杂。

Common Lisp 有一个规则,即绑定的值LET从左到右计算。函数调用的值是如何计算的 - 从左到右。所以,LET是概念上更简单的语句,应该默认使用它。

输入LOOP?经常使用。有一些易于记住的类型声明的原始形式。例子:

(LOOP FOR i FIXNUM BELOW (TRUNCATE n 2) do (something i))

上面声明了变量i成为一个fixnum.

Richard P. Gabriel 于 1985 年出版了他关于 Lisp 基准测试的书,当时这些基准测试也用于非 CL Lisp。 Common Lisp 本身在 1985 年还是全新的——CLtL1描述该语言的书于 1984 年刚刚出版。难怪当时的实现不是很优化。实现的优化与之前的实现(如 MacLisp)基本相同(或更少)。

But for LET vs. LET*主要区别在于代码使用LET对于人类来说更容易理解,因为绑定子句是相互独立的 - 特别是因为利用从左到右的评估(不将变量设置为副作用)是不好的风格。

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

Common Lisp 中的 LET 与 LET* 的相关文章

  • 如何使用 common lisp 确定操作系统和主机名?

    为了让我的 sbclrc 文件在我使用的两台计算机上工作 我想要一种从 sbcl 中获取主机名和 或操作系统的方法 我知道我可以设置然后查找环境变量 但是有更直接的方法吗 Update 我将问题更改为引用 common lisp 因为 Ke
  • 在 LISP 中如何检查闭包中的自由变量?

    在 lisp 中 我可以像这样绑定在闭包中绑定的自由变量 let x 1 y 2 z 3 defun free variables x y z free variables 结果是 6 我想知道是否可以动态检查绑定的闭包变量 E g ins
  • LISP - 小数点后的数字

    有谁知道如何在 Lisp 中指定浮点数小数点后的位数 假设我在 REPL 上打印此命令 CL USER 3 gt format t 15f float 1 7 I get 0 142857150000000 但是该数字四舍五入到小数点后第
  • LISP:关键字参数,提供-p

    目前我正在学习 Peter Seibel 的 Practical Common Lisp 在 实用 一个简单的数据库 一章中 http www gigamonkeys com book practical a simple database
  • 如何使用 SBCL 正确保存 Common Lisp 图像?

    如果我想创建我的程序的 Lisp 映像 我该如何正确地做到这一点 有什么先决条件吗 它与 QUICKLISP 配合得很好吗 现在 如果我启动 SBCL 仅预加载 QUICKLISP 并保存图像 save lisp and die core
  • Common Lisp 重新启动到条件绑定

    我在空闲时间学习 Common Lisp 并对条件系统有疑问 当我们在 common lisp 中处理错误时 我们在处理程序中指定错误类型来确定要处理哪个错误 在引发和处理错误之间 我可以进行一些重新启动 例如使用 restart case
  • 了解 LISP 中的绑定变量和自由变量

    我正在阅读SICP 又出现了绑定变量和自由变量的话题 然而 我对此感到困惑 术语 绑定变量 仅适用于形式参数变量吗 此外 文本还指出过程定义 绑定 其形式参数 这让我感到困惑 因为有些人说我们将值 绑定 到变量 显然 当我们谈论不同类型的变
  • Common Lisp 中的 LET 与 LET*

    我理解 LET 和 LET 并行绑定与顺序绑定 之间的区别 并且作为理论上的问题 它非常有意义 但有没有什么情况你曾经真正需要过 LET 在我最近查看的所有 Lisp 代码中 您可以将每个 LET 替换为 LET 而无需进行任何更改 编辑
  • 防止 LISP 中的终端输出

    我想运行一个函数 但不让它在终端中输出结果 例如 set A B 正常返回B在控制台中如下所示 gt gt gt set A B B gt gt gt A B 我不希望它返回任何东西 我仍然希望该函数能够完成它应该做的事情 只是默默地 gt
  • C# 中的通用 Func<> 类型

    我正在用 C 编写一个小型 Lisp 解释器 它基本上已经可以工作了 目前我正在使用一个接口来表示函数 public interface LispFunction object Apply ArrayList parameters 该接口由
  • 如何克服 emacs lisp 闭包缺少局部变量的问题

    我现在正在学习 Emacs Lisp参考手册 http www gnu org software emacs manual elisp html和 Common Lisp 来自LISP https rads stackoverflow co
  • CLISP - 反转简单列表

    我必须反转简单 单维 列表的元素 我知道有一个内置的反向函数 但我不能用它来做这个 这是我的尝试 defun LISTREVERSE LISTR cond lt length LISTR 2 LISTR listr is 1 atom or
  • Common Lisp 中的(随机)不那么随机?

    好的 最后一个问题 我将用 Common Lisp 完成我的猜数游戏 D 每当游戏开始 或者在第一个游戏之后开始新游戏 时 都会调用以下函数 Play the game defun play If it s their first time
  • elisp:有没有办法获取当前 .el 模块的名称(如 C 中的 __FILE__ )?

    在我的 elisp 模块的顶部 我想做一些简单的事情 message concat Loading expand file name current elisp module 您可以使用变量load file name https www
  • 展开方案中的函数

    Goal 实施unfold仅使用两个参数的函数 论据 第一个参数是 f 它接受某种类型 I 的初始值并返回 nil 或两个元素的 cons 对 这两个元素中的第一个是某种类型 A 的列表中的下一个元素 下一个初始值又是某些类型 I 第二个参
  • 在 Lisp 解释过程中,“读者”的任务是什么?

    我想知道 读者 在解释 编译 Lisp 程序期间的目的 或者更准确地说 是 读者 的任务 从我刚刚完成的问题前研究来看 在我看来 读者 特别是本例中的 Clojure 可以被视为 语法预处理器 它的主要职责是读取器宏和原始形式的扩展 所以
  • 如何定义和使用 Common Lisp 包(库)?

    我在几个 Lisp 源文件中开发了一些 Common Lisp 函数 我希望这些函数可以轻松地供我编写的其他函数使用 或者如果我认为它们对其他人有用的话 可以在 github 上提供 现在 我只是将它们放在一些预定义的文件夹中并使用 req
  • 为什么在基于 Lisp 的语言中习惯上将许多右括号放在一行上?

    通常代码如下所示 one thing another thing arg1 f arg5 r another thing arg1 f arg5 r 为什么不喜欢这样 one thing another thing arg1 f arg5
  • 对于案例,这些表达案例的方法中哪种最好?

    这些都有效 defun testcaseexpr thecase case thecase foo format t matched foo bar format t matched bar funk format t matched fu
  • 在Emacs中,这个错误是什么意思? “警告:运行时需要 cl 包”

    我正在字节编译一个模块 它给了我这个警告 Warning cl package required at runtime 为什么这是一个警告 我很清楚我正在使用cl包裹 事实上有一个 require cl 模块中的语句 使用有什么问题吗cl

随机推荐

  • 浏览器如何处理高度和宽度的非整数值?

    当浏览器给出的元素的宽度和高度不是整数值时 它们如何处理它们 尤其 非整数值在什么阶段进行四舍五入 它们是四舍五入到最接近的整数 还是截断它们 当容器的子元素具有非整数尺寸时 是否会出现子元素长度或高度之和不等于父元素的内部宽度 高度的情况
  • 显示 UILabel * 秒;除了 NSTimer 之外还有其他方法吗?

    是否有其他方式显示对象 按钮 其他内容 例如 3 秒而不是 NSTimer 我可以使用动画来做到这一点吗 您可以使用 performSelector withObject afterDelay 尽管它内部使用了一个计时器 theLabel
  • 获取 NSTextField 内容以缩放

    我怎样才能让文本比例适合我给它的边界 我过去也做过类似的事情 void calcFontSizeToFitRect NSRect r float targetWidth r size width xMargin float targetHe
  • C++ 按升序打印文件名

    我正在使用以下代码来迭代目录中的文件 该目录中的所有文件都有编号 每个文件都有唯一的编号 下面的代码成功打印出目录中的所有文件 但不是按升序排列 它完全随机出现 并且有一个文件是重复的 我找不到另一种打印文件或按升序打印文件的方法 我确实需
  • C# Xamarin Forms - 执行任务,超时

    和其他许多人一样 我需要编写一个返回任务的函数 并且我希望该任务在一段时间后自动超时 初始代码如下所示 class MyClass TaskCompletionSource
  • 按 nginx 中的位置提供 pdf 文件

    我如何提供文件 webapps app static downloads privacy policy pdf 按地址 https my site net privacy 我尝试在 nginx 中使用位置 但这不起作用 location p
  • Dropwizard ExceptionMapper:验证原始标头字段

    有谁知道如何从请求中获取原始标头字段 我想验证客户端是否会收到 html 或只是纯 文本响应 我可以在异常映射器的 toResponse 方法中获取此字段吗 我像这篇文章中一样创建了异常映射器 http gary rowe com agil
  • 使用温莎城堡解析 HttpControllerContext

    In the ASP NET Web API http www asp net web api HttpControllerContext实例提供了很多有关当前环境的信息 包括当前请求的URI 如果服务依赖于此类信息 例如请求 URI 则应
  • 在 Windows 上使用 Python 3.7 安装 pycairo

    我正在尝试安装 pycairo 尽管我在互联网上找到了这些内容 但我无法安装它 我确实 pip install pycairo 但它要求我安装 Visual Basic Build Tool 我做到了 但当时不起作用 我尝试了在网上找到的很
  • C++编译引入错误

    我在 Visual Studio 2010 中有一个多线程 C windows 项目 它使用 Qt 5 1 1 和 OpenCV 2 4 8 当我构建它时Debug模式一切运行正常 但是当我构建它时Release模式下程序崩溃 两种配置几乎
  • Keycloak/Undertow/JBoss-CLI - 从环境变量设置“web-context”

    我对 Wildfly Undertow 和 JBoss CLI 设置 Keycloak 的 Web 上下文有疑问 环境变量似乎并未在 undertow 本身中得到解决 但其他环境变量似乎已得到解决 我创建了以下 CLI 脚本 subsyst
  • Spring MVC 中的 PropertyPlaceholderConfigurer

    我在我的项目中使用 Spring MVC 我在中定义了详细信息web xml像这样
  • 对 mysql 中的结果进行排名(mysql 相当于 oracle 中的“dense_rank()”或“row_number()”函数)

    以下是样本数据 dept id salary 10 10000 10 20000 10 20000 10 30000 20 50000 20 60000 我想对部门 ID 进行分组 然后按升序生成工资的排名值 输出应如下所示 dept id
  • 如何获得 Rails 路线以将扩展保留为 id 的一部分?

    我定义了以下路线 map resources images only gt index new destroy 当我做一个rake routes我得到以下信息 image DELETE images id format action gt
  • ServiceStack.DataAnnotations 缺少属性定义?

    我正在尝试使用 ServiceStack DataAnnotations 中的 ServiceStack 属性装饰器 但是当我在 MSVS 对象浏览器中查看 ServiceStack DataAnnotations 命名空间时 只有以下类型
  • 为所有测试配置一次 jest 超时

    根据文档 可以使用以下命令将默认异步超时从 5000ms 增加玩笑对象 https jestjs io docs en jest object 更具体地说 通过使用玩笑 settimeout 超时 https jestjs io docs
  • 如何过滤 django-taggit 顶部标签

    假设您有一个数据库 其中包含在 Django 应用程序后面运行的 User 对象 你想使用django taggit标记用户对象 以便您可以使用一些方便的过滤来检索子组 此外 您还有一个仪表板 您希望在其中显示有关已用标签的有趣统计信息 以
  • 防止 fork() 复制套接字

    我有以下情况 伪代码 function f pid fork if pid 0 exec to another long running executable no communication needed to that process
  • C# 逐字字符串换行符:CRLF、CR 或 LF?

    我今天遇到了一个有趣的问题 我的测试在构建机器上始终失败 而即使使用相同的配置 它们在我的机器上运行得很好 当我查看故障转储中 Assert AreEqual 输出的差异时 我看不到任何不同 经过一系列调查后 我发现测试用例源代码中的逐字字
  • Common Lisp 中的 LET 与 LET*

    我理解 LET 和 LET 并行绑定与顺序绑定 之间的区别 并且作为理论上的问题 它非常有意义 但有没有什么情况你曾经真正需要过 LET 在我最近查看的所有 Lisp 代码中 您可以将每个 LET 替换为 LET 而无需进行任何更改 编辑