Algorithm 列出列表的笛卡尔积及其本身
所以我有一个完整的代码要解释,但这部分对我来说没有意义,有人能给我解释一下吗?我知道列表iter在您希望看到列表中的每个元素完成某些操作时使用,但我很难遵循此处的路径。让我们假设Algorithm 列出列表的笛卡尔积及其本身,algorithm,function,clojure,Algorithm,Function,Clojure,所以我有一个完整的代码要解释,但这部分对我来说没有意义,有人能给我解释一下吗?我知道列表iter在您希望看到列表中的每个元素完成某些操作时使用,但我很难遵循此处的路径。让我们假设slist iter执行您解释为list iter的行为,即“当您希望看到列表中的每个元素完成某些操作时使用” 现在,我将向您展示另一种使用Clojure核心函数进行笛卡尔积的方法,这样我可以为您指出可能会让您困惑的关键元素 (defn slist笛卡尔[lst] (doseq[x lst y lst] (println
slist iter
执行您解释为list iter
的行为,即“当您希望看到列表中的每个元素完成某些操作时使用”
现在,我将向您展示另一种使用Clojure核心函数进行笛卡尔积的方法,这样我可以为您指出可能会让您困惑的关键元素
(defn slist笛卡尔[lst]
(doseq[x lst
y lst]
(println x y)))
这就是doseq
所做的。你们可以读它,比如lst中的每个x,lst中的每个y,打印x和y
现在,这里的关键部分是,您正在为x
和y
重复lst
。这样我们就得到了lst
与lst
的笛卡尔积
这正是您显示的代码所做的。它使用lst
作为两个slistiter
调用要处理的列表
要明白,每次从一开始就需要处理列表,以得到你想要的:笛卡尔积
现在,您可以通过doseq表达式和slist iter函数来实现这一点
可能您需要理解为什么您可以以slist iter的形式进行操作
这是可能的,因为fn
创建了一个函数,并且该函数是“这意味着“它”可以访问创建函数时范围内的所有变量”
这意味着调用第一个slist iter
时,正在使用fn
创建的函数slist cartesian
可以访问参数lst
。让我们将该函数称为匿名函数
每当第一个slist iter
开始处理lst
的新元素时,将再次调用该匿名函数,但lst
将与后者创建前者时接收和使用的slist笛卡尔
相同
我希望这回答了你的问题
如果你还想对这个主题进行更多的思考和挖掘,还有另一种思考方法,那就是一步一步地构造函数 用你自己的话来说
(defn slist笛卡尔[lst]
(slist iter)
lst;;包含元素的列表
对列表中的元素执行的操作
))
要做的事情是一个函数,它接收1参数。该函数将被调用,作为参数传递列表的一个元素,列表中的所有元素一次传递一个元素
如果我们将函数设为println
,它将多次调用它,列表中每个元素调用一次,并将该元素作为参数。这意味着它将打印整个列表,一次打印一项:
(defn slist-cartesian [lst]
(slist-iter
lst
(fn [x]
(slist-iter
lst
(fn [y]
(println x y))))))
当您需要向打印内容添加更多信息时会发生什么情况?您需要一个比简单的println
更复杂的函数
让我们创建一个函数,该函数将为列表中的每个项目添加一个文本前缀并打印它们。让我们在文本前面加上前缀“number:”
。因为我们有slistiter
,我们只需要解决文本前缀为单个数字的问题,函数只有一个参数,因此它可以被slistiter
使用,从而解决列表中所有元素的问题。让我们把这个解决方案变成一个函数:
(defn前缀文本编号和打印[x]
(打印号码:x)
现在,让我们使用它来构建一个函数,该函数为列表中的所有元素添加前缀“number:”
,并打印它们。让我们调用该函数为每个
添加文本编号前缀:
(每个[lst]的defn前缀文本编号)
(slist iter)
lst
前缀(文本编号和打印)
(在每个“(1 2 3)”前面加上文本编号)
;; 编号:1
;; 编号:2
;; 电话:3
酷。但是如果我们需要更改前缀的文本,会发生什么呢?这意味着需要通过为前缀添加一个参数来通用函数前缀文本编号和打印。但这将使该函数对slistiter
无效。然后呢
我们将要做的是创建一个广义函数,然后以某种方式从中导出一个精确时刻所需的特殊函数
(defn slist-cartesian [lst]
(slist-iter
lst
println
))
(slist-cartesian '(1 2 3))
;; 1
;; 2
;; 3
因此,对于即将推出的函数为每个
添加前缀文本,我们将执行以下操作:
(为每个[prefix,x]定义前缀文本)
(slist iter)
lst
(以某种方式派生函数前缀文本和打印前缀));;注意
有许多方法可以当场创建函数。您已经在显示的代码中为此使用了一个工具。您正在使用函数fn
就地构建函数。另一种方法是使用函数partial
。让我们首先探索部分
选项
为此,我将执行为文本添加前缀并打印
,这与我对为文本编号添加前缀并打印
所做的操作相反。我将专门研究它。我将根据前缀文本和打印
定义前缀文本编号和打印
。首先用手,然后用partial
:
;;手工
(defn前缀文本编号和打印[x]
(前缀文本和打印“编号:”x)
;; 使用部分
(def前缀文本编号和打印)
(部分前缀文本和打印“编号:”)
两个定义产生相同的结果:一个函数。注意,最后一个使用def
而不是defn
使用partial的定义很简单
(defn prefix-text-and-print [prefix, x] ;; Generalized function
(println prefix x))
(def print-2-lsts-combined [a-lst b-lst]
(slist-iter
b-lst
(partial prefix-list-and-print a-lst)))
(print-2-lsts-combined '(1 2 3) '(10 20 30))
;; 1 10
;; 1 20
;; 1 30
;; 2 10
;; 2 20
;; 2 30
;; 3 10
;; 3 20
;; 3 30