Fork me on GitHub

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 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.

👍 4

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))

(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)))


Is there a better way to do it?


can just do peano:

(defn plus
  [x y]
  (if (pos? y)
    (recur (inc x) (dec y))


if inc and dec are allowed anyway

Denis G09:09:48

@mihir why are you using atoms? are you doing it in parallel?

Denis G09:09:01

@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}}


Just juxt 🙂

😉 8

@denisgrebennicov @mg How about this?

(defn add [x y]  (- x (- y)))

Denis G12:09:20

I assume - is also not allowed. Otherwise it doesn't make sense 😄


No only + is not

Denis G12:09:39

Is it an interview question?


Nope. Self imposed.


Integer.sum 😄

Denis G12:09:17

a + b = a - (- b)

Denis G12:09:17

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))

Denis G12:09:20

(add 3 1) gives you 4?


Maybe, not that great at math.

Denis G12:09:03

😄 looks good but I guess it doesn't work on negative numbers, does it? works O_o

Denis G12:09:34



@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 me


maybe 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.


user=> (into (sorted-map-by >)  {1 :a  2 :b  3 :c} )
{3 :c, 2 :b, 1 :a}

Alex Miller (Clojure team)13:09:33

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

Alex Miller (Clojure team)13:09:46

but you can do it with spec:

Alex Miller (Clojure team)13:09:19

(s/every (s/tuple int? keyword?) :into (sorted-map))

Alex Miller (Clojure team)13:09:58

user=> (s/def ::c (s/every (s/tuple int? keyword?) :into (sorted-map)))
user=> (s/conform ::c {1 :a  2 :b  3 :c})
{1 :a, 2 :b, 3 :c}

Alex Miller (Clojure team)13:09:33

actually, trying with some other examples, that’s not working. :into is really designed for default colls and I think is colliding here

Alex Miller (Clojure team)13:09:23

so would probably need a post step to dump into a sorted map

Alex Miller (Clojure team)13:09:37

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 😉

Alex Miller (Clojure team)13:09:43

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

Alex Miller (Clojure team)13:09:30

juxt is useful to make a function that plucks values from a map in pred order

Alex Miller (Clojure team)13:09:45

user=> (def data [{:a 1 :b "x"} {:a 5 :b "y"}])
(user=> (map (juxt :a :b) data)
([1 "x"] [5 "y"])

Alex Miller (Clojure team)13:09:07

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)))


so my hope was that someone could point me to a keys-from-spec function really...


but the principled answer 'avoid relying on order' is probably better anyways. Thanks again @U064X3EF3 @UCQL6E7PY

Alex Miller (Clojure team)14:09:04

it is possible to remove the duplication if you’re willing to use eval while defining the spec

Alex Miller (Clojure team)14:09:51

but this is actually an area I’m expecting will have better answers in spec in coming months


ok, looking forward to it then


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


vim fireplace has limited functionality compared to cider or cursive


unfortunately things are a little in flux right now


VIM folks seem to enjoy spacemacs


inf-clojure in emacs may be an option if all else fails


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.


I noticed CIDER itself is also in flux, so I can’t really say what to use


I’d heartily recommend CIDER and emacs the docs are pretty good right now


it has instructions for figwheel and figwheel-main


and or try spacemacs

wizard 4

but keep in mind you will probably need to ask for help if its your first time


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 editor eval is the jam, we are sooooo close to having it be easy to set up


CIDER is %97 percent of the way there


Nice, thanks for all the hard work! I'll mention it's coming 🙂


it works now quite well


its just that you need some experience if something goes wrong


and it also works handily in vsCode


yeah i’ve used vim exclusively for years, but evil-mode made switching for the REPL integration a lot more palpable


ok, well.. the easy set up. ok. I'll give it a go


its reccomend straight emacs with evil mode


over spacemacs for starters

👍 8

Hmm.. the VSCode might go over much better with React folks


thanks, i think i tried it once. So it supports cljs eval?


not sure - i've not used it myself


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 🙂


@bhauman a demo with figwheel and vscode doing in-editor eval would be fantastic...


@orestis yeah plus a guide on how to set it up


but … the support isn’t anywhere near as good as CIDER or Cursive


