How to keep a list of objects in Clojure? - clojure

I'm trying to use java interop, to create a list of objects.
I have tried for and doseq, and they both have problems.
for is lazy, and I need to create all the objects, as they interact with each other internally.
(def master-object (MasterObject.))
(for [x [1 10 50 99]]
(let [child (.createChildObject master-object)]
(.setCoefficient child x)
child))
doseq creates all, but don't return a list.
(doseq [x [1 10 50 99]]
(let [child (.createChildObject master-object)]
(.setCoefficient child x)
child))
I was thinking about using loop and recur, but was wondering if could be a more idiomatic way of doing that.
Thanks

If you need to create all the objects then I think it would be idiomatic to return a vector rather than a list, for example:
(vec (for [x (range 3)]
x))
There are a few different ways to force all the output from a for. The above is one of them. vec is just short for into []. So if you definitely need a realised list you could instead:
(into '() (for [x (range 3)]
x))
For creating a list of objects doseq will not help you as it is only about 'side effects'.
Really you could look at using map for what you want to accomplish. Make a separate mapping function and map over it:
(defn make-child [x]
(let [child (.createChildObject master-object)]
(.setCoefficient child x)
child))
(map make-child [1 10 50 99])

The magic word for realising lazy sequences is doall. If you wrap it round your for, you'll get the effect you want:
(doall
(for [x [1 10 50 99]]
(let [child (.createChildObject master-object)]
(.setCoefficient child x)
child)))
=>
(#object[interop.core.ChildObject 0x326037f1 "interop.core.ChildObject#326037f1"]
#object[interop.core.ChildObject 0x759b711 "interop.core.ChildObject#759b711"]
#object[interop.core.ChildObject 0x2bc06dcb "interop.core.ChildObject#2bc06dcb"]
#object[interop.core.ChildObject 0x4a37a35a "interop.core.ChildObject#4a37a35a"])
Notice that the returned object is a LazySeq,not a list. And the REPL forces its realisation anyway.
If setCoefficient returns Java this, you can abbreviate the above to
(doall
(for [x [1 10 50 99]]
(.. master-object
(createChildObject)
(setCoefficient x))))
The structure of your code worries me. You are implementing half the association between MasterObject and ChildObject - a child knows its master; but not the other half - a master does not know its children. We don't see you do anything with the generated collection of children. If that is so, nothing refers to them, and they are garbage that will be disposed of whenever.
I think the MasterObject should keep a collection of its children, added to when the ChildObject is created in createChildObject. Then you needn't keep the collection of created children, and doseq is to be preferred to for. I've done it entirely in Clojure interop as follows:
(ns interop.core)
(definterface ChildInterface
(setCoefficient [x]))
(definterface MasterInterface
(createChildObject [])
(getChildren []))
(deftype ChildObject [master ^:unsynchronized-mutable coefficient]
Object
(toString [this]
(str "Child " coefficient))
ChildInterface
(setCoefficient [this x]
(set! coefficient x)
this))
(deftype MasterObject [^:unsynchronized-mutable children]
Object
(toString [this]
(str "Master children: " (.seq children)))
MasterInterface
(createChildObject [this]
(let [child (ChildObject. this nil)]
(set! children (conj children child))
child))
(getChildren [this]
children))
(def master-object (MasterObject. []))
(doseq [x [1 10 50 99]]
(.. master-object
(createChildObject)
(setCoefficient x)))
This is still pretty ugly, as I haven't worked out how to suppress the default rendering of Java objects:
master-object
=>
#object[interop.core.MasterObject
0x3f7683a
"Master children: (#object[interop.core.ChildObject 0xb1cf4bb \"Child 1\"] #object[interop.core.ChildObject 0x16b56f70 \"Child 10\"] #object[interop.core.ChildObject 0x5dadc8ab \"Child 50\"] #object[interop.core.ChildObject 0x6f22f049 \"Child 99\"])"]
I've used a Clojure vector for the children. In this context, a Java collection would do just as well.

Related

Clojure loop collection

