I'm attempting to create my own immutable datatype/methods with defrecord in Clojure. The goal is to have a datatype that I can create instances of, and then call its methods to return a new copy of itself with mutated variables. Say a and b are vectors. I'd like to update a value in both and return a new copy of the entire structure with those vectors updated. This obviously doesn't compile, I'm just trying to get my ideas across.
(defrecord MyType [a b]
(constructor [N]
; I'd like to build an initial instance, creating a and b as vectors of length N
)
(mutate-and-return []
; I'd like to mutate (assoc the vectors) and return the new structure, a and b modified
)
)
I'd like to call the constructor and then the mutator as many times as I'd like (there are other functions that don't mutate, but I don't want to make it more complex for the question).
Alternatively, if this is not idiomatic Clojure, how are you supposed to do something like this?
Here's how you define your record:
(defrecord MyType [a b])
Note that in Clojure you don't typically define "methods" within your record type itself (the exception is if you want to directly implement a Java interface or a protocol).
A basic constructor (prefixed with ->) gets generated automatically for free:
(def foo (->MyType [1 2 3] [4 5 6]))
foo
=> #user.MyType{:a [1 2 3], :b [4 5 6]}
You can then write more sophisticated constructor functions that use this, e.g.
(defn mytype-with-length [n]
(let [a (vec (range n))
b (vec (range n))]
(->MyType a b)))
(mytype-with-length 3)
=> #user.MyType{:a [0 1 2], :b [0 1 2]}
And "mutate-and-return" also comes for free - you can just use assoc:
(assoc foo :b [7 8 9])
=> user.MyType{:a [1 2 3], :b [7 8 9]}
Clojure defrecord example:
;;define Address record
(defrecord Address [city state])
;;define Person record
(defrecord Person [firstname lastname ^Address address])
;;buid the constructor
(defn make-person ([fname lname city state]
(->Person fname lname (->Address city state))))
;;create a person
(def person1 (make-person "John" "Doe" "LA" "CA"))
;;retrieve values
(:firstname person1)
(:city (:address person1))
Clojure allows you to create records, which are custom, maplike data types.
They’re maplike in that they associate keys with values, you can look up their values the same way you can with maps, and they’re immutable like maps.
(defrecord Person [last first address])
;=> core.Person
(defrecord Ad [street city zip])
;=> core.Ad
(def p1 (Person. "Jhon" "Mick"
(Ad. "US187956" "NY" 3369)))
;=> #'core/p1
(update-in p1 [:address :zip] inc)
;=> #core.Person{:last "Jhon", :first "Mick", :address #playsync.core.Ad{:street "US187956", :city "NY", :zip 3370}}
(assoc p1 :last "Adam")
;=> #core.Person{:last "Adam", :first "Mick", :address #playsync.core.Ad{:street "US187956", :city "NY", :zip 3370}}
Related
(defn image-of
"computes the image of the element x under R"
[R x]
(set
(for [r R]
(when (= (first r) x)
(second r)))))
Function idea: Add the second variable in R when it's first is equal to x.
So this function is supposed to compute image of a relation. This is kinda successful. When running a test I get this result:
Input: (image-of #{[1 :a] [2 :b] [1 :c] [3 :a]} 1)
Expected: #{:c :a}
Actual: #{nil :c :a}
So it includes a nil value for some reason. What in the function causes this? I guess I could filter out any nil values but would like to have the solution on a single line.
So the problem was I didn't know exactly how to use when
This solution does it:
(set (for [r R
:when (= (first r) x)]
(second r)))
Let me suggest a different approach.
The natural way to represent a relation in Clojure is as a map from keys to sets (or other collections) of values. A function to convert your collection of pairs to this form is ...
(defn pairs->map [pairs]
(reduce
(fn [acc [key value]]
(assoc acc key (conj (acc key #{}) value)))
{}
pairs))
For example, ...
(pairs->map #{[1 :a] [2 :b] [1 :c] [3 :a]})
=> {2 #{:b}, 1 #{:c :a}, 3 #{:a}}
You can use this map as a function. I you feed it a key, it returns the corresponding value:
({2 #{:b}, 1 #{:c :a}, 3 #{:a}} 1)
=> #{:c :a}
You construct this map once and or all and use it as often as you like. Looking it up as a function is effectively a constant-time operation. But you run through the entire collection of pairs every time you evaluate image-of.
Say I have a board like this
(def board {:a 10 :b 12})
And a list of functions like this
(def funcs [(assoc board :a 2)
(assoc board :b 4)
(assoc board :a (inc (get board :a)))])
How would I go about applying each operation in the list to my board, having it update each time in a functional fashion.
Evaluating funcs in my repl, gives a list of return values after calling each function, but the board itself remains unchanged each time
user=> funcs
[{:a 2, :b 12} {:a 10, :b 4} {:a 11, :b 12}
Ideally I'd like the value of the board to update each time a function is ran
so after running the all commands the final state of the board should be:
{:a 3 :b 4}
I'm aware this is possible using tail recursion but I'd like to avoid doing so as I'm almost certain a combination of reduce/apply/map will do the trick
One of the defining traits of clojure is that its data structures are immutable. That means that board will never change, functions that operate on data structures return modified copies of the data structure. So what you've done in funcs is make a vector of three different boards, the original board with a fuction applied.
Usually what you want is to apply a bunch of functions to some initial value, where each function takes the returned value of the function before, then use the returned value for something. Usually passing it around in function parameters.
;; First of all, there's a function for that
(assoc board :a (inc (get board :a)))
;; The function update takes a map and a key and a function
;; It applies the function to value currently at key,
;; then sets key in the retuned "copy" of the map to be the return value of the function.
;; Equivalent to the above
(update board :a inc)
If you want an updated board with these functions applied, you need to to pass the return value through the functions, because the original board never changes, they all just return updated copies of their input.
(def updated-board
;; The innermost forms are evaluated first.
(update (assoc (assoc board :a 2) :b 4) :a inc))
This can be made more readable by using the -> or "thread first" macro. It takes an initial value and forms which are missing the first argument, then rewrites the code to "thread" the return value of each one as the first argument to the next.
(def updated-board-threaded
(-> board
(assoc :a 2)
(assoc :b 4)
(update :a inc)))
;; You can expand the macro to see for yourself
;; that the two examples are exactly equivalent.
(macroexpand-1 '(-> board
(assoc :a 2)
(assoc :b 4)
(update :a inc)))
;;=> (update (assoc (assoc board :a 2) :b 4) :a inc)
This is the way to "think in clojure", functions usually just take immutable values and return other immutable values.
But sometimes you need something mutable, and clojure delivers this in the form of atoms. An atom can be thought of as a mutable box that contains an immutable value.
It uses the functions swap! and reset! to apply controlled mutation. And the function deref to get the current value.
(def board (atom {:a 10, :b 12}))
;; I'll define a function that takes a board and returns an updated version of it.
(defn do-stuff-with-board [b]
(-> b
(assoc :a 2)
(assoc :b 4)
(update :a inc)))
;; Get the current value of board.
(deref board) ;;=> {:a 10, :b 12}
;; Swap takes an atom and a function and
;; sets the value of the atom to be the return value of the function
(swap! board do-stuff-with-board)
;; Now the mutable board atom contains a new immutable value.
(deref board) ;;=> {:a 3, :b 4}
;; derefing an atom is a very usual operation, so there's syntax sugar for it
;; Equivalent to (deref board)
#board ;;=> {:a 3, :b 4}
reset! sets the value of board to be another value, like = in "normal" languages. It's not usually idiomatic to do this as it kinda says to the reader that the new value of the atom has nothing to do with the old one, but clojure is pragmatic, and sometimes it's what you need.
(reset! board "And now for something completely different.")
;; The value is now a string.
#board ;;=> "And now for something completely different."
As an aside. The data structures are not actually deep copies of each other, there is magic behind the scenes to make it almost as efficient as updating the data structure in place, but from the perspective of the programmer they are equivalent to deep copies in other languages.
I'd like to suggest a different approach to #madstap's fine answer.
In ...
(def funcs [(assoc board :a 2)
(assoc board :b 4)
(assoc board :a (inc (get board :a)))])
... the elements such as (assoc board :b 4) are not functions: they are function calls, which, as #madstap points out, fail to modify whatever board refers to.
We can, without too much trouble, turn them into proper functions:
(def funcs [(fn [board] (assoc board :a 2))
(fn [board] (assoc board :b 4))
(fn [board] (assoc board :a (inc (get board :a))))])
The boards here are locals. Any distinct identifier would do as well:
(def funcs [(fn [b] (assoc b :a 2))
(fn [b] (assoc b :b 4))
(fn [b] (assoc b :a (inc (get b :a))))])
We can write a function to compose them:
(defn compose [fs]
(fn [x] (reduce (fn [a f] (f a)) x fs)))
This is a simplified version of the standard comp. It applies the functions first to last instead of last to first.
Now, for example, if
(def board {:a 10 :b 12})
... then
((compose funcs) board)
;{:a 3, :b 4}
Furthermore, we can modify compose to show the chain of results:
(defn compositions [fs]
(fn [x] (reductions (fn [a f] (f a)) x fs)))
((compositions funcs) board)
;({:a 10, :b 12} {:a 2, :b 12} {:a 2, :b 4} {:a 3, :b 4})
Notice that compose and compositions are completely generic - they just do stuff with functions.
Could you please tell me how can I make the dict form the list?
E.g. I have the list [3 4 5] and :value keyword.
I need to create the following dict:
{{:constant_keyword "constant", :value 5 } {:constant_keyword "constant", :value 4} {:constant_keyword "constant", :value 3}}?
I know how to make a constant value:
(def const-dict (take (count [my-list]) (repeat {:column "type"})))
But I do not know who to do it with a parameter like the item of an array:
(take (count [my_list]) :value) - doesn't work, I can't create list of keywords and then zipmap it to another list.
How can I do it?
(map #(assoc {:constant_keyword "constant"} :value %) [3 4 5])
I'm hitting some kind of mental roadblock related to destructuring...
(sorted-set 4 2 5)
gives:
#{2 4 5}
But How I can get that same sorted set from:
((fn [???] (sorted-set ???)) [4 2 5])
or from a set (unsorted) passed as an argument:
((fn [???] (sorted-set ???)) #{4 2 5})
I tried several destructuring, I was thinking that:
((fn [#{elems}] (sorted-set elems)) #{4 2 5})
would work but this is not the case.
I'd like to know how to do that and it would be even better if you could explain why my way of reasoning is bogus...
the sorted-set function param is a var-arg: [& keys], which means that if you have a collection and you want to call that function you need to use the apply function like:
user=> (def v [4 8 2])
#'user/v
user=> (apply sorted-set v)
#{2 4 8}
The signature of a function that accepts a collection and returns a sorted-set would be like:
user=> (defn to-ss [c] (apply sorted-set c))
#'user/to-ss
user=> (to-ss v)
#{2 4 8}
You could also create an empty sorted-set and then add all the elements of the collection to it:
(defn to-ss [c] (into (sorted-set) c))
Note that if you were to define your function with a var-arg parameter, you will need to use apply to both call the function and create the sorted-set:
user=> (defn to-ss [& items] (apply sorted-set items))
#'user/to-ss
user=> (apply to-ss v)
#{2 4 8} <-- expected value
user=> (to-ss v)
#{[4 8 2]} <-- sorted-set with just one value
I am going through this article on Tree Visitors in Clojure and came across the below example:
(def data [[1 :foo] [2 [3 [4 "abc"]] 5]])
(walk/postwalk #(do (println "visiting:" %) %) data)
What is the outer form of postwalk doing? I can't understand its utility. How and why is postwalk used? Any explanations will be appreciated.
I'm not sure if you're asking what #() means or what the purpose of do(form1 form2) means, so I'll answer both.
#() is a shorthand for declaring an anonymous function. Anonymous functions are useful when you're passing some function into another function.
To illustrate, look at this in the repl
; define an anonymous function
user=> #(+ %1 %2)
#<user$eval68$fn__69 user$eval68$fn__69#9fe84e>
; is equivalent to
user => (fn [a b] (+ a b))
#<user$eval1951$fn__1952 user$eval1951$fn__1952#118bd3c>
; furthermore, you could then assign your anonymous function to a var
(def f #(+ %1 %2))
; is equivalent to
(defn f [a b] (+ a b))
user=> (#(+ %1 %2) 1 2)
3
user=> (f 1 2)
3
The %n refers to the arguments to positional arguments to a function where n means nth argument, starting at 1 As a further shorthand you can use % to refer to the first argument which works well for single arg anonymous functions. This is what you have in your example.
So you example is equivalent to
(def data [[1 :foo] [2 [3 [4 "abc"]] 5]])
(defn f [x] (do (println "visiting:" x) x))
(walk/postwalk f data)
The do here is a special form, which, from the docs:
(do exprs*)
Evaluates the expressions in order and returns the value of the last. If no expressions are supplied, returns nil.
In fact defn already has an implicit do, so my example above doesn't actually need the do...
; your example is equivalent to:
(def data [[1 :foo] [2 [3 [4 "abc"]] 5]])
(defn f [x] (println "visiting:" x) x)
(walk/postwalk f data)
I had the same question today and find this necrotopik. Maybe later is better the newer. Find this on clojure api reference:
postwalk
function
Usage: (postwalk f form)
Performs a depth-first, post-order traversal of form. Calls f on
each sub-form, uses f's return value in place of the original.
Recognizes all Clojure data structures except sorted-map-by.
Consumes seqs as with doall.
Also this example from clojuredocs makes things clearer:
(use 'clojure.walk)
(let [counter (atom -1)]
(postwalk (fn [x]
[(swap! counter inc) x])
{:a 1 :b 2}))
=> [6 {2 [[0 :a] [1 1]], 5 [[3 :b] [4 2]]}]
So, postwalk replaces every subform with result of the function. It is used for updating nested structures with new values. That is why resulting function contains x or % at the end. Adding input to result leads to even more nested stucture.
In the example above it is seen as it walks through the depths of nested map stucture. It is going first on deepest elements of the map, then go up on higher level, then lurk down to the next form, then again goes up and finishes its last move on the whole form.