Fork me on GitHub
#beginners
<
2015-07-14
>
paulspencerwilliams10:07:02

Anyone up for a little assistence in diagnosing a NPE thrown when trying to build an associative tree from a list of paths? Specifically in fairly simple code

(defn as-tree []
  (reduce
    (fn [the-map row]
      (let [[prod-type class sub-class] row]
      (assoc
        the-map
        prod-type
        (assoc

          (the-map prod-type)
          
class
          (conj ((the-map prod-type) class) sub-class)))))
    
{}
    [["a" "b" "c"][["a" "b" "d"]]))

dnolen10:07:28

@paulspencerwilliams: (the-map prod-type) could return nil, you can’t invoke nil like you are in ((the-map prod-type) class)

paulspencerwilliams10:07:41

@dnolen: cheers. I know it CAN, but didn't think it would for this trivial list of lists. I assume the outer assoc will have added "a" to the map by the time I'm trying to add b as a child.

dnolen11:07:15

@paulspencerwilliams: that would only happen if the map is mutable, but it isn't

paulspencerwilliams11:07:16

@dnolen: I thought that, but it works for the first, but not second level if that makes sense

dnolen11:07:49

even so that wouldn’t be the evaluation order, inner expressions will always evaluate before outer ones in this case

paulspencerwilliams11:07:34

so this approach using nested assoc is not viable?

dnolen11:07:50

@paulspencerwilliams: I’m only suggesting why the current implementation does not work

paulspencerwilliams11:07:15

dnolen: understood and thank you. Obviously, nil checks would be a kludge. Would building the maps upwards (leaves first) be more idiomatic / reliable?

dnolen11:07:22

@paulspencerwilliams: in this case Clojure already provides all the functions to accomplish what you want, but it’s not clear to me that’s what you’re looking for?

paulspencerwilliams11:07:02

dnolen: I'm trying to convert [["a" "b" "c"]["a" "b" "d"]] into {"a" {"b" ["c" "d"]}}

dnolen11:07:13

yes I know simple_smile

dnolen11:07:01

Just trying to gauge how much of the solution you want.

paulspencerwilliams11:07:39

Okay, in the overall, I'm looking for an idiomatic way of acheving it, but in the short term I wondered why my solution wouldn't work.

dnolen11:07:33

right but I already explained why your solution can’t work

dnolen11:07:56

maps are not mutable, your notion of evaluation order is not the right one

paulspencerwilliams11:07:07

yep, I understand the mutable consequences. That's why I thought approaching it in reverse might work. In effect, the inner loop returning lists, the middle loop associng it to a map and the top level combining these maps. Apologies for my vocabulary, I'm still learning the terms and functions that clojurians use / provide.

dnolen11:07:30

if you build your values inside out, that would work

dnolen11:07:47

you do need to add logic for the initial vector

paulspencerwilliams11:07:59

yes, the first time a subtype of "b" is found?

dnolen11:07:00

I would try this and then look at how update-in combined with fnil handles all of this for you.

paulspencerwilliams11:07:43

dnolen: I will. Thanks for the help. I really enjoy writing in Clojure even though / especially because it warps the mind of someone with 15 years of imperative coding experience.

coyotespike20:07:53

I have a button that :onClick calls a function, which sends http/get to the server. This returns a PDF.

coyotespike20:07:08

I'd like to open this PDF in a new window. I can do this with a straight-up link, but then I can't pass a parameter to the server. How can I replicate the [:a {:href "/make-pdf" :target "_blank"} "make it!"]] with my button/function?

coyotespike20:07:44

(js/window.open response) opens a new window, but this just mangles an odd string.

coyotespike22:07:21

Never mind - I was able to do it by just wrapping the link in a button. No function call necessary. I'll leave Cljs I/O for another day...