clojure generating a vector vs a map literal expression - clojure

This seems paradoxical:
(def foo ["some" "list" "of" "strings"])
`[ ~#(apply concat (map (fn [a] [a (symbol a)]) foo)) ]
; ["some" some "list" list "of" of "strings" strings]
; Changing only the outer [] into {}
`{ ~#(apply concat (map (fn [a] [a (symbol a)]) foo)) }
; RuntimeException Map literal must contain an even number of forms
; However, this works:
`{"some" some "list" list "of" of "strings" strings}
; {"list" clojure.core/list, "of" user/of, "strings" user/strings, "some" clojure.core/some}
Whats going on?

The exception is triggered by the reader because it can't read a literal map with one element which is your unsplice form before evaluation.
Workaround:
`{~#(apply concat (map (fn [a] [a (symbol a)]) foo)) ~#[]}

Unless you are writing a macro, it may be easiest to say:
(into {} (map (fn [a] [a (symbol a)]) foo))
;=> {"some" some, "list" list, "of" of, "strings" strings}

Related

clojure.lang.LazySeq cannot be cast to java.lang.CharSequence

I am writing a function that, for any given string, replaces any digits within that String with the same number of '.' characters.
Examples:
AT2X -> AT..X
QW3G45 -> QW...G.........
T3Z1 -> T...Z.
I've written the following Clojure function but I am getting an error I don't quite understand:
java.lang.ClassCastException: clojure.lang.LazySeq (in module: Unnamed Module) cannot be case to java.lang.Charsequence
I'm interpreting from the error that I need to force an evaluation of a lazy sequence back into a String (or CharSequence) but I can't figure out where to do so or if this is correct.
(defn dotify
;;Replaces digits with the same number of '.'s for use in traditional board formats
[FEN]
(let [values (doall (filter isDigit (seq FEN)))]
(fn [values]
(let [value (first values)]
(str/replace FEN value (fn dots [number]
(fn [s times]
(if (> times 0)
(recur (str s ".") (dec times)))) "" (Character/digit number 10)) value))
(recur (rest values))) values))
There is a standard clojure.string/replace function that may handle that case. Its last argument might be not just a string or a pattern but also a function that turns a found fragment into what you want.
Let's prepare such a function first:
(defn replacer [sum-str]
(let [num (read-string num-str)]
(apply str (repeat num \.))))
You may try it in this way:
user> (replacer "2")
..
user> (replacer "9")
.........
user> (replacer "22")
......................
user>
Now pass it into replace as follows:
user> (clojure.string/replace "a2b3c11" #"\d+" replacer)
a..b...c...........
Here's a way to do this using reduce:
(defn dotify [s]
(->> s
(reduce (fn [acc elem]
(if (Character/isDigit elem)
(let [dots (Integer/parseInt (str elem))]
(apply conj acc (repeat dots \.)))
(conj acc elem)))
[])
(apply str)))
(dotify "zx4g1z2h")
=> "zx....g.z..h"
And another version using mapcat:
(defn dotify-mapcat [s]
(apply str
(mapcat (fn [c]
(if (Character/isDigit c)
(repeat (Integer/parseInt (str c)) \.)
[c]))
s)))
There are some issues in your example:
Many of the internal forms are themselves functions, but it looks like you just want their bodies or implementations instead of wrapping them in functions.
It's hard to tell by the indentation/whitespace, but the entire function is just recur-ing, the fn above it is not being used or returned.
One of the arguments to str/replace is a function that returns a function.
It helps to break the problem down into smaller pieces. For one, you know you'll need to examine each character in a string and decide whether to just return it or expand it into a sequence of dots. So you can start with a function:
(defn expand-char [^Character c]
(if (Character/isDigit c)
(repeat (Integer/parseInt (str c)) \.)
[c]))
Then use that function that operates on one character at a time in a higher-order function that operates on the entire string:
(apply str (mapcat expand-char s))
=> "zx....g.z..h"
Note this is also ~5x faster than the examples above because of the ^Character type-hint in expand-char function.
You can do this with str/replace too:
(defn expand-char [s]
(if (Character/isDigit ^Character (first s))
(apply str (repeat (Integer/parseInt s) \.))
s))
(str/replace "zx4g1z2h" #"." expand-char)
=> "zx....g.z..h"

How to test in Clojure if any given value is not-empty collection?

I need a predicate which returns logically true if the given value is a not-empty collection and logically false if it's anything else (number, string etc.).
And more specifically, that the predicate won't throw the IllegalArgumentException if applied to single number, or string.
I came up with the following function, but I'm wondering if there is some more idiomatic approach?
(defn not-empty-coll? [x]
(and (coll? x) (seq x)))
This will satisfy following tests:
(is (not (not-empty-coll? nil))) ;; -> false
(is (not (not-empty-coll? 1))) ;; -> false
(is (not (not-empty-coll? "foo"))) ;; -> false
(is (not (not-empty-coll? []))) ;; -> nil (false)
(is (not (not-empty-coll? '()))) ;; -> nil (false)
(is (not (not-empty-coll? {}))) ;; -> nil (false)
(is (not-empty-coll? [1])) ;; -> (1) (true)
(is (not-empty-coll? '(1))) ;; -> (1) (true)
(is (not-empty-coll? {:a 1})) ;; -> ([:a 1]) (true)
EDIT: A potential use case:
Let's say we need to process some raw external data which are not (yet) under our control. Input could be for example a collection which contains either primitive values, or nested collections. Other example could be a collection holding some inconsistent (maybe broken?) tree structure. So, we can consider mentioned predicate as first line data cleaning.
Otherwise, I agree with comments that is better to explicitly separate and process collection and non-collection data.
How about using Clojure protocols and type extensions to solve this?
(defprotocol EmptyCollPred
(not-empty-coll? [this]))
(extend-protocol EmptyCollPred
Object
(not-empty-coll? [this] false)
nil
(not-empty-coll? [this] false)
clojure.lang.Seqable
(not-empty-coll? [this] (not (empty? (seq this)))))
(is (not (not-empty-coll? nil))) ;; -> false
(is (not (not-empty-coll? 1))) ;; -> false
(is (not (not-empty-coll? "foo"))) ;; -> false
(is (not (not-empty-coll? []))) ;; -> nil (false)
(is (not (not-empty-coll? '()))) ;; -> nil (false)
(is (not (not-empty-coll? {}))) ;; -> nil (false)
(is (not-empty-coll? [1])) ;; -> (1) (true)
(is (not-empty-coll? '(1))) ;; -> (1) (true)
(is (not-empty-coll? {:a 1})) ;; -> ([:a 1]) (true)
Maybe it would be cleaner to extend just String and Number instead of Object - depends on what do you know about the incoming data. Also, it would be probably better to filter out nils beforehand instead of creating a case for it as you see above.
Another - conceptually similar - solution could use multimethods.
As suggested in the comments, I would consider calling not-empty? with a non-collection argument to be an invalid usage, which should generate an IllegalArgumentException.
There is already a function not-empty? available for use in the Tupelo library. Here are the unit tests:
(deftest t-not-empty
(is (every? not-empty? ["one" [1] '(1) {:1 1} #{1} ] ))
(is (has-none? not-empty? [ "" [ ] '( ) {} #{ } nil] ))
(is= (map not-empty? ["1" [1] '(1) {:1 1} #{1} ] )
[true true true true true] )
(is= (map not-empty? ["" [] '() {} #{} nil] )
[false false false false false false ] )
(is= (keep-if not-empty? ["1" [1] '(1) {:1 1} #{1} ] )
["1" [1] '(1) {:1 1} #{1} ] )
(is= (drop-if not-empty? ["" [] '() {} #{} nil] )
["" [] '() {} #{} nil] )
(throws? IllegalArgumentException (not-empty? 5))
(throws? IllegalArgumentException (not-empty? 3.14)))
Update
The preferred approach would be for a function to only receive collection parameters in a given argument, not a mixture scalar & collection arguments. Then, one only needs not-empty given the pre-knowledge that the value in question is not a scalar. I often use Plumatic Schema to enforce this assumption and catch any errors in the calling code:
(ns xyz
(:require [schema.core :as s] )) ; plumatic schema
(s/defn foo :- [s/Any]
"Will do bar to the supplied collection"
[coll :- [s/Any]]
(if (not-empty coll)
(mapv bar foo)
[ :some :default :value ] ))
The 2 uses of notation :- [s/Any] checks that the arg & return value are both declared to be a sequential collection (list or vector). Each element is unrestricted by the s/Any part.
If you can't enforce the above strategy for some reason, I would just modify your first approach as follows:
(defn not-empty-coll? [x]
(and (coll? x) (t/not-empty? x)))
I'm hoping you know at least a little about the param x so the question becomes: Is x a scalar or a non-empty vector. Then you could say something like:
(defn not-empty-coll? [x]
(and (sequential? x) (t/not-empty? x)))

Clojure partial right

I have the following function
(defn fun [a b] (str a b))
(fun "1" "2") ;; --> "12"
Thanks to (partial) I can turn it into (fun b) and have a fixed a
(def fun2 (partial fun "1"))
(fun2 "2") ;; --> "12"
Does clojure have something like (partial-right) or a way to rearrange the arguments of a function so that instead of having a fixed a I can have a fixed b and hence have the function (fun a)?
Thanks
(defn partial-right [f & args1]
(fn [& args2]
(apply f (concat args2 args1))))
But ask yourself...why isn't this already part of the standard library? Is it perhaps that other people have wandered this way and it turned out badly?
For your particular example you could go with multi arity:
(defn fun
([a b] (str a b))
([a] (str a "1")))

Combining methods in Clojure

Suppose we have a multimethod foo. It has several realizations. Let's say that one of them is called when argument of foo is a string that contains character \r and another is executed when argument of foo is a string containing character \!. Pseudocode:
(defmulti foo ???) ; can't come up with function..
(defmethod foo \r [_]
(println "one"))
(defmethod foo \! [_]
(println "two"))
So when we call our function like this:
(foo "right!") ;; desired output:
one
two
;; => nil
Important thing here is that list of supported methods should be not rigid, but expandable, so new methods can be added later without touching the original code.
Although I improved my Clojure skill significantly in last few days, I still lack experience. My best idea is to keep a map with pairs 'character - function' and then manually traverse it and execute right functions. In this case I will also need some interface to register new functions, etc. What is idiomatic solution?
I think multimethods don't work the way you expect them to work.
That is: the dispatch in multimethods is called only once for a single multimethod call, so there's no way of getting the result you expect (both 'one' and 'two' printed for "right!" as argument) unless you define one implementation that actually handles the case of having both \r and \! in the input string and prints the output you want.
This will not be easily expandable.
Nicer way to achieve what you want is to make multiple calls explicitly by iterating the input string:
; You want the dispatch function to just return the character passed to it.
(defmulti foo identity)
; The argument list here is mandatory, but we don't use them at all, hence '_'
(defmethod foo \r [_]
(println "one"))
(defmethod foo \! [_]
(println "two"))
; You need the default case for all the other characters
(defmethod foo :default [_]
())
; Iterates the string and executes foo for each character
(defn bar [s]
(doseq [x s]
(foo x)))
so calling
(bar "right!")
will print:
one
two
Edit
If you need to access the whole string inside the multimethod body, then pass it explicitly together with the character:
; You want the dispatch function to just return the character passed to it as the first arg.
(defmulti foo (fn [c _] c))
(defmethod foo \r [c s]
(println "one"))
(defmethod foo \! [c s]
(println "two"))
; The default now takes two arguments which we ignore
(defmethod foo :default [_ _] ())
; Iterates the string and executes foo for each character
(defn bar [s]
(doseq [x s]
(foo x s)))
A plain list of functions would allow arbitrary conditionals. Also Regexs may make your life simpler if you are dealing with strings:
;; start with some functions
(defn on-r [x]
(when (re-find #"r" x)
"one"))
(defn on-! [x]
(when (re-find #"!" x)
"two"))
(def fns (atom [on-r on-!]))
;; call all functions on some value
(keep #(% "right!") #fns)
=> ("one" "two")
(keep #(% "aaaa") #fns)
=> ()
;; later add more functions
(defn on-three [x]
(when (= 3 (count x))
"three"))
(swap! fns conj on-three)
(keep #(% "bar") #fns)
=> ("one" "three")
;; or just use different rules altogether
(def other-fns [#(when (rand-nth [true false])
(str % (rand-int 10)))
#(when (nil? %) "nil")])
(keep #(% nil) other-fns)
=> ("3" "nil")

Howto find a listitem which contains a specific substring

I have a list of strings, fx '("abc" "def" "gih") and i would like to be able to search the list for any items containing fx "ef" and get the item or index returned.
How is this done?
Combining filter and re-find can do this nicely.
user> (def fx '("abc" "def" "gih"))
#'user/fx
user> (filter (partial re-find #"ef") fx)
("def")
user> (filter (partial re-find #"a") fx)
("abc")
In this case I like to combine them with partial though defining an anonymous function works fine in that case as well. It is also useful to use re-pattern if you don't know the search string in advance:
user> (filter (partial re-find (re-pattern "a")) fx)
("abc")
If you want to retrieve all the indexes of the matching positions along with the element you can try this:
(filter #(re-find #"ef" (second %)) (map-indexed vector '("abc" "def" "gih")))
=>([1 "def"])
map-indexed vector generates an index/value lazy sequence
user> (map-indexed vector '("abc" "def" "gih"))
([0 "abc"] [1 "def"] [2 "gih"])
Which you can then filter using a regular expression against the second element of each list member.
#(re-find #"ef" (second %))
Just indices:
Lazily:
(keep-indexed #(if (re-find #"ef" %2)
%1) '("abc" "def" "gih"))
=> (1)
Using loop/recur
(loop [[str & strs] '("abc" "def" "gih")
idx 0
acc []]
(if str
(recur strs
(inc idx)
(cond-> acc
(re-find #"ef" str) (conj idx)))
acc))
For just the element, refer to Arthur Ulfeldts answer.
Here is a traditional recursive definition that returns the index. It's easy to modify to return the corresponding string as well.
(defn strs-index [re lis]
(let [f (fn [ls n]
(cond
(empty? ls) nil
(re-find re (first ls)) n
:else (recur (rest ls) (inc n))))]
(f lis 0)))
user=> (strs-index #"de" ["abc" "def" "gih"])
1
user=> (strs-index #"ih" ["abc" "def" "gih"])
2
user=> (strs-index #"xy" ["abc" "def" "gih"])
nil
(Explanation: The helper function f is defined as a binding in let, and then is called at the end. If the sequence of strings passed to it is not empty, it searches for the regular expression in the first element of the sequence and returns the index if it finds the string. This uses the fact that re-find's result counts as true unless it fails, in which case it returns nil. If the previous steps don't succeed, the function starts over with the rest of the sequence and an incremented index. If it gets to the end of the sequence, it returns nil.)