Fork me on GitHub
#admin-announcements
<
2015-07-13
>
lucasbradstreet01:07:20

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

Paco01:07:42

That facepalm emoji is very “falic” looking 😛

karlmikko02:07:53

@lucasbradstreet: it is quite fun to code with emoji

emil0r06:07:01

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

emil0r06:07:28

although i suppose you could just have multiple compile targets

slipset07:07:33

Just out of curiousity, I opened up Atom and Sublimetext2 and checked out their clojure support.

slipset07:07:42

Conclusion so far, not very impressive.

slipset07:07:45

The syntax highlighting works, but I couldn't get the repl working as I expected

lazy-lambda07:07:47

We should list editors that support structural editing

Pablo Fernandez08:07:31

IntelliJ, Emacs… any others? LightTable?

ordnungswidrig08:07:44

doesn’t atom have something paredit like?

Jakub Holý (HolyJak)08:07:58

@ordnungswidrig: Yes, it had but the package hasn’t been updated to work with Atom 1.0 I believe

ordnungswidrig08:07:32

I see, never tried id.

spiralganglion08:07:37

@pupeno: Nightcode? (Never used it, but I know it exists)

spiralganglion08:07:14

I don't know which of those support structural editing, but at least, this gives us a good overview of candidates to winnow out.

spiralganglion08:07:33

For Atom, there's 2 paredit packages

spiralganglion08:07:52

lisp-paredit seems to be the more fleshed-out choice

spiralganglion08:07:41

They've both been updated within the last month

cfleming08:07:38

LightTable has some paredit support as of quite recently I believe, but I haven’t used it.

cfleming08:07:44

Vim also has paredit.

otijhuis09:07:56

LightTable has had paredit plugins for a long time. Even wrote one of them. Might be that they have more "official" support now though.

sp3n09:07:40

eclipse with counterclockwise has paredit support, works really well

juhoteperi09:07:01

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)

lazy-lambda09:07:57

I use paredit.vim, but I intent to learn vim-sexp

dnolen10:07:31

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

bozhidar10:07:32

I wonder if Emacs has paredit as well? This sounds like something really cool!

robert-stuttaford10:07:53

@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

robert-stuttaford10:07:26

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-stuttaford10:07:36

it seems to happen the first time i invoke, but the second time it works

bozhidar10:07:45

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

bozhidar10:07:09

Note to self - the project needs way more tests simple_smile

robert-stuttaford10:07:29

yeah i refactored my emacs config yesterday so it’s very likely i caught something from you simple_smile

robert-stuttaford10:07:38

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

robert-stuttaford10:07:03

writing ticket now

robert-stuttaford10:07:06

ah. projectile-known-projects somehow has the value b in it.

robert-stuttaford10:07:58

holy moly i’m an idiot

bozhidar11:07:58

it has b for you locally?

bozhidar11:07:18

I’m guessing you edited it accidentally, right?

wiruzx11:07:23

Is it possible to write this macro to be able to use it in threading macro?

