2017-04-18 3 views
2

ich eine Matrix verwende wie folgtclojure.core.matrix :: Mutate Element in der Matrix

(require '[clojure.core.matrix :as ccm]) 
(def M (ccm/matrix [[1 2] [3 4]])) 
(ccm/mset! M 0 0 10) 

Allerdings wirft dies ein Fehler

Illegal Keine Implementierung der Methode: Set-2d! Protokoll: # 'clojure.core.matrix.protocols/PIndexedSettingMutable für die Klasse gefunden: clojure.lang.PersistentVector clojure.core/-cache-Protokoll-fn (core_deftype.clj: 568)

Allerdings sollte diese Arbeit nach dem Wiki https://mikera.github.io/core.matrix/doc/clojure.core.matrix.html#var-mset.21

Antwort

1

core.matrix kann verschiedene zugrunde liegende Matriximplementierungen verwenden. Standardmäßig verwendet es die persistent-vector-Implementierung, was bedeutet, dass Matrizen einfach Clojure-Vektoren sind, die Clojure-Vektoren enthalten. Clojure Vektoren sind jedoch unveränderlich, so dass mset! nicht auf ihnen funktioniert. Dies ist das erwartete Verhalten.

Um mset! zu verwenden, müssen Sie eine der core.matrix-Implementierungen verwenden, die veränderbare Matrizen erstellen können. ndarray ist die Matriximplementierung, die in core.matrix standardmäßig immer verfügbar ist, aber Sie müssen core.matrix mitteilen, dass Sie sie verwenden möchten.

user=> (use 'clojure.core.matrix) 
nil 
user=> (matrix [[1 2] [3 4]]) 
[[1 2] [3 4]] 

So sieht eine persistente Vektormatrix aus.

Sie können, indem ein zusätzliches Keyword an die matrix Funktion eine ndarray Matrix erstellen:

user=> (def M (matrix :ndarray [[1 2] [3 4]])) 
#'user/M 
user=> M 
#object[clojure.core.matrix.impl.ndarray_object.NDArray 0x561ddbde "[[1 2] [3 4]]"] 

Jetzt mset! arbeiten:

user=> (mset! M 0 0 10) 
10 
user=> M 
#object[clojure.core.matrix.impl.ndarray_object.NDArray 0x561ddbde "[[10 2] [3 4]]"] 

Hinweis, die Elemente auf der rechten Seite vorbei. Sie können auch pm verwenden, um eine schönere Darstellung zu erstellen:

user=> (pm M) 
[[10 2] 
[ 3 4]] 

Um den Standard zu machen ndarray verwenden set-current-implementation:

user=> (set-current-implementation :ndarray) 
:ndarray 

user=> (def M (matrix [[1 2] [3 4]])) 
#'user/M 

user=> M 
#object[clojure.core.matrix.impl.ndarray_object.NDArray 0x5cd44e57 "[[1 2] [3 4]]"] 

user=> (mset! M 0 0 10) 
10 

user=> M 
#object[clojure.core.matrix.impl.ndarray_object.NDArray 0x5cd44e57 "[[10 2] [3 4]]"] 

Es gibt mehrere andere Implementierungen zur Verfügung, wenn sie sich als Abhängigkeiten (zB Set in Dein Leiningen project.clj). Einige von ihnen unterstützen sowohl veränderbare als auch unveränderliche Matrizen.

Übrigens, wie amalloy vorgeschlagen, können Sie eine veränderbare Matrix aus einer unveränderlichen Matrix erhalten, indem Sie die unveränderliche Matrix an mutable übergeben. Wenn Sie dies mit einer persistenten Vektormatrix tun, ist die zurückgegebene Matrix keine persistente Vektormatrix, da es keine veränderbaren persistenten Vektormatrizen gibt.Die neue Matrix wird eine Matrix aus einer anderen Implementierung sein. Welche Implementierung verwendet wird, hängt von Ihrer aktuellen Umgebung ab, aber wenn Sie nichts Besonderes getan haben, sollte eine ndarray-Matrix das sein, was zurückgegeben wird.

1

diese

Nein zur Wiki nach sollte jedoch arbeiten, der Link eindeutig vorgesehen besagt, dass es eine Ausnahme ausgelöst wird, wenn die Matrix nicht wandelbar ist. Die Dokumentation für matrix ist nicht klar, ob es eine veränderbare Matrix erzeugt oder nicht, aber offensichtlich nicht. Es ist jedoch nicht schwer, eine Möglichkeit zu finden, eine veränderbare Matrix zu erzeugen: Die Funktion mutable ist genau dort auf der gleichen Seite.

Verwandte Themen