Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrong number of args (0) passed to: PersistentHashMap

Tags:

clojure

I'm very new to Clojure, and am trying to learn it by porting one of my code, however I'm currently stuck in the following problem:

=> lineup
{:c b4|b4|b3|b3, :sg b6|b11|b6|b6, :sf b7|b5|b5|b5, :pf b3|b1|b1|b1, :pg b10|b10|b11|b10}
=> (validate-lineup lineup)
ArityException Wrong number of args (0) passed to: PersistentHashMap  clojure.lang.AFn.throwArity (AFn.java:437)

And here's the function:

(defn validate-lineup [lineup]
    (map (fn [position]
        ((hash-map (position 0)
            (map
                (fn [s] (.substring s 1))
                (str/split (position 1) #"\|"))
                ))
        ) lineup))

And I'm trying to produce something like the following result:

{:c {"4" "4" "3" "3"} :sg {"6" "11" "6" "6"} :sf {"7" "5" "5" "5"} ... }

Thanks for the help, and if I'm not writing in the correct "Lisp" way, please teach me how as well.

like image 638
TheOnly92 Avatar asked Aug 05 '12 12:08

TheOnly92


1 Answers

Your main problem is here:

(fn [position]
  ((hash-map (position 0)
             (map
               (fn [s] (.substring s 1))
               (str/split (position 1) #"\|")))))

You create hash-map and then call it as function (note double parenthesis before hash-map). You can remove it and get this:

(fn [position]
  (hash-map (position 0)
             (map
               (fn [s] (.substring s 1))
               (str/split (position 1) #"\|"))))

This way validate-lineup will return

({:c ("4" "4" "3" "3")} 
 {:sg ("6" "11" "6" "6")} 
 {:sf ("7" "5" "5" "5")} 
 {:pf ("3" "1" "1"` "1")} 
 {:pg ("10" "10" "11" "10")})

But you need single map, not a sequence of maps. You can merge them:

(apply merge (validate-lineup lineup))

Some advices:

Use subs instead of .substring: (fn [s] (subs s 1))
Use destructuring when you iterate through map

(fn [[key value]]
  (hash-map key
             (map
               (fn [s] (subs s 1))
               (str/split value #"\|"))))

There is a neat way to create map from vector of pairs using into function. So you can transform lineup to vector of pairs where first item of pair is a key and second is a list of numbers:

(defn validate-lineup [lineup]
  (into {} (map (fn [[key value]]
                    [key
                     (map #(subs s 1) (str/split value #"\|"))])
             lineup)))

You can parse b4|b4|b3|b3 to sequence of numbers by re-seq:

user=> (re-seq #"\d+" "b1|b2|b3")
("1" "2" "3")

And finally you can replace outer map with for macro:

(defn validate-lineup [lineup]
  (into {} (for [[key value] lineup]
                [key (re-seq #"\d+" value)])))
like image 196
Mikita Belahlazau Avatar answered Sep 28 '22 01:09

Mikita Belahlazau