Clojure 修改向量,以便可以使用两个参数调用它
我在Clojure中玩一个矩阵实现,我这样做是为了好玩,并学习更多关于Clojure的知识,而不是因为我想创建世界上最好、最酷的矩阵实现 像这样的代码中需要的主要操作之一是能够返回矩阵中给定行和列的值,这当然是我作为函数编写的Clojure 修改向量,以便可以使用两个参数调用它,clojure,Clojure,我在Clojure中玩一个矩阵实现,我这样做是为了好玩,并学习更多关于Clojure的知识,而不是因为我想创建世界上最好、最酷的矩阵实现 像这样的代码中需要的主要操作之一是能够返回矩阵中给定行和列的值,这当然是我作为函数编写的 (mat-getrc m 2 3) 表示“给我矩阵m第2行第3列的值”。非常好的Clojure,但冗长且丑陋。我宁愿写信 当然,A)向量(在我的包中,矩阵只是向量)只响应一个参数,B)向量不知道如何使用行号和列号来确定正确的值存储在哪里 从(应该实现哪些向量)来看,似乎
(mat-getrc m 2 3)
表示“给我矩阵m第2行第3列的值”。非常好的Clojure,但冗长且丑陋。我宁愿写信
当然,A)向量(在我的包中,矩阵只是向量)只响应一个参数,B)向量不知道如何使用行号和列号来确定正确的值存储在哪里
从(应该实现哪些向量)来看,似乎存在一个双参数版本的invoke
,但是如何让我的“矩阵”向量实现并响应它呢
任何建议和指向正确的方向都将不胜感激
(def matrix [[1 2 3 4][5 6 7 8][9 10 11 12]])
正如你在问题中所说,这是可能的:
(matrix 2)
但这不是:
(matrix 2 3)
这是获取索引索引的标准方法:
(get-in matrix [2 3])
只需多做几件事,您就几乎可以得到您想要的:
((matrix 2) 3)
您可以定义一个更高阶的函数:
(defn matrix-hof [matrix]
(fn [x y]
(get-in matrix [x y])))
然后将函数而不是矩阵置于函数位置:
(let [m (matrix-hof matrix)]
(m 2 3))
我不相信使用函数或宏就可以实现您的要求。您不能修改向量的调用方式,因为它内置于向量的实现中,但您可以定义自己的类型,该类型封装向量,充当向量,并且可以使用
deftype
以任何方式调用。您需要扩展vectors实现的许多相同接口(这是一个很大的列表):
“矩阵只是正则向量”属性对您有多重要?这就是说——你修改所有向量的工作方式对你来说真的很重要吗,而不是只有一种被认为是矩阵的特定类型的对象(而且,因为你希望它是vector-y,实现接口)?如果所有向量突然开始可以用两个参数调用,这不会困扰我。当我实现它们时,矩阵看起来像
[[3 2]1 2 3 4 5 6]
,其中索引0处的元素本身是一个两元素向量,表示矩阵中的行数和列数,以下元素是按行大顺序排列的矩阵值。今晚早些时候,我正在考虑@ChrisMurphy建议的替代实现(例如[[1 2 3][4 5 6]
)但是,考虑到我当前的实现带来了一些有趣的挑战,我想我会坚持下去。:-@CharlesDuffy:但是,进一步跟进您的评论,我也不介意将特定类型的对象实现为矩阵。当前实现的吸引力在于坚持使用“标准”Clojure类型,其思想是“最好有几个类型和很多功能在它们上面运行,而不是有很多不同类型和每个类型上都有几个功能“。但这对我来说是一个游戏时间项目,我愿意接受任何建议。@BobJarvis如果所有向量开始以这种方式运行,您可能会很高兴,但是如果另一个加载的库希望所有向量开始将两参数IFn调用视为assoc
?例如,('[x y z]1'a)
返回”[x a z]
。乍一看,两者似乎都很合理,但不能共存,这表明对于库作者来说,两者都不是一件合理的事情。相反,按照Charles Duffy的建议去做,为矩阵定义一个单独的类型,它可以完全按照您的要求运行;不要使用纯向量。如果您没有看到它,会做什么你想要。万岁!另一个风车!桑乔-拿出我的长矛!-)我以前没有调查过deftype
-我会调查的。:-)
(let [m (matrix-hof matrix)]
(m 2 3))
user=> (ancestors clojure.lang.PersistentVector)
#{clojure.lang.IEditableCollection clojure.lang.ILookup
java.util.concurrent.Callable java.lang.Runnable clojure.lang.IMeta
java.lang.Comparable clojure.lang.IReduceInit
clojure.lang.IPersistentCollection clojure.lang.IHashEq java.lang.Iterable
clojure.lang.IReduce java.util.List clojure.lang.AFn clojure.lang.Indexed
clojure.lang.Sequential clojure.lang.IPersistentStack java.io.Serializable
clojure.lang.Reversible clojure.lang.Counted java.util.Collection
java.util.RandomAccess java.lang.Object clojure.lang.Seqable
clojure.lang.Associative clojure.lang.APersistentVector
clojure.lang.IKVReduce clojure.lang.IPersistentVector clojure.lang.IObj
clojure.lang.IFn}