Evaluate a list of functions in Clojure - clojure

I have a list of functions which have no side-effects and take the same arguments. I need to evaluate each function in my list and put the results into another list. Is there a function in Clojure that does it?

juxt should do it:
((juxt inc dec) 1)
=> [2 0]
(If you literally have a list of functions and you want a list of results, do (apply list ((apply juxt (list inc dec)) 1)), as indicated in the comments.)

(map #(% arg) function-list)
Should do the job?

(map apply [+ - * /] (repeat [1 2 3 4]))
=> (10 -8 24 1/24)

Related

Using a mult-argument Predicate with Filter in Clojure

Is it possible to use filter with a predicate with multiple arguments? If so, how would I do it under the context of this code:
;predicate
(defn classInstructor [instructor class]
(str/includes? class instructor))
(defn instructorClasses [instructor classList]
(filter classInstructor classList))
The map function can take a function that applies to several arguments. For example,
=> (map + [1 2 3] [4 5 6])
(5 7 9)
The + gets two arguments, one from each sequence. There is no corresponding version of filter. You could extend the standard filter as follows:
(defn filter
([f coll]
(clojure.core/filter f coll))
([f coll & colls]
(filter #(apply f %) (apply map vector (cons coll colls)))))
For example,
=> (filter (comp odd? +) [1 2 3] [4 6 8])
([1 4] [3 8])
As you can see, we have to present the surviving sequences somehow. I don't find it persuasive or natural to do so. Not worth doing, I think.
I would do it like so, using an anonymous function:
(defn classInstructor [instructor class]
(str/includes? class instructor))
(defn instructorClasses [instructor classList]
(filter #(classInstructor instructor %) classList))
This way, when one calls instructorClasses, the value of instructor is passed through to classInstructor.

Return a sequence with the elements not in common to two original sequences by using clojure

I have two sequences, which can be vector or list. Now I want to return a sequence whose elements are not in common to the two sequences.
Here is an example:
(removedupl [1 2 3 4] [2 4 5 6]) = [1 3 5 6]
(removeddpl [] [1 2 3 4]) = [1 2 3 4]
I am pretty puzzled now. This is my code:
(defn remove-dupl [seq1 seq2]
(loop [a seq1 b seq2]
(if (not= (first a) (first b))
(recur a (rest b)))))
But I don't know what to do next.
I encourage you to think about this problem in terms of set operations
(defn extrasection [& ss]
(clojure.set/difference
(apply clojure.set/union ss)
(apply clojure.set/intersection ss)))
Such a formulation assumes that the inputs are sets.
(extrasection #{1 2 3 4} #{2 4 5 6})
=> #{1 6 3 5}
Which is easily achieved by calling the (set ...) function on lists, sequences, or vectors.
Even if you prefer to stick with a sequence oriented solution, keep in mind that searching both sequences is an O(n*n) task if you scan both sequences [unless they are sorted]. Sets can be constructed in one pass, and lookup is very fast. Checking for duplicates is an O(nlogn) task using a set.
I'm still new to Clojure but I think the functional mindset is more into composing functions than actually doing it "by hand", so I propose the following solution:
(defn remove-dupl [seq1 seq2]
(concat
(remove #(some #{%} seq1) seq2)
(remove #(some #{%} seq2) seq1)))
EDIT: I think it is better if we define that remove part as a local function and reuse it:
(defn remove-dupl [seq1 seq2]
(let [removing (fn [x y] (remove #(some #{%} x) y))]
(concat (removing seq1 seq2) (removing seq2 seq1))))
EDIT2: As commented by TimothyPratley
(defn remove-dupl [seq1 seq2]
(let [removing (fn [x y] (remove (set x) y))]
(concat (removing seq1 seq2) (removing seq2 seq1))))
There are several problems with your code.
It doesn't test for the end of either sequence argument.
It steps through b but not a.
It implicitly returns nil when any two sequences have the same
first element.
You want to remove the common elements from the concatenated sequences. You have to work out the common elements first, otherwise you don't know what to remove. So ...
We use
clojure.set/intersection to find the common elements,
concat to stitch the collections together.
remove to remove (1) from (2).
vec to convert to a vector.
Thus
(defn removedupl [coll1 coll2]
(let [common (clojure.set/intersection (set coll1) (set coll2))]
(vec (remove common (concat coll1 coll2)))))
... which gives
(removedupl [1 2 3 4] [2 4 5 6]) ; [1 3 5 6]
(removedupl [] [1 2 3 4]) ; [1 2 3 4]
... as required.

How do I replicate items from a list in Clojure?

I've tried this for so many nights that I've finally given up on myself. Seems like an extremely simple problem, but I guess I'm just not fully understanding Clojure as well as I should be (I partially attribute that to my almost sole experience with imperative languages). The problem is from hackerrank.com
Here is the problem:
Problem Statement
Given a list repeat each element of the list n times. The input and output
portions will be handled automatically by the grader.
Input Format
First line has integer S where S is the number of times you need to repeat
elements. After this there are X lines, each containing an integer. These are the
X elements of the array.
Output Format
Repeat each element of the original list S times. So you have to return
list/vector/array of S*X integers. The relative positions of the values should be
same as the original list provided as input.
Constraints
0<=X<=10
1<=S<=100
So, given:
2
1
2
3
Output:
1
1
2
2
3
3
I've tried:
(fn list-replicate [num list]
(println (reduce
(fn [element seq] (dotimes [n num] (conj seq element)))
[]
list))
)
But that just gives me an exception. I've tried so many other solutions, and this probably isn't one of my better ones, but it was the quickest one I could come up with to post something here.
(defn list-replicate [num list]
(mapcat (partial repeat num) list))
(doseq [x (list-replicate 2 [1 2 3])]
(println x))
;; output:
1
1
2
2
3
3
The previous answer is short and it works, but it is very "compressed" and is not easy for new people to learn. I would do it in a simpler and more obvious way.
First, look at the repeat function:
user=> (doc repeat)
-------------------------
clojure.core/repeat
([x] [n x])
Returns a lazy (infinite!, or length n if supplied) sequence of xs.
user=> (repeat 3 5)
(5 5 5)
So we see how to easily repeat something N times.
What if we run (repeat n ...) on each element of the list?
(def N 2)
(def xvals [1 2 3] )
(for [curr-x xvals]
(repeat N curr-x))
;=> ((1 1) (2 2) (3 3))
So we are getting close, but we have a list-of-lists for output. How to fix? The simplest way is to just use the flatten function:
(flatten
(for [curr-x xvals]
(repeat N curr-x)))
;=> (1 1 2 2 3 3)
Note that both repeat and for are lazy functions, which I prefer to avoid unless I really need them. Also, I usually prefer to store my linear collections in a concrete vector, instead of a generic "seq" type. For these reasons, I include an extra step of forcing the results into a single (eagar) vector for the final product:
(defn list-replicate [num-rep orig-list]
(into []
(flatten
(for [curr-elem xvals]
(repeat N curr-elem)))))
(list-replicate N xvals)
;=> [1 1 2 2 3 3]
I would suggest building onto Alan's solution and instead of flatten use concat as this will preserve the structure of the data in case you have input sth like this [[1 2] [3 4]].
((fn [coll] (apply concat (for [x coll] (repeat 2 x)))) [[1 2] [3 4]])
output: => ([1 2] [1 2] [3 4] [3 4])
unlike with flatten, which does the following
((fn [coll] (flatten (for [x coll] (repeat 2 x)))) [[1 2] [3 4]])
output: => (1 2 1 2 3 4 3 4)
as for simple lists e.g. '(1 2 3), it works the same:
((fn [coll] (apply concat (for [x coll] (repeat 2 x)))) '(1 2 3))
output => (1 1 2 2 3 3)
(reduce #(count (map println (repeat %1 %2))) num list)

Standard version or idiomatic use of (fn [f & args] (apply f args))

Every so often I find myself wanting to apply a collection of functions on several collections of parameters. It's easy to do with map and a very simple function.
(map
(fn invoke [f & args] (apply f args))
[- + *]
[1 2 3]
[1 2 3]
[1 2 3])
(-1 6 27)
Searching the web turns up quite a few libraries that define a similar function, often called funcall or invoke. Because of Clojure's penchant for variadic functions, I cannot help but think there should already be a default version of this function.
Is there, or is there another idiomatic way to solve situations like this ?
Edit:
Another form may be
(map
(comp eval list)
[- + *]
[1 2 3]
[1 2 3]
[1 2 3])
(-1 6 27)
Which scares me because of the eval.
If you really don't have a clue about the function name, but you know what the in- and output have to be, you can try https://github.com/Raynes/findfn.
(find-arg [-1 6 27] map '% [- + *] [1 2 3] [1 2 3] [1 2 3])
;=> (clojure.core/trampoline)
This tells us that
(map trampoline [- + *] [1 2 3] [1 2 3] [1 2 3])
;=> (-1 6 27)
Actually, you can abuse trampoline as funcall in clojure. But it is hardly idiomatic, because it is a Lisp-1. The above code evaluates to:
[(trampoline - 1 1 1), (trampoline + 2 2 2), (trampoline * 3 3 3)] which then becomes
[-1 6 27] (in the form a of lazyseq to be precise).
As Adrian Mouat points out in the comment below, this probably isn't the preferred way to solve it. Using a funcall like construct smells a bit funny. There must be a cleaner solution. Until you've found that one, findfn can be helpful ;-).
Edit: this will do what you want (as #BrandonH mentioned):
(map #(apply %1 %&) [- + *] [1 2 3] [1 2 3] [1 2 3])
But this is hardly an improvement over your version -- it just uses a shorthand for anonymous functions.
My understanding is that FUNCALL is necessary in Common Lisp, as it's a Lisp-2, whereas Clojure is a Lisp-1.
There isn't a funcall or equivalent function in the standard Clojure library that works exactly this way. "apply" is pretty close but needs a collection of arguments at the end rather than being purely variadic.
With this in mind, you can "cheat" with apply to make it work as follows by adding an infinite list of nils to the end (which get considered as empty sequences of additional arguments):
(map apply [- + *] [1 2 3] [1 2 3] [1 2 3] (repeat nil))
=> (-1 6 27)
Overall though, I think the sensible approach if you really want to use this function frequently is just to define it:
(defn funcall [f & ps]
(apply f ps))
(map funcall [- + *] [1 2 3] [1 2 3] [1 2 3])
=> (-1 6 27)
(map #(%1 %2 %3 %4) [- + *][1 2 3][1 2 3][1 2 3])
(-1 6 27)
The problem is that if you want to allow a variable number of arguments, the & syntax puts the values in a vector, necessitating the use of apply. Your solution looks fine to me but as Brandon H points out, you can shorten it to #(apply %1 %&).
As the other answerers have noted, it has nothing to do with funcall which I think is used in other Lisps to avoid ambiguity between symbols and functions (note that I called the function as (%1 ...) here, not (funcall %1 ...).
I personally think your first version is pretty clear and idiomatic.
Here's an alternative you might find interesting to consider however:
(map
apply
[- + *]
(map vector [1 2 3] [1 2 3] [1 2 3]))
=> (-1 6 27)
Note the trick of using (map vector ....) to transpose the sequence of arguments into ([1 1 1] [2 2 2] [3 3 3]) so that they can be used in the apply function.
Another approach which is fairly self explanatory: "for each nth function, apply it to all nth elements of the vectors":
(defn my-juxt [fun-vec & val-vecs]
(for [n (range 0 (count fun-vec))]
(apply (fun-vec n) (map #(nth % n) val-vecs))))
user> (my-juxt [- + *] [1 2 3] [1 2 3] [1 2 3])
(-1 6 27)
I can't right now thing of a clojure.core function that you could plug into your map and have it do what you want. So, I'd say, just use your own version.
Matt is probably right that the reason there isn't a funcall, is that you hardly ever need it in a Lisp-1 (meaning, functions and other bindings share the same name space in clojure)
What about this one? It selects the relevant return values from juxt. Since this is all lazy, it should only calculate the elements needed.
user> (defn my-juxt [fns & colls]
(map-indexed (fn [i e] (e i))
(apply map (apply juxt fns) colls)))
#'user/my-juxt
user> (my-juxt [- + *] [1 2 3] [1 2 3] [1 2 3])
(-1 6 27)

Clojure: How to replace an element in a nested list?

I have this deeply nested list (list of lists) and I want to replace a single arbitrary element in the list. How can I do this ? (The built-in replace might replace many occurrences while I need to replace only one element.)
As everyone else already said, using lists is really not a good idea if you need to do this kind of thing. Random access is what vectors are made for. assoc-in does this efficiently. With lists you can't get away from recursing down into the sublists and replacing most of them with altered versions of themselves all the way back up to the top.
This code will do it though, albeit inefficiently and clumsily. Borrowing from dermatthias:
(defn replace-in-list [coll n x]
(concat (take n coll) (list x) (nthnext coll (inc n))))
(defn replace-in-sublist [coll ns x]
(if (seq ns)
(let [sublist (nth coll (first ns))]
(replace-in-list coll
(first ns)
(replace-in-sublist sublist (rest ns) x)))
x))
Usage:
user> (def x '(0 1 2 (0 1 (0 1 2) 3 4 (0 1 2))))
#'user/x
user> (replace-in-sublist x [3 2 0] :foo)
(0 1 2 (0 1 (:foo 1 2) 3 4 (0 1 2)))
user> (replace-in-sublist x [3 2] :foo)
(0 1 2 (0 1 :foo 3 4 (0 1 2)))
user> (replace-in-sublist x [3 5 1] '(:foo :bar))
(0 1 2 (0 1 (0 1 2) 3 4 (0 (:foo :bar) 2)))
You'll get IndexOutOfBoundsException if you give any n greater than the length of a sublist. It's also not tail-recursive. It's also not idiomatic because good Clojure code shies away from using lists for everything. It's horrible. I'd probably use mutable Java arrays before I used this. I think you get the idea.
Edit
Reasons why lists are worse than vectors in this case:
user> (time
(let [x '(0 1 2 (0 1 (0 1 2) 3 4 (0 1 2)))] ;'
(dotimes [_ 1e6] (replace-in-sublist x [3 2 0] :foo))))
"Elapsed time: 5201.110134 msecs"
nil
user> (time
(let [x [0 1 2 [0 1 [0 1 2] 3 4 [0 1 2]]]]
(dotimes [_ 1e6] (assoc-in x [3 2 0] :foo))))
"Elapsed time: 2925.318122 msecs"
nil
You also don't have to write assoc-in yourself, it already exists. Look at the implementation for assoc-in sometime; it's simple and straightforward (compared to the list version) thanks to vectors giving efficient and easy random access by index, via get.
You also don't have to quote vectors like you have to quote lists. Lists in Clojure strongly imply "I'm calling a function or macro here".
Vectors (and maps, sets etc.) can be traversed via seqs. You can transparently use vectors in list-like ways, so why not use vectors and have the best of both worlds?
Vectors also stand out visually. Clojure code is less of a huge blob of parens than other Lisps thanks to widespread use of [] and {}. Some people find this annoying, I find it makes things easier to read. (My editor syntax-highlights (), [] and {} differently which helps even more.)
Some instances I'd use a list for data:
If I have an ordered data structure that needs to grow from the front, that I'm never going to need random-access to
Building a seq "by hand", as via lazy-seq
Writing a macro, which needs to return code as data
For the simple cases a recursive substitution function will give you just what you need with out much extra complexity. when things get a little more complex its time to crack open clojure build in zipper functions: "Clojure includes purely functional, generic tree walking and editing, using a technique called a zipper (in namespace zip)."
adapted from the example in: http://clojure.org/other_libraries
(defn randomly-replace [replace-with in-tree]
(loop [loc dz]
(if (zip/end? loc)
(zip/root loc)
(recur
(zip/next
(if (= 0 (get-random-int 10))
(zip/replace loc replace-with)
loc)))))
these will work with nested anything (seq'able) even xmls
It sort of doesn't answer your question, but if you have vectors instead of lists:
user=> (update-in [1 [2 3] 4 5] [1 1] inc)
[1 [2 4] 4 5]
user=> (assoc-in [1 [2 3] 4 5] [1 1] 6)
[1 [2 6] 4 5]
So if possible avoid lists in favour of vectors for the better access behaviour. If you have to work with lazy-seq from various sources, this is of course not much of an advice...
You could use this function and adapt it for your needs (nested lists):
(defn replace-item
"Returns a list with the n-th item of l replaced by v."
[l n v]
(concat (take n l) (list v) (drop (inc n) l)))
A simple-minded suggestion from the peanut gallery:
copy the inner list to a vector;
fiddle that vector's elements randomly and to your heart's content using assoc;
copy the vector back to a list;
replace the nested list in the outer list.
This might waste some performance; but if this was a performance sensitive operation you'd be working with vectors in the first place.