clojure - Clojure 函数的方案(subst)
问题描述
我正在阅读 Paul Graham 的Lisp 的根源
我尝试转换subst
第 5 页上的函数,其定义如下:
(defun subst (x y z)
(cond ((atom z)
(cond ((eq z y) x)
('t z)))
('t (cons (subst x y (car z))
(subst x y (cdr z))))))
对其相应的Clojure
实现。我没有使用这两种语言的生产经验(我一直在阅读 Clojure),因此我将不胜感激任何帮助,因为我正在阅读本文以了解 LISP 的根源。我最接近的是这个(但这是非常错误的):
(defn subst
[x y z]
(if (not (nil? z)) z x)
(if (= z y) x z)
(cons (subst x y (first z))
(subst (x y (rest z)))))
解决方案
“传统的,传统的”
(这可以翻译为“翻译者,叛徒”,但这样做会破坏双关语,这本身就很有趣)
很难在您的 Clojure 代码中暗示可能的修复,因为规范不清楚:如果您严格遵守Lisp 的根源,您将在 Clojure 之上实现一个 Lisp,并且subst
可能类似于这本书。但是如果你想实现subst
Lisp 中常用的,这里显示的代码是行不通的。
尽管 Clojure 具有cons
和nil?
功能,但它们的含义与 Common Lisp 中的不同(分别是cons
和null
):有关详细信息,请参阅clojure: no cons cells。在你可以翻译之前subst
,你必须确定在 Clojure 中做什么是惯用的。
通常subst
用于转换由 cons 单元组成的树;请注意,例如,subst
它不会递归到向量、字符串等。在这些树中,树的特定子集是 Lisp 形式的树。事实上,一个重要的用例subst
是在代码生成期间搜索和替换表单。
据我所知,如果您将自己限制为 ClojureCons
类型,那么您将不支持将代码作为数据。由于 Clojure 代码还使用向量和映射,因此您可能需要递归到此类对象中。因此,如何翻译subst
并不是一个容易指定的问题。
一个可能的起点是阅读LispReader.java
以确定构成 AST 的对象集,并查看您想要执行哪种代码遍历。
我的建议是先独立学习这些语言。通过对每个方面的一些经验,您将有一个更好的方法来了解它们之间的相似之处和不同之处。
推荐阅读
- javascript - 来自 jQuery $.ajax 调用的响应变量上的 javascript querySelector
- c++ - std::bind() 参数列表中仿函数的执行顺序(可能与函数参数的评估顺序无关)
- python - python中的多个shell命令(Windows)
- amazon-web-services - 用于传送 fluentd 日志的 aws kubernetes 集群间通信
- scala - 使用 OptionT 将 Future[Option[_]] 与普通 Future[_] 组合时语法更好
- asp.net-core - 使用 AbpMvcAuthorize 自定义身份验证方案
- php - openssl_public_encrypt 在大输入上返回空输出
- ios - 在 ARKit 水平面上绘制填充多边形
- python - 使用 paramiko,重命名文件和更改目录失败。为什么?
- linux - 在单个别名命令中链接 xwininfo 和 imagemagick?