Clojure id-mat函数else分支使用n(矩阵尺寸)的疑问
关于Clojure
id-mat 函数中分支逻辑的疑问 我正在阅读《Clojure for Machine Learning》一书,对其中id-mat函数的部分逻辑存在疑问。相关代码如下:
(defn square-mat "Creates a square matrix of size n x n whose elements are all e. Accepts an option argument for the matrix implementation" [n e & {:keys [implementation] :or {implementation :persistent-vector}}] (let [repeater #(repeat n %)] (matrix implementation (-> e repeater repeater)))) (defn id-mat "Creates an identity matrix of n x n size" [n] (let [init (square-mat :clatrix n 0) identity-f (fn [i j n] (if (= i j) 1 n))] (cl/map-indexed identity-f init)))
在id-mat函数中,我不理解逻辑(if (= i j) 1 n),为什么else分支要使用代表矩阵尺寸的n?
嘿,这个问题抓得真准——第一眼看到这段代码确实会困惑,毕竟单位矩阵的非对角线元素明明应该是0啊!
其实这是书中代码的一个笔误,逻辑完全写错了,咱们来拆解清楚:
- 首先看
id-mat里的init变量:它调用square-mat生成了一个n×n的全0矩阵,这一步的目的就是为了生成单位矩阵的“基底”——单位矩阵只需要把对角线位置改成1,其余保持0就行。 - 然后看
identity-f这个匿名函数,它是给cl/map-indexed用的,作用是遍历矩阵的每个位置(i,j),返回对应的值。按照单位矩阵的定义,当i=j(对角线位置)时返回1,其他位置应该返回0,而不是n。 - 如果保留当前代码里的
n,那生成的矩阵会是对角线为1、其余位置全是矩阵尺寸值的奇怪矩阵,完全不符合单位矩阵的定义。比如n=3的话,得到的会是:
这显然不是我们想要的单位矩阵。[[1 3 3] [3 1 3] [3 3 1]]
所以正确的代码应该把else分支的n改成0,同时把第三个参数改成下划线(Clojure里用来表示“忽略该参数”的惯用写法),也就是:
identity-f (fn [i j _] (if (= i j) 1 0))
内容的提问来源于stack exchange,提问作者nenad
相关产品推荐
相关产品推荐

