This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-06-05
Channels
- # announcements (10)
- # beginners (59)
- # calva (172)
- # cider (13)
- # clj-kondo (1)
- # cljdoc (10)
- # cljs-dev (4)
- # cljsrn (65)
- # clojure (144)
- # clojure-europe (2)
- # clojure-italy (26)
- # clojure-losangeles (1)
- # clojure-nl (14)
- # clojure-spec (26)
- # clojure-uk (91)
- # clojurescript (75)
- # core-async (53)
- # cursive (11)
- # datomic (16)
- # fulcro (42)
- # graalvm (29)
- # graphql (9)
- # kaocha (3)
- # leiningen (22)
- # off-topic (26)
- # qa (1)
- # re-frame (3)
- # reagent (7)
- # reitit (10)
- # rewrite-clj (56)
- # robots (1)
- # shadow-cljs (107)
- # spacemacs (10)
- # specter (5)
- # sql (15)
- # tools-deps (39)
- # vim (11)
Morning. @rickmoynihan coming back to your comment the other day around loop/recur, etc., what are you thoughts on for
and how it ties into what you were mentioning before? https://clojurians.slack.com/archives/C064BA6G2/p1559135544122400
Nothing wrong with for
🙂
It’s essentially list comprehensions, so very powerful, like map
you reach for it when you’re constructing sequences from others.
I’d prefer it to map
when you have nested iteration, and sometimes even if you don’t, as it can read better — though being a macro it naturally doesn’t compose. Also :while
and :when
and :let
can be very useful, and can be more elegant than the equivalent usage of sequence functions.
obviously it’s also lazy, so if you want to realise eagerly effects use doseq
Cool, thanks for the explanations all round 🙂
oo never used :while
in for, use :when
and :let
all the time
That gets my vote... Anything practical that helps us use the powerful abstractions in Clojure would be great.
@reborg did a great workshop on transducers a couple of years ago. Would be great to see more on the powerful features of clojure.core
We keep getting a steady stream of new people joining the community, so definitely an audience for this
Thanks for the invite; I’d love to help out but I’m not sure I’ll be able to make clojure X this year — let alone run a workshop. 😞
No problem. The invite will remain open 🙂 If I create some of my own content along those lines, I'll let you know and perhaps if you have time you could have a little review
Cool. Always happy to review anything you put together.
I found this video quite good in explaining for
and list comprehension in clojure [27:35]:
https://www.youtube.com/watch?v=5lvV9ICwaMo