I want to know if this is the right way to loop through an collection:
(def citrus-list ["lemon" "orange" "grapefruit"])
(defn display-citrus [citruses]
(loop [[citrus & citruses] citruses]
(println citrus)
(if citrus (recur citruses))
))
(display-citrus citrus-list)
I have three questions:
the final print displays nil, is it ok or how can avoid it?
I understand what & is doing in this example but I donĀ“t see it in other cases, maybe you could provide a few examples
Any other example to get the same result?
Thanks,
R.
First of all your implementation is wrong. It would fail if your list contains nil:
user> (display-citrus [nil "asd" "fgh"])
;;=> nil
nil
And print unneeded nil if the list is empty:
user> (display-citrus [])
;;=> nil
nil
you can fix it this way:
(defn display-citrus [citruses]
(when (seq citruses)
(loop [[citrus & citruses] citruses]
(println citrus)
(if (seq citruses) (recur citruses)))))
1) it is totally ok: for non-empty collection the last call inside function is println, which returns nil, and for empty collection you don't call anything, meaning nil would be returned (clojure function always returns a value). To avoid nil in your case you should explicitly return some value (like this for example):
(defn display-citrus [citruses]
(when (seq citruses)
(loop [[citrus & citruses] citruses]
(println citrus)
(if (seq citruses) (recur citruses))))
citruses)
user> (display-citrus citrus-list)
;;=> lemon
;;=> orange
;;=> grapefruit
["lemon" "orange" "grapefruit"]
2) some articles about destructuring should help you
3) yes, there are some ways to do this. The simplest would be:
(run! println citrus-list)
Answering your last question, you should avoid using loop in Clojure. This form is rather for experienced users that really know what they do. In your case, you may use such more user-friendly forms as doseq. For example:
(doseq [item collection]
(println item))
You may also use map but keep in mind that it returns a new list (of nils if your case) that not sometimes desirable. Say, you are interested only in printing but not in the result.
In addition, map is lazy and won't be evaluated until it has been printed or evaluated with doall.
For most purpose, you can use either map, for or loop.
=> (map count citrus-list)
(5 6 10)
=> (for [c citrus-list] (count c))
(5 6 10)
=> (loop [[c & citrus] citrus-list
counts []]
(if-not c counts
(recur citrus (conj counts (count c)))))
[5 6 10]
I tend to use map as much of possible. The syntax is more concise, and it clearly separates the control flow (sequential loop) from the transformation logic (count the values).
For instance, you can run the same operation (count) in parallel by simply replacing map by pmap
=> (pmap count citrus-list)
[5 6 10]
In Clojure, most operations on collection are lazy. They will not take effect as long as your program doesn't need the new values. To apply the effect immediately, you can enclose your loop operation inside doall
=> (doall (map count citrus-list))
(5 6 10)
You can also use doseq if you don't care about return values. For instance, you can use doseq with println since the function will always return nil
=> (doseq [c citrus-list] (println c))
lemon
orange
grapefruit

Clojure: How to determine if a nested list contains non-numeric items?

