This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-11-27
Channels
- # admin-announcements (72)
- # beginners (121)
- # boot (9)
- # business (1)
- # cider (6)
- # cljs-dev (2)
- # cljsjs (8)
- # cljsrn (12)
- # clojure (142)
- # clojure-dev (5)
- # clojure-nl (7)
- # clojure-russia (41)
- # clojure-uk (3)
- # clojurecup (1)
- # clojurescript (351)
- # cursive (45)
- # data-science (1)
- # datavis (5)
- # datomic (7)
- # editors (6)
- # editors-rus (15)
- # emacs (53)
- # hoplon (1)
- # ldnclj (53)
- # lein-figwheel (7)
- # liberator (2)
- # om (73)
- # onyx (28)
- # re-frame (1)
- # reagent (3)
- # yada (7)
Yeah, I really like the SICP material. It’s been quite inspiring to read through it (I’m not quite done though).
oh cool, I’m going to have to watch her video on Adapting Clojure to a CS Classroom.
Are there any clojurescript libraries that use vdom and web workers in a way that the UI thread is only given the smallest possible patch, and nothing else is done in the UI thread?
That blog post really is a pretty good example of why the browser is such a terrible platform for development. It’s 2015 and people are excited for multithread, using technology that’s been around for 5 years (?), but has hardly been adopted because of lacking browser support - .-
Mind you, I’m not saying we should not dev for the browser, rather than this is just one of of those things that’s kind of funny and sad at the same time
It’s not a terrible platform, it’s just several OK-ish ones which are almost compatible, which is somehow worse
webworkers are pretty cool actually, only problem is that there is no efficient way to share data between them and the page
so you can end up in scenarios where serializing/deserializing stuff actually takes longer than the actual computation
does react have the ability to split the diff/patch/apply? that would be interesting
Hmm, but there's transferable objects as well to use shared memory instead of copying, and it says you can transfer MessagePort
s. This could probably serve to make it faster.
but the whole webworker thing falls apart as soon as you need anything from the dom anyways
Yeah, that's true, but being able to run logic there still looks like it could work sensibly
ehh, it’s not so bad. I make my cash dollars from JS, and it’s a more fun and expressive language to work in than many. There are warts, but with a bit of practice you can code around them. Not sure what your problem with the require stuff is; I like that it’s just an expression, so it’s immediately clear what scope you’re using a package in, although that’s going away with ES6 imports
And only now with CLJS and elm and friends are we getting really workable options for compile-to-JS languages with radically different semantics
https://github.com/nolanlawson/pokedex.org/blob/master/src/js/shared/monster/getMonsterWeight.js
It’s a fair point - the benefit you get from closure is the dead code analysis, which is exceptionally good
require/commonjs stuff works better on the node side, in the browser it’s a somewhat leaky abstraction which gets you the warm glow of familiarity, plus everything on NPM that makes sense in a browser
which is handy
Well, normal libraries don't look like that, I think. Take a look at react for example - it has a more sane module structure; they build up a module object and export that.
it depends what you mean by normal
react does that as well, the functions are just longer and sometimes have "some" support functions
look at lodash nowadays, you have the standard package with all the functions, but there’s also a NPM entry for each individual function
it’s partly philosophical (there’s an ideologically commitment to Tiny Things in node) but partly due to the dumbness of compilers, as discussed
ie, you don’t want 30k of lodash just for _.compact
Hello
Well the philosophical part is taken to the extreme, but ok, I get the "can't shake them trees" part.
probably
but for the time being, we have stuff like this https://www.npmjs.com/package/methods
exactly what it says on the tin (tm)
module.exports = [
'get',
'post',
'put',
'head',
'delete',
'options',
'trace',
'copy',
'lock',
'mkcol',
'move',
'purge',
'propfind',
'proppatch',
'unlock',
'report',
'mkactivity',
'checkout',
'merge',
'm-search',
'notify',
'subscribe',
'unsubscribe',
'patch',
'search',
'connect'
];
it’s a transitive dependency of some important packages, you can see there
well, in fairness, that list would only be written once in your application, so why should it be written more than once in the entire world? 😉
I'm quite new to CLJ+CLJS development, and I've kind of run into a wall with regards to thought process
@trancehime: what problems you running into?
@tragiclifestories: You can require single files with require
, so why separate packages?
@tragiclifestories: I'm stuck with trying to figure out a sane way to implement WebSockets using sente
on immutant
in order to create a sort of lobby system where I can keep track of users subscribed to a particular lobby
where would it go? I mean, you could put it in node stdlib somewhere, but what if I want a list of HTTP methods on the client with browserify/webpack etc
very few people require this directly, it’s just buried in express, request etc
I mean, the actual implementation part shouldn't be that difficult, but it's the whole logic and architecture behind it really
@trancehime: I’ve never worked with websockets so it’s a bit tough for me to go into specifics, but there’s some ideas floating around for the architecture stuff
@trancehime: how comfortable are you with Clojure? Because I have code for a presentation that does something really close to that (a chat with channels, but at the moment no join/part) I could link to
And then answer questions if it's unclear (which it probably will be, I'm not the greatest programmer ever)
@jaen Any references would be nice; I've pretty much been forced into using Clojure due to a work assignment/project, and deadline is real tight. I've already done and insane amount with the time I've been given, despite having only had about a few days of time allotted to refresh myself on it. So I'd say I
I'm fairly comfortable with it by now
you could have a look at this, another one of those post-flux/FRP ideas, should be nice and agnostic as to where your data is coming from https://github.com/Day8/re-frame
Yeah, I've actually read the re-frame README, a very interesting read. Unfortunately it's assuming your data is within the client-side using something like datascript
forgot about that bit
I've managed to populate my data with AJAX calls and present it in Reagent, so that's not a real problem
er, rather my atoms
And not to mention, I have to handle email notifications too, and postal
on the CLJ side really hasn't been helpful
At this point work is making me do full-stack all on my own in a language I've only just become comfortable in using haha
@trancehime: ok, so catch - https://gitlab.com/jaen/clj-cljs-presentation
@jaen thank you so much, I appreciate it
presentation.backend.async.core
is the backend, presentation.backend.async.core
is the frontend part of the async communications
presentation.backend.chat.core
is next-to-none backend logic, presentation.frontend.chat.core
is the chat reagent component
Now it's more complicated than strictly necessary, because I use transit for serialisation, take care of timestamps with clj-time/cljs-time and use component
@trancehime: actually re-frame doesn't assume datascript IIRC, it uses a single atom. But for something as simple as chat you could probably do without it.
@jaen: yeah, the examples just use a single atom but basically its explanations hinge on utilizing something like datascript
or basically data which could be populated on client-side such as a single app-state
ratom. But it just gave me some confusion as at the time I was reading it I had no idea how to process making AJAX calls and then rendering them in the render function. Now I know how to do it though haha
When I first learned of re-frame instead of using it I actually re-implemented it by going through the readme and source and this let me understand how it works. But that's certainly the long way round.
If time was something I had, I would have taken time to study the intricacies behind it. Sadly I do not
I thought of it mainly because it seems like a websocket would be a good candidate for treating as a stream in the FRP kind of way
I'm actually behind on schedule because of problems that occurred in my past work that I had to fix urgently
So, as I understand it, basically when async
is started, I don't have to care about how many potential channels
or pages I'm going to be having, right?
Ok, basically what I do is sente has this taoensso.sente/start-chsk-router!
function which takes two arguments - the receive channel you get out of taoensso.sente/make-channel-socket!
and a function that will be called for your message.
They are in the async file for you to read, but basically what they do is they match on the sente message, :chsk/recv
is a message that's received from the other side (so from client on server, from server on client)
And I have a multimethod that dispatches on the event, events are 2-tuples [:event-name payload]
and I just act accordingly
In this table here you have described what the messages look like - https://github.com/ptaoussanis/sente#now-what
I now see my code is slightly confused as to how it dispatches on event type, you should be able to dispatch just on id
in ev-msg
(those sente short names are somewhat confusign).
If I get :chat/new-message
I add the message to atom on the client side, I send it to other connected clients on server side. If I get :chat/new-channel
I add new channel, and so on.
omg. So actually, through using ch-recv
and chsk-send!
I am basically just manipulating the data structures and then sending it (optionally broadcast it if I need to) to other connected clients.
And you don't need to use ch-recv
directly, start-chsk-router!
sets the event loop up for you.
thank you
Gonna think about this, I have to go home, but I will be back
Sure, if anything's unclear there - feel free to ask. It will also help me, since I want to present to people that cannot into Clojure at all at some point, so any remarks on what's confusing will be helpful.
i noticed you used component
but does it matter much if I don't use it?
also i will try and see how does start-chsk-router
work
Figured, just wanted to be sure
In fact, if you're pressed for time it's probably better you don't, it slows you down somehow for benefits you won't get in a small, throwaway app.
Otherwise sente won't work and you'll be scratching your head as to why for a good while.
I already wrap those middleware
So it's fine
Then good; it's needed for the default implementation of user-id-fn
(you don't have to provide one, like I did)
I left it there because I cannibalised it from another project where the user-id
depended on authentication, you have to provide user-id
on your own in such cases
If your app doesn't need auth (you for example identify by usernames only) then no need to care about that.
incidentally i have used friend
for auth using a custom workflow, yet i dont want to open a connection until after they authenticate
thats been making my head spin a little
ANyway, is it posible for me to control when does the ws connection get opened?
most examples i saw start async immediately
I saw a blog entry of someone wrapping the sente routes behind friend/authenticated
but that seeemed really weird
I have a core.async channel that I can queue messages to send on and I connect when I want to.
And when I connect I just run a go-loop
that takes the messages from the channel and sends them, when connection breaks/disconnects, I stop the go-loop.
But most of the time connection ASAP is what you do; you don't have to though, entirely up to you.
And then if client supports it, it switches over to websocket, otherwise simulates it by (I think) long polling
hmm, right
now it makes sense
I've did it a bit differently, but I removed it from the presentation since it complicates things a little
I just decided I'll wrap all my messages to look like so {:payload actual-message :something-else i-need}
and set user id that way
When user authenticates I return him the id he should now have, he disconnects and reconnects with it
But such wrapping is nifty if you for example generate uuid for each message and can attach metadata to which message it was a reply (if you need so).
Hopefully you can get friend to cooperate easily, otherwise switching to buddy might be easier.
my auth is working fine wihout ws at the moment
So it should hopefully just work if you wrap sente routes (not sure if both or only the handshake one) and base user id on things friend assoc'd into the request map.
Yeah I was just using the default for friend
omg, that debug message. {:top "kek"}
this page is not really useful https://github.com/clojure/clojurescript/wiki/Companies-Using-ClojureScript
@jaen, @thheller FYI, my experience with web workes and cljs: https://groups.google.com/d/msg/clojurescript/Iu8ePb8OZR4/MEaan9zGBwAJ
@mike: tenzing uses boot. boot does not use project.clj
@martinklepsch: does cursive understand boot? I know it works with project.clj.
@martinklepsch: do I have to add the code to my ~/profile.boot
(is this where the file is supposed to be?), and then regenerate the boot project all over again?
you can also add it to your local build.boot file but since you might have multple projects/other people not using cursive you most likely want to put it into profile.boot
@mike: after you’ve added it you just need to run boot lein-generate
once and then after you add additional dependencies
@mike: the lein-generate task derives a project.clj from your build.boot so Cursive can parse that.
cool. do I have to keep running boot lein-generate
in the future to keep the two projects in sync?
yes, when you add dependencies you’ll need to re-run it
I'm working on creating a cljs-compatible js lib on cljsjs, and a clojars lib of my wrapper for that js lib (more details yesterday on this channel, 11:40am-1:30pm). Of those here who are familiar with either or both parts of that process, is there someone willing to be pestered with a bunch of noob questions about it?
Cool, thanks @martinklepsch . I'll hit you up in PM.
There’s #C0E66E1H7 as well
I do not find (.getElementById js/document "container")
intuitive, why not (js/document :getElementById "container")
?
@mike Consider (macroexpand '(.getElementById js/document "container”))
which yields (. js/document getElementById "container”)
And the macro is a 'method' macro that grabs the method from the object that comes next. Is that the way it works?
(.getElementById js/document ..)
is short for "get property getElementById of js/document and call it with ..."
I mean, can I import any clojure library into clojurescript code and have that library compiled to javascript?
given that figwheel already autoloads new changes, is there a point of evaluating code in repl, as it happens in clojure?
I'm trying to understand why one would want to connect to nrepl and evaluate clojurescript code.
I just created a new project using https://github.com/martinklepsch/tenzing , it requires boot-reload.
I think there are some thing that could be improved if they re-used figwheel code but don't really know what they are, since I didn't encounter any.
devcards isn’t really the same thing, it works with figwheel but doesn’t duplicate its functionality
Yeah, figwheel is used only for convenience with devcards, so you can get your devcards reloaded on the fly; I imagine you can use devcards with boot as well, I just didn't have an occasion to try yet
people are using devcards + boot
I didn't say it doesn't, it's just I didn't see an example. And it looks like there is one, thanks.
there are some other examples as well
is reagent a wrapper for a specific version of react, or can it be used with any react version? (sorry for x-post, #C0620C0C8 is mostly 💤 )
@jaen 0.14 has been out for a fairly long time, does reagent normally lag behind this much?
but it does not necessarily mean that when reagent is upgraded to 0.14, codes using reagent will need breaking changes.
Also when you're not using React directly I imagine changes to it are not as important as when you're writing React directly.
@mike document.body vs document["body"]
so, if I want to protect variable renaming from closure compiler advanced optimizer, I can use aget
?
maybe http://himera.herokuapp.com/synonym.html needs updating.
@mike: reagent started upgrade to 0.14 on 8 october ! https://github.com/reagent-project/reagent/commits/master?page=2 i guess the changes are somewhat more than trivial
and there will be some breaking changes, though i don't think these will break any of my code https://github.com/reagent-project/reagent/commit/348ac4aaf86dd120d0aa254dc06c5efa5991ce22
ubuntu users here? How do I get started? Java problem pops up first. Which version do I take?
Does anybody know how to extend Closure library classes with cljs? I am trying to use closure rich text editor and need to write a custom plugin. It would be nice to do it in cljs...
The code I would like to do should do something like this:
goog.editor.plugins.BasicTextFormatter = function() {
goog.editor.Plugin.call(this);
};
goog.inherits(goog.editor.plugins.BasicTextFormatter, goog.editor.Plugin);
/** @override */
goog.editor.plugins.BasicTextFormatter.prototype.getTrogClassId = function() {
return 'BTF';
};
@dreic: openjdk-8-jdk should be available in Ubuntu 15.10 and to install Oracle JDK 1.8 on older versions you can use this PPA: https://launchpad.net/~webupd8team/+archive/ubuntu/java
@juhoteperi: so openjdk is fine, too?
@nbdam: This might help a bit: https://gist.github.com/Deraen/8fede09ce77859004537
thanks @juhoteperi this looks like it will
just found this book with clojurescript exercises http://catcode.com/etudes-for-clojurescript/etudes-for-clojurescript.pdf
if some has a few minutes, i need some help getting data out of my channel ... in the cljs repl
simple-dash.core=> (def a (get-data))
#'simple-dash.core/a
simple-dash.core=> a
#object[cljs.core.async.impl.channels.ManyToManyChannel]
I tried (go (println (<! a))
which doesn't seem to work
@clojuregeek: if you have used enable-console-print!
it's normal you don't see it in the repl I think
if you really want to interact directly with the future value in the REPL, I think your best shot is putting it in an atom.
yeah i don't see anything in the browser... ok i'll try putting in an atom
hmm ... maybe the channel is returning null Uncaught Error: No protocol method ReadPort.take! defined for type undefined:
most likely a
is undefined