#clojure logs

2014-10-08

00:01myguidingstarwow, I can see lots of 'characters' marching
00:01myguidingstaris this a live broadcast of Hong Kong protest ;)
00:01zaneshttps://gist.github.com/zane/00655f136470458e21e1
00:02zanesSeems useful, but I can’t tell if I’m being crazy.
00:10devnzanes: it was meant to be
00:17dbasch,(apply str (map char (take 10 (repeatedly #(+ 30000 (rand-int 30000))))))
00:17clojurebot"耞텊쁻빻鏚硑箔豶뼕腵"
00:18dbaschaccording to Google Translate that means "Some loss 텊 쁻빻 Qipingbofen 뼕 Jia"
00:20devnI can parse a little bit but...
00:25zanesAre there combinators for transducers other than comp?
00:26zanese.x. (sequence (both (map inc) (map identity) [1 2 3]) ;; => (2 1 3 2 4 3)
00:28beamsoi'm trying to use cljs-ajaxa
00:28beamso*cljs-ajax
00:28beamsoit looks like there were undocumented broken changes
00:29justin_smithzanes: that looks like mapcat / juxt
00:29justin_smith,(mapcat (juxt inc identity) [1 2 3])
00:29clojurebot(2 1 3 2 4 ...)
00:30justin_smithis there a mapcat transducer type?
00:30zanesYeah, that seems right. But I’d like to be able to do that with transducers instead of bare functions.
00:30justin_smithright
00:31justin_smithmapcat has a transducer arity...
00:32justin_smith,(sequence (mapcat (juxt inc identity)) [1 2 3])
00:32clojurebot(2 1 3 2 4 ...)
00:32justin_smiththere we go!
00:33justin_smithand of course that mapcat could be combined with other transducers
00:34zanesRight, but what if inc and identity are themselves transducers?
00:34zanesi.e. What if we want to do filtering and such in there?
00:38TEttinger##(mapcat (juxt inc identity) [1 2 3]) ; dammit justin_smith beat me to it
00:38lazybot⇒ (2 1 3 2 4 3)
00:38TEttinger(inc justin_smith)
00:38lazybot⇒ 89
00:39justin_smithhell I even dug up the transducing version :)
00:56nhanHAfter 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:56zanesI guess what I really want is the transducer version of juxt. I can just compose that with cat.
01:17lukecosseyHey 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:50vIkSiThello all
02:51vIkSiThas anyone here used clojurescript/om?
02:51vIkSiTI'm wracking my head around this now
02:51vIkSiThow do I get component a to auto update, if component b does an ajax fetch?
02:51lukecosseyYeah it's great!
02:52vIkSiTI have an autocomplete module (the standard one) - which fetches data.
02:52vIkSiTI have a "search results" module that knows how to render a query
02:52vIkSiTOr rather, a set of search results
02:52vIkSiTBut I don't know how to update the search results on an event where I click something on the autocomplete widget
02:53vIkSiTSince these are two components, and while they share app state, they are different cursors
02:53vIkSiTlukecossey, any pointers? :)
02:53lukecosseyYou could use core.async channels?
02:53vIkSiTlukecossey, I'm trying to figure out how
02:53vIkSiTfor instance
02:53vIkSiTI can (put! my-chan search-result)
02:53vIkSiTbut how do I get the search results component to "listen" to this?
02:54lukecosseyYou could store the my-chan in the app-state.
02:55vIkSiTbut they have different cursors
02:55vIkSiTeg. (def app-state {:autocompelte [..] :search-results [])
02:56vIkSiTone gets key 1 and the other gets key 2 as their cursors
02:56vIkSiTso they can't reference the other key
02:58lukecosseyYou can pass the complete app state as well as your specific data through when you build the components.
02:58lukecossey(om/build page1-view {:specific cursor1
02:58lukecossey :app-state app-state})
02:58lukecossey(om/build page2-view {:specific cursor2
02:58lukecossey :app-state app-state})
02:58lukecosseyDoes that help at all?
02:59vIkSiTah hmmm
02:59vIkSiTlukecossey, that's interesting - didn't know you could do that. quick orthogonal question
02:59lukecosseyIf the component is defined as (defn page-view [page owner]
02:59vIkSiTcan you specify targets in om/build?
03:00vIkSiTeg, i have a page template built as a static html, but only two divs are om components (id autocomplete and results)
03:00lukecosseyThen you can get the data with (get-in page [:specific])
03:00lukecosseyAnd the app-state with (get-in page [:app-state :autocompelte])
03:00vIkSiTthat makes sense
03:01vIkSiTSo now I would ask
03:01vIkSiTHow does Om know to re-render if that channel changes?
03:01vIkSiTis there some auto pub sub mechanism?
03:03vIkSiTlukecossey, ^ any pointers?
03:04lukecosseySomething like this
03:04lukecosseyom/IWillMount
03:04lukecossey(will-mount [_]
03:04lukecossey (let [my-chan (get-in page [:app-state :my-chan])]
03:04lukecossey (go (while true
03:04lukecossey (do-something-to-search-result (<! my-chan) owner)))))
03:05lukecossey (do-something-to-search-result (<! my-chan))))))*
03:05vIkSiTso will-mount is called every time something changes?
03:06vIkSiTahh
03:06vIkSiTso we initialize this behavior in will-mount wih a go loop.
03:06vIkSiTI'm guessing this is in the search result view. hmm
03:06vIkSiTand then in autocomplete i can populate this channel
03:07vIkSiTlukecossey, is there a way I can force an re-render of the view itself if this channel changes?
03:07lukecosseyhttps://github.com/swannodette/om/wiki/Documentation#iwillmount
03:08esirolahi
03:08lukecosseyYou need to change the state using set-state!
03:08vIkSiTah
03:09lukecosseyso once you receive the data from the channel, set it to (set-state! owner :search-results (<! my-chan))
03:09esirolajust looked hickey's talk on transducers (https://www.youtube.com/watch?v=6mTbuzafcII), very interesting
03:10lukecosseyvIkSiT: and when you are building your search-results-list-view or whatever use (om/get-state owner :search-results).
03:11esirolawill the modified map/reduce/etc enter clojure 1.7?
03:11vIkSiTlukecossey, use that in place of?
03:12lukecosseyvIkSiT, 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:13vIkSiTah I see
03:13vIkSiTtrying to wrap my head around this.
03:13lukecosseyYeah it's tricky when you start, I'm still learning!
03:14vIkSiT:)
03:14lukecosseyThis 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:16vIkSiTlukecossey, that would be awesome
03:18vIkSiTlukecossey, so if I understand correctly
03:19vIkSiTselect-video! sets the state :current-video in the main cursors thats given to that functino as well as the video page view
03:19christian_stammHi! Is it possible to generate doc of test code with lein-marginalia?
03:20vIkSiTand then the set-active! sets that state
03:20vIkSiTand because there's a go loop intiialized in will-mount.
03:22vIkSiTwhich checks the channel that is updated on click.
03:23lukecosseyvIkSiT, 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:23vIkSiTah.
03:23vIkSiTthis is very very veery useful :)
03:23vIkSiTI think I just need ot read through this
03:23vIkSiTI kinda get the feeling for it now hehe
03:23lukecosseyAnd everytime the state is changed the component will re-render
03:24lukecosseyYeah, try get it running to help out with that. It's a wee bit messy, but hopefully it will help!
03:27vIkSiTlukecossey, any examples of where you actually render these views?
03:27vIkSiTusing om/root?
03:28lukecosseyYeah have a look at the core file
03:28lukecosseyhttps://github.com/Secondi/secondi-homepage/blob/develop/src/secondi/core.cljs
03:28kungijustin_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:28lukecosseyIt's a wee bit abstract
03:29vIkSiTah thanks
03:29vIkSiTlukecossey, two more questions for you if you have time :)
03:30vIkSiTone - do you know if each om/build invocation can be given a separate target?
03:30vIkSiTand two - are you using secretary routing with a server side compojure/luminus style routing?
03:43lukecosseyvIkSiT, Yes you can have multiple om roots. Not sure what you mean by targets
03:43lukecosseyWe use Django to serve our cljs applications and nginx for the server side routing I guess?
03:44nonubyis 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:49vIkSiTlukecossey, ah I mean. if I do the following,
03:50vIkSiTom/build ... {:target (document.getElemetbyId ("autocomplete")
03:50vIkSiTlet me paste a gist
03:50vIkSiTlukecossey, https://gist.github.com/viksit/f1e9744a2cda4b0bf9fa
03:51vIkSiTBasically I can either do two calls to om/root
03:51vIkSiTor I can combine them into one app
03:51vIkSiTIn the latter case, I don't know how to tell each om/build to happen in a *Separate* div
03:51vIkSiTby default, evrything gets rednered in the main div
03:54nonubyvIkSit, 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:56vIkSiTnonuby, I could - except, that I have designers who do html design.
03:56nonubyso 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:56vIkSiTnow, either I shift them to using clojurescript :/
03:57vIkSiTor, they give html, and then I inject the dynamic components in there using om
03:57nonubyah i see, Im using jade and kioo to handle that..
03:57vIkSiTnonuby, yeah, theyre doing photoshop -> html, the old way
03:57vIkSiTand I don't think rewriting all that is a good idea
03:57vIkSiTI personally like enlive..
03:57vIkSiTbut yeah
03:58nonubythats 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:58nonubyyou can't just --> you can just
03:58nonubynote kioo syntax not exact, but similar
04:00nonubyvIKSiT, 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:00vIkSiToh kioo can render html?
04:00vIkSiToh i never thought of that
04:00vIkSiTgood point
04:00nonubyif you supply zero transformation, then it will just render the html file
04:01vIkSiTthat is *awesome*
04:01nonubyit does compile time to dom/* (thus using clj enlive under the hood)
04:01vIkSiTnonuby, fantastic
04:01vIkSiTthat does make life a lot easier
04:03nonubykioo 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:04nonubythen you can just use (render [_] (filecomponent "myhtml.html {})
04:04nonubythe last args is the transformations - which ive left empty, but usually want to make some
04:05vIkSiTah
04:05vIkSiTthanks for the info!
04:10mbufwhat is incorrect for this hello world example https://gist.github.com/shakthimaan/f6a501835198f1fd1d07?
04:10mbuf*in this
04:10vIkSiThello mbuf. long time no see.
04:11mbufvIkSiT, hi
04:12nonubymbuf, is core.clj in src/clojure_noob (underscore vs dash)
04:12mbufnonuby, oops, it is src/app/core.clj
04:17mbufnonuby, works now; had to use (ns app.core ...) in core.clj and (:main app.core) in project.clj
04:17mbuflater
04:19nonubyyep your ns will your src path (usually..)
04:33vIkSiTlukecossey, around?
04:33vIkSiTfollowing your example : https://gist.github.com/viksit/353d73081a0152aba0a8
04:33vIkSiTI'm confused about how to implement the "click" button in my autocomplete view.
04:33vIkSiTAny ideas?
04:36nonubyr1 -> app
04:37nonubyactually ignore that, why you are reaching out to r1, shouldnt that be part of your app-state or shared state
04:37vIkSiTnonuby, hmm, im just making this in a way that works
04:38vIkSiTultimately, r/r1 come from xhr calls..
04:38vIkSiTall I want to do is - when i click that button, it does something that makes the search-results-view refresh :)
04:39vIkSiTnonuby, does that make sense btw?
04:53clgvupdate of *loaded-libs* is transactional but actually loading a namespace via `require` is not :(
05:00dysfuni 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:01clgvdysfun: maybe there are multiple versions of midje classpath somehow. did you check "lein deps :tree"
05:01clgvand "lein classpath"?
05:02dysfunodd, midje isn't in 'lein deps :tree', but it's in project.clj
05:02dysfunno, ignore me, i'm in the wrong terminal tab :/
05:54lgrapenthinI 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:11clgvlgrapenthin: you need to use some frontend for nrepl
06:13lgrapenthinclgv: what do you mean? I am wrapping cider middleware server side and jack in via cider from emacs
06:14lgrapenthinshould say connect, not jack in
06:14clgvlgrapenthin: ah you use emacs+cider to communicate with that nrepl instance in your application?
06:14lgrapenthinclgv: yes
06:14clgvlgrapenthin: then check whether "lein repl :connect" works. if it does, you can blame cider
06:15lgrapenthinclgv: I can connect just fine
06:15lgrapenthinit's printing that doesn't work
06:15clgvlgrapenthin: I mean, connect with leiningen repl and try to evaluate the same stuff you tried from cider/emacs
06:15lgrapenthine. g. (doc ...) (println ...) all return nil and print somewhere in netbeans
06:15lgrapenthinevaluation works fine
06:16lgrapenthinso I suppose I have to bind *out* to sth. else
06:16clgvand printing does not work in lein repl as well?
06:16lgrapenthinbut don't know what
06:17clgvyou did bind *out* manually?
06:17lgrapenthinclgv: nope. and lein repl does work
06:17lgrapenthinclgv: apparently
06:18clgvlgrapenthin: I have a working nrepl in my application just via "(nrepl/start-server :port nrepl)"
06:18clgvlgrapenthin: ok, so maybe the printing output ends up in some strange buffer in emacs?
06:18lgrapenthinclgv: me too. and your guess was right. it must be ciders fault
06:19clgvlgrapenthin: I usually check pure lein first when my IDE/editor does strange things with respect to leiningen's feature set
06:20lgrapenthinclgv: hmm. this is strange because when I use nrepl-jack-in cider prints fine
06:21lgrapenthinthanks anyway
06:21clgvlgrapenthin: yeah maybe something differs when you connect to a foreign repl
06:24clgvdidn't nightcode have it's repl and editor as standalone component libraries? or was that some other project?
06:25clgvaah ok, you can use them separately but it is on lib
06:38clgvback 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:41weavejesterclgv: Why do you use a ref?
06:42clgvweavejester: because I need to return the delay instance
06:44weavejesterclgv: Okay… but why go to all that trouble? If you just want a require to be evaluated once, why not using locking?
06:44weavejester*use locking
06:44weavejesterFor that matter, is require thread unsafe?
06:44clgvweavejester: yes it is
06:45clgvweavejester: only *loaded-libs* is managed in a ref but not used to decide whether the actual `load` needs to happen
06:45clgvweavejester: I found this from an actual problem
06:47weavejesterclgv: So why not something like (let [o (Object.)] (fn [ns] (locking o (require ns))))
06:47clgvweavejester: 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:48clgvweavejester: yes but that way everyone must wait
06:48weavejesterclgv: Is there any other safe way of doing it?
06:48weavejesterclgv: If you have namespaces a and b that both depend on c
06:48clgvweavejester: humm right my solution does not account for the fact o transitive namespaces being required in parallel
06:48weavejesterclgv: You’d need to know that you can’t load up a concurrently with b if c is not loaded
06:49clgvweavejester: I wish Clojure had that built-in...
06:49clgvok back to simple locking ...
06:49clgvah well at least I can check what was already loaded.
06:50weavejesterUnless it becomes a performance issue, I’d be tempted just to go for the simplest solution
06:51clgvweavejester: it is an issue. usually I have around 20 threads using this.
06:52weavejesterclgv: What’s the use case? I mean, what are you doing for that to happen?
06:52clgvweavejester: it's a "worker server" implementation
06:53weavejesterclgv: So… you load up worker functions/namespaces on the fly based on messages to the server?
06:53clgvwhich does not know anything about specific implementations and thus can not preload application specific stufff
06:53clgvweavejester: yeah, you can describe it like that
06:53weavejesterclgv: Have you considered using classloaders?
06:54clgvweavejester: not in the current state. I think if I had the time I'd change to single worker jvms
06:56clgvweavejester: 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:57clgvweavejester: I am not entirely sure what the reason is, since these computations share nothing but the implementation. maybe jvm maybe clojure itself
06:57weavejesterclgv: Really? I was under the impression the JVM was pretty good at assigning threads to cores
06:58clgvweavejester: if I remember correctly I had individual task runtimes increased by at least a factor of 2
06:59clgvweavejester: not sure if there are impacts from cpu cache misses and stuff due to 20 parallel executions...
06:59weavejesterclgv: If the server is constantly running, then surely a require would only happen once?
06:59weavejesterclgv: So performance issues would only be limited to the first time it requires a namespace
07:00clgvweavejester: oh these performance figures where not about the `require` but in general
07:00weavejesterclgv: So a concurrent require might not be your problem?
07:01clgvweavejester: no, I switched context without a hint, sorry ;)
07:01clgvweavejester: I am back to https://gist.github.com/guv/ac76b9ab1878705062c6
07:03weavejesterclgv: Why do you use *loaded-libs* directly? Why not (loaded-libs) ?
07:03GonzihHi guys, how should I configure log4j from inside lein plugin?
07:04clgvweavejester: oh damn, I did not find that one. I search clojure.core but seems I missed that one
07:04clgvweavejester: thank you
07:07weavejesterGonzih: Which lein plugin?
07:09clgvGonzih: 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:09Gonzihweavejester: 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:09Gonzihhere is plugin code https://github.com/Gonzih/lein-feeds2imap
07:10clgvGonzih: it probably does not pickup the log4j.properties file
07:11GonzihI have one in dependency library and in plugin src directory
07:11Gonzihis there any way to set properties file using setProperty call?
07:11clgvGonzih: yes. like I said above
07:11clgvGonzih: ah no the properties and not the file ;)
07:13clgvGonzih: there is also Properties.load - not sure if that works on the (System/getProperties)
07:35gnzhclgv: I tried to use clj-logging-config without much success.
07:36clgvgnzh: I have a working solution where I just set the properties via a function. but loading them seems possible as well
07:36gnzhcan you show me example?
07:36gnzhof loading via fn
07:41gnzhclgv: can you? please :)
07:42cYmenWhat do I need to do to install cider-nrepl? I get this error: https://www.refheap.com/4437faae1d2d42f5f2c766670
07:43LauJensenGents. 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:48kungicYmen: include the plugin in your project.clj or profiles.clj
07:48cYmenkungi: I'm not in any project...
07:48kungicYmen: then include it in the user profile of ~/.lein/profiles.clj
07:49justin_smithcYmen: ~/.lein/profiles.clj applies even if not using a project
07:49kungihi justin_smith
07:49justin_smithalso, that message misspells the snapshot name
07:49justin_smith0.8.0-SNAPSHOT
07:49justin_smithkungi: hello
07:49cYmenI don't have that, can either of you provide me with a reasonable default, please? :)
07:50justin_smith{:user {:plugins [[cider-nrepl "0.8.0-SNAPSHOT"]]}}
07:50justin_smiththat goes in ~/.lein/profiles.clj
07:53justin_smithhere'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:54justin_smithand sometimes the latest version of either one will be just plain broken - it's alpha software
07:57jcidahoHi 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:58cYmenjustin_smith: What do you do for a living? :p
08:04justin_smith$mail cYmen backend clojure web developer
08:04lazybotMessage saved.
08:04cYmenBack!
08:05justin_smithheh, you get that message from lazybot?
08:06cYmenjep :)
08:07dnolen_jcidaho: no
08:07cYmenjustin_smith: Apparently this nrepl version does not exist....
08:08cYmencider-nrepl
08:08justin_smithoh sorry
08:08justin_smithit's cider/cider-nrepl
08:08justin_smith{:user {:plugins [[cider/cider-nrepl "0.8.0-SNAPSHOT"]]}}
08:09clgvgnzh: just combine java.lang.System.getProperties, java.util.Properties.load and maybe clojure.io/resource
08:09cYmenjustin_smith: Works. Thanks!
08:35noncomis there any clojure lib that allows to easy record function calls, their parameters and time of happening ?
08:35noncomand then reproduce it.. ?
08:39gfredericksnoncom: what's the use case? debugging? logging?
08:40noncomgfredericks: saving the order of actions to reproduce later.. closer to a save game
08:41noncomjust to be able to play back / stop /pause / modify
08:41noncomrecord user actions i mean
08:41justin_smithnoncom: tools.trace will show arguments / return value, but doesn't record them for replay per se
08:46bacon1989I 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:46bacon1989basically, I need to include a js/console
08:46CookedGryphonIf I were to implement a simple Tuple2 with deftype, what would I need to support to allow destructuring, nth, first, second and last?
08:46ro_stbetter to shim in normal javascript, bacon1989
08:47bacon1989so basically, I hsould just let someone else deal with the issue?
08:47bacon1989I could always just tear the console.log messages out
08:47ro_sti 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:48ro_stbetter to use (enable-console-print!) … (prn …)
08:48dnolen_ro_st: in-ns only works for REPL interaction
08:48dnolen_bacon1989: I'm not sure what you are saying. What does shimming have to do w/ console.log
08:48dnolen_?
08:49noncomCookedGryphon: look at the sources of destructure, nth and other fns ?
08:49ro_stdnolen_: i think he wants to do that fix that makes it safe to console.log in older IE
08:49dnolen_bacon1989: if want to *use* console.log (.log js/console "foo")
08:49noncomCookedGryphon: i have looked at destructure recently
08:49dnolen_bacon1989: (if (exists? js/console) ...)
08:49noncomyou may find it informative
08:50ro_stdnolen_: your webinar code was super handy today. finally got to start using transducers today
08:50ro_stso good.
08:50dnolen_ro_st: sweet
08:51folippiI'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:51folippilojure and become a pro?
08:51ro_stfolippi: 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:52ro_stClojure is still new enough that folks learn it on the job
08:52dnolen_bacon1989: (when (exists? js/console.log) (defn log [varArgs] (.apply js/console js/console js/arguments)))
08:52ro_stthis is true for my whole team and i
08:54folippiOk, that's reassuring ro_st :). I'll gather some confidence and go for it!
08:54ro_stfolippi: having said that, it certainly wouldn't hurt to hack on some opensource and demonstrate some knowledge with the paradigm
08:54folippiro_st: right
08:55ro_stdo you have any experience at all?
08:55ro_stif not, clojurekoans.com is a great place to start
08:56bacon1989dnolen_: neat, thank you
08:56kungiHaving 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:56folippiro_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:57bacon1989dnolen_: but with that method, wouldn't I need to start using the log function?
08:57ro_stfolippi: you might consider skipping emacs and using cursiveclojure.com instead
08:57bacon1989not that that's a big deal
08:57kungifolippi: have you tried evil mode? It's a very neat vim emulation in emacs
08:58dnolen_bacon1989: ah you want the JS-ism
08:58folippikungi: tried to set it up but gave up. And I figure learning the 'real' way before would be a good idea
08:58ro_stfolippi: Timothy Baldridge has a nice overview here https://tbaldridge.pivotshare.com/media/overview-of-cursive-clojure/9349/feature
08:58dnolen_(def (set! (.-console js/window) (fn [...] ...)))
08:58kungifolippi: 'real' way?
08:58folippiro_st: that looks really really neat! Thanks for sharing
08:58bacon1989dnolen_: 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:58ro_stand one for clojurescript https://tbaldridge.pivotshare.com/media/cursive-and-clojurescript/12952/feature
08:58folippikungi: well well ;)
08:59ro_sti did the emacs gauntlet and use it daily, but cursive is getting more and more appealing as an alternative
08:59dnolen_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:00ro_stfolippi: lots of stuff to explore at www.stuttaford.me/codex/. courses, books, talks, screencasts. jump in and make something :-)
09:00dnolen_bacon1989: and that should have been (set! (.-console js/window) #js {:log (fn [...] ...) :error ...})
09:00bacon1989well, it's only being used for subscriptions that don't provide a callback
09:00bacon1989in otherwords, it doesn't affect production code
09:01bacon1989it's specifically for when developing
09:01dnolen_bacon1989: k makes more sense
09:01bacon1989https://github.com/benzap/flyer.js/blob/master/src-cljs/flyer/messaging.cljs#L19
09:02bacon1989yeah, I could probably take it out
09:26CookedGryphonHow does one make a deftype'd class available to java at aot compile time?
09:29justin_smithCookedGryphon: clojure aot doesn't use javac does it?
09:30CookedGryphonUmm...
09:34cddrHey folks, what do you think of this idea? https://github.com/cddr/crud
09:35ro_stcddr: have you looked at liberator?
09:35ordnungswidrigI like it (even if you don't use liberator)
09:35ordnungswidrigBut beware that CRUD does not match web/http and rest very good.
09:36ro_stsame. 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:38ordnungswidrigHowever, 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:40cddrordnungswidrig: There's a CRUD/HTTP impedence mismatch? How so?
09:40ordnungswidrigPUT is more like Create or Update
09:40ordnungswidrigand POST is not necessarily create
09:43cddrHm, maybe I should change the name because I definitely want it to be "RESTy"
09:43kungihi ordnungswidrig
09:44ordnungswidrig:-)
09:46kungiordnungswidrig: Can I somehow remove a dependency from the classpath at runtime? With pomegranate I can add one but ...
09:51xeqikungi: theres nothing built to do it currently
09:52xeqiit'd take a lot of classloader fiddling
09:52ordnungswidrigjust restart the repl
09:57kungiordnungswidrig: that is sadly not an option in this case
09:57kungixeqi: hmm ok thank you
09:58justin_smithkungi: what end would removing an item from the classpath achieve?
09:59kungijustin_smith: for example unloading a plugin at runtime and make it not reloadable any more
10:01stuartsierrakungi: 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:02TimMcSeveral Clojure programmers I know are even now sinking slowly into that tarpit.
10:03kungiTimMc: the OSGi tarpit?
10:03TimMcyeah
10:03borkdudeI saw a slide somewhere that said NOOSGi (as a feature)
10:04TimMcThat'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:17clgvyou could talk to laurent petit about what impact OSGi had on for Counterclockwise development
11:01AeroNotixasd
11:06kungiAeroNotix: f
11:06AeroNotixkungi: aaioun
11:06kungiuiae
11:07ordnungswidrigäöü
11:08kungiordnungswidrig: The germans are coming with their umlauts ...
11:09kungiHopefully at least someone I dont't know will attend our user group meeting this evening :-)
11:10winkß
11:10ordnungswidrig☃☃☃
11:10ordnungswidrig*SCNR*
11:11winkhehe
11:11winkI don't have that on my keyboard. only λ, µ and …
11:11karlsõ
11:11kungiνρτδψγφϕ
11:12CookedGryphonWith 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:12CookedGryphon(.write writer (str a b c)) or (.write writer a)(.write writer b)(.write writer c)
11:33ordnungswidrigwink: copy it form here http://unicodesnowmanforyou.com/
11:33winkboo
11:34kungiwink: where are you from?
11:38mikerodIs 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:38Bronsamikerod: yeah
11:38mikerodI know there has to be more overhead to going through the AFn.applyToHelper
11:39gfredericksmikerod: also sequence construction/traversal
11:39mikerodbut is something like this preventing some good JVM optimizations from happening?
11:39winkordnungswidrig: there you have it. caps-n is now ☃
11:39mikerodI end up seeing profiling showing me a lot of PersistentList#first happening
11:39winkkungi: Germany
11:39Bronsayou're definitely preventing some clojure optimizations too
11:39mikerodfrom the applyToHelper
11:39mikerodYikes, I never knew this
11:39kungiwink: yes I am aware of that where in germany
11:39mikerodI guess it is obvious
11:40Bronsamikerod: only in some cases though, e.g. when using a primitive function or a protocol function
11:40mikerodBronsa: gfredericks thanks for the feedback. Looks like I need to play around with restructuring this code a bit.
11:40Bronsaor an inlineable one
11:40mikerodBronsa: oh... it is a protocol function...
11:40winkkungi: why are you aware? because I can type ß? ;) Munich it is
11:40mikerodnow that I think of it
11:41kungiwink: yes because you have an ß on your keyboard.
11:41kungiwink: I am from Mannheim
11:41Bronsamikerod: direct protocol invocations have a callsite cache
11:41mikerodI didn't see anything from the profiling that "looked protocol-fn'ish", but who knows if it'd show up
11:41clgvhumm, neithder wink nor kungi are on #clojure.de ...
11:41mikerodBronsa: Yeah, I've seen some of this in the compiler before. I definitely haven't dug into the details though.
11:41winkkungi: I have us-intl with a custom xmodmap :P
11:41kungiclgv: there is a clojure.de?
11:42winkclgv: didn't know it existed until now :D
11:44mikerodBronsa: Is there anywhere out there that explains this callsite caching at all?
11:45Bronsano
11:45mikerodBronsa: 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:45mikerodYay. :P
11:46mikerodI don't mind reading the details, but I do love it when I can first come across some design talk/notes or something.
11:56literaryIs 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:56literaryEvery single time, I have to look it up in Dash.
11:58literaryAlso, does Clojure have goto? Right now I have code stored in an anonymous function which I call on two of three cond branches.
12:02csd_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:02literarySo many questions, so few answers.
12:04mdrogaliscsd_: Not that I know of, no, and because AOT is hairy.
12:04mdrogalisAnswered in order.
12:05csd_weird, fair enough
12:05kungicsd_: are the namespaces present in the uberjar?
12:06stuartsierraliterary: Only `cond` uses an :else clause
12:07stuartsierraliterary: No, Clojure does not have anything like goto.
12:07csd_kungi: There were a bunch, but what resolved the problem was doing ^skip-aot to the .core ns that contains -main
12:07literaryOkay I'll try to come up with a mnemonic.
12:07mdrogalisEr, meant to reply to literary, not csd_. Sorry.
12:09kungistuartsierra: 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:09stuartsierrakungi: Yes, you can change the set of directories that `refresh` uses.
12:10stuartsierrakungi: http://clojure.github.io/tools.namespace/#clojure.tools.namespace.repl/set-refresh-dirs
12:10mr_rmI'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:12literary"C.O.N.D. = continuously obeisant, never diacritic"
12:12literaryno that won't do
12:12literary"COND -> can't otherwise notify deadra"
12:13literarythis is hard
12:13literary"cond uses :else -> cuz otherwise nobody does"
12:13literaryokay that one works.
12:14donbonif_isn't this: (fn [x] true) the same as this: #(true) ?
12:14literarydonbonif_: No.
12:14literarydonbonif_: same as (fn [x] (true))
12:14literary,(#(true))
12:14clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.IFn>
12:14donbonif_ohhhh, that's it. thanks literary
12:14literaryMy pleasure.
12:29mr_rmI'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:40kungistuartsierra: thank you
12:53razum2umcan I destruct a vector like this (let [[x & ys z] (range 10)] (println ys)) ?
12:54razum2umthis obviosly doesnt work but you get the idea?
12:54dnolen_razum2um: you cannot
12:54razum2umdnolen_: so I should use butlast ?
12:54dnolen_razum2um: yes
12:55razum2umbtw, is this a fundamental restriction of ISeq or just wait to be implemented?
12:55razum2umi understand, that in case of lazyseq it realizes it
12:56razum2umbut so butlast does anyway
12:58dnolen_razum2um: I don't personally see the value of supporting this kind of sugar. butlast + last work fine
12:59Bronsadnolen_: by that same logic, first and rest work fine too :) I've had the desire for a destructuring syntax from both ends too
13:00dnolen_Bronsa: first/rest can obviously work relatively efficiently for seqs, not true for this
13:00razum2umdnolen_: still, don't get why not? so ruby does: a, *b, c = (1..10).to_a; b
13:01dnolen_razum2um: anyways, I'm placing my bet now this will never happen :)
13:02Bronsadnolen_: 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:03razum2umBronsa: exactly. I miss map destruction in ruby, it's awesome ;)
13:03Bronsarazum2um: not sure what you mean with that, clojure can already destructure maps
13:03razum2umyes, I know
13:03dnolen_razum2um: rhickey is a relatively perf conscious lang designer - in general sugary constructs with linear complexity are avoided
13:04Bronsarazum2um: ah yeah I get it now
13:07razum2umdnolen_: 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:08razum2umunder the hood it will be the same as actuall call but more concise
13:08razum2umdnolen_: btw, it this behaviour doable by macros?
13:08dnolen_razum2um: your idea doesn't seem to jive with future or deref'ing patterns that already exist in the language
13:09dnolen_razum2um: no implicit future would need compiler support
13:11razum2umdnolen_: mm, look it doen't need to be actual IDeref, it can be just transformed in the scope somehow to @c
13:11razum2umby parser i mean
13:11dnolen_razum2um: which doesn't address it being returned as a value
13:12razum2umdnolen_: sorry, don't understand you
13:12devnGiven 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:12dnolen_razum2um: if it escapes the let binding i.e. gets returned as a value
13:17razum2umdnolen_: 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:17dnolen_razum2um: if you can't solve escaping, the other parts don't really matter
13:19razum2umdnolen_: 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:20razum2umactually i mean [a &b _]
13:21razum2umotherwise [a &b c] - parser can (should) realize b and get last one
13:21kungiIs there a refactoring tool to rename symbols project wide in emacs?
13:22dnolen_razum2um: or you could just right a simple function that does this
13:22razum2umdnolen_: hm, yes. perhaps it's best one
13:22dnolen_(defn foo [x & xs] [x (butlast xs) (last xs)])
13:23dnolen_(let [[a b _] (foo (range 10))] ...)
13:24razum2umdnolen_: hm, are you sure xs isn't gtting realized inside foo?
13:24dnolen_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:25razum2um:\ ok, will stay with that, thanks!
13:35cYmenWhat's the preferred browser connected repl these days? Do people still use brepl?
13:35dnolen_cYmen: I do for simple stuff, but Weasel is very popular now
13:37cYmenDifferences? Reasons?
13:38mikerodIn clojure.core/emit-defrecord I was looking at the impl
13:38mikerodThis line particularly regarding hasheq made me think: `(hasheq [this#] (bit-xor ~type-hash (clojure.lang.APersistentMap/mapHasheq this#))
13:38mikerodtype-hash is just (hash classname)
13:38mikerodhow is this guaranteed to not ever collide 2 class names to the same hash
13:39mikerodSo 2 classes, same classname hash and same map contents would be =
13:39Bronsamikerod: hashes don't have to be unique
13:39mikerodBronsa: I know, and if they weren't we could get a false positive for =
13:39mikerodthat's why I'm asking
13:40Bronsamikerod: 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:40mikerodHowever, this is a (hash classname), which I think is really a clojure.lang.Util#hasheq call on a String
13:40mikerodwhich uses Murmur3.hashInt so maybe it isn't likely enough to matter?
13:41Bronsamikerod: no you have a misuinderstanding of how = uses the hash. it's only used as a fast path for not-equality
13:41mikerodBronsa: Oh, duh. I confused what is used by =
13:41mikerod`equiv` is the impl I should have been looking at.
13:42mikerodWhich has a `(identical? (class this#) (class ~gs))` :P
13:42mikerodI sometimes get mixed up in the whole hasheq, equiv, hashCode, equals world
13:44mikerodI 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:44devnHey, 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:45cYmenMan, I wish there was a nice clojure/clojurescript ide for windows.
13:45devnbasically i want to flatten out the children, but have them reference their parent's id
13:45BronsacYmen: have you tried cursive?
13:45justin_smithcYmen: have you tried cursive?
13:45justin_smithhaha
13:45cYmenI've heard about it but I have not
13:45Bronsalol
13:45technomancydoes CCW not handle cljs?
13:46noonianwell... there is always emacs :P
13:46cYmennoonian: Well, I have emacs.
13:46cYmenAnd I just spent forever setting it up on this machine.
13:47arrdemdevn: for is your friend
13:47noonianget your .emacs in version control and your set for life!
13:47cYmenI definitely need to do that...
13:47Bronsanoonian: +1
13:48mikeroddevn: Did you mean to leave off the :id from the second parent?
13:48mikeroddevn: Did you mean that every level of the hierarchy is supposed to have an :id on it?
13:49mikeroddevn: 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:49arrdem+1 mikerod, the first child should probably have an id
13:53mikeroddevn: 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:54arrdemdevn: https://www.refheap.com/91412
13:58dnolen_cYmen: I guess because it uses nREPL & WebSockets? A lot of CLJ/CLJS lein templates now ship w/ it which means less config
14:02technomancygreghendershott: 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:02cflemingcYmen: 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:02technomancygreghendershott: since we don't have the fancy drracket arrow stuff =)
14:02technomancy(carrying over the conversation from another channel)
14:03technomancygreghendershott: also, it's not a requirement to place tests in separate files, just a default
14:03cflemingtechnomancy: 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:04justin_smithgreghendershott: when your symbols are prefixed, it makes refactoring a big namespace (those are the ones you most likely need to refactor) very easy
14:04technomancycfleming: 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:04technomancyeither the arglist or a require form
14:04greghendershotttechnomancy: justin_smith: Thanks, that's helpful to understand the motivation.
14:04cflemingtechnomancy: Nice, thanks
14:05technomancycfleming: the arrows for the stack traces are actually a lot more helpful IMO
14:05cflemingtechnomancy: They indicate where in the source the trace elements come from?
14:05technomancycfleming: right
14:06mikeroddevn: Oh, yeah I meant prewalk there
14:06cflemingtechnomancy: That is cool.
14:06mikeroddevn: https://www.refheap.com/91413 was my prewalk example, I'd probably prefer arrdem style more
14:07technomancygreghendershott: 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_1Hey 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:11arrdem_pr0t0type_1: conj makes no guarantees about order, deferring to conj for behavior
14:11arrdems/conj/into/g
14:12dnolen__pr0t0type_1: depends on the collection, as arrdem says, conj is polymorphic on it's argument
14:12arrdem_pr0t0type_1: some examples http://grimoire.arrdem.com/1.6.0/clojure.core/conj
14:13_pr0t0type_1I see
14:13_pr0t0type_1Thanks guys, this makes sense
14:13arrdemany word on how close we are to 1.7 dropping?
14:14devnarrdem: nested :children won't have :id, it'll need to be added
14:15arrdemdevn: counting from what... the id of the parent?
14:15devnyes
14:15devnit also should include the root as a row
14:15devnwhere parent-id would be nil
14:16cflemingarrdem: 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:16arrdemI would say keep the recursive mapcat of pulling children out and do a zipmap (partial apply assoc)
14:16mi6x3mhow would you name a binding holding a namespace clojure?
14:16mi6x3mn?
14:17arrdemcfleming: yeah I'm feeling sooner rather than later given yesterday's jira noise as well
14:17puredangeryes
14:17justin_smithmi6x3m: well, it can't literally hold a namespace, only the symbol of the ns, since namepsaces are not first class
14:17mi6x3mjustin_smith: well they are in java
14:17llasramjustin_smith: ? &*ns*
14:18llasramMan, always do the wrong syntax: ##*ns*
14:18llasramNo, needs to be a list. Whatever, you get the idea
14:18mi6x3m,*ns*
14:18clojurebot#<Namespace sandbox>
14:18justin_smithright - I appear to be confused, sorry
14:18mi6x3m,(let [n *ns*] n)
14:18clojurebot#<Namespace sandbox>
14:19llasrammi6x3m: A local identifier referring to a namespsace object? I'd call it just `ns`
14:19devnarrdem: example? sorry, not following you on the zipmap partial apply assoc
14:19mi6x3mllasram: I prefer n, but seems to be a matter of taste :)
14:20foodooHi, any recommendations for a Clojure library (maintained) that I can use to send and receive HTTP REST requests?
14:21justin_smithclj-http is decent
14:21arrdemdevn: nevermind. after sketching that out it wouldn't work :P
14:22foodoojustin_smith: thanks. There is just too much choice on clojars
14:22mi6x3mfoodoo: http-kit :)
14:22justin_smithright - and for basic stuff you can even use slurp
14:23justin_smith,(slurp "http://www.google.com&quot;)
14:23clojurebot#<SecurityException java.lang.SecurityException: denied>
14:23justin_smith:P
14:23mi6x3mfoodoo: http-kit offers a client and a server, very easy to use
14:23noonianfoodoo: if you are using http-kit for your server then i'd use their client also just to avoid another dependency
14:24foodooI want to write a client. The server already exists (Cytoscape cyREST)
14:24mr_rmI'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:25ustunozguris 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:25ustunozgurequivalent in underscore is for example _.compact(_.flatten(_.zip(array1, array2)))
14:27bbloom,(mapcat vector [1 2] [3 4 5]) ; maybe something like this
14:27clojurebot(1 3 2 4)
14:27bbloomno still note quite
14:28opqdonutbbloom: no, that stops after two elements
14:28opqdonutI can't think of an easy way to do it
14:29stuartsierrarewrite interleave
14:30opqdonut,(let [a [1 2] b [3 4 5 6]]] (concat (interleave a) (drop (count a) b) (drop (count b) a)))
14:30clojurebot#<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>
14:30opqdonut,(let [a [1 2] b [3 4 5 6]] (concat (interleave a) (drop (count a) b) (drop (count b) a)))
14:30clojurebot(1 2 5 6)
14:30bbloom,(mapcat conj (concat (map vector [1 2]) (repeat [])) [3 4 5])
14:30clojurebot(1 3 2 4 5)
14:31opqdonutheh
14:31opqdonut,(let [a [1 2] b [3 4 5 6]] (concat (interleave a b) (drop (count a) b) (drop (count b) a)))
14:31clojurebot(1 3 2 4 5 ...)
14:31opqdonutthere
14:31opqdonutbbloom: then you need to know which one is shorter
14:31stuartsierra`count` destroys laziness
14:31mi6x3mopqdonut: almost readable :)
14:31opqdonutbbloom: since you can't append repeat [] to both
14:31opqdonutstuartsierra: yeah, a lazy solution would need tobe written from scratch I think
14:32bbloomyeah, coding it recursively with lazy-seq is surely the way to go
14:33mikerodcfleming: I was a bit sad for some of the things pulled from 1.7
14:34mikerodHowever, transducers sooner than later is cool too
14:34arrdemdevn: https://www.refheap.com/91415 cheating with mutable state
14:34ustunozgurthis one (called weave) is by fogus in js: https://github.com/documentcloud/underscore-contrib/blob/master/underscore.array.builders.js#L95
14:35puredangerHey 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:37justin_smithopqdonut: https://www.refheap.com/91416
14:37justin_smithmy attempt
14:37devnarrdem: haha booo!
14:38devnarrdem: we did it with a reduce where we call ourselves and change the initial value
14:38devnbecause we didn't want an atom :)
14:38arrdemdevn: lols. you could do it "purely", but then you can't use mapcat because you need to know how many children were returned
14:38arrdemyeah a reduction and a work queue would be more natural for that approach
14:55michaelmeixnernoob-question
14:55michaelmeixnerI can do:
14:56michaelmeixner(map (fn [x] [x 7]) [:a :b])
14:56michaelmeixnerbut not:
14:56michaelmeixner(map #([% 7]) [:a :b])
14:56michaelmeixnerWhy not?
14:56bbloom,'#([% 7])
14:56clojurebot(fn* [p1__25#] ([p1__25# 7]))
14:56gfredericks#() is not good for returning literals
14:56bbloommichaelmeixner: does that make it clear?
14:57hiredmanpuredanger: 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:57puredangerthen don't check anything :)
14:57gfrederickshiredman: "biological needs"
14:57hiredmanhaha
14:57puredangermaybe I should add "I am using maximum Clojure" :)
14:57puredangerI actually had the same response :)
14:58michaelmeixnerbbloom not clear immediately, but something to think about - thanks!
14:58bbloommichaelmeixner: basically #(...) is short for (fn [...] (...))
14:58bbloommichaelmeixner: note the extra parens
14:58hiredmanthe only thing stopping me from using it more is other people keep writing code in other languages :/
14:58noonianmichaelmeixner: 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:58bbloommichaelmeixner: 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:59michaelmeixneraha!
14:59michaelmeixnerguess i got it
14:59TimMcin fact...
14:59TimMc,(macroexpand-1 '#())
14:59clojurebot(fn* [] ())
14:59TimMc,(#())
14:59clojurebot()
15:00noonianyou could do #(vector % 7)
15:00TimMc#(do [% 7])
15:00noonianor #(vec [% 7])
15:00noonianTimMc: nice! and you've found the usecase for do that does not involve side affects that I couldn't come up with!
15:00noonian(inc TimMc)
15:00lazybot⇒ 73
15:01bbloompuredanger: the usefulness question seems like you're going to get ambiguous answers between usefulness and desired usefulness ... particularly the question about startup performance
15:01bbloomit would be very useful to me if startup performance was better
15:01bbloombut the poor startup performance now is not useful at all :-P
15:01technomancybbloom: yeah, my answers were mixed on those questions
15:02puredangerthat'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:02puredangerat this point, don't want to change anything, will just have to be feedback into next year
15:03justin_smithfor the "what has been more frustrating" would the answer "runtime performance" also include "runtime resource usage" ?
15:03bbloompuredanger: i figured it was too late to change, but worth knowing if the data is funky
15:03puredangerjustin_smith: sure
15:04ustunozgurhaving "I've stopped using it" just after 6+ years is slightly worrying : ) seems like a sequence of events when read top to bottom.
15:08devnIs there a simple way to avoid AOT in a WAR created via ring?
15:09justin_smithdevn: I think at the very least you need a compiled class that the container can invoke
15:09justin_smithbut you could use a shim and avoid all other AOT
15:10bbloomwufoo just ate my cljs survey form
15:10bbloomit said whoops w/ a 500
15:10bbloomnot sure if it went through or not
15:10bbloomform data is lost though :-(
15:10devnjustin_smith: like this? https://gist.github.com/devn/3acd0c210113721eb024
15:11AeroNotixpuredanger: the questions on that survey are a bit weird
15:11AeroNotix"How useful have these aspects been to you" => Performance
15:11devnjustin_smith: this seems messy to me, would be nice to have a simpler way to do this
15:11AeroNotixand then the answers are "Not useful" to "Very useful"
15:11justin_smithdevn: agreed
15:11AeroNotixwhich aspect of performance?
15:12AeroNotixwhat's the scale here?
15:12nullptryeah, how could transducers be "useful" to anyone at this point?
15:12devnjustin_smith: who to talk to? :)
15:12AeroNotixare we answering whether the performance is bad or good?
15:12justin_smithdevn: tbh I have always just done aot to deploy wars, and it always worked
15:12puredangerinterpret it as you will and we will try to make it better next year
15:12AeroNotixpuredanger: ok
15:12AeroNotix"Extensible reader" lolwat?
15:12devnjustin_smith: the problem is when 3rd party libs that aren't AOT safe start getting into the mix
15:12justin_smithdevn: 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:12justin_smithdevn: yeah, that would be a problem
15:13puredangerall 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:13AeroNotixpuredanger: what extensible reader?
15:13puredangertagged literals
15:13AeroNotix^String "fooo" ?
15:13AeroNotixpuredanger: ?
15:13puredangerhttp://clojure.org/reader#The Reader--Tagged Literals
15:14AeroNotixholy shit
15:14arrdemhttp://clojure.org/reader#The%20Reader--Tagged%20Literals
15:14justin_smithdevn: 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:14justin_smithand it's not horrifying levels of ugly
15:15devnjustin_smith: it seems like a patch to lein and/or ring would be a nice fix
15:15justin_smithyes, patching lein and or ring so you don't need the shim would be great - it's also a big task
15:17vermaI 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:17puredangerarrdem: thx, I hate those goofy anchors
15:17vermaand the engine takes care of making sure that the currect javascript objects are manipulated
15:17AeroNotixpuredanger: ok filled it in, where's my cheque :)
15:17arrdempuredanger: <3
15:17vermanow I need to pass in huge amounts of point data into it, but don't want it held up in the state
15:17puredangerAeroNotix: it's in the mail to the address you provided :)
15:18AeroNotixpuredanger: GOOD!
15:18arrdemI wonder where mail addressed to Null goes...
15:18vermathinking of storing stuff in local storage tagged with an ID
15:18vermaand then passing that ID to the renderer
15:18vermathe renderer just reads from local storage
15:18vermaand then clears it out or something
15:18vermaany ideas?
15:19justin_smithverma: have you looked at the "entity component system" design at all?
15:19technomancydevn: patches to lein?
15:20puredangerarrdem: 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&amp;requestId=10519 and release a beta
15:20vermajustin_smith, I think it is sort of similar
15:21arrdempuredanger: feature expressions... glhf
15:21puredangerarrdem: 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:21justin_smithdevn: 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:22devntechnomancy: 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:22puredangerI smell CLJ-322 :)
15:22technomancydevn: I can't think of a decent way to make that happen from lein
15:23puredangerand it distresses me that I did not need to look up that ticket number
15:23justin_smithpuredanger: yeah, that's the real fix, thanks for pointing that out
15:23justin_smith(inc puredanger)
15:23lazybot⇒ 17
15:24arrdemugh. PSA: version your URLs lest your routing scheme become context sensitive
15:24technomancyjustin_smith: if ring shipped with a class file that could defer to a clojure namespace that would do it
15:24technomancyjustin_smith: I mean, probably? I know nothing about war files, but assuming they're like jar entry points
15:25devnhmmmm
15:25justin_smithtechnomancy: 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:25vermajustin_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:26vermajustin_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:26justin_smithverma: 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:26devntechnomancy: what about the generation of that entry point as an option?
15:26justin_smithverma: and I mentioned it exactly because what you are doing already kind of reminded me of it
15:27technomancydevn: why generate one? just include it in ring
15:29justin_smithor write and compile a very small java class that simply uses the java API to spin up clojure and create the handler
15:29weavejesterLein-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:29justin_smithbut that's not much different from the pure clojure shim you already had in that paste
15:29weavejesterI just don’t really use lein-ring these days. I’m trying to give more people commit access
15:29weavejesterI should probably add a note in the README to that effect
15:30vermajustin_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:33vermabasically the incoming state forms "keys" in my render state, if the incoming state has a huge object it becomes a key :P
15:36devnweavejester: would you be opposed to something like we were discussing?
15:36weavejesterdevn: For Lein-Ring, not at all. I might even have an existing issue. I know I’ve mentioned it enough times.
15:36devnweavejester: like: :ring {:aot :none, :handler my.app/handler, :init my.app/init} ?
15:36weavejesterdevn: Why use aot at all?
15:36devnyeah there's an issue here: https://github.com/weavejester/lein-ring/issues/52
15:37weavejesterIf people want AOT, they can explicitly set it using normal Lein options, right?
15:37weavejesterI don’t see any reason not to use a shim instead of AOT to generate the servlet class.
15:38justin_smithyeah, 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:38myguidingstarpuredanger, I've just look at the survey
15:39myguidingstarin the Clojure one: How useful have each of these aspects of Clojure been to you and your projects?
15:39myguidingstarI think logic programming and pattern matching should be mentioned, too
15:39devnweavejester: this brings it back to lein then, no? /cc technomancy
15:39puredangermyguidingstar: those aren't part of the Clojure language though?
15:40weavejesterdevn: lein-ring
15:40myguidingstarwell, I see 'reducer' and 'tranducer' there
15:41puredangermyguidingstar: those are part of the core library
15:41myguidingstarokay
15:41myguidingstarand in the Clojurescript one
15:41myguidingstarin the question Which JavaScript environments do you target?
15:42myguidingstarcan you add ArangoDB's FOXX?
15:42myguidingstarit's similar to CouchDB's but more complete
15:43myguidingstarpuredanger, https://www.arangodb.org/foxx
15:44puredangermyguidingstar: added
15:44myguidingstarmany thanks
15:53myguidingstarpuredanger, in the Clojurescript survey, I find this question unclear: In which contexts do you use each of ClojureScript's optimization settings? :none, :simple ...
15:54puredangeryeah...
15:54devnweavejester: 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:55puredangermyguidingstar: ah, that question did not get correctly transferred from last year's survey, sorry about that
15:56puredangermyguidingstar: 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:57myguidingstarthen?
15:58nullptrpuredanger: most people qualified to answer that question probably interpreted it correctly
15:58justin_smithdevn: hey, that's a good summary
15:59justin_smithdevn: minor nitpick, the text references highlighting, and my pdf reader shows no highlighting (inline pdf display in google chrome)
15:59devnjustin_smith: ah yeah, the highlighting isn't all that helpful fwiw
16:00devnjustin_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:00devnbut im not sure what the story is on the JAR side
16:00csd_Is there a function that will take [vec1], [vec2] and return [{v11 v21} {v12 v22}...]?
16:02justin_smith,(map hash-map [:a :b :c :d :e] [0 1 2 3 4])
16:02clojurebot({:a 0} {:b 1} {:c 2} {:d 3} {:e 4})
16:02justin_smithwhy though?
16:03csd_just trying to simplify a korma statement
16:03justin_smithOK
16:03myguidingstarpuredanger, the order should be: :none, :whitespace, :simple, :advanced
16:03csd_list of ids and a list of values, this way i can combine them into one statement
16:03myguidingstarsorry for being so annoying
16:04puredangermyguidingstar: I'm not going to change that, not sure how changing the ordering affects the data recording
16:04devnjustin_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:04myguidingstarI see
16:04csd_devn: what are you trying to do?
16:05devncsd_: read above. there's a document i referenced.
16:05devncsd_: in short, avoid all AOT in JARs and WARs without needing to create a shim every time.
16:06justin_smithdevn: 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:08technomancydevn: are you trying to avoid all AOT, or just AOT during development?
16:09weavejesterThe servlet shim should go in Lein-Ring, IMO.
16:09weavejesterOr else be a separate library.
16:10weavejesterIt probably doesn’t belong in Ring.
16:10weavejesterAnd definitely doesn’t belong in Lein or Clojure, if that’s been suggested!
16:10hiredmanhttps://github.com/hiredman/lein-ring
16:11justin_smithweavejester: 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:12technomancythere exist simple ways of avoiding dev-time AOT with uberjars. I don't know about wars.
16:12weavejesterjustin_smith: Hm… I’m not sure how that would work, but that’s an interesting idea.
16:12justin_smithtechnomancy: he specified he needed to avoid all aot, even for deployment
16:12weavejestertechnomancy: Lein-Ring currently generates a Clojure AOTed namespace to act as the servlet. It would be better replaced with a Java shim, IMO.
16:13hiredmanhttps://github.com/hiredman/lein-ring/blob/master/java/com/thelastcitadel/Servlet.java
16:13weavejesterhiredman: Are you working on a PR?
16:14hiredmanno, I deleted a bunch of stuff
16:14technomancyhm; ok. nearly all the AOT issues I've seen so far are due to reloading, so AOT strictly for uberjars sidesteps that.
16:14technomancybut there could be other issues I'm unaware of
16:14justin_smithtechnomancy: something about libs that break when aot-compiled
16:14technomancyjustin_smith: like old versions of core.match?
16:14devnthird party libs are not always guaranteed to be AOT friendly
16:15hiredmanweavejester: I don't want any of the dev middleware or the browser launching whatever
16:15technomancyseems like this is just routing around the root issue
16:15justin_smithhiredman: that java shim looks like a good way to approach it
16:15devntechnomancy: but what is the alternative?
16:15hiredmanand I am not actively working on it, I forked, sliced it up, and have started using it for my stuff
16:15weavejesterhiredman: Okay, but none of that’s added to the war file anyway.
16:16technomancydevn: if a library has bugs they should be fixed?
16:16dbaschI had trouble AOT’ing apps to run on hadoop
16:16technomancyI mean obviously the real world isn't that simple, but this should be considered a workaround rather than a long-term solution
16:16devntechnomancy: totally agreed, but for now, i think the workaround is preferred
16:16technomancysure
16:17justin_smithtechnomancy: 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:17AeroNotixany recommendations for graphing libraries?
16:17devnAeroNotix: rhizome
16:18dbaschparkour in particular does some compile-time reflection using the hadoop library you’re compiling against
16:18AeroNotixdevn: looks nice, but not for my use-case
16:19devnwait, where did puredanger mention non-transitive AOT?
16:19puredangerhttp://dev.clojure.org/jira/browse/CLJ-322
16:20technomancyjustin_smith: given its low issue ID, odds are low?
16:20puredangerI think if it had a consensus approach, could definitely move forward. not sure if that exists though.
16:24devnpuredanger: i haven't read the whole thread in detail, but has rich peeked at this ticket recently?
16:24technomancyheh, yeah... this is assembla-old
16:25devni only ask because there's one person in particular who can achieve consensus by using his fist :)
16:25amalloychuck norris is a clojure developer?
16:25devnthat would be roundhouse kicks ;D
16:25bbloom"assembla-old" is an amusing phrase
16:26devntechnomancy: so, did i hear right that you wouldn't be totally opposed to having a workaround in lein?
16:26technomancydevn: there sort of is a workaround in lein
16:26technomancyit breaks a bunch of things though
16:27technomancy:clean-non-project-classes
16:27devnwhat is the workaround, and what does it break? :)
16:27technomancyiirc the problem is protocol functions don't gracefully fall back when they're AOT'd but refer to namespaces that aren't
16:27technomancyso just don't use protocols; problem solved =)
16:27devnhaha
16:28technomancyI don't want to put anything war-specific in lein though
16:28puredangerdevn: 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:28justin_smithdevn: 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:29justin_smithr
16:29devnpuredanger: much obliged for the info
16:29weavejesterI don’t think it’s really a good idea to put a workaround in Lein if it can be fixed in Lein-Ring.
16:30devnwe'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:32devni 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:32technomancydevn: actually for uberjars that's not true either
16:32devnwhich part?
16:32technomancydevn: set :main clojure.core, then launch it with -m my.ns
16:32devnyes, i forgot to mention that in this doc
16:33technomancyAOT is only required for uberjars if you need it to launch using bare `java -jar ...`
16:33technomancyor rather, you need a shim, but you already have one =)
16:33devntechnomancy: yes, we do need/want to java -jar them
16:34technomancydevn: gotcha. there is lein-otf for that, but it may have bitrotten due to the -m approach being simpler
16:37devntechnomancy: thanks
16:38christop1ehrm, got disconnected. Contracters shortcircuited the place -_-
16:41cYmenAbout 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:46devntechnomancy: 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:47technomancydevn: you mean two workarounds?
16:47devni think im confusing myself now.
16:48devntechnomancy: 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:48technomancywe'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:48devnone where*
16:50devn1) 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:50devntechnomancy: ^
16:51technomancydevn: if the shim is just a class file, why does it belong in lein? why not just add it to :dependencies?
16:51technomancyI 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:52technomancyoh... 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:54technomancy(just put user.clj in a :source-paths element that is only included in the uberjar profile)
16:55devntechnomancy: why user.clj?
16:56technomancydevn: otherwise clojure.main will just drop you into a repl when used as Main-Class
16:58technomancyit's just that this seems like a project-space concern
16:59jeffterrellI just read this: http://pastebin.com/bSW5dfRQ — about how HN stores session state in closures.
16:59jeffterrellJust curious, is it possible to store closures in Clojure?
17:00hiredmanno
17:01technomancysort of, but not really
17:01jeffterrellWhy not? Is it a fundamental limitation of e.g. the JVM, or is it just that nobody needed to do it yet?
17:01amalloyis that still true, jeffterrell? i thought they had switched to a more common method of storing sessions
17:01jeffterrellThey have, as of recently. The link above discusses the transition.
17:01technomancyI thought they closed over continuations specifically
17:02hiredmanstoring closures is gross for a number of reasons, a closure is tied to the executable state of a machine
17:02jeffterrelltechnomancy: That _seems_ to be what's going on, yes. I'm not clear on the details, and I don't deeply understand continuations.
17:02jeffterrellhiredman: True, but it seems like a worthwhile tradeoff to avoid database/serialization/etc issues when starting out a project.
17:02turbofailno, they're just closures, written in continuation passing style
17:02ordnungswidrighmm, can closures be persistet (in arc) over process restarts?
17:02technomancyhuh
17:02hiredmanjeffterrell: no no, it just makes those issuses worse
17:02ordnungswidrigI mean, what if they reboot the machine?
17:03jeffterrellordnungswidrig: Maybe with their new architecture, but with the old one, they were just stored in RAM.
17:03ordnungswidrigfrightening.
17:03hiredmanthe problem is vms like the jvm generally don't provide a way to serialize and pass around the state of the machine
17:03jeffterrellordnungswidrig: That's why you would occasionally (mostly before the new architecture; see link) see "link expired" messages.
17:03technomancyordnungswidrig: or like ... used a load balancer?
17:03technomancyyeah, it's a mess
17:04technomancyhow not to scale an http service
17:04ordnungswidrigyou don't need a link balancer when you can hold your state in ram :-)
17:04turbofailif you could serialize the closures, you could store them in redis or something
17:04dbaschordnungswidrig: 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:04technomancyoh that's right; netsplits are a myth =)
17:05hiredmanyou have to serialize basically the whole object graph from the closure
17:05hiredmanlike, why? just use a session
17:05hiredmanyou won't feel as cool, but you won't want to rip it out and rewrite it in a month
17:06turbofailwell it'd also be nice if you could write something that will automatically put relevant closure variables into a session
17:06turbofaili believe the racket web framework offers something that can do that
17:07turbofailof course a better solution is to just not have so much damn state in the first place
17:08hiredmanor you spin up a machine / process / vm / etc per user and just always route them to the same one
17:08dbaschplus it’s not like there are that many cases of the “next 30 stories.”
17:08ordnungswidrighiredman: no no, nowadays you spin up a docker container
17:09hiredman(http://research.microsoft.com/pubs/210931/orleans-msr-tr-2014-41.pdf)
17:09jeffterrellIt'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:09jeffterrellIf 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:10ordnungswidrigI'm popping out. Please leave a not when you came to some sane conclusion :-)
17:10technomancyjeffterrell: does it really save time vs cookie store though?
17:10aztakhowdy 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:11jeffterrelltechnomancy: 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:11turbofailtechnomancy: well using a cookie store is basically the same thing except you have to manually record the state into a cookie
17:12turbofailand extract it later
17:12ghadishaybanaztak: seems fine to me
17:12clojurebotCool story bro.
17:12technomancyturbofail: that middleware ships with ring iirc
17:12justin_smithaztak: #(= 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:12technomancyjust return :session in the response map and your'e done
17:12jeffterrellclojurebot: You're like a child, wandering into a theater…
17:12clojurebotexcusez-moi
17:13turbofailtechnomancy: well you still need to put your environment into that session
17:13ghadishaybanaztak: 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:13ghadishaybanHOD == Higher-order Diarrhea
17:13aztakjustin_smith: ah, that's a nice approach. But I agree - It's perhaps less readable.
17:13technomancyturbofail: IME that falls naturally out of the functional approach
17:14technomancybut I have limited experience with web apps
17:14aztakghadishayban & justin_smith - thanks for having a look :) And thanks for the suggestions.
17:15turbofaili 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:15turbofailwell not serialized in this case
17:16turbofailthere's certainly cases where it would give some value-add over stuffing things into sessions
17:16dbaschaztak: I’d write (for [d data :when (not= unwanted-id (:id d)] (dissoc d :auth_token))
17:19aztakdbasch: argh - list comprehensions, I haven't reached that chapter yet *grin*. Interesting approach though. In a way it's more readable I guess.
17:19ghadishaybani actually prefer not using the comprehensions
17:19ghadishaybanit buries the actual kernel of logic somewhere in the syntax
17:20ghadishaybanand you have to name extra things, not fun
17:20dbaschit depends on how you express it, because abuse of arrows and comp could make it even less readable
17:20ghadishaybantotally legit approach though
17:20ghadishaybanyup HOD
17:21ghadishayban(I really want that term to catch on)
17:22ghadishaybanimpl-wise low-level, the 'for' macro does emit a ton of code
17:23ghadishayban,(for [a (range) b a c b d c e d f e] (inc a))
17:23clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>
17:27ghadishaybanargh CLJ-1322 has the bug
17:28vIkSiThello all
17:28vIkSiThow do I get a key from a cljs.core/PersistentArrayMap ?
17:28vIkSiTor rather, the value for a given key
17:29vIkSiTI got a native js object on which I ran a js->clj
17:29vIkSiTBut using keys, get, aget - none of that works
17:29dnolen_vIkSiT: they are just maps, get should work
17:29dnolen_vIkSiT: if it doesn't work need to see a minimal example
17:30joeltseems like Clojure/script is picking up a little steam job-wise
17:33vIkSiTdnolen_, just a sec, pasting a gist here
17:38literaryIs it okay to use :goto as a final clause in (cond) instead of :else?
17:39technomancydefine "okay"?
17:39justin_smithliterary: anything truthy works, :goto is misleading though
17:39literaryWhat about :fail ?
17:39pjstadig:these-arent-the-droids-youre-looking-for
17:39justin_smith,(cond nil :nope false :umm "Whatever" :OK)
17:39clojurebot:OK
17:39noonianliterary: short answer is yes :)
17:39literaryOr :never-reaches-this-line
17:40technomancy
17:40noonian:wth-just-happened?
17:40literary,(cond :cond 3)
17:40clojurebot3
17:40literaryWhat is the best word for this?
17:40vIkSiTdnolen_, https://gist.github.com/viksit/106822bdacd7e1d41ec0
17:40vIkSiThere's some sample code.
17:40literaryMaybe :mov
17:40literaryor even :MOV
17:40justin_smithtechnomancy: well :無 would work
17:41literary,:·
17:41clojurebot
17:41vIkSiTto 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:43justin_smithvIkSiT: can you print the keys of a?
17:43justin_smithor, prn them rather
17:43noonian,(keys {:foo "", :msg ""})
17:43clojurebot(:msg :foo)
17:43vIkSiTI get nil
17:43dnolen_vIkSiT: (keys some-array-map)
17:43vIkSiT (prn (keys a)) -> nil
17:44kryftUgh, 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:45vIkSiTargh.
17:45vIkSiTI never thought I'd bitch about parens, but..
17:45vIkSiTwhen I added that "After conversion" line
17:45vIkSiTextra paren.
17:45vIkSiTThat closed the [let ..] and of course, everything else is nil
17:46vIkSiTdnolen_, justin_smith - thanks for the help.
17:46dnolen_vIkSiT: np, in general if you see a strange error like this you should go hunting for syntax errors first :)
17:46dnolen_vIkSiT: at this point 1000s of people use ClojureScript this is basic functionality
17:46vIkSiThehe, I figured emacs + paredit was taking care of it.
17:46vIkSiTindeed
17:46dbasch&(cond nil "foo" ::"what")
17:46lazybot⇒ "what"
17:47vIkSiTdnolen_, 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:47vIkSiTwhy should I not be able to build a component with its own target, and have om/root point to say document.body?
17:47dnolen_vIkSiT: :target is only for root, this goes back to how React works
17:48vIkSiThmm
17:48dnolen_vIkSiT: again some limitations are React limitations
17:48nooniankryft: there is a keywordize-keys fn in clojure.walk and there is also a similar one in prismatic's plumbing lib i believe
17:48dnolen_vIkSiT: but you can have multiple roots
17:48vIkSiTso 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:49vIkSiTdnolen_, yeah, I see why that's the case
17:49dnolen_vIkSiT: both roots can share the same atom
17:49dnolen_so they can be coordinated
17:49dnolen_or they can share the same channel - whatever - coordination is not that challenging
17:49kryftnoonian: Ok, thanks!
17:49vIkSiTyeah, I ended up using channels for now rather than IResolve. I couldn't get on-changes working with it.
17:50technomancykeywordize-keys =(
17:50justin_smithtechnomancy: clearly we need wordkeyize-words
17:50technomancyI 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:50technomancyI mean while we're asking for a pony
17:51kryfttechnomancy: Would you suggest something else than keywordize-keys?
17:51dbaschI asked for a pony: better exceptions / error messages
17:51technomancykryft: keywordize-keys should be generalized to map-vals, but that doesn't exist, which makes me sad.
17:51kryfttechnomancy: Ah :)
17:52technomancydbasch: I would have put that, but it's hard to classify it as a language feature
17:52arrdemdbasch: I asked for a bigger pony... official docs to kill Grimoire/ClojureDocs :P
17:52technomancy*map-keys rather
17:52dnolen_vIkSiT: probably wise IResolve is not fully baked
17:52justin_smithkryft: why do the keys need to be keywords? doesn't the double translation just make everything more brittle?
17:52technomancy(def keywordize-keys (partial map-keys keyword)) ; done
17:52puredangerdbasch: 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:52dnolen_vIkSiT: channels/callback via :shared are a good solution to many problems
17:53puredangerI'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:53vIkSiTdnolen_, indeed - this is what I have now : https://gist.github.com/viksit/353d73081a0152aba0a8
17:53technomancypuredanger: there's just so many obvious fixes it's hard to know where to begin though
17:53technomancyalso, it was like a one-line field
17:53technomancyin the survey
17:53dbaschpuredanger: agree, it’s more about pointing out specific exceptions that could be more informative
17:53kryftjustin_smith: The keys correspond to columns in an SQL database, and jdbc/query returns a map with keywords corresponding to column names
17:54nooniantechnomancy: map-vals is also in prismatic's plumbing lib heh
17:54Bronsamap-vals and map-keys should be a thing
17:55dbasch(inc map-vals)
17:55lazybot⇒ 2
17:55puredangertechnomancy: dbasch: there are specific exceptions improved (generally ones with higher votes) every release yet we never seem to escape this complaint
17:55Bronsahttps://github.com/search?utf8=✓&amp;q=defn+map-vals&amp;type=Code&amp;ref=searchresults
17:55puredanger(also, I am highly in favor of map-keys and map-vals being in core)
17:55kryftjustin_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:56AeroNotixpuredanger: same
17:56AeroNotixit's a very common thing to want to do
17:56puredangertechnomancy: 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:56justin_smithkryft: there is an optional keyword argument to cheshire/read-string to make the keys keywords - perhaps your middleware has a similar option
17:56dbaschpuredanger: 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:57dbaschthat’s really true of all software
17:57puredangerdbasch: but I don't see that complaint about other languages so I take it as an actual complaint here
17:58technomancypuredanger: spend a bit of time talking with people who haven't already built up mental scar tissue around the problem, I'd say
17:58Bronsauhm I actually called map-vals update-vals in t.a
17:59kryftjustin_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:59kryftjustin_smith: Anyway, manually calling keywordize-keys should work well enough for now.
17:59justin_smithOK
18:01nooniankryft: you could pretty easily make your own middleware that calls keywordize-keys also
18:01TimMcDown with keywordizing!
18:02justin_smithpuredanger: 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:02kryftnoonian: Right
18:03justin_smithpuredanger: throw in a few anonymous functions with auto-generated names into the mix, and it's all pretty intimidating at first
18:03puredangerjustin_smith: how can we capture data around that situation to understand what needs to be fixed
18:03puredangerjustin_smith: as of next alpha, the anon-generated names are slightly more helpful (thanks Bronsa !)
18:03justin_smithoh, cool
18:04justin_smithpuredanger: not sure - maybe dev time assertions about inputs? But that seems to conflict with the prevalent clojure coding style.
18:05puredangerjustin_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:05justin_smithright
18:06puredangerhere's a list of errormsg tickets in jira http://dev.clojure.org/jira/secure/IssueNavigator.jspa?reset=true&amp;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:06justin_smithpuredanger: just spitballing, but a mechanism that defined a run time check, and reliably stripped checks when building an artifact would be nice
18:06Bronsapuredanger: my guess is that that's because nobody uses JIRA
18:07technomancyBronsa: yeah, I stopped voting on things a while ago
18:07puredangerwell I use it :)
18:07puredangerand in particular I use votes to decide what gets triaged, so...
18:07Bronsapuredanger: yeah me too, but my point is that the community just doesn't vote on tickets because most feel it's kinda useless
18:08puredangerwe 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:08puredangerso I'm telling you (as the one that makes those decisions), that it's useful
18:08TimMcThat's good to hear.
18:08puredangerI look those numbers every day
18:09TimMcI usually fail to vote because I find Clojure bugs on my work computer but have Jira login info on my home computer. :-P
18:09puredangerTimMc: that is outside my ability to fix :)
18:09puredangergotta run….
18:10TimMcfixing it now :-P
18:10puredangerI also watch Andy's report: http://jafingerhut.github.io/clj-ticket-status/CLJ-top-tickets-by-weighted-vote.html
18:10Bronsapuredanger: I wasn't questioning that, just making you aware that a big chunk of the community doesn't know the value of voting
18:10danneukryft: just apply the wrap-json-params middleware before the ring.middleware.keyword-params/wrap-keyword-prams middleware that you're probably already using
18:10puredangerBronsa: noted, and will try to re-assert the value of that more
18:12kryftdanneu: 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:12xeqiI'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:13noonianso you just need two more middleware to move :params to :proto-params and back again!
18:14kryft:D
18:14xeqipuredanger: is there a way to see what I've voted on?
18:14noonianbut at this point thats a lot of work just to use someone elses middleware hehe
18:15kryftnoonian: 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:16danneukryft: huh? wrap-json-params updates the :params map. wrap-keyword-params updates the :params map
18:17kryftdanneu: 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:17kryftThat confused me for a while too
18:18danneuhow can i repro that
18:18weavejesterwrap-json-params should put all of the properties in params
18:18weavejesterI believe it’s just a merge
18:19weavejesterGenerally speaking wrap-json-body is a better middleware to use
18:19weavejesterUnless you have specific needs
18:19danneui use wrap-json-params -> wrap-keyword-params on my json apis and it works ifne
18:20kryftdanneu: Well, I posted {"signup_form":[], "title" : "Foo", event_id : 7} from the browser, and :params was missing the signup_form property
18:22kryftweavejester: I think I was using wrap-json-params because friend expected it
18:23danneukryft: what happens when you (cheshire.core/decode <your browser string>)
18:26muraiki_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:27muraiki_since there's a state machine error I imagine I'm doing something wrong with (go)
18:27weavejestermuraiki: It looks like you’re sending nil into your channel, which causes an exception
18:27justin_smithmuraiki_: do you have a full stacktrace?
18:27muraiki_the full stacktrace is posted as a comment at the bottom of the gist
18:28justin_smithoh, now I see it, thanks
18:28kryftdanneu: (decode "{\"signup_form\":[],\"title\":\"foo\",\"event_id\":7}") produces {"signup_form" [], "title" "foo", "event_id" 7}
18:29muraiki_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:30danneukryft: drop some `prn`s into your middleware stack and look at the actual vals coming over the wire
18:30danneu(prn request)
18:30danneu((fn [handler] (fn [req] (prn req) (handler req)))
18:31danneuensure content-type is 'application/json'
18:32ghadishaybanmuraiki_: 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:32ghadishaybanbut it may have been non-async (normal) fn call that did it
18:32muraiki_ghadishayban: thanks, that's good to know. :)
18:32ghadishaybanthe stacktrace shows line 43, which is (is-diff? (data/diff res (url-name @last-state))
18:32muraiki_weavejester is right, there appears to be a nil going on the channel
18:33ghadishaybanI'd try to duplicate it minimally
18:33muraiki_does my (<! (timeout 10000)) put a nil on the channel? what I'm trying to do is to block for 10 seconds
18:33ghadishaybanno
18:34ghadishaybanthat is fine, it's a take from a channel
18:34ghadishaybanthe only thing putting onto a channel in your source is L64
18:36kryftdanneu: Yup, the content-type is "application/json; charset=utf-8" for the relevant post requests
18:36ghadishaybanAlso, putting a nil on the channel results in a different exception, you'll see a clear "Can't put nil on channel"
18:36muraiki_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/&quot;}]
18:36muraiki_oh ok, thank you
18:36kryftdanneu: I do also see all properties in both :params and :json-params in the prn after wrap-json-params
18:37ghadishaybanmuraiki_: so in your code you must ascertain that make-req never returns nil
18:37danielcomptonIn clj 1.7 alpha 2, why would partition not have a 1 arg arity that returns a transducer?
18:37danielcomptonpartition-by and partition-all both do
18:38muraiki_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:38ghadishaybanpartition 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:38muraiki_oops, messaged myself :n
18:38danneukryft: if your :params map has nonkeyword keys in your routes, then wrap-keyword-params is getting the request before wrap-json-params
18:39jeffterrellpuredanger: 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://…&quot; 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:39jeffterrelltheir 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:39jeffterrellArg, puredanger left the room. IRC veterans, what does one typically do in a case like this?
18:40justin_smith$mail jeffterrell via lazybot
18:40lazybotMessage saved.
18:40technomancyjeffterrell: you could do that in an nrepl middleware
18:40technomancyit doesn't need to be part of clojure
18:40ghadishaybanjeffterrell: which case specifically?
18:40kryftdanneu: 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:40technomancywith nrepl-discover you could even prompt (do you want to report a usability bug) interactively
18:41dbasch(inc technomancy) ;; that’s a great idea
18:41lazybot⇒ 141
18:42dbaschI’d love to have the time to work on that, or I’d gladly contribute to a bounty for something like it
18:43hiredmanugh
18:43hiredmanterrible
18:43hiredmanI hate those things
18:43danielcomptonghadishayban: ah yes I see now
18:43jeffterrelljustin_smith: Whoa, what does this magical $mail thing do exactly?
18:43hiredmanmy laptop does it, my phone does
18:44jeffterrelltechnomancy: Brilliant! …about the nrepl middleware. That would be way better: no pasting, and automatically report things like Clojure version.
18:44justin_smithjeffterrell: lazybot sends the person a message when they show up again
18:44jeffterrellghadishayban: The case where you reply to somebody after they've left the chatroom, but you want them to see your message somehow.
18:44kryftdanneu: 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:44ghadishaybanoh i see
18:45bja_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:45danneukryft: gist your middleware stack?
18:45dbaschhiredman: as long as it’s opt-in and disabled by default, I think it’s awesome
18:45jeffterrelljustin_smith: nifty! Thanks!
18:45technomancyjust put it in cider-middleware, then hiredman will never see it
18:45technomancy=D
18:45jeffterrell$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://…&quot; 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:45lazybotMessage saved.
18:45jeffterrellpasting 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:46bja_err, not prismatic.core, plumbing.core/defnk
18:47kryftdanneu: https://gist.github.com/kryft/45ce18c0ca7e26092b39
18:47jeffterrellhiredman: 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:47hiredmanjeffterrell: no
18:48hiredmanjeffterrell: in a few months when you know clojure you won't care about it anymore
18:48ghadishaybanjeffterrell: true ^
18:48ghadishaybanthough it would be nice to have a guide for decoding exceptions for users
18:48hiredmanjeffterrell: you are optimizing for the experience of new users, a class of users that basically disapears every two months
18:49jeffterrellhiredman: …and perpetually reappears. :-)
18:49ghadishaybanWhen you see a NullPointer, look at the stack frame just above it
18:49ghadishaybanWhen you see a ClassCastException ... couldn't treat number as ISeq, etc.
18:49hiredmannot 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:50hiredmanyou think such a thing should exist, write the code to do it
18:50ghadishaybanhiredman: he just wants to help future peoples.
18:51hiredmanghadishayban: sure, then write the app and try and get people to use it
18:51ghadishaybanjeffterrell: It will never be accepted in core, but a useful nrepl middleware is promising
18:51dbaschperhaps the way for newbies to enable it is via a template for newbies that could be suggested in tutorials
18:51ghadishaybanyup, agreed.
18:51jeffterrellhiredman: 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:52jeffterrellNor does anybody, for that matter (obviously).
18:52hiredmanjeffterrell: if you don't even like it to work on it, why expect someone else to?
18:52jeffterrellI don't.
18:52ghadishaybanhiredman: just trying to stay positive
18:52hiredmanthen why send puredanger a mail about it?
18:53jeffterrellpuredanger asked for ideas on how to collect data about confusing exception messages. I'm just responding to his request.
18:53ghadishaybanyeah maybe that's too eager. prior art in this area is aviso/pretty
18:53ghadishaybanneed concrete impls and soundness before core will even consider something
18:53ghadishaybanhttps://github.com/AvisoNovate/pretty
18:53dbasch(inc (Math/abs ghadishayban))
18:53lazybot⇒ 1
18:53hiredmanjeffterrell: ok, I guess
18:54dbasch(helping ghadishayban stay positive)
18:54hiredmanjeffterrell: 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:55hiredmanand people who generally are new themselves wringing their hands over the user experience of people new to clojure
18:55jeffterrellhiredman: 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:55danneukryft: what does (prn request) look like after handler/site?
18:55technomancyimagine, that, newbies caring disproportionately about usability
18:55danneufor 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:56hiredmantechnomancy: they care about the usability for someone who doesn't know what they are doing
18:56jeffterrellIf 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:56hiredmantechnomancy: which is why they tend to propose silly things like hiding stacktraces
18:56jeffterrellghadishayban: New lib; thanks for the link.
18:57hiredmanas someone who knows things(or atleast I like to thing I do) having stacktraces around that show me everything is useful
18:58justin_smithtechnomancy: 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:59kryftdanneu: https://gist.github.com/kryft/26faacbb5f39877d9fee
19:00_pr0t0type_1Hey 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:00ghadishaybantrue 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:00kryftdanneu: Everything looks fine after wrap-json-params, but "signup_form" mysteriously disappears from :params some time later.
19:00hiredmandoes being a beginner stink? become an expert, it's super
19:01ghadishaybanJRuby goes to great (incredible) lengths to re-write the stacktrce
19:01bja_(inc hiredman)
19:01lazybot⇒ 57
19:01kryftdanneu: (And I don't see anything weird after handler/site either, but no :params or :json-params there obviously)
19:01hiredmanghadishayban: well, they have to show ruby stacks right?
19:01ghadishaybansi
19:01AeroNotixclojure stacktraces suck and anyone defending them should not be allowed to talk about usability
19:01AeroNotixend of story
19:01ghadishaybanAeroNotix: it's complicated =)
19:02AeroNotixof course it is, nothing about what I said included the fact that it was an easy fix
19:02AeroNotixit's hard and I understand why
19:02AeroNotixbut it still sucks
19:02kryftdanneu: Anyway, I think I have to sleep off this cold :)
19:02danneukryft: break handler/site into its individual middleware. put its wrap*params related stuff at the end of your (-> app ... ) stack
19:02bja__pr0t0type_1, (ns foo (:require [environ.core :refer [env]]) (defn base-url [] (:base-url env)))
19:03seancorfieldAeroNotix: stack traces stop sucking after you get over the initial shock...
19:03AeroNotixseancorfield: 3 years and counting.
19:03_pr0t0type_1bja_: thank you!
19:03seancorfieldand as ghadishayban says, learning to read stacktraces - regardless of language - is a useful skill that I wish more developers had
19:04AeroNotixand that CIDER middleware actually can make things worse sometimes
19:04ghadishaybanand jvm's fast throw
19:05amalloythe 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:05jeffterrellJust to be clear, I don't think anybody's proposing simplified stacktraces. Unless I missed it…
19:06ghadishaybanthe CIDER toggles for hiding / showing info are entirely in user-space
19:06justin_smithright, we have been talking about better error messages - something that complements stack traces and doesn't replace them
19:06cflemingjeffterrell: It's generally the first thing that people propose for making Clojure more newbie-friendly
19:06kryftdanneu: Thanks for helping with the debugging!
19:07ghadishaybanthe aviso library above just does some pretty-printing, aligning of the line numbers
19:07cflemingI agree that stack traces are really not a problem, but I disagree that making Clojure more accessible for newbies is a bad goal.
19:07jeffterrellcfleming: Is there a typical response to such proposals? I'd be interested to read it.
19:07cflemingjeffterrell: 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:07ghadishaybanthe 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:08kryftdanneu: I'll try breaking down compojure.handler/site to its individual middleware later as you suggested
19:08nooniani 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:08ambrosebsthis is the most practical idea i've come up with for improving error messages https://github.com/frenchy64/dynalint
19:08justin_smithnoonian: I came to clj with scheme / common lisp/ ocaml experience, and the stack traces drove me batty
19:08ghadishayban(inc cfleming )
19:08lazybot⇒ 1
19:09justin_smithghadishayban: it's sensetive to spaces
19:09justin_smith(inc cfleming)
19:09lazybot⇒ 3
19:09ghadishaybanHelping newbs shouldn't mean designing for newbs
19:10ghadishaybanrich's example of the guitar hero guitar with 4 buttons...
19:10cflemingghadishayban: Having a powerful language is totally orthogonal to it being easy to use
19:11noonianjustin_smith: yeah, but you will see waaay more stack traces if you don't understand lisp at all than if you do :P
19:11ghadishaybanyeah I am agreeing with you
19:12justin_smithnoonian: and many of the lisper problems actually have decent messages
19:12justin_smith,(let ((a 0) (b 1)) a)
19:12clojurebot#<CompilerException java.lang.IllegalArgumentException: let requires a vector for its binding in sandbox:, compiling:(NO_SOURCE_FILE:0:0)>
19:12jeffterrellambrosebs: That's pretty nifty!
19:12justin_smith(lost count of how many times I did that...)
19:13ambrosebsso yea, that's a very compelling way to improve error messages if you're so inclined.
19:15justin_smith(inc ambrosebs)
19:15lazybot⇒ 10
19:15justin_smithnice
19:19cflemingAnother thing that would make a huge difference IMO would be for clojure.core to use seqex or something similar for its macro parsing.
19:19cflemingi.e. illuminated macros
19:19jeffterrellThat would be sweet.
19:19ambrosebsor just redefine them to use them...
19:20ambrosebssurely that's a library somewhere?
19:20cflemingThat'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:21jeffterrellcfleming: I like it. Any idea about performance implications?
19:21ghadishaybanmacros cost only at load time, so startup
19:22cflemingjeffterrell: No, no idea, sorry. I implemented something similar for Cursive but didn't test the difference. Frankly, I didn't care.
19:22cflemingThe correctness benefits were totally worth it.
19:22ghadishaybancgrand/seqexp is also amazing, and only 200LOC
19:23cflemingYeah, although that only works for regular languages IIRC
19:23technomancydoes it declare version ranges?
19:24cflemingambrosebs: You mean redefine e.g. let to use seqex and then expand to the previous version?
19:25ghadishaybantechnomancy: which?
19:25technomancyghadishayban: cgrand's thingy
19:25technomancybeen burned before
19:25ghadishaybanit doesn't appear to
19:25technomancyprogress =)
19:25bja_ is there a way (other than fork and fix project.clj) to remove the version range declarations in third party libraries?
19:25ambrosebscfleming: yea alter-var-root clojure.core/let to an equivalent macro that's nicer
19:26bja_(or tell lein deps :tree to ignore them)
19:26ambrosebsthere's a bootstrapping issue but it should probably mostly work. dynalint does it for a few macros
19:26technomancybja_: just :exclusions
19:26cfleminginteresting idea, I hadn't thought of that. It would make a great POC if nothing else.
19:27ambrosebsdynalint convinced me that it's a good idea. or our only idea.
19:27ambrosebsit's just a poc itself anyway.
19:28ambrosebsthe next step would be a more structured error catching mechanism... like seqex :)
19:30ambrosebscfleming: the macro redefs in dynalint https://github.com/frenchy64/dynalint/blob/master/src/dynalint/lint.clj#L1485
19:33ambrosebsthe downside is you really can only target specific clojure versions
19:33ambrosebsand you better hope no other lib is pulling the same trick
19:34ambrosebsbut it's the user's fault anyway, they loaded the monkey patches
19:34ambrosebs;)
19:36cflemingHehe, right. But there's clearly lots of gain to be had, especially around error messages.
19:37ambrosebsyep, very low hanging fruit.
19:39QbYany clojure freelancers looking for immediate work?
19:40ambrosebsQbY: maybe ask https://twitter.com/cgrand
19:42jeffterrellQbY: I may have a colleague who is.
19:42muraiki_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:43muraiki_as always, reading the documentation helps :)
19:44muraiki_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:44arrdemambrosebs: cfleming: glad to see I'm not the only one kicking that idea around :D
19:45bbloomsweet! https://github.com/clojure/clojure/blob/9aaee3c111ce18b9b70695dd45a04b401a174113/src/clj/clojure/core.clj#L7286
19:45bbloomi called that "each"
19:45bbloombut each! or run! is fine by me too
19:45bbloomi've needed/used that quite a few times for side effects from a seq
19:46ghadishaybanbbloom: it's a useful addition
19:46ghadishaybanalso *way* faster than doseq
19:47Bronsathat's a nice fn, I didn't notice it
19:47bridgethillyerI need a favor from someone
19:48bridgethillyerAt the conj, can someone please explain to me why being concerned with the beginner experience in Clojure is a *bad* idea?
19:48bridgethillyerI really feel like I can only figure this out if someone explains it to me in person
19:48technomancysomeone: you heard her, spit it out
19:48arrdem(inc technomancy)
19:49lazybot⇒ 142
19:49technomancy(sorry)
19:49amalloybbloom: 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:49jeffterrellbbloom: I'm sure I'm missing something, but why is that different than e.g. `(do (map proc coll) nil)`?
19:49bridgethillyer:)
19:49ghadishaybandoseq has chunked traversal
19:49amalloyjeffterrell: well, your example does nothing at all, just returns nil
19:49bbloomamalloy: i didn't say it, ghadishayban did
19:49jeffterrellha, right, say mapv then :-)
19:49bbloomjeffterrell: mapv builds a data structure you'd just throw away...
19:50amalloywell *that* example consumes unbounded memory
19:50amalloy(for large enough colls)
19:50ghadishaybanhmm does clojurebot macroexpand...
19:50bridgethillyerI’m serious, though. I promise to even be nice and listen a lot if someone is willing to do that for me
19:50amalloybut what you really mean is (do (dorun (map f coll)) nil)
19:50jeffterrellOK, true, good points all :-)
19:50amalloywhich has the problem of allocating a bunch of cons cells
19:50technomancybridgethillyer: 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:50ghadishayban,(macroexpand '(doseq [a (range 50) b (range 50)] (do)))
19:50clojurebot(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:50bridgethillyertechnomancy: Loved your blog post today
19:50jeffterrellOK, I see why the reduce version is better. Nice.
19:50technomancyI mean, not necessarily *you* in particular
19:51technomancybridgethillyer: thanks
19:51bridgethillyertechnomancy: It’s in my one open browser tab right now. Going to spend some serious time thinking about it.
19:52technomancybridgethillyer: 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:52jeffterrellbridgethillyer: 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:52hiredmanbridgethillyer: 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:53bridgethillyertechnomancy: brilliant, yes
19:53bbloomi think i'd like the name each! better than run!
19:53bbloombut i'm just glad to finally have that function :-)
19:53bridgethillyerhiredman: We should totally have a beer or something at the conj
19:53hiredmanI object to what seems to be the idea that it is a universal priority
19:53ghadishaybanyeah
19:53ghadishayban(inc hiredman)
19:53lazybot⇒ 58
19:54ghadishaybanwhoa we gotta catch up
19:54ghadishaybanAnd beginners shouldn't drive design changes to a language
19:54hiredmanhah, yeah, I suppose so, boy it feels like forever since I was in one place with a lot of clojurists
19:54bbloombridgethillyer: did i miss some context?
19:55bridgethillyerbbloom: yeah, sorry referring to things 30 min - 1 hour ago
19:55ghadishaybantooling can and is improving
19:56hiredmanoutside of tooling, errors messages that have issues filed against them get changed and patched
19:56bridgethillyerghadishayban: Ok, you’re invited for the beer/other beverage of your choice, too, at the conj
19:56ghadishaybanthere 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:56bbloombridgethillyer: ok i read the scroll back
19:57hiredmanwe'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:57ghadishaybanLOL
19:57arrdempfft
19:57bridgethillyerhiredman: lol I’m totally signed up
19:58bja_hiredman: sounds more like stalin scheme
19:58arrdem"if they aren't motivated enough to join #clojure and ask questions they don't belong anyway"
19:59technomancywhat kind of person tries to learn a programming language without freenode; I can't even imagine
19:59bbloombridgethillyer: 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:59bbloomlike domain checking functions
19:59bbloomwe've discussed garbage in / garbage out quite a bit here in this room
20:00hiredmanracket's tower of languages approach works well there
20:00technomancyoh 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:00technomancysuper easy to turn off too
20:00bbloomtechnomancy: oh yeah, i'm all for optional contracts, etc
20:01bbloombut i do think that designing for optional validation from the start would yield a pretty different language
20:01hiredmanI wonder what kind of errors you get from core.contracts
20:01technomancyassertion failed: (= a b)
20:01bbloomfor example the lack of conditional destructuring in clojure can make a lot of contracts more verbose to specify
20:01technomancy^ http://p.hagelb.org/csp.jpg
20:02bridgethillyerOk, I get the “don’t design for beginners” thing, and I agree
20:02hiredmanwell, I mean, there are lots of options for improving error messages
20:02hiredmanschema, core.typed, dynalint, eastwood
20:03bridgethillyerIMO, designing for beginners and being concerned about the beginner experience are two, not necessarily overlapping things
20:03bbloomhiredman: 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:03hiredmanbridgethillyer: the question is, where should the beginner experience fall on the list of priorities
20:04beppuRacket's beginner experience is wonderful due to how much information DrRacket gives ou.
20:04hiredmanbbloom: ok, so use core.typed :)
20:04hiredmanI 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:05hiredmanmaybe technomancy will write DrClojure
20:05hiredmantechnomancy: you like programming swing if I recall
20:06bridgethillyerhiredman: That’s my dream, although I doubt it’s possible
20:06bridgethillyerhiredman: and to your much earlier point, while I dream of that, I’m not willing to work on it at all :)
20:06hiredmanthe best thing for errors would likely be to enrich the communication of errors between the compiler and tools
20:07beppuI 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:07hiredmanan exception with a message means the compiler has to make policy descions with regard to generating that message
20:07beppuThe error messages have been pretty good so far, too (in DrRacket).
20:07ghadishaybanbeppu: cursive does most of that, without the lines drawn
20:07technomancyhiredman: I'm too far gone
20:07hiredmanif 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:07bbloomit's funny, the 3 approaches of types, contracts, and schema seem to fall in logic, OOP, and grammar programming buckets respectively :-)
20:07beppughadishayban: That's good to know. Maybe I'll try cursive out one of these days.
20:08ambrosebscfleming: can cursive ever draw the lines for scoping like drracket?
20:08technomancythe 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:08technomancywhich is why I'm building a hypercard clone
20:09ghadishaybanin my limited use of it, it seems that cursive is aware of scoping rules
20:09hiredmanand once you are starting to talk about changes to the compiler, you have my attention
20:10technomancyat 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:11bridgethillyertechnomancy: okay!
20:11technomancyat that point the racket->jvm jump would start to feel a bit like jvm->js
20:12technomancytrade good tooling and decent usability for increased reach. then do it again.
20:12hiredmanwell, the jvm is way better than js runtimes
20:13hiredmanso not entirely like clojure->clojurescript
20:13technomancyTBH 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:14hiredmanthe 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:15arrdemkinda hard to avoid when there isn't a spec for Clojure, just an implementation
20:15technomancyright; I mean if you can be "clojure" without even having vars, who can say where the line is drawn
20:15arrdemI'd be up for Clojure in Racket... I've been wanting to play with Racket anyway
20:15hiredmanhave you looked at https://github.com/takikawa/racket-clojure ?
20:16bbloomtechnomancy: i would be interested in a racket-clojure for FFI purposes
20:16technomancyright, so spoiler alert is that https://github.com/greghendershott/rackjure exists
20:16hiredmanvars are so great, I dunno if they were introduced just for utility or the greatness was understood
20:16bbloomtbaldridge seems to be tinkering w/ a pypy based clojure too
20:16technomancyit doesn't have vars, metadata, pervasive destructuring, or persistent vectors
20:16beppuracket is nice on its own
20:16technomancybut yeah
20:16hiredmanbut being able to talk about linkage in a first class way
20:16hiredmanfantastic
20:16technomancyhiredman: srsly
20:16bbloommodules/units are the biggest thing i want from racket land
20:17bbloomhuge deal
20:17hiredmanvery tricky
20:17bbloomin racket? in general? or to add to clojure?
20:17hiredmanto add to clojure
20:17bbloomyeah, agreed
20:17bbloomi thought about it a bunch and my brain hurt so i gave up thinking about it
20:18hiredmanI mean, unless you want to throw out the current namespace system, which I dunno, I might be fine with
20:18technomancyhiredman: if you're going to replace namespaces, they need to be replaced with namespaces-as-values, I think
20:18bbloomheh, yeaaah... that seems unlikely
20:18technomancyif that bandaid is gonna get pulled, make it count =)
20:18hiredmantechnomancy: nah
20:18lukecosseyAnyone used the goog.fx.css3 Transition? I'm having problems with it working in Safari.
20:19hiredmannamespaces as values don't really make sense
20:19hiredmanthey have a name, they are an identity
20:19technomancybbloom: hm; so to me racket's use of submodules for main feels pretty tacky
20:20technomancyvs just "main is a function, so you know, call it"
20:20bbloomhiredman: 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:20hiredmanbbloom: what would you do with that?
20:20bbloomtechnomancy: i can't comment on rackets use of modules, sub or otherwise, since i haven't used racket beyond some tinkering in drracket
20:21bbloomhiredman: one thing is something like hiphiparray does with specialization
20:21bbloomhiredman: another thing would be for providing alternate backing implementations for say clj + cljs
20:21bbloometc
20:21hiredmanbbloom: sure, but that seems pretty orthogonal to namespaces as a value
20:21technomancyhiredman: for isolating out subtrees of namespaces to allow multiple versions to coexist
20:21hiredmanbbloom: what you want is someway to template namespaces
20:22bbloomhiredman: which is effectively what racket's units are
20:22hiredmanbbloom: sure
20:22bbloomhiredman: i was just trying to clarify technomancy's comment
20:22hiredmanI am pretty sure they do all that without having namespaces as immutable values
20:22hiredmanerrr
20:22hiredmanmodules
20:22hiredmantechnomancy: yeah, but that has nothing to do with namespaces as values
20:23bbloomhiredman: 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:23hiredmanthat just has to do with how namespaces exist
20:23hiredmanright now clojure namespaces exist in a flatspace
20:23technomancythey should be first-class things you can operate on without their being globally rooted
20:23ghadishaybanwhat would a motivating purpose of ns templating be? type specialization or running multiple versions of a subtree of code, like technomancy suggests?
20:23hiredmanif you turned it in to a tree with some scoping rules
20:24hiredmanghadishayban: the hiphiparray example is type specialization
20:24bbloomghadishayban: and cljx is basically all namespace templating
20:25hiredmanalthough, to be fair, I think you can do namespace templating with some macros already
20:25xcthulhubbloom: When I want to do such things, I use `with-redefs` to do such instrumentation
20:25hiredmanpeople just would rather slurp in a string and call eval
20:25hiredmaninsane
20:25hiredmanlike, I can't believe hiphiparray does what it does
20:25xcthulhuOkay, maybe you have something else in mind
20:25bbloomhiredman: not in a way that will compose well with other macros (in clojure at least)
20:25hiredmanbbloom: I am not so sure of that
20:26bbloomhiredman: i'd be interested to see what you come up with if you attempt to maintain any clj/cljs hybrid projects
20:27hiredmanso I never completed this https://github.com/hiredman/hiphip/blob/foo/src/hiphip/impl.clj
20:27hiredmanbut I started rewriting it at some point with a macro
20:27hiredmanit isn't done, so of course I can't say "it works, I have proof" but I think it would
20:27bbloomhiredman: oh yeah, i was using hiphip as a motivating use case, not as a great impl of the idea
20:28hiredmanbbloom: the clj/cljs stuff I have no idea
20:28bbloomhiredman: it's much harder b/c of when macros get evaluated, and reader behavior
20:28hiredmansure
20:28ghadishaybani want what hiphip does, but with HOFs, rather than with macro comprehensions
20:28bbloomnot just when macros get evaluated, but what environment they get evaluated in too
20:29technomancycljs has metadata, just no vars?
20:29technomancy*right?
20:29hiredmantechnomancy: it is complicated, because cljs macros are written in clojure not cljs
20:30hiredmancljs is a whole other kettle of fish
20:30technomancyright... does metadata exist at runtime then?
20:30bbloomhiredman: but that's the parameterized namespace motiviation that is most important to me
20:30hiredman(which I would rather not touch, I mean, have you held a kettle of fish?)
20:30bbloomtype specialization can be accomplished in other ways
20:30hiredmanleast important to me :)
20:31ghadishaybanbbloom: HOFs in clojure make type specialization hard
20:31technomancyright; having metadata without vars is a lot less interesting to begin with
20:31hiredmantechnomancy: I dunno, I mean they could just stick it any old place cause javascript objects
20:31bbloomghadishayban: more specifically HOF w/o defunctionalization, which is due to the dynamic nature of our runtime
20:31hiredmantechnomancy: on the other hand the closure compiler will strip it all out anyway
20:31ghadishaybanbbloom: defunctionalization?
20:31hiredmanλ lifting?
20:32bbloomghadishayban: compilers for static runtimes will take all higher order functions and turn them in to first order
20:32bbloomhttps://en.wikipedia.org/wiki/Defunctionalization
20:33ghadishaybanbbloom: i see. the way generic functions dispatch in Julia helps too
20:33bbloomghadishayban: yeah, they have both per function caches and per call site caches
20:33ghadishaybanbbloom: not sure if that is the same approach
20:33bbloomgfredericks: we have per function for multimethods and per call site for protocols
20:34bbloomer i mean ghadishayban ^
20:34bbloompolymorphic caches are not defunctionalization, no
20:35bbloomghadishayban: the JVM provides the same sort of caching for *virtual* methods
20:35ghadishaybandammit i got bbloomed right when i have to leave
20:36bbloomwhich i guess all our IFn invokes are, but there are sooo many implementers of IFn....
20:36ghadishaybanback in a bit
20:36bbloombbloomed == told to read some crazy area of comp sci? lol
20:37hiredmanbbloom: ghadishayban has been doing some work invokedynamicing vars (apropos of all the implementors of IFn)
20:38jasonjcknbbloom: do you have a blog?
20:38jasonjckn(link)
20:38bbloomhttp://www.brandonbloom.name/
20:38jasonjcknyour last name is actually bloom?
20:38jasonjcknnice
20:38hiredmane.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:38bbloomhiredman: that'd be super nice
20:39hiredmanvirtual mechanical sympathy
21:11sritchiedoes anyone remember a library that lets you publish a bunch of modules out of a single project,
21:11sritchieby carving up the source tree?
21:13technomancysritchie: voom?
21:13sritchietechnomancy: not that one… someone had written it for a util library
21:14sritchieso 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:14sritchiewith proper dependencies between them if necessary
21:18xeqisritchie: lein-modules?
21:18sritchiexeqi: no, I remember it did it automatically
21:18sritchieI can’t find the damned thing anywhere
21:19xeqihmm, I only know of #{sub, modules, voom}
21:50hiredmanlein-repack
21:51hiredmanhttps://github.com/zcaudate/lein-repack
22:14cflemingambrosebs: Re arrows (came back late, sorry) - Cursive can probably draw them, but not efficiently.
22:15ambrosebscfleming: oh cool to know
22:15cflemingambrosebs: Since you'd have to redraw most of the screen probably.
22:15cflemingambrosebs: 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:16ambrosebsit would be cool to teach cursive about my own binding macros
22:16ambrosebssomehow :)
22:16cflemingambrosebs: I'm also thinking about things like setting the background colour of then/else clauses of if to a subtle red/green
22:16cflemingThat's coming :-)
22:17cflemingI 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:17cflemingI also need to migrate the existing code to the parser I showed you
22:18cflemingSo it's all consistent.
22:18cflemingAll that code will be open source with the API
22:18ambrosebswill I be able to release a core.typed binding macro file that people can just import into cursive?
22:19cflemingYup
22:19ambrosebssweet
22:19cflemingI'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:20ambrosebsfantastic
22:20ambrosebsthat will probably work well enough
22:20cflemingBut people will also be able to create support for their internal DSLs and provide them to Cursive too.
22:20cflemingThere's lots of trickiness about the best way to integrate that into IntelliJ without having everything grind to a halt at startup though.
22:21ambrosebsya right
22:26cflemingI need to sit down and spend some time with DrRacket, actually
22:26cflemingI read a bunch of papers about things like the macro debugger, but I've never actually used it.
22:26ambrosebscfleming: the master branch of DrRacket just added Typed Racket mouseovers
22:27cflemingYeah, I saw that, it looks very like the Typed Clojure support in Cursive actually, someone sent that to me the other day.
22:28cflemingCan they require an explicit "type check this file" step, or can they integrate it more continuously?
22:28cflemings/Can they/Do they/
22:28ambrosebstype checking is triggered by macroexpansion :)
22:28ambrosebs#lang typed/racket
22:29ambrosebsthe only way to stop type checking is #lang typed/racket/nocheck
22:29cflemingBut what I mean is, can the editor do it in real time like IntelliJ would do with Java, for example?
22:29ambrosebsahh I doubt it
22:29cflemingThere you get type errors provided by the IDE, but that means that the IDE basically reimplements the type system.
22:30cflemingI'm still amazed they did that for Scala
22:30ambrosebsare you serious
22:30cflemingYup
22:30ambrosebsok I'll just accept that
22:30cflemingThe Eclipse IDE has a frankenintegration with the Scala compiler
22:31cflemingThe IntelliJ one they wrote it themselves
22:31ambrosebssheesh
22:32cflemingThey do that for basically all the languages they support - Cursive has a lot of knowledge of Clojure semantics built in too
22:32ambrosebsso 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:32cflemingNice, I can get you deltas
22:33cflemingSemantic deltas or text?
22:34cflemingIntelliJ accurately tracks all changes to documents, in fact I already use that to move the annotations around when the file is edited.
22:34ambrosebswhat do you mean by the former?
22:36cflemingWhether you would want to receive the forms that had changed, or a list of text ranges that had been updated in the document.
22:36cflemingText ranges can be converted into forms by just re-parsing, of course.
22:39ambrosebscfleming: hmm it depends what I do on the core.typed side I guess.
22:39cflemingcfleming: sure, either is relatively trivial. Let me know when you have a clearer idea of what you need and we can try it.
22:39cflemingUgh, that should have gone to you, not to me, of course, sheesh
22:40cflemingTalking to myself
22:41ambrosebsdid you ever get the type querying thing working with cursive?
22:41ambrosebslike local type info for expressions?
22:41ambrosebsIIRC there was some incompatibility with the info I was providing
22:41cflemingNo, I just display the errors that are sent back - I can't remember the details.
22:41cflemingI'll check and let you know.
22:42cflemingGot to run
22:42ambrosebscya!
22:42cflemingSeeya
22:47cddrWhat 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:59kenrestivoi'm pretty sure there's a formal REST specification somewhere that answers that
23:00beamsoHTTP status 204 == no result
23:00beamsono content, actually
23:43TimMccddr: An empty collection.
23:44TimMcThe API results should be homogeneous; don't change the "type" of the response based on the query window.
23:51Jesterman81hey ladies/gents
23:51awwaiidgreetings earth/human
23:53Jesterman81is there a cleaner way of getting the hash of data then the following https://gist.github.com/deefa3a8e7a1f9610b3e.git
23:54Jesterman81https://gist.github.com/Jesterman81/deefa3a8e7a1f9610b3e
23:54Jesterman81I’m a clojure noob
23:55justin_smithso you just want the :foo key / val from each map?
23:55Jesterman81yeah
23:55justin_smith,(map #(select-keys % [:foo]) [{:foo "foo" :bar "dummy" :axe "blood"} {:foo "baz" :bar "dummy"}])
23:55Jesterman81[{:foo “foo} {:foo “bar”}]
23:55clojurebot({:foo "foo"} {:foo "baz"})
23:56Jesterman81thx
23:57awwaiidwhat are you going to do with those key/value pairs where the key is always what you gave it?
23:57Jesterman81yes
23:57Jesterman81I want to elimiate everyting but just the :foo keys and values
23:57awwaiidI mean -- if you only care about the values, you could do #(% :foo) in that map instead
23:58Jesterman81right…I was just wondering if thats as short as I can get it and I am not missing some destructing or cleaner way
23:58justin_smithawwaiid: btw #(% :foo) can be replaced with :foo for this purpose
23:59justin_smith,(map :foo [{:foo "foo" :bar "dummy" :axe "blood"} {:foo "baz" :bar "dummy"}])
23:59clojurebot("foo" "baz")