This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # admin-announcements (296)
- # beginners (19)
- # boot (40)
- # cider (77)
- # clojure (139)
- # clojure-australia (2)
- # clojure-bangladesh (6)
- # clojure-dev (19)
- # clojure-japan (25)
- # clojure-russia (23)
- # clojure-sg (1)
- # clojure-uk (4)
- # clojurescript (131)
- # datomic (41)
- # editors (42)
- # ldnclj (35)
- # off-topic (11)
- # reagent (10)
Replete is going to be cool. I can totally see myself trying to write a few functions in some dead time waiting for a train
@dnolen: won't web assembly suffer from the same problem as everything else that is introduced to js? you will still need to support older browsers. or do you reckon that will go away in 3-4 years with MS's acceleration of phasing out older browsers?
Just out of curiousity, I opened up Atom and Sublimetext2 and checked out their clojure support.
@ordnungswidrig: Yes, it had but the package hasn’t been updated to work with Atom 1.0 I believe
From the State of Clojure survey: https://cognitect.wufoo.com/widgets/h1w98xtl0c9q903/
I don't know which of those support structural editing, but at least, this gives us a good overview of candidates to winnow out.
LightTable has some paredit support as of quite recently I believe, but I haven’t used it.
LightTable has had paredit plugins for a long time. Even wrote one of them. Might be that they have more "official" support now though.
Vim has at least two paredit plugins, paredit.vim and vim-sexp. I think many use the latter (with vim-sexp-mappings-for-regular-people)
@emil0r: there’s that problem too. WA is worth tracking, but I suspect ClojureScript’s current strategy will be the right one for a very long time.
@bozhidar: forgive the hit-and-run bug-report, but sometimes i get this when using projectile’s switch project:
projectile-merge-known-projects: Wrong type argument: listp, b
it’s a freshly installed projectile and fresh bookmarks file, so it’s not old data or code. what might i be doing wrong?
@robert-stuttaford: I was doing some changes over the weekend and I guess I broke something. File a ticket with some repro steps and I’ll look into this.
yeah i refactored my emacs config yesterday so it’s very likely i caught something from you
it’s actually quite annoying. even when i run this on a fresh start (by pressing F12), https://github.com/robert-stuttaford/.emacs.d/blob/master/keybinds.el#L8, it happens
Is it possible to write this macro to be able to use it in threading macro?
(defmacro <? [expr] `(throw-err (<! ~expr)))
The problem is, if I write it as function composition, clojure will yell at me, because I'm using <! out of Go block
Can we produce better stack traces ? It will help giving better first impression to beginners
@lazy-lambda: There are various libraries to do that, and Cursive and CIDER (at least, maybe more tools) do that by default too.
Your options are: use a tool which prettifies them, or use a library which prettifies them.
If you can consistently catch exceptions at some point in your app, you can use something like aviso/pretty to print them nicely.
Boot includes something like aviso/pretty by default. Maybe “by default” could be read as “in the lowest possible layer”, i.e. the build tool?
I guess, although it’s famously hard to catch all your exceptions and print them nicely. Doing it at the build tool level will only work for exceptions that you don’t catch yourself, and obviously only if you’re using that build tool, and only if you’re using the build tool to run your app.
Back to our earlier discussion about what Clojure(Script) needs to really take off, I think on the ClojureScript side there has been a lot of interest generated by Om and its reactive siblings, which is great. But I think there is a layer missing underneath Om & Co. that is just starting to get filled and needs to happen. IMO, that layer/set of libraries needs to provide support for: logging, debugging, testing, inspecting, and async "channeling". And these should work independent of any particular editor or IDE. Thoughts?
@roberto: I think there will be a great benefit if everything in the browser goes through core.async channels and that means all these low-level tools need to use core.async
I think that is rather a matter of taste. I use core.async for xhr requests, but I don’t think it should be the
And then applications themselves should also use core.async channels and to use them most effectively it might make sense if there was some kind of library that provided support for async "channeling"
using core.async everywhere may not be suitable for all applications. It should be a decision made in a case by case basis.
what does using a lib that's written on top of core.async buy you over a similar lib that doesn't?
@bostonaholic: if you are creating an app using Om, Reagent, Re-Frame, etc. then those libraries already use core.async
Just to throw in the importance of tooling in adoption. I think Figwheel does a lot to convince people to try and use Clojurescript. I have been showing my JS dev friends and they all think it is amazing
in their docs they use cljs-ajax https://github.com/Day8/re-frame/wiki/Talking-To-Servers
i think in general core.async is for processes and side-effects, and i don't want libs managing their own side-effects.
react manages side-effects, but that's a special-case because the DOM is there anyway and it only makes it more manageable
all of re-frame's middleware and dispatching of event handlers is done using core.async https://github.com/Day8/re-frame/search?utf8=%E2%9C%93&q=core.async
yeah, and re-frame does not force you to use core.async for xhr requests. Which I appreciate.
although reagent is async via other means: https://holmsand.github.io/reagent/news/reagent-is-async.html
Everyone talks about callback hell and now we have a great solution in core.async and everyone wants to argue against it. Interesting...
@meow: I think what people are trying to say is "core.async is a really great tool for solving issues that is is designed for. But including it and using it everywere, especially when it's not the best tool for the job, is too much overkill."
@meow: I'm not so much concerned with the callback hell inside the implementation details of libs I use, i'm more concerned with it in application code. I'm saying there's different tradeoffs in applications vs libs. I don't need to make my application code as composable as lib code needs to be.
When I look at cljs apps in the wild, like via searches of code on github, I see a lot of callbacks being used, even in apps that use react. So to me it seems like core.async isn't being used where it could/should be used and that something is still missing that isn't making it easy enough to use it.
So you wouldn't want a library that provides logging capabilities to use core.async, right?
callbacks are not always bad either. There are cases where it is the right choice. And there are cases where core.async is the right choice. It is the overuse that leads to pain.
okay, but in general I don't think core.async is overused and is likely misused because there aren't enough good examples of how to use it well.
so what we need is more examples of core.async in the wild and the types of problems it's well suited for
One thing I think I keep hearing is that core.async should only be used where it is appropriate and so far the examples of where it should be limited to don't make sense to me.
pkobrien: Being given a small library that is amenable to orchestration with channels is more important than making a specific decision for the consumer
@gtrak: So when you call that logging function, what if the logging library used channels under-the-covers? Good? Bad?
depends on what it's doing, I guess, but having to import the core.async dependency that might conflict with the version I want to use is a strike against it.
if the lib uses core.async, and the api changes, then either the lib won't work with a new dep or my app won't work unless I use the old.
if a logging library used core.async, how does that force anything on the consumer of that library?
the logging library exposes functions that you call, just like any other logging library
to me, I am going to weigh the cost (size of js, performance) to the benefits (ease of use, features)
pkobrien: I'm afraid I don't follow your reasoning. tools should solve specific problems... not just have the "async" feature bullet
that’s one thing I do like about Go, csp is inherent in the language, so there is no concern about whether things will taken channels or whatever. The fact that it is just macros is nice if you just want to plug in though. There are tradeoffs everywhere
can we please not complect this discussion about proper use of core.async with its size or dependency management issues that have nothing to do with the main issue? Re-Frame is very popular, perhaps more so than Reagent, and Re-Frame not only uses core.async but it forces you to structure you code in a certain way because of that and its users love Re-Frame for that very reason.
yeah, I think the focus should be on ‘what the tool does’ and not on ‘what libraries the tool uses’.
dependency management is part of composability, the argument against using core.async is it's less composable than a simple callback for simple things.
but size of a dependency is huge when you're building for web. especially mobile
now we are talking about "easy" when I've been trying to talk about "simple" - I give up.
@meow : Zach Tellman has said interesting things about this: https://github.com/ztellman/manifold/blob/master/docs/rationale.md
The practical effect of this is that by choosing one abstraction, we often make the others off-limits. When writing an application, this may be acceptable, if not really desirable. When writing a library or something meant to be reused, though, it's much worse; only people who have chosen your particular walled garden can use your work.
While I love building apps with core.async, I too agree that it does not seem wise to make such opinionated an approach the default, especially when there are quite interesting alternatives (futures/promises, FRP, etc.)
@roberto dnolen linked an article talking about that issue. I think it was refereed to as the mapping problem(?)
He sent this link http://people.engr.ncsu.edu/efg/517/f00/syllabus/annotations/lec13.html
pkobrien: Brandom Bloom mentioned a front-end case of core.async overuse in his Clojure/West talk
The bottom line is that I think well-constructed browser applications will need to make more use of loose-coupling via async communication, whether that's using core.async or manifold or some other tool, or a combination, and that the community would benefit by having lower-level primitives to make it easier. These primitives would be on top of core.async or whatever, but would provide slightly higher levels of abstraction. They would provide good examples of how to do async properly, and would keep app developers from inadvertently using callbacks when they shouldn't.
you use core.async (or queues in general) when you want to separate “what” from “when"
if you’re sending messages just to immediately effect a change, that’s a misuse of the abstraction
what about the separation of logic so that, in a gui or browser, when a user clicks on a button the on-click doesn't contain logic about mutating state or sending off a query to a server, but instead simply "sends a signal" or puts some data on a queue/channel for some other part of the app to deal with?
i prefer a simple callback, that I can then pipe to whatever messaging strategy i've chosen for my app
a core.async channel is a pretty complex bit of code to use as a container for callbacks
@ztellman: I'm still exploring this area, so I can't say definitively, but it seems to me that it isn't that hard to add a small layer of code and a slight change in thinking to make it pretty easy to use channels as containers for callbacks
pkobrien: what does a channel give you that an atom containing a list of callbacks doesn’t?
plus with transducers its easy to change the data into something regular and more meaningful for the consumers
you’re just not getting enough events, and the complexity it adds is a huge impediment to predictability
but if your needs are “when this event happens, this code needs to run”, that should be a callback
I definitely agree that higher-order transformations of async streams/values are valuable
a user clicks on a button, a transducer turns that into meaningful data, data placed on channel, something listening to the channel gets triggered when data appears on the channel, when data appears something gets logged. Seems reasonable to me.
I don't think core.async is a magic bullet, just a powerful tool that has more application that what I'm seeing.
I think most people who write libraries are trying to keep options open for their users
Just like signals/slots in GUI programming are a better solution than burying app logic behind widgets all over the place. But you still have to understand signals and slots and use them wisely.
signals and slots seems more appropriate for OO and for things that are built to a 'framework' than loosely coupled libs
I don't want to get sidetracked with the signals/slots example - they are rather OO, but QML, which is declarative on top of OO, had a nicer implementation, but its something that can be used well or used poorly. The main thing for me is to have ways to separate my UI from the core logic. Part of that is the tools you have, and part of it is a design discipline that you learn over time, usually by creating OO messes. 😉
In C#/WPF your buttons are/can be attached to Commands (instead of wired directly to a callback). This how in .NET world you separate UI components from Domain logic.
This doesn't really have much (anything) to do with Event filtering (aka Reactive Extensions)
I don't know much about ClojureScript/React/Reagent/ReFrame but I don't get the impression that DataBinding is a big part of that world?
Also a lot of this presupposes the existence of UI Designers who are adverse to "programming" and only can design with XAML and hate touching C#. So the "coders" come up with Commands that the "Designers" can attach to UI Widgets, and ViewModels that can be also attached to widgets and manipulated with the MS Blend editor.
@meow: Responding to your earlier thought about a low-level layer on the front-end for "logging, debugging, testing, inspecting, and async 'channeling'" — agreed. I've started a document (currently just on my machine, but I'd throw it up somewhere collaborative if someone suggested a good home) capturing various ideas that have surfaced during this discussion. I'll add those aspects to the "framework (possibly comprised of libraries)" bullet.
@meow: as for the core.async debate, I think I understand where you were coming from with that, and here's how I'd phrase it: If someone were to bring together a suite of libraries to create some sort of framework (or, say, a
re-frame-like "these are good ideas and a reference implementation DON'T CALL IT A FRAMEWORK! AHH THE FLASHBACKS"), using a good abstraction for intra/inter-system messaging, rather than encouraging callback soup, would be well worth pursuing in the design.
Sorry, I'm missing the context. Are you replying to a specific thought / point?
trying to think about what's hard about UI work right now, my company's using pure react on top of ember, but I've done a lot of clojure at my previous job. I don't know if a batteries-included framework would solve the parts I think are hard?
that's why we're considering switching to a flux implementation instead of our home-grown thing.
I personally haven't seen a case where true/total component reuse scaled beyond the simplest things. But for pretty much any idea where "code reuse" was a stated benefit, there were other benefits that also made said idea compelling. Just my 2¢
Eg: "If you write your components this way, they'll be more reusable" <- also encourages consistency, which helps for lots of things
I would like to see different libs for different types of use-cases, for instance this react form lib is actually very lispy, compiles a tree of vdom elts as a 'form schema' into react components: https://github.com/prometheusresearch/react-forms I could see wanting to embed something like hoplon as well.
each component lib has to reinvent how to embed custom components and things like state.
we were able to make reusable, stateful components that way by overriding writes and merging in state from a parent, but it's a little ad-hoc.
in this case, each component managed its own selections, or its selection state was managed by a parent.
@gtrak Kudos for it working with selections. So many component systems I've see fail to handle that nicely, or at all. How did it do on state-transition animations?
This is where I tap out — I've never used React directly, only through Reagent, at arm's-length from props and component-local state