If the variables are immutable in Clojure, then why did it allow to redefine the same variable in the following snippet:
(ns tutorial.test-immutability-of-variables)
(defn test_if_variables_are_mutable
[]
(def a 1)
(def a 10)
(println (format "Value of a: %d" a) )
)
(test_if_variables_are_mutable)
The above code compiles and o/p is 10.
Clojure makes a distinction between values and references to values. Clojure guarantees that values are immutable.
Consider what happens when your function is evaluated:
(def a 1)
When the above form is evaluated, a Clojure Var is created (with name a and namespace tutorial.test-immutability-of-variables) and it is bound to the value 1.
(def a 10)
When this form is evaluated, the existing Clojure Var is rebound to the value 10.
Use of def within a function is strongly discouraged. Use def for top level forms only in your code. Alternatively for a lexically bound symbol use let.
The full story of what happens is a bit more involved than I've outlined above, see the reference documentation on Vars. There are other reference types in Clojure, such as Atoms.
As the other answer points out, you can change what the global Var points to, but you cannot change the original value. Here is another example:
(def x 42)
(defn changer-1
[]
(println "changer-1: x - old" x)
(let [x "Goodbye"] ; change a local variable
(println "changer-1: x - new" x)))
(defn caller-1
[]
(newline)
(let [x "Hello"]
(println "caller-1: x - before" x)
(changer-1)
(println "caller-1: x - after " x)))
(defn changer-2
[]
(println "changer-2: x - old" x)
(def x 666) ; reset the global Var (normally bad form)
(println "changer-2: x - new" x))
(defn caller-2
[]
(newline)
(println "caller-2: Var x - before" x)
(let [x "Hello"]
(println "caller-2: x - before" x)
(changer-2)
(println "caller-2: x - after " x))
(println "caller-2: Var x - after" x))
(caller-1)
(caller-2)
with result
-----------------------------------
Clojure 1.10.3 Java 15.0.2
-----------------------------------
caller-1: x - before Hello
changer-1: x - old 42
changer-1: x - new Goodbye
caller-1: x - after Hello
caller-2: Var x - before 42
caller-2: x - before Hello
changer-2: x - old 42
changer-2: x - new 666
caller-2: x - after Hello
caller-2: Var x - after 666
For more information, please see this list of documentation sources, especially "Getting Clojure" and "Brave Clojure"
Related
How does [] work in a function in Clojure?
(def square (fn [x] (* x x)))
(square 10) ; -> 100
As I understand from the above, we pass 10 in the place of x. Shouldn't I be able to do the following?
(def square (fn [x y] (* x y)))
(square 5 10) ; -> 50
In Clojure, [] is used to represent the argument list. That is to say, the anonymous function defined in square takes a single argument and multiplies it against itself.
You can absolutely extend that, but you're probably going to want to change the name of the function to better reflect what it's actually doing instead.
(def multiply (fn [x y] (* x y)))
Some comments on Makoto's answer.
You don't need to name a function in order to use it:
((fn [x] (* x x)) 10) ; 100
((fn [x y] (* x y)) 5 10) ; 50
Anonymous functions often crop up as arguments to higher order functions such as map.
Clojure (and other Lisps) separate the act of making a function as a thing from the act of naming it. def does the naming. A subsequent def for a name erases/obliterates/overwrites an earlier one.
Nor do you need to explicate a function in order to name it. Instead of
(def multiply (fn [x y] (* x y)))
just write
(def multiply *)
There's a lovely explanation of this (for Common Lisp) in Paul Graham's On Lisp.
Until now, I had always assumed that anything you can do in let binding, you can do within the arguments vector for a defn form.
However, I just noticed this -- if I do this with a let binding, it works:
(let [[x & more :as full-list] (range 10)]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
; x: 0
; more: (1 2 3 4 5 6 7 8 9)
; full list: (0 1 2 3 4 5 6 7 8 9)
But if I try to pull it out into a function, I get an exception:
(defn foo [x & more :as full-list]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
; CompilerException java.lang.RuntimeException: Unexpected parameter, compiling:(/tmp/form-init615613631940782255.clj:1:1)
Of note, this works:
(defn foo [[x & more :as full-list]]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
But then I have to pass in the argument as a collection, i.e. (foo [1 2 3]).
Is it possible to define a function that takes a variable number of arguments, and bind the entire group of arguments to a local variable, without specifically using a let binding inside? It strikes me as weird that you can't just do (defn foo [x & more :as full-list] ... Is there a particular reason why this doesn't (or shouldn't) work?
If you want a variable number of args, you are missing an &:
(defn foo [& [x & more :as full-list]]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
Clojure param definition has only one special case that is the & char to indicate a variadic number of arguments. The rest are plain simple named arguments.
Now each simple argument can be destructured using the map or list syntax. For example:
(defn foo [ x y ] ...)
Can be destructured like:
(defn foo [[x1 x2 & x-more :as x] {:keys [y1 y2 y3]}] ...)
So we are saying that we expect the first param to be a list of at least 2 elements and the second param to be a map with some keys. Note that this will still be a fn of two params and that Clojure is not going to enforce that x actually has at least two elements. If x is an empty list, x1 and x2 will be nil.
Coming back to your question, if you look at my answer you will see that my fn has 0 mandatory params, with a variable number of arguments, while the one that you have has 1 mandatory param with a a variable number of arguments. What I am doing is just destructuring the var arg.
I would like to know how to increment by X amount a number, in other languages I used to do
foo += 0.1;
but I have not idea how it can be done in Clojure
Variables are immutable in Clojure. So you should not try to change the value of foo, but instead, "create" a new foo:
(def foo2 (+ foo 0.1))
...or, if in a loop, recur with a new value:
(loop [foo 5.0]
(when (< foo 9)
(recur (+ foo 0.1))))
...or, if foo is an atom, swap! it with a new value:
(def foo (atom 5.0))
(swap! foo (partial + 0.1))
I recommend you start by reading the rationale of Clojure.
Blacksad's answer covers defining vars so I would just like to add the other scopes in which you may wish to have a value that is incremented from another value:
within a function's local scope:
user> (defn my-function [x]
(let [y (inc x)
z (+ x y)]
[x y z]))
#'user/my-function
user> (my-function 4)
[4 5 9]
and If you want to build a value incrementally to make the process more clear:
user> (defn my-function [x]
(let [y (inc x)
z (+ x y)
z (+ z 4)
z (* z z)]
[x y z]))
#'user/my-function
user> (my-function 4)
[4 5 169]
This can make the process more presentable, though it is not a "way to get variables back" and is really only useful in limited contexts. This pattern is used in clojure.core's threading macros.
the other day I was trying to come up with an example of closure in Clojure. I came up with and example I had seen before and thought it was appropriate.
Alas, I was told it was not a good one and that I should provide something with let.
Can anyone shed some light?
(defn pow [x n] (apply * (repeat x n)))
(defn sq [y] (pow y 2))
(defn qb [y] (pow y 3))
A closure is a function that has access to some named value/variable outside its own scope, so from a higher scope surrounding the function when it was created (this excludes function arguments and local named values created within the function). Your examples do not qualify, because every function just uses named values from their own scopes.
Example:
(def foo
(let [counter (atom 0)]
(fn [] (do (swap! counter inc) #counter))))
(foo) ;;=> 1
(foo) ;;=> 2
(foo) ;;=> 3, etc
Now foo is a function that returns the value of an atom that is outside its scope. Because the function still holds a reference to that atom, the atom will not be garbage-collected as long as foo is needed.
Function that returns function i.e higher order functions are nice examples of closure.
(defn pow [n]
(fn [x] (apply * (repeat n x))))
(def sq (pow 2))
(def qb (pow 3))
Another example of closure. There are two functions that share the same environment (state).
(defn create-object [init-state]
(let [state (atom init-state)]
{:getter (fn []
#state)
:setter (fn [new-val]
(reset! state new-val))}))
(defn test-it []
(let [{:keys [setter getter]} (create-object :init-value)]
(println (getter))
(setter :new-value)
(println (getter))))
(test-it)
=> :init-value
:new-value
I wanted to have something that setup constant value(s) that are to be used each time.
(def myran
(let [constrand (rand)]
(fn [n] (* n constrand))))
(myran 3)
2.7124521745892096
(myran 1)
0.9041507248630699
(myran 3)
2.7124521745892096
This will only set a value for "constrand" once. This is a very contrived example, but I wanted to be able to do something like:
This is from: JavaScript: The Good Parts
Even though I have used Clojure, I hadn't looked at the scoping rules in detail. I am getting more confused as I read the documentations.
I made a small test to try out the scoping resolutions and am apalled at the complexity. Could somebody explain the intent and various rules that Clojure uses?
(def x 1)
(defn dummy-fn2[]
(+ x 1))
(defn dummy-fn[]
(println "entering function: " x)
(let [x 100]
(println "after let: " x)
(let [x (dummy-fn2)]
(println "after let and dummy2: " x)
(binding [x 100]
(println "after binding: " x)
(let [x (dummy-fn2)]
(println "after binding and dummy2: " x))))))
1:2 foo=> (dummy-fn)
entering function: 1
after let: 100
after let and dummy2: 2
after binding: 2
after binding and dummy2: 101
nil
let shadows the toplevel Var x with a local x. let does not create a Var or affect the toplevel Var; it binds some symbol such that local references to that symbol will be replaced with the let-bound value. let has lexical scope, so its bindings are only visible within the let form itself (not in functions called from within the let).
binding temporarily (thread-locally) changes the value of the toplevel Var x, that's all it does. If a let binding is in place, binding doesn't see it when deciding which value to change (and let's bindings are not vars and are not alterable, so that' a good thing or it'd give you an error). And binding won't mask let. binding has dynamic scope, so its affects on toplevel Vars are visible within the binding form and in any function that is called from within the binding form.
Accessing the value of plain old x will give you whatever is at the top of the stack of bindings, either the most nested let-bound value of x (or the function paramater called x, or some value x is replaced with if you use your own macro, or other possibilities.), and only uses the current value of the toplevel Var x by default if there is no other binding in place.
Even if the toplevel Var x is masked by a let-bound x, you can always access the toplevel Var via ##'x. Try this version, maybe it'll make more sense:
(def x 1)
(defn dummy-fn2[]
(println "x from dummy-fn2:" x)
(+ x 1))
(defn dummy-fn[]
(println "entering function:" x)
(println "var x:" ##'x)
(dummy-fn2)
(println "---")
(let [x 100]
(println "after let:" x)
(println "var x:" ##'x)
(dummy-fn2)
(println "---")
(let [x (dummy-fn2)]
(println "after let and dummy-fn2:" x)
(println "var x:" ##'x)
(dummy-fn2)
(println "---")
(binding [x 888]
(println "after binding:" x)
(println "var x:" ##'x)
(dummy-fn2)
(println "---")
(let [x (dummy-fn2)]
(println "after binding and dummy2:" x)
(println "var x:" ##'x)
(dummy-fn2)
(println "---"))))))
Gives:
entering function: 1
var x: 1
x from dummy-fn2: 1
---
after let: 100
var x: 1
x from dummy-fn2: 1
---
x from dummy-fn2: 1
after let and dummy-fn2: 2
var x: 1
x from dummy-fn2: 1
---
after binding: 2
var x: 888
x from dummy-fn2: 888
---
x from dummy-fn2: 888
after binding and dummy2: 889
var x: 888
x from dummy-fn2: 888
---
Clojure uses both lexical scope let for symbols and dynamic scope binding for vars
check out clojure's vars documentation.
"entering function": doing fine so far! the symbol x resolves to the var and this is grabbing the "root binding" of the var x.
"after let": a local binding covered up the var, the symbol x is now 100 not a var.
"after let and dummy2": the x in dummy-fn2 refers to the var x, so it uses the root binding of x and returned one more than that (+ 1 1)
"after binding": tricky one! binding dynamically replaced the root binding of the var named x (which was 1) with 100, but the local symbol x is not the var anymore so you get the local binding.
"after binding and dummy2": the binding replaced the root value of the var x with 100 and this returned one more than that (+ 100 1)