2014-10-08
| 00:01 | myguidingstar | wow, I can see lots of 'characters' marching |
| 00:01 | myguidingstar | is this a live broadcast of Hong Kong protest ;) |
| 00:01 | zanes | https://gist.github.com/zane/00655f136470458e21e1 |
| 00:02 | zanes | Seems useful, but I can’t tell if I’m being crazy. |
| 00:10 | devn | zanes: it was meant to be |
| 00:17 | dbasch | ,(apply str (map char (take 10 (repeatedly #(+ 30000 (rand-int 30000)))))) |
| 00:17 | clojurebot | "耞텊쁻빻鏚硑箔豶뼕腵" |
| 00:18 | dbasch | according to Google Translate that means "Some loss 텊 쁻빻 Qipingbofen 뼕 Jia" |
| 00:20 | devn | I can parse a little bit but... |
| 00:25 | zanes | Are there combinators for transducers other than comp? |
| 00:26 | zanes | e.x. (sequence (both (map inc) (map identity) [1 2 3]) ;; => (2 1 3 2 4 3) |
| 00:28 | beamso | i'm trying to use cljs-ajaxa |
| 00:28 | beamso | *cljs-ajax |
| 00:28 | beamso | it looks like there were undocumented broken changes |
| 00:29 | justin_smith | zanes: that looks like mapcat / juxt |
| 00:29 | justin_smith | ,(mapcat (juxt inc identity) [1 2 3]) |
| 00:29 | clojurebot | (2 1 3 2 4 ...) |
| 00:30 | justin_smith | is there a mapcat transducer type? |
| 00:30 | zanes | Yeah, that seems right. But I’d like to be able to do that with transducers instead of bare functions. |
| 00:30 | justin_smith | right |
| 00:31 | justin_smith | mapcat has a transducer arity... |
| 00:32 | justin_smith | ,(sequence (mapcat (juxt inc identity)) [1 2 3]) |
| 00:32 | clojurebot | (2 1 3 2 4 ...) |
| 00:32 | justin_smith | there we go! |
| 00:33 | justin_smith | and of course that mapcat could be combined with other transducers |
| 00:34 | zanes | Right, but what if inc and identity are themselves transducers? |
| 00:34 | zanes | i.e. What if we want to do filtering and such in there? |
| 00:38 | TEttinger | ##(mapcat (juxt inc identity) [1 2 3]) ; dammit justin_smith beat me to it |
| 00:38 | lazybot | ⇒ (2 1 3 2 4 3) |
| 00:38 | TEttinger | (inc justin_smith) |
| 00:38 | lazybot | ⇒ 89 |
| 00:39 | justin_smith | hell I even dug up the transducing version :) |
| 00:56 | nhanH | After I update to lein 2.5.0, I can't uberjar my app any more (Got a "java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest"), did something change? It was working fine with an earlier lein version (I can't figure out which version it is now though) |
| 00:56 | zanes | I guess what I really want is the transducer version of juxt. I can just compose that with cat. |
| 01:17 | lukecossey | Hey all. Anyone had much experience using goog.fx.css3.Transition in cljs? I've got it working perfectly for me in Chrome & Firefox, but the transitions don't happen at all in Safari... any ideas? |
| 02:50 | vIkSiT | hello all |
| 02:51 | vIkSiT | has anyone here used clojurescript/om? |
| 02:51 | vIkSiT | I'm wracking my head around this now |
| 02:51 | vIkSiT | how do I get component a to auto update, if component b does an ajax fetch? |
| 02:51 | lukecossey | Yeah it's great! |
| 02:52 | vIkSiT | I have an autocomplete module (the standard one) - which fetches data. |
| 02:52 | vIkSiT | I have a "search results" module that knows how to render a query |
| 02:52 | vIkSiT | Or rather, a set of search results |
| 02:52 | vIkSiT | But I don't know how to update the search results on an event where I click something on the autocomplete widget |
| 02:53 | vIkSiT | Since these are two components, and while they share app state, they are different cursors |
| 02:53 | vIkSiT | lukecossey, any pointers? :) |
| 02:53 | lukecossey | You could use core.async channels? |
| 02:53 | vIkSiT | lukecossey, I'm trying to figure out how |
| 02:53 | vIkSiT | for instance |
| 02:53 | vIkSiT | I can (put! my-chan search-result) |
| 02:53 | vIkSiT | but how do I get the search results component to "listen" to this? |
| 02:54 | lukecossey | You could store the my-chan in the app-state. |
| 02:55 | vIkSiT | but they have different cursors |
| 02:55 | vIkSiT | eg. (def app-state {:autocompelte [..] :search-results []) |
| 02:56 | vIkSiT | one gets key 1 and the other gets key 2 as their cursors |
| 02:56 | vIkSiT | so they can't reference the other key |
| 02:58 | lukecossey | You can pass the complete app state as well as your specific data through when you build the components. |
| 02:58 | lukecossey | (om/build page1-view {:specific cursor1 |
| 02:58 | lukecossey | :app-state app-state}) |
| 02:58 | lukecossey | (om/build page2-view {:specific cursor2 |
| 02:58 | lukecossey | :app-state app-state}) |
| 02:58 | lukecossey | Does that help at all? |
| 02:59 | vIkSiT | ah hmmm |
| 02:59 | vIkSiT | lukecossey, that's interesting - didn't know you could do that. quick orthogonal question |
| 02:59 | lukecossey | If the component is defined as (defn page-view [page owner] |
| 02:59 | vIkSiT | can you specify targets in om/build? |
| 03:00 | vIkSiT | eg, i have a page template built as a static html, but only two divs are om components (id autocomplete and results) |
| 03:00 | lukecossey | Then you can get the data with (get-in page [:specific]) |
| 03:00 | lukecossey | And the app-state with (get-in page [:app-state :autocompelte]) |
| 03:00 | vIkSiT | that makes sense |
| 03:01 | vIkSiT | So now I would ask |
| 03:01 | vIkSiT | How does Om know to re-render if that channel changes? |
| 03:01 | vIkSiT | is there some auto pub sub mechanism? |
| 03:03 | vIkSiT | lukecossey, ^ any pointers? |
| 03:04 | lukecossey | Something like this |
| 03:04 | lukecossey | om/IWillMount |
| 03:04 | lukecossey | (will-mount [_] |
| 03:04 | lukecossey | (let [my-chan (get-in page [:app-state :my-chan])] |
| 03:04 | lukecossey | (go (while true |
| 03:04 | lukecossey | (do-something-to-search-result (<! my-chan) owner))))) |
| 03:05 | lukecossey | (do-something-to-search-result (<! my-chan))))))* |
| 03:05 | vIkSiT | so will-mount is called every time something changes? |
| 03:06 | vIkSiT | ahh |
| 03:06 | vIkSiT | so we initialize this behavior in will-mount wih a go loop. |
| 03:06 | vIkSiT | I'm guessing this is in the search result view. hmm |
| 03:06 | vIkSiT | and then in autocomplete i can populate this channel |
| 03:07 | vIkSiT | lukecossey, is there a way I can force an re-render of the view itself if this channel changes? |
| 03:07 | lukecossey | https://github.com/swannodette/om/wiki/Documentation#iwillmount |
| 03:08 | esirola | hi |
| 03:08 | lukecossey | You need to change the state using set-state! |
| 03:08 | vIkSiT | ah |
| 03:09 | lukecossey | so once you receive the data from the channel, set it to (set-state! owner :search-results (<! my-chan)) |
| 03:09 | esirola | just looked hickey's talk on transducers (https://www.youtube.com/watch?v=6mTbuzafcII), very interesting |
| 03:10 | lukecossey | vIkSiT: and when you are building your search-results-list-view or whatever use (om/get-state owner :search-results). |
| 03:11 | esirola | will the modified map/reduce/etc enter clojure 1.7? |
| 03:11 | vIkSiT | lukecossey, use that in place of? |
| 03:12 | lukecossey | vIkSiT, I'm not entirely sure of your project, but that was just an example of how to the get-state to access any data coming from your channel... |
| 03:13 | vIkSiT | ah I see |
| 03:13 | vIkSiT | trying to wrap my head around this. |
| 03:13 | lukecossey | Yeah it's tricky when you start, I'm still learning! |
| 03:14 | vIkSiT | :) |
| 03:14 | lukecossey | This is the project I'm currently working on... https://github.com/Secondi/secondi-homepage/blob/develop/src/secondi/pages/video.cljs still early days, but it may help to see state use in action? |
| 03:16 | vIkSiT | lukecossey, that would be awesome |
| 03:18 | vIkSiT | lukecossey, so if I understand correctly |
| 03:19 | vIkSiT | select-video! sets the state :current-video in the main cursors thats given to that functino as well as the video page view |
| 03:19 | christian_stamm | Hi! Is it possible to generate doc of test code with lein-marginalia? |
| 03:20 | vIkSiT | and then the set-active! sets that state |
| 03:20 | vIkSiT | and because there's a go loop intiialized in will-mount. |
| 03:22 | vIkSiT | which checks the channel that is updated on click. |
| 03:23 | lukecossey | vIkSiT, select-video! actually sets the state, so not the cursor that's passed through to it. Notice in render-state, it uses (:current-video state) to get that video out of the state parameter. |
| 03:23 | vIkSiT | ah. |
| 03:23 | vIkSiT | this is very very veery useful :) |
| 03:23 | vIkSiT | I think I just need ot read through this |
| 03:23 | vIkSiT | I kinda get the feeling for it now hehe |
| 03:23 | lukecossey | And everytime the state is changed the component will re-render |
| 03:24 | lukecossey | Yeah, try get it running to help out with that. It's a wee bit messy, but hopefully it will help! |
| 03:27 | vIkSiT | lukecossey, any examples of where you actually render these views? |
| 03:27 | vIkSiT | using om/root? |
| 03:28 | lukecossey | Yeah have a look at the core file |
| 03:28 | lukecossey | https://github.com/Secondi/secondi-homepage/blob/develop/src/secondi/core.cljs |
| 03:28 | kungi | justin_smith: The culprit really is http-kit. I tried using jetty and I dont't get multiple content-length headers with it. I will file the bug report this evening. |
| 03:28 | lukecossey | It's a wee bit abstract |
| 03:29 | vIkSiT | ah thanks |
| 03:29 | vIkSiT | lukecossey, two more questions for you if you have time :) |
| 03:30 | vIkSiT | one - do you know if each om/build invocation can be given a separate target? |
| 03:30 | vIkSiT | and two - are you using secretary routing with a server side compojure/luminus style routing? |
| 03:43 | lukecossey | vIkSiT, Yes you can have multiple om roots. Not sure what you mean by targets |
| 03:43 | lukecossey | We use Django to serve our cljs applications and nginx for the server side routing I guess? |
| 03:44 | nonuby | is there a shortcut for importing multiple ns in one statement where paths only differ by final segment e.g. [acme.views.x :as x] [acme.views.y :as y] [acme.views.z :as z]? |
| 03:49 | vIkSiT | lukecossey, ah I mean. if I do the following, |
| 03:50 | vIkSiT | om/build ... {:target (document.getElemetbyId ("autocomplete") |
| 03:50 | vIkSiT | let me paste a gist |
| 03:50 | vIkSiT | lukecossey, https://gist.github.com/viksit/f1e9744a2cda4b0bf9fa |
| 03:51 | vIkSiT | Basically I can either do two calls to om/root |
| 03:51 | vIkSiT | or I can combine them into one app |
| 03:51 | vIkSiT | In the latter case, I don't know how to tell each om/build to happen in a *Separate* div |
| 03:51 | vIkSiT | by default, evrything gets rednered in the main div |
| 03:54 | nonuby | vIkSit, why cant you use om/dom to build app layout and do (dom/div nil (om/build ...), it will get messy if you are picking up div via getElementById more than a few times. you only desire a :target when using om/root |
| 03:56 | vIkSiT | nonuby, I could - except, that I have designers who do html design. |
| 03:56 | nonuby | so you'd have something like (render [_] (dom/div {:className "parent"} (dom/div nil (om/build autcomp (:autocomp data)) (dom/div nil (om/build timelime (:timeline data)) ))) |
| 03:56 | vIkSiT | now, either I shift them to using clojurescript :/ |
| 03:57 | vIkSiT | or, they give html, and then I inject the dynamic components in there using om |
| 03:57 | nonuby | ah i see, Im using jade and kioo to handle that.. |
| 03:57 | vIkSiT | nonuby, yeah, theyre doing photoshop -> html, the old way |
| 03:57 | vIkSiT | and I don't think rewriting all that is a good idea |
| 03:57 | vIkSiT | I personally like enlive.. |
| 03:57 | vIkSiT | but yeah |
| 03:58 | nonuby | thats okay the jade step is optional, you can't just take html so (render [_] (dom/div {:className "parent"} (dom/div nil (kioo/component "autocomp.html" autcomp (:autocomp data)) (dom/div nil (om/build timelime (:timeline data)) ))) |
| 03:58 | nonuby | you can't just --> you can just |
| 03:58 | nonuby | note kioo syntax not exact, but similar |
| 04:00 | nonuby | vIKSiT, just ideas (that may or may not be viable to your scenario), tis very new to me, and doesnt seem to be much guidance on best practice out there yet |
| 04:00 | vIkSiT | oh kioo can render html? |
| 04:00 | vIkSiT | oh i never thought of that |
| 04:00 | vIkSiT | good point |
| 04:00 | nonuby | if you supply zero transformation, then it will just render the html file |
| 04:01 | vIkSiT | that is *awesome* |
| 04:01 | nonuby | it does compile time to dom/* (thus using clj enlive under the hood) |
| 04:01 | vIkSiT | nonuby, fantastic |
| 04:01 | vIkSiT | that does make life a lot easier |
| 04:03 | nonuby | kioo reference the html files as java resources unless you use a wrapper macro to use arbitary file paths i use something like this https://gist.github.com/anonymous/8f2c26809ed88f0e6dd0 |
| 04:04 | nonuby | then you can just use (render [_] (filecomponent "myhtml.html {}) |
| 04:04 | nonuby | the last args is the transformations - which ive left empty, but usually want to make some |
| 04:05 | vIkSiT | ah |
| 04:05 | vIkSiT | thanks for the info! |
| 04:10 | mbuf | what is incorrect for this hello world example https://gist.github.com/shakthimaan/f6a501835198f1fd1d07? |
| 04:10 | mbuf | *in this |
| 04:10 | vIkSiT | hello mbuf. long time no see. |
| 04:11 | mbuf | vIkSiT, hi |
| 04:12 | nonuby | mbuf, is core.clj in src/clojure_noob (underscore vs dash) |
| 04:12 | mbuf | nonuby, oops, it is src/app/core.clj |
| 04:17 | mbuf | nonuby, works now; had to use (ns app.core ...) in core.clj and (:main app.core) in project.clj |
| 04:17 | mbuf | later |
| 04:19 | nonuby | yep your ns will your src path (usually..) |
| 04:33 | vIkSiT | lukecossey, around? |
| 04:33 | vIkSiT | following your example : https://gist.github.com/viksit/353d73081a0152aba0a8 |
| 04:33 | vIkSiT | I'm confused about how to implement the "click" button in my autocomplete view. |
| 04:33 | vIkSiT | Any ideas? |
| 04:36 | nonuby | r1 -> app |
| 04:37 | nonuby | actually ignore that, why you are reaching out to r1, shouldnt that be part of your app-state or shared state |
| 04:37 | vIkSiT | nonuby, hmm, im just making this in a way that works |
| 04:38 | vIkSiT | ultimately, r/r1 come from xhr calls.. |
| 04:38 | vIkSiT | all I want to do is - when i click that button, it does something that makes the search-results-view refresh :) |
| 04:39 | vIkSiT | nonuby, does that make sense btw? |
| 04:53 | clgv | update of *loaded-libs* is transactional but actually loading a namespace via `require` is not :( |
| 05:00 | dysfun | i have an odd issue with midje: lein midje can't find midje.util.ecosystem and bail out and yet (use 'midje.sweet) in lein repl works fine |
| 05:01 | clgv | dysfun: maybe there are multiple versions of midje classpath somehow. did you check "lein deps :tree" |
| 05:01 | clgv | and "lein classpath"? |
| 05:02 | dysfun | odd, midje isn't in 'lein deps :tree', but it's in project.clj |
| 05:02 | dysfun | no, ignore me, i'm in the wrong terminal tab :/ |
| 05:54 | lgrapenthin | I have a Java Application from which I invoke the start of tools.nrepl so that I have a Clojure REPL into it. Unfortunately, I don't get the print output via nrepl. How could I fix that? |
| 06:11 | clgv | lgrapenthin: you need to use some frontend for nrepl |
| 06:13 | lgrapenthin | clgv: what do you mean? I am wrapping cider middleware server side and jack in via cider from emacs |
| 06:14 | lgrapenthin | should say connect, not jack in |
| 06:14 | clgv | lgrapenthin: ah you use emacs+cider to communicate with that nrepl instance in your application? |
| 06:14 | lgrapenthin | clgv: yes |
| 06:14 | clgv | lgrapenthin: then check whether "lein repl :connect" works. if it does, you can blame cider |
| 06:15 | lgrapenthin | clgv: I can connect just fine |
| 06:15 | lgrapenthin | it's printing that doesn't work |
| 06:15 | clgv | lgrapenthin: I mean, connect with leiningen repl and try to evaluate the same stuff you tried from cider/emacs |
| 06:15 | lgrapenthin | e. g. (doc ...) (println ...) all return nil and print somewhere in netbeans |
| 06:15 | lgrapenthin | evaluation works fine |
| 06:16 | lgrapenthin | so I suppose I have to bind *out* to sth. else |
| 06:16 | clgv | and printing does not work in lein repl as well? |
| 06:16 | lgrapenthin | but don't know what |
| 06:17 | clgv | you did bind *out* manually? |
| 06:17 | lgrapenthin | clgv: nope. and lein repl does work |
| 06:17 | lgrapenthin | clgv: apparently |
| 06:18 | clgv | lgrapenthin: I have a working nrepl in my application just via "(nrepl/start-server :port nrepl)" |
| 06:18 | clgv | lgrapenthin: ok, so maybe the printing output ends up in some strange buffer in emacs? |
| 06:18 | lgrapenthin | clgv: me too. and your guess was right. it must be ciders fault |
| 06:19 | clgv | lgrapenthin: I usually check pure lein first when my IDE/editor does strange things with respect to leiningen's feature set |
| 06:20 | lgrapenthin | clgv: hmm. this is strange because when I use nrepl-jack-in cider prints fine |
| 06:21 | lgrapenthin | thanks anyway |
| 06:21 | clgv | lgrapenthin: yeah maybe something differs when you connect to a foreign repl |
| 06:24 | clgv | didn't nightcode have it's repl and editor as standalone component libraries? or was that some other project? |
| 06:25 | clgv | aah ok, you can use them separately but it is on lib |
| 06:38 | clgv | back to the topic of transactional require (ensure that a namespace is only required once when multiple thread need it at the same time): I tested this snippet with multiple thread and it seems to work. any opinions, concerns or suggestions? https://gist.github.com/guv/ac76b9ab1878705062c6 |
| 06:41 | weavejester | clgv: Why do you use a ref? |
| 06:42 | clgv | weavejester: because I need to return the delay instance |
| 06:44 | weavejester | clgv: Okay… but why go to all that trouble? If you just want a require to be evaluated once, why not using locking? |
| 06:44 | weavejester | *use locking |
| 06:44 | weavejester | For that matter, is require thread unsafe? |
| 06:44 | clgv | weavejester: yes it is |
| 06:45 | clgv | weavejester: only *loaded-libs* is managed in a ref but not used to decide whether the actual `load` needs to happen |
| 06:45 | clgv | weavejester: I found this from an actual problem |
| 06:47 | weavejester | clgv: So why not something like (let [o (Object.)] (fn [ns] (locking o (require ns)))) |
| 06:47 | clgv | weavejester: the construction is motivated that the only waiting should occur when multiple thread require the same namespace. if they require different ones or a require is not needed then they should not wait |
| 06:48 | clgv | weavejester: yes but that way everyone must wait |
| 06:48 | weavejester | clgv: Is there any other safe way of doing it? |
| 06:48 | weavejester | clgv: If you have namespaces a and b that both depend on c |
| 06:48 | clgv | weavejester: humm right my solution does not account for the fact o transitive namespaces being required in parallel |
| 06:48 | weavejester | clgv: You’d need to know that you can’t load up a concurrently with b if c is not loaded |
| 06:49 | clgv | weavejester: I wish Clojure had that built-in... |
| 06:49 | clgv | ok back to simple locking ... |
| 06:49 | clgv | ah well at least I can check what was already loaded. |
| 06:50 | weavejester | Unless it becomes a performance issue, I’d be tempted just to go for the simplest solution |
| 06:51 | clgv | weavejester: it is an issue. usually I have around 20 threads using this. |
| 06:52 | weavejester | clgv: What’s the use case? I mean, what are you doing for that to happen? |
| 06:52 | clgv | weavejester: it's a "worker server" implementation |
| 06:53 | weavejester | clgv: So… you load up worker functions/namespaces on the fly based on messages to the server? |
| 06:53 | clgv | which does not know anything about specific implementations and thus can not preload application specific stufff |
| 06:53 | clgv | weavejester: yeah, you can describe it like that |
| 06:53 | weavejester | clgv: Have you considered using classloaders? |
| 06:54 | clgv | weavejester: not in the current state. I think if I had the time I'd change to single worker jvms |
| 06:56 | clgv | weavejester: since 20 threads in one jvm on a 20 core intel get a significant penalty with respect to individual task runtime compared to tasks being executed in a single thread |
| 06:57 | clgv | weavejester: I am not entirely sure what the reason is, since these computations share nothing but the implementation. maybe jvm maybe clojure itself |
| 06:57 | weavejester | clgv: Really? I was under the impression the JVM was pretty good at assigning threads to cores |
| 06:58 | clgv | weavejester: if I remember correctly I had individual task runtimes increased by at least a factor of 2 |
| 06:59 | clgv | weavejester: not sure if there are impacts from cpu cache misses and stuff due to 20 parallel executions... |
| 06:59 | weavejester | clgv: If the server is constantly running, then surely a require would only happen once? |
| 06:59 | weavejester | clgv: So performance issues would only be limited to the first time it requires a namespace |
| 07:00 | clgv | weavejester: oh these performance figures where not about the `require` but in general |
| 07:00 | weavejester | clgv: So a concurrent require might not be your problem? |
| 07:01 | clgv | weavejester: no, I switched context without a hint, sorry ;) |
| 07:01 | clgv | weavejester: I am back to https://gist.github.com/guv/ac76b9ab1878705062c6 |
| 07:03 | weavejester | clgv: Why do you use *loaded-libs* directly? Why not (loaded-libs) ? |
| 07:03 | Gonzih | Hi guys, how should I configure log4j from inside lein plugin? |
| 07:04 | clgv | weavejester: oh damn, I did not find that one. I search clojure.core but seems I missed that one |
| 07:04 | clgv | weavejester: thank you |
| 07:07 | weavejester | Gonzih: Which lein plugin? |
| 07:09 | clgv | Gonzih: you can configure it programmatically if that is better for your usecase. you just need to set the appropriate properties in (System/getProperties). that way you can also retrieve them from project.clj and set them |
| 07:09 | Gonzih | weavejester: I'm working on my own plugin (lein-feeds2imap). I just reuse my existing project inside which logs everything to console logger using clojure.tools.logging. But there is no output from within lein plugin call. |
| 07:09 | Gonzih | here is plugin code https://github.com/Gonzih/lein-feeds2imap |
| 07:10 | clgv | Gonzih: it probably does not pickup the log4j.properties file |
| 07:11 | Gonzih | I have one in dependency library and in plugin src directory |
| 07:11 | Gonzih | is there any way to set properties file using setProperty call? |
| 07:11 | clgv | Gonzih: yes. like I said above |
| 07:11 | clgv | Gonzih: ah no the properties and not the file ;) |
| 07:13 | clgv | Gonzih: there is also Properties.load - not sure if that works on the (System/getProperties) |
| 07:35 | gnzh | clgv: I tried to use clj-logging-config without much success. |
| 07:36 | clgv | gnzh: I have a working solution where I just set the properties via a function. but loading them seems possible as well |
| 07:36 | gnzh | can you show me example? |
| 07:36 | gnzh | of loading via fn |
| 07:41 | gnzh | clgv: can you? please :) |
| 07:42 | cYmen | What do I need to do to install cider-nrepl? I get this error: https://www.refheap.com/4437faae1d2d42f5f2c766670 |
| 07:43 | LauJensen | Gents. I have an app running that I wrote some time ago. I've now opened it in Lighttable and connected to an nrepl. Everything loads fine but Im looking to connect a Watch to one of my vars, Alt-W gives me nothing, what do I do ? |
| 07:48 | kungi | cYmen: include the plugin in your project.clj or profiles.clj |
| 07:48 | cYmen | kungi: I'm not in any project... |
| 07:48 | kungi | cYmen: then include it in the user profile of ~/.lein/profiles.clj |
| 07:49 | justin_smith | cYmen: ~/.lein/profiles.clj applies even if not using a project |
| 07:49 | kungi | hi justin_smith |
| 07:49 | justin_smith | also, that message misspells the snapshot name |
| 07:49 | justin_smith | 0.8.0-SNAPSHOT |
| 07:49 | justin_smith | kungi: hello |
| 07:49 | cYmen | I don't have that, can either of you provide me with a reasonable default, please? :) |
| 07:50 | justin_smith | {:user {:plugins [[cider-nrepl "0.8.0-SNAPSHOT"]]}} |
| 07:50 | justin_smith | that goes in ~/.lein/profiles.clj |
| 07:53 | justin_smith | here's a thing though: that snapshot, being a snapshot, will be replaced on occasion with a new snapshot version, and things may break unless you also update to the latest alpha elisp code that goes with it |
| 07:54 | justin_smith | and sometimes the latest version of either one will be just plain broken - it's alpha software |
| 07:57 | jcidaho | Hi is there a way in core.async to wait on a channel to have finished processing everything in its buffer, once it's been closed? |
| 07:58 | cYmen | justin_smith: What do you do for a living? :p |
| 08:04 | justin_smith | $mail cYmen backend clojure web developer |
| 08:04 | lazybot | Message saved. |
| 08:04 | cYmen | Back! |
| 08:05 | justin_smith | heh, you get that message from lazybot? |
| 08:06 | cYmen | jep :) |
| 08:07 | dnolen_ | jcidaho: no |
| 08:07 | cYmen | justin_smith: Apparently this nrepl version does not exist.... |
| 08:08 | cYmen | cider-nrepl |
| 08:08 | justin_smith | oh sorry |
| 08:08 | justin_smith | it's cider/cider-nrepl |
| 08:08 | justin_smith | {:user {:plugins [[cider/cider-nrepl "0.8.0-SNAPSHOT"]]}} |
| 08:09 | clgv | gnzh: just combine java.lang.System.getProperties, java.util.Properties.load and maybe clojure.io/resource |
| 08:09 | cYmen | justin_smith: Works. Thanks! |
| 08:35 | noncom | is there any clojure lib that allows to easy record function calls, their parameters and time of happening ? |
| 08:35 | noncom | and then reproduce it.. ? |
| 08:39 | gfredericks | noncom: what's the use case? debugging? logging? |
| 08:40 | noncom | gfredericks: saving the order of actions to reproduce later.. closer to a save game |
| 08:41 | noncom | just to be able to play back / stop /pause / modify |
| 08:41 | noncom | record user actions i mean |
| 08:41 | justin_smith | noncom: tools.trace will show arguments / return value, but doesn't record them for replay per se |
| 08:46 | bacon1989 | I have a clojurescript question for you guys. I'm trying include an html shiv for IEs issue with console.log, but I can't seem to figure out how to include a new Var in a namespace that i'm not currently in |
| 08:46 | bacon1989 | basically, I need to include a js/console |
| 08:46 | CookedGryphon | If I were to implement a simple Tuple2 with deftype, what would I need to support to allow destructuring, nth, first, second and last? |
| 08:46 | ro_st | better to shim in normal javascript, bacon1989 |
| 08:47 | bacon1989 | so basically, I hsould just let someone else deal with the issue? |
| 08:47 | bacon1989 | I could always just tear the console.log messages out |
| 08:47 | ro_st | i think the js ns is handled differently in the code. dnolen_ can confirm. to answer your actual question, generally speaking, you can (in-ns 'something) (def some-var), but i'm not sure if that's for cljs too |
| 08:48 | ro_st | better to use (enable-console-print!) … (prn …) |
| 08:48 | dnolen_ | ro_st: in-ns only works for REPL interaction |
| 08:48 | dnolen_ | bacon1989: I'm not sure what you are saying. What does shimming have to do w/ console.log |
| 08:48 | dnolen_ | ? |
| 08:49 | noncom | CookedGryphon: look at the sources of destructure, nth and other fns ? |
| 08:49 | ro_st | dnolen_: i think he wants to do that fix that makes it safe to console.log in older IE |
| 08:49 | dnolen_ | bacon1989: if want to *use* console.log (.log js/console "foo") |
| 08:49 | noncom | CookedGryphon: i have looked at destructure recently |
| 08:49 | dnolen_ | bacon1989: (if (exists? js/console) ...) |
| 08:49 | noncom | you may find it informative |
| 08:50 | ro_st | dnolen_: your webinar code was super handy today. finally got to start using transducers today |
| 08:50 | ro_st | so good. |
| 08:50 | dnolen_ | ro_st: sweet |
| 08:51 | folippi | I'm a developer who's been working with Ruby, Python, Javascript, the usual. I'm super intrigued by clojure/cljs, FP and lisp. I dream wet dreams about doing it 9-5. Would one make an ass of themselves by showing up in a clojure shop and saying "I don't know clojure, but I'm interested and want to learn. I'll take a great pay cut for the chance to do that here" and like ask for a one year contract with low pay but get to write c |
| 08:51 | folippi | lojure and become a pro? |
| 08:51 | ro_st | folippi: if you did that, it'd probably just be a Wednesday for the person you're asking. put another way, no. not at all :-) |
| 08:52 | ro_st | Clojure is still new enough that folks learn it on the job |
| 08:52 | dnolen_ | bacon1989: (when (exists? js/console.log) (defn log [varArgs] (.apply js/console js/console js/arguments))) |
| 08:52 | ro_st | this is true for my whole team and i |
| 08:54 | folippi | Ok, that's reassuring ro_st :). I'll gather some confidence and go for it! |
| 08:54 | ro_st | folippi: having said that, it certainly wouldn't hurt to hack on some opensource and demonstrate some knowledge with the paradigm |
| 08:54 | folippi | ro_st: right |
| 08:55 | ro_st | do you have any experience at all? |
| 08:55 | ro_st | if not, clojurekoans.com is a great place to start |
| 08:56 | bacon1989 | dnolen_: neat, thank you |
| 08:56 | kungi | Having the requirement that I develop customized versions of our product for some customers I would like to create a plugin system. For loading plugins I thought about using pomegranate to add the dependencies at runtime and then load a namespace and call a well known function (like init-plugin). How would one unload a plugin at runtime and remove the dependency from the classpath as well. |
| 08:56 | folippi | ro_st: I've done those, and I've done a few tutorials (especially cljs/om) and I enjoy seeing how advanced things I can do in the lighttable instarepl. But I still havent gotten the hang of emacs (old time vim-mer) and all of that |
| 08:57 | bacon1989 | dnolen_: but with that method, wouldn't I need to start using the log function? |
| 08:57 | ro_st | folippi: you might consider skipping emacs and using cursiveclojure.com instead |
| 08:57 | bacon1989 | not that that's a big deal |
| 08:57 | kungi | folippi: have you tried evil mode? It's a very neat vim emulation in emacs |
| 08:58 | dnolen_ | bacon1989: ah you want the JS-ism |
| 08:58 | folippi | kungi: tried to set it up but gave up. And I figure learning the 'real' way before would be a good idea |
| 08:58 | ro_st | folippi: Timothy Baldridge has a nice overview here https://tbaldridge.pivotshare.com/media/overview-of-cursive-clojure/9349/feature |
| 08:58 | dnolen_ | (def (set! (.-console js/window) (fn [...] ...))) |
| 08:58 | kungi | folippi: 'real' way? |
| 08:58 | folippi | ro_st: that looks really really neat! Thanks for sharing |
| 08:58 | bacon1989 | dnolen_: it's all good, i'm likely just going to document that it uses console.log, and suggest people use shiv if they have issues |
| 08:58 | ro_st | and one for clojurescript https://tbaldridge.pivotshare.com/media/cursive-and-clojurescript/12952/feature |
| 08:58 | folippi | kungi: well well ;) |
| 08:59 | ro_st | i did the emacs gauntlet and use it daily, but cursive is getting more and more appealing as an alternative |
| 08:59 | dnolen_ | bacon1989: ok, but using console.log like will likely mean people just won't use your lib so I don't know if you will need a notice ;) |
| 09:00 | ro_st | folippi: lots of stuff to explore at www.stuttaford.me/codex/. courses, books, talks, screencasts. jump in and make something :-) |
| 09:00 | dnolen_ | bacon1989: and that should have been (set! (.-console js/window) #js {:log (fn [...] ...) :error ...}) |
| 09:00 | bacon1989 | well, it's only being used for subscriptions that don't provide a callback |
| 09:00 | bacon1989 | in otherwords, it doesn't affect production code |
| 09:01 | bacon1989 | it's specifically for when developing |
| 09:01 | dnolen_ | bacon1989: k makes more sense |
| 09:01 | bacon1989 | https://github.com/benzap/flyer.js/blob/master/src-cljs/flyer/messaging.cljs#L19 |
| 09:02 | bacon1989 | yeah, I could probably take it out |
| 09:26 | CookedGryphon | How does one make a deftype'd class available to java at aot compile time? |
| 09:29 | justin_smith | CookedGryphon: clojure aot doesn't use javac does it? |
| 09:30 | CookedGryphon | Umm... |
| 09:34 | cddr | Hey folks, what do you think of this idea? https://github.com/cddr/crud |
| 09:35 | ro_st | cddr: have you looked at liberator? |
| 09:35 | ordnungswidrig | I like it (even if you don't use liberator) |
| 09:35 | ordnungswidrig | But beware that CRUD does not match web/http and rest very good. |
| 09:36 | ro_st | same. i haven't used liberator, but i know it plays in the same space, so i'm curious if it solves a different problem |
| 09:38 | ordnungswidrig | However, I'd love to see something like that to be implemented on top of liberator. Adding etag, et.al. would be nice, I guess. |
| 09:40 | cddr | ordnungswidrig: There's a CRUD/HTTP impedence mismatch? How so? |
| 09:40 | ordnungswidrig | PUT is more like Create or Update |
| 09:40 | ordnungswidrig | and POST is not necessarily create |
| 09:43 | cddr | Hm, maybe I should change the name because I definitely want it to be "RESTy" |
| 09:43 | kungi | hi ordnungswidrig |
| 09:44 | ordnungswidrig | :-) |
| 09:46 | kungi | ordnungswidrig: Can I somehow remove a dependency from the classpath at runtime? With pomegranate I can add one but ... |
| 09:51 | xeqi | kungi: theres nothing built to do it currently |
| 09:52 | xeqi | it'd take a lot of classloader fiddling |
| 09:52 | ordnungswidrig | just restart the repl |
| 09:57 | kungi | ordnungswidrig: that is sadly not an option in this case |
| 09:57 | kungi | xeqi: hmm ok thank you |
| 09:58 | justin_smith | kungi: what end would removing an item from the classpath achieve? |
| 09:59 | kungi | justin_smith: for example unloading a plugin at runtime and make it not reloadable any more |
| 10:01 | stuartsierra | kungi: OSGi is designed for that sort of thing, but it comes with its own slew of problems and it doesn't work very well with Clojure's dynamic classloaders. |
| 10:02 | TimMc | Several Clojure programmers I know are even now sinking slowly into that tarpit. |
| 10:03 | kungi | TimMc: the OSGi tarpit? |
| 10:03 | TimMc | yeah |
| 10:03 | borkdude | I saw a slide somewhere that said NOOSGi (as a feature) |
| 10:04 | TimMc | That's not to say OSGi is a bad idea; I don't really know anything about it except that some people are attracted to the feature set (like moths to a lamp?) and are really struggling to wedge Clojure in there. |
| 10:17 | clgv | you could talk to laurent petit about what impact OSGi had on for Counterclockwise development |
| 11:01 | AeroNotix | asd |
| 11:06 | kungi | AeroNotix: f |
| 11:06 | AeroNotix | kungi: aaioun |
| 11:06 | kungi | uiae |
| 11:07 | ordnungswidrig | äöü |
| 11:08 | kungi | ordnungswidrig: The germans are coming with their umlauts ... |
| 11:09 | kungi | Hopefully at least someone I dont't know will attend our user group meeting this evening :-) |
| 11:10 | wink | ß |
| 11:10 | ordnungswidrig | ☃☃☃ |
| 11:10 | ordnungswidrig | *SCNR* |
| 11:11 | wink | hehe |
| 11:11 | wink | I don't have that on my keyboard. only λ, µ and … |
| 11:11 | karls | õ |
| 11:11 | kungi | νρτδψγφϕ |
| 11:12 | CookedGryphon | With a java writer (I'm overriding a print-method - for something which gets called a *lot*), which is quicker and results in less memory churn: |
| 11:12 | CookedGryphon | (.write writer (str a b c)) or (.write writer a)(.write writer b)(.write writer c) |
| 11:33 | ordnungswidrig | wink: copy it form here http://unicodesnowmanforyou.com/ |
| 11:33 | wink | boo |
| 11:34 | kungi | wink: where are you from? |
| 11:38 | mikerod | Is there any chance that in a "hot spot" of code that `apply` would be quite a bit slower than doing a direct function invocation? |
| 11:38 | Bronsa | mikerod: yeah |
| 11:38 | mikerod | I know there has to be more overhead to going through the AFn.applyToHelper |
| 11:39 | gfredericks | mikerod: also sequence construction/traversal |
| 11:39 | mikerod | but is something like this preventing some good JVM optimizations from happening? |
| 11:39 | wink | ordnungswidrig: there you have it. caps-n is now ☃ |
| 11:39 | mikerod | I end up seeing profiling showing me a lot of PersistentList#first happening |
| 11:39 | wink | kungi: Germany |
| 11:39 | Bronsa | you're definitely preventing some clojure optimizations too |
| 11:39 | mikerod | from the applyToHelper |
| 11:39 | mikerod | Yikes, I never knew this |
| 11:39 | kungi | wink: yes I am aware of that where in germany |
| 11:39 | mikerod | I guess it is obvious |
| 11:40 | Bronsa | mikerod: only in some cases though, e.g. when using a primitive function or a protocol function |
| 11:40 | mikerod | Bronsa: gfredericks thanks for the feedback. Looks like I need to play around with restructuring this code a bit. |
| 11:40 | Bronsa | or an inlineable one |
| 11:40 | mikerod | Bronsa: oh... it is a protocol function... |
| 11:40 | wink | kungi: why are you aware? because I can type ß? ;) Munich it is |
| 11:40 | mikerod | now that I think of it |
| 11:41 | kungi | wink: yes because you have an ß on your keyboard. |
| 11:41 | kungi | wink: I am from Mannheim |
| 11:41 | Bronsa | mikerod: direct protocol invocations have a callsite cache |
| 11:41 | mikerod | I didn't see anything from the profiling that "looked protocol-fn'ish", but who knows if it'd show up |
| 11:41 | clgv | humm, neithder wink nor kungi are on #clojure.de ... |
| 11:41 | mikerod | Bronsa: Yeah, I've seen some of this in the compiler before. I definitely haven't dug into the details though. |
| 11:41 | wink | kungi: I have us-intl with a custom xmodmap :P |
| 11:41 | kungi | clgv: there is a clojure.de? |
| 11:42 | wink | clgv: didn't know it existed until now :D |
| 11:44 | mikerod | Bronsa: Is there anywhere out there that explains this callsite caching at all? |
| 11:45 | Bronsa | no |
| 11:45 | mikerod | Bronsa: I'm just interested in mechanics of that and how to be sure to utilize it. Is one of those things that just comes down to reading through the Compiler, etc? |
| 11:45 | mikerod | Yay. :P |
| 11:46 | mikerod | I don't mind reading the details, but I do love it when I can first come across some design talk/notes or something. |
| 11:56 | literary | Is there some kind of mnemonic to remember which of cond and case take an odd number of args or takes a truthy value like :else? |
| 11:56 | literary | Every single time, I have to look it up in Dash. |
| 11:58 | literary | Also, does Clojure have goto? Right now I have code stored in an anonymous function which I call on two of three cond branches. |
| 12:02 | csd_ | Why would having AOT compilation enabled cause class not found errors when I try to run an uberjar? Adding ^:skip-aot to :main was the only thing that was able to fix this. |
| 12:02 | literary | So many questions, so few answers. |
| 12:04 | mdrogalis | csd_: Not that I know of, no, and because AOT is hairy. |
| 12:04 | mdrogalis | Answered in order. |
| 12:05 | csd_ | weird, fair enough |
| 12:05 | kungi | csd_: are the namespaces present in the uberjar? |
| 12:06 | stuartsierra | literary: Only `cond` uses an :else clause |
| 12:07 | stuartsierra | literary: No, Clojure does not have anything like goto. |
| 12:07 | csd_ | kungi: There were a bunch, but what resolved the problem was doing ^skip-aot to the .core ns that contains -main |
| 12:07 | literary | Okay I'll try to come up with a mnemonic. |
| 12:07 | mdrogalis | Er, meant to reply to literary, not csd_. Sorry. |
| 12:09 | kungi | stuartsierra: Can I prevent tools.namespace.repl/refresh from trying to load the test namespaces? I moved all test dependencies to the :test profile in leiningen and now refresh breaks. |
| 12:09 | stuartsierra | kungi: Yes, you can change the set of directories that `refresh` uses. |
| 12:10 | stuartsierra | kungi: http://clojure.github.io/tools.namespace/#clojure.tools.namespace.repl/set-refresh-dirs |
| 12:10 | mr_rm | I'm using Liberator (http://clojure-liberator.github.io/liberator) and i'm confused by something. My :handle-created function is getting called even when I'm doing a GET (also on POST). Is that normal behavior? The HTTP response for my GET is 200 but it's still calling the :handle-created handler. |
| 12:12 | literary | "C.O.N.D. = continuously obeisant, never diacritic" |
| 12:12 | literary | no that won't do |
| 12:12 | literary | "COND -> can't otherwise notify deadra" |
| 12:13 | literary | this is hard |
| 12:13 | literary | "cond uses :else -> cuz otherwise nobody does" |
| 12:13 | literary | okay that one works. |
| 12:14 | donbonif_ | isn't this: (fn [x] true) the same as this: #(true) ? |
| 12:14 | literary | donbonif_: No. |
| 12:14 | literary | donbonif_: same as (fn [x] (true)) |
| 12:14 | literary | ,(#(true)) |
| 12:14 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.IFn> |
| 12:14 | donbonif_ | ohhhh, that's it. thanks literary |
| 12:14 | literary | My pleasure. |
| 12:29 | mr_rm | I'm using Liberator (http://clojure-liberator.github.io/liberator) and i'm confused by something. My :handle-created function is getting called even when I'm doing a GET (also on POST). Is that normal behavior? The HTTP response for my GET is 200 but it's still calling the :handle-created handler. |
| 12:40 | kungi | stuartsierra: thank you |
| 12:53 | razum2um | can I destruct a vector like this (let [[x & ys z] (range 10)] (println ys)) ? |
| 12:54 | razum2um | this obviosly doesnt work but you get the idea? |
| 12:54 | dnolen_ | razum2um: you cannot |
| 12:54 | razum2um | dnolen_: so I should use butlast ? |
| 12:54 | dnolen_ | razum2um: yes |
| 12:55 | razum2um | btw, is this a fundamental restriction of ISeq or just wait to be implemented? |
| 12:55 | razum2um | i understand, that in case of lazyseq it realizes it |
| 12:56 | razum2um | but so butlast does anyway |
| 12:58 | dnolen_ | razum2um: I don't personally see the value of supporting this kind of sugar. butlast + last work fine |
| 12:59 | Bronsa | dnolen_: by that same logic, first and rest work fine too :) I've had the desire for a destructuring syntax from both ends too |
| 13:00 | dnolen_ | Bronsa: first/rest can obviously work relatively efficiently for seqs, not true for this |
| 13:00 | razum2um | dnolen_: still, don't get why not? so ruby does: a, *b, c = (1..10).to_a; b |
| 13:01 | dnolen_ | razum2um: anyways, I'm placing my bet now this will never happen :) |
| 13:02 | Bronsa | dnolen_: right, I'm just saying it's not unreasonable to expect the existence of some sugar for that, after all we have special sugar for map destructuring |
| 13:03 | razum2um | Bronsa: exactly. I miss map destruction in ruby, it's awesome ;) |
| 13:03 | Bronsa | razum2um: not sure what you mean with that, clojure can already destructure maps |
| 13:03 | razum2um | yes, I know |
| 13:03 | dnolen_ | razum2um: rhickey is a relatively perf conscious lang designer - in general sugary constructs with linear complexity are avoided |
| 13:04 | Bronsa | razum2um: ah yeah I get it now |
| 13:07 | razum2um | dnolen_: actually, why do variables need to be realized instantly? in this case [a &b c] - c might be like a future and b still a lazyseq of butlast result |
| 13:08 | razum2um | under the hood it will be the same as actuall call but more concise |
| 13:08 | razum2um | dnolen_: btw, it this behaviour doable by macros? |
| 13:08 | dnolen_ | razum2um: your idea doesn't seem to jive with future or deref'ing patterns that already exist in the language |
| 13:09 | dnolen_ | razum2um: no implicit future would need compiler support |
| 13:11 | razum2um | dnolen_: mm, look it doen't need to be actual IDeref, it can be just transformed in the scope somehow to @c |
| 13:11 | razum2um | by parser i mean |
| 13:11 | dnolen_ | razum2um: which doesn't address it being returned as a value |
| 13:12 | razum2um | dnolen_: sorry, don't understand you |
| 13:12 | devn | Given I have {:name "foo" :id 1 :children [{:name "bar" :children [{:name "baz"}]}]}, I want: [{:name "foo" :id 1} {:id 2 :name "bar" :parent-id 1} {:id 3 :name "baz" :parent-id 2}] |
| 13:12 | dnolen_ | razum2um: if it escapes the let binding i.e. gets returned as a value |
| 13:17 | razum2um | dnolen_: yep, got you, but still parser can detect these cases like it does with recur and transform internally to let + [a b @c] where b already got realized |
| 13:17 | dnolen_ | razum2um: if you can't solve escaping, the other parts don't really matter |
| 13:19 | razum2um | dnolen_: sorry, but still don't get you. I won't optimize this by hijacking futures, just sugar. anyway in this case i care about b, not c and b still can stay lazy |
| 13:20 | razum2um | actually i mean [a &b _] |
| 13:21 | razum2um | otherwise [a &b c] - parser can (should) realize b and get last one |
| 13:21 | kungi | Is there a refactoring tool to rename symbols project wide in emacs? |
| 13:22 | dnolen_ | razum2um: or you could just right a simple function that does this |
| 13:22 | razum2um | dnolen_: hm, yes. perhaps it's best one |
| 13:22 | dnolen_ | (defn foo [x & xs] [x (butlast xs) (last xs)]) |
| 13:23 | dnolen_ | (let [[a b _] (foo (range 10))] ...) |
| 13:24 | razum2um | dnolen_: hm, are you sure xs isn't gtting realized inside foo? |
| 13:24 | dnolen_ | razum2um: yes it will be realized by the call to last, if you really don't care about the last thing then just use butlast |
| 13:25 | razum2um | :\ ok, will stay with that, thanks! |
| 13:35 | cYmen | What's the preferred browser connected repl these days? Do people still use brepl? |
| 13:35 | dnolen_ | cYmen: I do for simple stuff, but Weasel is very popular now |
| 13:37 | cYmen | Differences? Reasons? |
| 13:38 | mikerod | In clojure.core/emit-defrecord I was looking at the impl |
| 13:38 | mikerod | This line particularly regarding hasheq made me think: `(hasheq [this#] (bit-xor ~type-hash (clojure.lang.APersistentMap/mapHasheq this#)) |
| 13:38 | mikerod | type-hash is just (hash classname) |
| 13:38 | mikerod | how is this guaranteed to not ever collide 2 class names to the same hash |
| 13:39 | mikerod | So 2 classes, same classname hash and same map contents would be = |
| 13:39 | Bronsa | mikerod: hashes don't have to be unique |
| 13:39 | mikerod | Bronsa: I know, and if they weren't we could get a false positive for = |
| 13:39 | mikerod | that's why I'm asking |
| 13:40 | Bronsa | mikerod: if two colls have a different hash, they are guaranteed to be different, if two colls have the same hash they are not necessarily equal |
| 13:40 | mikerod | However, this is a (hash classname), which I think is really a clojure.lang.Util#hasheq call on a String |
| 13:40 | mikerod | which uses Murmur3.hashInt so maybe it isn't likely enough to matter? |
| 13:41 | Bronsa | mikerod: no you have a misuinderstanding of how = uses the hash. it's only used as a fast path for not-equality |
| 13:41 | mikerod | Bronsa: Oh, duh. I confused what is used by = |
| 13:41 | mikerod | `equiv` is the impl I should have been looking at. |
| 13:42 | mikerod | Which has a `(identical? (class this#) (class ~gs))` :P |
| 13:42 | mikerod | I sometimes get mixed up in the whole hasheq, equiv, hashCode, equals world |
| 13:44 | mikerod | I see that types created via defrecord, when posing as java.util.Map's would be in the #hashCode and #equals space; but when in Clojure dealing with `hash` and `=` they are working in the hasheq and equiv space. But sorry, I got mixed up with the hasheq vs equiv in this case. |
| 13:44 | devn | Hey, sorry for the repeat, but I can't brane good and have a case of the dums. Given I have {:name "foo" :id 1 :children [{:name "bar" :children [{:name "baz"}]}]}, I want: [{:name "foo" :id 1} {:id 2 :name "bar" :parent-id 1} {:id 3 :name "baz" :parent-id 2}] |
| 13:45 | cYmen | Man, I wish there was a nice clojure/clojurescript ide for windows. |
| 13:45 | devn | basically i want to flatten out the children, but have them reference their parent's id |
| 13:45 | Bronsa | cYmen: have you tried cursive? |
| 13:45 | justin_smith | cYmen: have you tried cursive? |
| 13:45 | justin_smith | haha |
| 13:45 | cYmen | I've heard about it but I have not |
| 13:45 | Bronsa | lol |
| 13:45 | technomancy | does CCW not handle cljs? |
| 13:46 | noonian | well... there is always emacs :P |
| 13:46 | cYmen | noonian: Well, I have emacs. |
| 13:46 | cYmen | And I just spent forever setting it up on this machine. |
| 13:47 | arrdem | devn: for is your friend |
| 13:47 | noonian | get your .emacs in version control and your set for life! |
| 13:47 | cYmen | I definitely need to do that... |
| 13:47 | Bronsa | noonian: +1 |
| 13:48 | mikerod | devn: Did you mean to leave off the :id from the second parent? |
| 13:48 | mikerod | devn: Did you mean that every level of the hierarchy is supposed to have an :id on it? |
| 13:49 | mikerod | devn: From the example, it looks like there is an :id 1 for :parent-id 1, but then it is just like the "depth" that is how you come up with :parent-id 2 |
| 13:49 | arrdem | +1 mikerod, the first child should probably have an id |
| 13:53 | mikerod | devn: if there are :id's at every level, something like clojure.walk/postwalk would work if you aren't going to run into any quirks there, (like losing metadata you need on something :P ) |
| 13:54 | arrdem | devn: https://www.refheap.com/91412 |
| 13:58 | dnolen_ | cYmen: I guess because it uses nREPL & WebSockets? A lot of CLJ/CLJS lein templates now ship w/ it which means less config |
| 14:02 | technomancy | greghendershott: re: prefixing in require, it's not about avoiding collisions as much as it is about being able to tell at a glance which identifiers come from the current namespace vs those that are external |
| 14:02 | cfleming | cYmen: I develop Cursive - I don't develop much with CLJS myself, but a bunch of users have reported success with Weasel. It requires less config as dnolen_ says and the connection seems more reliable as well. Additionally you can use it to connect to more types of target (node.js, embedded JavaScriptCore on iOS etc). |
| 14:02 | technomancy | greghendershott: since we don't have the fancy drracket arrow stuff =) |
| 14:02 | technomancy | (carrying over the conversation from another channel) |
| 14:03 | technomancy | greghendershott: also, it's not a requirement to place tests in separate files, just a default |
| 14:03 | cfleming | technomancy: How does the DrRacket arrow stuff work? I saw a screenshot in your blog post but wasn't sure what it was showing me. |
| 14:04 | justin_smith | greghendershott: when your symbols are prefixed, it makes refactoring a big namespace (those are the ones you most likely need to refactor) very easy |
| 14:04 | technomancy | cfleming: that image was a stack trace; here I'm actually talking about how you place the pointer over an identifier and it will show a line to where it's coming from |
| 14:04 | technomancy | either the arglist or a require form |
| 14:04 | greghendershott | technomancy: justin_smith: Thanks, that's helpful to understand the motivation. |
| 14:04 | cfleming | technomancy: Nice, thanks |
| 14:05 | technomancy | cfleming: the arrows for the stack traces are actually a lot more helpful IMO |
| 14:05 | cfleming | technomancy: They indicate where in the source the trace elements come from? |
| 14:05 | technomancy | cfleming: right |
| 14:06 | mikerod | devn: Oh, yeah I meant prewalk there |
| 14:06 | cfleming | technomancy: That is cool. |
| 14:06 | mikerod | devn: https://www.refheap.com/91413 was my prewalk example, I'd probably prefer arrdem style more |
| 14:07 | technomancy | greghendershott: also as a note, recur is considered a very low-level primitive in clojure; as a newbie most of the time you should consider re-framing the problem in terms of sequences |
| 14:10 | _pr0t0type_1 | Hey guys, how does the order of 'into' work? Does it even matter? It seems like it would matter when your're conjoining special forms. ie (into '(if) '(true)) ==> (true if) |
| 14:11 | arrdem | _pr0t0type_1: conj makes no guarantees about order, deferring to conj for behavior |
| 14:11 | arrdem | s/conj/into/g |
| 14:12 | dnolen_ | _pr0t0type_1: depends on the collection, as arrdem says, conj is polymorphic on it's argument |
| 14:12 | arrdem | _pr0t0type_1: some examples http://grimoire.arrdem.com/1.6.0/clojure.core/conj |
| 14:13 | _pr0t0type_1 | I see |
| 14:13 | _pr0t0type_1 | Thanks guys, this makes sense |
| 14:13 | arrdem | any word on how close we are to 1.7 dropping? |
| 14:14 | devn | arrdem: nested :children won't have :id, it'll need to be added |
| 14:15 | arrdem | devn: counting from what... the id of the parent? |
| 14:15 | devn | yes |
| 14:15 | devn | it also should include the root as a row |
| 14:15 | devn | where parent-id would be nil |
| 14:16 | cfleming | arrdem: Seems like it's closer than expected since they want to get transducers out to the world - that's why a bunch of stuff got moved to 1.8 yesterday |
| 14:16 | arrdem | I would say keep the recursive mapcat of pulling children out and do a zipmap (partial apply assoc) |
| 14:16 | mi6x3m | how would you name a binding holding a namespace clojure? |
| 14:16 | mi6x3m | n? |
| 14:17 | arrdem | cfleming: yeah I'm feeling sooner rather than later given yesterday's jira noise as well |
| 14:17 | puredanger | yes |
| 14:17 | justin_smith | mi6x3m: well, it can't literally hold a namespace, only the symbol of the ns, since namepsaces are not first class |
| 14:17 | mi6x3m | justin_smith: well they are in java |
| 14:17 | llasram | justin_smith: ? &*ns* |
| 14:18 | llasram | Man, always do the wrong syntax: ##*ns* |
| 14:18 | llasram | No, needs to be a list. Whatever, you get the idea |
| 14:18 | mi6x3m | ,*ns* |
| 14:18 | clojurebot | #<Namespace sandbox> |
| 14:18 | justin_smith | right - I appear to be confused, sorry |
| 14:18 | mi6x3m | ,(let [n *ns*] n) |
| 14:18 | clojurebot | #<Namespace sandbox> |
| 14:19 | llasram | mi6x3m: A local identifier referring to a namespsace object? I'd call it just `ns` |
| 14:19 | devn | arrdem: example? sorry, not following you on the zipmap partial apply assoc |
| 14:19 | mi6x3m | llasram: I prefer n, but seems to be a matter of taste :) |
| 14:20 | foodoo | Hi, any recommendations for a Clojure library (maintained) that I can use to send and receive HTTP REST requests? |
| 14:21 | justin_smith | clj-http is decent |
| 14:21 | arrdem | devn: nevermind. after sketching that out it wouldn't work :P |
| 14:22 | foodoo | justin_smith: thanks. There is just too much choice on clojars |
| 14:22 | mi6x3m | foodoo: http-kit :) |
| 14:22 | justin_smith | right - and for basic stuff you can even use slurp |
| 14:23 | justin_smith | ,(slurp "http://www.google.com") |
| 14:23 | clojurebot | #<SecurityException java.lang.SecurityException: denied> |
| 14:23 | justin_smith | :P |
| 14:23 | mi6x3m | foodoo: http-kit offers a client and a server, very easy to use |
| 14:23 | noonian | foodoo: if you are using http-kit for your server then i'd use their client also just to avoid another dependency |
| 14:24 | foodoo | I want to write a client. The server already exists (Cytoscape cyREST) |
| 14:24 | mr_rm | I'm using Liberator (http://clojure-liberator.github.io/liberator) and i'm confused by something. My :handle-created function is getting called even when I'm doing a GET (also on POST). Is that normal behavior? The HTTP response for my GET is 200 but it's still calling the :handle-created handler. |
| 14:25 | ustunozgur | is there a version of interleave that continues taking after one coll is exhausted? (interleave [1 2] [3 4 5]) should return [1 3 2 4 5] for example instead of [1 3 2 4] |
| 14:25 | ustunozgur | equivalent in underscore is for example _.compact(_.flatten(_.zip(array1, array2))) |
| 14:27 | bbloom | ,(mapcat vector [1 2] [3 4 5]) ; maybe something like this |
| 14:27 | clojurebot | (1 3 2 4) |
| 14:27 | bbloom | no still note quite |
| 14:28 | opqdonut | bbloom: no, that stops after two elements |
| 14:28 | opqdonut | I can't think of an easy way to do it |
| 14:29 | stuartsierra | rewrite interleave |
| 14:30 | opqdonut | ,(let [a [1 2] b [3 4 5 6]]] (concat (interleave a) (drop (count a) b) (drop (count b) a))) |
| 14:30 | clojurebot | #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]> |
| 14:30 | opqdonut | ,(let [a [1 2] b [3 4 5 6]] (concat (interleave a) (drop (count a) b) (drop (count b) a))) |
| 14:30 | clojurebot | (1 2 5 6) |
| 14:30 | bbloom | ,(mapcat conj (concat (map vector [1 2]) (repeat [])) [3 4 5]) |
| 14:30 | clojurebot | (1 3 2 4 5) |
| 14:31 | opqdonut | heh |
| 14:31 | opqdonut | ,(let [a [1 2] b [3 4 5 6]] (concat (interleave a b) (drop (count a) b) (drop (count b) a))) |
| 14:31 | clojurebot | (1 3 2 4 5 ...) |
| 14:31 | opqdonut | there |
| 14:31 | opqdonut | bbloom: then you need to know which one is shorter |
| 14:31 | stuartsierra | `count` destroys laziness |
| 14:31 | mi6x3m | opqdonut: almost readable :) |
| 14:31 | opqdonut | bbloom: since you can't append repeat [] to both |
| 14:31 | opqdonut | stuartsierra: yeah, a lazy solution would need tobe written from scratch I think |
| 14:32 | bbloom | yeah, coding it recursively with lazy-seq is surely the way to go |
| 14:33 | mikerod | cfleming: I was a bit sad for some of the things pulled from 1.7 |
| 14:34 | mikerod | However, transducers sooner than later is cool too |
| 14:34 | arrdem | devn: https://www.refheap.com/91415 cheating with mutable state |
| 14:34 | ustunozgur | this one (called weave) is by fogus in js: https://github.com/documentcloud/underscore-contrib/blob/master/underscore.array.builders.js#L95 |
| 14:35 | puredanger | Hey all, Chas asked us to do the State of Clojure/ClojureScript survey this year and it is now available - would be great to see responses from any and all! http://blog.cognitect.com/blog/2014/10/3/2014-state-of-clojure-clojurescript-survey |
| 14:37 | justin_smith | opqdonut: https://www.refheap.com/91416 |
| 14:37 | justin_smith | my attempt |
| 14:37 | devn | arrdem: haha booo! |
| 14:38 | devn | arrdem: we did it with a reduce where we call ourselves and change the initial value |
| 14:38 | devn | because we didn't want an atom :) |
| 14:38 | arrdem | devn: lols. you could do it "purely", but then you can't use mapcat because you need to know how many children were returned |
| 14:38 | arrdem | yeah a reduction and a work queue would be more natural for that approach |
| 14:55 | michaelmeixner | noob-question |
| 14:55 | michaelmeixner | I can do: |
| 14:56 | michaelmeixner | (map (fn [x] [x 7]) [:a :b]) |
| 14:56 | michaelmeixner | but not: |
| 14:56 | michaelmeixner | (map #([% 7]) [:a :b]) |
| 14:56 | michaelmeixner | Why not? |
| 14:56 | bbloom | ,'#([% 7]) |
| 14:56 | clojurebot | (fn* [p1__25#] ([p1__25# 7])) |
| 14:56 | gfredericks | #() is not good for returning literals |
| 14:56 | bbloom | michaelmeixner: does that make it clear? |
| 14:57 | hiredman | puredanger: I use clojure for everything, so I am not sure how to answer the "what has stopped you from using clojure for more" question |
| 14:57 | puredanger | then don't check anything :) |
| 14:57 | gfredericks | hiredman: "biological needs" |
| 14:57 | hiredman | haha |
| 14:57 | puredanger | maybe I should add "I am using maximum Clojure" :) |
| 14:57 | puredanger | I actually had the same response :) |
| 14:58 | michaelmeixner | bbloom not clear immediately, but something to think about - thanks! |
| 14:58 | bbloom | michaelmeixner: basically #(...) is short for (fn [...] (...)) |
| 14:58 | bbloom | michaelmeixner: note the extra parens |
| 14:58 | hiredman | the only thing stopping me from using it more is other people keep writing code in other languages :/ |
| 14:58 | noonian | michaelmeixner: the shorthand fn notation creates a function that always calls another function, so writing #([% 7]) when applied to the first element :a will eval the expression '([:a 1]) which throws the error |
| 14:58 | bbloom | michaelmeixner: when you write #([%]) that's the same as (fn [x] ([x])) which is trying to call the vector like a function, but with no arguments |
| 14:59 | michaelmeixner | aha! |
| 14:59 | michaelmeixner | guess i got it |
| 14:59 | TimMc | in fact... |
| 14:59 | TimMc | ,(macroexpand-1 '#()) |
| 14:59 | clojurebot | (fn* [] ()) |
| 14:59 | TimMc | ,(#()) |
| 14:59 | clojurebot | () |
| 15:00 | noonian | you could do #(vector % 7) |
| 15:00 | TimMc | #(do [% 7]) |
| 15:00 | noonian | or #(vec [% 7]) |
| 15:00 | noonian | TimMc: nice! and you've found the usecase for do that does not involve side affects that I couldn't come up with! |
| 15:00 | noonian | (inc TimMc) |
| 15:00 | lazybot | ⇒ 73 |
| 15:01 | bbloom | puredanger: the usefulness question seems like you're going to get ambiguous answers between usefulness and desired usefulness ... particularly the question about startup performance |
| 15:01 | bbloom | it would be very useful to me if startup performance was better |
| 15:01 | bbloom | but the poor startup performance now is not useful at all :-P |
| 15:01 | technomancy | bbloom: yeah, my answers were mixed on those questions |
| 15:02 | puredanger | that's essentially the same question we've had in the past years. it has its issues but I kept (as much as I could across changing form hosts) the intent |
| 15:02 | puredanger | at this point, don't want to change anything, will just have to be feedback into next year |
| 15:03 | justin_smith | for the "what has been more frustrating" would the answer "runtime performance" also include "runtime resource usage" ? |
| 15:03 | bbloom | puredanger: i figured it was too late to change, but worth knowing if the data is funky |
| 15:03 | puredanger | justin_smith: sure |
| 15:04 | ustunozgur | having "I've stopped using it" just after 6+ years is slightly worrying : ) seems like a sequence of events when read top to bottom. |
| 15:08 | devn | Is there a simple way to avoid AOT in a WAR created via ring? |
| 15:09 | justin_smith | devn: I think at the very least you need a compiled class that the container can invoke |
| 15:09 | justin_smith | but you could use a shim and avoid all other AOT |
| 15:10 | bbloom | wufoo just ate my cljs survey form |
| 15:10 | bbloom | it said whoops w/ a 500 |
| 15:10 | bbloom | not sure if it went through or not |
| 15:10 | bbloom | form data is lost though :-( |
| 15:10 | devn | justin_smith: like this? https://gist.github.com/devn/3acd0c210113721eb024 |
| 15:11 | AeroNotix | puredanger: the questions on that survey are a bit weird |
| 15:11 | AeroNotix | "How useful have these aspects been to you" => Performance |
| 15:11 | devn | justin_smith: this seems messy to me, would be nice to have a simpler way to do this |
| 15:11 | AeroNotix | and then the answers are "Not useful" to "Very useful" |
| 15:11 | justin_smith | devn: agreed |
| 15:11 | AeroNotix | which aspect of performance? |
| 15:12 | AeroNotix | what's the scale here? |
| 15:12 | nullptr | yeah, how could transducers be "useful" to anyone at this point? |
| 15:12 | devn | justin_smith: who to talk to? :) |
| 15:12 | AeroNotix | are we answering whether the performance is bad or good? |
| 15:12 | justin_smith | devn: tbh I have always just done aot to deploy wars, and it always worked |
| 15:12 | puredanger | interpret it as you will and we will try to make it better next year |
| 15:12 | AeroNotix | puredanger: ok |
| 15:12 | AeroNotix | "Extensible reader" lolwat? |
| 15:12 | devn | justin_smith: the problem is when 3rd party libs that aren't AOT safe start getting into the mix |
| 15:12 | justin_smith | devn: but hypothetically only the part the container accesses needs aot, and it can invoke the rest, beyond that your guess is likely as good as mine |
| 15:12 | justin_smith | devn: yeah, that would be a problem |
| 15:13 | puredanger | all of those rows are from the last 4 years of survey. the question types were a little different in wufoo and I made up the column choices. |
| 15:13 | AeroNotix | puredanger: what extensible reader? |
| 15:13 | puredanger | tagged literals |
| 15:13 | AeroNotix | ^String "fooo" ? |
| 15:13 | AeroNotix | puredanger: ? |
| 15:13 | puredanger | http://clojure.org/reader#The Reader--Tagged Literals |
| 15:14 | AeroNotix | holy shit |
| 15:14 | arrdem | http://clojure.org/reader#The%20Reader--Tagged%20Literals |
| 15:14 | justin_smith | devn: on the bright side, the shim isn't a seed of ugliness that will inevitably spread outward - it is an adaptor layer allowing the ugliness to be absent elsewhere |
| 15:14 | justin_smith | and it's not horrifying levels of ugly |
| 15:15 | devn | justin_smith: it seems like a patch to lein and/or ring would be a nice fix |
| 15:15 | justin_smith | yes, patching lein and or ring so you don't need the shim would be great - it's also a big task |
| 15:17 | verma | I am working on this state driven 3D engine mostly for rendering point clouds (for http://plas.io), all things are added and removed by updating a state, e.g. if you want to change the location of the camera you basically do an (assoc state [:view :camera] [0 0 0]) |
| 15:17 | puredanger | arrdem: thx, I hate those goofy anchors |
| 15:17 | verma | and the engine takes care of making sure that the currect javascript objects are manipulated |
| 15:17 | AeroNotix | puredanger: ok filled it in, where's my cheque :) |
| 15:17 | arrdem | puredanger: <3 |
| 15:17 | verma | now I need to pass in huge amounts of point data into it, but don't want it held up in the state |
| 15:17 | puredanger | AeroNotix: it's in the mail to the address you provided :) |
| 15:18 | AeroNotix | puredanger: GOOD! |
| 15:18 | arrdem | I wonder where mail addressed to Null goes... |
| 15:18 | verma | thinking of storing stuff in local storage tagged with an ID |
| 15:18 | verma | and then passing that ID to the renderer |
| 15:18 | verma | the renderer just reads from local storage |
| 15:18 | verma | and then clears it out or something |
| 15:18 | verma | any ideas? |
| 15:19 | justin_smith | verma: have you looked at the "entity component system" design at all? |
| 15:19 | technomancy | devn: patches to lein? |
| 15:20 | puredanger | arrdem: re 1.7 wonderings in the back chat, goal is to get through this stuff http://dev.clojure.org/jira/secure/IssueNavigator.jspa?mode=hide&requestId=10519 and release a beta |
| 15:20 | verma | justin_smith, I think it is sort of similar |
| 15:21 | arrdem | puredanger: feature expressions... glhf |
| 15:21 | puredanger | arrdem: everything else was pushed to 1.8. rather than thinking about pushing off, really thinking about it as dropping a release where we are now as people need a transducers ga |
| 15:21 | justin_smith | devn: technomancy: giving it more thought - is this really just a lein / ring issue? the container needs a compiled class, that is not negotiable - what could lein or ring do - make it so aot was not transitive? |
| 15:22 | devn | technomancy: to avoid AOT, having a shim like `(ns my.aot.avoider (:gen-class)) (def main-ns "my.aot.app") (defn -main [] (require (symbol main-ns)) ((resolve (symbol main-ns "-main"))))` |
| 15:22 | puredanger | I smell CLJ-322 :) |
| 15:22 | technomancy | devn: I can't think of a decent way to make that happen from lein |
| 15:23 | puredanger | and it distresses me that I did not need to look up that ticket number |
| 15:23 | justin_smith | puredanger: yeah, that's the real fix, thanks for pointing that out |
| 15:23 | justin_smith | (inc puredanger) |
| 15:23 | lazybot | ⇒ 17 |
| 15:24 | arrdem | ugh. PSA: version your URLs lest your routing scheme become context sensitive |
| 15:24 | technomancy | justin_smith: if ring shipped with a class file that could defer to a clojure namespace that would do it |
| 15:24 | technomancy | justin_smith: I mean, probably? I know nothing about war files, but assuming they're like jar entry points |
| 15:25 | devn | hmmmm |
| 15:25 | justin_smith | technomancy: a war is a jar with a special format, and like a jar it has an entry point (that the java container process uses) |
| 15:25 | verma | justin_smith, I really don't want to design a 3D engine per se, mostly an abstraction over existing engines, so that I can "visualize" a state, I may later want to pull this state out, send it over the network to see exactly the same view |
| 15:26 | verma | justin_smith, ECS seems more like here's how to do it, which I am already sort of doing, mostly property watchers and custom "render state" updaters |
| 15:26 | justin_smith | verma: I don't think the entity component system thing is at all 3d specific, it's more about a way of organizing your data (and it's a data oriented way of constructing a game) |
| 15:26 | devn | technomancy: what about the generation of that entry point as an option? |
| 15:26 | justin_smith | verma: and I mentioned it exactly because what you are doing already kind of reminded me of it |
| 15:27 | technomancy | devn: why generate one? just include it in ring |
| 15:29 | justin_smith | or write and compile a very small java class that simply uses the java API to spin up clojure and create the handler |
| 15:29 | weavejester | Lein-Ring could certainly have a servlet shim in it. I don’t necessarily know about Ring itself. I tend to be more conservative with that project. |
| 15:29 | justin_smith | but that's not much different from the pure clojure shim you already had in that paste |
| 15:29 | weavejester | I just don’t really use lein-ring these days. I’m trying to give more people commit access |
| 15:29 | weavejester | I should probably add a note in the README to that effect |
| 15:30 | verma | justin_smith, nice :) I use THREE.js for rendering right now, which I think has ECS at its core, I am basically trying to take a state and "view it" I guess, only problem is the state has the potentional of blowing up in size :P |
| 15:33 | verma | basically the incoming state forms "keys" in my render state, if the incoming state has a huge object it becomes a key :P |
| 15:36 | devn | weavejester: would you be opposed to something like we were discussing? |
| 15:36 | weavejester | devn: For Lein-Ring, not at all. I might even have an existing issue. I know I’ve mentioned it enough times. |
| 15:36 | devn | weavejester: like: :ring {:aot :none, :handler my.app/handler, :init my.app/init} ? |
| 15:36 | weavejester | devn: Why use aot at all? |
| 15:36 | devn | yeah there's an issue here: https://github.com/weavejester/lein-ring/issues/52 |
| 15:37 | weavejester | If people want AOT, they can explicitly set it using normal Lein options, right? |
| 15:37 | weavejester | I don’t see any reason not to use a shim instead of AOT to generate the servlet class. |
| 15:38 | justin_smith | yeah, it could be a very small java class, with a config that tells it which clojure ns to load up, and the function in that ns to call |
| 15:38 | myguidingstar | puredanger, I've just look at the survey |
| 15:39 | myguidingstar | in the Clojure one: How useful have each of these aspects of Clojure been to you and your projects? |
| 15:39 | myguidingstar | I think logic programming and pattern matching should be mentioned, too |
| 15:39 | devn | weavejester: this brings it back to lein then, no? /cc technomancy |
| 15:39 | puredanger | myguidingstar: those aren't part of the Clojure language though? |
| 15:40 | weavejester | devn: lein-ring |
| 15:40 | myguidingstar | well, I see 'reducer' and 'tranducer' there |
| 15:41 | puredanger | myguidingstar: those are part of the core library |
| 15:41 | myguidingstar | okay |
| 15:41 | myguidingstar | and in the Clojurescript one |
| 15:41 | myguidingstar | in the question Which JavaScript environments do you target? |
| 15:42 | myguidingstar | can you add ArangoDB's FOXX? |
| 15:42 | myguidingstar | it's similar to CouchDB's but more complete |
| 15:43 | myguidingstar | puredanger, https://www.arangodb.org/foxx |
| 15:44 | puredanger | myguidingstar: added |
| 15:44 | myguidingstar | many thanks |
| 15:53 | myguidingstar | puredanger, in the Clojurescript survey, I find this question unclear: In which contexts do you use each of ClojureScript's optimization settings? :none, :simple ... |
| 15:54 | puredanger | yeah... |
| 15:54 | devn | weavejester: technomancy: let me send you a doc and you guys tell me what patches to submit to make life easier: https://www.dropbox.com/s/medk1iocrqu9nk2/war-jar-aot-oh-myyyyy.pdf?dl=0 |
| 15:55 | puredanger | myguidingstar: ah, that question did not get correctly transferred from last year's survey, sorry about that |
| 15:56 | puredanger | myguidingstar: I've tweaked to at least make some sense, but I can't really change it without altering the survey too much at this point. |
| 15:57 | myguidingstar | then? |
| 15:58 | nullptr | puredanger: most people qualified to answer that question probably interpreted it correctly |
| 15:58 | justin_smith | devn: hey, that's a good summary |
| 15:59 | justin_smith | devn: minor nitpick, the text references highlighting, and my pdf reader shows no highlighting (inline pdf display in google chrome) |
| 15:59 | devn | justin_smith: ah yeah, the highlighting isn't all that helpful fwiw |
| 16:00 | devn | justin_smith: if you have a suggestion here im interested as well. basically what im hearing is: lein-ring should never AOT, since you could choose to AOT with lein anyway if you really wanted it |
| 16:00 | devn | but im not sure what the story is on the JAR side |
| 16:00 | csd_ | Is there a function that will take [vec1], [vec2] and return [{v11 v21} {v12 v22}...]? |
| 16:02 | justin_smith | ,(map hash-map [:a :b :c :d :e] [0 1 2 3 4]) |
| 16:02 | clojurebot | ({:a 0} {:b 1} {:c 2} {:d 3} {:e 4}) |
| 16:02 | justin_smith | why though? |
| 16:03 | csd_ | just trying to simplify a korma statement |
| 16:03 | justin_smith | OK |
| 16:03 | myguidingstar | puredanger, the order should be: :none, :whitespace, :simple, :advanced |
| 16:03 | csd_ | list of ids and a list of values, this way i can combine them into one statement |
| 16:03 | myguidingstar | sorry for being so annoying |
| 16:04 | puredanger | myguidingstar: I'm not going to change that, not sure how changing the ordering affects the data recording |
| 16:04 | devn | justin_smith: correct me if you read differently in the above conversation, but i am hearing: 1) never AOT in ring, 2) lein can't do what im asking, but I'm not sure #2 is true. I want to say: `:aot :none, :main mycorp.miwidget.app`, and have the gen-class entry point shim created for me |
| 16:04 | myguidingstar | I see |
| 16:04 | csd_ | devn: what are you trying to do? |
| 16:05 | devn | csd_: read above. there's a document i referenced. |
| 16:05 | devn | csd_: in short, avoid all AOT in JARs and WARs without needing to create a shim every time. |
| 16:06 | justin_smith | devn: well clojure.core could do that, or lein could do that, or ring could, or lein-ring could - but it's a weird ugly thing to implement and it seems everyone would naturually be happier if the feature was in someone else's project (except clojure.core, which is simply conservative, and that would be a huge change I think) |
| 16:08 | technomancy | devn: are you trying to avoid all AOT, or just AOT during development? |
| 16:09 | weavejester | The servlet shim should go in Lein-Ring, IMO. |
| 16:09 | weavejester | Or else be a separate library. |
| 16:10 | weavejester | It probably doesn’t belong in Ring. |
| 16:10 | weavejester | And definitely doesn’t belong in Lein or Clojure, if that’s been suggested! |
| 16:10 | hiredman | https://github.com/hiredman/lein-ring |
| 16:11 | justin_smith | weavejester: I meant not specifically the shim (that's a means to an end) but the non-transitive aot solution (another means to the same end) |
| 16:12 | technomancy | there exist simple ways of avoiding dev-time AOT with uberjars. I don't know about wars. |
| 16:12 | weavejester | justin_smith: Hm… I’m not sure how that would work, but that’s an interesting idea. |
| 16:12 | justin_smith | technomancy: he specified he needed to avoid all aot, even for deployment |
| 16:12 | weavejester | technomancy: Lein-Ring currently generates a Clojure AOTed namespace to act as the servlet. It would be better replaced with a Java shim, IMO. |
| 16:13 | hiredman | https://github.com/hiredman/lein-ring/blob/master/java/com/thelastcitadel/Servlet.java |
| 16:13 | weavejester | hiredman: Are you working on a PR? |
| 16:14 | hiredman | no, I deleted a bunch of stuff |
| 16:14 | technomancy | hm; ok. nearly all the AOT issues I've seen so far are due to reloading, so AOT strictly for uberjars sidesteps that. |
| 16:14 | technomancy | but there could be other issues I'm unaware of |
| 16:14 | justin_smith | technomancy: something about libs that break when aot-compiled |
| 16:14 | technomancy | justin_smith: like old versions of core.match? |
| 16:14 | devn | third party libs are not always guaranteed to be AOT friendly |
| 16:15 | hiredman | weavejester: I don't want any of the dev middleware or the browser launching whatever |
| 16:15 | technomancy | seems like this is just routing around the root issue |
| 16:15 | justin_smith | hiredman: that java shim looks like a good way to approach it |
| 16:15 | devn | technomancy: but what is the alternative? |
| 16:15 | hiredman | and I am not actively working on it, I forked, sliced it up, and have started using it for my stuff |
| 16:15 | weavejester | hiredman: Okay, but none of that’s added to the war file anyway. |
| 16:16 | technomancy | devn: if a library has bugs they should be fixed? |
| 16:16 | dbasch | I had trouble AOT’ing apps to run on hadoop |
| 16:16 | technomancy | I mean obviously the real world isn't that simple, but this should be considered a workaround rather than a long-term solution |
| 16:16 | devn | technomancy: totally agreed, but for now, i think the workaround is preferred |
| 16:16 | technomancy | sure |
| 16:17 | justin_smith | technomancy: right, which is why that non-transative AOT thing that puredanger pointed out looks nice (though I don't know if there is any clear way to implement it) |
| 16:17 | AeroNotix | any recommendations for graphing libraries? |
| 16:17 | devn | AeroNotix: rhizome |
| 16:18 | dbasch | parkour in particular does some compile-time reflection using the hadoop library you’re compiling against |
| 16:18 | AeroNotix | devn: looks nice, but not for my use-case |
| 16:19 | devn | wait, where did puredanger mention non-transitive AOT? |
| 16:19 | puredanger | http://dev.clojure.org/jira/browse/CLJ-322 |
| 16:20 | technomancy | justin_smith: given its low issue ID, odds are low? |
| 16:20 | puredanger | I think if it had a consensus approach, could definitely move forward. not sure if that exists though. |
| 16:24 | devn | puredanger: i haven't read the whole thread in detail, but has rich peeked at this ticket recently? |
| 16:24 | technomancy | heh, yeah... this is assembla-old |
| 16:25 | devn | i only ask because there's one person in particular who can achieve consensus by using his fist :) |
| 16:25 | amalloy | chuck norris is a clojure developer? |
| 16:25 | devn | that would be roundhouse kicks ;D |
| 16:25 | bbloom | "assembla-old" is an amusing phrase |
| 16:26 | devn | technomancy: so, did i hear right that you wouldn't be totally opposed to having a workaround in lein? |
| 16:26 | technomancy | devn: there sort of is a workaround in lein |
| 16:26 | technomancy | it breaks a bunch of things though |
| 16:27 | technomancy | :clean-non-project-classes |
| 16:27 | devn | what is the workaround, and what does it break? :) |
| 16:27 | technomancy | iirc the problem is protocol functions don't gracefully fall back when they're AOT'd but refer to namespaces that aren't |
| 16:27 | technomancy | so just don't use protocols; problem solved =) |
| 16:27 | devn | haha |
| 16:28 | technomancy | I don't want to put anything war-specific in lein though |
| 16:28 | puredanger | devn: I have not talked to Rich about it since 1.6 timeframe, don't recall a strong opinion. there is some more stuff on it here: http://dev.clojure.org/display/design/Transitive+AOT+Compilation |
| 16:28 | justin_smith | devn: technomancy: I can see how that could work - your "shim" ns doesn't need to not require other namespaces now, it just needs to not call any protocol functions - much nice |
| 16:29 | justin_smith | r |
| 16:29 | devn | puredanger: much obliged for the info |
| 16:29 | weavejester | I don’t think it’s really a good idea to put a workaround in Lein if it can be fixed in Lein-Ring. |
| 16:30 | devn | we're talking about the WAR case only right now though. the doc i posted: https://www.dropbox.com/s/medk1iocrqu9nk2/war-jar-aot-oh-myyyyy.pdf?dl=0 discusses JAR stuff at the bottom |
| 16:32 | devn | i mean, i agree with you on the ring side, yes, let's fix it in lein-ring, but even then, if i want to reference a -main and avoid AOT while still keeping the jar executable, i need a shim |
| 16:32 | technomancy | devn: actually for uberjars that's not true either |
| 16:32 | devn | which part? |
| 16:32 | technomancy | devn: set :main clojure.core, then launch it with -m my.ns |
| 16:32 | devn | yes, i forgot to mention that in this doc |
| 16:33 | technomancy | AOT is only required for uberjars if you need it to launch using bare `java -jar ...` |
| 16:33 | technomancy | or rather, you need a shim, but you already have one =) |
| 16:33 | devn | technomancy: yes, we do need/want to java -jar them |
| 16:34 | technomancy | devn: gotcha. there is lein-otf for that, but it may have bitrotten due to the -m approach being simpler |
| 16:37 | devn | technomancy: thanks |
| 16:38 | christop1e | hrm, got disconnected. Contracters shortcircuited the place -_- |
| 16:41 | cYmen | About this https://github.com/swannodette/om/wiki/Basic-Tutorial under "Your first Om component" we suddenly use build all where we just used map earlier. I assume that means we are now creating some sort of subcomponent but why? |
| 16:46 | devn | technomancy: so even with otf, i couldn't convince you that kicking off a chain of AOT is undesirable and that having a workaround in leiningen would be nice? :D |
| 16:47 | technomancy | devn: you mean two workarounds? |
| 16:47 | devn | i think im confusing myself now. |
| 16:48 | devn | technomancy: yes, i suppose then im asking for two workarounds, where it's a bit more declarative in the project.clj what will be shimmed in order to avoid AOT |
| 16:48 | technomancy | we've got a workaround in clojure (-m), a workaround in lein (:clean-non-project-classes), a workaround in a plugin, and a workaround in a patch on jira =) |
| 16:48 | devn | one where* |
| 16:50 | devn | 1) the plugin is currently broken and questions its own existence due to the ability to use -m, 2) :clean-non-project-classes according to you "breaks a bunch of things", 3) -m isn't an option for me, and 4) the patch on jira is like 4 years old |
| 16:50 | devn | technomancy: ^ |
| 16:51 | technomancy | devn: if the shim is just a class file, why does it belong in lein? why not just add it to :dependencies? |
| 16:51 | technomancy | I think the lein-otf approach is right for your use case; it'd be quicker to fix the plugin than add a feature to lein |
| 16:52 | technomancy | oh... actually you don't need that. you can set clojure.main as your :main and include a user.clj in the uberjar that requires and loads your own entry point |
| 16:54 | technomancy | (just put user.clj in a :source-paths element that is only included in the uberjar profile) |
| 16:55 | devn | technomancy: why user.clj? |
| 16:56 | technomancy | devn: otherwise clojure.main will just drop you into a repl when used as Main-Class |
| 16:58 | technomancy | it's just that this seems like a project-space concern |
| 16:59 | jeffterrell | I just read this: http://pastebin.com/bSW5dfRQ — about how HN stores session state in closures. |
| 16:59 | jeffterrell | Just curious, is it possible to store closures in Clojure? |
| 17:00 | hiredman | no |
| 17:01 | technomancy | sort of, but not really |
| 17:01 | jeffterrell | Why not? Is it a fundamental limitation of e.g. the JVM, or is it just that nobody needed to do it yet? |
| 17:01 | amalloy | is that still true, jeffterrell? i thought they had switched to a more common method of storing sessions |
| 17:01 | jeffterrell | They have, as of recently. The link above discusses the transition. |
| 17:01 | technomancy | I thought they closed over continuations specifically |
| 17:02 | hiredman | storing closures is gross for a number of reasons, a closure is tied to the executable state of a machine |
| 17:02 | jeffterrell | technomancy: That _seems_ to be what's going on, yes. I'm not clear on the details, and I don't deeply understand continuations. |
| 17:02 | jeffterrell | hiredman: True, but it seems like a worthwhile tradeoff to avoid database/serialization/etc issues when starting out a project. |
| 17:02 | turbofail | no, they're just closures, written in continuation passing style |
| 17:02 | ordnungswidrig | hmm, can closures be persistet (in arc) over process restarts? |
| 17:02 | technomancy | huh |
| 17:02 | hiredman | jeffterrell: no no, it just makes those issuses worse |
| 17:02 | ordnungswidrig | I mean, what if they reboot the machine? |
| 17:03 | jeffterrell | ordnungswidrig: Maybe with their new architecture, but with the old one, they were just stored in RAM. |
| 17:03 | ordnungswidrig | frightening. |
| 17:03 | hiredman | the problem is vms like the jvm generally don't provide a way to serialize and pass around the state of the machine |
| 17:03 | jeffterrell | ordnungswidrig: That's why you would occasionally (mostly before the new architecture; see link) see "link expired" messages. |
| 17:03 | technomancy | ordnungswidrig: or like ... used a load balancer? |
| 17:03 | technomancy | yeah, it's a mess |
| 17:04 | technomancy | how not to scale an http service |
| 17:04 | ordnungswidrig | you don't need a link balancer when you can hold your state in ram :-) |
| 17:04 | turbofail | if you could serialize the closures, you could store them in redis or something |
| 17:04 | dbasch | ordnungswidrig: if you reboot the machine who cares. Either you have to read state from disk or reconstitute it lazily, who knows what will be faster |
| 17:04 | technomancy | oh that's right; netsplits are a myth =) |
| 17:05 | hiredman | you have to serialize basically the whole object graph from the closure |
| 17:05 | hiredman | like, why? just use a session |
| 17:05 | hiredman | you won't feel as cool, but you won't want to rip it out and rewrite it in a month |
| 17:06 | turbofail | well it'd also be nice if you could write something that will automatically put relevant closure variables into a session |
| 17:06 | turbofail | i believe the racket web framework offers something that can do that |
| 17:07 | turbofail | of course a better solution is to just not have so much damn state in the first place |
| 17:08 | hiredman | or you spin up a machine / process / vm / etc per user and just always route them to the same one |
| 17:08 | dbasch | plus it’s not like there are that many cases of the “next 30 stories.” |
| 17:08 | ordnungswidrig | hiredman: no no, nowadays you spin up a docker container |
| 17:09 | hiredman | (http://research.microsoft.com/pubs/210931/orleans-msr-tr-2014-41.pdf) |
| 17:09 | jeffterrell | It's true, there are some definite limitations with this approach, but I don't think it's strictly worse, I think it's just a tradeoff. I could see it being lots better in the beginning, when you're serving like 10 users per day. |
| 17:09 | jeffterrell | If I knew how to use this approach, I could see writing something like HN in an afternoon, which would be a great way to do a proof-of-concept or win a Clojure Cup. :-) |
| 17:10 | ordnungswidrig | I'm popping out. Please leave a not when you came to some sane conclusion :-) |
| 17:10 | technomancy | jeffterrell: does it really save time vs cookie store though? |
| 17:10 | aztak | howdy folks.. any suggestions for how to make this code more Clojuresque? https://gist.github.com/metamorph/ceda1cc0a97cde08cf04 -- It feels a bit too verbose :p |
| 17:11 | jeffterrell | technomancy: Interesting. Maybe not? I suppose you could define a record to contain the continuation state, and store such records in an atom-map keyed by user. Sounds slightly more complicated than just evaluating a stored fn with closed-over state, but maybe not much. |
| 17:11 | turbofail | technomancy: well using a cookie store is basically the same thing except you have to manually record the state into a cookie |
| 17:12 | turbofail | and extract it later |
| 17:12 | ghadishayban | aztak: seems fine to me |
| 17:12 | clojurebot | Cool story bro. |
| 17:12 | technomancy | turbofail: that middleware ships with ring iirc |
| 17:12 | justin_smith | aztak: #(= unwanted-id (:id %)) could be (comp #{unwanted-id} :id) (but I only suggest that switch if you end up with at least two ids to check) |
| 17:12 | technomancy | just return :session in the response map and your'e done |
| 17:12 | jeffterrell | clojurebot: You're like a child, wandering into a theater… |
| 17:12 | clojurebot | excusez-moi |
| 17:13 | turbofail | technomancy: well you still need to put your environment into that session |
| 17:13 | ghadishayban | aztak: some devs will write (comp #(= unwanted-id %) :id) or (comp (partial = unwanted-id) :id) but that can turn into HOD when taken to the extreme |
| 17:13 | ghadishayban | HOD == Higher-order Diarrhea |
| 17:13 | aztak | justin_smith: ah, that's a nice approach. But I agree - It's perhaps less readable. |
| 17:13 | technomancy | turbofail: IME that falls naturally out of the functional approach |
| 17:14 | technomancy | but I have limited experience with web apps |
| 17:14 | aztak | ghadishayban & justin_smith - thanks for having a look :) And thanks for the suggestions. |
| 17:15 | turbofail | i dunno. i implemented a human-powered merge sort at one point, and i think it would have been much more annoying without the serialized-CPS approach |
| 17:15 | turbofail | well not serialized in this case |
| 17:16 | turbofail | there's certainly cases where it would give some value-add over stuffing things into sessions |
| 17:16 | dbasch | aztak: I’d write (for [d data :when (not= unwanted-id (:id d)] (dissoc d :auth_token)) |
| 17:19 | aztak | dbasch: argh - list comprehensions, I haven't reached that chapter yet *grin*. Interesting approach though. In a way it's more readable I guess. |
| 17:19 | ghadishayban | i actually prefer not using the comprehensions |
| 17:19 | ghadishayban | it buries the actual kernel of logic somewhere in the syntax |
| 17:20 | ghadishayban | and you have to name extra things, not fun |
| 17:20 | dbasch | it depends on how you express it, because abuse of arrows and comp could make it even less readable |
| 17:20 | ghadishayban | totally legit approach though |
| 17:20 | ghadishayban | yup HOD |
| 17:21 | ghadishayban | (I really want that term to catch on) |
| 17:22 | ghadishayban | impl-wise low-level, the 'for' macro does emit a ton of code |
| 17:23 | ghadishayban | ,(for [a (range) b a c b d c e d f e] (inc a)) |
| 17:23 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long> |
| 17:27 | ghadishayban | argh CLJ-1322 has the bug |
| 17:28 | vIkSiT | hello all |
| 17:28 | vIkSiT | how do I get a key from a cljs.core/PersistentArrayMap ? |
| 17:28 | vIkSiT | or rather, the value for a given key |
| 17:29 | vIkSiT | I got a native js object on which I ran a js->clj |
| 17:29 | vIkSiT | But using keys, get, aget - none of that works |
| 17:29 | dnolen_ | vIkSiT: they are just maps, get should work |
| 17:29 | dnolen_ | vIkSiT: if it doesn't work need to see a minimal example |
| 17:30 | joelt | seems like Clojure/script is picking up a little steam job-wise |
| 17:33 | vIkSiT | dnolen_, just a sec, pasting a gist here |
| 17:38 | literary | Is it okay to use :goto as a final clause in (cond) instead of :else? |
| 17:39 | technomancy | define "okay"? |
| 17:39 | justin_smith | literary: anything truthy works, :goto is misleading though |
| 17:39 | literary | What about :fail ? |
| 17:39 | pjstadig | :these-arent-the-droids-youre-looking-for |
| 17:39 | justin_smith | ,(cond nil :nope false :umm "Whatever" :OK) |
| 17:39 | clojurebot | :OK |
| 17:39 | noonian | literary: short answer is yes :) |
| 17:39 | literary | Or :never-reaches-this-line |
| 17:40 | technomancy | 無 |
| 17:40 | noonian | :wth-just-happened? |
| 17:40 | literary | ,(cond :cond 3) |
| 17:40 | clojurebot | 3 |
| 17:40 | literary | What is the best word for this? |
| 17:40 | vIkSiT | dnolen_, https://gist.github.com/viksit/106822bdacd7e1d41ec0 |
| 17:40 | vIkSiT | here's some sample code. |
| 17:40 | literary | Maybe :mov |
| 17:40 | literary | or even :MOV |
| 17:40 | justin_smith | technomancy: well :無 would work |
| 17:41 | literary | ,:· |
| 17:41 | clojurebot | :· |
| 17:41 | vIkSiT | to restate my question, how do I get keys from a cljs.core/PersistentArrayMap in this case (the key exists but I get a nil) |
| 17:43 | justin_smith | vIkSiT: can you print the keys of a? |
| 17:43 | justin_smith | or, prn them rather |
| 17:43 | noonian | ,(keys {:foo "", :msg ""}) |
| 17:43 | clojurebot | (:msg :foo) |
| 17:43 | vIkSiT | I get nil |
| 17:43 | dnolen_ | vIkSiT: (keys some-array-map) |
| 17:43 | vIkSiT | (prn (keys a)) -> nil |
| 17:44 | kryft | Ugh, how do I turn the string keys in the :json-params produced by wrap-json-params into keywords? wrap-keyword-params doesn't seem to touch :json-params |
| 17:45 | vIkSiT | argh. |
| 17:45 | vIkSiT | I never thought I'd bitch about parens, but.. |
| 17:45 | vIkSiT | when I added that "After conversion" line |
| 17:45 | vIkSiT | extra paren. |
| 17:45 | vIkSiT | That closed the [let ..] and of course, everything else is nil |
| 17:46 | vIkSiT | dnolen_, justin_smith - thanks for the help. |
| 17:46 | dnolen_ | vIkSiT: np, in general if you see a strange error like this you should go hunting for syntax errors first :) |
| 17:46 | dnolen_ | vIkSiT: at this point 1000s of people use ClojureScript this is basic functionality |
| 17:46 | vIkSiT | hehe, I figured emacs + paredit was taking care of it. |
| 17:46 | vIkSiT | indeed |
| 17:46 | dbasch | &(cond nil "foo" ::"what") |
| 17:46 | lazybot | ⇒ "what" |
| 17:47 | vIkSiT | dnolen_, thanks for pointing to the multi refs example of shared state btw. I have a question on why om/build doesnt' currently take different :targets.. |
| 17:47 | vIkSiT | why should I not be able to build a component with its own target, and have om/root point to say document.body? |
| 17:47 | dnolen_ | vIkSiT: :target is only for root, this goes back to how React works |
| 17:48 | vIkSiT | hmm |
| 17:48 | dnolen_ | vIkSiT: again some limitations are React limitations |
| 17:48 | noonian | kryft: there is a keywordize-keys fn in clojure.walk and there is also a similar one in prismatic's plumbing lib i believe |
| 17:48 | dnolen_ | vIkSiT: but you can have multiple roots |
| 17:48 | vIkSiT | so how would you recommend solving a case where I have a static template, and two divs are dynamic. Both have om/root builds, but this of course means I can't combine them in the same om/root view |
| 17:49 | vIkSiT | dnolen_, yeah, I see why that's the case |
| 17:49 | dnolen_ | vIkSiT: both roots can share the same atom |
| 17:49 | dnolen_ | so they can be coordinated |
| 17:49 | dnolen_ | or they can share the same channel - whatever - coordination is not that challenging |
| 17:49 | kryft | noonian: Ok, thanks! |
| 17:49 | vIkSiT | yeah, I ended up using channels for now rather than IResolve. I couldn't get on-changes working with it. |
| 17:50 | technomancy | keywordize-keys =( |
| 17:50 | justin_smith | technomancy: clearly we need wordkeyize-words |
| 17:50 | technomancy | I almost put map-keys and map-vals as "what one feature would you add" in the survey, but "namespaces that are values" won instead |
| 17:50 | technomancy | I mean while we're asking for a pony |
| 17:51 | kryft | technomancy: Would you suggest something else than keywordize-keys? |
| 17:51 | dbasch | I asked for a pony: better exceptions / error messages |
| 17:51 | technomancy | kryft: keywordize-keys should be generalized to map-vals, but that doesn't exist, which makes me sad. |
| 17:51 | kryft | technomancy: Ah :) |
| 17:52 | technomancy | dbasch: I would have put that, but it's hard to classify it as a language feature |
| 17:52 | arrdem | dbasch: I asked for a bigger pony... official docs to kill Grimoire/ClojureDocs :P |
| 17:52 | technomancy | *map-keys rather |
| 17:52 | dnolen_ | vIkSiT: probably wise IResolve is not fully baked |
| 17:52 | justin_smith | kryft: why do the keys need to be keywords? doesn't the double translation just make everything more brittle? |
| 17:52 | technomancy | (def keywordize-keys (partial map-keys keyword)) ; done |
| 17:52 | puredanger | dbasch: I hear people say this all the time, but I think people mean different things by that and just saying "better errors" is too vague to be useful |
| 17:52 | dnolen_ | vIkSiT: channels/callback via :shared are a good solution to many problems |
| 17:53 | puredanger | I'm not saying this to disagree but b/c it's something that I would like to remove as a complaint and I want a better way to collect useful data |
| 17:53 | vIkSiT | dnolen_, indeed - this is what I have now : https://gist.github.com/viksit/353d73081a0152aba0a8 |
| 17:53 | technomancy | puredanger: there's just so many obvious fixes it's hard to know where to begin though |
| 17:53 | technomancy | also, it was like a one-line field |
| 17:53 | technomancy | in the survey |
| 17:53 | dbasch | puredanger: agree, it’s more about pointing out specific exceptions that could be more informative |
| 17:53 | kryft | justin_smith: The keys correspond to columns in an SQL database, and jdbc/query returns a map with keywords corresponding to column names |
| 17:54 | noonian | technomancy: map-vals is also in prismatic's plumbing lib heh |
| 17:54 | Bronsa | map-vals and map-keys should be a thing |
| 17:55 | dbasch | (inc map-vals) |
| 17:55 | lazybot | ⇒ 2 |
| 17:55 | puredanger | technomancy: dbasch: there are specific exceptions improved (generally ones with higher votes) every release yet we never seem to escape this complaint |
| 17:55 | Bronsa | https://github.com/search?utf8=✓&q=defn+map-vals&type=Code&ref=searchresults |
| 17:55 | puredanger | (also, I am highly in favor of map-keys and map-vals being in core) |
| 17:55 | kryft | justin_smith: It would be practical to have keyword keys (or string keys) on both the data coming from the frontend and the data coming from the database |
| 17:56 | AeroNotix | puredanger: same |
| 17:56 | AeroNotix | it's a very common thing to want to do |
| 17:56 | puredanger | technomancy: dbasch what does it take to move the needle? there are other things too that contribute from an experience pov (stack traces on compile errors, etc) |
| 17:56 | justin_smith | kryft: there is an optional keyword argument to cheshire/read-string to make the keys keywords - perhaps your middleware has a similar option |
| 17:56 | dbasch | puredanger: I’d see it as a good thing. If only a small group used Clojure, nobody would care that much about error messages. As the community grows, it will demand more. |
| 17:57 | dbasch | that’s really true of all software |
| 17:57 | puredanger | dbasch: but I don't see that complaint about other languages so I take it as an actual complaint here |
| 17:58 | technomancy | puredanger: spend a bit of time talking with people who haven't already built up mental scar tissue around the problem, I'd say |
| 17:58 | Bronsa | uhm I actually called map-vals update-vals in t.a |
| 17:59 | kryft | justin_smith: Thanks, but doesn't seem like it does; wrap-json-body does have a :keywords? parameter, but wrap-json-params doesn't. The docs for wrap-json-params suggest using wrap-keyword-params, but that doesn't seem to work. |
| 17:59 | kryft | justin_smith: Anyway, manually calling keywordize-keys should work well enough for now. |
| 17:59 | justin_smith | OK |
| 18:01 | noonian | kryft: you could pretty easily make your own middleware that calls keywordize-keys also |
| 18:01 | TimMc | Down with keywordizing! |
| 18:02 | justin_smith | puredanger: with many languages the core functions are more likely to validate input. With clojure it's common to give invalid input, and for call chain to go down quite a few levels before that becomes a problem. So the user (especially the naive user) sees a bunch of class names and function names they have never heard of, and see an error message that seems like a non-sequitor for the input they provided. |
| 18:02 | kryft | noonian: Right |
| 18:03 | justin_smith | puredanger: throw in a few anonymous functions with auto-generated names into the mix, and it's all pretty intimidating at first |
| 18:03 | puredanger | justin_smith: how can we capture data around that situation to understand what needs to be fixed |
| 18:03 | puredanger | justin_smith: as of next alpha, the anon-generated names are slightly more helpful (thanks Bronsa !) |
| 18:03 | justin_smith | oh, cool |
| 18:04 | justin_smith | puredanger: not sure - maybe dev time assertions about inputs? But that seems to conflict with the prevalent clojure coding style. |
| 18:05 | puredanger | justin_smith: there is little tolerance for checks that impede performance (although this is something that could be done in a special "dev mode" build - that's been discussed at length) |
| 18:05 | justin_smith | right |
| 18:06 | puredanger | here's a list of errormsg tickets in jira http://dev.clojure.org/jira/secure/IssueNavigator.jspa?reset=true&jqlQuery=labels+%3D+errormsgs+and+project%3Dclj+and+status+%3D+open - other than one or two , only a couple have more than 2 votes |
| 18:06 | justin_smith | puredanger: just spitballing, but a mechanism that defined a run time check, and reliably stripped checks when building an artifact would be nice |
| 18:06 | Bronsa | puredanger: my guess is that that's because nobody uses JIRA |
| 18:07 | technomancy | Bronsa: yeah, I stopped voting on things a while ago |
| 18:07 | puredanger | well I use it :) |
| 18:07 | puredanger | and in particular I use votes to decide what gets triaged, so... |
| 18:07 | Bronsa | puredanger: yeah me too, but my point is that the community just doesn't vote on tickets because most feel it's kinda useless |
| 18:08 | puredanger | we also used votes as a way to see which issues needed to be kept in 1.7 this week vs pushed off to 1.8 |
| 18:08 | puredanger | so I'm telling you (as the one that makes those decisions), that it's useful |
| 18:08 | TimMc | That's good to hear. |
| 18:08 | puredanger | I look those numbers every day |
| 18:09 | TimMc | I usually fail to vote because I find Clojure bugs on my work computer but have Jira login info on my home computer. :-P |
| 18:09 | puredanger | TimMc: that is outside my ability to fix :) |
| 18:09 | puredanger | gotta run…. |
| 18:10 | TimMc | fixing it now :-P |
| 18:10 | puredanger | I also watch Andy's report: http://jafingerhut.github.io/clj-ticket-status/CLJ-top-tickets-by-weighted-vote.html |
| 18:10 | Bronsa | puredanger: I wasn't questioning that, just making you aware that a big chunk of the community doesn't know the value of voting |
| 18:10 | danneu | kryft: just apply the wrap-json-params middleware before the ring.middleware.keyword-params/wrap-keyword-prams middleware that you're probably already using |
| 18:10 | puredanger | Bronsa: noted, and will try to re-assert the value of that more |
| 18:12 | kryft | danneu: It didn't seem to work, and actually the docs for wrap-keyword-params said that it "does not alter the maps under :*-params keys". *shrug* |
| 18:12 | xeqi | I'd lean towards error messages being something that bothers people that haven't gotten used to them, and those people don't overlap with jira accounts that vote |
| 18:13 | noonian | so you just need two more middleware to move :params to :proto-params and back again! |
| 18:14 | kryft | :D |
| 18:14 | xeqi | puredanger: is there a way to see what I've voted on? |
| 18:14 | noonian | but at this point thats a lot of work just to use someone elses middleware hehe |
| 18:15 | kryft | noonian: Yes, I'll probably end up writing my own keywordize-json-params middleware (sort of like I write my own FUNCTIONS, gee whiz, I'm a real programmer) |
| 18:16 | danneu | kryft: huh? wrap-json-params updates the :params map. wrap-keyword-params updates the :params map |
| 18:17 | kryft | danneu: For some reason wrap-json-params only puts some of the properties of the posted json object into :params, but all of them into :json-params |
| 18:17 | kryft | That confused me for a while too |
| 18:18 | danneu | how can i repro that |
| 18:18 | weavejester | wrap-json-params should put all of the properties in params |
| 18:18 | weavejester | I believe it’s just a merge |
| 18:19 | weavejester | Generally speaking wrap-json-body is a better middleware to use |
| 18:19 | weavejester | Unless you have specific needs |
| 18:19 | danneu | i use wrap-json-params -> wrap-keyword-params on my json apis and it works ifne |
| 18:20 | kryft | danneu: Well, I posted {"signup_form":[], "title" : "Foo", event_id : 7} from the browser, and :params was missing the signup_form property |
| 18:22 | kryft | weavejester: I think I was using wrap-json-params because friend expected it |
| 18:23 | danneu | kryft: what happens when you (cheshire.core/decode <your browser string>) |
| 18:26 | muraiki_ | hi all. I'm new to clojure and ran into an error that I'm having trouble understanding. the error is "Exception in thread "async-dispatch-4" java.lang.NullPointerException". I've posted the code and stacktrace here; any help would be most appreciated! https://gist.github.com/muraiki/11831288662a0c07b7d4 |
| 18:27 | muraiki_ | since there's a state machine error I imagine I'm doing something wrong with (go) |
| 18:27 | weavejester | muraiki: It looks like you’re sending nil into your channel, which causes an exception |
| 18:27 | justin_smith | muraiki_: do you have a full stacktrace? |
| 18:27 | muraiki_ | the full stacktrace is posted as a comment at the bottom of the gist |
| 18:28 | justin_smith | oh, now I see it, thanks |
| 18:28 | kryft | danneu: (decode "{\"signup_form\":[],\"title\":\"foo\",\"event_id\":7}") produces {"signup_form" [], "title" "foo", "event_id" 7} |
| 18:29 | muraiki_ | weavejester: hrm, let me see where that might be happening... I know that I put at least one legitimate thing on the channel because my browser client does get a websocket message, heh. |
| 18:30 | danneu | kryft: drop some `prn`s into your middleware stack and look at the actual vals coming over the wire |
| 18:30 | danneu | (prn request) |
| 18:30 | danneu | ((fn [handler] (fn [req] (prn req) (handler req))) |
| 18:31 | danneu | ensure content-type is 'application/json' |
| 18:32 | ghadishayban | muraiki_: just because there is an async reference in the stacktrace, doesn't mean anything except tat the exception blew up on the async thread pool |
| 18:32 | ghadishayban | but it may have been non-async (normal) fn call that did it |
| 18:32 | muraiki_ | ghadishayban: thanks, that's good to know. :) |
| 18:32 | ghadishayban | the stacktrace shows line 43, which is (is-diff? (data/diff res (url-name @last-state)) |
| 18:32 | muraiki_ | weavejester is right, there appears to be a nil going on the channel |
| 18:33 | ghadishayban | I'd try to duplicate it minimally |
| 18:33 | muraiki_ | does my (<! (timeout 10000)) put a nil on the channel? what I'm trying to do is to block for 10 seconds |
| 18:33 | ghadishayban | no |
| 18:34 | ghadishayban | that is fine, it's a take from a channel |
| 18:34 | ghadishayban | the only thing putting onto a channel in your source is L64 |
| 18:36 | kryft | danneu: Yup, the content-type is "application/json; charset=utf-8" for the relevant post requests |
| 18:36 | ghadishayban | Also, putting a nil on the channel results in a different exception, you'll see a clear "Can't put nil on channel" |
| 18:36 | muraiki_ | I did a prn on url-maps to make sure some weird value wasn't in there, but I only see [{:name "jsontest", :url "http://ip.jsontest.com/"}] |
| 18:36 | muraiki_ | oh ok, thank you |
| 18:36 | kryft | danneu: I do also see all properties in both :params and :json-params in the prn after wrap-json-params |
| 18:37 | ghadishayban | muraiki_: so in your code you must ascertain that make-req never returns nil |
| 18:37 | danielcompton | In clj 1.7 alpha 2, why would partition not have a 1 arg arity that returns a transducer? |
| 18:37 | danielcompton | partition-by and partition-all both do |
| 18:38 | muraiki_ | muraiki_: wow, that should have been obvious. I made the assumption that it'd always succeed, which is of course not true. let me play with that a bit |
| 18:38 | ghadishayban | partition has more knobs than the other two functions, and the only knob you could do with one arity is to have a short final partition, which is arguably a rare desire. (speaking for myself) |
| 18:38 | muraiki_ | oops, messaged myself :n |
| 18:38 | danneu | kryft: if your :params map has nonkeyword keys in your routes, then wrap-keyword-params is getting the request before wrap-json-params |
| 18:39 | jeffterrell | puredanger: Crazy idea to collect data about confusing exception messages: make a lightweight webapp that collected Clojure exceptions. Every exception in Clojure 1.7 includes a link to the web site with a message: "Did you find this exception confusing? Let us know here: http://…" The site parses the exception and aggregates exception instances into groups of like messages. Users would still have to go to the trouble of pasting |
| 18:39 | jeffterrell | their exception in, but that would at least be a way to start collecting data about it. The pattern matching used to group exception instances could also be used to provide helpful suggestions in Clojure 1.8. |
| 18:39 | jeffterrell | Arg, puredanger left the room. IRC veterans, what does one typically do in a case like this? |
| 18:40 | justin_smith | $mail jeffterrell via lazybot |
| 18:40 | lazybot | Message saved. |
| 18:40 | technomancy | jeffterrell: you could do that in an nrepl middleware |
| 18:40 | technomancy | it doesn't need to be part of clojure |
| 18:40 | ghadishayban | jeffterrell: which case specifically? |
| 18:40 | kryft | danneu: Actually this instance was running without wrap-keyword-params at all. And the "signup_form" value has disappeared from :params by the time I get to my compojure post request handler :P |
| 18:40 | technomancy | with nrepl-discover you could even prompt (do you want to report a usability bug) interactively |
| 18:41 | dbasch | (inc technomancy) ;; that’s a great idea |
| 18:41 | lazybot | ⇒ 141 |
| 18:42 | dbasch | I’d love to have the time to work on that, or I’d gladly contribute to a bounty for something like it |
| 18:43 | hiredman | ugh |
| 18:43 | hiredman | terrible |
| 18:43 | hiredman | I hate those things |
| 18:43 | danielcompton | ghadishayban: ah yes I see now |
| 18:43 | jeffterrell | justin_smith: Whoa, what does this magical $mail thing do exactly? |
| 18:43 | hiredman | my laptop does it, my phone does |
| 18:44 | jeffterrell | technomancy: Brilliant! …about the nrepl middleware. That would be way better: no pasting, and automatically report things like Clojure version. |
| 18:44 | justin_smith | jeffterrell: lazybot sends the person a message when they show up again |
| 18:44 | jeffterrell | ghadishayban: The case where you reply to somebody after they've left the chatroom, but you want them to see your message somehow. |
| 18:44 | kryft | danneu: Just to clarify, wrap-keyword-params works fine, but for some reason one key/value from :params disappears before I get to my app's request handler. :P |
| 18:44 | ghadishayban | oh i see |
| 18:45 | bja_ | anyone around know why I can't annotate a prismatic.core/defnk function's output with {:foo AnyProtocolHere}? see https://gist.github.com/emidln/2b3a192b7e7f3d305f94 |
| 18:45 | danneu | kryft: gist your middleware stack? |
| 18:45 | dbasch | hiredman: as long as it’s opt-in and disabled by default, I think it’s awesome |
| 18:45 | jeffterrell | justin_smith: nifty! Thanks! |
| 18:45 | technomancy | just put it in cider-middleware, then hiredman will never see it |
| 18:45 | technomancy | =D |
| 18:45 | jeffterrell | $mail puredanger Crazy idea to collect data about confusing exception messages: make a lightweight webapp that collected Clojure exceptions. Every exception in Clojure 1.7 includes a link to the web site with a message: "Did you find this exception confusing? Let us know here: http://…" The site parses the exception and aggregates exception instances into groups of like messages. Users would still have to go to the trouble of |
| 18:45 | lazybot | Message saved. |
| 18:45 | jeffterrell | pasting their exception in, but that would at least be a way to start collecting data about it. The pattern matching used to group exception instances could also be used to provide helpful suggestions in Clojure 1.8. |
| 18:46 | bja_ | err, not prismatic.core, plumbing.core/defnk |
| 18:47 | kryft | danneu: https://gist.github.com/kryft/45ce18c0ca7e26092b39 |
| 18:47 | jeffterrell | hiredman: The trick is that the newbies need to have it enabled, because they're the ones we're trying to help. But maybe it could be disable-able by a dynamic var? Who knows. I'll label it a policital decision and bow out. :-) |
| 18:47 | hiredman | jeffterrell: no |
| 18:48 | hiredman | jeffterrell: in a few months when you know clojure you won't care about it anymore |
| 18:48 | ghadishayban | jeffterrell: true ^ |
| 18:48 | ghadishayban | though it would be nice to have a guide for decoding exceptions for users |
| 18:48 | hiredman | jeffterrell: you are optimizing for the experience of new users, a class of users that basically disapears every two months |
| 18:49 | jeffterrell | hiredman: …and perpetually reappears. :-) |
| 18:49 | ghadishayban | When you see a NullPointer, look at the stack frame just above it |
| 18:49 | ghadishayban | When you see a ClassCastException ... couldn't treat number as ISeq, etc. |
| 18:49 | hiredman | not only that, but you appear to think that there is a dearth of ideas in the world, and so by just coming up with an idea you are doing a service to the world |
| 18:50 | hiredman | you think such a thing should exist, write the code to do it |
| 18:50 | ghadishayban | hiredman: he just wants to help future peoples. |
| 18:51 | hiredman | ghadishayban: sure, then write the app and try and get people to use it |
| 18:51 | ghadishayban | jeffterrell: It will never be accepted in core, but a useful nrepl middleware is promising |
| 18:51 | dbasch | perhaps the way for newbies to enable it is via a template for newbies that could be suggested in tutorials |
| 18:51 | ghadishayban | yup, agreed. |
| 18:51 | jeffterrell | hiredman: I realize having the idea is like 0.001% of the overall effort. But maybe somebody will like it and Clojure will be improved. If you don't like it, you don't have to work on it. :-) |
| 18:52 | jeffterrell | Nor does anybody, for that matter (obviously). |
| 18:52 | hiredman | jeffterrell: if you don't even like it to work on it, why expect someone else to? |
| 18:52 | jeffterrell | I don't. |
| 18:52 | ghadishayban | hiredman: just trying to stay positive |
| 18:52 | hiredman | then why send puredanger a mail about it? |
| 18:53 | jeffterrell | puredanger asked for ideas on how to collect data about confusing exception messages. I'm just responding to his request. |
| 18:53 | ghadishayban | yeah maybe that's too eager. prior art in this area is aviso/pretty |
| 18:53 | ghadishayban | need concrete impls and soundness before core will even consider something |
| 18:53 | ghadishayban | https://github.com/AvisoNovate/pretty |
| 18:53 | dbasch | (inc (Math/abs ghadishayban)) |
| 18:53 | lazybot | ⇒ 1 |
| 18:53 | hiredman | jeffterrell: ok, I guess |
| 18:54 | dbasch | (helping ghadishayban stay positive) |
| 18:54 | hiredman | jeffterrell: we just get wave after wave of people learning the language in #clojure, who propose these things, and then stop caring about them after two montsh |
| 18:55 | hiredman | and people who generally are new themselves wringing their hands over the user experience of people new to clojure |
| 18:55 | jeffterrell | hiredman: Makes sense. Sorry. :-/ I understand the frustration with people who flippantly propose things and then don't follow up to your thoughtful reply because they never cared in the first place. |
| 18:55 | danneu | kryft: what does (prn request) look like after handler/site? |
| 18:55 | technomancy | imagine, that, newbies caring disproportionately about usability |
| 18:55 | danneu | for one, it looks like wrap-params resets :params https://github.com/ring-clojure/ring/blob/1.3.1/ring-core/src/ring/middleware/params.clj |
| 18:56 | hiredman | technomancy: they care about the usability for someone who doesn't know what they are doing |
| 18:56 | jeffterrell | If it helps, I've been using Clojure for over two years and know my way around. :-) So my idea wouldn't help me out any. |
| 18:56 | hiredman | technomancy: which is why they tend to propose silly things like hiding stacktraces |
| 18:56 | jeffterrell | ghadishayban: New lib; thanks for the link. |
| 18:57 | hiredman | as someone who knows things(or atleast I like to thing I do) having stacktraces around that show me everything is useful |
| 18:58 | justin_smith | technomancy: jeffterrell: it may be that the problem is that for a single person, learning to read the existing stack traces is easier than making better error reporting (despite the fact that better error reporting would save time for many people in the long term, and could complement the existing stacktrace reading instead of just replacing it) |
| 18:59 | kryft | danneu: https://gist.github.com/kryft/26faacbb5f39877d9fee |
| 19:00 | _pr0t0type_1 | Hey guys, do you know if there is any equivalent to base_url in clojure/compojure/ring? I don't want to have to hardcode two different urls (and paths) for developement vs production (ie localhost:8000/myendpoint) vs (production.com/myapp/myendpoint) |
| 19:00 | ghadishayban | true once you can read stacktraces well, you're set for life. but ongoing usability is always nice. There's always the danger though, which has been stated over and over by Rich about designing for beginners is never a goal |
| 19:00 | kryft | danneu: Everything looks fine after wrap-json-params, but "signup_form" mysteriously disappears from :params some time later. |
| 19:00 | hiredman | does being a beginner stink? become an expert, it's super |
| 19:01 | ghadishayban | JRuby goes to great (incredible) lengths to re-write the stacktrce |
| 19:01 | bja_ | (inc hiredman) |
| 19:01 | lazybot | ⇒ 57 |
| 19:01 | kryft | danneu: (And I don't see anything weird after handler/site either, but no :params or :json-params there obviously) |
| 19:01 | hiredman | ghadishayban: well, they have to show ruby stacks right? |
| 19:01 | ghadishayban | si |
| 19:01 | AeroNotix | clojure stacktraces suck and anyone defending them should not be allowed to talk about usability |
| 19:01 | AeroNotix | end of story |
| 19:01 | ghadishayban | AeroNotix: it's complicated =) |
| 19:02 | AeroNotix | of course it is, nothing about what I said included the fact that it was an easy fix |
| 19:02 | AeroNotix | it's hard and I understand why |
| 19:02 | AeroNotix | but it still sucks |
| 19:02 | kryft | danneu: Anyway, I think I have to sleep off this cold :) |
| 19:02 | danneu | kryft: break handler/site into its individual middleware. put its wrap*params related stuff at the end of your (-> app ... ) stack |
| 19:02 | bja_ | _pr0t0type_1, (ns foo (:require [environ.core :refer [env]]) (defn base-url [] (:base-url env))) |
| 19:03 | seancorfield | AeroNotix: stack traces stop sucking after you get over the initial shock... |
| 19:03 | AeroNotix | seancorfield: 3 years and counting. |
| 19:03 | _pr0t0type_1 | bja_: thank you! |
| 19:03 | seancorfield | and as ghadishayban says, learning to read stacktraces - regardless of language - is a useful skill that I wish more developers had |
| 19:04 | AeroNotix | and that CIDER middleware actually can make things worse sometimes |
| 19:04 | ghadishayban | and jvm's fast throw |
| 19:05 | amalloy | the problem with simplified stacktraces is that beginners might actually use them. then they'll come in here with a stacktrace that's missing all the useful information that's in a real stacktrace |
| 19:05 | jeffterrell | Just to be clear, I don't think anybody's proposing simplified stacktraces. Unless I missed it… |
| 19:06 | ghadishayban | the CIDER toggles for hiding / showing info are entirely in user-space |
| 19:06 | justin_smith | right, we have been talking about better error messages - something that complements stack traces and doesn't replace them |
| 19:06 | cfleming | jeffterrell: It's generally the first thing that people propose for making Clojure more newbie-friendly |
| 19:06 | kryft | danneu: Thanks for helping with the debugging! |
| 19:07 | ghadishayban | the aviso library above just does some pretty-printing, aligning of the line numbers |
| 19:07 | cfleming | I agree that stack traces are really not a problem, but I disagree that making Clojure more accessible for newbies is a bad goal. |
| 19:07 | jeffterrell | cfleming: Is there a typical response to such proposals? I'd be interested to read it. |
| 19:07 | cfleming | jeffterrell: There are a couple of libraries that implement it, so generally you can get that if you want it. aviso/pretty, clj-stracktrace etc |
| 19:07 | ghadishayban | the only rational approach for Clojure is to do what it already does, which is include all possible information. it's a hosted language, so sometimes that gets messy |
| 19:08 | kryft | danneu: I'll try breaking down compojure.handler/site to its individual middleware later as you suggested |
| 19:08 | noonian | i think the biggest barrier for newbies is that it is a lisp, and you really have to learn about how the language works before jumping in and trying to write stuff |
| 19:08 | ambrosebs | this is the most practical idea i've come up with for improving error messages https://github.com/frenchy64/dynalint |
| 19:08 | justin_smith | noonian: I came to clj with scheme / common lisp/ ocaml experience, and the stack traces drove me batty |
| 19:08 | ghadishayban | (inc cfleming ) |
| 19:08 | lazybot | ⇒ 1 |
| 19:09 | justin_smith | ghadishayban: it's sensetive to spaces |
| 19:09 | justin_smith | (inc cfleming) |
| 19:09 | lazybot | ⇒ 3 |
| 19:09 | ghadishayban | Helping newbs shouldn't mean designing for newbs |
| 19:10 | ghadishayban | rich's example of the guitar hero guitar with 4 buttons... |
| 19:10 | cfleming | ghadishayban: Having a powerful language is totally orthogonal to it being easy to use |
| 19:11 | noonian | justin_smith: yeah, but you will see waaay more stack traces if you don't understand lisp at all than if you do :P |
| 19:11 | ghadishayban | yeah I am agreeing with you |
| 19:12 | justin_smith | noonian: and many of the lisper problems actually have decent messages |
| 19:12 | justin_smith | ,(let ((a 0) (b 1)) a) |
| 19:12 | clojurebot | #<CompilerException java.lang.IllegalArgumentException: let requires a vector for its binding in sandbox:, compiling:(NO_SOURCE_FILE:0:0)> |
| 19:12 | jeffterrell | ambrosebs: That's pretty nifty! |
| 19:12 | justin_smith | (lost count of how many times I did that...) |
| 19:13 | ambrosebs | so yea, that's a very compelling way to improve error messages if you're so inclined. |
| 19:15 | justin_smith | (inc ambrosebs) |
| 19:15 | lazybot | ⇒ 10 |
| 19:15 | justin_smith | nice |
| 19:19 | cfleming | Another thing that would make a huge difference IMO would be for clojure.core to use seqex or something similar for its macro parsing. |
| 19:19 | cfleming | i.e. illuminated macros |
| 19:19 | jeffterrell | That would be sweet. |
| 19:19 | ambrosebs | or just redefine them to use them... |
| 19:20 | ambrosebs | surely that's a library somewhere? |
| 19:20 | cfleming | That's just a huge win for everyone, macros are easier to write, easier to read, and you remove a whole class of "can't make seq from symbol" error messages |
| 19:21 | jeffterrell | cfleming: I like it. Any idea about performance implications? |
| 19:21 | ghadishayban | macros cost only at load time, so startup |
| 19:22 | cfleming | jeffterrell: No, no idea, sorry. I implemented something similar for Cursive but didn't test the difference. Frankly, I didn't care. |
| 19:22 | cfleming | The correctness benefits were totally worth it. |
| 19:22 | ghadishayban | cgrand/seqexp is also amazing, and only 200LOC |
| 19:23 | cfleming | Yeah, although that only works for regular languages IIRC |
| 19:23 | technomancy | does it declare version ranges? |
| 19:24 | cfleming | ambrosebs: You mean redefine e.g. let to use seqex and then expand to the previous version? |
| 19:25 | ghadishayban | technomancy: which? |
| 19:25 | technomancy | ghadishayban: cgrand's thingy |
| 19:25 | technomancy | been burned before |
| 19:25 | ghadishayban | it doesn't appear to |
| 19:25 | technomancy | progress =) |
| 19:25 | bja_ | is there a way (other than fork and fix project.clj) to remove the version range declarations in third party libraries? |
| 19:25 | ambrosebs | cfleming: yea alter-var-root clojure.core/let to an equivalent macro that's nicer |
| 19:26 | bja_ | (or tell lein deps :tree to ignore them) |
| 19:26 | ambrosebs | there's a bootstrapping issue but it should probably mostly work. dynalint does it for a few macros |
| 19:26 | technomancy | bja_: just :exclusions |
| 19:26 | cfleming | interesting idea, I hadn't thought of that. It would make a great POC if nothing else. |
| 19:27 | ambrosebs | dynalint convinced me that it's a good idea. or our only idea. |
| 19:27 | ambrosebs | it's just a poc itself anyway. |
| 19:28 | ambrosebs | the next step would be a more structured error catching mechanism... like seqex :) |
| 19:30 | ambrosebs | cfleming: the macro redefs in dynalint https://github.com/frenchy64/dynalint/blob/master/src/dynalint/lint.clj#L1485 |
| 19:33 | ambrosebs | the downside is you really can only target specific clojure versions |
| 19:33 | ambrosebs | and you better hope no other lib is pulling the same trick |
| 19:34 | ambrosebs | but it's the user's fault anyway, they loaded the monkey patches |
| 19:34 | ambrosebs | ;) |
| 19:36 | cfleming | Hehe, right. But there's clearly lots of gain to be had, especially around error messages. |
| 19:37 | ambrosebs | yep, very low hanging fruit. |
| 19:39 | QbY | any clojure freelancers looking for immediate work? |
| 19:40 | ambrosebs | QbY: maybe ask https://twitter.com/cgrand |
| 19:42 | jeffterrell | QbY: I may have a colleague who is. |
| 19:42 | muraiki_ | ok, so I figured out what was happening to put nil on the channel. (onto-chan ch col) closes the channel once the collection is exhausted, unless you tell it not to |
| 19:43 | muraiki_ | as always, reading the documentation helps :) |
| 19:44 | muraiki_ | that being said, I'm not certain how to block the channel with a timeout so that I don't have onto-chan executing over and over immediately. I've used (<! (timeout 5000)) to accomplish this, but it doesn't seem to be working here |
| 19:44 | arrdem | ambrosebs: cfleming: glad to see I'm not the only one kicking that idea around :D |
| 19:45 | bbloom | sweet! https://github.com/clojure/clojure/blob/9aaee3c111ce18b9b70695dd45a04b401a174113/src/clj/clojure/core.clj#L7286 |
| 19:45 | bbloom | i called that "each" |
| 19:45 | bbloom | but each! or run! is fine by me too |
| 19:45 | bbloom | i've needed/used that quite a few times for side effects from a seq |
| 19:46 | ghadishayban | bbloom: it's a useful addition |
| 19:46 | ghadishayban | also *way* faster than doseq |
| 19:47 | Bronsa | that's a nice fn, I didn't notice it |
| 19:47 | bridgethillyer | I need a favor from someone |
| 19:48 | bridgethillyer | At the conj, can someone please explain to me why being concerned with the beginner experience in Clojure is a *bad* idea? |
| 19:48 | bridgethillyer | I really feel like I can only figure this out if someone explains it to me in person |
| 19:48 | technomancy | someone: you heard her, spit it out |
| 19:48 | arrdem | (inc technomancy) |
| 19:49 | lazybot | ⇒ 142 |
| 19:49 | technomancy | (sorry) |
| 19:49 | amalloy | bbloom: why is that way faster than doseq? like, i see that you're using reduce, which is fast, but i guess i would have expected doseq to do that as well |
| 19:49 | jeffterrell | bbloom: I'm sure I'm missing something, but why is that different than e.g. `(do (map proc coll) nil)`? |
| 19:49 | bridgethillyer | :) |
| 19:49 | ghadishayban | doseq has chunked traversal |
| 19:49 | amalloy | jeffterrell: well, your example does nothing at all, just returns nil |
| 19:49 | bbloom | amalloy: i didn't say it, ghadishayban did |
| 19:49 | jeffterrell | ha, right, say mapv then :-) |
| 19:49 | bbloom | jeffterrell: mapv builds a data structure you'd just throw away... |
| 19:50 | amalloy | well *that* example consumes unbounded memory |
| 19:50 | amalloy | (for large enough colls) |
| 19:50 | ghadishayban | hmm does clojurebot macroexpand... |
| 19:50 | bridgethillyer | I’m serious, though. I promise to even be nice and listen a lot if someone is willing to do that for me |
| 19:50 | amalloy | but what you really mean is (do (dorun (map f coll)) nil) |
| 19:50 | jeffterrell | OK, true, good points all :-) |
| 19:50 | amalloy | which has the problem of allocating a bunch of cons cells |
| 19:50 | technomancy | bridgethillyer: as someone who's just spent three weeks diving into racket, you could do a lot worse than copying everything about their attitude and getting started experience =) |
| 19:50 | ghadishayban | ,(macroexpand '(doseq [a (range 50) b (range 50)] (do))) |
| 19:50 | clojurebot | (loop* [seq_27 (clojure.core/seq (range 50)) chunk_28 nil count_29 ...] (if (clojure.core/< i_30 count_29) (clojure.core/let [a (.nth chunk_28 i_30)] (clojure.core/loop [seq_35 (clojure.core/seq (range 50)) chunk_36 nil count_37 ...] (if (clojure.core/< i_38 count_37) (clojure.core/let [b (.nth chunk_36 i_38)] (do (do)) (recur seq_35 chunk_36 count_37 (clojure.core/unchecked-inc i_38))) (clojure.c... |
| 19:50 | bridgethillyer | technomancy: Loved your blog post today |
| 19:50 | jeffterrell | OK, I see why the reduce version is better. Nice. |
| 19:50 | technomancy | I mean, not necessarily *you* in particular |
| 19:51 | technomancy | bridgethillyer: thanks |
| 19:51 | bridgethillyer | technomancy: It’s in my one open browser tab right now. Going to spend some serious time thinking about it. |
| 19:52 | technomancy | bridgethillyer: so actually what you should do is convince greghendershott to write down everything that's sub-par, confusing, or seems unnecessary; since he's coming from racket-land to clojure-land, his standards are pretty high =) |
| 19:52 | jeffterrell | bridgethillyer: I think part of the issue is that newbies often want an "easy" solution, in the Rich Hickey sense, where it's just a recipe they can apply with little effort. But the real solution often involves real work to understand the underlying concepts. So I think that's one sense in which catering to newbies can be a bad idea. (Emphasis on "can be"—it doesn't have to go that way.) |
| 19:52 | hiredman | bridgethillyer: maybe, I'll be at the conj, but I don't think it is bad, and if someone is interested in it, they should work on it |
| 19:53 | bridgethillyer | technomancy: brilliant, yes |
| 19:53 | bbloom | i think i'd like the name each! better than run! |
| 19:53 | bbloom | but i'm just glad to finally have that function :-) |
| 19:53 | bridgethillyer | hiredman: We should totally have a beer or something at the conj |
| 19:53 | hiredman | I object to what seems to be the idea that it is a universal priority |
| 19:53 | ghadishayban | yeah |
| 19:53 | ghadishayban | (inc hiredman) |
| 19:53 | lazybot | ⇒ 58 |
| 19:54 | ghadishayban | whoa we gotta catch up |
| 19:54 | ghadishayban | And beginners shouldn't drive design changes to a language |
| 19:54 | hiredman | hah, yeah, I suppose so, boy it feels like forever since I was in one place with a lot of clojurists |
| 19:54 | bbloom | bridgethillyer: did i miss some context? |
| 19:55 | bridgethillyer | bbloom: yeah, sorry referring to things 30 min - 1 hour ago |
| 19:55 | ghadishayban | tooling can and is improving |
| 19:56 | hiredman | outside of tooling, errors messages that have issues filed against them get changed and patched |
| 19:56 | bridgethillyer | ghadishayban: Ok, you’re invited for the beer/other beverage of your choice, too, at the conj |
| 19:56 | ghadishayban | there was an example of a Groovy stacktrace at the JVM Language Summit this summer, and it was a couple pages full with 0% of user code represented in the trace |
| 19:56 | bbloom | bridgethillyer: ok i read the scroll back |
| 19:57 | hiredman | we'll have an unsession: "people who love new comers vs. those who feel they should be left in the cold with the wolves and if they survive they are welcome" :) |
| 19:57 | ghadishayban | LOL |
| 19:57 | arrdem | pfft |
| 19:57 | bridgethillyer | hiredman: lol I’m totally signed up |
| 19:58 | bja_ | hiredman: sounds more like stalin scheme |
| 19:58 | arrdem | "if they aren't motivated enough to join #clojure and ask questions they don't belong anyway" |
| 19:59 | technomancy | what kind of person tries to learn a programming language without freenode; I can't even imagine |
| 19:59 | bbloom | bridgethillyer: i think part of the problem w/ clojure+beginners is that a lot of beginner support stuff has non-trivial complexity and performance costs |
| 19:59 | bbloom | like domain checking functions |
| 19:59 | bbloom | we've discussed garbage in / garbage out quite a bit here in this room |
| 20:00 | hiredman | racket's tower of languages approach works well there |
| 20:00 | technomancy | oh man... I spent like half an hour writing contracts over the weekend, and it paid off many times over already https://github.com/technomancy/cooper/blob/master/cooper/cooper.rkt |
| 20:00 | technomancy | super easy to turn off too |
| 20:00 | bbloom | technomancy: oh yeah, i'm all for optional contracts, etc |
| 20:01 | bbloom | but i do think that designing for optional validation from the start would yield a pretty different language |
| 20:01 | hiredman | I wonder what kind of errors you get from core.contracts |
| 20:01 | technomancy | assertion failed: (= a b) |
| 20:01 | bbloom | for example the lack of conditional destructuring in clojure can make a lot of contracts more verbose to specify |
| 20:01 | technomancy | ^ http://p.hagelb.org/csp.jpg |
| 20:02 | bridgethillyer | Ok, I get the “don’t design for beginners” thing, and I agree |
| 20:02 | hiredman | well, I mean, there are lots of options for improving error messages |
| 20:02 | hiredman | schema, core.typed, dynalint, eastwood |
| 20:03 | bridgethillyer | IMO, designing for beginners and being concerned about the beginner experience are two, not necessarily overlapping things |
| 20:03 | bbloom | hiredman: schema has some serious problems when it comes to error messages... see my chat w/ wolfe here: https://github.com/Prismatic/schema/pull/134 |
| 20:03 | hiredman | bridgethillyer: the question is, where should the beginner experience fall on the list of priorities |
| 20:04 | beppu | Racket's beginner experience is wonderful due to how much information DrRacket gives ou. |
| 20:04 | hiredman | bbloom: ok, so use core.typed :) |
| 20:04 | hiredman | I dunno, my point is there are diverse options for this, the issue is because there are options you need some amount of expertise to choose one |
| 20:05 | hiredman | maybe technomancy will write DrClojure |
| 20:05 | hiredman | technomancy: you like programming swing if I recall |
| 20:06 | bridgethillyer | hiredman: That’s my dream, although I doubt it’s possible |
| 20:06 | bridgethillyer | hiredman: and to your much earlier point, while I dream of that, I’m not willing to work on it at all :) |
| 20:06 | hiredman | the best thing for errors would likely be to enrich the communication of errors between the compiler and tools |
| 20:07 | beppu | I really liked how you could hover over symbols, and DrRacket would draw lines to other references to those symbols. I also liked how you could hover over a library, and see every occurence of a symbol used from that library have a line drawn to it. It was so programmer-friendly. |
| 20:07 | hiredman | an exception with a message means the compiler has to make policy descions with regard to generating that message |
| 20:07 | beppu | The error messages have been pretty good so far, too (in DrRacket). |
| 20:07 | ghadishayban | beppu: cursive does most of that, without the lines drawn |
| 20:07 | technomancy | hiredman: I'm too far gone |
| 20:07 | hiredman | if the compiler just sort of stopped, said to what repl client or whatever you use, and said "there was an error here, here is the state, what do I do?" |
| 20:07 | bbloom | it's funny, the 3 approaches of types, contracts, and schema seem to fall in logic, OOP, and grammar programming buckets respectively :-) |
| 20:07 | beppu | ghadishayban: That's good to know. Maybe I'll try cursive out one of these days. |
| 20:08 | ambrosebs | cfleming: can cursive ever draw the lines for scoping like drracket? |
| 20:08 | technomancy | the only way for me to do anything that's remotely useful for newbies is to disengage with everything I know and start from scratch |
| 20:08 | technomancy | which is why I'm building a hypercard clone |
| 20:09 | ghadishayban | in my limited use of it, it seems that cursive is aware of scoping rules |
| 20:09 | hiredman | and once you are starting to talk about changes to the compiler, you have my attention |
| 20:10 | technomancy | at some point the simplest thing to be would just be to port clojure to the racket runtime and get all their awesome tooling for free, then get them switched over to the jvm once they are comfortable but need to call java libs |
| 20:11 | bridgethillyer | technomancy: okay! |
| 20:11 | technomancy | at that point the racket->jvm jump would start to feel a bit like jvm->js |
| 20:12 | technomancy | trade good tooling and decent usability for increased reach. then do it again. |
| 20:12 | hiredman | well, the jvm is way better than js runtimes |
| 20:13 | hiredman | so not entirely like clojure->clojurescript |
| 20:13 | technomancy | TBH I bet the only reason that hasn't already happened is that racket is already close enough as-is that it's not worth the hassle |
| 20:14 | hiredman | the really annoying thing about projects that claim to target clojure at other runtimes is they either get semantics subtly wrong, or get the clojurescript semantics instead of clojure's |
| 20:15 | arrdem | kinda hard to avoid when there isn't a spec for Clojure, just an implementation |
| 20:15 | technomancy | right; I mean if you can be "clojure" without even having vars, who can say where the line is drawn |
| 20:15 | arrdem | I'd be up for Clojure in Racket... I've been wanting to play with Racket anyway |
| 20:15 | hiredman | have you looked at https://github.com/takikawa/racket-clojure ? |
| 20:16 | bbloom | technomancy: i would be interested in a racket-clojure for FFI purposes |
| 20:16 | technomancy | right, so spoiler alert is that https://github.com/greghendershott/rackjure exists |
| 20:16 | hiredman | vars are so great, I dunno if they were introduced just for utility or the greatness was understood |
| 20:16 | bbloom | tbaldridge seems to be tinkering w/ a pypy based clojure too |
| 20:16 | technomancy | it doesn't have vars, metadata, pervasive destructuring, or persistent vectors |
| 20:16 | beppu | racket is nice on its own |
| 20:16 | technomancy | but yeah |
| 20:16 | hiredman | but being able to talk about linkage in a first class way |
| 20:16 | hiredman | fantastic |
| 20:16 | technomancy | hiredman: srsly |
| 20:16 | bbloom | modules/units are the biggest thing i want from racket land |
| 20:17 | bbloom | huge deal |
| 20:17 | hiredman | very tricky |
| 20:17 | bbloom | in racket? in general? or to add to clojure? |
| 20:17 | hiredman | to add to clojure |
| 20:17 | bbloom | yeah, agreed |
| 20:17 | bbloom | i thought about it a bunch and my brain hurt so i gave up thinking about it |
| 20:18 | hiredman | I mean, unless you want to throw out the current namespace system, which I dunno, I might be fine with |
| 20:18 | technomancy | hiredman: if you're going to replace namespaces, they need to be replaced with namespaces-as-values, I think |
| 20:18 | bbloom | heh, yeaaah... that seems unlikely |
| 20:18 | technomancy | if that bandaid is gonna get pulled, make it count =) |
| 20:18 | hiredman | technomancy: nah |
| 20:18 | lukecossey | Anyone used the goog.fx.css3 Transition? I'm having problems with it working in Safari. |
| 20:19 | hiredman | namespaces as values don't really make sense |
| 20:19 | hiredman | they have a name, they are an identity |
| 20:19 | technomancy | bbloom: hm; so to me racket's use of submodules for main feels pretty tacky |
| 20:20 | technomancy | vs just "main is a function, so you know, call it" |
| 20:20 | bbloom | hiredman: i think he means to be able to capture a snapshot of a namespace and to manipulate them as values, not to remove their identity nature |
| 20:20 | hiredman | bbloom: what would you do with that? |
| 20:20 | bbloom | technomancy: i can't comment on rackets use of modules, sub or otherwise, since i haven't used racket beyond some tinkering in drracket |
| 20:21 | bbloom | hiredman: one thing is something like hiphiparray does with specialization |
| 20:21 | bbloom | hiredman: another thing would be for providing alternate backing implementations for say clj + cljs |
| 20:21 | bbloom | etc |
| 20:21 | hiredman | bbloom: sure, but that seems pretty orthogonal to namespaces as a value |
| 20:21 | technomancy | hiredman: for isolating out subtrees of namespaces to allow multiple versions to coexist |
| 20:21 | hiredman | bbloom: what you want is someway to template namespaces |
| 20:22 | bbloom | hiredman: which is effectively what racket's units are |
| 20:22 | hiredman | bbloom: sure |
| 20:22 | bbloom | hiredman: i was just trying to clarify technomancy's comment |
| 20:22 | hiredman | I am pretty sure they do all that without having namespaces as immutable values |
| 20:22 | hiredman | errr |
| 20:22 | hiredman | modules |
| 20:22 | hiredman | technomancy: yeah, but that has nothing to do with namespaces as values |
| 20:23 | bbloom | hiredman: sure, but it would be nice to be able to capture an immutable value, do some mutable thing to the identity, then capture another value, then *look at them* for debugging, if nothing else |
| 20:23 | hiredman | that just has to do with how namespaces exist |
| 20:23 | hiredman | right now clojure namespaces exist in a flatspace |
| 20:23 | technomancy | they should be first-class things you can operate on without their being globally rooted |
| 20:23 | ghadishayban | what would a motivating purpose of ns templating be? type specialization or running multiple versions of a subtree of code, like technomancy suggests? |
| 20:23 | hiredman | if you turned it in to a tree with some scoping rules |
| 20:24 | hiredman | ghadishayban: the hiphiparray example is type specialization |
| 20:24 | bbloom | ghadishayban: and cljx is basically all namespace templating |
| 20:25 | hiredman | although, to be fair, I think you can do namespace templating with some macros already |
| 20:25 | xcthulhu | bbloom: When I want to do such things, I use `with-redefs` to do such instrumentation |
| 20:25 | hiredman | people just would rather slurp in a string and call eval |
| 20:25 | hiredman | insane |
| 20:25 | hiredman | like, I can't believe hiphiparray does what it does |
| 20:25 | xcthulhu | Okay, maybe you have something else in mind |
| 20:25 | bbloom | hiredman: not in a way that will compose well with other macros (in clojure at least) |
| 20:25 | hiredman | bbloom: I am not so sure of that |
| 20:26 | bbloom | hiredman: i'd be interested to see what you come up with if you attempt to maintain any clj/cljs hybrid projects |
| 20:27 | hiredman | so I never completed this https://github.com/hiredman/hiphip/blob/foo/src/hiphip/impl.clj |
| 20:27 | hiredman | but I started rewriting it at some point with a macro |
| 20:27 | hiredman | it isn't done, so of course I can't say "it works, I have proof" but I think it would |
| 20:27 | bbloom | hiredman: oh yeah, i was using hiphip as a motivating use case, not as a great impl of the idea |
| 20:28 | hiredman | bbloom: the clj/cljs stuff I have no idea |
| 20:28 | bbloom | hiredman: it's much harder b/c of when macros get evaluated, and reader behavior |
| 20:28 | hiredman | sure |
| 20:28 | ghadishayban | i want what hiphip does, but with HOFs, rather than with macro comprehensions |
| 20:28 | bbloom | not just when macros get evaluated, but what environment they get evaluated in too |
| 20:29 | technomancy | cljs has metadata, just no vars? |
| 20:29 | technomancy | *right? |
| 20:29 | hiredman | technomancy: it is complicated, because cljs macros are written in clojure not cljs |
| 20:30 | hiredman | cljs is a whole other kettle of fish |
| 20:30 | technomancy | right... does metadata exist at runtime then? |
| 20:30 | bbloom | hiredman: but that's the parameterized namespace motiviation that is most important to me |
| 20:30 | hiredman | (which I would rather not touch, I mean, have you held a kettle of fish?) |
| 20:30 | bbloom | type specialization can be accomplished in other ways |
| 20:30 | hiredman | least important to me :) |
| 20:31 | ghadishayban | bbloom: HOFs in clojure make type specialization hard |
| 20:31 | technomancy | right; having metadata without vars is a lot less interesting to begin with |
| 20:31 | hiredman | technomancy: I dunno, I mean they could just stick it any old place cause javascript objects |
| 20:31 | bbloom | ghadishayban: more specifically HOF w/o defunctionalization, which is due to the dynamic nature of our runtime |
| 20:31 | hiredman | technomancy: on the other hand the closure compiler will strip it all out anyway |
| 20:31 | ghadishayban | bbloom: defunctionalization? |
| 20:31 | hiredman | λ lifting? |
| 20:32 | bbloom | ghadishayban: compilers for static runtimes will take all higher order functions and turn them in to first order |
| 20:32 | bbloom | https://en.wikipedia.org/wiki/Defunctionalization |
| 20:33 | ghadishayban | bbloom: i see. the way generic functions dispatch in Julia helps too |
| 20:33 | bbloom | ghadishayban: yeah, they have both per function caches and per call site caches |
| 20:33 | ghadishayban | bbloom: not sure if that is the same approach |
| 20:33 | bbloom | gfredericks: we have per function for multimethods and per call site for protocols |
| 20:34 | bbloom | er i mean ghadishayban ^ |
| 20:34 | bbloom | polymorphic caches are not defunctionalization, no |
| 20:35 | bbloom | ghadishayban: the JVM provides the same sort of caching for *virtual* methods |
| 20:35 | ghadishayban | dammit i got bbloomed right when i have to leave |
| 20:36 | bbloom | which i guess all our IFn invokes are, but there are sooo many implementers of IFn.... |
| 20:36 | ghadishayban | back in a bit |
| 20:36 | bbloom | bbloomed == told to read some crazy area of comp sci? lol |
| 20:37 | hiredman | bbloom: ghadishayban has been doing some work invokedynamicing vars (apropos of all the implementors of IFn) |
| 20:38 | jasonjckn | bbloom: do you have a blog? |
| 20:38 | jasonjckn | (link) |
| 20:38 | bbloom | http://www.brandonbloom.name/ |
| 20:38 | jasonjckn | your last name is actually bloom? |
| 20:38 | jasonjckn | nice |
| 20:38 | hiredman | e.g. if invokedynamic worked well, and clojure's IFn casting was replaced with invokedynamic, fns would not have to share an interface, and possibly the jvm optimizations would handle them better |
| 20:38 | bbloom | hiredman: that'd be super nice |
| 20:39 | hiredman | virtual mechanical sympathy |
| 21:11 | sritchie | does anyone remember a library that lets you publish a bunch of modules out of a single project, |
| 21:11 | sritchie | by carving up the source tree? |
| 21:13 | technomancy | sritchie: voom? |
| 21:13 | sritchie | technomancy: not that one… someone had written it for a util library |
| 21:14 | sritchie | so if I have racehub/stripe/x.clj, racehub/stripe/y.clj, racehub/mandrill/z.clj, publishing would generate racehub.stripe, racehub.mandrill, and racehub artifacts |
| 21:14 | sritchie | with proper dependencies between them if necessary |
| 21:18 | xeqi | sritchie: lein-modules? |
| 21:18 | sritchie | xeqi: no, I remember it did it automatically |
| 21:18 | sritchie | I can’t find the damned thing anywhere |
| 21:19 | xeqi | hmm, I only know of #{sub, modules, voom} |
| 21:50 | hiredman | lein-repack |
| 21:51 | hiredman | https://github.com/zcaudate/lein-repack |
| 22:14 | cfleming | ambrosebs: Re arrows (came back late, sorry) - Cursive can probably draw them, but not efficiently. |
| 22:15 | ambrosebs | cfleming: oh cool to know |
| 22:15 | cfleming | ambrosebs: Since you'd have to redraw most of the screen probably. |
| 22:15 | cfleming | ambrosebs: Cursive already highlights uses of items that the cursor is over, although I like the idea of doing the same if a library is selected too. |
| 22:16 | ambrosebs | it would be cool to teach cursive about my own binding macros |
| 22:16 | ambrosebs | somehow :) |
| 22:16 | cfleming | ambrosebs: I'm also thinking about things like setting the background colour of then/else clauses of if to a subtle red/green |
| 22:16 | cfleming | That's coming :-) |
| 22:17 | cfleming | I keep finding new things I need to add to the API as I add inspections and refactorings - once that's stable I'll release |
| 22:17 | cfleming | I also need to migrate the existing code to the parser I showed you |
| 22:18 | cfleming | So it's all consistent. |
| 22:18 | cfleming | All that code will be open source with the API |
| 22:18 | ambrosebs | will I be able to release a core.typed binding macro file that people can just import into cursive? |
| 22:19 | cfleming | Yup |
| 22:19 | ambrosebs | sweet |
| 22:19 | cfleming | I'm probably going to have a public repo that people can contribute to that will be shipped with Cursive, like https://github.com/borisyankov/DefinitelyTyped |
| 22:20 | ambrosebs | fantastic |
| 22:20 | ambrosebs | that will probably work well enough |
| 22:20 | cfleming | But people will also be able to create support for their internal DSLs and provide them to Cursive too. |
| 22:20 | cfleming | There's lots of trickiness about the best way to integrate that into IntelliJ without having everything grind to a halt at startup though. |
| 22:21 | ambrosebs | ya right |
| 22:26 | cfleming | I need to sit down and spend some time with DrRacket, actually |
| 22:26 | cfleming | I read a bunch of papers about things like the macro debugger, but I've never actually used it. |
| 22:26 | ambrosebs | cfleming: the master branch of DrRacket just added Typed Racket mouseovers |
| 22:27 | cfleming | Yeah, I saw that, it looks very like the Typed Clojure support in Cursive actually, someone sent that to me the other day. |
| 22:28 | cfleming | Can they require an explicit "type check this file" step, or can they integrate it more continuously? |
| 22:28 | cfleming | s/Can they/Do they/ |
| 22:28 | ambrosebs | type checking is triggered by macroexpansion :) |
| 22:28 | ambrosebs | #lang typed/racket |
| 22:29 | ambrosebs | the only way to stop type checking is #lang typed/racket/nocheck |
| 22:29 | cfleming | But what I mean is, can the editor do it in real time like IntelliJ would do with Java, for example? |
| 22:29 | ambrosebs | ahh I doubt it |
| 22:29 | cfleming | There you get type errors provided by the IDE, but that means that the IDE basically reimplements the type system. |
| 22:30 | cfleming | I'm still amazed they did that for Scala |
| 22:30 | ambrosebs | are you serious |
| 22:30 | cfleming | Yup |
| 22:30 | ambrosebs | ok I'll just accept that |
| 22:30 | cfleming | The Eclipse IDE has a frankenintegration with the Scala compiler |
| 22:31 | cfleming | The IntelliJ one they wrote it themselves |
| 22:31 | ambrosebs | sheesh |
| 22:32 | cfleming | They do that for basically all the languages they support - Cursive has a lot of knowledge of Clojure semantics built in too |
| 22:32 | ambrosebs | so if there are accurate deltas about what changed in a file I have some ideas how to incrementally type check it without rewriting the checker :P |
| 22:32 | cfleming | Nice, I can get you deltas |
| 22:33 | cfleming | Semantic deltas or text? |
| 22:34 | cfleming | IntelliJ accurately tracks all changes to documents, in fact I already use that to move the annotations around when the file is edited. |
| 22:34 | ambrosebs | what do you mean by the former? |
| 22:36 | cfleming | Whether you would want to receive the forms that had changed, or a list of text ranges that had been updated in the document. |
| 22:36 | cfleming | Text ranges can be converted into forms by just re-parsing, of course. |
| 22:39 | ambrosebs | cfleming: hmm it depends what I do on the core.typed side I guess. |
| 22:39 | cfleming | cfleming: sure, either is relatively trivial. Let me know when you have a clearer idea of what you need and we can try it. |
| 22:39 | cfleming | Ugh, that should have gone to you, not to me, of course, sheesh |
| 22:40 | cfleming | Talking to myself |
| 22:41 | ambrosebs | did you ever get the type querying thing working with cursive? |
| 22:41 | ambrosebs | like local type info for expressions? |
| 22:41 | ambrosebs | IIRC there was some incompatibility with the info I was providing |
| 22:41 | cfleming | No, I just display the errors that are sent back - I can't remember the details. |
| 22:41 | cfleming | I'll check and let you know. |
| 22:42 | cfleming | Got to run |
| 22:42 | ambrosebs | cya! |
| 22:42 | cfleming | Seeya |
| 22:47 | cddr | What would people expect an HTTP collection query (e.g. "/tweets&since=yesterday") to respond with if it found no results? 404 seems wrong if it *might* return a response with different query parameters |
| 22:59 | kenrestivo | i'm pretty sure there's a formal REST specification somewhere that answers that |
| 23:00 | beamso | HTTP status 204 == no result |
| 23:00 | beamso | no content, actually |
| 23:43 | TimMc | cddr: An empty collection. |
| 23:44 | TimMc | The API results should be homogeneous; don't change the "type" of the response based on the query window. |
| 23:51 | Jesterman81 | hey ladies/gents |
| 23:51 | awwaiid | greetings earth/human |
| 23:53 | Jesterman81 | is there a cleaner way of getting the hash of data then the following https://gist.github.com/deefa3a8e7a1f9610b3e.git |
| 23:54 | Jesterman81 | https://gist.github.com/Jesterman81/deefa3a8e7a1f9610b3e |
| 23:54 | Jesterman81 | I’m a clojure noob |
| 23:55 | justin_smith | so you just want the :foo key / val from each map? |
| 23:55 | Jesterman81 | yeah |
| 23:55 | justin_smith | ,(map #(select-keys % [:foo]) [{:foo "foo" :bar "dummy" :axe "blood"} {:foo "baz" :bar "dummy"}]) |
| 23:55 | Jesterman81 | [{:foo “foo} {:foo “bar”}] |
| 23:55 | clojurebot | ({:foo "foo"} {:foo "baz"}) |
| 23:56 | Jesterman81 | thx |
| 23:57 | awwaiid | what are you going to do with those key/value pairs where the key is always what you gave it? |
| 23:57 | Jesterman81 | yes |
| 23:57 | Jesterman81 | I want to elimiate everyting but just the :foo keys and values |
| 23:57 | awwaiid | I mean -- if you only care about the values, you could do #(% :foo) in that map instead |
| 23:58 | Jesterman81 | right…I was just wondering if thats as short as I can get it and I am not missing some destructing or cleaner way |
| 23:58 | justin_smith | awwaiid: btw #(% :foo) can be replaced with :foo for this purpose |
| 23:59 | justin_smith | ,(map :foo [{:foo "foo" :bar "dummy" :axe "blood"} {:foo "baz" :bar "dummy"}]) |
| 23:59 | clojurebot | ("foo" "baz") |