我在看保罗·格雷厄姆的李斯特的根
我已经尝试过转换第5页中的函数subst,它的定义如下:
(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)))))发布于 2020-04-06 17:14:13
我就是这样做的,包括一个单元测试来验证:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require [clojure.walk :as walk]))
(defn subst
[replacement target listy]
(walk/postwalk (fn [elem]
(if (= elem target)
replacement
elem))
listy))
(dotest
(is= (subst :m :b [:a :b [:a :b :c] :d])
[:a :m [:a :m :c] :d]))然而,我不会花很多时间去阅读40年前在Common上发表的文章,尽管我认为保罗·格雷厄姆( Paul )的书“黑客与画家”让人心神不宁。
Clojure已经将最先进的lisp发展到至少一个数量级(我想说更像是2 )。主要的改进包括JVM的使用、持久数据结构、并发性、语法和数据文字(仅举几个例子)。
请查看这个Clojure学习资源列表,并可能从获取Clojure或类似的内容开始。
更新
以上是Paul Graham为您带来的更多信息。

发布于 2020-04-06 14:30:44
"Traduttore,traditore“
(这可以翻译成“翻译家,叛徒”,但这样做会破坏双关语,这本身就很有趣)
很难在Clojure代码中提示可能的修复,因为规范还不清楚:如果您完全按照Lisp的根操作,那么您将在Clojure的基础上实现一个Lisp,subst可能与本书中的类似。但是,如果您想要实现在Lisp中常用的subst,这里所示的代码将无法实现。
尽管Clojure具有cons和nil?函数,但它们的含义与Common (resp )并不相同。cons和null):详细信息请参见clojure:没有反单元格。在翻译subst之前,您必须确定在Clojure中应该做什么。
通常,subst用于转换由cons单元格组成的树;例如,请注意,subst不递归为向量、字符串等。在这些树中,树的特定子集是Lisp形式的树。实际上,subst的一个重要用例是在代码生成过程中搜索和替换表单。
据我所知,如果您将自己限制为Clojure Cons类型,您将不支持代码作为数据。因为Clojure代码也使用向量和映射,所以您可能需要递归到这些对象中。因此,如何翻译subst并不是一个容易的问题。
一个可能的起点是读取LispReader.java,以确定构成AST的对象集,并查看您想要执行的代码类型。
我的建议是先独立学习这些语言。有了一点经验,你将有一个更好的方式来了解他们之间有多么相似和有多不同。
发布于 2020-04-06 19:08:00
方案版本的翻译可能如下所示:
(defn my-subst [new old data]
(when-not (nil? data)
(cond (sequential? data) (cons (my-subst new old (first data))
(my-subst new old (next data)))
(= data old) new
:else data)))
user> (my-subst 1 :x '(1 2 :x (:x 10 :x [:x :z :x])))
;;=> (1 2 1 (1 10 1 (1 :z 1)))这是相当接近的(虽然不完全相同,因为有多个本机集合类型,这使您面临这样的选择:哪些应该被认为是要替换的目标)。此示例处理'listy‘(顺序)结构,同时省略散列映射和集合。另一个问题是保留原始序列的类型和形式,这并不像听起来那么简单(例如(into (empty (list 1 2 3)) (list 1 2 3)) => (3 2 1) )。
所以你要做的是,首先决定替换的语义,而在方案中,它只是一个自然的列表处理。
对于已经提到的clojure.walk,使用它进行替换的最简单方法可能是
(defn subst [new old data]
(clojure.walk/prewalk-replace {old new} data))
user> (subst :z :x [1 :x 3 '(:x {:a :x}) #{:x 1}])
;;=> [1 :z 3 (:z {:a :z}) #{1 :z}]https://stackoverflow.com/questions/61056834
复制相似问题