Intro
- named references (symbol) to values of fn
- they live in a namespace
- mutable reference to an immutable value
Var is separate from the value so you can redefine it
Note: symbol is just name
Dig Deeper
Functions are actually stored in vars
(defn greet [name] (str "hello" name))
; is equal to
(def greet (fn [name] (str "hello" name)))
; because defn is macro
Enter fullscreen mode Exit fullscreen mode
Dynamic vars
Allows temporary thread-local bindings
(def ^:dynamic *debug* false)
; temporarily change it
(binding [*debug* true]
(prinlnt *debug*))
Enter fullscreen mode Exit fullscreen mode
Metadata
(def ^{:doc "A counter"} counter 0)
Enter fullscreen mode Exit fullscreen mode
Symbol vs Var
Symbol
Pice of code that names something
(type 'x)
;; => clojure.lang.Symbol
Enter fullscreen mode Exit fullscreen mode
Writen as 'x
Exists in code and data
Var
Runtime object that point to immutable value
Written as #’x or (var x)
Exists at runtime
Symbol ──▶ Var ──▶ Value
x ──▶ #'user/x ──▶ 42
Example explained
(def x 43)
x
; 43
Enter fullscreen mode Exit fullscreen mode
In the code
- find the symbol
- resolve it to var
#'user/x - dereference var
- produce 42
Dig Deeper
Note symbol can refere to local binding (not a Var) or local variable
; local binding
(let [x 10]
x)
; local variable
(fn [x] x)
Enter fullscreen mode Exit fullscreen mode
Immutability
Vars are mutable
The values they point are (usually immutable)
The var can change what it points to the data/vale cannot change
Imagine a program without vars
we have immutable values but no way to give them names
Vars and namespaces
Namespace is mapping from symbols to vars
Namespace is object that contains vars
(ns math)
; internaly
; pi --> var
; inc --> var
Enter fullscreen mode Exit fullscreen mode
Referring to another namespace
(ns animals)
(def dog "Labrador")
(ns zoo
(:require [animals]))
animals/dog ;;
(ns zoo-2
(:require [animals :as a])) ; aliases
a/dog ; shorthand for animals/dog
(ns zoo-2
(:require [animals :refer [dog]])) ; refering vars
dog ; shorthland for a/dog
Enter fullscreen mode Exit fullscreen mode
Dereferencing
Var fully qualified name includes namespace: math/pi or user/x
Example
(def x 42)
Enter fullscreen mode Exit fullscreen mode
When evaluating steps
- find var
- deref var
- 42
you can also do dereferencing by:
@#'x
; or
(deref #'x)
Enter fullscreen mode Exit fullscreen mode
Evaluation pipeline simplify
Examples
(double-it x)
Enter fullscreen mode Exit fullscreen mode
Soruce code contains symbols (double-it x)
Symbols is name (‘x, it has type clojure.lang.Symbol)Compiler resolve namespace
What does the symbol x refer to in the current namespace
So we get namespace-name/x var
Note: namespace dosen’t store values it stores varsVar is runtime object so it dereferences it to get values
Invocation (of the function or the value)
Why we have vars, what not directly have values, because with vars we have
- redefintion (REPL)
- metadata
- dynaming binding
Dig Deeper
Special Symbols
‘ — Quote
Dont evaluate this treat it as data
Example
(def x 42)
Enter fullscreen mode Exit fullscreen mode
This means
- Resolve symbol
- Find the var
- Return it value
'x
; => x
Enter fullscreen mode Exit fullscreen mode
This means
- Return symbol
#’ — Var Quote
Resolve this symbol to its Var
Example
(def x 42)
#'x
;; => #'user/x
Enter fullscreen mode Exit fullscreen mode
The result is not 42
the result is the Var object
To get a value you can dereference it using @
@#'x
;; => 42
; or
(deref #'x)
Enter fullscreen mode Exit fullscreen mode
When to use it
- Metadata is attached to the Var
- Testing and mocking
- Implementing macros
- Dynamic Vars and advanced runtime features
답글 남기기