This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-20
Channels
- # beginners (61)
- # cider (25)
- # cljsrn (7)
- # clojure (76)
- # clojure-austin (1)
- # clojure-russia (10)
- # clojure-uk (2)
- # clojurescript (96)
- # cursive (12)
- # datomic (38)
- # defnpodcast (9)
- # emacs (24)
- # fulcro (1)
- # graphql (5)
- # hoplon (3)
- # jobs (1)
- # keechma (20)
- # leiningen (4)
- # lumo (5)
- # off-topic (13)
- # perun (6)
- # re-frame (19)
- # reagent (1)
- # remote-jobs (2)
- # shadow-cljs (199)
- # sql (6)
- # vim (7)
I have a data structure like this: ({:number 1 :name "John"}{:number 2 :name "Harry"}{:number 3 :name ""})
@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.
@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 let
statments. Can I do all my getting
inside a single let-body?the multiplayer-game-state
example in https://clojure.org/guides/destructuring#_associative_destructuring shows getting one of the nested maps. can one do multiple?
No. By replacing the lhs of the map destructuring with more destructuring, you lose the info about what to do at that level.
fwiw @U064X3EF3 see https://clojurians.slack.com/archives/C053AK3F9/p1516488849000006 for how to do this.
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 https://youtu.be/doZ0XAc9Wtc?t=18m38s ? 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
@david479 Populist talks tend to skate over the facts and/or skews the facts to suit the message. Seen a lot of those.
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.
e.g.
(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 "]
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)
#{r}
(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)
#{r}
(into #{}
(map (fn [x]
(knapsack t
(disj s x)
(conj r x))))
s)))
if only to make it easier to apply other transformations, but it’s not clear this is idiomatic.thanks
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
hi guys
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
oh right
thanks
+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)
+user=>
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
@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 "
nil
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
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__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)]
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