This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-20
Channels
- # 100-days-of-code (2)
- # aleph (53)
- # architecture (2)
- # aws (3)
- # beginners (230)
- # boot (15)
- # calva (3)
- # cider (19)
- # cljs-dev (1)
- # clojure (139)
- # clojure-conj (3)
- # clojure-italy (47)
- # clojure-nl (19)
- # clojure-spec (26)
- # clojure-uk (98)
- # clojurescript (152)
- # clojutre (4)
- # core-async (22)
- # cursive (5)
- # datomic (48)
- # emacs (11)
- # events (1)
- # figwheel-main (219)
- # fulcro (15)
- # instaparse (3)
- # jobs (4)
- # jobs-rus (1)
- # leiningen (30)
- # luminus (8)
- # off-topic (67)
- # onyx (5)
- # pedestal (16)
- # re-frame (1)
- # reagent (4)
- # reitit (31)
- # ring (8)
- # ring-swagger (3)
- # shadow-cljs (115)
- # specter (4)
- # videos (1)
- # vim (20)
- # yada (15)
I'm struggling to learn how to model my problem domain in clojure and reading as much as I can. Anyways I was looking at this advice https://gist.github.com/reborg/dc8b0c96c397a56668905e2767fd697f#should-i-use-a-namespace-to-bundle-functions-to-model-a-domain-object-like-a-customer-or-product and trying to understand if the advice is dissuading me from creating a map per entity or just a namespace per entity with its associated "getters and setters". If I am reading it correctly i'm assuming I can still map my entities to hashmaps but do so in a way where I can reuse functions. Try to use as few data structures as possible and have lots of functions, basically don't segregate my entities strictly. Any examples on github of a clojure codebase with complex domain modeling?
@dfcarpenter Having "getters and setters" as functions is not idiomatic Clojure. Just use keywords for the items in the hash map.
I am trying to write a function to add 2 positive integers without using the + operator.
(defn inc-1 [x]
(loop [y 1
x x]
(if (not (= 0 y))
(let [c (bit-and x y)
x (bit-xor x y)
y (bit-shift-left c 1)]
(recur y x))
x)))
(defn add [x y]
(let [x1 (atom 0)
y1 (atom 0)
return? (atom false)
result (atom 0)]
(while (not @return?)
(cond (not (= x @x1)) (do (reset! result (inc-1 @result)) (reset! x1 (inc-1 @x1)))
(not (= y @y1)) (do (reset! result (inc-1 @result)) (reset! y1 (inc-1 @y1)))
(and (= y @y1) (= x @x1)) (reset! return? true)))
@result))
@michael.gaare no. inc/decs are not allowed. you can write your own inc, dec using bit operations, then it's legit but @michael.gaare shows very good abstraction. This code is easy to understand
What’s the most idiomatic way to go from a seq of maps that share a common key to a map from a value of that key to the original map?
I have
(def orig [{:k 1 :v "a"} {:k 2 :v "b"} {:k 3 :v "c"}])
user=> (into {} (for [m orig] [(:k m) m]))
{1 {:k 1, :v "a"}, 2 {:k 2, :v "b"}, 3 {:k 3, :v "c"}}
You could also do
(def ms [{:foo 1} {:foo 2} {:foo 3}])
=> #'user/ms
(into {} (map (juxt :foo identity) ms))
=> {1 {:foo 1}, 2 {:foo 2}, 3 {:foo 3}}
@denisgrebennicov @mg How about this?
(defn add [x y] (- x (- y)))
But I think the point was of doing it using bitwise operators, otherwise, dunno ... I've heard about this kind of interview questions
(defn add [x y]
(loop [x x
y y]
(if-not (zero? y)
(recur (bit-xor x y) (bit-shift-left (bit-and x y) 1))
x)))
@orestis maybe group-by
would work for you - it returns a slightly different structure (wraps the value in a vector, in case there are multiple similar keys)
(group-by :k [{:k 1 :v "a"} {:k 2 :v "b"} {:k 3 :v "c"}])
=> {1 [{:k 1, :v "a"}], 2 [{:k 2, :v "b"}], 3 [{:k 3, :v "c"}]}
is there a way to use spec
to enforce an order of keys in a map?
{:a 1 :b 2 :c 3}
passes but {:a 1 :c 3 :b 2}
fails or is automatically re-ordered correctly?
I was hoping i could use such a spec to reorder incoming json with potentially scrambled key order into csv with always the same ordering.
common maps don't generally have a sort order - when you assoc a new value in a map there is no guarantee that it goes to the "end"
what you can do to coerce it to sort by key is (into (sorted-map) {k1 v1 ... kn nv})
user=> (into (sorted-map) {:a 1 :b 3 :c 2})
{:a 1 :b 3 :c 2}
user=> (into (sorted-map) {:a 1 :c 2 :b 3})
{:a 1 :b 3 :c 2}
thx, i kind of did that in a more opaque way by doing this:
(let [keys-sorted (sort (keys req))
values-sorted ((apply juxt keys-sorted) req)]
(`req` being a request map)
and then writing the sorted values. But then i realized i want an order that differs from alphabetical. And that that very order is already in my spec. So i wouldn't like to have to re-write it down here again to enforce it but was hoping i could get spec to do that for memaybe sorted-map-by
would be useful? I've never used spec myself, so not sure if I'll be much help determining what it can do for you.
well I’d first say you should think really hard about why you want to do this in the first place. generally I’d say you should try to avoid relying on sorted data structures if at all possible - it’s way too easy to serialize to edn and lose it on a print/read roundtrip
but you can do it with spec:
(s/every (s/tuple int? keyword?) :into (sorted-map))
user=> (s/def ::c (s/every (s/tuple int? keyword?) :into (sorted-map)))
:user/c
user=> (s/conform ::c {1 :a 2 :b 3 :c})
{1 :a, 2 :b, 3 :c}
actually, trying with some other examples, that’s not working. :into is really designed for default colls and I think is colliding here
so would probably need a post step to dump into a sorted map
but again, I’d think real hard about whether you really need it in the first place
thank you. i need to write to a log to COPY
to redshift from s3. I was convinced that this requires ordered csv files, but it seems it doesn't. One can do json as well. In light of this, i will probably just stick with the json until COPY
supports edn format 😉
I don’t see any reason you need ordered maps to make csv export work - you only need to enforce the order when write a line
juxt
is useful to make a function that plucks values from a map in pred order
user=> (def data [{:a 1 :b "x"} {:a 5 :b "y"}])
#'user/data
(user=> (map (juxt :a :b) data)
([1 "x"] [5 "y"])
that assumes keyword keys, and you drop the column ordering into juxt - that’s a perfectly good input for writing csvs with a lib like data.csv
yeah, that was my starting point. Maybe my question wasn't clear enough. I am somewhat reluctant to have a spec file which specifies something like:
(s/def my-spec (s/keys [:b :c :a]))
and then have my csv-writer which specifies that order again
(map (juxt :b :c :a) data)
It seems redundant and error prone if the spec ever changes. Also, i have quite a few events with different keys and i would have to enlist each of them twice as above, once in the spec and once in the csv-writer, which further escalates the problem. I was just hoping that the spec (which i have written anyways) can take care of the second job (even with something like (map (juxt (keys-from-spec s/my-spec)))
but the principled answer 'avoid relying on order' is probably better anyways. Thanks again @U064X3EF3 @UCQL6E7PY
it is possible to remove the duplication if you’re willing to use eval while defining the spec
but this is actually an area I’m expecting will have better answers in spec in coming months
Anyone have a good up-to-date reference for getting my editor connected to a figwheel clojurescript repl, so I can eval code like I do in clojure? (Vim user at the moment, but will try others if it's easier to set up)
personally, i’ve found emacs to be easier on average for repl support.. fireplace.vim exists but i didn’t find it as useful
Thanks Bruce, I just followed your Using-the-Figwheel-REPL-within-NRepl guide to get a cljs repl. Thought that might work. I'll try it from another editor, maybe that's the problem.
Thanks. Yeah, i've installed spacemacs a few times, but never had time to actually use it. Been happy with figwheel alone, but thought it'd be cool to demo eval in editor for a React talk
yeah i’ve used vim exclusively for years, but evil-mode made switching for the REPL integration a lot more palpable
@stvnmllr2 another option is https://atom.io/packages/proto-repl
also learning a bit about debugging and navigating in emacs will pay dividends. its quite easy to just step through CIDER and then you are very close to being able to submit a patch 🙂
Yeah, I know. But in-editor eval is something CLJS lags behind compared to Clojure, right? Therefore we rely on watching the file system.
protorepl is more mature, but that falls pretty far short of CIDER and Cursive as well
I’m using emacs myself, but I’m willing to give vs code a try for the sake of teammates :)
Right, this is what I think a demo is useful... I base my comments on my experience months ago.
so.. i guess i’m showing my inexperience with JVM, but websockets in aleph are built with manifold streams which seem to accept strings or java.nio.ByteBuffers
or if that’s even the right question to be asking … ultimately all i’d like to do is pass a clojure map through an aleph websocket.
check out this example: https://aleph.io/examples/literate.html#aleph.examples.tcp
that uses gloss, which is pretty nice: https://github.com/ztellman/gloss
here you can see it used for a map: https://github.com/ztellman/gloss/wiki/Introduction
ah, excellent! looks like the piece i’m missing. i’ll dig into this and see how much further i can get. thanks so much for your help!
Nope, because I tried to set it up months ago, failed, then the general advice was “just use figwheel and save your files”. Has that changed now? Can I re-eval a reagent component and see live updates? That would make for a killer demo.
In answer to your question, CLJS eval works very well in cider and has for quite some time
Then is it “just” a matter of setting up some post-eval hooks somewhere to call a function after every eval? Or just bind the re-render to some keystroke and do it manually?
Right, I have to check the cider docs on how to get a CLJS repl again. I think this has changed now, so it kinda “just works”?
:thinking_face: I wonder if you could use mount/component/whatever like in CLJ to re-render your app
It might not even make sense to work this incrementally when doing UI work, but for some reasons I was convinced that it was the expected way.
inline eval is good for the same things in ClojureScript that it is good for in Clojure
yes!! i often have to switch to clj files to try out my code before copying back to cljs
https://cider.readthedocs.io/en/latest/using_the_repl/#customizing-newline-interaction I do this so that its easier to type multiple lines
Many swear by Cursive, but I have no previous IntelliJ experience, and found the number of bells and whistles daunting. No previous Vim and Emacs experience, so I found it mentally challenging to put what I’m actually trying to accomplish aside for the unknown number of days (or weeks? Who knows) it will take me to be sufficiently fluent in them. Calva and VSC seem nice, but don’t seem to support deps.edn etc. just yet.
With regards to editors, I feel like there are some aimed at beginners, some aimed at experts, and virtually none aimed att creating experts out of beginners.
i think emacs is quite helpful at becomming an "expert". everything is documented, navigation to source code is built in. evaluation, debugging, etc. It is quite easy to start poking and prodding with a 20 minute introduction to where files are and how to navigate
@gtzogana i doubt you will find lots of emacs people on a closed platform like slack. This gives an official emacs channel or irc though: https://www.emacswiki.org/emacs/EmacsChannel
I'd raise a thumbs up for cursive + intellij idea. Easy setup and integration, everything you do not know the shortcut for can be clicked or reached quickly by the action bar.
Designing anything that’s sufficiently curated, and yet sufficiently flexible, allows quick entry, and yet continued growth, is really hard in any domain. Arguably, that’s one of the key ingredients in what’s made Apple successful in their domain.
I feel like Lighttable had that goal inherently, along with the idea of taking the feedback loop further, but the project didn’t quite reach maturity.
I bet Emacs and Vim are kind of like Clojure itself, a revelation once understood. From the “entry” aspect, though, it’s a challenging thought to need a tutorial to open a file or switch to another file.
it did still require an investment of time, but the interface was at least discoverable through the HUD menus
Emacs and Vim have a strength in being completely “other” though. The first impression of opening IntelliJ is like being transported back in time to the age where we’d just about popularized GUI, but hadn’t quite mastered it yet.
I like that CIDER is open source. I like that cursive is closed source. One person makes his livelihood from it and is quite responsive
Being completely different is a disadvantage. It makes discovery harder for the beginners. Apart from that, you can customize intellij idea so far you can use key strokes for everything.
It also makes discovery harder when you took a longer break from emacs / vim, cause you have to look up shortcuts again.
I can really see both of them having a niche in being by and for experts though, there’s nothing wrong with that.
Thats true, I just wanted to give a counterpoint for someone starting out with clojure so that he does not have to learn clojure + some editor.
The ecosystem aspect is hard to overcome as well. Lighttable ran into this. We could plot a new editor, I suppose, but it takes enormous muscle just to get the basic aspects right. Even if that is done right, there’s the even greater challenge of the network effects (or lack thereof). All editors need community to provide for the “able to grow into an expert” aspect, even if “entry” and the rest of it is taken care of.
Thats also the reason why clojure / clojurescript is so popular, cause its backed by java / javascript and the jvm.
Absolutely. It’s always mildly amusing when the JVM is brought up as a disadvantage when it’s so obviously a major reason for Clojure’s success.
none of us would be talking about Clojure today if it didn’t use the JVM
which is not to say that the JVM is all benefits. but it’s benefits vastly outweigh its downsides
that’s what I’m saying
people frequently ask for Clojure, but native, ignoring the amazing (and essential) things in the JVM like garbage collection
Thinking of editors, there’s been progress in UX for programmers, but to me it seems like aspects of “simple” and “easy” are as poorly defined in UX as everywhere else. Efforts to enhance UX seem too often to lead down an “easy” path to a local maximum.
I’ve studied design problems in what could be generalized to two domains: let’s call them “the smartphone domain” and the “nuclear reactor domain”.
You cannot and should not design a nuclear reactor control room to the same affordances as a smartphone.
Broadly: smartphones have to be designed for things to be easy to get right. Nuclear reactor control rooms have to be designed for things to be hard to get wrong.
folks want both, and they want it for every possible programming situation, ML, data science, web, libraries, operating systems
For what it’s worth @bhauman, your efforts are astoundingly effective in pursuing both paths.
We haven’t even talked about market forces yet, but yes, if there was an obvious big pot of gold at the other end of this, everyone would be at it.
Google, Apple and others do have incentive to improve the “easy” part, because that yields payoffs in their respective ecosystems, but it’s also limited to getting people entrenched in the ecosystems. Not too much attention to “basic research” or however you want to put it, but more of applicability to their specific business challenges.
Jeez, it just dawned on me that this is #beginners and not #off-topic. Sorry everyone!
Does anyone here have experience with both core.async channels and aleph streams? Does anybody have strong opinions in this regard?
I've used core.async a fair bit, but haven't used manifold directly, but have spent a little bit of time looking at the manifold source. My impression is that core.async is to some degree based more in the formalisms of CSP, whereas manifold doesn't seem to be based on some underlying formalism, so core.async has fewer(but plenty of) kind of weird edges and omissions
particularly when trying to do something like core.async's alt!, manifold I don't think manifold can do that, you can get a deferred from two different streams, and then choose between the deferreds, but you can't un-get the deferred from the stream you didn't choose
but there maybe some different pattern for that case you are supposed to use in manifold (I use alt! a lot)
IIRC, core.async is a fundamental enough model that you can build most other async semantics with it.
it prevents some operations that are allowed in a simpler model, and that way makes certain classes of errors impossible
I've yet to come across something I couldn't model in the end with core.async though. But yes, some things are not allowed, and it takes some effort to reason with channels when starting.
simple example: you can't look at a value ready from a channel without consuming it
this is a straightforward operation in most queue based systems
Yeah, it does stuff like that. You can't check if a channel is closed except by consuming from it.
(but it introduces a class of race conditions that CSP avoids by not having that operation)
right
concurrent ml would be nicer, and would allow you to do things like extend core.async's alt! to work on a mix of core.async channels and java.nio channels
Or it stops consuming from the channel, pausing your producer (assuming it's used to consume)
This is a desirable trait. I've used it to create customized threadpool-like functions.
go loops that read from one source and write to another must introduce a buffer of 1