Reputation: 1070
I started to learn clojure so pardon for noob question I try to implement following function
pseudo code:
function(x y) {
if (x != oldX)
dosomething(y);
oldX = x;
}
oldX
is global variable
How can i properly do this the clojure way?
I wrote something this but is this correct way or not?
(defn rec [x y]
(if (not= x oldX)
(println "y"))
(def oldX x))
Upvotes: 2
Views: 83
Reputation: 6477
Clojure is a functional programming language. This is a different paradigm than it is used in other popular programming languages like Python. It appears that you are not thinking functional ;-)
The Clojure-way would be not to use a variable for this case. Just solve it with functions or, if it is really necessary, use atoms
or ref
s, depending on what you need.
An atom
or a ref
can be modified within a function to store the old result - this may be the solution you are looking for.
But for most cases there exists a simpler solution without the need for a variable like oldX
- and this is were the benefits of a functional language come into place.
Your Code
(defn rec [x y]
(if (not= x oldX)
(println "y"))
(def oldX x))
As @cgrand already said, def
should only be used on the first level.
You use if
, but you define only the true
case. If you check only, if a certain statement is true, then you can use when
.
The last line defines a new oldX
in the scope of the function rec
. This is a new variable, not the old one with a new value, in the active namespace (thanks to @user1571406).
Upvotes: 3
Reputation: 121
I think what you're looking for is something like this. I've tried to keep your var names as your originals, so it's easier to see the difference.
atom
to store oldX
compare-and-set!
to determine whether you've changed the atom(dosomething y)
Note: This is kind of like a swap!
, except swap!
returns the value swapped in, not whether or not your call to swap!
changed the value, so it's less useful here.
Something like this:
(defn dosomething [y]
;; does something, presumably with y...
)
(defonce x-atom (atom nil))
(defn swap-x
"swaps x-atom for new x, calls (dosomething ...) with y if successful"
[x y]
(let [oldX @x-atom] ; get the cur value of x
(when (not= oldX x)
(when (compare-and-set! x-atom oldX x)
(dosomething y))
If the compare-and-set!
fails, then it means some other thread has modified the atom since you got its value. If you need to handle that case, the answer is a little different. You could either use a swap!
or a loop+recur
. If you're unfamiliar, a swap!
is sort of like a compare-and-set!
that recurs on failure.
Upvotes: 0
Reputation: 7949
defs
should only be top level. (def oldX (atom nil))
and (reset! oldX x)
is more correct.
Upvotes: 5