What does the clojure syntax '[] mean? - clojure

'() is a syntax sugar for (quote ()). But what does '[] mean? Quote a vector?
For example:
(use '[clojure.test :as t])
(.get '[a b c] 1)
(.containsAll '[a b c] '[b c])
((fnth 5) '[a b c d e])

Precisely. ' is a synonym for quote, so
'[a b c]
is just
(quote [a b c])
quote prevents evaluation of a Clojure code, so quoting the whole vector is essentially the same as quoting every single element of it:
['a 'b 'c]
It allows you to produce a vector of symbols, without explicitly calling symbol function:
[(symbol "a") (symbol "b") (symbol "c")]

Related

define-values macros in Clojure

Is it possible to write a define-values macros in Clojure?
Racket language provides such a thing like define-values form which acts in this way
(define -values '(a b c) (1 2 3))
Where a, b, c are global variables now.
How can I do it in Clojure?
(defmacro defvar [x y]
`(let [a# ~x
b# ~y]
(def b# a#)))
(println (defvar 'a 2))
=> #'user/b__2__auto__
;;;It binds the value to auto generated symbol
define-values doesn't make any sense in Clojure. It makes sense in Racket because values lets one expression evaluate to multiple values. In Clojure, an expression always evaluates to exactly one value: there's no values to extract into definitions.
Of course, you can write a macro def-several-things such that
(def-several-things [x y] [1 2])
expands to
(do (def x 1)
(def y 2))
but this is less readable, not more, so nobody does it.

How to bind function variables to current scope of execution in Clojure?

Given:
(defn some-fn
[]
(let [a 1
b 2
c (+ a b)]
(println c)))
and given that there are multiple such functions, where:
a and b have different values;
c is always equal to (+ a b)
is there a way to extract c without making it a function, which accepts a and b as arguments. So, I don't want:
(defn c-outside
[a b]
(+ a b))
(defn some-fn
[]
(let [a 1
b 2
c (c-outside a b)]
(println c)))
but ideally, something like:
(defn c-outside
[]
(+ a b))
(defn some-fn
[]
(let [a 1
b 2
c (c-outside)]
(println c)))
Is there a way to make c-outside look for the values of a and b in the context, in which it is called? Do I need a macro for that?
there is a way to do it using dynamic bindings:
user> (def ^:dynamic a 10)
#'user/a
user> (def ^:dynamic b 20)
#'user/b
user> (defn c-outside []
(+ a b))
user> (defn some-fn []
(binding [a 1
b 2]
(c-outside)))
#'user/some-fn
user> (some-fn)
;;=> 3
user> (c-outside)
;;=> 30
the trick is that you can temporarily rebind some dynamic vars for the 'duration' of some scope.
This is mostly used in clojure for concurrent programming: the dynamically bound vars keep their values in the threads, spawned from inside the block (as far as i remember)
Otherwise, i see more potential harm from this feature, than the profit, since it obscures the code, adding some unneeded implicit behaviour.
Also as far as i know, this is one of the most arguable features in lisps (in common lisp, to be more specific)
Almost in any case it is better to pass a and b values explicitly to the summing function, since it makes in clean and therefore testable, and helps to reason about it's correctness and performance, and increases readability
you could also think of using macro for that, like this for example:
user> (defmacro c-outside-1 []
`(+ ~'x ~'y))
#'user/c-outside-1
user> (defn some-fn-1 []
(let [x 1
y 2]
(c-outside-1)))
#'user/some-fn-1
user> (some-fn-1)
;;=> 3
but that idea is obviously even worse.

Clojure macros: resolving vars

I can seem to wrap my head around macros in Clojure. I'm probably missing something basic. First, allow me to describe an example of what I want.
(defmacro macrotest [v] `(d ...))
(def a '(b c))
(macroexpand-1 '(macrotest a))
; => (d (b c))
In other words, the var passed to macrotest is resolved, but not evaluated further.
Providing the macro with the value of the var works:
(defmacro macrotest [v] `(d ~v))
(macroexpand-1 '(macrotest (b c)))
; => (d (b c))
But providing the var does not:
(def a '(b c))
(macroexpand-1 '(macrotest a))
; => (d a)
Is it possible to resolve a var in Clojure macro, but not evaluate its value?
EDIT: What I want seems to be possible with eval:
(defmacro macrotest [v] `(d ~(eval v)))
(def a '(b c))
(macroexpand-1 '(macrotest a))
; => (user/d (b c))
Its important to understand that macros evaluate at compile time, not at runtime.
at compile time var a does not yet have a value, so its value is not passed to the macro, only its name. However, when you explicitly pass the "value" - well, then it exists at compile time, and you see that it "works".
Lexical environment
Using eval inside a macro is bad practice. Sure, the following works:
(macroexpand-1 '(macrotest a))
; => (user/d (b c))
... but then, this does not work as expected:
(macroexpand-1 '(let [a "oh no"]
(macrotest a)))
; => (user/d (b c))
Surely you would like the macro to evaluate a as it was defined locally, not using the global variable bound to it, but you cannot because the macro does not evaluate v in the right lexical context. And this is the key to understanding macros: they take code and produce code; any data manipulated by that code is not available to you yet. In other words, the moment at which macros are expanded might be totally unrelated to the time their resulting code is evaluated: anything you evaluate while a macro is being executed is probably evaluated too soon w.r.t. the relevance of your data.
What do you want to do?
There is a form named macrotest which should accepts an argument, v and then perform as-if you had form d applied to it. But:
(macrotest (b c)) should not evaluate (b c), just copy it untouched to produce (d (b c)).
(macrotest a) should evaluate a, which results in a quoted form, and place that form in the resulting code, also returning (d (b c)).
You have a problem here, because the meaning changes radically in one or the other case. Either you evaluate an argument, in which case you must quote (b c) and you write:
(defmacro macrotest [v] `(d ~v))
... which requires that d is ready to handle quoted arguments; or you are okay with the argument being not evaluated.
With the same d as above, you can quote the argument explicitly:
(defmacro macrotest [v] `(d '~v))
However, if d itself is a macro that does not evaluate its argument, you have to avoid the quote in front of ~v.

Nested function arguments with partials

I have this function definition, but I was wondering if it was possible to do this with just a def and higher order functions (i'd like the result to take args in the same order)
(defn f1
[a b c]
(f2
(partial f3 a)
b c))
f2 and f3 look like (keeping arguments relevantly named):
(defn f2
[f b c]
(my-fn-using f b c))
(defn f3
[a x c]
(another-fn-using a x c))
I'm not a 100% sure I understand what you are asking, but here's my take on an answer.
Converting f1 to a HOF could involve modifying it to take the arguments [f g a b c] and calling it using f and g as my-fn-using and another-fn-using.
(defn f1 [f g a b c]
(f (partial g a) b c))
You would then call it as:
(f1 my-fn-using another-fn-using a b c)
Which would be applied as:
(my-fn-using (partial another-fn-using a) b c)
The reason that I'm not sure if this is what you are looking for is that you mention "nested function arguments", but I don't see where those are. Missing arguments for another-fn-using come from inside my-fn-using when the former is called, and the latter gets its arguments directly.
For example:
(defn my-fn-using [f b c]
(let [x [:b b]]
;; do stuff using b and/or c
(f x c)))
(defn another-fn-using [a x c]
;; do other stuff using a x c
[a x c])
;; call f1
(f1 my-fn-using another-fn-using 1 2 3)
;; or create a partially applied function that takes [a b c]
(def f (partial f1 my-fn-using another-fn-using))
(f 1 2 3)

Quoting Confusion

Why does this series of clojure commands return false and not true? What is the difference between the result of statement 1 "C" and 2 "(quote C)"?
; SLIME 2009-03-04
user> ('A 'B 'C)
C
user> (last '('A 'B 'C))
(quote C)
user> (= ('A 'B 'C) (last '('A 'B 'C)))
false
This question is somewhat similar to How does clojure's syntax-quote work?
In Clojure (and other Lisps) the ' is a shortcut for the form (quote ...). So when Clojure sees this:
('A 'B 'C)
which is "translated" by the reader into:
((quote A) (quote B) (quote C))
Each of those quote forms evaluates to a symbol, so (quote A) evaluates to the symbol named A. In Clojure, symbols are functions and can be applied, so ((quote A) (quote B) (quote C)) is actually a function call. From the docs:
"Symbols, just like Keywords, implement IFn for invoke() of one argument (a map) with an optional second argument (a default value). For example ('mysym my-hash-map :none) means the same as (get my-hash-map 'mysym :none)."
So what happens is that C is the default value and that's why it's returned.
Meanwhile, this
'('A 'B 'C)
is translated by the reader into
(quote ((quote A) (quote B) (quote C)))
Which is actually a list of three elements, each of which is a list of two elements, the symbol quote and another symbol (in this case A, B, C).
So, (last '('A 'B 'C)) is actually (quote C). That's the difference between those two results, C is the symbol with the name C while (quote C) is a list of two elements.
You can confirm this:
user=> (class ('A 'B 'C))
clojure.lang.Symbol
user=> (class (last '('A 'B 'C)))
clojure.lang.PersistentList
user=>
Hope that's clear!
('x 'y) is very unusual, for just this reason. Usually you want '(x y), which is a list of the literal symbols x and y. If you quote TWICE with '('x 'y), you get a list with (quote x) instead: the literal symbol quote, followed by the literal symbol x.