Clojure Koans 23 Meta Notebook
Original Clojure Koans: https://github.com/functional-koans/clojure-koans/
Spoilers Alert
{:deps {org.clojure/clojure {:mvn/version "1.10.1"} ;; complient is used for autocompletion ;; add your libs here (and restart the runtime to pick up changes) compliment/compliment {:mvn/version "0.3.9"}}}{:hello (clojure-version)}Initial Thoughts
When and where is using meta beneficial to me as a writer of Clojure?
(def giants (with-meta Giants {:league "National League"}));; skill 23001: Tag an object with meta data by using the `with-meta` function (?);; question 23001: What role & function does `'Giants` play here?;; question 23002: What is the structure of the object returned by `with-meta`?;; question 23003: What is meant by "object" in the context of the input for `with-meta`? reference: https://clojuredocs.org/clojure.core/with-meta;; "Some objects can be tagged using the with-meta function"(= {:league "National League"} (meta giants));; skill 23002: Access an object's meta data by using the `meta` function (?);; "Or more succinctly with a reader macro"(= {:division "West"} (meta {:division "West"} Giants));; question 23004: What role does `Giants` play here? It appears to be a symbol. Might it be a local binding of sorts? Does it function as an object?;; guess 23004a: It appears that a reader macro for assigning/tagging meta-data to an object is being used to assign a meta-tag hashmap to the symbol `Giants` (?), and then that meta-data is read/accessed by the `meta` function;; "While others can't"(= "This doesn't implement the IObj interface" (try (with-meta 2 {:prime true}) (catch ClassCastException e "This doesn't implement the IObj interface")));; question 23005: Is the IObj interface a Java thing, a Clojure thing, both, or neither?;; question 23006: Supposedly, the `with-meta` functon cannot assign meta-data to things (objects?) that do not implement the clojure.lang.IObj interface - What are the things that do not implement clojure.lang.IObj? What are the things that do? How can one programmatically determine if something implements clojure.lang.IObj?;; "Notice when metadata carries over"(= {:foo :bar} (meta (merge {:foo :bar} {:a 1 :b 2} {:b 3 :c 4})));; question 23007: What exactly is happening here? What is meant by "carries over"?;; question 23008: To what is the meta-data here being assigned?;; "And when it doesn't"(= nil (meta (merge {:a 1 :b 2} {:foo :bar} {:b 3 :c 4})));; question 23009: What exactly is happening here?;; "Metadata can be used as a type hint to avoid reflection during runtime"(= \C ((.charAt String % 0) "Cast me"));; skill 23003: Use metadata as a type hint to avoid reflection during runtime (?);; question 23010: What is a "type hint" in the above context?;; question 23011: What is "reflection" in Clojure? Please show concise/concrete/clear examples.;; question 23012: What is "reflection during runtime"? Please show a couple concise/concrete/clear examples.;; question 23013: How is this different than `(.charAt "Cast me" 0)`?;; "You can directly update an object's metadata"(= 8 (let [giants (with-meta Giants {:world-series-titles (atom 7)})] (swap! (:world-series-titles (meta giants)) inc) (:world-series-titles (meta giants))));; question 23014: What does the `@` (at) sign prefix stand for?;; "You can also create a new object from another object with metadata"(= {:league "National League" :park "AT&T Park"} (meta (vary-meta giants assoc :park "AT&T Park")));; skill 23004: Create a new object from another object with metadata by using the `vary-meta` function;; "But it won't affect behavior like equality"(= giants (vary-meta giants dissoc :league));; question 23015: What do they mean by "it", and how so will "it" not affect behavior like equality?;; question 23016: What exactly is happening here, and what kind of issue is this & when does it occur? (human error, syntax, etc., at read, compilation, runtime, etc.);; "Or the object's printed representation"(= (pr-str Giants) (pr-str (vary-meta giants dissoc :league)));; question 23017: What does `pr-str` do exactly?;; question 23017a: It seems to cast/convert to string type with some differences from the `str` function. from the docs: "pr to a string, returning it" source: https://clojuredocs.org/clojure.core/pr-str;; question 23018: What does the `pr-str` stand for?;; answer 23018a: Well... `pr` stands for `pr`, from the docs:;; Prints the object(s) to the output stream that is the current value;; of *out*. Prints the object(s), separated by spaces if there is;; more than one. By default, pr and prn print in a way that objects;; can be read by the reader;; source: https://clojuredocs.org/clojure.core/pr-strClosing Thoughts
Reading the docs lately has been more fun for me. It feels less like gibberish, and more like sage wisdom.
For next time:
[ ] Mine docs for skills: https://clojuredocs.org/clojure.core/pr-str
[ ] Demo turning data into a string: https://clojuredocs.org/clojure.core/pr-str#example-542692cbc026201cdc326c20
[ ] Demo turning string into data: https://clojuredocs.org/clojure.core/pr-str#example-542692cbc026201cdc326c20
[ ] Serialize an object to disk: https://clojuredocs.org/clojure.core/pr-str#example-542692d4c026201cdc327033
[ ] Read docs on `pr`: https://clojuredocs.org/clojure.core/pr
[ ] Find workaround to stringify the result of threading lazy sequences with side-effects where you could get undesired doubling: https://clojuredocs.org/clojure.core/pr-str#example-5a5e020ee4b0a08026c48cf7
[ ] Find workaround to stringify lazy sequence results without side-effects where `str` would result in a `clojure.lang.LazySeq` object: https://clojuredocs.org/clojure.core/pr-str#example-5a7a4adee4b0e2d9c35f741f
[ ] Find workaround to global var print-length limit: https://clojuredocs.org/clojure.core/pr-str#example-5ac34d90e4b045c27b7fac30