I need to write a Clojure function which takes an unevaluated arbitrarily deep nesting of lists as input, and then determines if any item in the list (not in function position) is non-numeric. This is my first time writing anything in Clojure so I am a bit confused. Here is my first attempt at making the function:
(defn list-eval
[x]
(for [lst x]
(for [item lst]
(if(integer? item)
(println "")
(println "This list contains a non-numeric value")))))
I tried to use a nested for-loop to iterate through each item in every nested list. Trying to test the function like so:
=> (list-eval (1(2 3("a" 5(3)))))
results in this exception:
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn listeval.core/eval7976 (form-init4504441070457356195.clj:1)
Does the problem here lie in the code, or in how I call the function and pass an argument? In either case, how can I make this work as intended?
This happens because (1 ..) is treated as calling a function, and 1 is a Long, and not a function. First you should change the nested list to '(1(2 3("a" 5(3)))). Next you can change your function to run recursively:
(defn list-eval
[x]
(if (list? x)
(for [lst x] (list-eval lst))
(if (integer? x)
(println "")
(println "This list contains a non-numeric value"))))
=> (list-eval '(1(2 3("a" 5(3)))))
There is a cool function called tree-seq that does all the hard work for you in traversing the structure. Use it then remove any collections, remove all numbers, and check if there is anything left.
(defn any-non-numbers?
[x]
(->> x
(tree-seq coll? #(if (map? %) (vals %) %))
(remove (some-fn coll? number?))
not-empty
boolean))
Examples:
user=> (any-non-numbers? 1)
false
user=> (any-non-numbers? [1 2])
false
user=> (any-non-numbers? [1 2 "sd"])
true
user=> (any-non-numbers? [1 2 "sd" {:x 1}])
true
user=> (any-non-numbers? [1 2 {:x 1}])
false
user=> (any-non-numbers? [1 2 {:x 1 :y "hello"}])
true
If you want to consider map keys as well, just change (vals %) to (interleave (keys %) (vals %)).
quoting
As others have mentioned, you need to quote a list to keep it from being evaluated as
code. That's the cause of the exception you're seeing.
for and nesting
for will only descend to the nesting depth you tell it to. It is not a for loop,
as you might expect, but a sequence comprehension, like the the python list comprehension.
(for [x xs, y ys] y) will presume that xs is a list of lists and flatten it.
(for [x xs, y ys, z zs] z) Is the same but with an extra level of nesting.
To walk down to any depth, you'd usually use recursion.
(There are ways to do this iteratively, but they're more difficult to wrap your head around.)
side effects
You're doing side effects (printing) inside a lazy sequence. This will work at the repl,
but if you're not using the result anywhere, it won't run and cause great confusion.
It's something every new clojurian bumps into at some point.
(doseq is like for, but for side effects.)
The clojure way is to separate functions that work with values from functions that
"do stuff", like printing to the console of launching missiles, and to keep the
side effecting functions as simple as possible.
putting it all together
Let's make a clear problem statement: Is there a non number anywhere inside an
arbitrarily nested list? If there is, print a message saying that to the console.
In a lot of cases, when you'd use a for loop in other langs reduce is what you want in clojure.
(defn collect-nested-non-numbers
;; If called with one argument, call itself with empty accumulator
;; and that argument.
([form] (collect-nested-non-numbers [] form))
([acc x]
(if (coll? x)
;; If x is a collection, use reduce to call itself on every element.
(reduce collect-nested-non-numbers acc x)
;; Put x into the accumulator if it's a non-number
(if (number? x)
acc
(conj acc x)))))
;; A function that ends in a question mark is (by convention) one that
;; returns a boolean.
(defn only-numbers? [form]
(empty? (collect-nested-non-numbers form)))
;; Our function that does stuff becomes very simple.
;; Which is a good thing, cause it's difficult to test.
(defn warn-on-non-numbers [form]
(when-not (only-numbers? form)
(println "This list contains a non-numeric value")))
And that'll work. There already exists a bunch of things that'll help you walk a nested structure, though, so you don't need to do it manually.
There's the clojure.walk namespace that comes with clojure. It's for when you have
a nested thing and want to transform some parts of it. There's tree-seq which is explained
in another answer. Specter is a library which is
a very powerful mini language for expressing transformations of nested structures.
Then there's my utils library comfy which contains reduce versions of the
functions in clojure.walk, for when you've got a nested thing and want to "reduce" it to a single value.
The nice thing about that is that you can use reduced which is like the imperative break statement, but for reduce. If it finds a non-number it doesn't need to keep going through the whole thing.
(ns foo.core
(:require
[madstap.comfy :as comfy]))
(defn only-numbers? [form]
(comfy/prewalk-reduce
(fn [ret x]
(if (or (coll? x) (number? x))
ret
(reduced false)))
true
form))
Maybe by "any item in the list (not in function position)" you meant this?
(defn only-numbers-in-arg-position? [form]
(comfy/prewalk-reduce
(fn [ret x]
(if (and (list? x) (not (every? (some-fn number? list?) (rest x))))
(reduced false)
ret))
true
form))

Create a record of the same type as another

I have a case where I would like to create a new instance of a record based on the type of a record instance that is coming as an argument together with a map of attributes.
(defn record-from-instance
[other attrs]
;; Code that creates the new record based on "other"
)
What I have right now is something among the lines:
(defn record-from-instance
[other attrs]
(let [matched (s/split (subs (str (class other)) 6) #"\.")
path (s/join "." (pop matched))
class-name (peek matched)]
((resolve (symbol (str path "/" "map->" class-name))) attrs)))
Is there any other simpler more idiomatic way to do this that I cannot see?
Thanks!
EDIT
To give some more details I am constructing an AST with nodes being records and I am using a zipper to visit and possibly alter / remove parts of the AST. I have an IZipableTreeNode protocol
(defprotocol IZipableTreeNode
(branch? [node])
(children [node])
(make-node [node children]))
Between the different types that implement the IZipableTreeNode is IPersistentMap
IPersistentMap
(branch? [node] true)
(children [node] (seq node))
(make-node [node children]
(let [hmap (into {} (filter #(= (count %) 2)) children)]
(if (record? node)
(record/from-instance node hmap)
hmap)))
When a visitor say deletes a field from a node (or alters it) the make-node gets called with node being the record AST node and children the new key/value pairs (that may not contain some of the fields in node).
I thought clojure.core/empty used to do this. That is, I thought
(defrecord Foo [x])
(empty (Foo. 1))
would return
#user.Foo{:x nil}
But it certainly doesn't do that now: I'm not sure whether that changed or I misremembered. I can't find a super clean way to do this, but I do at least have something better than your approach. The user/map->Foo function you're using is based on the static method generated along with the class, user.Foo/create, and it is somewhat classier to invoke that directly instead, through reflection.
user> ((fn [r attrs]
(.invoke (.getMethod (class r) "create"
(into-array [clojure.lang.IPersistentMap]))
nil, (into-array Object [attrs])))
(Foo. 1) {:x 5})
#user.Foo{:x 5}
However, it occurs to me now you may not need to do any of this! You started with the preconception that the way to meet your goal of "build a new thing based on a previous thing" was to start from scratch, but why do that? As long as the record being passed into your function doesn't have any "extension" fields added onto it (i.e., those not part of the record definition itself), then you can simply use clojure.core/into:
(into (Foo. 1) {:x 5}) ;=> #user.Foo{:x 5}
You could also do this:
(defn clear [record]
(reduce (fn [record k]
(let [without (dissoc record k)]
(if (= (type record) (type without))
without
(assoc record k nil))))
record
(keys record)))
(defn map->record [record m]
(into (clear record) m))
Example:
(defrecord Foo [x y])
(map->record (map->Foo {:x 1 :y 2 :z 3}) {:y 4})
;;=> #example.core.Foo{:x nil, :y 4}
I'm not sure if this would be more efficient or less efficient than #amalloy's reflection approach.

How to print each elements of a hash map list using map function in clojure?

I am constructing a list of hash maps which is then passed to another function. When I try to print each hash maps from the list using map it is not working. I am able to print the full list or get the first element etc.
(defn m [a]
(println a)
(map #(println %) a))
The following works from the repl only.
(m (map #(hash-map :a %) [1 2 3]))
But from the program that I load using load-file it is not working. I am seeing the a but not its individual elements. What's wrong?
In Clojure tranform functions return a lazy sequence. So, (map #(println %) a) return a lazy sequence. When consumed, the map action is applied and only then the print-side effect is visible.
If the purpose of the function is to have a side effect, like printing, you need to eagerly evaluate the transformation. The functions dorun and doall
(def a [1 2 3])
(dorun (map #(println %) a))
; returns nil
(doall (map #(println %) a))
; returns the collection
If you actually don't want to map, but only have a side effect, you can use doseq. It is intended to 'iterate' to do side effects:
(def a [1 2 3])
(doseq [i a]
(println i))
If your goal is simply to call an existing function on every item in a collection in order, ignoring the returned values, then you should use run!:
(run! println [1 2 3])
;; 1
;; 2
;; 3
;;=> nil
In some more complicated cases it may be preferable to use doseq as #Gamlor suggests, but in this case, doseq only adds boilerplate.
I recommend to use tail recursion:
(defn printList [a]
(let [head (first a)
tail (rest a)]
(when (not (nil? head))
(println head)
(printList tail))))

Pre-aggregated datastructure in clojure

In OLAP-cubes it's possible to do very quick look ups on large amounts of aggregated data. The major reason for this is that one pre-aggregates data in operations which are easy to combine upwards (mainly +, -, mean, std, max, min and some more).
How to get this "anti-lazy" behaviour in clojure?
I'm thinking on something like
(def world-population {:africa 4e8 ;;this is an aggregation!
:africa/liberia 3.4e6
:africa/ethiopia 7.4e7
...})
How to update a datastructure like this and make sure the parents of an entity is updated too? Do one have to roll one's own ref-implementation?
By storing your data in an atom, you can add watches - essentially callbacks when the atom is updated
Something like this:
(def world-population (atom {:africa 4e8
:africa/liberia 3.4e6
...}))
(add-watch word-population :population-change-key
(fn [key ref old new]
(prn "population change")))
You could build some event propagation logic on top of that.
You could write a recursive rollup function as a higher order function, something like:
(defn rollup
([data heirarchy func]
(loop [top (second (first heirarchy))]
(if (nil? (heirarchy top))
(rollup data heirarchy func top)
(recur (heirarchy top)))))
([data heirarchy func root]
(let [children (reduce (fn [l [k v]] (if (= v root) (cons k l) l)) '() heirarchy)
data (reduce (fn [d c] (if (d c) d (rollup d heirarchy func c))) data children)
child-values (map data children)]
(assoc data root (apply func child-values)))))
Which can then be used with any particular rollup operation or hierarchy you like:
(def populations { :africa/liberia 3.4e6
:africa/ethiopia 7.4e7})
(def geography {:africa/liberia :africa
:africa/ethiopia :africa
:africa :world})
(rollup populations geography +)
=> {:africa 7.74E7,
:world 7.74E7,
:africa/ethiopia 7.4E7,
:africa/liberia 3400000.0}
Obviously it gets more complicated if you have very large data sets or multiple hierarchies etc., but this should be enough for many simple cases.