This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-12-16
Channels
- # adventofcode (76)
- # aleph (1)
- # aws (2)
- # beginners (101)
- # boot (1)
- # boot-dev (1)
- # calva (25)
- # cider (12)
- # cljs-dev (29)
- # clojure (214)
- # clojure-europe (1)
- # clojure-nl (5)
- # clojure-spec (1)
- # clojure-uk (6)
- # clojurescript (155)
- # data-science (1)
- # datomic (48)
- # figwheel-main (5)
- # immutant (1)
- # leiningen (11)
- # nrepl (2)
- # off-topic (24)
- # pathom (2)
- # pedestal (2)
- # portkey (8)
- # protorepl (5)
- # re-frame (2)
- # rum (4)
- # shadow-cljs (21)
Say you need a data model for contacts in a quick application you're building. Where would you go to find a decent, complete, battle driven data model for that?
Wouldn’t a hash-map work well for looking up contacts? Not sure what the use case is here.
I may be using the wrong term there. What I mean is more like this:
[{:id int
:name string
:nickname [string & optional strings]
:addresses [{:street,...} {:street...}]
:phone [phone-1 phone-2 phone-3]
:father opt-id
...}]
Like, what is expected of a complete contact. Hard to explain since I have very little experience with databases and data in general. Maybe people probably set this things up in databases, so I should probably be looking for "database contact model" or something like this.
You could definitely do that! Keep in mind whether you want to do a relational model or a nosql model, which might lead to you to actually create a database to index records rather than storing them in memory. The example you showed seems solid. Think about how you'll query the records and what your use case is most importantly.
Thank you 🙂
hey folks, can i consider this (doall (map @profiles connections-ids))
under side effect of @profiles
?
Daouda also posted the same question to #clojure channel, where I have sent a few responses.
What's the operation that removes a thing from a set?
I have a list of maps like this ({:type "G", :location [2 1], :hp 300} {:type "G", :location [5 5], :hp 250})
and I would like to apply a function to the :hp key for an element where the :location is [2 1] for example. I'd like to have the resulting list. Is there an idiomatic way to do this "select for update" logic?
I’m not sure if there’s a better idiom but (map #(if (= [2 1] (:location %)) (update % :hp f) %) data)
would be clear enough IMO
By the way you phrase the question, I would ask whether you should be using a map indexed by location as your data structure, rather than a list
@U064X3EF3 what do you mean?
I think Alex is saying if your data structure was {[2 1] {:type “G” :hp 300}}
instead then the operation would be trivial and more efficient.
I used to program in C# for my job. Almost the only way to interact with your code is to press f5 and run the entire application or set up unit tests. There was a program called LinqPad that was a quick way to evaluate and interact with code and scripts and it was amazing. You can write a little code and exercise it and see how it behaves rather than setting up a unit test and 4 mocked objects injected in. Python and ruby both have repls as well but they are different a little. I think stu halloway put it best in that a lisp's repl allows your tools to run in your code rather than the opposite where the code runs in your tools.
Does Clojure have a package manager/build tool like cargo
of rust or mix
of Elixir? Sorry my questions are dumb.
you most probably want lein
: https://leiningen.org/
but there's also deps.edn a newer take on package management. It is unabashedly not a build tool though. https://clojure.org/guides/deps_and_cli
Can someone explain to me the reason why deref
s will trigger transaction retries? I am not sure, but as I understood it, the STM system will try to guarantee that the ref values seen during transactions are the same as they were at the beginning of the transaction. Am I correct?
I am confused because I don't understand the reason for this. What if I want the latest value in the ref, and not the one given at the beginning of the transaction?
In what way is a transaction worthy of the name 'transaction' if it computes a new state based upon a mix of different starting states?
I am not saying there is no such thing -- if there is such a system that calls a thing like that a transaction, I would be interested in learning about it.
I also do not know for certain whether deref's always trigger a transaction retry inside of a dosync
, or only in some cases. I would guess it is not always, but perhaps only if the STM implementation detects that the ref
has been updated by a different transaction, since the current transaction began.
And note that deref
is the same operation used for uncoordinated dereferencing of Clojure atoms, promises, futures, etc., not only STM ref
s, so what I say above is only intended to refer to ref
s.
since there are no transactions at all for any of those other kinds of objects on which a deref
can be performed.
I see. I liked your first statement, it gave me a good point of view of why we need a "static snapshot of the world" inside of the transaction
Now I understand the reason for the ref-history mechanism
Yes, deref
will trigger a transaction retry only if the value of the ref was changed since the beginning of the transaction.
Thank you, sir!
I'm implementing an algorithm with many recur places and complex data structures. I'd like to be able to trace and see how the execution flows. What would be a good way to instrument the code to dump tracing messages and the contents of the data to the console or file?
You can get a fair way with println
🙂
- There are lots of useful versions of tracing functions, often called spy
. One that you automatically have on hand is clojure.tools.logging/spy
.
- Many clj/s editors like emacs/CIDER include debuggers.
- If you need a really powerful approach, take a look at Sayid (although I’d try lighter-weight solutions first):
https://github.com/clojure-emacs/sayid
I want to transform:
(def data [{:id {4 67} :person_id {12 74}}])
; or
(def data-2 [{:id {4 67} :person_id {12 74}} {:id {12 83} :person_id {14 89}}])
to
((4 67 12 74))
((4 67 12 74) (12 83 14 89))
My current solution is
(map
(fn [m]
(reduce (fn [acc [k v]] (concat acc (first v))) '() m))
data-2)
This does not feel as "nice" as I imagine it could be. Any suggestions for alternatives.
> assumption: the values of each k/v pair in data
and data-2
will only ever have 1 kv pair in them.Not off the shelf solution, but you can call vals
on a map to get the … vals
oh wait, its maps in maps
why is that, don’t you want to have like maps of keys -> lists/sets/vecs?
You could do this... (->> data (map vals) (map #(map vec %)) (map flatten))
Should really clean up that map map though
it's a terrible solution
What would you recommend as an alternative?
{:id [4 67] :person-id [12 74]}
or {:id #{4 67} :person-id #{12 74}}
or {:id '(4 67) :person-id '(12 74)}
You seem to not care that they are key value pairs ie one is associated with another. So don't use an associative data structure
(thats vecs/sets/lists respectively)
i wasn't sure if the id maps were actually being used for lookups, otherwise the first probably makes the most sense
{4 67}
would represent a before and after value.
is it actually a mapping, thats the question you should ask yourself ^^
In my mind, yes. But I might be too close to this at this point 😜
So all instances of 4
will become 67
. Thats why I initially thought map could be a good option.
well, thats a bit conflicting with your desire to flatten them to lists
Are you trying to maintain a history of IDs for these records?
maybe I am just misunderstanding
Imagine a db value is updated from 4
-> 67
and you need to remember this. That is what I have in mind.
The need to flatten them comes when I have to transform them to something a sql query can use.
right makes sense
It would be complicated to update those maps multiple times like if {4 67} turned into {5 4 4 67}
Maybe just maintain current ID and set/vector of past IDs? Then it would be easy to collect these, if this is the only option for maintaining history of a record
yeah, you could maintain history in a vec instead right by treating it as a fifo
user=> (def data [{:id {:old 4 :new 67} :person-id {:old 12 :new 74}}])
user=> (->> data (map vals) (flatten)
#_=> (map :old))
(4 12)
user=> (->> data (map vals) (flatten)
#_=> (map :new))
(67 74)
user=> (interleave
#_=> (->> data (map vals) (flatten)
#_=> (map :old))
#_=> (->> data (map vals) (flatten)
#_=> (map :new)))
(4 67 12 74)
probably a cleverer way to do it, but it certainly looks clearer to me what’s happening if I were to read it a week later
bikeshedding: would prefer :current
and :previous
:new
and :old
sound like future and past, :current
and :previous
more like current and past.
I like that alternative @lilactown.
lol I figure @tkjone can put his own spin on the names according to his domain. but the point is: names are good!
haha indeed.
ofcourse you can, you make :previous
a vec or a list
You can find just as good a name without this no. Just call it {:ids-over-time [2 45 67]}
Hum, ya, maybe that's clearer to split out the current and the prior ones. But it seems harder to work with. Depending what you need to do
as long as things are consistently collections or consistently scalars ^^
But I do like the suggestion of say {:current-id 45 :prior-ids [2 34 67]}
in terms of readability. Though it also brings some question. Like the code must now maintain the invariants of coordinating the two. Making sure to conj to prior and update current when a new id is added. And its unclear if prior-ids include current or not.
Catch to the above: there will never be multiple prior-ids
. Its only going to be something like 1
-> 15*
Eh, if this was persistent data, like the model for a document store. I would design for future extension in mind, and so I'd make it a vector just in case in the future we need further history.
I'm getting a NullPointerException clojure.core/name (core.clj:1546)
in a function that turns a keyword into a vector. Any ideas why?
@tkjone Anyway, no right answer here. I think using keys like current and prior does make it more readable, so if you really don't need more then one prior, it seems a pretty good choice.
Thanks all!
Also, just test your keyword to vector function. What does it do if you give it nil? Does it throw that error?
I have a log entry as a map that contains a :timestamp
which is a java.time.OffsetDateTime
. How should I print it to an edn file? pr-str
gives me :timestamp #object[java.time.OffsetDateTime 0x67573db5 "2018-12-05T00:15:30.151200+05:30"]
I want it to show with #inst
you can implement print-method for it, like here: https://gist.github.com/defndaines/0b5c37c8c585e975d8c5b70271a1dce1
What's the difference b/w print-method
and print-dup
? Which should be implemented when?
This worked beautifully:
(defmethod print-method java.time.OffsetDateTime
[dt out]
(.write out (str "#inst \"" (.toString dt) "\"")))
Thanks @jkr.sw!I keep forgetting that read
and print
are extensible via multimethods.