Map Defaults #156 not "Elementary"?

283 views
Skip to first unread message

Phil Virgo

unread,
May 1, 2016, 11:49:21 PM5/1/16
to 4Clojure
Is there an "elementary" solution - which should be something like a line of code?  I had to write a function and as a newbie it took a while!

(#(loop [zz %2  maap {}]
     (if (= ()  zz) 
       maap
       (recur (rest zz) (merge  maap  { (first zz) %1} ))
     )
   ) 5 [:a :s :q]) 

That works but the function with the IDENTICAL logic fails!  Why?

((fn [defy keyz]
    (loop [zz keyz  maap {}]
      (if (= ()  zz) 
        maap
        (recur (rest zz) (merge  maap  { (first zz) defy} ))
      )
    )) 5 [:a :s :q] )

Leif

unread,
May 2, 2016, 10:28:56 AM5/2/16
to 4Clojure
Hi, Phil.

When I was a newbie myself, I wrote a lot of this kind of code.  I think it's a necessary first step to "getting" clojure.  It's fine code for those of us coming from an imperative programming background.  To teach yourself to think in a higher-level, more functional style, I would suggest rewriting this twice:

1. You use loop/recur, building up a data structure as you go.  That suggests a rewrite using `reduce`.  Also, you could look at other ways of adding things to a map: conj and (http://clojure.org/api/cheatsheet > Maps > Create, 'Change')
2. After that, try to identify the combination of clojure.core fns that can replace the reduce you just wrote (harder).  Some hints: (http://clojure.org/api/cheatsheet > Creating a Lazy Seq > From constant) and (http://clojure.org/api/cheatsheet > Using a Seq > Construct coll) 
3. Optionally rewrite yet again, using slightly different functions.  I'll also point out the `for` macro.  I am partial to it, since it is functional, while looking reassuringly imperative / pythonic.

Happy hacking,
Leif

Leif

unread,
May 2, 2016, 10:36:13 AM5/2/16
to 4Clojure
Oh, and both versions of your code worked for me.  Check that you copied just the function part, with no extra/missing parens.

--Leif

Bill Allen

unread,
May 2, 2016, 11:15:16 AM5/2/16
to 4clo...@googlegroups.com
Leif is right, but I'd say simply to your original question, that yes there are very simple one line "elementary" solutions, but you've got to familiarize yourself with the core library functions to know what they are.

What I found very helpful in doing 4clojure problems was to follow other people that have done the problems already. Once I came up with my solution, I would check it against the solutions the people I follow have done. It has almost always been very eye opening and quite instructive.

On Mon, May 2, 2016 at 10:36 AM, Leif <leif.p...@gmail.com> wrote:
Oh, and both versions of your code worked for me.  Check that you copied just the function part, with no extra/missing parens.

--Leif

--
You received this message because you are subscribed to the Google Groups "4Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to 4clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Phil Virgo

unread,
May 4, 2016, 9:03:18 PM5/4/16
to 4Clojure
Thanks - I know I am doing something wrong because my solution was too much work - how do I find other people's solutions?

Bill Allen

unread,
May 4, 2016, 9:32:24 PM5/4/16
to 4clo...@googlegroups.com
On the 4clojure site, there are tabs at the top, one of which is "Top Users". Click that and you'll get a list of people who've solved the most problems (you won't see me, I stopped, for now, at 147). On that page you can click "follow". What that means is that for any problem you've solved, no matter how badly, you can see how the people you're following have solved it.

BTW: leif who originally responded to your request is leifp and he has solve 155 problems. Follow him.

Phil Virgo

unread,
May 5, 2016, 12:49:47 AM5/5/16
to 4Clojure
Thanks Leif!   I just spent a long time failing to figure a way using reduce!  I'll try again tomorrow.  I looked at your solution with "for" which seems very natural and easy to understand.  It is odd that my 2nd version works for you because it absolutely does not work when I submit it.

~Phil  

Leif

unread,
May 5, 2016, 10:24:12 AM5/5/16
to 4Clojure
Yes, feel free to follow me, but bear in mind that many/most of these problems were solved when I was a beginner.  I would say the more people you follow, the better, preferably with different styles.  I am following amalloy, amcnamara, cgrand, chouser, ckirkendall, condotti, gajomi, maximental, and tomchappell.  That mix usually shows me two or three solutions I wouldn't have thought of.

Bear in mind that a lot of people are playing code golf, so their solutions are way more terse than if they were writing code for human consumption.  I've avoided that, at the expense of elegance that I wouldn't be able to pull off anyway.  But you can follow cgrand, who codes as elegantly as only the French can.

--Leif

Leif

unread,
May 5, 2016, 10:43:08 AM5/5/16
to 4Clojure

You’re welcome. Here are the exact parts of your solution I put in the text area:

;; parens cleaned up a bit
#(loop [zz %2  maap {}]
   (if (= () zz)
     maap   
     (recur (rest zz) (merge maap {(first zz) %1}))))
;; also works
(fn [defy keyz]
  (loop [zz keyz  maap {}]
    (if (= () zz)
      maap        
      (recur (rest zz) (merge maap {(first zz) defy})))))

Here’s a translation of a loop/recur to reduce:

(loop [m {}, ks [:a :b :c]]
  (if (seq ks)
    (recur (assoc m (first ks) (first ks)) (next ks))
    m))
;; -->
(reduce (fn [m k] (assoc m k k)) {} [:a :b :c])

Hope that helps,
Leif

Phil Virgo

unread,
May 5, 2016, 3:31:04 PM5/5/16
to 4Clojure
funny and extremely useful - if I stick with this you'll have saved me a vast from a vast chasm of frustration!

Phạm Nam

unread,
May 15, 2019, 4:58:36 AM5/15/19
to 4Clojure
I'm new to this community :) 
Here is my solution, I believe this one is pretty elementary: 

(fn [val coll]
  (let [val (into [] (take (count coll) (repeat val)))]
    (zipmap coll val)))
Reply all
Reply to author
Forward
0 new messages