(defmacro <? [expr]
  `(throw-err (<! ~expr)))

wiruzx11:07:48

The problem is, if I write it as function composition, clojure will yell at me, because I'm using <! out of Go block

lazy-lambda13:07:21

Can we produce better stack traces ? It will help giving better first impression to beginners

cfleming13:07:10

@lazy-lambda: There are various libraries to do that, and Cursive and CIDER (at least, maybe more tools) do that by default too.

lazy-lambda13:07:37

And also to ones who are not familiar with java

lazy-lambda13:07:11

But many of us use vim

lazy-lambda13:07:16

and atom and sublime text

cfleming13:07:48

There’s no way to get the stacktraces pretty by default.

cfleming13:07:20

Your options are: use a tool which prettifies them, or use a library which prettifies them.

cfleming13:07:30

Depending on your use case.

lazy-lambda13:07:27

Is there any plan to produce friendlier stack traces

cfleming13:07:06

It can’t be done. It’s a JVM issue.

cfleming13:07:43

If you can consistently catch exceptions at some point in your app, you can use something like aviso/pretty to print them nicely.

martinklepsch13:07:06

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?

cfleming13:07:00

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.

cfleming13:07:12

Which is not to say it’s not worth doing, of course.

fode15:07:20

I'm new here. Hello everybody simple_smile

chris15:07:45

hey ✌️:skin-tone-3:

meow16:07:07

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?

roberto16:07:41

what do you mean by async channeling?

meow16:07:39

@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

roberto16:07:52

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

bostonaholic16:07:05

there's a lot of overhead in core.async, too

meow16:07:17

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"

meow16:07:18

@bostonaholic: what kind of overhead?

bostonaholic16:07:04

I'm thinking in terms of size of js sent to the browser

bostonaholic16:07:26

core.async adds a lot if you only need simple Xhr

roberto16:07:35

using core.async everywhere may not be suitable for all applications. It should be a decision made in a case by case basis.

gtrak16:07:37

what does using a lib that's written on top of core.async buy you over a similar lib that doesn't?

gtrak16:07:59

one thing that I can think of is ordering guarantees by virtue of using queues.

gtrak16:07:12

callbacks are more fine-grained by default?

meow16:07:14

@bostonaholic: if you are creating an app using Om, Reagent, Re-Frame, etc. then those libraries already use core.async

meow16:07:46

so core.async is pretty much a given in the environment I'm targeting

gtrak16:07:13

weird, I'm trying to find where om actually uses it, it's listed in dependencies

bostonaholic16:07:39

I don't believe Reagent uses core.async

gtrak16:07:07

om only uses it in examples, so it doesn't use it

bostonaholic16:07:17

same with reagent

roberto16:07:40

sorry, but re-frame does not use core.async

roberto16:07:01

it leaves making the xhr requests up to you

kamn16:07:18

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

gtrak16:07:40

i think in general core.async is for processes and side-effects, and i don't want libs managing their own side-effects.

bostonaholic16:07:04

@kamn: don't let them know there are similar tools for plain js 😜

gtrak16:07:33

react manages side-effects, but that's a special-case because the DOM is there anyway and it only makes it more manageable simple_smile

meow16:07:34

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&amp;q=core.async

meow16:07:04

it looks like reagent does not use core.async

roberto16:07:58

yeah, and re-frame does not force you to use core.async for xhr requests. Which I appreciate.

meow16:07:42

@roberto: I'm not talking about xhr

roberto16:07:23

so, you are talking about specific cases?

roberto16:07:26

which would those be?

meow16:07:53

internal to the app

meow16:07:14

look at how and why re-frame uses core.async

roberto16:07:36

yeah, but that was for a pub-sub

meow16:07:12

I think core.async should be applied widely

roberto16:07:18

i would disagree there

roberto16:07:26

it has to be applied where it makes sense

roberto16:07:47

i guess i have a problem with widely and trying to understand what that means

roberto16:07:59

sorry if I sound a little nitpicky

ghadi16:07:23

something something when you have a hammer

meow16:07:50

When all you have is a hammer everything looks like a nail

meow16:07:55

Wow, this is great.

gtrak16:07:56

when you have a hammer, you make other people use it

ghadi16:07:04

gtrak: heh

meow16:07:33

Everyone talks about callback hell and now we have a great solution in core.async and everyone wants to argue against it. Interesting...

bostonaholic16:07:29

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

ghadi16:07:37

well said bostonaholic

gtrak16:07:02

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

meow16:07:54

so what issue was core.async designed to solve?

gtrak16:07:13

it's concurrent state machines

gtrak16:07:44

when i don't really want my libs to have state machines

meow16:07:03

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.

bostonaholic16:07:38

I could see that

bostonaholic16:07:50

1. it's still new

meow16:07:54

So you wouldn't want a library that provides logging capabilities to use core.async, right?

bostonaholic16:07:04

2. the paradigms are unfamiliar with a lot of people

meow16:07:14

logging is not a concurrent state machine, right?

roberto16:07:19

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.

meow16:07:04

Show me one case where core.async was overused.

roberto16:07:17

oh, I had one, but i deleted it simple_smile

roberto16:07:20

in a personal project

roberto16:07:30

i went all core.async gongho

roberto16:07:35

was a mess

roberto16:07:45

it doesn’t mean I should not use core.async at all

roberto16:07:53

i use it where it is appropriate

meow16:07:05

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.

gtrak16:07:16

I don't get the point of the logging example

bostonaholic16:07:16

^^^ yes, to pkobrien

gtrak16:07:34

I can call a function or macro to log stuff, i don't need to talk to channels directly

roberto16:07:43

yeah, I agree with that. There should be more literature on its appropriate use.

bostonaholic16:07:45

so what we need is more examples of core.async in the wild and the types of problems it's well suited for

dnolen16:07:02

@meow: core.async doesn’t play well with React’s life cycle

roberto16:07:05

but it is so new, we are all learning

dnolen16:07:17

you have to be careful when using it in that context

meow16:07:36

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.

roberto16:07:37

currently, I only use core.async for xhr requests.

ghadi16:07:22

pkobrien: Being given a small library that is amenable to orchestration with channels is more important than making a specific decision for the consumer

meow16:07:46

@gtrak: So when you call that logging function, what if the logging library used channels under-the-covers? Good? Bad?

gtrak16:07:47

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.

gtrak16:07:14

that's part of being composable

meow16:07:49

@gtrak: that's a version dependency issue completely independent of core.async

gtrak16:07:23

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.

meow16:07:43

if a logging library used core.async, how does that force anything on the consumer of that library?

meow16:07:02

libraries depend on other libraries all the time

meow16:07:37

the logging library exposes functions that you call, just like any other logging library

roberto16:07:40

tell that to the node ppl simple_smile

roberto16:07:50

I have run into those issues there

meow16:07:53

you pass it data, it puts that data on a channel, etc

bostonaholic16:07:59

to me, I am going to weigh the cost (size of js, performance) to the benefits (ease of use, features)

gtrak16:07:04

nvm deps can have multiple versions of the same lib in a single runtime

roberto16:07:39

what would the logging function use core.async for? To push data to a server?

ghadi16:07:39

pkobrien: I'm afraid I don't follow your reasoning. tools should solve specific problems... not just have the "async" feature bullet

chris16:07:16

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

meow16:07:24

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.

roberto16:07:24

yeah, I think the focus should be on ‘what the tool does’ and not on ‘what libraries the tool uses’.

roberto16:07:55

re-frame uses core.async as a pub-sub

roberto16:07:05

i don’t love re-frame because it uses core.async for its pub-sub

gtrak16:07:07

dependency management is part of composability, the argument against using core.async is it's less composable than a simple callback for simple things.

roberto16:07:10

I like it because of the workflow

roberto16:07:16

it could have used anything else for its pub-sub

roberto16:07:22

and I would be perfectly happy

bostonaholic16:07:54

but size of a dependency is huge when you're building for web. especially mobile

bostonaholic16:07:12

so yes, I will take that into consideration when using a library

meow16:07:19

now we are talking about "easy" when I've been trying to talk about "simple" - I give up.

roberto16:07:53

I don’t understand where the ‘easy’ part came in.

roberto16:07:39

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.

roberto16:07:43

I like that part.

val_waeselynck16:07:00

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

roberto16:07:14

yes, and it will limit future innovation

kamn16:07:52

@roberto dnolen linked an article talking about that issue. I think it was refereed to as the mapping problem(?)

roberto17:07:14

oh, nice. I’ll google it.

kamn17:07:44

Ops Mapping dilemma*

kamn17:07:39

Ah. I didn't see this

meow17:07:44

does manifold work with clojurescript, or just clojure?

val_waeselynck17:07:26

Currently only Clojure I believe

ztellman17:07:14

yeah, I haven’t had the time/personal need for a cljs port

ztellman17:07:39

pkobrien: Brandom Bloom mentioned a front-end case of core.async overuse in his Clojure/West talk

meow17:07:51

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.

ztellman17:07:01

you use core.async (or queues in general) when you want to separate “what” from “when"

ztellman17:07:20

if you’re sending messages just to immediately effect a change, that’s a misuse of the abstraction

meow17:07:19

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?

gtrak17:07:51

i prefer a simple callback, that I can then pipe to whatever messaging strategy i've chosen for my app

ztellman17:07:10

a core.async channel is a pretty complex bit of code to use as a container for callbacks

meow17:07:51

@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

ztellman17:07:16

pkobrien: what does a channel give you that an atom containing a list of callbacks doesn’t?

meow17:07:20

plus with transducers its easy to change the data into something regular and more meaningful for the consumers

ztellman17:07:30

other than lack of predictability w.r.t. when your code runs

ztellman17:07:50

ok, so you want buffering

meow17:07:57

sliding buffers for events I don't care about except the most recent

ztellman17:07:04

if that’s the case, godspeed

ztellman17:07:21

I’d argue that 99% of UI code doesn't

ztellman17:07:40

you’re just not getting enough events, and the complexity it adds is a huge impediment to predictability

dnolen17:07:58

this conclusion doesn’t make really make any sense to me

ztellman17:07:07

@dnolen: my conclusion?

dnolen17:07:17

some components are very complex and internally core.async can be huge benefit

dnolen17:07:35

note internally

ztellman17:07:46

@dnolen: I’ll defer to your experience on this

dnolen17:07:47

the actual interface presented to other people, probably a calllback

meow17:07:57

I see core.async as a way to, for example, do signals/slots in Qt/QML

ztellman17:07:10

but if your needs are “when this event happens, this code needs to run”, that should be a callback

ztellman17:07:43

I definitely agree that higher-order transformations of async streams/values are valuable

ztellman17:07:23

or are valuable where they’re valuable, as tautological as that is

meow17:07:07

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.

meow17:07:34

the async nature is just a side benefit

dnolen17:07:39

I think we can agree with “it depends"

dnolen17:07:46

a mess of events is a mess of events

dnolen17:07:52

core.async doesn’t fix messes

meow17:07:40

I don't think core.async is a magic bullet, just a powerful tool that has more application that what I'm seeing.

ztellman17:07:16

pkobrien: I think it has a ton of uses at the application level

ztellman17:07:33

I think most people who write libraries are trying to keep options open for their users

ztellman17:07:51

certainly that’s the line I try to walk on the server-side

meow17:07:59

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.

dnolen17:07:27

this I don’t really agree with

dnolen17:07:30

exposed wires

meow17:07:43

don't agree with what?

dnolen17:07:52

exposing wires

meow17:07:04

not sure what you mean

dnolen17:07:34

core.async + encapsulation probably leads to good results

dnolen17:07:56

anything else and you’ll have a typical object oriented mess

gtrak17:07:38

signals and slots seems more appropriate for OO and for things that are built to a 'framework' than loosely coupled libs

gtrak17:07:49

from what i'm reading it's a global event bus

meow17:07:49

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

meow17:07:56

Going from OO to functional and to a great language like Clojure helps a lot.

dmich18:07:38

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.

dmich18:07:21

This doesn't really have much (anything) to do with Event filtering (aka Reactive Extensions)

dmich18:07:54

And a main part of the separation of UI/Domain Logic in WPF is it's Data Binding

dmich18:07:56

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?

dmich18:07:15

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.

dmich18:07:08

I get the impression that ClojureScript people just do the whole stack?

dnolen18:07:54

I don’t really think that is the case

dnolen18:07:36

there are many ways to integrate plain HTML templates into ClojureScript

robert-stuttaford18:07:46

enfocus, kioo to name two

robert-stuttaford18:07:00

(the latter being for use with React, the former, with the DOM directly)

spiralganglion20:07:08

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

spiralganglion20:07:21

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

gtrak20:07:37

I feel like getting truly reusable components is still a pipe dream

spiralganglion20:07:01

Sorry, I'm missing the context. Are you replying to a specific thought / point?

gtrak20:07:53

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?

gtrak20:07:44

it would at least give junior developers more sense of best-practices.

gtrak20:07:00

as a place to throw documentation

gtrak20:07:18

that's why we're considering switching to a flux implementation instead of our home-grown thing.

spiralganglion20:07:39

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¢

spiralganglion20:07:24

Eg: "If you write your components this way, they'll be more reusable" <- also encourages consistency, which helps for lots of things

gtrak20:07:34

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.

gtrak20:07:41

each component lib has to reinvent how to embed custom components and things like state.

gtrak20:07:23

whether to manage its own or let you control it somehow

gtrak20:07:32

I think the core difficulty is you really can't get away from the lifecycle methods.

gtrak20:07:38

except by limiting what you can do?

gtrak20:07:18

also styling is always a pain

gtrak20:07:41

there needs to be ways to override all behavior from the outside of a component.

gtrak20:07:48

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.

gtrak21:07:17

in this case, each component managed its own selections, or its selection state was managed by a parent.

gtrak21:07:36

And driven by changes in the parent, if used in that context.

mateusz-fiolka21:07:04

What would be the channel to ask a question regarding testing / midje?

tcrayford21:07:28

#C03S1KBA2 I think

spiralganglion21:07:57

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

gtrak21:07:20

we don't have any simple_smile

gtrak21:07:52

though that wouldn't really affect how react does animations

gtrak21:07:21

it's just a mixin that merges this.state with a prop passed in by a parent.

gtrak21:07:28

and offers getters

gtrak21:07:45

similar overrides on callbacks

gtrak21:07:06

the parent sends down a dispatch map that overrides a child's dispatch map

spiralganglion21:07:16

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

gtrak21:07:41

sure, I mean it'd be the same with om, I think.

gtrak21:07:00

minus the concept of a mixin

gtrak21:07:04

also om controls your state for you

gtrak21:07:10

so maybe that's a bad example

gtrak21:07:27

I used om first simple_smile

gtrak21:07:20

the state dispatch map is analogous to like a multimethod switching on the first arg

gtrak21:07:34

then transacting state changes, but they're not global.

gtrak21:07:52

and we don't have cursors

meow21:07:05

@ivanreese: I think you summed up my thoughts pretty well, yes. I'm still exploring a lot of these ideas as I learn the best way to use ClojureScript. So my own thoughts are still a work in progress. Thanks for the feedback.