#clojure log - Oct 08 2014

The Joy of Clojure
Main Clojure site
Google Group
IRC
List of all logged dates

0:01 myguidingstar: wow, I can see lots of 'characters' marching

0:01 is this a live broadcast of Hong Kong protest ;)

0:01 zanes: https://gist.github.com/zane/00655f136470458e21e1

0:02 Seems useful, but I can’t tell if I’m being crazy.

0:10 devn: zanes: it was meant to be

0:17 dbasch: ,(apply str (map char (take 10 (repeatedly #(+ 30000 (rand-int 30000))))))

0:17 clojurebot: "耞텊쁻빻鏚硑箔豶뼕腵"

0:18 dbasch: according to Google Translate that means "Some loss 텊 쁻빻 Qipingbofen 뼕 Jia"

0:20 devn: I can parse a little bit but...

0:25 zanes: Are there combinators for transducers other than comp?

0:26 e.x. (sequence (both (map inc) (map identity) [1 2 3]) ;; => (2 1 3 2 4 3)

0:28 beamso: i'm trying to use cljs-ajaxa

0:28 *cljs-ajax

0:28 it looks like there were undocumented broken changes

0:29 justin_smith: zanes: that looks like mapcat / juxt

0:29 * zanes ponders.

0:29 justin_smith: ,(mapcat (juxt inc identity) [1 2 3])

0:29 clojurebot: (2 1 3 2 4 ...)

0:30 justin_smith: is there a mapcat transducer type?

0:30 zanes: Yeah, that seems right. But I’d like to be able to do that with transducers instead of bare functions.

0:30 justin_smith: right

0:31 mapcat has a transducer arity...

0:32 ,(sequence (mapcat (juxt inc identity)) [1 2 3])

0:32 clojurebot: (2 1 3 2 4 ...)

0:32 justin_smith: there we go!

0:33 and of course that mapcat could be combined with other transducers

0:34 zanes: Right, but what if inc and identity are themselves transducers?

0:34 i.e. What if we want to do filtering and such in there?

0:38 TEttinger: ##(mapcat (juxt inc identity) [1 2 3]) ; dammit justin_smith beat me to it

0:38 lazybot: ⇒ (2 1 3 2 4 3)

0:38 TEttinger: (inc justin_smith)

0:38 lazybot: ⇒ 89

0:39 justin_smith: hell I even dug up the transducing version :)

0:56 nhanH: After I update to lein 2.5.0, I can't uberjar my app any more (Got a "java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest"), did something change? It was working fine with an earlier lein version (I can't figure out which version it is now though)

0:56 zanes: I guess what I really want is the transducer version of juxt. I can just compose that with cat.

1:17 lukecossey: Hey all. Anyone had much experience using goog.fx.css3.Transition in cljs? I've got it working perfectly for me in Chrome & Firefox, but the transitions don't happen at all in Safari... any ideas?

2:50 vIkSiT: hello all

2:51 has anyone here used clojurescript/om?

2:51 I'm wracking my head around this now

2:51 how do I get component a to auto update, if component b does an ajax fetch?

2:51 lukecossey: Yeah it's great!

2:51 * vIkSiT is stuck

2:52 vIkSiT: I have an autocomplete module (the standard one) - which fetches data.

2:52 I have a "search results" module that knows how to render a query

2:52 Or rather, a set of search results

2:52 But I don't know how to update the search results on an event where I click something on the autocomplete widget

2:53 Since these are two components, and while they share app state, they are different cursors

2:53 lukecossey, any pointers? :)

2:53 lukecossey: You could use core.async channels?

2:53 vIkSiT: lukecossey, I'm trying to figure out how

2:53 for instance

2:53 I can (put! my-chan search-result)

2:53 but how do I get the search results component to "listen" to this?

2:54 lukecossey: You could store the my-chan in the app-state.

2:55 vIkSiT: but they have different cursors

2:55 eg. (def app-state {:autocompelte [..] :search-results [])

2:56 one gets key 1 and the other gets key 2 as their cursors

2:56 so they can't reference the other key

2:58 lukecossey: You can pass the complete app state as well as your specific data through when you build the components.

2:58 (om/build page1-view {:specific cursor1

2:58 :app-state app-state})

2:58 (om/build page2-view {:specific cursor2

2:58 :app-state app-state})

2:58 Does that help at all?

2:59 vIkSiT: ah hmmm

2:59 lukecossey, that's interesting - didn't know you could do that. quick orthogonal question

2:59 lukecossey: If the component is defined as (defn page-view [page owner]

2:59 vIkSiT: can you specify targets in om/build?

3:00 eg, i have a page template built as a static html, but only two divs are om components (id autocomplete and results)

3:00 lukecossey: Then you can get the data with (get-in page [:specific])

3:00 And the app-state with (get-in page [:app-state :autocompelte])

3:00 vIkSiT: that makes sense

3:01 So now I would ask

3:01 How does Om know to re-render if that channel changes?

3:01 is there some auto pub sub mechanism?

3:03 lukecossey, ^ any pointers?

3:04 lukecossey: Something like this

3:04 om/IWillMount

3:04 (will-mount [_]

3:04 (let [my-chan (get-in page [:app-state :my-chan])]

3:04 (go (while true

3:04 (do-something-to-search-result (<! my-chan) owner)))))

3:05 (do-something-to-search-result (<! my-chan))))))*

3:05 vIkSiT: so will-mount is called every time something changes?

3:06 ahh

3:06 so we initialize this behavior in will-mount wih a go loop.

3:06 I'm guessing this is in the search result view. hmm

3:06 and then in autocomplete i can populate this channel

3:07 lukecossey, is there a way I can force an re-render of the view itself if this channel changes?

3:07 lukecossey: https://github.com/swannodette/om/wiki/Documentation#iwillmount

3:08 esirola: hi

3:08 lukecossey: You need to change the state using set-state!

3:08 vIkSiT: ah

3:09 lukecossey: so once you receive the data from the channel, set it to (set-state! owner :search-results (<! my-chan))

3:09 esirola: just looked hickey's talk on transducers (https://www.youtube.com/watch?v=6mTbuzafcII), very interesting

3:10 lukecossey: vIkSiT: and when you are building your search-results-list-view or whatever use (om/get-state owner :search-results).

3:11 esirola: will the modified map/reduce/etc enter clojure 1.7?

3:11 vIkSiT: lukecossey, use that in place of?

3:12 lukecossey: vIkSiT, I'm not entirely sure of your project, but that was just an example of how to the get-state to access any data coming from your channel...

3:13 vIkSiT: ah I see

3:13 trying to wrap my head around this.

3:13 lukecossey: Yeah it's tricky when you start, I'm still learning!

3:14 vIkSiT: :)

3:14 lukecossey: This is the project I'm currently working on... https://github.com/Secondi/secondi-homepage/blob/develop/src/secondi/pages/video.cljs still early days, but it may help to see state use in action?

3:16 vIkSiT: lukecossey, that would be awesome

3:18 lukecossey, so if I understand correctly

3:19 select-video! sets the state :current-video in the main cursors thats given to that functino as well as the video page view

3:19 christian_stamm: Hi! Is it possible to generate doc of test code with lein-marginalia?

3:20 vIkSiT: and then the set-active! sets that state

3:20 and because there's a go loop intiialized in will-mount.

3:22 which checks the channel that is updated on click.

3:23 lukecossey: vIkSiT, select-video! actually sets the state, so not the cursor that's passed through to it. Notice in render-state, it uses (:current-video state) to get that video out of the state parameter.

3:23 vIkSiT: ah.

3:23 this is very very veery useful :)

3:23 I think I just need ot read through this

3:23 I kinda get the feeling for it now hehe

3:23 lukecossey: And everytime the state is changed the component will re-render

3:24 Yeah, try get it running to help out with that. It's a wee bit messy, but hopefully it will help!

3:27 vIkSiT: lukecossey, any examples of where you actually render these views?

3:27 using om/root?

3:28 lukecossey: Yeah have a look at the core file

3:28 https://github.com/Secondi/secondi-homepage/blob/develop/src/secondi/core.cljs

3:28 kungi: justin_smith: The culprit really is http-kit. I tried using jetty and I dont't get multiple content-length headers with it. I will file the bug report this evening.

3:28 lukecossey: It's a wee bit abstract

3:29 vIkSiT: ah thanks

3:29 lukecossey, two more questions for you if you have time :)

3:30 one - do you know if each om/build invocation can be given a separate target?

3:30 and two - are you using secretary routing with a server side compojure/luminus style routing?

3:43 lukecossey: vIkSiT, Yes you can have multiple om roots. Not sure what you mean by targets

3:43 We use Django to serve our cljs applications and nginx for the server side routing I guess?

3:44 nonuby: is there a shortcut for importing multiple ns in one statement where paths only differ by final segment e.g. [acme.views.x :as x] [acme.views.y :as y] [acme.views.z :as z]?

3:49 vIkSiT: lukecossey, ah I mean. if I do the following,