That gets my vote... Anything practical that helps us use the powerful abstractions in Clojure would be great.
@reborg did a great workshop on transducers a couple of years ago. Would be great to see more on the powerful features of clojure.core
We keep getting a steady stream of new people joining the community, so definitely an audience for this
Oh and by the way, we are running 9 events this month,. so hopefully something for everyone... Hope you will make some of them
That's pretty incredible @jr0cket - 9 events in one month! 👍
I see the Crux evening is on meetup twice
Thanks. There are some dedicated people that make these events happen, so my thanks to them. Its great to see the JUXT team come out and play this month too
https://www.meetup.com/London-Clojurians/events/262005356/ and https://www.meetup.com/London-Clojurians/events/262005170/
Ah, it seems someone created an extra event. I guess I will do some more http://meetup.com coaching 😁
https://www.meetup.com/London-Clojurians/events/262005356/ is the legit one
Does anyone know how to “prettify” a large map in an Emacs buffer, please? My Google-Fu is failing me. (I use Spacemacs in Evil Mode if that’s relevant)
is there something in that ns?
see pp in that ns
Yup, pp is my go-to, there's also this: https://github.com/brandonbloom/fipp if you want something else.
In my non-scientific testing, it has proven to be at least five times as fast as clojure.pprint.
🙂
@maleghast there's an option in cider for doing it automatically
Yeah M-x cider-pprint-eval-last-sexp
not sure what spacemacs binding it’ll have but for me in Emacs it’s bound to C-c C-p
. cc @maleghast
@maleghast , e P
opens the result pretty printed in a new window
I also have fipp in my Spacemacs config https://practicalli.github.io/spacemacs/
I totally forgot about the cider inspector; it’s just something I’m not in the habit of using, as I usually prefer a printed representation. I wonder if it will be extended to support datafy / nav ; as it’s essentially the equivalent of REBL; but 5 invented ~5years before Rich 😉
There's been some issues with making it work (which is why rebl didn't use nrepl in the first place)
@rickmoynihan tbh, I imagine you're vaguely familiar with the issues that crop up due to your work.
REBL didn't use nREPL I suspect because Rich doesn't think nREPL is the "right" way to build REPL tooling, based on what he has said publicly about streaming REPLs (c.f. nREPL).
yeah — though as I recall nREPL was originally inspired by stuff Rich was talking about back in the day. Which was counter to streaming REPLs. My memory is hazy, but at the time he was pushing to implement a networked repl on top of the STOMP protocol. Having written stuff to process the STOMP protocol — I’m very glad that never happened 🙂 as the protocol is terrible and totally underspecified. Obviously Rich is totally entitled to change his mind too 🙂, and he didn’t write nREPL so he could also just be unsatisfied with aspects of the implementation.
From the archives: Rich arguing for message based REPLs: http://clojure-log.n01se.net/date/2010-09-29.html#i56 🙂
Also, just above that anchor, Rich says "what I am advocating is - get away from custom transport and protocol. Use netty + websockets. Concentrate on value add (clojure repl stuff) get on with our lives"
and then Rich says "cemerick: learn websockets or learn your custom protocol?"
Seems pretty clear he's against a custom protocol -- which is what nREPL enshrines.
Rich sums up here http://clojure-log.n01se.net/date/2010-09-29.html#11:35d (including "please use a standard protocol like websockets or stomp")/
yeah, but STOMP is garbage 🙂 I know because I was inspired by witnessing this conversation to try it; and I’m not convinced websockets are enough. I could be misinterpreting him, but he might as well have said use TCP, as websockets don’t give you much more than that. And nREPL uses TCP right? 🙂
So then you have socket repl — which is just characters… nothing wrong with that it’s simple but has no framing or semantics beyond effectively eval, and exposes you to interpreting clojure on the wire. So it’s not enough for all use cases… Which brings us to prepl which is also a custom protocol. Less elaborate than nREPL yes, but it uses EDN instead of JSON which is great, but less portable for framing (Emacs only learned to parse EDN properly recently), and EDN wasn’t an option back then as it didn’t exist until clojure 1.5. Also clojure slowly improved with regards datafying important things, e.g. exceptions didn’t used to be data… so you couldn’t really just read them back then.
Anyway I’m very happy to see the evolution of all the new REPLs and where they end up; they all exist for sound reasons as far as I can see. I just don’t think nREPL was wrong at the time.
And new things come along, e.g. socket-repl, EDN, datafy / nav which Rich can put in at the bottom… and when he does so it can enable better tooling.
It's an interesting discussion (in that log). I'm substantially further down than the entry point you linked to...
Yeah, I’ll re-read it later… funny the conversations you remember 🙂
Later the next day, Rich complains "as you your current wire protocol, I have to admit to really not liking it. I don't think you serve non-Clojure clients by making it newline terminated [dribble]" but makes it clear he's thinking about programmatic REPLs at that point and that seems to be fundamental to his objections. Which, I guess, is why Clojure has stuck to streaming REPLs with Clojure expressions, then over a socket, then a programmatic shell (`prepl`)...
Ok read some more… (though not as far as you have) I think you’re right that he argues strongly throughout for not-a-custom-protocol… but he strongly argues against sockets, and for messaging… which was really the point I remembered… and why I felt the recent push to socket repl’s was counter to his ideas back then. I remember this because at the time I was very excited by the idea of effectively having a pubsub repl, and sidecar tools that could subscribe to repl events etc. To some degree REBL is a demonstration of the sidecaring ideas; but without the MQ fabric… and nREPL unfortunately never really delivered on that front.
My reading was that he considered pure streaming important even back then but wanted to rely on messages over the streams, which were simple Clojure data. I don't think messaging is in conflict with streams, but it does require a parser on both ends?
not sure I follow the logic there. streams exist at the bottom as TCP, above that you be stream oriented or message oriented; how can you be both? (granted they’re somewhat ill-defined terms). but messaging to me implies packing things in ways that the packages (though not necessarily the contents) can be understood by middlemen. And packing into boxes with some upper size limit.
i.e. giving consumers some guarantees they can rely on, so they’re not exposed to all the problems of reading the wire itself.
I was reading Rich's position as messages-over-streams. So the underlying level is streams that you read/write. But the assumption is that the level above is (something like Clojure data) messages that consumers and publishers know how to parse/read and print/write... You can then connect this to any in/out stream system.
but plugging into an MQ server behind the scenes certainly has to be done at the message level not the stream level so ¯\(ツ)/¯
(I've always found that part of the discussion a bit opaque)
well I think prepl’s position is that you treat the stream as consisting of EDN messages; that a clojure client can consume/write with minimal effort - and that multiplexing is best done out of the protocol by just opening another socket. i.e. no need to build complexity in when alternatives exist outside. But prepl is still a custom protocol; it’s just most of the complexity is handled in your EDN parser. At the level of the stream an intermediary may not have enough information available to handle those messages; which say the STOMP stuff Rich was talking about would have. Prior to 1.10 I quite liked what cgrand was doing with unrepl; though I’m not sure what the advantages are relative to prepl now… or whether it will continue.
unrepl elisions were pretty cool… though I guess datafy
/`nav` support at least some of that usecase.
I use unrepl to "upgrade" a simple socket REPL on QA/production processes so that I have a reasonable REPL experience. It can side-load compliment so you get auto-completion in the REPL which is nice (so compliment doesn't need to be a dependency in QA/production, although it will be added if you unrepl into it). I would still prefer a client that didn't actually load in any libraries, just eval'd code to do that sort of thing. Apparently, nREPL is getting unrepl/side-load support, via cgrand. That does not make me happy 😐 but I can just ignore it I suspect.
Unrepl has clearer and more useful serialization of unusual things like exceptions than prepl
> Apparently, nREPL is getting unrepl/side-load support, via cgrand. That does not make me happy 😐 but I can just ignore it I suspect. Why not?
Because whenever I talk about how I like simple tooling that doesn't add dependencies, and why I like Socket REPL etc, someone usually comes along and says "Oh, nREPL is getting side-load support so you'll be able to use it without it being a dependency in your project!" -- which completely misses the point. And, as you may have gathered, I'm no fan of nREPL and never have been 🙂
I’m definitely down with the simpler tooling; and nREPL is pretty complicated; for reasons beyond the protocol… it’s probably fair to say nREPL isn’t that important to me. What is important are the functionality in the cider-nrepl middlewares. If they were to built on top of socket REPL, that would be great — but I can completely understand why bozhidar is reluctant to do so.
still I recon side loading in nREPL will be a good thing… as would upgrading to an nREPL via a socket repl.
@dominicm Pretty much what @rickmoynihan just said: I like simple tooling and nREPL is pretty complicated. At one time we ran an nREPL server inside our apps, with enough CIDER middleware to have a "usable" Emacs connection story but that was a lot of code I didn't want in a production app (and starting the REPL with the standard middleware was s-l-o-w -- something they've "fixed" since then, I believe, by lazy-loading the middleware?). As far as I'm concerned, nREPL/CIDER is bloatware that I don't want in my app. I have a very streamlined REPL-based workflow that works with lightweight tools and can be used against a production app just as easily as a local app in dev.
I think that's quite unfair on cider. Cider should be the foundation for socket based tooling, I think.
I don't see how CIDER can be that foundation given the vast range of client technologies that editors use -- unless it's all done on the server-side and I've already explained above why I do not want that.
Yeah, and as I explained earlier, I don't much care for that either.
Seriously, tool makers need to focus on slimming down dependencies.
With Chlorine for Atom, I can add commands in the init.coffee
script that interact with REBL and whatever -- with no dependencies at all.
@dominicm yes though I was never entirely satisfied with the answers. IIRC rebl didn’t use nrepl because making it work over wires was complicated by needing a weak reference manager. Which is totally true; however in dev you can choose to run rebl inside your nrepl process.
Which is essentially how my nrebl-middleware works. Though I’ve never been fully satisfied with it’s correctness. Also I never completely managed to parse the discussion on https://github.com/nrepl/nrepl/issues/99
when I last decided to devote a few minutes to looking at accessing the bindings out of *1
it didn’t work; and I think I determined that it wasn’t possible to do so as described — after reading the code etc…
Though I could be wrong about that and it was complicated by other factors, e.g. whether or not I’m hooking into the nrepl middleware application order in the right way (IIRC I tried several ways — as suggested on the ticket and others). So I parked it.
Yeah, I think it could have happened too. The inspector does storage on the server to enable inspection.
Yeah I think that’s effectively the weak reference system Rich is talking about. Not sure how the inspector does it; but the general issues with it are deciding when to release the handle on something. I guess it puts you on a spectrum with an explicit protocol with calls to release etc left to the user/client at one end and distributed garbage collection at the other.