This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-11-28
Channels
- # admin-announcements (21)
- # beginners (102)
- # boot (8)
- # cider (40)
- # cljsrn (2)
- # clojure (52)
- # clojure-nl (2)
- # clojure-russia (6)
- # clojure-taiwan (2)
- # clojure-uk (1)
- # clojurescript (363)
- # datavis (22)
- # datomic (69)
- # emacs (4)
- # hoplon (1)
- # immutant (2)
- # jobs-rus (13)
- # ldnclj (6)
- # lein-figwheel (2)
- # leiningen (9)
- # liberator (1)
- # off-topic (1)
- # om (68)
- # onyx (28)
- # parinfer (3)
@clojuregeek - to keep taking data (plural) out I think go-loop instead of go, so:
Released a template for building nw
(formerly node webkit
) applications. Generates all the boilerplate needed to get a cider repl running and its deployed to clojars so you can use it with lein new
! https://github.com/tvanhens/nw-template
this looks great, but probably not easy to use with Reagent, since it implements its own atoms? https://www.niwi.nz/2015/11/26/introduction-to-lenses-and-how-to-use-them-instead-of-cursors/
Yeah, I imagine one would have to re-implement that for reagent, since it requires more than watchers IIRC.
Not sure what are performance implications, I imagine reagent might use custom atoms for performance optimisations or something.
@jaen: not sure about that. I think Reagent is just one practical idea that applies in many situations, but it's more complected than Rum.
@borkdude from a quick look you could roll your own reagent-alike from rum & cats-lenses
can anyone help me with a protocols/namespacing problem?
i did this in one namespace
(ns app.vectors)
(defprotocol IEnsureValue
"Protocol for data types that can have a value ensured at a position"
(ensure-last [this v] "Ensure the last item of this is v"))
(extend-type PersistentVector
IEnsureValue
(ensure-last [this v] …))
now i’m struggling to get ensure-last
in another namespace
i tried :require [app.vectors :as v]
but both (ensure-last v l)
and (v/ensure-last v l)
fail
Of those two I'd choose Om.next. Om is just not as nice as reagent, but Om.next gets you future superpowers.
@thedavidmeister: when you create your protocol, a function app.vectors/ensure-last
is created, so v/ensurelast
is the way to go indeed. What's the error ?
WARNING: Use of undeclared Var app.vectors/ensure-last
If that happens at the REPL, you should make sure everything gets loaded in the right namespace, it gets me all the time
not at the repl
happens when i run tests
it didn’t happen when the function wasn’t part of the protocol
@thedavidmeister: hmm no idea then 😕
ok, just noticed some weird stuff going on in my file system
cache.edn files
and stuff
oh, nm
i think i’m modifying the wrong file
ermigawd
that was it
@val_waeselynck: thanks for helping anyway
@thedavidmeister: it happens
@mike: I'm not saying Om.next is as simple as reagent. It certainly is more complex, but it also gets you aforementioned superpowers. On the other hand Om.prev is more complex than reagent, but you don't really have any benefits from it.
Reagent is probably the best way to start, that's for sure, I just replied how those two compare IMO.
is front end development really getting this complicated, or, are we making it as complicated?
You can't really make a complex desktop-like client-side application without encountering problems Relay/Falcor/Om.next try to solve.
@dnolen: I'm sure you had good intentions with om next. but it just does not feel like a smooth path to start with.
It's probably not explicitly meant to be the first introduction into SPAs in Clojurescript anyway.
on a slightly related note are there any recommendations for which library or features to use for the remote communications part? sending and receiving json mainly. seems there's quite a selection of libraries..
I wish I had client-side database like datascript in my app with seamless synchronisation with the backend.
@jaen that is just the very same pattern with Angular 1, and now Angular 2.. everyone says,.. yeah it's hard at the beginning, but once you learn it...
@marvotron: fwiw, I never use the 3rd party things. Closure is quite capable
I dunno, I never could learn Angular. Had no problems with reagent, exactly because it's not as prescriptive.
But I can appreaciate what Om.next is trying to solve having tried to do exactly that once (granted, that was my own overengineering probably, but still).
@marvotron: depends on what you want to achieve. I tend to use cljs-ajax
it's pretty nice to start with.
@mike the problem with Angular or any MVC has nothing to with being easy or hard to learn
short term goal, send json to elastic endpoint, get json back and update state atom (whatever thats based on, om / reagent)
But it is hard to learn. It bring swathes of new concepts for no appreciable gain. At least that's how I felt when I tried to approach it.
the only interesting metric IMO is does MVC X decrease overall complexity of the system down the road, is it easy to swap out decisions later, is it easy to optimize?
@mike: If I may provide another anecdote. My day job is spent building a SPA in ember/ruby back-end for managing patient care(very complex) and things like 2 way bindings/ember-data/json-api are proving to be too simplistic for our needs. So i'm very interested in the ideas things like om.next is exploring. But it is probably overkill for your basic CRUD apps, unfortunately apps worth doing are not your basic CRUD apps IMO
@marvotron: if you are comfortable with closure then sure. I probably couldn't even use it if I tried. Also, if you're using JSON then take a look at prismatic's schemas for coercions. It really makes it more bearable to interact with JSON APIs
@marvotron: this isn’t guidance against any of the things that are out there, a lot of people like the various libs, I just find Closure acceptable
@twillis: agreed if you’re really doing basic CRUD why bother with all the front end stuff
I find closure kinda inscrutable. But I'm pretty sure it is top notch if google is using it for so long.
@mike Om Now is approaching 2 years with plenty of users and I intend to maintain both things … so sure!
sometimes it is nice to gain experience and keep using it like a craftsman and his 50 year old tool.
@mike what I like about ClojureScript is that it's the closest thing to an accomplished and mature solution I have found in the frontend world.
Because the decisions it makes are long-term, and because it strives to tackle all the deep problems
The use of the Closure compiler with Dead Code Elimination is an example
@val_waeselynck: at language level, I agree with you. but at library level, how is it different to js?
Precisely, DCE is key to a solid, durable library ecosystem
@mike since you’re not me I’m not sure what there is to doubt about delivering a well maintained ClojureScript lib But OK
@dnolen: I can answer that. both om and reagent are based on react idea. maybe in 3 years react feels like backbone. where would that put om next and reagent on the map?
@mike the fact of the matter is that no one is satisfied with old JS libraries, because the browsers and application requirements have been evolving a lot.
That's why betting on a tool that evolves very fast and makes flexible choices is interesting currently
I'm talking about the general concept here. a new shiny thing will replace falcor and relay in 3 years.
Backbone is not just a view layer and it does nothing for you with respect to rendering on many targets
apart from google cloure library, please name another front end library/framework which has not been aged since 2006.
I, for one, am ecstatic that we luckily have things like React Native and ClojureScript, and I’m glad Om Next is pushing forward on solving real problems. I know all of this is new, but I suspect we’ll be using an evolved version of all of it a few years from now.
@mike: the key to avoid library deprecation is to compose small, special-purpose libraries with separate concerns, instead of having one big package that tries to get everything right. ClojureScript delivers that, much better than e.g AngularJS.
jQuery based SPA? Isn't that a headache?
@mike well, do productivity and flexibility not matter ?
we're in a room of 3.6k front end developers, and the room was created by an inferior technology.
sometimes when I get tired of learning fancy stuff, I tell myself, maybe I should just go with jquery?
just because time passes and library versions go higher, it does not mean we're moving forward.
@mike the 'it worked for' argument is usually moot. Project management is about risks, and when it comes to risk, you're interesting in the probablity of being successful knowing that you use <this technology>, not the probablity of using <this technology> knowing that you're successful.
Angular for me isn't really a headache. Actually I should go check the major changes in 2, but after I finish this CLJ+CLJS thing
@mike Previously, I had to write iOS apps in an imperative style. Now I can employ FP. That’s forward, for me.
It doesn't matter that 10x more successful project use jQuery than ClojureScript, if 100x more failed project use jQuery too
right so I don’t believe in stuff like this. the truth is that people are quite effective with “less capable” tools
Right, but that shouldn't be an excuse I don't think
@dnolen: I have yet to read your om.next tutorials, which I have planned for Xmas, but is there also something on GraphQL/Falcor server implementation in Clojure that co-exists?
speaking as a clojure newbie, I am amazed at how much i got done with it in a couple weeks
Perhaps what is really changing is not the shiny tools we use, but we as developers are growing as a group
eventually I’ll write up something but it may be the community stuff ends up more comprehensive
I will say this community has been quitr helpful to noob like myself, it's great.
I played around with Scala/Play stuff lately, and I'm impressed how good their 'getting started' documentation is. Doesn't Clojure need something like that for newcomers, a web development stack supported by a company + good docs?
I had the feeling Pedestal App + Server were to become this, but maybe progression stopped when app was abandoned?
@borkdude: Pedestal was supposed to be that thing - it still could be but there’s no urgency anymore
@dnolen: is om.next supported/backed by Cognitect, or entirely your personal project?
(Interestingly, Om Next seems to have pushed me over the tipping point for wanting Datomic.)
I should study datomic in more depth. preferablu when im currently not typing in bed
@borkdude: I think too early to say - there’s a lot of non-obvious ideas in Om Next that people are sorting through
From an outsider’s perspective, Cognitect seems to focus its strength on the server-side technologies, which is a great base of strength. The UI stuff is swirling around outside of it. But, then again Transit pushes in that direction.
For mass adoption it would be good to have some kind of 'framework' that everyone knows and writes things around, like say Ruby on Rails. I hope someday that will happen
@borkdude: well, Luminus is an effort towards this
@borkdude: but I'm still not sure it's possible to have both the simplicity and the 'out-of-the-box' things at the same time, they seem opposite
@val_waeselynck: how big a deal is the 'single thread' issue in Ring-based apps? Play supports the async model like Pedestal does
@borkdude: well it depends on your performance requirements. I think the majority of apps can be completely fine with the 'one thread per request' constraint.
But it's definitely an issue, since basically all the existing Ring middleware becomes unusable as soon as you want to go async
I hope the Ring spec/ecosystem will evolve to decomplect the middleware from the execution model
I think there is not a lot of pressure to go towards the async model, because a lot of database drivers are still blocking
Look how many people are successful even with synchronous, single-threaded servers like Django or Rails
@val_waeselynck: true, but look how many people are also stepping away from it when they want to scale up
@borkdude: I think the solution then may be to use something like Sente
well Websockets
The bulk of AOL’s backend is built with single-threaded C-based servers. No context switching.
@borkdude: but I totally agree that pushing towards support for asynchrony is beneficial, be it only for decomplecting
@val_waeselynck: maybe I should go learn Pedestal 😄
@borkdude: I tried to go non-blocking when I started with Ring, but failed http://stackoverflow.com/questions/24980014/can-i-make-a-fully-non-blocking-backend-application-with-http-kit-and-core-async
@val_waeselynck: I built my server that way (http-kit, core.async)
The only blocking bit is the database layer, but I put that in a thread pool with a queue
And the thing is, now I'm backed by Datomic, which currently has a synchronous model backed by lazy IO, so not very compatible with async
@mfikes: Im curious, why go async then ? Do not most of your requests talk to your database ?
(maybe we should move this to another channel )
@val_waeselynck: I’m lucky in that most of my app is heavy read-based, and I can afford to slurp the main bit into a gigantic Clojure map, and I hit that most of the time. Yes… this is no longer about ClojureScript
@val_waeselynck: The async approach really shines for me when my server has to talk to yet another server in order to satisfy a request. A thread is a terrible thing to waste.
so om(.next) is difficult and reagent is simple? I think I need to pick one now and go with it. I'm learning ClojureScript with my project.
@dreic: difficult is not the opposite of simple
@val_waeselynck: I don't want to get lost while learning
@dreic: Difficult is not perhaps the correct word. More complex perhaps, but that's because it tries to solve problems that Reagent doesn't tackle.
@dreic: it's a matter of taste. Reagent is more 'magical', and concise, at the expense maybe of being less transparent / customizable IMO
@dreic: if you already know how an atom works and hiccup syntax, you're almost there
@dreic: yeah if you're learning ClojureScript too it's a good call to go with easy minimalistic stuff like Reagent
@dreic: you can always move to om.next as a next library and extend what you've learned by building with reagent
@dreic: having said that, you doneed to be knowledgeable about React at some point, even in Reagent
In my editor I'm confronted with an extension that doesn't let me remove parens. That's what's irritating me. Otherwise I'm eager to see what's up.
@dreic: this should help you v
val_waeselynck: I read through the react docs and created a small editor. Not being a JS user I'm fine with the concepts.
"Magical Elegance" description Luke gives in the presentation for Reagent is okay, but I would argue that Reagent is not Magical as in "hard to understand understand how it works"
@dreic: will age quickly imho
I'm thinking Reagent might be less confusing it Ratoms were named differently
E.g. hoplon/javelin uses names cell and formula cell for things which are identical to Reagent atom and reaction
@juhoteperi: there is value in the fact that Ratoms have the same interface as atoms
well, there is an open ebook here: http://funcool.github.io/clojurescript-unraveled/
@val_waeselynck: Javelin cells also implement IReset, ISwap and such
@juhoteperi: yes what i meant was that they probably chose that name to emphasize this particular aspect
Yeah, but the name doesn't really describe why ratoms do exist
It's not because performance but because they need to track when they are dereffenced by components or reactions
@juhoteperi they were spending a lot of time on the cache invalidation problem, so they didn't spend as much time on the naming problem
@dreic: didn't read it myself, but came across this free clojurescript book yesterday: http://catcode.com/etudes-for-clojurescript/toc.html
@mfikes: @val_waeselynck re async, just saw this: http://blog.paralleluniverse.co/2014/01/22/introducing-comsat/
Hah nice. I’m now wondering if go
/ CSP language support directly in Java will become the next “waiting for lambdas” issue a few years from now. So glad we have macros.
You can use these actors from Pulsar in Java already and they can be distributed/monitored unlike go processes I guess?
@borkdude: the thing is, as long as the DB drivers are blocking, asynchrony cannot help much...
There's exciting stuff happening in the Node.js world with generators: http://koajs.com/
Hi. What's the best way to turn snippet of CLJS into equivalent snippet of JS? I want to have piece of CLJS code to do a job for me inside LibreOffice extension. When I compile on some online tool (or Chrome extension), it emits code which relies on cljs library. What's left is to add the library and apply Google Closure to it. What's the best way to do two last points?
@andrewboltachev: you got to compile with google closure
It's probably better to just use a build tool and use the resulting file. Here's a minimal sample on how to set up such a project - https://github.com/adzerk-oss/boot-cljs-example. You'd probably have to modify :compiler-options
in the src/main.cljs.edn
file to use optimizations like whitespace or advanced.
@andrewboltachev: if you want to use :advanced
make sure you mark the functions you want to call from libreoffice with ^:export
metadata
@jaen: sure, boot is cool, but would it make single file for me?
Re: optimization levels - https://github.com/clojure/clojurescript/wiki/Compiler-Options#optimizations
@andrewboltachev: all modes except :none
create single file artifacts
@martinklepsch: thanks, that export thing is a good point
thx guys, let me test it out
Actually, let me back up a bit, you don't have to modify the cljs.edn
file in the sample
You can select optimizations right here - https://github.com/adzerk-oss/boot-cljs-example/blob/master/build.boot#L33
lein new tenzing
will give you a very minimal boot/cljs setup that should be good for your purposes
btw, assumign that code that I would be generating is "clear logic" like adding two numbers/manipulating data structures, should I specify any "target platfrom" anyway?
e.g. I might imagine assigning global vars to window instead of just "var"
@jaen any real world apps other than https://github.com/madvas/fractalify/ using re-frame?
So, is it true that CLJS compiler supports two exact targets — Browser and Node.js, and won't support very "custom" code snippets?
like e.g. compiling for LibreOffice extension?
@andrewboltachev: ClojureScript just generates JavaScript the target stuff is really only Node.js specific sugar-y bits
so you can’t use the Closure stuff for loading code at runtime, you need the compiler to generate a single file
@dnolen: Thanks. Wish I see (1) Even more optimzing Closure compiler, which produces not ~250 lines for "Hello world" but only a few (though it's real complexity and hardware restrictions are the issues there). (2) Ability to compile flexibly that code which isn't using I/O (just to offload my complex logic there). In the future
@andrewboltachev: “Hello world” is a useless metric when assessing ClojureScript
@shaunlebron: just saw these API docs and wished there would be something as awesome (as typedoc) for clj/s libs: http://plottablejs.org/docs/modules/plottable.html Then I thought of your http://cljs.info work and that the analysis you're doing could maybe be used to gather this kind of information. Have you considered this kind of use case at all?
@andrewboltachev: what JS runtime does LibreOffice use?
Also out of curiosity - would it be possible to point your analyzer at clojure as well?
@andrewboltachev: for scripting purposes bootstrapped may be simpler for you, people have already embedded in Excel for example with that
if all you want to write is one-off scripting that may be simpler for you, esp. since in LibreOffice who cares how big the JS is
Envisioning a tool that generates an edn description of a given source tree, ideally with similar change log like information as you have in http://cljs.info
@dnolen: @martinklepsch About the runtime — I only know that JS is and option among Python, Basic and yes, if I understand well Java is supported too ('cause it's what it's written in) but I'm not sure.
@dnolen: but what do you mean "bootstrapped" here?
Clojurescript compiler can now run in Clojurescript, that's what "bootstrapped" here means.
ah sure
http://stackoverflow.com/questions/33967344/simpler-arithmetic — was thinking there must be something in for this but didn’t find anything...
a bit (+ surprised disappointed) that clojuretv has almost nothing on reagent + re-frame.
I’m playing with ‘temporal recursion’. I can define foo as (defn foo [v] (prn v) (js/setTimeout #(foo (inc v)) 1000))
and then call (foo 42)
.
But I cannot define foo as (defn foo [v] (prn v) (js/setTimeout #(#'foo (inc v)) 1000))
?
@jaen: I see. Is there any other way of being able to redefine foo
and make the next js/setTimeout
invocation call the new definition of foo
?
Would it make sense to put the function in an atom and then deref’ing? I guess it’s just some kind of indirection that I am after.
That said, I'm not 100% sure on what I said. I think at some point Clojurescript got some form of vars, but they are different from Clojure ones and they don't exist at runtime. Someone more knowledgeable would have to chime in.
@jaen: cool, well set!
works, but I have to use set!
consistently, ie first using defn
and then set!
won’t work
Ie
(set! foo (fn [v] (prn v) (js/setTimeout #(foo (inc v)) 1000)))
(foo 42)
yields 42 43 43
etc in the console.
(set! foo (fn [v] (prn “hello” v) (js/setTimeout #(foo (inc v)) 1000)))
changes this to hello 44 hello 45
etcBut if I start out by defn’ing foo
before invoking it, I cannot change the definition dynamically
we could probably change emission to handle this differently, but would need a lot of testing to see if it doesn’t break expectations
so probably not really worth it since there are other ways to accomplish the same thing
@grav: Interestingly, you can workaround your issue if you namespace-qualify your var: (defn foo [v] (prn v) (js/setTimeout #(#'cljs.user/foo (inc v)) 1000))
Then (foo 42)
starts it counting up, and (defn foo [v] (prn v) (js/setTimeout #(#'cljs.user/foo (dec v)) 1000))
cause the running counter to go down, if that’s what it supposed to do.
Another ns-independent workaround is to employ let
to capture the var outside of the fn
form: (def foo (let [var-foo #'foo] (fn ([v] (prn v) (js/setTimeout #(var-foo (inc v)) 1000)))))
So, the compiler bug appears to be summarized by these simple variants
(def f (fn [] #'f)) ;; fails
(def f (let [vf #'f] (fn [] vf))) ;; works
(def f (fn [] #'cljs.user/f)) ;; works
You can also work around this way:
(declare f)
(let [x (fn [] #'f)] (def f x))
So whatever it is, it is constrained to that one failing form.What about a named fn
?
(def f (fn foo [v] (prn v) (js/setTimeout #(foo (inc v)) 1000)))
I added http://dev.clojure.org/jira/browse/CLJS-1495 If David or others conclude that a fix is dangerous, at least we have it captured and can close it as won’t fix.
Nothing, but who would want to write onself a callback hell? It's a convenience really, the macro transforms sequential code into asynchronous one. You could write it all without a macro, but it would be a chore.
Does anyone have suggestions of smallish (maybe <1000 loc) projects in cljs that I could read through to familiarize myself w/ the language? games, libs, cli tools, etc
somebody mentioned https://github.com/madvas/fractalify/ and that looks cool
I haven't done anything serious in either, but I've tried to get into both multiple times. I've made a few toy things
I'll second @mfikes; the parts of Clojure written in Clojure are just incredibly lucid & a pleasure to read (with the single caveat that the docstrings tend to be more a terse reference than a beginners' explanation -- but you can turn elsewhere for that).
Re: cljs specifically, re-frame is a pleasure to read, and only a few hundred lines of code. If you're not familiar, it's a framework for Reagent (& hence React). https://github.com/Day8/re-frame
The clj code is actually fine for reading in bite-sized pieces; a lot of it is extremely self-contained.
@jaredly: your question is a good one. I learned the language by doing the 4clojure problems and comparing my solutions to others. But, the most code I've read is the compiler. Perhaps cljs.core is a good read, if not dry :)
I'd probably start with the 2nd half of https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj and then work your way backward to the foundations (given the style you're requesting).
ClojureScript One might be a more "business applicable" codebase. (I'm guessing; haven't read it.) But it was designed with pedagogy in mind.
Does ClojureScript One still exist? It looks like their website ( http://clojurescriptone.com/ ) just bounces you to the main cljs github.
@eggsyntax: Hmm. Right you are
@eggsyntax: does not exist anymore