Created
January 9, 2016 02:30
-
-
Save rwilson/95b33fdbd503dc3775a0 to your computer and use it in GitHub Desktop.
Beware dissociating declared record fields
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; tldr; If you treat a record as a map and dissoc a property, clojure converts the | |
;; record to a PersistentArrayMap under the hood. | |
;; Example by way of a repl session | |
user> (defrecord Foo [bar baz]) ;; Define our record type | |
user.Foo | |
user> (map->Foo {:bar 1}) ;; Create a Foo... | |
#user.Foo{:bar 1, :baz nil} | |
user> (update *1 :bar inc) ;; Modify a Foo... | |
#user.Foo{:bar 2, :baz nil} | |
user> (assoc *1 :baz "foobar") ;; it's all still a Foo! | |
#user.Foo{:bar 2, :baz "foobar"} | |
user> (.bar *1) | |
2 | |
;; Ok, let's get wild: | |
user> (assoc *1 :xyz 123) ;; We can assoc an undeclared property, and remain a Foo. | |
#user.Foo{:bar 2, :baz "foobar", :xyz 123} | |
user> (dissoc *1 :xyz) ;; We can dissoc an undeclared property, and remain a Foo. | |
#user.Foo{:bar 2, :baz "foobar"} | |
user> (dissoc *1 :baz) ;; But, if we dissoc a declared property... | |
{:bar 2} ;; ...now it's not a Foo, it's just a map | |
;; So, if you're doing to dissoc a declared property, be aware that after doing so | |
;; you will only have a map, which means that the type'd way of accessing declared | |
;; fields, e.g. `(.bar *1)` is no longer an option. | |
;; And if you try... | |
user> (.bar *1) | |
IllegalArgumentException No matching field found: bar for class clojure.lang.PersistentArrayMap | |
clojure.lang.Reflector.getInstanceField (Reflector.java:271) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment