Does memoize keep track of changes to binding which may make returning a computation it has stored incorrect?
For example if I have a function foo such as:
(defn foo [bar baz]
...
(let [config-val *config-val*]
...)
)
which I contain within a binding so I can change the value of *config-val*, does memoizing it mean that if I change the value of *config-val*, but not the parameters to it that it will not recompute the value of the function? Instead it will give me the value of the function with the old configuration?
In Clojure 1.3.0 memoize doesn't keep track of rebinding.
user=> (def ^:dynamic *x* 5)
#'user/*x*
user=> (def f (memoize #(+ *x* %)))
#'user/f
user=> (f 1)
6
user=> (binding [*x* 6] (f 1))
6
user=> (binding [*x* 7] (f 1))
6
Additionally,
user=> (binding [*x* 7] (f 3))
10
user=> (f 3)
10
user=> *x*
5
memoize does not account for binding, this can be confirmed by looking at the source where the map in the atom is keyed only by the arguments. Indeed a function with dynamic rebinding is not "referentially transparent" (i.e. it cannot be replaced with its value).
Is there something that prevents you from passing the *config-val* as an argument, at least to the function you wish to memoize?
user=> (source memoize)
(defn memoize
"Returns a memoized version of a referentially transparent function. The
memoized version of the function keeps a cache of the mapping from arguments
to results and, when calls with the same arguments are repeated often, has
higher performance at the expense of higher memory use."
{:added "1.0"}
[f]
(let [mem (atom {})]
(fn [& args]
(if-let [e (find #mem args)]
(val e)
(let [ret (apply f args)]
(swap! mem assoc args ret)
ret)))))
As the documentation for memoize suggests, a memoized function will keep an internal cache of arguments mapping to results. When a memoized function is called with arguments it has already seen it will do nothing but look up the correct return value from the cache. Nothing will be recomputed and you will get the same result as you got the last time you called the function. Any rebindings will be ignored.
user=> (def ^:dynamic op +)
user=> (defn add [x y] (op x y))
user=> (add 1 2)
3
user=> (binding [op -]
(add 1 2))
-1
user=> (alter-var-root #'add memoize)
user=> (add 1 2)
3
user=> (binding [op -]
(add 1 2))
3
Related
I'm working through Htdp 2e, and have been given the problem of defining the map function from foldr or foldl. I'm not sure where to start.
Map takes in a function of one argument and a list. So I have defined my
function similarly. Fold requires a function of two arguments, a base, and a list.
My issue is how do I take the one argument function of map and recreate it with a two argument function in fold?
The purpose of the problem is to teach how to create abstractions using higher order functions.
Some push in the right direction would be greatly appreciated
; [X Y] [X -> Y] [List-of-X] -> [List-of-Y]
; consumes a function and a list and applies f
; to each item in the list
(define (map-from-fold f l)
(foldr f base lx))
Think about the main difference between foldr and map:
(map add1 '(1 2 3))
; == (cons (add1 1) (cons (add1 2) (cons (add1 3) '())))
(fold f '() '(1 2 3)
; ==> (f 1 (f 2 (f 3 '())))
Notice that f needs to cons as well as whatever function is added. Thus when you pass f to map the function that is passed to foldr needs to both cons the result of (f element) with the accumulator. Good luck!
What is the API for PersistentQueue?
Naïvely, it appears to lose any data put into it:
user=> (def q (into (clojure.lang.PersistentQueue/EMPTY)
(repeat 5 nil)))
#'user/q
user=> (def q2 (pop (conj q :a)))
#'user/q2
user=> (get q2 4)
nil
user=> (get q2 0)
nil
I must not be accessing PersistentQueue correctly. Clearly it doesn't work with get. What is the right way to access a PersistentQueue? What can you do with it?
And is PersistentQueue documented anywhere, even informally? ("It's only fully documented in my answer" is fine. Really, I'm hoping that someone will write the missing documentation in an answer, or tell where to find it if it's not missing.)
conj never mutates its argument, it returns a new data structure that is immutable, and may share data internally with the original. But I think you know this part already.
get only works on associative data, and returns nil rather than an error if used on non-associative data. queues are not associative. This issue is masked partially in your example by putting nil into the queue, which makes the nil returned by get ambiguous.
user=> (def q (into clojure.lang.PersistentQueue/EMPTY (repeat 5 :a)))
#'user/q
user=> (into [] q)
[:a :a :a :a :a]
user=> (def q2 (pop (conj q :b)))
#'user/q2
user=> (into [] q2)
[:a :a :a :a :b]
user=> (get q2 4)
nil
user=> (get q2 0)
nil
user=> (nth q2 4)
:b
user=> (nth q2 0)
:a
Typically the right operations to use with a queue are conj, into, peek, and pop.
user=> (def q3 (-> q2 (pop)
(conj :c :d)
(pop)
(conj :e)
(pop)
(pop)
(conj :f)))
#'user/q3
user=> (into [] q3)
[:b :c :d :e :f]
user=> (peek q3)
:b
The protocol for sequential collections is
(conj coll x) - return collection coll with x added to one end or the other;
(peek coll) - return the next item to be discarded from coll, if there is one;
(pop coll) - return coll less the discarded end.
peek and pop always work at the same end:
the front of a list (or general sequence);
the back of a vector or queue.
conj works at the same end as peek/pop of a vector or list, but at the opposite end (the front) of a queue. That's what makes it work as a queue.
As has been said, get and disj have nothing to do with sequential collections.
You may be puzzled because a PersistentQueue doesn't know how to properly convert itself into a string. seq will show you what you've got. For instance,
(def q (into (clojure.lang.PersistentQueue/EMPTY)
(repeat 5 nil)))
q ;=>#<PersistentQueue clojure.lang.PersistentQueue#1b4d89f>
(seq q) ;(nil nil nil nil nil)
For a class project I am implementing the Bron-Kerbosch algorithm for finding maximal cliques in a graph. With help from others on SO I have gotten down to the final few issues.
This link (http://pastebin.com/2GUPZFnR) contains a SSCCE of my current implementation that outlines the issue. The issue I think lies with my use of disj to find the intersection of two lists. I think this based on the error given when I call BK-Call with the "sanity" input.
fptests.core> (BK-Call (sanity1))
ClassCastException clojure.lang.PersistentList$EmptyList cannot be cast to clojure.lang.IPersistentSet clojure.core/disj (core.clj:1449)
This error tracks down to a few lines in my Bron-Kerbosch function itself
(defn Bron-Kerbosch [r p x graph cliques]
(cond (and (empty? p) (empty? x)) (conj cliques r)
:else
(let [neigh (neighV graph (dec (count p)))]
(loop [loop-clq '(cliques)
loop-cnt '(dec (count p))
loop-p '(p)
loop-x '(x)]
(cond (= -1 loop-cnt) loop-clq
:else
(recur (conj loop-clq (Bron-Kerbosch (conj r loop-cnt) (conj p neigh) (disj x neigh)))
(dec loop-cnt)
(disj p loop-cnt)
(conj x loop-cnt)))))))
Specifically in the recursive call to the function in the recur form. Though this issue I think applies to all uses of conj and disj. It seems that conj "works" but not in the manner I assumed.
fptests.core> (disj '(1) '(1 2 3))
ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IPersistentSet clojure.core/disj (core.clj:1449)
fptests.core> (conj '(1) '(2 3))
((2 3) 1)
I assumed that (conj '(1) '(2 3)) would return (1 2 3) and not (1 (2 3)). So it seems my use of lists in the function overall is the issue. Is there a way that I could overcome this issue?
I would have to imagine there are functions like conj and disj that work with lists. I guess my other option if this is not true is to use some other data structure in the algorithm. What would be appropriate?
use cons, rest and concat.
user=> (cons 1 '(2 3))
(1 2 3)
user=> (cons '(1) '(2 3))
((1) 2 3)
user=> (cons 1 ())
(1)
user=> (rest '(1 2 3))
(2 3)
user=> (concat '(1) '(2 3))
(1 2 3)
I would indeed suggest using a data structure more suited to the problem at hand, namely a set.
You're already using Clojure hash sets in your graph representation ((repeat n #{}) in empty-graph); the r, p and x parameters of the Bron-Kerbosch step function are all conceptually sets, so it makes sense to represent them as Clojure sets as well.
With that choice of representation, things will become simpler for you – set intersection can be computed using clojure.set/intersection, disj works for removing individual keys etc.
On a separate note, it would be more natural to use if rather than cond in Bron-Kerbosch (both conds in that function actually only have two branches). More importantly, you'll want to remove the quotes from the init expressions in your loop – '(dec (count p)) (notice the '), to take one example, is a two-element list, not a number. (It's also somewhat unusual in Clojure for function names to include capital letters, but of course this is purely a matter of style.)
Say I have a tree defined as per the recommendation in this post, although it's a vector in my case, which hopefully shouldn't matter (they're vectors in Programming Clojure book):
(def tree [1 [[2 [4] [5]] [3 [6]]]])
which should be something like:
1
/ \
2 3
/ \ |
4 5 6
Now, I'd like to do a breadth-first traversal of the tree without any of the traditional means such as the queue, and instead use exclusively the stack to pass information around. I know this isn't the easiest route, but I'm doing it mostly as exercise. Also at this point I'm not planning to return a collection (I'll figure that out afterwards as exercise) but instead just print out the nodes as I travel through them.
My current solution (just starting out with Clojure, be nice):
(defn breadth-recur
[queue]
(if (empty? queue)
(println "Done!")
(let [collections (first (filter coll? queue))]
(do
; print out nodes on the current level, they will not be wrapped'
; in a [] vector and thus coll? will return false
(doseq [node queue] (if (not (coll? node)) (println node)))
(recur (reduce conj (first collections) (rest collections)))))))
The last line is not working as intended and I'm stumped about how to fix it. I know exactly what I want: I need to peel each layer of vectors and then concatenate the results to pass into recur.
The issue I'm seeing is mostly a:
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long
Basically conj doesn't like appending a vector to a long, and if I swap conj for concat, then I fail when one of the two items I'm concatenating isn't a vector. Both conj and concat fail when facing:
[2 [4] [5] [3 [6]]]
I feel like I'm missing a really basic operation here that would work both on vectors and primitives in both positions.
Any suggestions?
Edit 1:
The tree should actually be (thanks Joost!):
(def tree [1 [2 [4] [5]] [3 [6]]])
However we still haven't found a breadth-first solution.
Since apparently there is still no breadth-first solution posted, here is a simple algorithm, implemented first eagerly, and then transformed to be lazy:
(defn bfs-eager [tree]
(loop [ret [], queue (conj clojure.lang.PersistentQueue/EMPTY tree)]
(if (seq queue)
(let [[node & children] (peek queue)]
(recur (conj ret node) (into (pop queue) children)))
ret)))
(defn bfs-lazy [tree]
((fn step [queue]
(lazy-seq
(when (seq queue)
(let [[node & children] (peek queue)]
(cons node
(step (into (pop queue) children)))))))
(conj clojure.lang.PersistentQueue/EMPTY tree)))
Your tree data is incorrect. It should be [1 [2 [4] [5]] [3 [6]]]
Also, you're mixing the tree traversal with printing and building up a result. Things get simpler if you concentrate on doing the hard part separately:
(def tree [1 [2 [4] [5]] [3 [6]]])
NOTE THIS IS DEPTH-FIRST. SEE BELOW
(defn bf "return elements in tree, breath-first"
[[el left right]] ;; a tree is a seq of one element,
;; followed by left and right child trees
(if el
(concat [el] (bf left) (bf right))))
(bf tree)
=> (1 2 4 5 3 6)
CORRECT VERSION
(defn bf [& roots]
(if (seq roots)
(concat (map first roots) ;; values in roots
(apply bf (mapcat rest roots))))) ;; recursively for children
(bf tree)
=> (1 2 3 4 5 6)
This might help, I was creating an algorithm to evaluate if a tree is symmetric and used a breadth-first traversal:
(defn node-values [nodes]
(map first nodes))
(defn node-children [nodes]
(mapcat next nodes))
(defn depth-traversal [nodes]
(if (not (empty? nodes))
(cons (node-values nodes) (depth-traversal (node-children nodes)))))
(defn tree-symmetric? [tree]
(every?
(fn [depth] (= depth (reverse depth)))
(depth-traversal (list tree))))
(def tree '(1 (2 (3) (4)) (2 (4) (3))))
(node-values (list tree)) ; (1)
(node-children (list tree)) ; ((2 (3) (4)) (2 (4) (3)))
(depth-traversal (list tree)) ; ((1) (2 2) (3 4 4 3))
(tree-symmetric? tree) ; true
many combinations of reduceand conj can be replaced with single into call
in the case above with reduce you may need to pass an initial empty vector to reduce to
get make conjunction happy.
if i have a list of functions:
(def lst '(+ -))
and i wish to apply the first of that list (+) to a list of numbers, i would think its
(apply (first lst) '(1 2 3 4))
but apparently U am wrong? Syntax mistake I assume. How do I do this?
PS:
=>(first lst)
+
=>(apply (first lst) '(1 2 3 4))
4
both return without error, they just return what i WOULD expect in the first case, and what i would NOT expect in the second.
Since your list is quoted:
(def lst '(+ -))
; ^- quote!
its members are two symbols, not functions. A symbol in Clojure can be used as a function, but then it acts very much like a keyword (i.e. looks itself up in its argument):
('foo {'foo 1})
; => 1
The correct solution is to use a list -- or, more idiomatically, a vector -- of functions:
(def lst (list + -)) ; ok
; or...
(def lst `(~+ ~-)) ; very unusual in Clojure
; or...
(def lst [+ -]) ; the idiomatic solution
Then your apply example will work.
By the way, notice that a function, when printed back by the REPL, doesn't look like the symbol which names it:
user=> +
#<core$_PLUS_ clojure.core$_PLUS_#10c10de0>