and a tad buggy


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


@orestis have you used it?


its not far behind at all anymore


I’m using emacs myself, but I’m willing to give vs code a try for the sake of teammates :)


I meant in editor eval, have you used that in CIDER or emacs for CLJS?


Right, this is what I think a demo is useful... I base my comments on my experience months ago.


VSCode’s support does lag way behind if that is what you mean


anyone ever used aleph or manifold? having some trouble with streams


yes, fire away


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


not quite sure how to get from something like a clj map to a bytebuffer.


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.


what you need is a called a serializer


same thing as map -> json but this is map -> some binary format


that uses gloss, which is pretty nice:


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!

👍 4

@bhauman No, I mean CLJS in editor eval.


Btw I am grateful for figwheel main. It’s awesome!


@orestis so I was wondering if you use CLJS editor eval in emacs regularly?


or do you rely on the console more?


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.


you can eval


but that’s not going to cause your app to re-render


if you eval a (re-render) fn that will


In answer to your question, CLJS eval works very well in cider and has for quite some time


I can not live without it


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”?


I hear what your are asking, I just think they are different things


Yep, agreed.


and there is no hook for eval


just like Clojure


But yes check the CIDER docs


there are some tricky parts, if you are using clj aliaes


: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


good for checking expressions


resetting state


yes!! i often have to switch to clj files to try out my code before copying back to cljs


I use the repl sometimes, but hard for bigger chucks of code.


nah that’s just hard (editing in the REPL itself)


do you know about the CIDER scratch buffer?


much prefer enter to add a newline and control-enter submit for evaluation


good to know 🙂


I don't know about CIDER scratch buffer, I'm in Vim so wouldn't apply right?


oh yeah that wouldn’t apply


but I guess you get the idea


you create a scratch buffer that you can edit and eval in


and you can accumulate expressions in there


in VIM you could just create a script file or something to do the same I guess


For me, everything but Protorepl has been a struggle.


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.


anyone know if there is an emacs discussion slack?


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


@henrik what would something like that look like?


@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:


unless you mean #emacs


that’s what i thought. thanks


didn’t know about that one though, cool


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.

👍 4

Idea delivers exactly that 🙂


The only disadvantage in my eyes is that cursive is not open source.


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.


that's one of the reasons that I started with (and still use) spacemacs


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.


agreed sveri. that's why I'm really excited for Calva + VS Code


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.

👍 4

Thats also the reason why clojure / clojurescript is so popular, cause its backed by java / javascript and the jvm.


despite being a LISP


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.

Alex Miller (Clojure team)17:09:12

none of us would be talking about Clojure today if it didn’t use the JVM

Alex Miller (Clojure team)17:09:35

because it would be dead

👍 4
💀 4

Or never would have been born, perhaps.

Alex Miller (Clojure team)17:09:17

which is not to say that the JVM is all benefits. but it’s benefits vastly outweigh its downsides


No, it’s just tremendous leverage.

Alex Miller (Clojure team)17:09:48

that’s what I’m saying

Alex Miller (Clojure team)17:09:15

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.


The tricky bit about programming and developing is that it’s a bit of both.


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.


oh thanks, wish I had a team of 10 programmers and support


It’s really, really hard to strike the balance.


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 meant manifold streams*


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)

✔️ 4

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)


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


Well, you can wrap anything you want in a channel really.


A go-loop and a channel will handle most things.


that will likely work, but the go loop ends up acting as extra buffer


Or it stops consuming from the channel, pausing your producer (assuming it's used to consume)


It doesn't have to buffer, but will then pause instead.


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


I.e., constraining concurrency to an arbitrary number of simultaneous executions.


because you read from one source, and then write to another, it doesn't atomically happen as once


Oh yeah, something is always in flight.


In the same sense that functions are buffers


No, this is true.


anyway, cml is really neat


@henrik what do you mean functions are buffers?

Mario C.21:09:12

Is it possible to have variadic multimethod?


yes, but your dispatch function also must be variadic in that case

Mario C.21:09:22

ahh okay I got it

Mario C.21:09:14

How would the (defmulti example ...) look like for a variadic one?

Mario C.21:09:10

nvm found an example