3:50 om/build ... {:target (document.getElemetbyId ("autocomplete")

3:50 let me paste a gist

3:50 lukecossey, https://gist.github.com/viksit/f1e9744a2cda4b0bf9fa

3:51 Basically I can either do two calls to om/root

3:51 or I can combine them into one app

3:51 In the latter case, I don't know how to tell each om/build to happen in a *Separate* div

3:51 by default, evrything gets rednered in the main div

3:54 nonuby: vIkSit, why cant you use om/dom to build app layout and do (dom/div nil (om/build ...), it will get messy if you are picking up div via getElementById more than a few times. you only desire a :target when using om/root

3:56 vIkSiT: nonuby, I could - except, that I have designers who do html design.

3:56 nonuby: so you'd have something like (render [_] (dom/div {:className "parent"} (dom/div nil (om/build autcomp (:autocomp data)) (dom/div nil (om/build timelime (:timeline data)) )))

3:56 vIkSiT: now, either I shift them to using clojurescript :/

3:57 or, they give html, and then I inject the dynamic components in there using om

3:57 nonuby: ah i see, Im using jade and kioo to handle that..

3:57 vIkSiT: nonuby, yeah, theyre doing photoshop -> html, the old way

3:57 and I don't think rewriting all that is a good idea

3:57 I personally like enlive..

3:57 but yeah

3:58 nonuby: thats okay the jade step is optional, you can't just take html so (render [_] (dom/div {:className "parent"} (dom/div nil (kioo/component "autocomp.html" autcomp (:autocomp data)) (dom/div nil (om/build timelime (:timeline data)) )))

3:58 you can't just --> you can just

3:58 note kioo syntax not exact, but similar

4:00 vIKSiT, just ideas (that may or may not be viable to your scenario), tis very new to me, and doesnt seem to be much guidance on best practice out there yet

4:00 vIkSiT: oh kioo can render html?

4:00 oh i never thought of that

4:00 good point

4:00 nonuby: if you supply zero transformation, then it will just render the html file

4:01 vIkSiT: that is *awesome*

4:01 nonuby: it does compile time to dom/* (thus using clj enlive under the hood)

4:01 vIkSiT: nonuby, fantastic

4:01 that does make life a lot easier

4:03 nonuby: kioo reference the html files as java resources unless you use a wrapper macro to use arbitary file paths i use something like this https://gist.github.com/anonymous/8f2c26809ed88f0e6dd0

4:04 then you can just use (render [_] (filecomponent "myhtml.html {})

4:04 the last args is the transformations - which ive left empty, but usually want to make some

4:05 vIkSiT: ah

4:05 thanks for the info!

4:10 mbuf: what is incorrect for this hello world example https://gist.github.com/shakthimaan/f6a501835198f1fd1d07?

4:10 *in this

4:10 vIkSiT: hello mbuf. long time no see.

4:11 mbuf: vIkSiT, hi

4:12 nonuby: mbuf, is core.clj in src/clojure_noob (underscore vs dash)

4:12 mbuf: nonuby, oops, it is src/app/core.clj

4:17 nonuby, works now; had to use (ns app.core ...) in core.clj and (:main app.core) in project.clj

4:17 later

4:19 nonuby: yep your ns will your src path (usually..)

4:33 vIkSiT: lukecossey, around?

4:33 following your example : https://gist.github.com/viksit/353d73081a0152aba0a8

4:33 I'm confused about how to implement the "click" button in my autocomplete view.

4:33 Any ideas?

4:36 nonuby: r1 -> app

4:37 actually ignore that, why you are reaching out to r1, shouldnt that be part of your app-state or shared state

4:37 vIkSiT: nonuby, hmm, im just making this in a way that works

4:38 ultimately, r/r1 come from xhr calls..

4:38 all I want to do is - when i click that button, it does something that makes the search-results-view refresh :)

4:39 nonuby, does that make sense btw?

4:53 clgv: update of *loaded-libs* is transactional but actually loading a namespace via `require` is not :(

5:00 dysfun: i have an odd issue with midje: lein midje can't find midje.util.ecosystem and bail out and yet (use 'midje.sweet) in lein repl works fine

5:01 clgv: dysfun: maybe there are multiple versions of midje classpath somehow. did you check "lein deps :tree"

5:01 and "lein classpath"?

5:02 dysfun: odd, midje isn't in 'lein deps :tree', but it's in project.clj

5:02 no, ignore me, i'm in the wrong terminal tab :/

5:54 lgrapenthin: I have a Java Application from which I invoke the start of tools.nrepl so that I have a Clojure REPL into it. Unfortunately, I don't get the print output via nrepl. How could I fix that?

6:11 clgv: lgrapenthin: you need to use some frontend for nrepl

6:13 lgrapenthin: clgv: what do you mean? I am wrapping cider middleware server side and jack in via cider from emacs

6:14 should say connect, not jack in

6:14 clgv: lgrapenthin: ah you use emacs+cider to communicate with that nrepl instance in your application?

6:14 lgrapenthin: clgv: yes

6:14 clgv: lgrapenthin: then check whether "lein repl :connect" works. if it does, you can blame cider

6:15 lgrapenthin: clgv: I can connect just fine

6:15 it's printing that doesn't work

6:15 clgv: lgrapenthin: I mean, connect with leiningen repl and try to evaluate the same stuff you tried from cider/emacs

6:15 lgrapenthin: e. g. (doc ...) (println ...) all return nil and print somewhere in netbeans

6:15 evaluation works fine

6:16 so I suppose I have to bind *out* to sth. else

6:16 clgv: and printing does not work in lein repl as well?

6:16 lgrapenthin: but don't know what

6:17 clgv: you did bind *out* manually?

6:17 lgrapenthin: clgv: nope. and lein repl does work

6:17 clgv: apparently

6:18 clgv: lgrapenthin: I have a working nrepl in my application just via "(nrepl/start-server :port nrepl)"

6:18 lgrapenthin: ok, so maybe the printing output ends up in some strange buffer in emacs?

6:18 lgrapenthin: clgv: me too. and your guess was right. it must be ciders fault

6:19 clgv: lgrapenthin: I usually check pure lein first when my IDE/editor does strange things with respect to leiningen's feature set

6:20 lgrapenthin: clgv: hmm. this is strange because when I use nrepl-jack-in cider prints fine

6:21 thanks anyway

6:21 clgv: lgrapenthin: yeah maybe something differs when you connect to a foreign repl

6:24 didn't nightcode have it's repl and editor as standalone component libraries? or was that some other project?

6:25 aah ok, you can use them separately but it is on lib

6:38 back to the topic of transactional require (ensure that a namespace is only required once when multiple thread need it at the same time): I tested this snippet with multiple thread and it seems to work. any opinions, concerns or suggestions? https://gist.github.com/guv/ac76b9ab1878705062c6

6:41 weavejester: clgv: Why do you use a ref?

6:42 clgv: weavejester: because I need to return the delay instance

6:44 weavejester: clgv: Okay… but why go to all that trouble? If you just want a require to be evaluated once, why not using locking?

6:44 *use locking

6:44 For that matter, is require thread unsafe?

6:44 clgv: weavejester: yes it is

6:45 weavejester: only *loaded-libs* is managed in a ref but not used to decide whether the actual `load` needs to happen

6:45 weavejester: I found this from an actual problem

6:47 weavejester: clgv: So why not something like (let [o (Object.)] (fn [ns] (locking o (require ns))))

6:47 clgv: weavejester: the construction is motivated that the only waiting should occur when multiple thread require the same namespace. if they require different ones or a require is not needed then they should not wait

6:48 weavejester: yes but that way everyone must wait

6:48 weavejester: clgv: Is there any other safe way of doing it?

6:48 clgv: If you have namespaces a and b that both depend on c

6:48 clgv: weavejester: humm right my solution does not account for the fact o transitive namespaces being required in parallel

6:48 weavejester: clgv: You’d need to know that you can’t load up a concurrently with b if c is not loaded

6:49 clgv: weavejester: I wish Clojure had that built-in...

6:49 ok back to simple locking ...

6:49 ah well at least I can check what was already loaded.

6:50 weavejester: Unless it becomes a performance issue, I’d be tempted just to go for the simplest solution

6:51 clgv: weavejester: it is an issue. usually I have around 20 threads using this.

6:52 weavejester: clgv: What’s the use case? I mean, what are you doing for that to happen?

6:52 clgv: weavejester: it's a "worker server" implementation

6:53 weavejester: clgv: So… you load up worker functions/namespaces on the fly based on messages to the server?

6:53 clgv: which does not know anything about specific implementations and thus can not preload application specific stufff

6:53 weavejester: yeah, you can describe it like that

6:53 weavejester: clgv: Have you considered using classloaders?

6:54 clgv: weavejester: not in the current state. I think if I had the time I'd change to single worker jvms

6:56 weavejester: since 20 threads in one jvm on a 20 core intel get a significant penalty with respect to individual task runtime compared to tasks being executed in a single thread

6:57 weavejester: I am not entirely sure what the reason is, since these computations share nothing but the implementation. maybe jvm maybe clojure itself

6:57 weavejester: clgv: Really? I was under the impression the JVM was pretty good at assigning threads to cores

6:58 clgv: weavejester: if I remember correctly I had individual task runtimes increased by at least a factor of 2

6:59 weavejester: not sure if there are impacts from cpu cache misses and stuff due to 20 parallel executions...

6:59 weavejester: clgv: If the server is constantly running, then surely a require would only happen once?

6:59 clgv: So performance issues would only be limited to the first time it requires a namespace

7:00 clgv: weavejester: oh these performance figures where not about the `require` but in general

7:00 weavejester: clgv: So a concurrent require might not be your problem?

7:01 clgv: weavejester: no, I switched context without a hint, sorry ;)

7:01 weavejester: I am back to https://gist.github.com/guv/ac76b9ab1878705062c6

7:03 weavejester: clgv: Why do you use *loaded-libs* directly? Why not (loaded-libs) ?

7:03 Gonzih: Hi guys, how should I configure log4j from inside lein plugin?

7:04 clgv: weavejester: oh damn, I did not find that one. I search clojure.core but seems I missed that one

7:04 weavejester: thank you

7:07 weavejester: Gonzih: Which lein plugin?

7:09 clgv: Gonzih: you can configure it programmatically if that is better for your usecase. you just need to set the appropriate properties in (System/getProperties). that way you can also retrieve them from project.clj and set them

7:09 Gonzih: weavejester: I'm working on my own plugin (lein-feeds2imap). I just reuse my existing project inside which logs everything to console logger using clojure.tools.logging. But there is no output from within lein plugin call.

7:09 here is plugin code https://github.com/Gonzih/lein-feeds2imap

7:10 clgv: Gonzih: it probably does not pickup the log4j.properties file

7:11 Gonzih: I have one in dependency library and in plugin src directory

7:11 is there any way to set properties file using setProperty call?

7:11 clgv: Gonzih: yes. like I said above

7:11 Gonzih: ah no the properties and not the file ;)

7:13 Gonzih: there is also Properties.load - not sure if that works on the (System/getProperties)

7:35 gnzh: clgv: I tried to use clj-logging-config without much success.

7:36 clgv: gnzh: I have a working solution where I just set the properties via a function. but loading them seems possible as well

7:36 gnzh: can you show me example?

7:36 of loading via fn

7:41 clgv: can you? please :)

7:42 cYmen: What do I need to do to install cider-nrepl? I get this error: https://www.refheap.com/4437faae1d2d42f5f2c766670

7:43 LauJensen: Gents. I have an app running that I wrote some time ago. I've now opened it in Lighttable and connected to an nrepl. Everything loads fine but Im looking to connect a Watch to one of my vars, Alt-W gives me nothing, what do I do ?

7:48 kungi: cYmen: include the plugin in your project.clj or profiles.clj

7:48 cYmen: kungi: I'm not in any project...

7:48 kungi: cYmen: then include it in the user profile of ~/.lein/profiles.clj

7:49 justin_smith: cYmen: ~/.lein/profiles.clj applies even if not using a project

7:49 kungi: hi justin_smith

7:49 justin_smith: also, that message misspells the snapshot name

7:49 0.8.0-SNAPSHOT

7:49 kungi: hello

7:49 cYmen: I don't have that, can either of you provide me with a reasonable default, please? :)

7:50 justin_smith: {:user {:plugins [[cider-nrepl "0.8.0-SNAPSHOT"]]}}

7:50 that goes in ~/.lein/profiles.clj

7:53 here's a thing though: that snapshot, being a snapshot, will be replaced on occasion with a new snapshot version, and things may break unless you also update to the latest alpha elisp code that goes with it

7:54 and sometimes the latest version of either one will be just plain broken - it's alpha software

7:57 jcidaho: Hi is there a way in core.async to wait on a channel to have finished processing everything in its buffer, once it's been closed?

7:58 cYmen: justin_smith: What do you do for a living? :p

8:04 justin_smith: $mail cYmen backend clojure web developer

8:04 lazybot: Message saved.

8:04 cYmen: Back!

8:05 justin_smith: heh, you get that message from lazybot?

8:06 cYmen: jep :)

8:07 dnolen_: jcidaho: no

8:07 cYmen: justin_smith: Apparently this nrepl version does not exist....

8:08 cider-nrepl

8:08 justin_smith: oh sorry

8:08 it's cider/cider-nrepl

8:08 {:user {:plugins [[cider/cider-nrepl "0.8.0-SNAPSHOT"]]}}

8:09 clgv: gnzh: just combine java.lang.System.getProperties, java.util.Properties.load and maybe clojure.io/resource

8:09 cYmen: justin_smith: Works. Thanks!

8:35 noncom: is there any clojure lib that allows to easy record function calls, their parameters and time of happening ?

8:35 and then reproduce it.. ?

8:39 gfredericks: noncom: what's the use case? debugging? logging?

8:40 noncom: gfredericks: saving the order of actions to reproduce later.. closer to a save game

8:41 just to be able to play back / stop /pause / modify

8:41 record user actions i mean

8:41 justin_smith: noncom: tools.trace will show arguments / return value, but doesn't record them for replay per se

8:46 bacon1989: I have a clojurescript question for you guys. I'm trying include an html shiv for IEs issue with console.log, but I can't seem to figure out how to include a new Var in a namespace that i'm not currently in

8:46 basically, I need to include a js/console

8:46 CookedGryphon: If I were to implement a simple Tuple2 with deftype, what would I need to support to allow destructuring, nth, first, second and last?

8:46 ro_st: better to shim in normal javascript, bacon1989

8:47 bacon1989: so basically, I hsould just let someone else deal with the issue?

8:47 I could always just tear the console.log messages out

8:47 ro_st: i think the js ns is handled differently in the code. dnolen_ can confirm. to answer your actual question, generally speaking, you can (in-ns 'something) (def some-var), but i'm not sure if that's for cljs too

8:48 better to use (enable-console-print!) … (prn …)

8:48 dnolen_: ro_st: in-ns only works for REPL interaction

8:48 bacon1989: I'm not sure what you are saying. What does shimming have to do w/ console.log

8:48 ?

8:49 noncom: CookedGryphon: look at the sources of destructure, nth and other fns ?

8:49 ro_st: dnolen_: i think he wants to do that fix that makes it safe to console.log in older IE

8:49 dnolen_: bacon1989: if want to *use* console.log (.log js/console "foo")

8:49 noncom: CookedGryphon: i have looked at destructure recently

8:49 dnolen_: bacon1989: (if (exists? js/console) ...)

8:49 noncom: you may find it informative

8:50 ro_st: dnolen_: your webinar code was super handy today. finally got to start using transducers today

8:50 so good.

8:50 dnolen_: ro_st: sweet

8:51 folippi: I'm a developer who's been working with Ruby, Python, Javascript, the usual. I'm super intrigued by clojure/cljs, FP and lisp. I dream wet dreams about doing it 9-5. Would one make an ass of themselves by showing up in a clojure shop and saying "I don't know clojure, but I'm interested and want to learn. I'll take a great pay cut for the chance to do that here" and like ask for a one year contract with low pay but get to write c

8:51 lojure and become a pro?

8:51 ro_st: folippi: if you did that, it'd probably just be a Wednesday for the person you're asking. put another way, no. not at all :-)

8:52 Clojure is still new enough that folks learn it on the job

8:52 dnolen_: bacon1989: (when (exists? js/console.log) (defn log [varArgs] (.apply js/console js/console js/arguments)))

8:52 ro_st: this is true for my whole team and i

8:54 folippi: Ok, that's reassuring ro_st :). I'll gather some confidence and go for it!

8:54 ro_st: folippi: having said that, it certainly wouldn't hurt to hack on some opensource and demonstrate some knowledge with the paradigm

8:54 folippi: ro_st: right

8:55 ro_st: do you have any experience at all?

8:55 if not, clojurekoans.com is a great place to start

8:56 bacon1989: dnolen_: neat, thank you

8:56 kungi: Having the requirement that I develop customized versions of our product for some customers I would like to create a plugin system. For loading plugins I thought about using pomegranate to add the dependencies at runtime and then load a namespace and call a well known function (like init-plugin). How would one unload a plugin at runtime and remove the dependency from the classpath as well.

8:56 folippi: ro_st: I've done those, and I've done a few tutorials (especially cljs/om) and I enjoy seeing how advanced things I can do in the lighttable instarepl. But I still havent gotten the hang of emacs (old time vim-mer) and all of that

8:57 bacon1989: dnolen_: but with that method, wouldn't I need to start using the log function?

8:57 ro_st: folippi: you might consider skipping emacs and using cursiveclojure.com instead

8:57 bacon1989: not that that's a big deal

8:57 kungi: folippi: have you tried evil mode? It's a very neat vim emulation in emacs

8:58 dnolen_: bacon1989: ah you want the JS-ism

8:58 folippi: kungi: tried to set it up but gave up. And I figure learning the 'real' way before would be a good idea

8:58 ro_st: folippi: Timothy Baldridge has a nice overview here https://tbaldridge.pivotshare.com/media/overview-of-cursive-clojure/9349/feature

8:58 dnolen_: (def (set! (.-console js/window) (fn [...] ...)))

8:58 kungi: folippi: 'real' way?

8:58 folippi: ro_st: that looks really really neat! Thanks for sharing

8:58 bacon1989: dnolen_: it's all good, i'm likely just going to document that it uses console.log, and suggest people use shiv if they have issues

8:58 ro_st: and one for clojurescript https://tbaldridge.pivotshare.com/media/cursive-and-clojurescript/12952/feature

8:58 folippi: kungi: well well ;)

8:59 ro_st: i did the emacs gauntlet and use it daily, but cursive is getting more and more appealing as an alternative

8:59 dnolen_: bacon1989: ok, but using console.log like will likely mean people just won't use your lib so I don't know if you will need a notice ;)

9:00 ro_st: folippi: lots of stuff to explore at www.stuttaford.me/codex/. courses, books, talks, screencasts. jump in and make something :-)

9:00 dnolen_: bacon1989: and that should have been (set! (.-console js/window) #js {:log (fn [...] ...) :error ...})

9:00 bacon1989: well, it's only being used for subscriptions that don't provide a callback

9:00 in otherwords, it doesn't affect production code

9:01 it's specifically for when developing

9:01 dnolen_: bacon1989: k makes more sense

9:01 bacon1989: https://github.com/benzap/flyer.js/blob/master/src-cljs/flyer/messaging.cljs#L19

9:02 yeah, I could probably take it out

9:26 CookedGryphon: How does one make a deftype'd class available to java at aot compile time?

9:29 justin_smith: CookedGryphon: clojure aot doesn't use javac does it?

9:30 CookedGryphon: Umm...

9:34 cddr: Hey folks, what do you think of this idea? https://github.com/cddr/crud

9:35 ro_st: cddr: have you looked at liberator?

9:35 ordnungswidrig: I like it (even if you don't use liberator)

9:35 But beware that CRUD does not match web/http and rest very good.

9:36 ro_st: same. i haven't used liberator, but i know it plays in the same space, so i'm curious if it solves a different problem

9:38 ordnungswidrig: However, I'd love to see something like that to be implemented on top of liberator. Adding etag, et.al. would be nice, I guess.

9:40 cddr: ordnungswidrig: There's a CRUD/HTTP impedence mismatch? How so?

9:40 ordnungswidrig: PUT is more like Create or Update

9:40 and POST is not necessarily create

9:43 cddr: Hm, maybe I should change the name because I definitely want it to be "RESTy"

9:43 kungi: hi ordnungswidrig

9:44 ordnungswidrig: :-)

9:46 kungi: ordnungswidrig: Can I somehow remove a dependency from the classpath at runtime? With pomegranate I can add one but ...

9:51 xeqi: kungi: theres nothing built to do it currently

9:52 it'd take a lot of classloader fiddling

9:52 ordnungswidrig: just restart the repl

9:57 kungi: ordnungswidrig: that is sadly not an option in this case

9:57 xeqi: hmm ok thank you

9:58 justin_smith: kungi: what end would removing an item from the classpath achieve?

9:59 kungi: justin_smith: for example unloading a plugin at runtime and make it not reloadable any more

10:01 stuartsierra: kungi: OSGi is designed for that sort of thing, but it comes with its own slew of problems and it doesn't work very well with Clojure's dynamic classloaders.

10:02 TimMc: Several Clojure programmers I know are even now sinking slowly into that tarpit.

10:03 kungi: TimMc: the OSGi tarpit?

10:03 TimMc: yeah

10:03 borkdude: I saw a slide somewhere that said NOOSGi (as a feature)

10:04 TimMc: That's not to say OSGi is a bad idea; I don't really know anything about it except that some people are attracted to the feature set (like moths to a lamp?) and are really struggling to wedge Clojure in there.

10:17 clgv: you could talk to laurent petit about what impact OSGi had on for Counterclockwise development

11:01 AeroNotix: asd

11:06 kungi: AeroNotix: f

11:06 AeroNotix: kungi: aaioun

11:06 kungi: uiae

11:07 ordnungswidrig: äöü

11:08 kungi: ordnungswidrig: The germans are coming with their umlauts ...

11:09 Hopefully at least someone I dont't know will attend our user group meeting this evening :-)

11:10 wink: ß

11:10 ordnungswidrig: ☃☃☃

11:10 *SCNR*

11:11 wink: hehe

11:11 I don't have that on my keyboard. only λ, µ and …

11:11 karls: õ

11:11 kungi: νρτδψγφϕ

11:12 CookedGryphon: With a java writer (I'm overriding a print-method - for something which gets called a *lot*), which is quicker and results in less memory churn:

11:12 (.write writer (str a b c)) or (.write writer a)(.write writer b)(.write writer c)

11:33 ordnungswidrig: wink: copy it form here http://unicodesnowmanforyou.com/

11:33 wink: boo

11:34 kungi: wink: where are you from?

11:38 mikerod: Is there any chance that in a "hot spot" of code that `apply` would be quite a bit slower than doing a direct function invocation?

11:38 Bronsa: mikerod: yeah

11:38 mikerod: I know there has to be more overhead to going through the AFn.applyToHelper

11:39 gfredericks: mikerod: also sequence construction/traversal

11:39 mikerod: but is something like this preventing some good JVM optimizations from happening?

11:39 wink: ordnungswidrig: there you have it. caps-n is now ☃

11:39 mikerod: I end up seeing profiling showing me a lot of PersistentList#first happening

11:39 wink: kungi: Germany

11:39 Bronsa: you're definitely preventing some clojure optimizations too

11:39 mikerod: from the applyToHelper

11:39 Yikes, I never knew this

11:39 kungi: wink: yes I am aware of that where in germany

11:39 mikerod: I guess it is obvious

11:40 Bronsa: mikerod: only in some cases though, e.g. when using a primitive function or a protocol function

11:40 mikerod: Bronsa: gfredericks thanks for the feedback. Looks like I need to play around with restructuring this code a bit.

11:40 Bronsa: or an inlineable one

11:40 mikerod: Bronsa: oh... it is a protocol function...

11:40 wink: kungi: why are you aware? because I can type ß? ;) Munich it is

11:40 mikerod: now that I think of it

11:41 kungi: wink: yes because you have an ß on your keyboard.

11:41 wink: I am from Mannheim

11:41 Bronsa: mikerod: direct protocol invocations have a callsite cache

11:41 mikerod: I didn't see anything from the profiling that "looked protocol-fn'ish", but who knows if it'd show up

11:41 clgv: humm, neithder wink nor kungi are on #clojure.de ...

11:41 mikerod: Bronsa: Yeah, I've seen some of this in the compiler before. I definitely haven't dug into the details though.

11:41 wink: kungi: I have us-intl with a custom xmodmap :P

11:41 kungi: clgv: there is a clojure.de?

11:42 wink: clgv: didn't know it existed until now :D

11:44 mikerod: Bronsa: Is there anywhere out there that explains this callsite caching at all?

11:45 Bronsa: no

11:45 mikerod: Bronsa: I'm just interested in mechanics of that and how to be sure to utilize it. Is one of those things that just comes down to reading through the Compiler, etc?

11:45 Yay. :P

11:46 I don't mind reading the details, but I do love it when I can first come across some design talk/notes or something.

11:56 literary: Is there some kind of mnemonic to remember which of cond and case take an odd number of args or takes a truthy value like :else?

11:56 Every single time, I have to look it up in Dash.

11:58 Also, does Clojure have goto? Right now I have code stored in an anonymous function which I call on two of three cond branches.

12:02 csd_: Why would having AOT compilation enabled cause class not found errors when I try to run an uberjar? Adding ^:skip-aot to :main was the only thing that was able to fix this.

12:02 literary: So many questions, so few answers.

12:04 mdrogalis: csd_: Not that I know of, no, and because AOT is hairy.

12:04 Answered in order.

12:05 csd_: weird, fair enough

12:05 kungi: csd_: are the namespaces present in the uberjar?

12:06 stuartsierra: literary: Only `cond` uses an :else clause

12:07 literary: No, Clojure does not have anything like goto.

12:07 csd_: kungi: There were a bunch, but what resolved the problem was doing ^skip-aot to the .core ns that contains -main

12:07 literary: Okay I'll try to come up with a mnemonic.

12:07 mdrogalis: Er, meant to reply to literary, not csd_. Sorry.

12:09 kungi: stuartsierra: Can I prevent tools.namespace.repl/refresh from trying to load the test namespaces? I moved all test dependencies to the :test profile in leiningen and now refresh breaks.

12:09 stuartsierra: kungi: Yes, you can change the set of directories that `refresh` uses.

12:10 kungi: http://clojure.github.io/tools.namespace/#clojure.tools.namespace.repl/set-refresh-dirs

12:10 mr_rm: I'm using Liberator (http://clojure-liberator.github.io/liberator) and i'm confused by something. My :handle-created function is getting called even when I'm doing a GET (also on POST). Is that normal behavior? The HTTP response for my GET is 200 but it's still calling the :handle-created handler.

12:11 * stuartsierra steps away

12:12 literary: "C.O.N.D. = continuously obeisant, never diacritic"

12:12 no that won't do

12:12 "COND -> can't otherwise notify deadra"

12:13 this is hard

12:13 "cond uses :else -> cuz otherwise nobody does"

12:13 okay that one works.

12:14 donbonif_: isn't this: (fn [x] true) the same as this: #(true) ?

12:14 literary: donbonif_: No.

12:14 donbonif_: same as (fn [x] (true))

12:14 ,(#(true))

12:14 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.IFn>

12:14 donbonif_: ohhhh, that's it. thanks literary

12:14 literary: My pleasure.

12:29 mr_rm: I'm using Liberator (http://clojure-liberator.github.io/liberator) and i'm confused by something. My :handle-created function is getting called even when I'm doing a GET (also on POST). Is that normal behavior? The HTTP response for my GET is 200 but it's still calling the :handle-created handler.

12:40 kungi: stuartsierra: thank you

12:53 razum2um: can I destruct a vector like this (let [[x & ys z] (range 10)] (println ys)) ?

12:54 this obviosly doesnt work but you get the idea?

12:54 dnolen_: razum2um: you cannot

12:54 razum2um: dnolen_: so I should use butlast ?

12:54 dnolen_: razum2um: yes

12:55 razum2um: btw, is this a fundamental restriction of ISeq or just wait to be implemented?

12:55 i understand, that in case of lazyseq it realizes it

12:56 but so butlast does anyway

12:58 dnolen_: razum2um: I don't personally see the value of supporting this kind of sugar. butlast + last work fine

12:59 Bronsa: dnolen_: by that same logic, first and rest work fine too :) I've had the desire for a destructuring syntax from both ends too

13:00 dnolen_: Bronsa: first/rest can obviously work relatively efficiently for seqs, not true for this

13:00 razum2um: dnolen_: still, don't get why not? so ruby does: a, *b, c = (1..10).to_a; b

13:01 dnolen_: razum2um: anyways, I'm placing my bet now this will never happen :)

13:02 Bronsa: dnolen_: right, I'm just saying it's not unreasonable to expect the existence of some sugar for that, after all we have special sugar for map destructuring

13:03 razum2um: Bronsa: exactly. I miss map destruction in ruby, it's awesome ;)

13:03 Bronsa: razum2um: not sure what you mean with that, clojure can already destructure maps

13:03 razum2um: yes, I know

13:03 dnolen_: razum2um: rhickey is a relatively perf conscious lang designer - in general sugary constructs with linear complexity are avoided

13:04 Bronsa: razum2um: ah yeah I get it now

13:07 razum2um: dnolen_: actually, why do variables need to be realized instantly? in this case [a &b c] - c might be like a future and b still a lazyseq of butlast result

13:08 under the hood it will be the same as actuall call but more concise

13:08 dnolen_: btw, it this behaviour doable by macros?

13:08 dnolen_: razum2um: your idea doesn't seem to jive with future or deref'ing patterns that already exist in the language

13:09 razum2um: no implicit future would need compiler support

13:11 razum2um: dnolen_: mm, look it doen't need to be actual IDeref, it can be just transformed in the scope somehow to @c

13:11 by parser i mean

13:11 dnolen_: razum2um: which doesn't address it being returned as a value

13:12 razum2um: dnolen_: sorry, don't understand you

13:12 devn: Given I have {:name "foo" :id 1 :children [{:name "bar" :children [{:name "baz"}]}]}, I want: [{:name "foo" :id 1} {:id 2 :name "bar" :parent-id 1} {:id 3 :name "baz" :parent-id 2}]

13:12 dnolen_: razum2um: if it escapes the let binding i.e. gets returned as a value

13:17 razum2um: dnolen_: yep, got you, but still parser can detect these cases like it does with recur and transform internally to let + [a b @c] where b already got realized

13:17 dnolen_: razum2um: if you can't solve escaping, the other parts don't really matter

13:19 razum2um: dnolen_: sorry, but still don't get you. I won't optimize this by hijacking futures, just sugar. anyway in this case i care about b, not c and b still can stay lazy

13:20 actually i mean [a &b _]

13:21 otherwise [a &b c] - parser can (should) realize b and get last one

13:21 kungi: Is there a refactoring tool to rename symbols project wide in emacs?

13:22 dnolen_: razum2um: or you could just right a simple function that does this

13:22 razum2um: dnolen_: hm, yes. perhaps it's best one

13:22 dnolen_: (defn foo [x & xs] [x (butlast xs) (last xs)])

13:23 (let [[a b _] (foo (range 10))] ...)

13:24 razum2um: dnolen_: hm, are you sure xs isn't gtting realized inside foo?

13:24 dnolen_: razum2um: yes it will be realized by the call to last, if you really don't care about the last thing then just use butlast

13:25 razum2um: :\ ok, will stay with that, thanks!

13:35 cYmen: What's the preferred browser connected repl these days? Do people still use brepl?

13:35 dnolen_: cYmen: I do for simple stuff, but Weasel is very popular now

13:37 cYmen: Differences? Reasons?

13:38 mikerod: In clojure.core/emit-defrecord I was looking at the impl

13:38 This line particularly regarding hasheq made me think: `(hasheq [this#] (bit-xor ~type-hash (clojure.lang.APersistentMap/mapHasheq this#))

13:38 type-hash is just (hash classname)

13:38 how is this guaranteed to not ever collide 2 class names to the same hash

13:39 So 2 classes, same classname hash and same map contents would be =

13:39 Bronsa: mikerod: hashes don't have to be unique

13:39 mikerod: Bronsa: I know, and if they weren't we could get a false positive for =

13:39 that's why I'm asking

13:40 Bronsa: mikerod: if two colls have a different hash, they are guaranteed to be different, if two colls have the same hash they are not necessarily equal

13:40 mikerod: However, this is a (hash classname), which I think is really a clojure.lang.Util#hasheq call on a String

13:40 which uses Murmur3.hashInt so maybe it isn't likely enough to matter?

13:41 Bronsa: mikerod: no you have a misuinderstanding of how = uses the hash. it's only used as a fast path for not-equality

13:41 mikerod: Bronsa: Oh, duh. I confused what is used by =

13:41 `equiv` is the impl I should have been looking at.

13:42 Which has a `(identical? (class this#) (class ~gs))` :P

13:42 I sometimes get mixed up in the whole hasheq, equiv, hashCode, equals world

13:44 I see that types created via defrecord, when posing as java.util.Map's would be in the #hashCode and #equals space; but when in Clojure dealing with `hash` and `=` they are working in the hasheq and equiv space. But sorry, I got mixed up with the hasheq vs equiv in this case.

13:44 devn: Hey, sorry for the repeat, but I can't brane good and have a case of the dums. Given I have {:name "foo" :id 1 :children [{:name "bar" :children [{:name "baz"}]}]}, I want: [{:name "foo" :id 1} {:id 2 :name "bar" :parent-id 1} {:id 3 :name "baz" :parent-id 2}]

13:45 cYmen: Man, I wish there was a nice clojure/clojurescript ide for windows.

13:45 devn: basically i want to flatten out the children, but have them reference their parent's id

13:45 Bronsa: cYmen: have you tried cursive?

13:45 justin_smith: cYmen: have you tried cursive?

13:45 haha

13:45 cYmen: I've heard about it but I have not

13:45 Bronsa: lol

13:45 technomancy: does CCW not handle cljs?

13:46 noonian: well... there is always emacs :P

13:46 cYmen: noonian: Well, I have emacs.

13:46 And I just spent forever setting it up on this machine.

13:47 arrdem: devn: for is your friend

13:47 * arrdem boots a repl

13:47 noonian: get your .emacs in version control and your set for life!

13:47 cYmen: I definitely need to do that...

13:47 Bronsa: noonian: +1

13:48 mikerod: devn: Did you mean to leave off the :id from the second parent?

13:48 devn: Did you mean that every level of the hierarchy is supposed to have an :id on it?

13:49 devn: From the example, it looks like there is an :id 1 for :parent-id 1, but then it is just like the "depth" that is how you come up with :parent-id 2

13:49 arrdem: +1 mikerod, the first child should probably have an id

13:53 mikerod: devn: if there are :id's at every level, something like clojure.walk/postwalk would work if you aren't going to run into any quirks there, (like losing metadata you need on something :P )

13:54 arrdem: devn: https://www.refheap.com/91412

13:58 dnolen_: cYmen: I guess because it uses nREPL & WebSockets? A lot of CLJ/CLJS lein templates now ship w/ it which means less config

14:02 technomancy: greghendershott: re: prefixing in require, it's not about avoiding collisions as much as it is about being able to tell at a glance which identifiers come from the current namespace vs those that are external

14:02 cfleming: cYmen: I develop Cursive - I don't develop much with CLJS myself, but a bunch of users have reported success with Weasel. It requires less config as dnolen_ says and the connection seems more reliable as well. Additionally you can use it to connect to more types of target (node.js, embedded JavaScriptCore on iOS etc).

14:02 technomancy: greghendershott: since we don't have the fancy drracket arrow stuff =)

14:02 (carrying over the conversation from another channel)

14:03 greghendershott: also, it's not a requirement to place tests in separate files, just a default

14:03 cfleming: technomancy: How does the DrRacket arrow stuff work? I saw a screenshot in your blog post but wasn't sure what it was showing me.

14:04 justin_smith: greghendershott: when your symbols are prefixed, it makes refactoring a big namespace (those are the ones you most likely need to refactor) very easy

14:04 technomancy: cfleming: that image was a stack trace; here I'm actually talking about how you place the pointer over an identifier and it will show a line to where it's coming from

14:04 either the arglist or a require form

14:04 greghendershott: technomancy: justin_smith: Thanks, that's helpful to understand the motivation.

14:04 cfleming: technomancy: Nice, thanks

14:05 technomancy: cfleming: the arrows for the stack traces are actually a lot more helpful IMO

14:05 cfleming: technomancy: They indicate where in the source the trace elements come from?

14:05 technomancy: cfleming: right

14:06 mikerod: devn: Oh, yeah I meant prewalk there

14:06 cfleming: technomancy: That is cool.

14:06 mikerod: devn: https://www.refheap.com/91413 was my prewalk example, I'd probably prefer arrdem style more

14:07 technomancy: greghendershott: also as a note, recur is considered a very low-level primitive in clojure; as a newbie most of the time you should consider re-framing the problem in terms of sequences

14:10 _pr0t0type_1: Hey guys, how does the order of 'into' work? Does it even matter? It seems like it would matter when your're conjoining special forms. ie (into '(if) '(true)) ==> (true if)

14:11 arrdem: _pr0t0type_1: conj makes no guarantees about order, deferring to conj for behavior

14:11 s/conj/into/g

14:12 dnolen_: _pr0t0type_1: depends on the collection, as arrdem says, conj is polymorphic on it's argument

14:12 arrdem: _pr0t0type_1: some examples http://grimoire.arrdem.com/1.6.0/clojure.core/conj

14:13 _pr0t0type_1: I see

14:13 Thanks guys, this makes sense

14:13 arrdem: any word on how close we are to 1.7 dropping?

14:14 devn: arrdem: nested :children won't have :id, it'll need to be added

14:15 arrdem: devn: counting from what... the id of the parent?

14:15 devn: yes

14:15 it also should include the root as a row

14:15 where parent-id would be nil

14:16 cfleming: arrdem: Seems like it's closer than expected since they want to get transducers out to the world - that's why a bunch of stuff got moved to 1.8 yesterday

14:16 arrdem: I would say keep the recursive mapcat of pulling children out and do a zipmap (partial apply assoc)

14:16 mi6x3m: how would you name a binding holding a namespace clojure?

14:16 n?

14:17 arrdem: cfleming: yeah I'm feeling sooner rather than later given yesterday's jira noise as well

14:17 puredanger: yes

14:17 justin_smith: mi6x3m: well, it can't literally hold a namespace, only the symbol of the ns, since namepsaces are not first class

14:17 mi6x3m: justin_smith: well they are in java

14:17 llasram: justin_smith: ? &*ns*

14:18 Man, always do the wrong syntax: ##*ns*

14:18 No, needs to be a list. Whatever, you get the idea

14:18 mi6x3m: ,*ns*

14:18 clojurebot: #<Namespace sandbox>

14:18 justin_smith: right - I appear to be confused, sorry

14:18 mi6x3m: ,(let [n *ns*] n)

14:18 clojurebot: #<Namespace sandbox>

14:19 llasram: mi6x3m: A local identifier referring to a namespsace object? I'd call it just `ns`

14:19 devn: arrdem: example? sorry, not following you on the zipmap partial apply assoc

14:19 mi6x3m: llasram: I prefer n, but seems to be a matter of taste :)

14:20 foodoo: Hi, any recommendations for a Clojure library (maintained) that I can use to send and receive HTTP REST requests?

14:21 justin_smith: clj-http is decent

14:21 arrdem: devn: nevermind. after sketching that out it wouldn't work :P

14:22 foodoo: justin_smith: thanks. There is just too much choice on clojars

14:22 mi6x3m: foodoo: http-kit :)

14:22 justin_smith: right - and for basic stuff you can even use slurp

14:23 ,(slurp "http://www.google.com")

14:23 clojurebot: #<SecurityException java.lang.SecurityException: denied>

14:23 justin_smith: :P

14:23 mi6x3m: foodoo: http-kit offers a client and a server, very easy to use

14:23 noonian: foodoo: if you are using http-kit for your server then i'd use their client also just to avoid another dependency

14:24 foodoo: I want to write a client. The server already exists (Cytoscape cyREST)

14:24 mr_rm: I'm using Liberator (http://clojure-liberator.github.io/liberator) and i'm confused by something. My :handle-created function is getting called even when I'm doing a GET (also on POST). Is that normal behavior? The HTTP response for my GET is 200 but it's still calling the :handle-created handler.

14:25 ustunozgur: is there a version of interleave that continues taking after one coll is exhausted? (interleave [1 2] [3 4 5]) should return [1 3 2 4 5] for example instead of [1 3 2 4]

14:25 equivalent in underscore is for example _.compact(_.flatten(_.zip(array1, array2)))

14:27 bbloom: ,(mapcat vector [1 2] [3 4 5]) ; maybe something like this

14:27 clojurebot: (1 3 2 4)

14:27 bbloom: no still note quite

14:28 opqdonut: bbloom: no, that stops after two elements

14:28 I can't think of an easy way to do it

14:29 stuartsierra: rewrite interleave

14:30 opqdonut: ,(let [a [1 2] b [3 4 5 6]]] (concat (interleave a) (drop (count a) b) (drop (count b) a)))

14:30 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

14:30 opqdonut: ,(let [a [1 2] b [3 4 5 6]] (concat (interleave a) (drop (count a) b) (drop (count b) a)))

14:30 clojurebot: (1 2 5 6)

14:30 bbloom: ,(mapcat conj (concat (map vector [1 2]) (repeat [])) [3 4 5])

14:30 clojurebot: (1 3 2 4 5)

14:31 opqdonut: heh

14:31 ,(let [a [1 2] b [3 4 5 6]] (concat (interleave a b) (drop (count a) b) (drop (count b) a)))

14:31 clojurebot: (1 3 2 4 5 ...)

14:31 opqdonut: there

14:31 bbloom: then you need to know which one is shorter

14:31 stuartsierra: `count` destroys laziness

14:31 mi6x3m: opqdonut: almost readable :)

14:31 opqdonut: bbloom: since you can't append repeat [] to both

14:31 stuartsierra: yeah, a lazy solution would need tobe written from scratch I think

14:32 bbloom: yeah, coding it recursively with lazy-seq is surely the way to go

14:33 mikerod: cfleming: I was a bit sad for some of the things pulled from 1.7

14:34 However, transducers sooner than later is cool too

14:34 arrdem: devn: https://www.refheap.com/91415 cheating with mutable state

14:34 ustunozgur: this one (called weave) is by fogus in js: https://github.com/documentcloud/underscore-contrib/blob/master/underscore.array.builders.js#L95

14:35 puredanger: Hey all, Chas asked us to do the State of Clojure/ClojureScript survey this year and it is now available - would be great to see responses from any and all! http://blog.cognitect.com/blog/2014/10/3/2014-state-of-clojure-clojurescript-survey

14:37 justin_smith: opqdonut: https://www.refheap.com/91416

14:37 my attempt

14:37 devn: arrdem: haha booo!

14:38 arrdem: we did it with a reduce where we call ourselves and change the initial value

14:38 because we didn't want an atom :)

14:38 arrdem: devn: lols. you could do it "purely", but then you can't use mapcat because you need to know how many children were returned

14:38 yeah a reduction and a work queue would be more natural for that approach

14:55 michaelmeixner: noob-question

14:55 I can do:

14:56 (map (fn [x] [x 7]) [:a :b])

14:56 but not:

14:56 (map #([% 7]) [:a :b])

14:56 Why not?

14:56 bbloom: ,'#([% 7])

14:56 clojurebot: (fn* [p1__25#] ([p1__25# 7]))

14:56 gfredericks: #() is not good for returning literals

14:56 bbloom: michaelmeixner: does that make it clear?

14:57 hiredman: puredanger: I use clojure for everything, so I am not sure how to answer the "what has stopped you from using clojure for more" question

14:57 puredanger: then don't check anything :)

14:57 gfredericks: hiredman: "biological needs"

14:57 hiredman: haha

14:57 puredanger: maybe I should add "I am using maximum Clojure" :)

14:57 I actually had the same response :)

14:58 michaelmeixner: bbloom not clear immediately, but something to think about - thanks!

14:58 bbloom: michaelmeixner: basically #(...) is short for (fn [...] (...))

14:58 michaelmeixner: note the extra parens

14:58 hiredman: the only thing stopping me from using it more is other people keep writing code in other languages :/

14:58 noonian: michaelmeixner: the shorthand fn notation creates a function that always calls another function, so writing #([% 7]) when applied to the first element :a will eval the expression '([:a 1]) which throws the error

14:58 bbloom: michaelmeixner: when you write #([%]) that's the same as (fn [x] ([x])) which is trying to call the vector like a function, but with no arguments

14:59 michaelmeixner: aha!

14:59 guess i got it

14:59 TimMc: in fact...

14:59 ,(macroexpand-1 '#())

14:59 clojurebot: (fn* [] ())

14:59 TimMc: ,(#())

14:59 clojurebot: ()

15:00 noonian: you could do #(vector % 7)

15:00 TimMc: #(do [% 7])

15:00 noonian: or #(vec [% 7])

15:00 TimMc: nice! and you've found the usecase for do that does not involve side affects that I couldn't come up with!

15:00 (inc TimMc)

15:00 lazybot: ⇒ 73

15:01 bbloom: puredanger: the usefulness question seems like you're going to get ambiguous answers between usefulness and desired usefulness ... particularly the question about startup performance

15:01 it would be very useful to me if startup performance was better

15:01 but the poor startup performance now is not useful at all :-P

15:01 technomancy: bbloom: yeah, my answers were mixed on those questions

15:02 puredanger: that's essentially the same question we've had in the past years. it has its issues but I kept (as much as I could across changing form hosts) the intent

15:02 at this point, don't want to change anything, will just have to be feedback into next year

15:03 justin_smith: for the "what has been more frustrating" would the answer "runtime performance" also include "runtime resource usage" ?

15:03 bbloom: puredanger: i figured it was too late to change, but worth knowing if the data is funky

15:03 puredanger: justin_smith: sure

15:04 ustunozgur: having "I've stopped using it" just after 6+ years is slightly worrying : ) seems like a sequence of events when read top to bottom.

15:08 devn: Is there a simple way to avoid AOT in a WAR created via ring?

15:09 justin_smith: devn: I think at the very least you need a compiled class that the container can invoke

15:09 but you could use a shim and avoid all other AOT

15:10 bbloom: wufoo just ate my cljs survey form

15:10 it said whoops w/ a 500

15:10 not sure if it went through or not

15:10 form data is lost though :-(

15:10 devn: justin_smith: like this? https://gist.github.com/devn/3acd0c210113721eb024

15:11 AeroNotix: puredanger: the questions on that survey are a bit weird

15:11 "How useful have these aspects been to you" => Performance

15:11 devn: justin_smith: this seems messy to me, would be nice to have a simpler way to do this

15:11 AeroNotix: and then the answers are "Not useful" to "Very useful"

15:11 justin_smith: devn: agreed

15:11 AeroNotix: which aspect of performance?

15:12 what's the scale here?

15:12 nullptr: yeah, how could transducers be "useful" to anyone at this point?

15:12 devn: justin_smith: who to talk to? :)

15:12 AeroNotix: are we answering whether the performance is bad or good?

15:12 justin_smith: devn: tbh I have always just done aot to deploy wars, and it always worked

15:12 puredanger: interpret it as you will and we will try to make it better next year

15:12 AeroNotix: puredanger: ok

15:12 "Extensible reader" lolwat?

15:12 devn: justin_smith: the problem is when 3rd party libs that aren't AOT safe start getting into the mix

15:12 justin_smith: devn: but hypothetically only the part the container accesses needs aot, and it can invoke the rest, beyond that your guess is likely as good as mine

15:12 devn: yeah, that would be a problem

15:13 puredanger: all of those rows are from the last 4 years of survey. the question types were a little different in wufoo and I made up the column choices.

15:13 AeroNotix: puredanger: what extensible reader?

15:13 puredanger: tagged literals

15:13 AeroNotix: ^String "fooo" ?

15:13 puredanger: ?

15:13 puredanger: http://clojure.org/reader#The Reader--Tagged Literals

15:14 AeroNotix: holy shit

15:14 arrdem: http://clojure.org/reader#The%20Reader--Tagged%20Literals

15:14 justin_smith: devn: on the bright side, the shim isn't a seed of ugliness that will inevitably spread outward - it is an adaptor layer allowing the ugliness to be absent elsewhere

15:14 and it's not horrifying levels of ugly

15:15 devn: justin_smith: it seems like a patch to lein and/or ring would be a nice fix

15:15 justin_smith: yes, patching lein and or ring so you don't need the shim would be great - it's also a big task

15:17 verma: I am working on this state driven 3D engine mostly for rendering point clouds (for http://plas.io), all things are added and removed by updating a state, e.g. if you want to change the location of the camera you basically do an (assoc state [:view :camera] [0 0 0])

15:17 puredanger: arrdem: thx, I hate those goofy anchors

15:17 verma: and the engine takes care of making sure that the currect javascript objects are manipulated

15:17 AeroNotix: puredanger: ok filled it in, where's my cheque :)

15:17 arrdem: puredanger: <3

15:17 verma: now I need to pass in huge amounts of point data into it, but don't want it held up in the state

15:17 puredanger: AeroNotix: it's in the mail to the address you provided :)

15:18 AeroNotix: puredanger: GOOD!

15:18 arrdem: I wonder where mail addressed to Null goes...

15:18 verma: thinking of storing stuff in local storage tagged with an ID

15:18 and then passing that ID to the renderer

15:18 the renderer just reads from local storage

15:18 and then clears it out or something

15:18 any ideas?

15:19 justin_smith: verma: have you looked at the "entity component system" design at all?

15:19 technomancy: devn: patches to lein?

15:20 puredanger: arrdem: re 1.7 wonderings in the back chat, goal is to get through this stuff http://dev.clojure.org/jira/secure/IssueNavigator.jspa?mode=hide&requestId=10519 and release a beta

15:20 verma: justin_smith, I think it is sort of similar

15:21 arrdem: puredanger: feature expressions... glhf

15:21 puredanger: arrdem: everything else was pushed to 1.8. rather than thinking about pushing off, really thinking about it as dropping a release where we are now as people need a transducers ga

15:21 justin_smith: devn: technomancy: giving it more thought - is this really just a lein / ring issue? the container needs a compiled class, that is not negotiable - what could lein or ring do - make it so aot was not transitive?

15:22 devn: technomancy: to avoid AOT, having a shim like `(ns my.aot.avoider (:gen-class)) (def main-ns "my.aot.app") (defn -main [] (require (symbol main-ns)) ((resolve (symbol main-ns "-main"))))`

15:22 puredanger: I smell CLJ-322 :)

15:22 technomancy: devn: I can't think of a decent way to make that happen from lein

15:23 puredanger: and it distresses me that I did not need to look up that ticket number

15:23 justin_smith: puredanger: yeah, that's the real fix, thanks for pointing that out

15:23 (inc puredanger)

15:23 lazybot: ⇒ 17

15:24 arrdem: ugh. PSA: version your URLs lest your routing scheme become context sensitive

15:24 technomancy: justin_smith: if ring shipped with a class file that could defer to a clojure namespace that would do it

15:24 justin_smith: I mean, probably? I know nothing about war files, but assuming they're like jar entry points

15:25 devn: hmmmm

15:25 justin_smith: technomancy: a war is a jar with a special format, and like a jar it has an entry point (that the java container process uses)

15:25 verma: justin_smith, I really don't want to design a 3D engine per se, mostly an abstraction over existing engines, so that I can "visualize" a state, I may later want to pull this state out, send it over the network to see exactly the same view

15:26 justin_smith, ECS seems more like here's how to do it, which I am already sort of doing, mostly property watchers and custom "render state" updaters

15:26 justin_smith: verma: I don't think the entity component system thing is at all 3d specific, it's more about a way of organizing your data (and it's a data oriented way of constructing a game)

15:26 devn: technomancy: what about the generation of that entry point as an option?

15:26 justin_smith: verma: and I mentioned it exactly because what you are doing already kind of reminded me of it

15:27 technomancy: devn: why generate one? just include it in ring

15:29 justin_smith: or write and compile a very small java class that simply uses the java API to spin up clojure and create the handler

15:29 weavejester: Lein-Ring could certainly have a servlet shim in it. I don’t necessarily know about Ring itself. I tend to be more conservative with that project.

15:29 justin_smith: but that's not much different from the pure clojure shim you already had in that paste

15:29 weavejester: I just don’t really use lein-ring these days. I’m trying to give more people commit access

15:29 I should probably add a note in the README to that effect

15:30 verma: justin_smith, nice :) I use THREE.js for rendering right now, which I think has ECS at its core, I am basically trying to take a state and "view it" I guess, only problem is the state has the potentional of blowing up in size :P

15:33 basically the incoming state forms "keys" in my render state, if the incoming state has a huge object it becomes a key :P

15:36 devn: weavejester: would you be opposed to something like we were discussing?

15:36 weavejester: devn: For Lein-Ring, not at all. I might even have an existing issue. I know I’ve mentioned it enough times.

15:36 devn: weavejester: like: :ring {:aot :none, :handler my.app/handler, :init my.app/init} ?

15:36 weavejester: devn: Why use aot at all?

15:36 devn: yeah there's an issue here: https://github.com/weavejester/lein-ring/issues/52

15:37 weavejester: If people want AOT, they can explicitly set it using normal Lein options, right?

15:37 I don’t see any reason not to use a shim instead of AOT to generate the servlet class.

15:38 justin_smith: yeah, it could be a very small java class, with a config that tells it which clojure ns to load up, and the function in that ns to call

15:38 myguidingstar: puredanger, I've just look at the survey

15:39 in the Clojure one: How useful have each of these aspects of Clojure been to you and your projects?

15:39 I think logic programming and pattern matching should be mentioned, too

15:39 devn: weavejester: this brings it back to lein then, no? /cc technomancy

15:39 puredanger: myguidingstar: those aren't part of the Clojure language though?

15:40 weavejester: devn: lein-ring

15:40 myguidingstar: well, I see 'reducer' and 'tranducer' there

15:41 puredanger: myguidingstar: those are part of the core library

15:41 myguidingstar: okay

15:41 and in the Clojurescript one

15:41 in the question Which JavaScript environments do you target?

15:42 can you add ArangoDB's FOXX?

15:42 it's similar to CouchDB's but more complete

15:43 puredanger, https://www.arangodb.org/foxx

15:44 puredanger: myguidingstar: added

15:44 myguidingstar: many thanks

15:53 puredanger, in the Clojurescript survey, I find this question unclear: In which contexts do you use each of ClojureScript's optimization settings? :none, :simple ...

15:54 puredanger: yeah...

15:54 devn: weavejester: technomancy: let me send you a doc and you guys tell me what patches to submit to make life easier: https://www.dropbox.com/s/medk1iocrqu9nk2/war-jar-aot-oh-myyyyy.pdf?dl=0

15:55 puredanger: myguidingstar: ah, that question did not get correctly transferred from last year's survey, sorry about that

15:56 myguidingstar: I've tweaked to at least make some sense, but I can't really change it without altering the survey too much at this point.

15:57 myguidingstar: then?

15:58 nullptr: puredanger: most people qualified to answer that question probably interpreted it correctly

15:58 justin_smith: devn: hey, that's a good summary

15:59 devn: minor nitpick, the text references highlighting, and my pdf reader shows no highlighting (inline pdf display in google chrome)

15:59 devn: justin_smith: ah yeah, the highlighting isn't all that helpful fwiw

16:00 justin_smith: if you have a suggestion here im interested as well. basically what im hearing is: lein-ring should never AOT, since you could choose to AOT with lein anyway if you really wanted it

16:00 but im not sure what the story is on the JAR side

16:00 csd_: Is there a function that will take [vec1], [vec2] and return [{v11 v21} {v12 v22}...]?

16:02 justin_smith: ,(map hash-map [:a :b :c :d :e] [0 1 2 3 4])

16:02 clojurebot: ({:a 0} {:b 1} {:c 2} {:d 3} {:e 4})

16:02 justin_smith: why though?

16:03 csd_: just trying to simplify a korma statement

16:03 justin_smith: OK

16:03 myguidingstar: puredanger, the order should be: :none, :whitespace, :simple, :advanced

16:03 csd_: list of ids and a list of values, this way i can combine them into one statement

16:03 myguidingstar: sorry for being so annoying

16:04 puredanger: myguidingstar: I'm not going to change that, not sure how changing the ordering affects the data recording

16:04 devn: justin_smith: correct me if you read differently in the above conversation, but i am hearing: 1) never AOT in ring, 2) lein can't do what im asking, but I'm not sure #2 is true. I want to say: `:aot :none, :main mycorp.miwidget.app`, and have the gen-class entry point shim created for me

16:04 myguidingstar: I see

16:04 csd_: devn: what are you trying to do?

16:05 devn: csd_: read above. there's a document i referenced.

16:05 csd_: in short, avoid all AOT in JARs and WARs without needing to create a shim every time.

16:06 justin_smith: devn: well clojure.core could do that, or lein could do that, or ring could, or lein-ring could - but it's a weird ugly thing to implement and it seems everyone would naturually be happier if the feature was in someone else's project (except clojure.core, which is simply conservative, and that would be a huge change I think)

16:08 technomancy: devn: are you trying to avoid all AOT, or just AOT during development?

16:09 weavejester: The servlet shim should go in Lein-Ring, IMO.

16:09 Or else be a separate library.

16:10 It probably doesn’t belong in Ring.

16:10 And definitely doesn’t belong in Lein or Clojure, if that’s been suggested!

16:10 hiredman: https://github.com/hiredman/lein-ring

16:11 justin_smith: weavejester: I meant not specifically the shim (that's a means to an end) but the non-transitive aot solution (another means to the same end)

16:12 technomancy: there exist simple ways of avoiding dev-time AOT with uberjars. I don't know about wars.

16:12 weavejester: justin_smith: Hm… I’m not sure how that would work, but that’s an interesting idea.

16:12 justin_smith: technomancy: he specified he needed to avoid all aot, even for deployment

16:12 weavejester: technomancy: Lein-Ring currently generates a Clojure AOTed namespace to act as the servlet. It would be better replaced with a Java shim, IMO.

16:13 hiredman: https://github.com/hiredman/lein-ring/blob/master/java/com/thelastcitadel/Servlet.java

16:13 weavejester: hiredman: Are you working on a PR?

16:14 hiredman: no, I deleted a bunch of stuff

16:14 technomancy: hm; ok. nearly all the AOT issues I've seen so far are due to reloading, so AOT strictly for uberjars sidesteps that.

16:14 but there could be other issues I'm unaware of

16:14 justin_smith: technomancy: something about libs that break when aot-compiled

16:14 technomancy: justin_smith: like old versions of core.match?

16:14 devn: third party libs are not always guaranteed to be AOT friendly

16:15 hiredman: weavejester: I don't want any of the dev middleware or the browser launching whatever

16:15 technomancy: seems like this is just routing around the root issue

16:15 justin_smith: hiredman: that java shim looks like a good way to approach it

16:15 devn: technomancy: but what is the alternative?

16:15 hiredman: and I am not actively working on it, I forked, sliced it up, and have started using it for my stuff

16:15 weavejester: hiredman: Okay, but none of that’s added to the war file anyway.

16:16 technomancy: devn: if a library has bugs they should be fixed?

16:16 dbasch: I had trouble AOT’ing apps to run on hadoop

16:16 technomancy: I mean obviously the real world isn't that simple, but this should be considered a workaround rather than a long-term solution

16:16 devn: technomancy: totally agreed, but for now, i think the workaround is preferred

16:16 technomancy: sure

16:17 justin_smith: technomancy: right, which is why that non-transative AOT thing that puredanger pointed out looks nice (though I don't know if there is any clear way to implement it)

16:17 AeroNotix: any recommendations for graphing libraries?

16:17 devn: AeroNotix: rhizome

16:18 dbasch: parkour in particular does some compile-time reflection using the hadoop library you’re compiling against

16:18 AeroNotix: devn: looks nice, but not for my use-case

16:19 devn: wait, where did puredanger mention non-transitive AOT?

16:19 puredanger: http://dev.clojure.org/jira/browse/CLJ-322

16:20 technomancy: justin_smith: given its low issue ID, odds are low?

16:20 puredanger: I think if it had a consensus approach, could definitely move forward. not sure if that exists though.

16:24 devn: puredanger: i haven't read the whole thread in detail, but has rich peeked at this ticket recently?

16:24 technomancy: heh, yeah... this is assembla-old

16:25 devn: i only ask because there's one person in particular who can achieve consensus by using his fist :)

16:25 amalloy: chuck norris is a clojure developer?

16:25 devn: that would be roundhouse kicks ;D

16:25 bbloom: "assembla-old" is an amusing phrase

16:26 devn: technomancy: so, did i hear right that you wouldn't be totally opposed to having a workaround in lein?

16:26 technomancy: devn: there sort of is a workaround in lein

16:26 it breaks a bunch of things though

16:27 :clean-non-project-classes

16:27 devn: what is the workaround, and what does it break? :)

16:27 technomancy: iirc the problem is protocol functions don't gracefully fall back when they're AOT'd but refer to namespaces that aren't

16:27 so just don't use protocols; problem solved =)

16:27 devn: haha

16:28 technomancy: I don't want to put anything war-specific in lein though

16:28 puredanger: devn: I have not talked to Rich about it since 1.6 timeframe, don't recall a strong opinion. there is some more stuff on it here: http://dev.clojure.org/display/design/Transitive+AOT+Compilation

16:28 justin_smith: devn: technomancy: I can see how that could work - your "shim" ns doesn't need to not require other namespaces now, it just needs to not call any protocol functions - much nice

16:29 r

16:29 devn: puredanger: much obliged for the info

16:29 weavejester: I don’t think it’s really a good idea to put a workaround in Lein if it can be fixed in Lein-Ring.

16:30 devn: we're talking about the WAR case only right now though. the doc i posted: https://www.dropbox.com/s/medk1iocrqu9nk2/war-jar-aot-oh-myyyyy.pdf?dl=0 discusses JAR stuff at the bottom

16:32 i mean, i agree with you on the ring side, yes, let's fix it in lein-ring, but even then, if i want to reference a -main and avoid AOT while still keeping the jar executable, i need a shim

16:32 technomancy: devn: actually for uberjars that's not true either

16:32 devn: which part?

16:32 technomancy: devn: set :main clojure.core, then launch it with -m my.ns

16:32 devn: yes, i forgot to mention that in this doc

16:33 technomancy: AOT is only required for uberjars if you need it to launch using bare `java -jar ...`

16:33 or rather, you need a shim, but you already have one =)

16:33 devn: technomancy: yes, we do need/want to java -jar them

16:34 technomancy: devn: gotcha. there is lein-otf for that, but it may have bitrotten due to the -m approach being simpler

16:37 devn: technomancy: thanks

16:38 christop1e: hrm, got disconnected. Contracters shortcircuited the place -_-

16:41 cYmen: About this https://github.com/swannodette/om/wiki/Basic-Tutorial under "Your first Om component" we suddenly use build all where we just used map earlier. I assume that means we are now creating some sort of subcomponent but why?

16:46 devn: technomancy: so even with otf, i couldn't convince you that kicking off a chain of AOT is undesirable and that having a workaround in leiningen would be nice? :D

16:47 technomancy: devn: you mean two workarounds?

16:47 devn: i think im confusing myself now.

16:48 technomancy: yes, i suppose then im asking for two workarounds, where it's a bit more declarative in the project.clj what will be shimmed in order to avoid AOT

16:48 technomancy: we've got a workaround in clojure (-m), a workaround in lein (:clean-non-project-classes), a workaround in a plugin, and a workaround in a patch on jira =)

16:48 devn: one where*

16:50 1) the plugin is currently broken and questions its own existence due to the ability to use -m, 2) :clean-non-project-classes according to you "breaks a bunch of things", 3) -m isn't an option for me, and 4) the patch on jira is like 4 years old

16:50 technomancy: ^

16:51 technomancy: devn: if the shim is just a class file, why does it belong in lein? why not just add it to :dependencies?

16:51 I think the lein-otf approach is right for your use case; it'd be quicker to fix the plugin than add a feature to lein

16:52 oh... actually you don't need that. you can set clojure.main as your :main and include a user.clj in the uberjar that requires and loads your own entry point

16:54 (just put user.clj in a :source-paths element that is only included in the uberjar profile)

16:55 devn: technomancy: why user.clj?

16:56 technomancy: devn: otherwise clojure.main will just drop you into a repl when used as Main-Class

16:58 it's just that this seems like a project-space concern

16:59 jeffterrell: I just read this: http://pastebin.com/bSW5dfRQ — about how HN stores session state in closures.

16:59 Just curious, is it possible to store closures in Clojure?

17:00 hiredman: no

17:01 technomancy: sort of, but not really

17:01 jeffterrell: Why not? Is it a fundamental limitation of e.g. the JVM, or is it just that nobody needed to do it yet?

17:01 amalloy: is that still true, jeffterrell? i thought they had switched to a more common method of storing sessions

17:01 jeffterrell: They have, as of recently. The link above discusses the transition.

17:01 technomancy: I thought they closed over continuations specifically

17:02 hiredman: storing closures is gross for a number of reasons, a closure is tied to the executable state of a machine

17:02 jeffterrell: technomancy: That _seems_ to be what's going on, yes. I'm not clear on the details, and I don't deeply understand continuations.

17:02 hiredman: True, but it seems like a worthwhile tradeoff to avoid database/serialization/etc issues when starting out a project.

17:02 turbofail: no, they're just closures, written in continuation passing style

17:02 ordnungswidrig: hmm, can closures be persistet (in arc) over process restarts?

17:02 technomancy: huh

17:02 hiredman: jeffterrell: no no, it just makes those issuses worse

17:02 ordnungswidrig: I mean, what if they reboot the machine?

17:03 jeffterrell: ordnungswidrig: Maybe with their new architecture, but with the old one, they were just stored in RAM.

17:03 ordnungswidrig: frightening.

17:03 hiredman: the problem is vms like the jvm generally don't provide a way to serialize and pass around the state of the machine

17:03 jeffterrell: ordnungswidrig: That's why you would occasionally (mostly before the new architecture; see link) see "link expired" messages.

17:03 technomancy: ordnungswidrig: or like ... used a load balancer?

17:03 yeah, it's a mess

17:04 how not to scale an http service

17:04 ordnungswidrig: you don't need a link balancer when you can hold your state in ram :-)

17:04 turbofail: if you could serialize the closures, you could store them in redis or something

17:04 dbasch: ordnungswidrig: if you reboot the machine who cares. Either you have to read state from disk or reconstitute it lazily, who knows what will be faster

17:04 technomancy: oh that's right; netsplits are a myth =)

17:05 hiredman: you have to serialize basically the whole object graph from the closure

17:05 like, why? just use a session

17:05 you won't feel as cool, but you won't want to rip it out and rewrite it in a month

17:06 turbofail: well it'd also be nice if you could write something that will automatically put relevant closure variables into a session

17:06 i believe the racket web framework offers something that can do that

17:07 of course a better solution is to just not have so much damn state in the first place

17:07 * ordnungswidrig wants to print fielding's thesis and throw it at the HN developers

17:08 hiredman: or you spin up a machine / process / vm / etc per user and just always route them to the same one

17:08 dbasch: plus it’s not like there are that many cases of the “next 30 stories.”

17:08 ordnungswidrig: hiredman: no no, nowadays you spin up a docker container

17:09 hiredman: (http://research.microsoft.com/pubs/210931/orleans-msr-tr-2014-41.pdf)

17:09 jeffterrell: It's true, there are some definite limitations with this approach, but I don't think it's strictly worse, I think it's just a tradeoff. I could see it being lots better in the beginning, when you're serving like 10 users per day.

17:09 If I knew how to use this approach, I could see writing something like HN in an afternoon, which would be a great way to do a proof-of-concept or win a Clojure Cup. :-)

17:10 ordnungswidrig: I'm popping out. Please leave a not when you came to some sane conclusion :-)

17:10 technomancy: jeffterrell: does it really save time vs cookie store though?

17:10 aztak: howdy folks.. any suggestions for how to make this code more Clojuresque? https://gist.github.com/metamorph/ceda1cc0a97cde08cf04 -- It feels a bit too verbose :p

17:11 jeffterrell: technomancy: Interesting. Maybe not? I suppose you could define a record to contain the continuation state, and store such records in an atom-map keyed by user. Sounds slightly more complicated than just evaluating a stored fn with closed-over state, but maybe not much.

17:11 turbofail: technomancy: well using a cookie store is basically the same thing except you have to manually record the state into a cookie

17:12 and extract it later

17:12 ghadishayban: aztak: seems fine to me

17:12 clojurebot: Cool story bro.

17:12 technomancy: turbofail: that middleware ships with ring iirc

17:12 justin_smith: aztak: #(= unwanted-id (:id %)) could be (comp #{unwanted-id} :id) (but I only suggest that switch if you end up with at least two ids to check)

17:12 technomancy: just return :session in the response map and your'e done

17:12 jeffterrell: clojurebot: You're like a child, wandering into a theater…

17:12 clojurebot: excusez-moi

17:13 turbofail: technomancy: well you still need to put your environment into that session

17:13 ghadishayban: aztak: some devs will write (comp #(= unwanted-id %) :id) or (comp (partial = unwanted-id) :id) but that can turn into HOD when taken to the extreme

17:13 HOD == Higher-order Diarrhea

17:13 aztak: justin_smith: ah, that's a nice approach. But I agree - It's perhaps less readable.

17:13 technomancy: turbofail: IME that falls naturally out of the functional approach

17:14 but I have limited experience with web apps

17:14 aztak: ghadishayban & justin_smith - thanks for having a look :) And thanks for the suggestions.

17:15 turbofail: i dunno. i implemented a human-powered merge sort at one point, and i think it would have been much more annoying without the serialized-CPS approach

17:15 well not serialized in this case

17:16 there's certainly cases where it would give some value-add over stuffing things into sessions

17:16 dbasch: aztak: I’d write (for [d data :when (not= unwanted-id (:id d)] (dissoc d :auth_token))

17:19 aztak: dbasch: argh - list comprehensions, I haven't reached that chapter yet *grin*. Interesting approach though. In a way it's more readable I guess.

17:19 ghadishayban: i actually prefer not using the comprehensions

17:19 it buries the actual kernel of logic somewhere in the syntax

17:20 and you have to name extra things, not fun

17:20 dbasch: it depends on how you express it, because abuse of arrows and comp could make it even less readable

17:20 ghadishayban: totally legit approach though

17:20 yup HOD

17:21 (I really want that term to catch on)

17:22 impl-wise low-level, the 'for' macro does emit a ton of code

17:23 ,(for [a (range) b a c b d c e d f e] (inc a))

17:23 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

17:27 ghadishayban: argh CLJ-1322 has the bug

17:28 vIkSiT: hello all

17:28 how do I get a key from a cljs.core/PersistentArrayMap ?

17:28 or rather, the value for a given key

17:29 I got a native js object on which I ran a js->clj

17:29 But using keys, get, aget - none of that works

17:29 dnolen_: vIkSiT: they are just maps, get should work

17:29 vIkSiT: if it doesn't work need to see a minimal example

17:30 joelt: seems like Clojure/script is picking up a little steam job-wise

17:33 vIkSiT: dnolen_, just a sec, pasting a gist here

17:38 literary: Is it okay to use :goto as a final clause in (cond) instead of :else?

17:39 technomancy: define "okay"?

17:39 justin_smith: literary: anything truthy works, :goto is misleading though

17:39 literary: What about :fail ?

17:39 pjstadig: :these-arent-the-droids-youre-looking-for

17:39 justin_smith: ,(cond nil :nope false :umm "Whatever" :OK)

17:39 clojurebot: :OK

17:39 noonian: literary: short answer is yes :)

17:39 literary: Or :never-reaches-this-line

17:40 technomancy:

17:40 noonian: :wth-just-happened?

17:40 literary: ,(cond :cond 3)

17:40 clojurebot: 3

17:40 literary: What is the best word for this?

17:40 vIkSiT: dnolen_, https://gist.github.com/viksit/106822bdacd7e1d41ec0

17:40 here's some sample code.

17:40 literary: Maybe :mov

17:40 or even :MOV

17:40 justin_smith: technomancy: well :無 would work

17:41 literary: ,:·

17:41 clojurebot:

17:41 vIkSiT: to restate my question, how do I get keys from a cljs.core/PersistentArrayMap in this case (the key exists but I get a nil)

17:43 justin_smith: vIkSiT: can you print the keys of a?

17:43 or, prn them rather

17:43 noonian: ,(keys {:foo "", :msg ""})

17:43 clojurebot: (:msg :foo)

17:43 vIkSiT: I get nil

17:43 dnolen_: vIkSiT: (keys some-array-map)

17:43 vIkSiT: (prn (keys a)) -> nil

17:44 kryft: Ugh, how do I turn the string keys in the :json-params produced by wrap-json-params into keywords? wrap-keyword-params doesn't seem to touch :json-params

17:45 vIkSiT: argh.

17:45 I never thought I'd bitch about parens, but..

17:45 when I added that "After conversion" line

17:45 extra paren.

17:45 That closed the [let ..] and of course, everything else is nil

17:46 dnolen_, justin_smith - thanks for the help.

17:46 dnolen_: vIkSiT: np, in general if you see a strange error like this you should go hunting for syntax errors first :)

17:46 vIkSiT: at this point 1000s of people use ClojureScript this is basic functionality

17:46 vIkSiT: hehe, I figured emacs + paredit was taking care of it.

17:46 indeed

17:46 dbasch: &(cond nil "foo" ::"what")

17:46 lazybot: ⇒ "what"

17:47 vIkSiT: dnolen_, thanks for pointing to the multi refs example of shared state btw. I have a question on why om/build doesnt' currently take different :targets..

17:47 why should I not be able to build a component with its own target, and have om/root point to say document.body?

17:47 dnolen_: vIkSiT: :target is only for root, this goes back to how React works

17:48 vIkSiT: hmm

17:48 dnolen_: vIkSiT: again some limitations are React limitations

17:48 noonian: kryft: there is a keywordize-keys fn in clojure.walk and there is also a similar one in prismatic's plumbing lib i believe

17:48 dnolen_: vIkSiT: but you can have multiple roots

17:48 vIkSiT: so how would you recommend solving a case where I have a static template, and two divs are dynamic. Both have om/root builds, but this of course means I can't combine them in the same om/root view

17:49 dnolen_, yeah, I see why that's the case

17:49 dnolen_: vIkSiT: both roots can share the same atom

17:49 so they can be coordinated

17:49 or they can share the same channel - whatever - coordination is not that challenging

17:49 kryft: noonian: Ok, thanks!

17:49 vIkSiT: yeah, I ended up using channels for now rather than IResolve. I couldn't get on-changes working with it.

17:50 technomancy: keywordize-keys =(

17:50 justin_smith: technomancy: clearly we need wordkeyize-words

17:50 technomancy: I almost put map-keys and map-vals as "what one feature would you add" in the survey, but "namespaces that are values" won instead

17:50 I mean while we're asking for a pony

17:51 kryft: technomancy: Would you suggest something else than keywordize-keys?

17:51 dbasch: I asked for a pony: better exceptions / error messages

17:51 technomancy: kryft: keywordize-keys should be generalized to map-vals, but that doesn't exist, which makes me sad.

17:51 kryft: technomancy: Ah :)

17:52 technomancy: dbasch: I would have put that, but it's hard to classify it as a language feature

17:52 arrdem: dbasch: I asked for a bigger pony... official docs to kill Grimoire/ClojureDocs :P

17:52 technomancy: *map-keys rather

17:52 dnolen_: vIkSiT: probably wise IResolve is not fully baked

17:52 justin_smith: kryft: why do the keys need to be keywords? doesn't the double translation just make everything more brittle?

17:52 technomancy: (def keywordize-keys (partial map-keys keyword)) ; done

17:52 puredanger: dbasch: I hear people say this all the time, but I think people mean different things by that and just saying "better errors" is too vague to be useful

17:52 dnolen_: vIkSiT: channels/callback via :shared are a good solution to many problems

17:53 puredanger: I'm not saying this to disagree but b/c it's something that I would like to remove as a complaint and I want a better way to collect useful data

17:53 vIkSiT: dnolen_, indeed - this is what I have now : https://gist.github.com/viksit/353d73081a0152aba0a8

17:53 technomancy: puredanger: there's just so many obvious fixes it's hard to know where to begin though

17:53 also, it was like a one-line field

17:53 in the survey

17:53 dbasch: puredanger: agree, it’s more about pointing out specific exceptions that could be more informative

17:53 kryft: justin_smith: The keys correspond to columns in an SQL database, and jdbc/query returns a map with keywords corresponding to column names

17:54 noonian: technomancy: map-vals is also in prismatic's plumbing lib heh

17:54 Bronsa: map-vals and map-keys should be a thing

17:55 dbasch: (inc map-vals)

17:55 lazybot: ⇒ 2

17:55 puredanger: technomancy: dbasch: there are specific exceptions improved (generally ones with higher votes) every release yet we never seem to escape this complaint

17:55 Bronsa: https://github.com/search?utf8=✓&q=defn+map-vals&type=Code&ref=searchresults

17:55 puredanger: (also, I am highly in favor of map-keys and map-vals being in core)

17:55 kryft: justin_smith: It would be practical to have keyword keys (or string keys) on both the data coming from the frontend and the data coming from the database

17:56 AeroNotix: puredanger: same

17:56 it's a very common thing to want to do

17:56 puredanger: technomancy: dbasch what does it take to move the needle? there are other things too that contribute from an experience pov (stack traces on compile errors, etc)

17:56 justin_smith: kryft: there is an optional keyword argument to cheshire/read-string to make the keys keywords - perhaps your middleware has a similar option

17:56 dbasch: puredanger: I’d see it as a good thing. If only a small group used Clojure, nobody would care that much about error messages. As the community grows, it will demand more.

17:57 that’s really true of all software

17:57 puredanger: dbasch: but I don't see that complaint about other languages so I take it as an actual complaint here

17:58 technomancy: puredanger: spend a bit of time talking with people who haven't already built up mental scar tissue around the problem, I'd say

17:58 Bronsa: uhm I actually called map-vals update-vals in t.a

17:59 kryft: justin_smith: Thanks, but doesn't seem like it does; wrap-json-body does have a :keywords? parameter, but wrap-json-params doesn't. The docs for wrap-json-params suggest using wrap-keyword-params, but that doesn't seem to work.

17:59 justin_smith: Anyway, manually calling keywordize-keys should work well enough for now.

17:59 justin_smith: OK

18:01 noonian: kryft: you could pretty easily make your own middleware that calls keywordize-keys also

18:01 TimMc: Down with keywordizing!

18:02 justin_smith: puredanger: with many languages the core functions are more likely to validate input. With clojure it's common to give invalid input, and for call chain to go down quite a few levels before that becomes a problem. So the user (especially the naive user) sees a bunch of class names and function names they have never heard of, and see an error message that seems like a non-sequitor for the input they provided.

18:02 kryft: noonian: Right

18:03 justin_smith: puredanger: throw in a few anonymous functions with auto-generated names into the mix, and it's all pretty intimidating at first

18:03 puredanger: justin_smith: how can we capture data around that situation to understand what needs to be fixed

18:03 justin_smith: as of next alpha, the anon-generated names are slightly more helpful (thanks Bronsa !)

18:03 justin_smith: oh, cool

18:04 puredanger: not sure - maybe dev time assertions about inputs? But that seems to conflict with the prevalent clojure coding style.

18:05 puredanger: justin_smith: there is little tolerance for checks that impede performance (although this is something that could be done in a special "dev mode" build - that's been discussed at length)

18:05 justin_smith: right

18:06 puredanger: here's a list of errormsg tickets in jira http://dev.clojure.org/jira/secure/IssueNavigator.jspa?reset=true&jqlQuery=labels+%3D+errormsgs+and+project%3Dclj+and+status+%3D+open - other than one or two , only a couple have more than 2 votes

18:06 justin_smith: puredanger: just spitballing, but a mechanism that defined a run time check, and reliably stripped checks when building an artifact would be nice

18:06 Bronsa: puredanger: my guess is that that's because nobody uses JIRA

18:07 technomancy: Bronsa: yeah, I stopped voting on things a while ago

18:07 puredanger: well I use it :)

18:07 and in particular I use votes to decide what gets triaged, so...

18:07 Bronsa: puredanger: yeah me too, but my point is that the community just doesn't vote on tickets because most feel it's kinda useless

18:08 puredanger: we also used votes as a way to see which issues needed to be kept in 1.7 this week vs pushed off to 1.8

18:08 so I'm telling you (as the one that makes those decisions), that it's useful

18:08 TimMc: That's good to hear.

18:08 puredanger: I look those numbers every day

18:09 TimMc: I usually fail to vote because I find Clojure bugs on my work computer but have Jira login info on my home computer. :-P

18:09 puredanger: TimMc: that is outside my ability to fix :)

18:09 gotta run….

18:10 TimMc: fixing it now :-P

18:10 puredanger: I also watch Andy's report: http://jafingerhut.github.io/clj-ticket-status/CLJ-top-tickets-by-weighted-vote.html

18:10 Bronsa: puredanger: I wasn't questioning that, just making you aware that a big chunk of the community doesn't know the value of voting

18:10 danneu: kryft: just apply the wrap-json-params middleware before the ring.middleware.keyword-params/wrap-keyword-prams middleware that you're probably already using

18:10 puredanger: Bronsa: noted, and will try to re-assert the value of that more

18:12 kryft: danneu: It didn't seem to work, and actually the docs for wrap-keyword-params said that it "does not alter the maps under :*-params keys". *shrug*

18:12 xeqi: I'd lean towards error messages being something that bothers people that haven't gotten used to them, and those people don't overlap with jira accounts that vote

18:13 noonian: so you just need two more middleware to move :params to :proto-params and back again!

18:14 kryft: :D

18:14 xeqi: puredanger: is there a way to see what I've voted on?

18:14 noonian: but at this point thats a lot of work just to use someone elses middleware hehe

18:15 kryft: noonian: Yes, I'll probably end up writing my own keywordize-json-params middleware (sort of like I write my own FUNCTIONS, gee whiz, I'm a real programmer)

18:16 danneu: kryft: huh? wrap-json-params updates the :params map. wrap-keyword-params updates the :params map

18:17 kryft: danneu: For some reason wrap-json-params only puts some of the properties of the posted json object into :params, but all of them into :json-params

18:17 That confused me for a while too

18:18 danneu: how can i repro that

18:18 weavejester: wrap-json-params should put all of the properties in params

18:18 I believe it’s just a merge

18:19 Generally speaking wrap-json-body is a better middleware to use

18:19 Unless you have specific needs

18:19 danneu: i use wrap-json-params -> wrap-keyword-params on my json apis and it works ifne

18:20 kryft: danneu: Well, I posted {"signup_form":[], "title" : "Foo", event_id : 7} from the browser, and :params was missing the signup_form property

18:22 weavejester: I think I was using wrap-json-params because friend expected it

18:23 danneu: kryft: what happens when you (cheshire.core/decode <your browser string>)

18:26 muraiki_: hi all. I'm new to clojure and ran into an error that I'm having trouble understanding. the error is "Exception in thread "async-dispatch-4" java.lang.NullPointerException". I've posted the code and stacktrace here; any help would be most appreciated! https://gist.github.com/muraiki/11831288662a0c07b7d4

18:27 since there's a state machine error I imagine I'm doing something wrong with (go)

18:27 weavejester: muraiki: It looks like you’re sending nil into your channel, which causes an exception

18:27 justin_smith: muraiki_: do you have a full stacktrace?

18:27 muraiki_: the full stacktrace is posted as a comment at the bottom of the gist

18:28 justin_smith: oh, now I see it, thanks

18:28 kryft: danneu: (decode "{\"signup_form\":[],\"title\":\"foo\",\"event_id\":7}") produces {"signup_form" [], "title" "foo", "event_id" 7}

18:29 muraiki_: weavejester: hrm, let me see where that might be happening... I know that I put at least one legitimate thing on the channel because my browser client does get a websocket message, heh.

18:30 danneu: kryft: drop some `prn`s into your middleware stack and look at the actual vals coming over the wire

18:30 (prn request)

18:30 ((fn [handler] (fn [req] (prn req) (handler req)))

18:31 ensure content-type is 'application/json'

18:32 ghadishayban: muraiki_: just because there is an async reference in the stacktrace, doesn't mean anything except tat the exception blew up on the async thread pool

18:32 but it may have been non-async (normal) fn call that did it

18:32 muraiki_: ghadishayban: thanks, that's good to know. :)

18:32 ghadishayban: the stacktrace shows line 43, which is (is-diff? (data/diff res (url-name @last-state))

18:32 muraiki_: weavejester is right, there appears to be a nil going on the channel

18:33 ghadishayban: I'd try to duplicate it minimally

18:33 muraiki_: does my (<! (timeout 10000)) put a nil on the channel? what I'm trying to do is to block for 10 seconds

18:33 ghadishayban: no

18:34 that is fine, it's a take from a channel

18:34 the only thing putting onto a channel in your source is L64

18:36 kryft: danneu: Yup, the content-type is "application/json; charset=utf-8" for the relevant post requests

18:36 ghadishayban: Also, putting a nil on the channel results in a different exception, you'll see a clear "Can't put nil on channel"

18:36 muraiki_: I did a prn on url-maps to make sure some weird value wasn't in there, but I only see [{:name "jsontest", :url "http://ip.jsontest.com/&quot;}]

18:36 oh ok, thank you

18:36 kryft: danneu: I do also see all properties in both :params and :json-params in the prn after wrap-json-params

18:37 ghadishayban: muraiki_: so in your code you must ascertain that make-req never returns nil

18:37 danielcompton: In clj 1.7 alpha 2, why would partition not have a 1 arg arity that returns a transducer?

18:37 partition-by and partition-all both do

18:38 muraiki_: muraiki_: wow, that should have been obvious. I made the assumption that it'd always succeed, which is of course not true. let me play with that a bit

18:38 ghadishayban: partition has more knobs than the other two functions, and the only knob you could do with one arity is to have a short final partition, which is arguably a rare desire. (speaking for myself)

18:38 muraiki_: oops, messaged myself :n

18:38 danneu: kryft: if your :params map has nonkeyword keys in your routes, then wrap-keyword-params is getting the request before wrap-json-params

18:39 jeffterrell: puredanger: Crazy idea to collect data about confusing exception messages: make a lightweight webapp that collected Clojure exceptions. Every exception in Clojure 1.7 includes a link to the web site with a message: "Did you find this exception confusing? Let us know here: http://…" The site parses the exception and aggregates exception instances into groups of like messages. Users would still have to go to the trouble of pasting

18:39 their exception in, but that would at least be a way to start collecting data about it. The pattern matching used to group exception instances could also be used to provide helpful suggestions in Clojure 1.8.

18:39 Arg, puredanger left the room. IRC veterans, what does one typically do in a case like this?

18:40 justin_smith: $mail jeffterrell via lazybot

18:40 lazybot: Message saved.

18:40 technomancy: jeffterrell: you could do that in an nrepl middleware

18:40 it doesn't need to be part of clojure

18:40 ghadishayban: jeffterrell: which case specifically?

18:40 kryft: danneu: Actually this instance was running without wrap-keyword-params at all. And the "signup_form" value has disappeared from :params by the time I get to my compojure post request handler :P

18:40 technomancy: with nrepl-discover you could even prompt (do you want to report a usability bug) interactively

18:41 dbasch: (inc technomancy) ;; that’s a great idea

18:41 lazybot: ⇒ 141

18:42 dbasch: I’d love to have the time to work on that, or I’d gladly contribute to a bounty for something like it

18:43 hiredman: ugh

18:43 terrible

18:43 I hate those things

18:43 danielcompton: ghadishayban: ah yes I see now

18:43 jeffterrell: justin_smith: Whoa, what does this magical $mail thing do exactly?

18:43 hiredman: my laptop does it, my phone does

18:44 jeffterrell: technomancy: Brilliant! …about the nrepl middleware. That would be way better: no pasting, and automatically report things like Clojure version.

18:44 justin_smith: jeffterrell: lazybot sends the person a message when they show up again

18:44 jeffterrell: ghadishayban: The case where you reply to somebody after they've left the chatroom, but you want them to see your message somehow.

18:44 kryft: danneu: Just to clarify, wrap-keyword-params works fine, but for some reason one key/value from :params disappears before I get to my app's request handler. :P

18:44 ghadishayban: oh i see

18:45 bja_: anyone around know why I can't annotate a prismatic.core/defnk function's output with {:foo AnyProtocolHere}? see https://gist.github.com/emidln/2b3a192b7e7f3d305f94

18:45 danneu: kryft: gist your middleware stack?

18:45 dbasch: hiredman: as long as it’s opt-in and disabled by default, I think it’s awesome

18:45 jeffterrell: justin_smith: nifty! Thanks!

18:45 technomancy: just put it in cider-middleware, then hiredman will never see it

18:45 =D

18:45 jeffterrell: $mail puredanger Crazy idea to collect data about confusing exception messages: make a lightweight webapp that collected Clojure exceptions. Every exception in Clojure 1.7 includes a link to the web site with a message: "Did you find this exception confusing? Let us know here: http://…" The site parses the exception and aggregates exception instances into groups of like messages. Users would still have to go to the trouble of

18:45 lazybot: Message saved.

18:45 jeffterrell: pasting their exception in, but that would at least be a way to start collecting data about it. The pattern matching used to group exception instances could also be used to provide helpful suggestions in Clojure 1.8.

18:46 bja_: err, not prismatic.core, plumbing.core/defnk

18:47 kryft: danneu: https://gist.github.com/kryft/45ce18c0ca7e26092b39

18:47 jeffterrell: hiredman: The trick is that the newbies need to have it enabled, because they're the ones we're trying to help. But maybe it could be disable-able by a dynamic var? Who knows. I'll label it a policital decision and bow out. :-)

18:47 hiredman: jeffterrell: no

18:48 jeffterrell: in a few months when you know clojure you won't care about it anymore

18:48 ghadishayban: jeffterrell: true ^

18:48 though it would be nice to have a guide for decoding exceptions for users

18:48 hiredman: jeffterrell: you are optimizing for the experience of new users, a class of users that basically disapears every two months

18:49 jeffterrell: hiredman: …and perpetually reappears. :-)

18:49 ghadishayban: When you see a NullPointer, look at the stack frame just above it

18:49 When you see a ClassCastException ... couldn't treat number as ISeq, etc.

18:49 hiredman: not only that, but you appear to think that there is a dearth of ideas in the world, and so by just coming up with an idea you are doing a service to the world

18:50 you think such a thing should exist, write the code to do it

18:50 ghadishayban: hiredman: he just wants to help future peoples.

18:51 hiredman: ghadishayban: sure, then write the app and try and get people to use it

18:51 ghadishayban: jeffterrell: It will never be accepted in core, but a useful nrepl middleware is promising

18:51 dbasch: perhaps the way for newbies to enable it is via a template for newbies that could be suggested in tutorials

18:51 ghadishayban: yup, agreed.

18:51 jeffterrell: hiredman: I realize having the idea is like 0.001% of the overall effort. But maybe somebody will like it and Clojure will be improved. If you don't like it, you don't have to work on it. :-)

18:52 Nor does anybody, for that matter (obviously).

18:52 hiredman: jeffterrell: if you don't even like it to work on it, why expect someone else to?

18:52 jeffterrell: I don't.

18:52 ghadishayban: hiredman: just trying to stay positive

18:52 hiredman: then why send puredanger a mail about it?

18:53 jeffterrell: puredanger asked for ideas on how to collect data about confusing exception messages. I'm just responding to his request.

18:53 ghadishayban: yeah maybe that's too eager. prior art in this area is aviso/pretty

18:53 need concrete impls and soundness before core will even consider something

18:53 https://github.com/AvisoNovate/pretty

18:53 dbasch: (inc (Math/abs ghadishayban))

18:53 lazybot: ⇒ 1

18:53 hiredman: jeffterrell: ok, I guess

18:54 dbasch: (helping ghadishayban stay positive)

18:54 hiredman: jeffterrell: we just get wave after wave of people learning the language in #clojure, who propose these things, and then stop caring about them after two montsh

18:55 and people who generally are new themselves wringing their hands over the user experience of people new to clojure

18:55 jeffterrell: hiredman: Makes sense. Sorry. :-/ I understand the frustration with people who flippantly propose things and then don't follow up to your thoughtful reply because they never cared in the first place.

18:55 danneu: kryft: what does (prn request) look like after handler/site?

18:55 technomancy: imagine, that, newbies caring disproportionately about usability

18:55 danneu: for one, it looks like wrap-params resets :params https://github.com/ring-clojure/ring/blob/1.3.1/ring-core/src/ring/middleware/params.clj

18:56 hiredman: technomancy: they care about the usability for someone who doesn't know what they are doing

18:56 jeffterrell: If it helps, I've been using Clojure for over two years and know my way around. :-) So my idea wouldn't help me out any.

18:56 hiredman: technomancy: which is why they tend to propose silly things like hiding stacktraces

18:56 jeffterrell: ghadishayban: New lib; thanks for the link.

18:57 hiredman: as someone who knows things(or atleast I like to thing I do) having stacktraces around that show me everything is useful

18:58 justin_smith: technomancy: jeffterrell: it may be that the problem is that for a single person, learning to read the existing stack traces is easier than making better error reporting (despite the fact that better error reporting would save time for many people in the long term, and could complement the existing stacktrace reading instead of just replacing it)

18:59 kryft: danneu: https://gist.github.com/kryft/26faacbb5f39877d9fee

19:00 _pr0t0type_1: Hey guys, do you know if there is any equivalent to base_url in clojure/compojure/ring? I don't want to have to hardcode two different urls (and paths) for developement vs production (ie localhost:8000/myendpoint) vs (production.com/myapp/myendpoint)

19:00 ghadishayban: true once you can read stacktraces well, you're set for life. but ongoing usability is always nice. There's always the danger though, which has been stated over and over by Rich about designing for beginners is never a goal

19:00 kryft: danneu: Everything looks fine after wrap-json-params, but "signup_form" mysteriously disappears from :params some time later.

19:00 hiredman: does being a beginner stink? become an expert, it's super

19:01 ghadishayban: JRuby goes to great (incredible) lengths to re-write the stacktrce

19:01 bja_: (inc hiredman)

19:01 lazybot: ⇒ 57

19:01 kryft: danneu: (And I don't see anything weird after handler/site either, but no :params or :json-params there obviously)

19:01 hiredman: ghadishayban: well, they have to show ruby stacks right?

19:01 ghadishayban: si

19:01 AeroNotix: clojure stacktraces suck and anyone defending them should not be allowed to talk about usability

19:01 end of story

19:01 ghadishayban: AeroNotix: it's complicated =)

19:02 AeroNotix: of course it is, nothing about what I said included the fact that it was an easy fix

19:02 it's hard and I understand why

19:02 but it still sucks

19:02 kryft: danneu: Anyway, I think I have to sleep off this cold :)

19:02 danneu: kryft: break handler/site into its individual middleware. put its wrap*params related stuff at the end of your (-> app ... ) stack

19:02 bja_: _pr0t0type_1, (ns foo (:require [environ.core :refer [env]]) (defn base-url [] (:base-url env)))

19:03 seancorfield: AeroNotix: stack traces stop sucking after you get over the initial shock...

19:03 AeroNotix: seancorfield: 3 years and counting.

19:03 _pr0t0type_1: bja_: thank you!

19:03 seancorfield: and as ghadishayban says, learning to read stacktraces - regardless of language - is a useful skill that I wish more developers had

19:04 AeroNotix: and that CIDER middleware actually can make things worse sometimes

19:04 ghadishayban: and jvm's fast throw

19:05 amalloy: the problem with simplified stacktraces is that beginners might actually use them. then they'll come in here with a stacktrace that's missing all the useful information that's in a real stacktrace

19:05 jeffterrell: Just to be clear, I don't think anybody's proposing simplified stacktraces. Unless I missed it…

19:06 ghadishayban: the CIDER toggles for hiding / showing info are entirely in user-space

19:06 justin_smith: right, we have been talking about better error messages - something that complements stack traces and doesn't replace them

19:06 cfleming: jeffterrell: It's generally the first thing that people propose for making Clojure more newbie-friendly

19:06 kryft: danneu: Thanks for helping with the debugging!

19:07 ghadishayban: the aviso library above just does some pretty-printing, aligning of the line numbers

19:07 cfleming: I agree that stack traces are really not a problem, but I disagree that making Clojure more accessible for newbies is a bad goal.

19:07 jeffterrell: cfleming: Is there a typical response to such proposals? I'd be interested to read it.

19:07 cfleming: jeffterrell: There are a couple of libraries that implement it, so generally you can get that if you want it. aviso/pretty, clj-stracktrace etc

19:07 ghadishayban: the only rational approach for Clojure is to do what it already does, which is include all possible information. it's a hosted language, so sometimes that gets messy

19:08 kryft: danneu: I'll try breaking down compojure.handler/site to its individual middleware later as you suggested

19:08 noonian: i think the biggest barrier for newbies is that it is a lisp, and you really have to learn about how the language works before jumping in and trying to write stuff

19:08 ambrosebs: this is the most practical idea i've come up with for improving error messages https://github.com/frenchy64/dynalint

19:08 justin_smith: noonian: I came to clj with scheme / common lisp/ ocaml experience, and the stack traces drove me batty

19:08 ghadishayban: (inc cfleming )

19:08 lazybot: ⇒ 1

19:09 justin_smith: ghadishayban: it's sensetive to spaces

19:09 (inc cfleming)

19:09 lazybot: ⇒ 3

19:09 ghadishayban: Helping newbs shouldn't mean designing for newbs

19:10 rich's example of the guitar hero guitar with 4 buttons...

19:10 cfleming: ghadishayban: Having a powerful language is totally orthogonal to it being easy to use

19:11 noonian: justin_smith: yeah, but you will see waaay more stack traces if you don't understand lisp at all than if you do :P

19:11 ghadishayban: yeah I am agreeing with you

19:12 justin_smith: noonian: and many of the lisper problems actually have decent messages

19:12 ,(let ((a 0) (b 1)) a)

19:12 clojurebot: #<CompilerException java.lang.IllegalArgumentException: let requires a vector for its binding in sandbox:, compiling:(NO_SOURCE_FILE:0:0)>

19:12 jeffterrell: ambrosebs: That's pretty nifty!

19:12 justin_smith: (lost count of how many times I did that...)

19:13 ambrosebs: so yea, that's a very compelling way to improve error messages if you're so inclined.

19:15 justin_smith: (inc ambrosebs)

19:15 lazybot: ⇒ 10

19:15 justin_smith: nice

19:19 cfleming: Another thing that would make a huge difference IMO would be for clojure.core to use seqex or something similar for its macro parsing.

19:19 i.e. illuminated macros

19:19 jeffterrell: That would be sweet.

19:19 ambrosebs: or just redefine them to use them...

19:20 surely that's a library somewhere?

19:20 cfleming: That's just a huge win for everyone, macros are easier to write, easier to read, and you remove a whole class of "can't make seq from symbol" error messages

19:21 jeffterrell: cfleming: I like it. Any idea about performance implications?

19:21 ghadishayban: macros cost only at load time, so startup

19:22 cfleming: jeffterrell: No, no idea, sorry. I implemented something similar for Cursive but didn't test the difference. Frankly, I didn't care.

19:22 The correctness benefits were totally worth it.

19:22 ghadishayban: cgrand/seqexp is also amazing, and only 200LOC

19:23 cfleming: Yeah, although that only works for regular languages IIRC

19:23 technomancy: does it declare version ranges?

19:24 cfleming: ambrosebs: You mean redefine e.g. let to use seqex and then expand to the previous version?

19:25 ghadishayban: technomancy: which?

19:25 technomancy: ghadishayban: cgrand's thingy

19:25 been burned before

19:25 ghadishayban: it doesn't appear to

19:25 technomancy: progress =)

19:25 bja_: is there a way (other than fork and fix project.clj) to remove the version range declarations in third party libraries?

19:25 ambrosebs: cfleming: yea alter-var-root clojure.core/let to an equivalent macro that's nicer

19:26 bja_: (or tell lein deps :tree to ignore them)

19:26 ambrosebs: there's a bootstrapping issue but it should probably mostly work. dynalint does it for a few macros

19:26 technomancy: bja_: just :exclusions

19:26 cfleming: interesting idea, I hadn't thought of that. It would make a great POC if nothing else.

19:27 ambrosebs: dynalint convinced me that it's a good idea. or our only idea.

19:27 it's just a poc itself anyway.

19:28 the next step would be a more structured error catching mechanism... like seqex :)

19:30 cfleming: the macro redefs in dynalint https://github.com/frenchy64/dynalint/blob/master/src/dynalint/lint.clj#L1485

19:33 the downside is you really can only target specific clojure versions

19:33 and you better hope no other lib is pulling the same trick

19:34 but it's the user's fault anyway, they loaded the monkey patches

19:34 ;)

19:36 cfleming: Hehe, right. But there's clearly lots of gain to be had, especially around error messages.

19:37 ambrosebs: yep, very low hanging fruit.

19:39 QbY: any clojure freelancers looking for immediate work?

19:40 ambrosebs: QbY: maybe ask https://twitter.com/cgrand

19:42 jeffterrell: QbY: I may have a colleague who is.

19:42 muraiki_: ok, so I figured out what was happening to put nil on the channel. (onto-chan ch col) closes the channel once the collection is exhausted, unless you tell it not to

19:43 as always, reading the documentation helps :)

19:44 that being said, I'm not certain how to block the channel with a timeout so that I don't have onto-chan executing over and over immediately. I've used (<! (timeout 5000)) to accomplish this, but it doesn't seem to be working here

19:44 arrdem: ambrosebs: cfleming: glad to see I'm not the only one kicking that idea around :D

19:45 bbloom: sweet! https://github.com/clojure/clojure/blob/9aaee3c111ce18b9b70695dd45a04b401a174113/src/clj/clojure/core.clj#L7286

19:45 i called that "each"

19:45 but each! or run! is fine by me too

19:45 i've needed/used that quite a few times for side effects from a seq

19:46 ghadishayban: bbloom: it's a useful addition

19:46 also *way* faster than doseq

19:47 Bronsa: that's a nice fn, I didn't notice it

19:47 bridgethillyer: I need a favor from someone

19:48 At the conj, can someone please explain to me why being concerned with the beginner experience in Clojure is a *bad* idea?

19:48 I really feel like I can only figure this out if someone explains it to me in person

19:48 technomancy: someone: you heard her, spit it out

19:48 arrdem: (inc technomancy)

19:49 lazybot: ⇒ 142

19:49 technomancy: (sorry)

19:49 amalloy: bbloom: why is that way faster than doseq? like, i see that you're using reduce, which is fast, but i guess i would have expected doseq to do that as well

19:49 jeffterrell: bbloom: I'm sure I'm missing something, but why is that different than e.g. `(do (map proc coll) nil)`?

19:49 bridgethillyer: :)

19:49 ghadishayban: doseq has chunked traversal

19:49 amalloy: jeffterrell: well, your example does nothing at all, just returns nil

19:49 bbloom: amalloy: i didn't say it, ghadishayban did

19:49 jeffterrell: ha, right, say mapv then :-)

19:49 bbloom: jeffterrell: mapv builds a data structure you'd just throw away...

19:50 amalloy: well *that* example consumes unbounded memory

19:50 (for large enough colls)

19:50 ghadishayban: hmm does clojurebot macroexpand...

19:50 bridgethillyer: I’m serious, though. I promise to even be nice and listen a lot if someone is willing to do that for me

19:50 amalloy: but what you really mean is (do (dorun (map f coll)) nil)

19:50 jeffterrell: OK, true, good points all :-)

19:50 amalloy: which has the problem of allocating a bunch of cons cells

19:50 technomancy: bridgethillyer: as someone who's just spent three weeks diving into racket, you could do a lot worse than copying everything about their attitude and getting started experience =)

19:50 ghadishayban: ,(macroexpand '(doseq [a (range 50) b (range 50)] (do)))

19:50 clojurebot: (loop* [seq_27 (clojure.core/seq (range 50)) chunk_28 nil count_29 ...] (if (clojure.core/< i_30 count_29) (clojure.core/let [a (.nth chunk_28 i_30)] (clojure.core/loop [seq_35 (clojure.core/seq (range 50)) chunk_36 nil count_37 ...] (if (clojure.core/< i_38 count_37) (clojure.core/let [b (.nth chunk_36 i_38)] (do (do)) (recur seq_35 chunk_36 count_37 (clojure.core/unchecked-inc i_38))) (clojure.c...

19:50 bridgethillyer: technomancy: Loved your blog post today

19:50 jeffterrell: OK, I see why the reduce version is better. Nice.

19:50 technomancy: I mean, not necessarily *you* in particular

19:51 bridgethillyer: thanks

19:51 bridgethillyer: technomancy: It’s in my one open browser tab right now. Going to spend some serious time thinking about it.

19:52 technomancy: bridgethillyer: so actually what you should do is convince greghendershott to write down everything that's sub-par, confusing, or seems unnecessary; since he's coming from racket-land to clojure-land, his standards are pretty high =)

19:52 jeffterrell: bridgethillyer: I think part of the issue is that newbies often want an "easy" solution, in the Rich Hickey sense, where it's just a recipe they can apply with little effort. But the real solution often involves real work to understand the underlying concepts. So I think that's one sense in which catering to newbies can be a bad idea. (Emphasis on "can be"—it doesn't have to go that way.)

19:52 hiredman: bridgethillyer: maybe, I'll be at the conj, but I don't think it is bad, and if someone is interested in it, they should work on it

19:53 bridgethillyer: technomancy: brilliant, yes

19:53 bbloom: i think i'd like the name each! better than run!

19:53 but i'm just glad to finally have that function :-)

19:53 bridgethillyer: hiredman: We should totally have a beer or something at the conj

19:53 hiredman: I object to what seems to be the idea that it is a universal priority

19:53 ghadishayban: yeah

19:53 (inc hiredman)

19:53 lazybot: ⇒ 58

19:54 ghadishayban: whoa we gotta catch up

19:54 And beginners shouldn't drive design changes to a language

19:54 hiredman: hah, yeah, I suppose so, boy it feels like forever since I was in one place with a lot of clojurists

19:54 bbloom: bridgethillyer: did i miss some context?

19:55 bridgethillyer: bbloom: yeah, sorry referring to things 30 min - 1 hour ago

19:55 ghadishayban: tooling can and is improving

19:56 hiredman: outside of tooling, errors messages that have issues filed against them get changed and patched

19:56 bridgethillyer: ghadishayban: Ok, you’re invited for the beer/other beverage of your choice, too, at the conj

19:56 ghadishayban: there was an example of a Groovy stacktrace at the JVM Language Summit this summer, and it was a couple pages full with 0% of user code represented in the trace

19:56 bbloom: bridgethillyer: ok i read the scroll back

19:57 hiredman: we'll have an unsession: "people who love new comers vs. those who feel they should be left in the cold with the wolves and if they survive they are welcome" :)

19:57 ghadishayban: LOL

19:57 arrdem: pfft

19:57 bridgethillyer: hiredman: lol I’m totally signed up

19:58 bja_: hiredman: sounds more like stalin scheme

19:58 arrdem: "if they aren't motivated enough to join #clojure and ask questions they don't belong anyway"

19:59 technomancy: what kind of person tries to learn a programming language without freenode; I can't even imagine

19:59 bbloom: bridgethillyer: i think part of the problem w/ clojure+beginners is that a lot of beginner support stuff has non-trivial complexity and performance costs

19:59 like domain checking functions

19:59 we've discussed garbage in / garbage out quite a bit here in this room

20:00 hiredman: racket's tower of languages approach works well there

20:00 technomancy: oh man... I spent like half an hour writing contracts over the weekend, and it paid off many times over already https://github.com/technomancy/cooper/blob/master/cooper/cooper.rkt

20:00 super easy to turn off too

20:00 bbloom: technomancy: oh yeah, i'm all for optional contracts, etc

20:01 but i do think that designing for optional validation from the start would yield a pretty different language

20:01 hiredman: I wonder what kind of errors you get from core.contracts

20:01 technomancy: assertion failed: (= a b)

20:01 bbloom: for example the lack of conditional destructuring in clojure can make a lot of contracts more verbose to specify

20:01 technomancy: ^ http://p.hagelb.org/csp.jpg

20:02 bridgethillyer: Ok, I get the “don’t design for beginners” thing, and I agree

20:02 hiredman: well, I mean, there are lots of options for improving error messages

20:02 schema, core.typed, dynalint, eastwood

20:03 bridgethillyer: IMO, designing for beginners and being concerned about the beginner experience are two, not necessarily overlapping things

20:03 bbloom: hiredman: schema has some serious problems when it comes to error messages... see my chat w/ wolfe here: https://github.com/Prismatic/schema/pull/134

20:03 hiredman: bridgethillyer: the question is, where should the beginner experience fall on the list of priorities

20:04 beppu: Racket's beginner experience is wonderful due to how much information DrRacket gives ou.

20:04 hiredman: bbloom: ok, so use core.typed :)

20:04 I dunno, my point is there are diverse options for this, the issue is because there are options you need some amount of expertise to choose one

20:05 maybe technomancy will write DrClojure

20:05 technomancy: you like programming swing if I recall

20:06 bridgethillyer: hiredman: That’s my dream, although I doubt it’s possible

20:06 hiredman: and to your much earlier point, while I dream of that, I’m not willing to work on it at all :)

20:06 hiredman: the best thing for errors would likely be to enrich the communication of errors between the compiler and tools

20:07 beppu: I really liked how you could hover over symbols, and DrRacket would draw lines to other references to those symbols. I also liked how you could hover over a library, and see every occurence of a symbol used from that library have a line drawn to it. It was so programmer-friendly.

20:07 hiredman: an exception with a message means the compiler has to make policy descions with regard to generating that message

20:07 beppu: The error messages have been pretty good so far, too (in DrRacket).

20:07 ghadishayban: beppu: cursive does most of that, without the lines drawn

20:07 technomancy: hiredman: I'm too far gone

20:07 hiredman: if the compiler just sort of stopped, said to what repl client or whatever you use, and said "there was an error here, here is the state, what do I do?"

20:07 bbloom: it's funny, the 3 approaches of types, contracts, and schema seem to fall in logic, OOP, and grammar programming buckets respectively :-)

20:07 beppu: ghadishayban: That's good to know. Maybe I'll try cursive out one of these days.

20:08 ambrosebs: cfleming: can cursive ever draw the lines for scoping like drracket?

20:08 technomancy: the only way for me to do anything that's remotely useful for newbies is to disengage with everything I know and start from scratch

20:08 which is why I'm building a hypercard clone

20:09 ghadishayban: in my limited use of it, it seems that cursive is aware of scoping rules

20:09 hiredman: and once you are starting to talk about changes to the compiler, you have my attention

20:10 technomancy: at some point the simplest thing to be would just be to port clojure to the racket runtime and get all their awesome tooling for free, then get them switched over to the jvm once they are comfortable but need to call java libs

20:11 bridgethillyer: technomancy: okay!

20:11 technomancy: at that point the racket->jvm jump would start to feel a bit like jvm->js

20:12 trade good tooling and decent usability for increased reach. then do it again.

20:12 hiredman: well, the jvm is way better than js runtimes

20:13 so not entirely like clojure->clojurescript

20:13 technomancy: TBH I bet the only reason that hasn't already happened is that racket is already close enough as-is that it's not worth the hassle

20:14 hiredman: the really annoying thing about projects that claim to target clojure at other runtimes is they either get semantics subtly wrong, or get the clojurescript semantics instead of clojure's

20:15 arrdem: kinda hard to avoid when there isn't a spec for Clojure, just an implementation

20:15 technomancy: right; I mean if you can be "clojure" without even having vars, who can say where the line is drawn

20:15 arrdem: I'd be up for Clojure in Racket... I've been wanting to play with Racket anyway

20:15 hiredman: have you looked at https://github.com/takikawa/racket-clojure ?

20:16 bbloom: technomancy: i would be interested in a racket-clojure for FFI purposes

20:16 technomancy: right, so spoiler alert is that https://github.com/greghendershott/rackjure exists

20:16 hiredman: vars are so great, I dunno if they were introduced just for utility or the greatness was understood

20:16 bbloom: tbaldridge seems to be tinkering w/ a pypy based clojure too

20:16 technomancy: it doesn't have vars, metadata, pervasive destructuring, or persistent vectors

20:16 beppu: racket is nice on its own

20:16 technomancy: but yeah

20:16 hiredman: but being able to talk about linkage in a first class way

20:16 fantastic

20:16 technomancy: hiredman: srsly

20:16 bbloom: modules/units are the biggest thing i want from racket land

20:17 huge deal

20:17 hiredman: very tricky

20:17 bbloom: in racket? in general? or to add to clojure?

20:17 hiredman: to add to clojure

20:17 bbloom: yeah, agreed

20:17 i thought about it a bunch and my brain hurt so i gave up thinking about it

20:18 hiredman: I mean, unless you want to throw out the current namespace system, which I dunno, I might be fine with

20:18 technomancy: hiredman: if you're going to replace namespaces, they need to be replaced with namespaces-as-values, I think

20:18 bbloom: heh, yeaaah... that seems unlikely

20:18 technomancy: if that bandaid is gonna get pulled, make it count =)

20:18 hiredman: technomancy: nah

20:18 lukecossey: Anyone used the goog.fx.css3 Transition? I'm having problems with it working in Safari.

20:19 hiredman: namespaces as values don't really make sense

20:19 they have a name, they are an identity

20:19 technomancy: bbloom: hm; so to me racket's use of submodules for main feels pretty tacky

20:20 vs just "main is a function, so you know, call it"

20:20 bbloom: hiredman: i think he means to be able to capture a snapshot of a namespace and to manipulate them as values, not to remove their identity nature

20:20 hiredman: bbloom: what would you do with that?

20:20 bbloom: technomancy: i can't comment on rackets use of modules, sub or otherwise, since i haven't used racket beyond some tinkering in drracket

20:21 hiredman: one thing is something like hiphiparray does with specialization

20:21 hiredman: another thing would be for providing alternate backing implementations for say clj + cljs

20:21 etc

20:21 hiredman: bbloom: sure, but that seems pretty orthogonal to namespaces as a value

20:21 technomancy: hiredman: for isolating out subtrees of namespaces to allow multiple versions to coexist

20:21 hiredman: bbloom: what you want is someway to template namespaces

20:22 bbloom: hiredman: which is effectively what racket's units are

20:22 hiredman: bbloom: sure

20:22 bbloom: hiredman: i was just trying to clarify technomancy's comment

20:22 hiredman: I am pretty sure they do all that without having namespaces as immutable values

20:22 errr

20:22 modules

20:22 technomancy: yeah, but that has nothing to do with namespaces as values

20:23 bbloom: hiredman: sure, but it would be nice to be able to capture an immutable value, do some mutable thing to the identity, then capture another value, then *look at them* for debugging, if nothing else

20:23 hiredman: that just has to do with how namespaces exist

20:23 right now clojure namespaces exist in a flatspace

20:23 technomancy: they should be first-class things you can operate on without their being globally rooted

20:23 ghadishayban: what would a motivating purpose of ns templating be? type specialization or running multiple versions of a subtree of code, like technomancy suggests?

20:23 hiredman: if you turned it in to a tree with some scoping rules

20:24 ghadishayban: the hiphiparray example is type specialization

20:24 bbloom: ghadishayban: and cljx is basically all namespace templating

20:25 hiredman: although, to be fair, I think you can do namespace templating with some macros already

20:25 xcthulhu: bbloom: When I want to do such things, I use `with-redefs` to do such instrumentation

20:25 hiredman: people just would rather slurp in a string and call eval

20:25 insane

20:25 like, I can't believe hiphiparray does what it does

20:25 xcthulhu: Okay, maybe you have something else in mind

20:25 bbloom: hiredman: not in a way that will compose well with other macros (in clojure at least)

20:25 hiredman: bbloom: I am not so sure of that

20:26 bbloom: hiredman: i'd be interested to see what you come up with if you attempt to maintain any clj/cljs hybrid projects

20:27 hiredman: so I never completed this https://github.com/hiredman/hiphip/blob/foo/src/hiphip/impl.clj

20:27 but I started rewriting it at some point with a macro

20:27 it isn't done, so of course I can't say "it works, I have proof" but I think it would

20:27 bbloom: hiredman: oh yeah, i was using hiphip as a motivating use case, not as a great impl of the idea

20:28 hiredman: bbloom: the clj/cljs stuff I have no idea

20:28 bbloom: hiredman: it's much harder b/c of when macros get evaluated, and reader behavior

20:28 hiredman: sure

20:28 ghadishayban: i want what hiphip does, but with HOFs, rather than with macro comprehensions

20:28 bbloom: not just when macros get evaluated, but what environment they get evaluated in too

20:29 technomancy: cljs has metadata, just no vars?

20:29 *right?

20:29 hiredman: technomancy: it is complicated, because cljs macros are written in clojure not cljs

20:30 cljs is a whole other kettle of fish

20:30 technomancy: right... does metadata exist at runtime then?

20:30 bbloom: hiredman: but that's the parameterized namespace motiviation that is most important to me

20:30 hiredman: (which I would rather not touch, I mean, have you held a kettle of fish?)

20:30 bbloom: type specialization can be accomplished in other ways

20:30 hiredman: least important to me :)

20:31 ghadishayban: bbloom: HOFs in clojure make type specialization hard

20:31 technomancy: right; having metadata without vars is a lot less interesting to begin with

20:31 hiredman: technomancy: I dunno, I mean they could just stick it any old place cause javascript objects

20:31 bbloom: ghadishayban: more specifically HOF w/o defunctionalization, which is due to the dynamic nature of our runtime

20:31 hiredman: technomancy: on the other hand the closure compiler will strip it all out anyway

20:31 ghadishayban: bbloom: defunctionalization?

20:31 hiredman: λ lifting?

20:32 bbloom: ghadishayban: compilers for static runtimes will take all higher order functions and turn them in to first order

20:32 https://en.wikipedia.org/wiki/Defunctionalization

20:33 ghadishayban: bbloom: i see. the way generic functions dispatch in Julia helps too

20:33 bbloom: ghadishayban: yeah, they have both per function caches and per call site caches

20:33 ghadishayban: bbloom: not sure if that is the same approach

20:33 bbloom: gfredericks: we have per function for multimethods and per call site for protocols

20:34 er i mean ghadishayban ^

20:34 polymorphic caches are not defunctionalization, no

20:35 ghadishayban: the JVM provides the same sort of caching for *virtual* methods

20:35 ghadishayban: dammit i got bbloomed right when i have to leave

20:36 bbloom: which i guess all our IFn invokes are, but there are sooo many implementers of IFn....

20:36 ghadishayban: back in a bit

20:36 bbloom: bbloomed == told to read some crazy area of comp sci? lol

20:37 hiredman: bbloom: ghadishayban has been doing some work invokedynamicing vars (apropos of all the implementors of IFn)

20:38 jasonjckn: bbloom: do you have a blog?

20:38 (link)

20:38 bbloom: http://www.brandonbloom.name/

20:38 jasonjckn: your last name is actually bloom?

20:38 nice

20:38 hiredman: e.g. if invokedynamic worked well, and clojure's IFn casting was replaced with invokedynamic, fns would not have to share an interface, and possibly the jvm optimizations would handle them better

20:38 bbloom: hiredman: that'd be super nice

20:39 hiredman: virtual mechanical sympathy

21:11 sritchie: does anyone remember a library that lets you publish a bunch of modules out of a single project,

21:11 by carving up the source tree?

21:13 technomancy: sritchie: voom?

21:13 sritchie: technomancy: not that one… someone had written it for a util library

21:14 so if I have racehub/stripe/x.clj, racehub/stripe/y.clj, racehub/mandrill/z.clj, publishing would generate racehub.stripe, racehub.mandrill, and racehub artifacts

21:14 with proper dependencies between them if necessary

21:18 xeqi: sritchie: lein-modules?

21:18 sritchie: xeqi: no, I remember it did it automatically

21:18 I can’t find the damned thing anywhere

21:19 xeqi: hmm, I only know of #{sub, modules, voom}

21:50 hiredman: lein-repack

21:51 https://github.com/zcaudate/lein-repack

22:14 cfleming: ambrosebs: Re arrows (came back late, sorry) - Cursive can probably draw them, but not efficiently.

22:15 ambrosebs: cfleming: oh cool to know

22:15 cfleming: ambrosebs: Since you'd have to redraw most of the screen probably.

22:15 ambrosebs: Cursive already highlights uses of items that the cursor is over, although I like the idea of doing the same if a library is selected too.

22:16 ambrosebs: it would be cool to teach cursive about my own binding macros

22:16 somehow :)

22:16 cfleming: ambrosebs: I'm also thinking about things like setting the background colour of then/else clauses of if to a subtle red/green

22:16 That's coming :-)

22:17 I keep finding new things I need to add to the API as I add inspections and refactorings - once that's stable I'll release

22:17 I also need to migrate the existing code to the parser I showed you

22:18 So it's all consistent.

22:18 All that code will be open source with the API

22:18 ambrosebs: will I be able to release a core.typed binding macro file that people can just import into cursive?

22:19 cfleming: Yup

22:19 ambrosebs: sweet

22:19 cfleming: I'm probably going to have a public repo that people can contribute to that will be shipped with Cursive, like https://github.com/borisyankov/DefinitelyTyped

22:20 ambrosebs: fantastic

22:20 that will probably work well enough

22:20 cfleming: But people will also be able to create support for their internal DSLs and provide them to Cursive too.

22:20 There's lots of trickiness about the best way to integrate that into IntelliJ without having everything grind to a halt at startup though.

22:21 ambrosebs: ya right

22:26 cfleming: I need to sit down and spend some time with DrRacket, actually

22:26 I read a bunch of papers about things like the macro debugger, but I've never actually used it.

22:26 ambrosebs: cfleming: the master branch of DrRacket just added Typed Racket mouseovers

22:27 cfleming: Yeah, I saw that, it looks very like the Typed Clojure support in Cursive actually, someone sent that to me the other day.

22:28 Can they require an explicit "type check this file" step, or can they integrate it more continuously?

22:28 s/Can they/Do they/

22:28 ambrosebs: type checking is triggered by macroexpansion :)

22:28 #lang typed/racket

22:29 the only way to stop type checking is #lang typed/racket/nocheck

22:29 cfleming: But what I mean is, can the editor do it in real time like IntelliJ would do with Java, for example?

22:29 ambrosebs: ahh I doubt it

22:29 cfleming: There you get type errors provided by the IDE, but that means that the IDE basically reimplements the type system.

22:30 I'm still amazed they did that for Scala

22:30 ambrosebs: are you serious

22:30 cfleming: Yup

22:30 ambrosebs: ok I'll just accept that

22:30 cfleming: The Eclipse IDE has a frankenintegration with the Scala compiler

22:31 The IntelliJ one they wrote it themselves

22:31 ambrosebs: sheesh

22:32 cfleming: They do that for basically all the languages they support - Cursive has a lot of knowledge of Clojure semantics built in too

22:32 ambrosebs: so if there are accurate deltas about what changed in a file I have some ideas how to incrementally type check it without rewriting the checker :P

22:32 cfleming: Nice, I can get you deltas

22:33 Semantic deltas or text?

22:34 IntelliJ accurately tracks all changes to documents, in fact I already use that to move the annotations around when the file is edited.

22:34 ambrosebs: what do you mean by the former?

22:36 cfleming: Whether you would want to receive the forms that had changed, or a list of text ranges that had been updated in the document.

22:36 Text ranges can be converted into forms by just re-parsing, of course.

22:39 ambrosebs: cfleming: hmm it depends what I do on the core.typed side I guess.

22:39 cfleming: cfleming: sure, either is relatively trivial. Let me know when you have a clearer idea of what you need and we can try it.

22:39 Ugh, that should have gone to you, not to me, of course, sheesh

22:40 Talking to myself

22:41 ambrosebs: did you ever get the type querying thing working with cursive?

22:41 like local type info for expressions?

22:41 IIRC there was some incompatibility with the info I was providing

22:41 cfleming: No, I just display the errors that are sent back - I can't remember the details.

22:41 I'll check and let you know.

22:42 Got to run

22:42 ambrosebs: cya!

22:42 cfleming: Seeya

22:47 cddr: What would people expect an HTTP collection query (e.g. "/tweets&since=yesterday") to respond with if it found no results? 404 seems wrong if it *might* return a response with different query parameters

22:59 kenrestivo: i'm pretty sure there's a formal REST specification somewhere that answers that

23:00 beamso: HTTP status 204 == no result

23:00 no content, actually

23:43 TimMc: cddr: An empty collection.

23:44 The API results should be homogeneous; don't change the "type" of the response based on the query window.

23:51 Jesterman81: hey ladies/gents

23:51 awwaiid: greetings earth/human

23:53 Jesterman81: is there a cleaner way of getting the hash of data then the following https://gist.github.com/deefa3a8e7a1f9610b3e.git

23:54 https://gist.github.com/Jesterman81/deefa3a8e7a1f9610b3e

23:54 I’m a clojure noob

23:55 justin_smith: so you just want the :foo key / val from each map?

23:55 Jesterman81: yeah

23:55 justin_smith: ,(map #(select-keys % [:foo]) [{:foo "foo" :bar "dummy" :axe "blood"} {:foo "baz" :bar "dummy"}])

23:55 Jesterman81: [{:foo “foo} {:foo “bar”}]

23:55 clojurebot: ({:foo "foo"} {:foo "baz"})

23:56 Jesterman81: thx

23:57 awwaiid: what are you going to do with those key/value pairs where the key is always what you gave it?

23:57 Jesterman81: yes

23:57 I want to elimiate everyting but just the :foo keys and values

23:57 awwaiid: I mean -- if you only care about the values, you could do #(% :foo) in that map instead

23:58 Jesterman81: right…I was just wondering if thats as short as I can get it and I am not missing some destructing or cleaner way

23:58 justin_smith: awwaiid: btw #(% :foo) can be replaced with :foo for this purpose

23:59 ,(map :foo [{:foo "foo" :bar "dummy" :axe "blood"} {:foo "baz" :bar "dummy"}])

23:59 clojurebot: ("foo" "baz")

Logging service provided by n01se.net