Fork me on GitHub

Hello Everyone.


I have a data structure like this: ({:number 1 :name "John"}{:number 2 :name "Harry"}{:number 3 :name ""})


I want to filter this based on name.


if name is empty. it should not be present.


Any idea guys. I am really new in clojure.


@rachna.rajput99 Using :name and seq, where seq will return nil (i.e. falsey) if the collection is empty. And since strings are collections, seq can be used on strings.

(filter (comp seq :name) '({:number 1 :name "John"}{:number 2 :name "Harry"}{:number 3 :name ""}))
;; => ({:number 1, :name "John"} {:number 2, :name "Harry"})


Thank you @U0CM1QURZ. I need to store this updated data. will this solution update the existing data structure?


@rachna.rajput99 Clojure data structures are immutable so when you use filter, map, etc you get back a new data structure and the old one is not changed.


omg filtering on strings like this is so neat


@rachna.rajput99 (comp seq :name) is equivalent to (fn [x] (seq (:name x)), fyi


I have some data which comes from HTML for which I'm trying to access specific values. An entry looks like this:

(def data
[{:type :element, :attrs {:name "4011334"}, :tag :a, :content nil}
{:type :element, :attrs nil, :tag :strong, :content ["Subject:"]}
{:type :element,
:attrs {:href "t.php?id=105375#4011334", :class "tr2"},
:tag :a,
:content ["has Aphex Twin ever come to Pittsburgh?"]}
" Jan 16th, 2018 at 05:24:21 pm\n            "])
It's a vector of maps and strings, and some maps are nested. I'm trying to [ab]use destructuring to minimize getters. I want the href, the Aphex Twin :content, and the date-string. I can either reach into a nested map like so:
(let [[_ _ {{:keys [href]} :attrs} date] data]
                  (pr href date))
=> "t.php?id=105375#4011334" " Jan 16th, 2018 at 05:24:21 pm\n            "
or I can use :keys to get values for some values of the nested map, one level deep.
(let [[_ _ {:keys [attrs content]} date] data]
                  (let [href (:href attrs)]
                    (pr href content date)))
The latter produces the result I want, but I don't like that it's two letstatments. Can I do all my getting inside a single let-body?


the multiplayer-game-state example in shows getting one of the nested maps. can one do multiple?

Alex Miller (Clojure team)13:01:35

No. By replacing the lhs of the map destructuring with more destructuring, you lose the info about what to do at that level.


in my humble opinion, you should be able to do:

(let [[_ _ {:keys [{{:keys [href]} :attrs} content]} date] data]
                  (pr href content date))
but that fails.


Can somebody explain to me what he means ? I can just use a debugger fine in Cider. Was it just not available in 2016? Or its only in cider and no other clojure IDEs?


The cynic in me wants to say "I bet the audience loved that talk...!"


It's a sensationalist talk. It's easy to stand up at an "X Conference" and give a rousing talk about how you went from "Language X" to "Language Y" and it was horrible so you came back to "Language X"...


but he said he went to a clojure user group, so they would have told him if there is a debugger?


Sure he went to a Clojure user group. He rewrote his whole app in Clojure from Ruby. And then he rewrote it again from Clojure to Ruby. shrug


It's best not to give too much weight to such talks... they're great crowd-pleasers.


it wasn't the whole app, it was split into 2 services, one in Clojure and one in ruby, which he admits was a mistake for a small company regardless of the languages involved


I don't put much weight on it, but I still wonder about this particular argument


@david479 Populist talks tend to skate over the facts and/or skews the facts to suit the message. Seen a lot of those.


so debuggers where available in 2016?


As you say, you can use debugging in CIDER just fine. There were debugging tools in Clojure years earlier too.


But they're typically not "step debuggers" in the old-fashioned sense.


Personally I think debuggers are terrible tools in any language so I would never care about a statement that says "Language X doesn't have a debugger"...


(and I've been programming for over 35 years in dozens of languages)


Some people like step debuggers and can't seem to function without them. I've never liked them. I've used them a handful of times in a handful of languages but I just don't find them very useful.


@mfm: I think clojure destructuring is too limited and you should use core.match



(match data [_ _ {:attrs {:href href} :content [content]} date] [href content date])
=> ["t.php?id=105375#4011334" "has Aphex Twin ever come to Pittsburgh?" " Jan 16th, 2018 at 05:24:21 pm\n            "]


but using zipper might be less brittle in case the order of the elements might change


Hello, new to clojure and I am trying to write a knapsack algorithm brute forcer as a simple learning exercise. I have this code which works:

(defn knapsack [T S r]
  (if (= (reduce + r) T)     
    (apply set/union (for [s S] (knapsack T (disj S s) (conj r s))))))
But I was wondering, is this good clojure? How could it be improved?


It seems fine. A few observations is all: 1. capital symbols are not idiomatic 2. Rich seems to regard the 2 arg form of reduce as a mistake; I always supply an initial value myself. 3. I would use a transducer for the second clause nowadays:

(defn knapsack
  [t s r]
  (if (= (reduce + 0 r) t)
    (into #{}
          (map (fn [x]
                 (knapsack t
                           (disj s x)
                           (conj r x))))
if only to make it easier to apply other transformations, but it’s not clear this is idiomatic.


I will have to look at the transducer stuff because I am not familiar with that 🙂


you can do multiple keys, just not inside one another

(let  [[_ _                                                                     
        {:keys  [content]                                                       
         {{:keys  [href]} :attrs}}                                              
        date] data]                                                             
  (pr href content date)) 


but usually a version with multiple destructurings is more maintainable - it's cool that you can do it all in one destructure though


oops, should have tagged @mfm above


what's the effect of quoting, say []?


quoting prevents all evaluation, but [] creates a vector while reading


so you get a vector, but if it has anything in it, those things are quoted


+user=> ,(map type [+ :a 1])
(clojure.core$_PLUS_ clojure.lang.Keyword java.lang.Long)
+user=> ,(map type '[+ :a 1])
(clojure.lang.Symbol clojure.lang.Keyword java.lang.Long)


sometimes the explanation of how lisp works sounds like doctrine of an ancient forgotten religion


I might have had a typo, one moment


@noisesmith and yeah i probably agree that it'd be more maintainable in separate steps. i was trying to do it in the first place to see if it was use or abuse : )


it has nothing to do with the vector, it is about map literal syntax


@david479 i've never used core.match! thanks for that.


@mfm it was a trivial typo - the {{:keys [href]} :attrs}} should have been {:keys [href]} :attrs /tmp/foo.clj:

(def data [{:type :element, :attrs {:name "4011334"}, :tag :a, :content nil}
           {:type :element, :attrs nil, :tag :strong, :content ["Subject:"]}
           {:type :element,
            :attrs {:href "t.php?id=105375#4011334", :class "tr2"},
            :tag :a,
            :content ["has Aphex Twin ever come to Pittsburgh?"]}
           " Jan 16th, 2018 at 05:24:21 pm\n            "])
(let  [[_ _
        {:keys  [content]
         {:keys  [href]} :attrs}
        date] data]
  (prn href content date))
in the repl:
user=> (load-file "/tmp/foo.clj")
"t.php?id=105375#4011334" ["has Aphex Twin ever come to Pittsburgh?"] " Jan 16th, 2018 at 05:24:21 pm\n            "


ah! thank you @noisesmith. i had been trying different combinations of {}'s and couldn't get it. thank you again.


one advantage of doing separate destructures instead of shoving it all into one, is that the result is much easier to read and think about 😄


also, putting multiple destructures into one left hand form isn’t a preformance optimization - the code that destructure expands to is quite unwieldy, in fact a simple optimization is often to replace a destructure with an explicit data access


ha. now having looked at it, i agree!


the cool thing is we have a clojure.core/destructure function that shows us the expansion directly

user=> (destructure '[[_ _
        {:keys  [content]
} :attrs}
         {:keys  [href]} :attrs}
        date] data])
[vec__184 data _ (clojure.core/nth vec__184 0 nil) _ (clojure.core/nth vec__184 1 nil) map__187 (clojure.core/nth vec__184 2 nil) map__187 (if (clojure.core/seq? map__187) (clojure.lang.PersistentHashMap/create (clojure.core/seq map__187)) map__187) map__188 (clojure.core/get map__187 :attrs) map__188 (if (clojure.core/seq? map__188) (clojure.lang.PersistentHashMap/create (clojure.core/seq map__188)) map__188) href (clojure.core/get map__188 :href) content (clojure.core/get map__187 :content) date (clojure.core/nth vec__184 3 nil)]


fixed to have normal let-block layout:

[vec__184 data
 _ (clojure.core/nth vec__184 0 nil)
 _ (clojure.core/nth vec__184 1 nil)
 map__187 (clojure.core/nth vec__184 2 nil)
 map__187 (if (clojure.core/seq? map__187)
            (clojure.lang.PersistentHashMap/create (clojure.core/seq map__187))
 map__188 (clojure.core/get map__187 :attrs)
 map__188 (if (clojure.core/seq? map__188)
            (clojure.lang.PersistentHashMap/create (clojure.core/seq map__188))
 href (clojure.core/get map__188 :href)
 content (clojure.core/get map__187 :content)
 date (clojure.core/nth vec__184 3 nil)]


oh neat! that's a little surprising: it decomposes to nth and get calls and if statements.


the primary distinction between let and let* (and fn vs. fn*) is the that version you normally use is a macro that expands its binding block using destructure before feeding the result to the more basic one