Skip to content

Latest commit

 

History

History

22-follow-along-links

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

Follow Along Links

Quickstart

clj -M:dev

-M assumes your using a Clojure Tools version greater than 1.10.3.855. Not sure what version your on? Run clj -h and you should see output near the top of the output like:

➜ clj -h
Version: 1.10.3.855 # this is the version your on

Visit site at http://localhost:9000

Learnings

Macros

(-> highlight .-style .-width)

I found myself writing the above a bunch and wondered if I could explore different ways of doing this in Clojure. I found two options that I wanted to explore:

  1. Macros
  2. Google Closure Library

Here what each of the solutions looked like:

Macro

To start, don't jump to macros. I was just trying to understand them better and compare against other solutions, but its a powerful tool that we can reserve for other times. What was interesting with Macros is I found it hard to get it to work initially. So here is an overview:

Broken Macro

;; I do not work
(defmacro get-attr
  [el attr]
  `(let [element#   ~el
         attribute# ~attr]
     (attribute# element# )))

Working Macro

;; I work
(defmacro get-attr
  [el attr]
  `(~attr ~el))

;; I work
(defmacro get-attr [i e]
(let [prop-sym i
      obj-sym e]
  (list prop-sym obj-sym)))

Lets break it down the first one that works

  1. The list is quoted - essentially telling clojure compiler not to evaluate the list or its items. Just return itself.
  2. At compile time, evaluate ~attr and ~el Which means our code now looks like this at the end of compile time:
(.-style element)

Okay, now compare to the very first example. So what was happening in the first example? Again, the whole thing is quoted, but the error happens here:

(let [element#   ~el
      attribute# ~attr])

Essentially the above is the equivalent of trying to do

(let [my-local .-style])

or

(def my-global .-style)

What is the problem with the above? Well, its because we were trying to evaluate an instanceField

(def my-global .-style)

The abvoe is going to break because each of the items is evaluated one at a time. first, the def. then the my-global and then .-style. Normally, the evaluator expects something with .- to be at the front of a list and have

The question is, what is .-. The answer is that the . dot part of it is special and reserved in clojure for interop. That's why it's not going to work.

After all the above, I believe the cleanest way might be the doto

(set! (-> highlight .-style .-width) (make-hw-val width))
(set! (-> highlight .-style .-height) (make-hw-val height))
(set! (-> highlight .-style .-transform) (make-trans-val left top)))))
(doto
  (-> highlight .-style)
  (set! -width (make-hw-val width))
  (set! -height (make-hw-val height))
  (set! -transform (make-trans-val left top))))))

Resources

https://cljs.github.io/api/syntax/dot

http://clojurescriptmadeeasy.com/blog/js-interop-property-access.html

https://clojure.org/guides/weird_characters