#clojure log - Jul 27 2015

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

0:39 justin_smith: (inc TimMc)

0:39 lazybot: ⇒ 101

1:15 rhg135: I wish you were joking

4:44 tgoossens: I have a function (defn blah [q] (.query conn q) (.close conn)) But i need the output of the query. Just us a let?

4:45 (the query output must be the return value, but close conn must come after obviously)

4:56 H4ns: tgoossens: (defn blah [q] (with-open [conn (open-conn)] (.query conn q))) may be an option

4:56 tgoossens: but if query can't ever fail, use a simple let.

4:57 tgoossens: H4ns, thanks!

7:46 noncom: is destructuring considered a super low cost operation? I am reading this now http://blog.redlinernotes.com/posts/Lessons-from-cl-6502.html and that spot about destructuring caught my attention

7:46 sure, the post is about CL, but that made me to think about Clojure destructuring too

7:47 i suppose the implementations can be comparable..

7:55 wasamasa: nope

7:55 do your own benchmarks and write a blog post

8:29 expez: (let [rdr (LineNumberingPushbackReader. (FileReader. path))] ...) I'm leaking file descriptors here, right?

8:30 schmir: expez: yes

8:30 expez: use the with-open macro

8:31 expez: mhmm

8:35 jeaye: I'd love some examples of non-trivial open source applications written in clojure so I can see how its idioms scale beyond the 20 line snippets that're so common in articles and tutorials.

8:36 Ideally, the projects would hit a nice sweet spot between trivial and too much of a time investment to understand fully. Suggestions?

8:44 hellofunk: jeaye: well the Ring stuff is open source and fairly moderate in size, and is responsible for huge amounts of web sites and web apps in the world

9:20 Leonidas: hi

9:20 I have a macro like this:

9:20 (defmacro nest [sym] `(defmacro ~sym [& more#] (~sym more#)))

9:21 unfortunately, I'd like to actually unquote-splicing more# but it doesn't work, since it is not in a quasi quote

9:21 what can I do?

9:23 (apply does not work, since sym is most likely a macro)

9:30 expez: Leonidas: writing macros to write macros is super uncommon. In the event that you aren't actually an expert in a situation requiring this problem to be solved, you might consider that you've taken a wrong path somewhere further up in the decision tree :)

9:31 tsdh: Leonidas: That can't work. Basically, you want to know the actual arguments to your macro in its very own definition.

9:31 expez: Macros writing macros is where the fun starts! ;-)

9:33 expez: "Let over Lambda" is a really entertaining book doing all these sorts of multi-stage programming.

9:34 expez: tsdh: That's next on my reading list. Going through On Lisp now :)

9:34 tsdh: expez: Have fun! :-)

9:34 Leonidas: expez: it gets better. I'm writing a macro to write a macro to replace existing macros :-/

9:35 tsdh: Leonidas: Awesome!

9:35 Leonidas: I have mastering clojure macros open too, but didn't get that much time to read it

9:35 LOL is on my reading list as well, though.

9:37 tsdh: Leonidas: Would it work to generate a macro with gets a collection `more` rather than having a varargs `more` parameter. If you need to, you can wrap it later to get to signature you want to have.

9:42 Leonidas: tsdh: the problem is that i have to call this ~sym macro I got passed with varargs

9:45 tsdh: Leonidas: Well, I think I simply don't get the context.

9:47 Leonidas: tsdh: I want to replace the macros of clojure.tools.logging with timbre macros.

9:47 (redef info) should re-def clojure.tools.logging.info with taoensso.timbre.info

9:48 If I replace them by hand-written macros if works just fine, but that's a lot of boilerplate

9:49 I have macros like (defmacro errorf [& more] `(taoensso.timbre/errorf ~@more))

9:50 and would like to replace the errorf part with the argument of the redef macro

9:56 tsdh: Leonidas: Hm, I think you can just build the expansion by hand in the generated macro instead of using quasi-quote.

9:56 (defmacro nest [sym]

9:56 (let [args (gensym "more")]

9:56 `(defmacro ~sym [& ~args]

9:56 (list* '~sym ~args))))

9:57 Leonidas: Of course, the expansion is an infinite recursion here but that has been in your initial example, too.

9:57 Leonidas: tsdh: yes, I'm rewriting the symbol in my actual code, I just left it out to reduce the noise.

9:57 will try

10:06 tsdh: this fails, it says it can't take the value of the macro

10:07 oh, wait

10:07 I missed the quote

10:09 tsdh: whee, works. thank you a lot! I will have to study this code more in depth

10:09 tsdh: Leonidas: You're welcome!

10:14 xificurC: when I fire up lein repl and in-ns into my namespace and try to evaluate (+ 3 4) I get java.lang.RuntimeException: Unable to resolve symbol + in this context

10:15 tsdh: xificurC: That namespace hasn't been created properly before, i.e., with (ns your.ns ...).

10:16 xificurC: Just (in-ns 'foo) creates the namespace without any bindings, i.e., you don't have all the clojure.core functions available and neither the bindings for java.lang classes.

10:17 xificurC: So compile your namespace before changing to it, or require it from the repl.

10:17 xificurC: tsdh: I have this under src/xml_palettes/core.clj http://sprunge.us/RYjY

10:18 tsdh: xificurC: Yeah, then (require 'xml-palettes.core) before you (in-ns 'xml-palettes.core).

10:18 xificurC: tsdh: I see, thanks!

10:18 tsdh: xificurC: Or compile it in your environment, e.g., with C-c C-k in CIDER.

10:18 xificurC: using inf-clojure

10:19 tsdh: xificurC: That probably also has a binding for that but I don't know it.

10:19 * xificurC C-h m's ...

10:20 xificurC: there's only C-c C-l for load file, not sure if that's the same

10:21 yeah, that seems to work, thanks tsdh

10:44 dnolen: Bronsa: putting the finishing touches on bootstrapped ClojureScript. Will probably cut a pre-release if you could cut a tools.reader release that depends on it, that would be great, then people can do some testing before we cut a "final" ClojureScript one.

10:48 Bronsa: dnolen: sure, I'll cut a 0.10.0-alpha2 release -- don't think I can or even need to depend on a "future" version of cljs

10:49 it'll just work when pulled in by the new cljs and not work if pulled in by older versions

11:11 dnolen: Bronsa: ok, thanks!

11:33 noncom|2: ,(concat '(1 2 3) {:a 1})

11:33 clojurebot: (1 2 3 [:a 1])

11:33 noncom|2: ummmm... how can that be?

11:34 justin_smith: ,(seq {:a 1}) ; because this

11:34 clojurebot: ([:a 1])

11:34 justin_smith: each entry is a two element vector

11:34 noncom|2: ah!

11:34 whoops, i was thinking i started sliding..

11:34 mixed up concat with conj..

11:34 it should be conj..

11:35 justin_smith: ,(conj '(1 2 3) {:a 1})

11:35 clojurebot: ({:a 1} 1 2 3)

11:35 noncom|2: yeah, the order is backwards coz it's a list

11:35 justin_smith: ,(into '(1 2 3) {:a 1})

11:35 clojurebot: ([:a 1] 1 2 3)

11:35 noncom|2: hmmmm

11:38 hellofunk: justin_smith: didn't you say you are using http-kit to create websockets on a clojure server? how is that working out for you, anything i should be aware of when giving it a go after working on jetty?

11:41 justin_smith: hellofunk: it's been working fine for me

11:41 hellofunk: using sente to do it

11:43 hellofunk: justin_smith: is sente basically an abstraction over the http-kit websocket support?

11:43 justin_smith: hellofunk: it is protocol based, it abstracts http-kit and aleph iirc

11:43 it definitely has more than one supported backend

11:44 hellofunk: it lets you use websockets pretty much as if it were core.async

11:44 hellofunk: justin_smith: http-kit's docs suggest the websocket support is already quite easy without any other libraries; what is the advantage of adding sente to the mix?

11:45 justin_smith: hellofunk: you can directly provide clojure datatypes, it covers the serialization / deserialization, and hooks it up to core.async channels

11:45 also it has routing facilities

11:46 hellofunk: word

11:46 justin_smith: if you plan on making your own serialization / deserialization, doing your own routing and async hookup, it won't do much fore you I guess

11:47 on my next project I plan on trying the plain websocket route - I started with sente on this one and it just worked

11:48 hellofunk: "it just worked"... ? you mean Apple invented it?

11:49 justin_smith: it behaved as expected, at first

11:49 since then I have had to intrusively extend the serializer, and put my own routing layer on top...

11:49 stuff that makes me think I could start from scratch next time :)

11:50 hellofunk: it suffices if all you need is one button

12:09 arrdem: justin_smith: so um fair warning gonna harass you about websockets eventually (tm)

12:10 justin_smith: arrdem: cool

12:11 arrdem: one thing that worked out super awesome for our team was defining a single cljc file that defined routing for websocket messages going in both directions, it made hooking up new functionality much less of a tangle

12:12 arrdem: justin_smith: nice!

12:12 justin_smith: otherwise you get the whole "wait, which end do I define first, did I hook up all the fiddly details, oh man I have to edit five different files to make this work" freakout

12:12 arrdem: DRY

12:13 justin_smith: right - if you can define the routes that handle the request and the reply in one place, and then those refer to the functions called - it becomes a nice tree of code to implement with the router at the top, and you just walk down the tree until done

12:13 because otherwise with two way messaging you can get lost in a tangle of calls and responses way to easily, and lose track of details fast

12:14 (which is starting to happen to me now that we add kafka messaging alongside the websockets... ugh).

12:14 arrdem: sure. cool! a year or two ago I remember trying to play with websockets because some of the *coin exchanges exposed websocket data streams for transactions that I couldn't trivially consume

12:14 justin_smith: arrdem: turns out, managing two party communication is 1/3 as complex as managing 3 party communication

12:14 arrdem: now you have a distributed system. merry christmass.

12:15 justin_smith: arrdem: indeed, don't I know it

12:15 arrdem: I would have settled for a puppy, much less work

12:15 and my distributed system doesn't like belly rubs

12:15 arrdem: haha

12:16 's ok you have a distributed system that doesn't like belly rubs, my emitter has been giving me the stinkeye of late too :P

12:16 justin_smith: in all seriousness, we did intend to make a distributed system, but even when you go into it with the attitude "distributed systems are hard, this is going to be a lot of work" - - it turns out distributed systems are still harder than that

12:17 I've been perusing the Lynch Distributed Algorithms book for guidance / orientation, which helps

12:18 even if I am not implementing those algorithms from scratch (kafka and onyx do those things for me), it's good to see why things are arranged the way they are

12:18 arrdem: have you written up or even just found a good Clojure network simulator?

12:18 justin_smith: hmm

12:18 no, I have not

12:18 arrdem: I've got some fun ideas for vector clock based systems but I haven't actually built out anything to prototype them

12:19 lol @ activation energy

12:22 justin_smith: arrdem: do jepsen or rymann do any of this, or do they do their simulation / interferance on an OS level?

12:22 sorry, riemann

12:24 arrdem: justin_smith: I can't quite tell but it looks like jepsen is probably a framework for doing exactly that sort of simulation testing

12:25 justin_smith: presumably it is and once aphyr gets the talk "done" it'll stablilize :P

12:25 justin_smith: arrdem: I think it uses linux kernel / system calls to do the "simulation" - so it is OS level simulaiton

12:25 which may suffice ?

12:26 arrdem: https://github.com/aphyr/jepsen/blob/master/doc/lxc.md

12:27 arrdem: justin_smith: right so this is a framework for spinning up and then partitioning networks of vms

12:27 justin_smith: exactly

12:28 arrdem: hum. I think that for what I'm after local testing with something akin to core.async to simulate a network buss would be sufficient.

12:28 anyway. pleny of other yaks

12:57 clojer_: How do I get a Reagent app uberjar to serve gzipped js files?

13:12 Seylerius: Hrm. How do I turn an clj-time interval into a decimal fraction of days?

13:13 596.23 days, for example.

13:24 joegallo: Seylerius: (in-days the-interval)?

13:28 amalloy: justin_smith: recalling last week's discussion about the oddities of clojure.core/destructure, what do you suppose are the values of a/b/c/d in (let [[a :as b c :as d] (range 5)]) (and, are any of them unbound?)

13:29 justin_smith: amalloy: oh, wow... umm a would be 0 I think, b would be the range... c and d nil?

13:29 wild guess there

13:29 amalloy: c and d are unbound, it turns out

13:29 but you don't get an error from the let-binding if you don't try to use c or d

13:29 you can just write any old junk after an :as

13:30 ,(let [[x y :as z 1 2 3 whatever] (range 5)] [x y z])

13:30 clojurebot: [0 1 (0 1 2 3 4)]

13:30 justin_smith: amalloy: I'm surprised how close I was to right there- but also surprised that those values are unbound rather than nil

13:31 (given the other behaviors I have seen)

13:31 amalloy: justin_smith: destructure just stops processing the binding list once it gets to :as

13:31 so it doesn't create bindings for those

13:31 Bronsa: unbound is slightly better than nil in this case

13:31 justin_smith: amalloy: hidden comment feature!

13:31 Bronsa: at least you get a runtime error rather than nothing

13:31 amalloy: yeah

13:31 justin_smith: Bronsa: yeah, I would rather have seen unbound errors in the other misuses of destructure

13:32 kavkaz: Does the condition map in a function, specifically for the :pre key, have an effect? Or is it purely for documentation?

13:32 justin_smith: I guess silently ignoring erroneous input can be one drawback in the general "data structures before functions, functions before macros" thing - where unused parts of the data structure can look like functionality you were intending to invoke but never get evaluated

13:33 Bronsa: ,((fn [a] {:pre [(string? a)]} a) 1) ;; kavkaz

13:33 clojurebot: #error {\n :cause "Assert failed: (string? a)"\n :via\n [{:type java.lang.AssertionError\n :message "Assert failed: (string? a)"\n :at [sandbox$eval50$fn__51 invoke "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval50$fn__51 invoke "NO_SOURCE_FILE" 0]\n [sandbox$eval50 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compiler eval "Compiler.java" 6792]\n [clojure.lang.Compiler eval "Compiler.java" 6...

13:33 justin_smith: kavkaz: it has an effect if assertions are on, whether assertions are on is a vm level thing outside clojure's control

13:33 Bronsa: justin_smith: there's actually clojure.ore/*assert*

13:33 justin_smith: Bronsa: oh, wow

13:34 Bronsa: I thought it just used the vm config. But anyway I think the same takeaway is there - it's a thing that a user can turn off, so don't rely on assertions enforcing correctness, but do use them to detect bad code.

13:35 Seylerius: joegallo: I'll try that, thanks.

13:35 kavkaz: Bronsa, justin_smith: thanks! saw somebody use it in book. Can i put anything inside that map? Before I knew it was a condition map, i played around with a function and added :hi "hi" to the map. Can I use this like let?

13:35 I know it wouldn't be idiomatic and it will be confusing, but in theory I could do that right?

13:36 justin_smith: kavkaz: it pays attention to the :pre and :post keys - you can put anything in there, but why?

13:36 amalloy: that wouldn't be anything like let. it wouldn't create any bindings

13:36 justin_smith: kavkaz: it isn't like let because it doesn't create bindings you can usefuly refer back to does it?

13:36 Bronsa: yeah sure -- there's actually a vm thing for the `assert` statement in java but we don't use that

13:37 justin_smith: Bronsa: I had figured that since it was raising an AssertionError, turning off assertions would turn it off

13:37 kavkaz: Oh i see, i put a string in there "bound" to a key, it compiled but I guess I never tried referring to that string

13:53 amalloy: i just tride building clojure/clojure for the first time in ages, and `mvn test` prints a bunch of errors about edn round-tripping failures. is that command supposed to work, or is that the wrong way to run clojure's tests?

13:57 arrdem: I believe that is indeed the official test command

13:57 Bronsa: amalloy: it's supposed to work

13:58 amalloy: maybe you had some stale files in target/ or an unclean git history?

13:59 amalloy: the git history is clean, i'm exactly on latest master. stale files in target sounds like it is probably right

14:00 Bronsa: thanks, it all works fine after deleting target. i wonder how old that stuff was

14:02 joefromct: can anyone recommend a current book, article, or blog in regards to getting started with clojure over hadoop processing? seems everything is a few years old at this point... i've looked at clojure-hadoop, netflix pigpen, and cascalog.

14:02 any tips appreciated.

14:02 arrdem: amalloy: probably pre-1.7 printing changes

14:19 justin_smith: joefromct: I know yieldbot has a few nice things. And big picture if you need distributed computation but might not actually specifically need hadoop, check out onyx

14:25 joefromct: justin_smith: that looks interesting, thanks i'll check it out.

14:26 justin_smith: joefromct: I've been experimenting with onyx and like it so far. The project lead is pretty responsive if you need help getting oriented.

14:41 pepijndevos: How the hell do I make a Hiccup select box? There is this select-options thing, but I can't get it to work, and I can;t find any examples.

14:42 arrdem: Has anyone messed with a "server" command mode for leiningen where you get a repl for issuing lein commands rather than a Clojure repl?

14:43 justin_smith: arrdem: lein 1.x had this and 2.x does not for reasons which are reasonable but forgotten by me

14:43 arrdem: of course you can do that easily with boot

14:43 arrdem: justin_smith: sure. ok. maybe time for some mail list archeology later then.

14:44 justin_smith: arrdem: hyPiRion might remember why long running lein executing various tasks stopped being a thing

14:44 amalloy: arrdem: it was called lein interactive, if this helps your searching

14:46 arrdem: https://groups.google.com/forum/#!msg/leiningen/whV-VUdKSWM/O9H7cUQbGF8J

14:49 reuigerg: Hi! I'm making my first web service in Clojure. I made non-web projects in the language, and would like to use it for web stuff too. My hope is not having to go back to Django and Rails for these things. I'm struggling with Authentication. There are 2 libraries in CLJ for doing this, Friend and Buddy. Does anyone have any experience with these, and can tell which one will get you off the ground with the least amount of wor

14:49 elegant solution, but want to have an "account" feature (log in, register, keep a token) before bedtime today. So: What is the leanest way to do authentication in Ring/Compojure webapps?

14:56 justin_smith: reuigerg: the first part of your question was too long and it got cut off by IRC

14:57 reuigerg: Sorry - I'll re-ask more briefly

15:00 I'm making my first Clojure web (& postgres) project (having done non-web stuff). It requires user accounts (login with email+password, save a token to cookie, validate that token on every request). From what I can see, most people either use the lib Friend or Buddy. I'd like to implement this feature as soon as possible, so my question is: what is, in your experience, the leanest and quickest way to implement this in a ri

15:00 webapp? What are some great texts to read, in order to understand how to do this? Like a screencast or tutorial.

15:03 justin_smith: reuigerg: first half was cut off again

15:03 reuigerg: Shortest version: What is the quickest and leanest way to do user account & authentication in Ring/Compojure webapps? Are there any good guides for this?

15:03 Sorry :(

15:03 justin_smith: reuigerg: it's OK, wanted to make sure we weren't missing essential stuff...

15:04 I looked into friend and just ended up whipping something up with ring-session and bcrypt, I've talked to a few other people with similar stories

15:05 reuigerg: I see. I'm wrestling with Friend as well at the moment, but don't know how to make sense of it all yet. Worried about doing it all vanilla, because it seems easy to screw up (and then screw all users over)

15:06 justin_smith: reuigerg: a) don't store a password, store the bcrypt hash b) use the bcrypt hash-verification function on login

15:07 and do this over ssl, of course

15:07 there's not a lot of moving parts there

15:08 if you need the extra workflow stuff from friend, use it of course. But for simpler setups it seems more trouble than it's worth.

15:09 reuigerg: justin_smith: Ok, thank you. Maybe that is the easiest way. Btw, I've seen you answer questions a lot in #clojure. Thanks for that! Appreciate it

15:10 expez: reuigerg: you might want to check out Buddy

15:10 justin_smith: I try, hopefully it's helpful

15:10 expez: reuigerg: https://github.com/funcool/buddy it's easier to pick and choose from buddy than it is from friend

15:11 reuigerg: justin_smith: how do you then check authentication on each request? I guess you always want to assure that the user is logged in. Do you save a session somewhere, or generate that (like in JWT)?

15:11 ed-g: reuigerg, I found a useful Friend tutorial @ https://github.com/ddellacosta/friend-interactive-form-tutorial

15:12 reuigerg, I'm in the same boat you are.

15:12 justin_smith: reuigerg: jwt if we load balance (WARNING: default for jwt is to accept the encoding type as provided by client, one of the encoding types is "none" which allows them to provide auth in plaintext and is a huge security hole. Be sure you are whitelisting encoding methods server side)

15:12 reuigerg: expez: I see. Have been fighting with both Friend a couple of days, but havent figured it out

15:12 ed-g: cool! Thank you! Will read :)

15:12 justin_smith: reuigerg: if not using load-balancing, it's easy to have a server side in-memory session and require users to log back in after restarts

15:14 reuigerg: justin_smith: valid point

15:17 To you all who answered: thank you for helping a guy confured in an unfamiliar but exciting labyrinth of parens

15:17 cmarques: What's the preferred way of doing function stubbing when testing with clojure.test?

15:19 justin_smith: cmarques: best option, if you can pull it off, is to parameterize your code so you don't actually need to mock a specific var

15:19 otherwise there is with-redefs

15:19 amalloy: arrdem: you mentioned wanting to see my reimplementation of destructure. not that i expect it would ever get in, but the patch is at https://www.refheap.com/bdd1b19b6f60d21fc00e48e0e. i'm no really sure about the change to use next/first instead of nth; it'll be faster for seqs, and involve one wasted allocation for vectors

15:20 cmarques: justin_smith my specific case: I have a ring handler that calls a function foo that accesses the database. When testing the handler, I don't want to access the database.

15:20 justin_smith: cmarques: yeah, sounds like a good use case for with-redefs, unless you want a test db

15:21 cmarques: or you could have a middleware that supplies the db access function, which could be replaced with a non-db replacement while testing

15:21 whatever is cleaner in your use case

15:22 cmarques: justin_smith I am looking at with-redefs, seems to do what I need. Thanks for your help!

15:24 justin_smith: cmarques: as with any with-foo, be super careful about scope+ laziness leading to unexpected results

15:24 basically, either do your work inside the body, or force anything lazy before returning it

15:25 cmarques: I see, I'll keep that in mind!

15:34 crazydiamond: Hi. If I have (defn f [a b] (+ a b)), can I get '(+ a b), i.e. the body?

15:34 justin_smith: no

15:35 well, you can from #'f

15:35 crazydiamond: so, I should have code in a first place

15:35 justin_smith: but not from the value of #'f

15:35 amalloy: justin_smith: not even from #'f really

15:35 hiredman: depends what you mean by having (defn f [a b] (+ a b))

15:35 justin_smith: ,(defn f [a b] (+ a b))

15:35 hiredman: if you run that through eval (the compiler) then you don't have it

15:35 clojurebot: #'sandbox/f

15:35 hiredman: you have compiled byte code

15:35 justin_smith: ,(:source #'f)

15:35 clojurebot: nil

15:35 justin_smith: ahh

15:36 crazydiamond: aha

15:36 hiredman: if you actually have (defn f [a b] (+ a b)) then

15:36 amalloy: justin_smith: source reads the .clj file

15:36 justin_smith: right, I forgot

15:36 crazydiamond: I tried to get it with clojure.repl/source and got "Source not found"

15:36 hiredman: ,(-> (defn f [a b] (+ a b)) (nth 3))

15:36 clojurebot: #error {\n :cause "nth not supported on this type: Var"\n :via\n [{:type java.lang.UnsupportedOperationException\n :message "nth not supported on this type: Var"\n :at [clojure.lang.RT nthFrom "RT.java" 881]}]\n :trace\n [[clojure.lang.RT nthFrom "RT.java" 881]\n [clojure.lang.RT nth "RT.java" 847]\n [sandbox$eval72 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compiler eval "Compiler.java" 68...

15:36 hiredman: ,(-> '(defn f [a b] (+ a b)) (nth 3))

15:36 clojurebot: (+ a b)

15:37 crazydiamond: ok, got it. thanks!

15:37 TEttinger: ,(-> '(defn f [a b] (+ a b)) (nth 3) eval)

15:37 clojurebot: #error {\n :cause "Unable to resolve symbol: a in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6611]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: a in this context"\n ...

15:37 TEttinger: ,(-> '(defn f [a b] (+ a b)) eval)

15:37 clojurebot: #'sandbox/f

15:37 TEttinger: ,(f 3 4)

15:37 clojurebot: 7

15:37 TEttinger: nice clojurebot!

15:37 (inc hiredman)

15:37 lazybot: ⇒ 81

15:37 hiredman: clojurebot: source?

15:37 clojurebot: source is http://github.com/hiredman/clojurebot/tree/master

15:38 hiredman: meh

15:38 source is misleading

15:47 devnewb: hi all can anyone point me to an example of core.async ‘async/reduce’ in the wild, I can’t seem to aggregate my channel results into it.. I only get the last item

15:48 cmarques: justin_smith: Just solved the problem with with-redefs, works beautifully! Thank you!

15:49 devnewb: I’ve tried something like : (println "merged : " (async/<!! (async/reduce merge {} some-chan)))

15:50 justin_smith: cmarques: (async/reduce conj [] some-chan) is less interesting, but has fewer gotchas

15:50 cmarques: cool, glad to hear it worked out

15:55 devnewb: justin_smith, thanks, I already had that and it worked.. I was just trying to puzzle through the merge gotchas… thanks for the pointer though

15:57 justin_smith: devnewb: if conj worked and merge did not, I would look at the hash maps you are merging - maybe you want merge-with and not merge

15:57 ,(merge {:a 0} {:a 1} {:a 2})

15:57 clojurebot: {:a 2}

15:57 justin_smith: ,(merge-with + {:a 0} {:a 1} {:a 2})

15:57 clojurebot: {:a 3}

15:58 devnewb: justin_smith: ah, thanks

15:58 I was misunderstanding merge

15:58 should have read the docs more

16:09 justin_smith: (inc docs)

16:09 lazybot: ⇒ 2

16:12 vas: Hi Guys, I finally have my site live, the login system is just an "email you a link and you click it" ... it works (!) but when I first run the app it takes an unusually long amount of time to send the first email... any ideas as to how I can get more "what's going on under the hood" feels/insight?

16:17 maybe it's a mail issue o.O

16:20 oddcully: vas: if you send your email synchronously, then there could be an overhead for establiching everything to make the mail go out

16:20 vas: things like authing and reverse lookups on hosts etc

16:21 vas: oddcully: you know it sounds like that might be it. i'm using postal to send mail. i wonder if there's a way to do it asynchronously and just kinda "throw it on the queue"

16:24 justin_smith: vas: you could put the send in a future (and be sure to come back and check the future for errors later)

16:25 dagda1_: when working with a binary tree clojure devs use zippers?

16:25 would clojure devs

16:26 justin_smith: dagda1_: that is one approach. If you are just navigating one a recursive function might suffice.

16:26 amalloy: depends what you are doing with the tree. usually not

16:26 dagda1_: amalloy would you just use a map?

16:26 amalloy: conveniently the same answer applies: depends what you are doing with the tree. usually not

16:27 vas: oddcully: I added a line to my apache config "ProxyBadHeader Ignore" and it works... =|

16:28 justin_smith: that's a cool idea. The future part of that makes sense to me, but how would one "come back to check errors" ?

16:29 dagda1_: well that cleared things up......glad I asked

16:29 justin_smith: vas: put the future somewhere where you can access it later (perhaps an atom). You can test if it has returned with realized?

16:29 vas: if you access the value, it will throw the exception it caught, if any

16:30 so you can put your exception handling code in a function (maybe another future...) that comes back later and checks that it was successful

16:31 of course this assumes that it is reasonable to fire-and-forget your email sending while handling a request, and come back and deal with errors (if any) later

16:32 oddcully: vas: also depends, if you really need to tell the user, that you have sent the email. you can as well just tell the user, that you have done so and just records failures on your server for forensics

16:32 amalloy: dagda1_: the point is, what you use to work with a data structure depends on what you want to do. you could as well ask "how would you work with an integer? would you just use division?" well, probably not, but i can't be sure without knowing your goal

16:34 oddcully: vas: i also don't see how the apache config there relates; i only know, that javamail takes a short time to establish stuff. it's in general a good idea to offload sending mails to a queue/worker/... since there can be errors all over the place

16:37 dagda1_: amalloy I am just tyring to solve this problem https://www.hackerrank.com/challenges/swap-nodes and to me a zipper seemed a good approach which made me wonder what somebody with more experience in clojure would use

16:41 amalloy: you might build the tree with a zipper. their input format is pretty hostile. the swapping seems like it would be easier to do with just some recursion of your own? i dunno, maybe you could use a zipper for that easily enough too

16:42 justin_smith: dagda1_: hell, I think that flip could be done with get-in / update-in

16:42 granted, that's after a skim, maybe that's too simple

16:42 amalloy: justin_smith: for *all* nodes at depth N? seems a bit tricky

16:43 justin_smith: ahh, yeah, so maybe recursion + update-in, right

16:53 crazydiamond: Hwdy get all subsequences of a vector? Like [1 2 3] -> [[1 2 3] [1 2] [2 3] [1] [2] [3]]?

16:57 amalloy: you forgot []

17:02 crazydiamond: amalloy, where? :)

17:02 ah, yep

17:02 0-length one

17:06 amalloy: anyway crazydiamond, of course there is nothing like this built in. you can build your own pretty easily with the use of clojure.core/partition

17:07 crazydiamond: amalloy, thanks. I was thinking about two nested loops

17:07 amalloy: in a functional language, you usually want to be thinking about recursion instead

17:08 (here, as in many cases, there is a better solution that involves combining some other built-ins, but doing it recursively first is a good exercise)

17:10 crazydiamond: in the meantime, I wonder why Rich Hickey made that (loop ...) explicit, but not e.g. transformation of tail recursion into loop/recur style

17:10 (though, I bet one might construct complex enough macro for it)

17:14 scriptor: crazydiamond: as I understand it, they wanted recur to be explicit so that it could be used as desired

17:14 otherwise, since there's no actual TCO

17:15 it'd be somewhat unclear when a function gets optimized or not

17:15 crazydiamond: aha, make sense

17:17 akkad: crazydiamond: jvm limitations? stack overflow

17:29 crazydiamond: amalloy, do you think this is good enough solution for my problem? or overcomplicated? http://dpaste.com/2DYXPPW

17:31 amalloy: you didn't like the partition suggestion? it is a much simpler way to write your all-subvecs-of...

17:31 ,(partition 3 1 (range 5))

17:31 clojurebot: ((0 1 2) (1 2 3) (2 3 4))

17:33 crazydiamond: ah... yep

17:33 I was thinking it returns only first one

17:33 lol

17:34 thanks for help!

17:37 amalloy: anyway, the simpler solution i alluded to earlier is ##((fn all-subvecs [xs] (cons [] (mapcat #(partition % 1 xs) (range 1 (inc (count xs)))))) (range 4))

17:37 lazybot: ⇒ ([] (0) (1) (2) (3) (0 1) (1 2) (2 3) (0 1 2) (1 2 3) (0 1 2 3))

17:43 crazydiamond: I'm so far from real solution. 'Cause what I want to do in the end is to extract common parts from functions (automated refactoring). And now I'm considering turning 1-argument function chains like (a (b (c))) and (a (b (d))) into [[(fn f0001 [x] (a (b x)))] (f0001 (c)) (f0001 (d))]

17:44 * crazydiamond enjoys loud thinking

17:50 joefromct: does anyone use parkour? I'm getting a strange class-not-found exception from the stable github checkout, and it's as simple as adding a lein dep.... no idea if i'm missing something. doesn't seem to be any issues.

17:50 (from others)

17:53 hiredman: I haven't used it in a while, what class not found exception?

17:55 I think I had to add a few hadoop artifacts as provided dependencies when I used it

17:55 joefromct: hiredman: yeah, i think thats what i did wrong. i bet i added hadoop stuff, but incorrect versions for my cluster or something .

17:56 hiredman: https://github.com/damballa/parkour/blob/master/doc/intro.md

17:56 could be

17:56 joefromct: yeah, i copied those dependencies verbatum

17:56 *verbatim

17:56 hiredman: ah, and if you are on emr, it needs to be 2.2.0

17:56 (or it did last time I was)

18:01 joefromct: hiredman: maybe it has something to do with my lein :user profile... i don't think it's pulling any of them. i just added hadoop as a project dep. and it pulled a bunch of dependencies

18:01 weird

18:01 *wierd

18:01 hiredman: yeah it shouldn't pull them in

18:02 that is what provided means, it means whatever environment the project runs in will provide them

18:02 joefromct: so, if it's in my user profile, and i put ":provided" , i need to add to my classpath manually or something ?

18:02 hiredman: I don't think so

18:02 joefromct: i guess i need to read up on that

18:02 i haven't used :provided for anything i've done this far

18:03 amalloy: i don't think you want a provided dependency in your user profile. that sounds weird

18:03 hiredman: the parkour local running should take care of it for testing, and the cluster will provide them for deploying

18:03 joefromct: ok. i'll just have to somehow be sure that my cluster "provides" that stuff at the same version and whatnot i guess.

18:18 Guthur: Hi, I was wondering if anyone has used Javelin with Reagent

18:19 I like javelins cell approach for data flow, but find myself having to wrap the value in Ratoms to get the dynamic updates of reagent

18:19 has anyone found a nice pattern for this

18:32 michaniskin: Guthur: you can check out https://github.com/HostelRocket/aspis for ideas

18:34 oh nevermind, i thought it was a different thing

18:34 jonathanj: is there something like (update) or (update-in) that operates on vectors?

18:35 hiredman: ,(update-in [0 1 2 3] [0] inc)

18:35 clojurebot: [1 1 2 3]

18:35 jonathanj: hrm, and if i have nested vecs? [["a" 0] ...]

18:35 hiredman: ,(update-in [0 [0 0] 2 3] [1 0] inc)

18:35 clojurebot: [0 [1 0] 2 3]

18:37 jonathanj: ,(map #(update-in % [1] inc) [["a" 0] ["b" 1]])

18:37 clojurebot: (["a" 1] ["b" 2])

18:37 jonathanj: but i was hoping for something more elegant

18:38 hiredman: you asked for something like update-in, and you got update-in exactly

18:39 jonathanj: no need to be defensive, i'm just trying to write better code

18:40 justin_smith: jonathanj: so what thing would be "like update-in but for vectors" and more elegant than using update-in with a vector?

18:40 jonathanj: i meant more elegant than map with an anonymous function

18:40 amalloy: jonathanj: ##(doc for)

18:40 lazybot: ⇒ "Macro ([seq-exprs body-expr]); List comprehension. Takes a vector of one or more binding-form/collection-expr pairs, each followed by zero or more modifiers, and yields a lazy sequence of evaluations of expr. Collections are iterated in a nested fashion, rightmost ... https://www.refheap.com/107101

18:41 amalloy: is usually prettier than map with a lambda

18:42 TEttinger: ,(mapv (juxt first (comp inc second)) [["a" 0] ["b" 1]])

18:42 clojurebot: [["a" 1] ["b" 2]]

18:42 hiredman: I am saying, you asked for update-in, and you got it, udpate-in works on maps and vectors the same way, if you wanted something more, then you should ask for that

18:42 TEttinger: no anonymous functions, tricky as heck

18:43 hiredman: it sounds like want you want is more like an a tree transform library like xlt or whatever for xml

18:43 TEttinger: anonymous functions can be more elegant that point free style when it's abused like I did

18:43 hiredman: I am sure someone has written such a thing for clojure, but writing your own shouldn't be that hard either

18:44 TEttinger: clojure.zip might be a good starting point?

18:44 jonathanj: i guess i want something like lenses

18:50 TEttinger: jonathanj: there's a series of articles on this blog about lenses in clojure, the first one is mostly about how update-in and assoc-in largely fill the same role. http://blog.podsnap.com/vanhole.html

18:50 jonathanj: TEttinger: yes, thank you, i found those upon searching for lenses in clojure, i'm busy reading through the series right now

19:13 bjarn: does anyone know if there is a way so pass a string directly into a query using java.jdbc’s query function, such that the string becomes a *part* of the query itself and not a parameter *to* the query?

19:14 hiredman: use the str function

19:15 [(str "select * from " table-name " where foo = ?") 5]

19:17 bjarn: wow, that should have been way more obvious than it was five minutes ago

19:18 wait, you mean the standard library will help with that???

19:18 lazybot: bjarn: How could that be wrong?

19:18 bjarn: thanks!

19:50 shayne_: Can you reference a let defined var from within a fn passed as an argument to the righthandside of that let declaration?

19:51 spieden_: shayne_: i'm pretty sure the function will close over it. you can reference symbols defined within the same let in any case

19:52 shayne_: e.g. (let [xyz (foo (fn [] (... xyz)))])

19:52 hiredman: no

19:53 the simple way to refer to that is as a recursive let binding

19:54 the way to reason about it is ((fn [xyz] ....) (foo (fn [] (... xyz))))

19:55 shayne_: hiredman - new to this, mind elaborating a little?

19:55 hiredman: (which is not to say the forms are equivilant, but it correctly guides the intuition in this case)

19:55 shayne_: thanks chewing on that

19:57 hiredman: some other languages have a thing called let rec, which will let you do stuff like that, clojure has letfn, which allows you to have local functions that are mutually recursive, but it is limited

20:00 shayne_: hireman: a little more color on what I'm trying to do: (let [id (addListener obj (fn [] (...) (...) (removeListener obj id)))])

20:01 the api I am working with emits an ID when you call addListener and I'd like to reference that ID within this closure. Something that's fairly trivial in, say, JavaScript.

20:02 hiredman* ^^

20:12 futuro: it sounds like what you want to do is bind a new value to id based on a previous value in id, so something like (defn fun [id] (let [id (addListener ...)]))

20:16 shayne_: furturo: close, but I actually do want the most recent reference to remove the listener's callback from its own callback

20:18 futuro: It doesn't?

20:20 shayne_: the value of id is the listener that was just added and inside of the listener's callback I want to remove the listener so the callback (itself) will no longer be called.... in js: var id = SomeObj.addListener(()=> { ...; SomeObj.removeListener(id)})

20:23 futuro: everything I've seen so far seems to imply that precisely what you have described should happen, and then id will be bound to whatever value is returned by addListener, so I have no clue why it wouldn't

20:30 shayne_: futuro: given the let method I described or another suggestion?

20:31 futuro: given the let method you described

20:33 shayne_: futuro: it doesn't appear to (it's nil) as the let expression is evaluated the fn that acts as the callback is not capturing the named var on the left-hand side of the let.

20:36 futuro: you'd need to pass in id before hand. That is, inside the let expression the first id will have no value initially. So (let [foo (some-fn) bar (str foo)]), before some-fn is evaluated, is somewhat like (let [nil (some-fn) bar nil]), since none of the LHS variables have had values assigned to them yet

20:38 if you want to pass in a value for id to some-fn at a later time you could use an anonymous function, or (partial), but since id hasn't had a value assigned to it yet, referencing it is nonsensical

20:39 shayne_: with: (let [id 0 id (addListener obj (fn [] (...) (removeListener obj id)))]) id: is always 0

20:42 futuro: does addListener return a value?

20:42 shayne_: futuro: yes

20:42 justin_smith: futuro: that wouldn't change how id is assigned - the initial value will always be shadowed

20:42 shayne_: futuro: Here's my workaround: (def id 0) (set! id (addListener obj (fn [] (...) (removeListener obj id))))

20:42 justin_smith: though the addListener call will not be able to use it's own return value in that lambda

20:43 that's terrible - def should not be used that way

20:44 shayne_: justin_smith- just a workaround

20:44 and I know it's terrible... bleck

20:44 futuro: justin_smith: id is not shadowed before the binding inside of let, but every reference afterwards it will be

20:44 shayne_: I really felt like this was something I was overlooking, because this pattern is so simple in other languages.

20:45 futuro: ,((fn [x] (let [x (inc x)] x)) 1)

20:45 clojurebot: 2

20:46 futuro: shayne_: without knowing more about what code you're working with, it sounds like you might be running into trouble with the immutable data structures of clojure, and the various methods of forcing mutability (like swap!)

20:46 shayne_: the problem is the lambda is passed into the expression that returns the value it needs to capture

20:46 again consider the JS... var id = obj.addListener(function() { ...; obj.removeListener(id); });

20:47 justin_smith: futuro: shayne_: the answer is to use a promise

20:47 shayne_: there's no immutability

20:47 err... mutation

20:47 justin_smith: right

20:47 justin_smith: doing that now

20:47 justin_smith: (let [id (promise)] (deliver id (fn [] ... (something @id))))

20:47 that's how you do it

20:48 shayne_: you understand the problem with using def right? def only creates globals, it doesn't do local scope

20:49 err, by globals I mean vars at the top level of a namespace, of course

20:50 shayne_: justin_smith: was just playing with the code, but a good reminder

20:51 justin_smith: shayne_: I'm pedantic about that one because it is one of the biggest differences between clojure and scheme, and a common mistake of newcomers from scheme

22:00 arrdem: Bronsa: ping

22:03 Bronsa: arrdem: pong

22:05 namra: does somenone know a vim command to move n lines up or down?

22:06 the motion docs don't provide any info

22:06 justin_smith: namra: <x>t<y> where x and y are numbers

22:07 namra: never mind, that is wrong

22:07 namra: justin_smith: sorry didn't state my question clearly, i just want to move the cursor

22:08 justin_smith: namra: oh, <x>j or <x>k to move x lines down or up

22:08 there is also Control+f and control+b for moving by screens

22:09 namra: justin_smith: yes those are the key commands. but they don't work as commands.

22:09 justin_smith: oh, I misunderstood

22:09 arrdem: Bronsa: got a minute to look at the ns-publics TANAL tree with me? trying to understand what the desired output bytecode is.

22:10 Bronsa: arrdem: yeah sure

22:11 arrdem: Bronsa: https://www.refheap.com/107106 trimmed tree of only the relevant lambda

22:12 Bronsa: arrdem: are you trying to understand why temjvm explodes on ns-publics?

22:13 arrdem: Bronsa: da

22:13 and fix...

22:13 Bronsa: arrdem: I thought I already mentioned the reason

22:13 arrdem: it's not an analysis bug

22:13 arrdem: Bronsa: maybe last year I didn't find it in my notes.

22:14 Bronsa: arrdem: no i mean, I remember mentioning it like 3 days ago in slack I might have not highlighted you though

22:14 arrdem: Bronsa: yeah I don't remember that

22:15 Bronsa: arrdem: look at the source code for ns-publics -- it's something like (fn [^Var v] (if (instance? Var v) (.something v)))

22:15 arrdem: Bronsa: yep

22:15 Bronsa: I get what's going on here, my real question is "is there something silly we could/should do so this just works"

22:16 Bronsa: arrdem: the only way to fix this is to change the emitter to emit "untyped" locals like Compiler.java does so that type hints are not enforced

22:17 arrdem: Bronsa: gotcha. OK.

22:17 Bronsa: arrdem: can't estimate how much work that'll be. might be tricky

22:18 arrdem: Bronsa: but for that it'd get us another step towards CinC I can't honestly say it's a feature

22:19 or rather but that

22:19 Bronsa: err, what?

22:20 arrdem: there is no point to that change but to make loading core work

22:20 Bronsa: yeah

22:20 arrdem: tempted to special case the eval of that AST to eval a less silly AST...

22:21 Bronsa: arrdem: I mean, clojure.org explicitely states that type hints are not enforced so I take the blame for this

22:22 arrdem: Bronsa: yeah. OK. I'll take a look at this and see what I can do while remaining a Clojure compiler.

22:22 Bronsa: (I still think that there's no good reason not to enforce type hints)

22:22 namra: justin_smith: one could specify the absolute line number. i.e. in command mode just type the line number and the cursor will jump to it

22:22 arrdem: you and me both

22:23 but if we ever figure out how to do emitter configs that's something a user could toggle

22:23 Bronsa: yes

22:23 arrdem: s/emitter configs/modular emitters/g

22:24 any thoughts on that? I threw some stuff at the wall but nothing I thought would really be performant.

22:24 kinda tempted to prioritize usability over perf

22:24 Bronsa: this particular use case could even be done as an AST rewrite without touching the emitter I think

22:24 rewrite pass*

22:24 arrdem: I mean you just drop the local tags or retag to Object

22:25 which we could do by default...

22:25 Bronsa: yeah, and move the cast to the interop point

22:26 arrdem: right that's what I was going to try. don't do any casting or typing until you interop and then checkcast.

22:26 Bronsa: that's what compiler.java does, yeah

22:26 arrdem: simplest stupidest thing that could possibly work...

22:26 Bronsa: has the disadvantage of requiring a checkcast for every interop form

22:27 arrdem: so one thing I've been thinking about is that the JVM bytecode we emit really hides the stack as a dataflow graph

22:27 don't know how to do this yet, but given a dataflow representation of generated code fixing stuff like that is dead easy

22:27 Bronsa: arrdem: depending on how bored I get next week I *might* try and refactor/rewrite the casting/boxing mess in t.a.jvm

22:28 arrdem: Bronsa: please do, it'll probably improve my test coverage as well <3

22:28 anyway I'm gonna keep banging on cleaning up the emitter for fun

22:29 hopefully I'll get to try profiling the new flatten stuff soon but I'd like to clear the current bug list before potentially introducing more with that

22:30 so if there are others I should know about speak now :P

22:31 TEttinger: yaaaay bug fixes

22:31 Bronsa: arrdem: other than the reflector stuff in the analyzer, I'm not aware of any other

22:33 arrdem: btw re the emitter, it would be interesting to know how much time is spent building up the bytecode data structure vs how much time it's spent traversing it & emitting actual bytecode

22:34 arrdem: Bronsa: I seem to recall from your previous investigations that we're wasting a _lot_ of time in concat right now.

22:34 Bronsa: hence the flatten stuff that does a single pass loop unrolled conj! with no intermediary datastructures

22:34 Bronsa: yeah, that definitely dominates time

22:35 TEttinger: uh, is this the flatten that is

22:35 ~flatten

22:35 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

22:35 arrdem: TEttinger: no this is my own flatten impl that is more domain specifi

22:35 *c

22:35 TEttinger: cool

22:35 * arrdem digs for commit

22:35 TEttinger: I wouldn't bother to optimize clojure.core/flatten

22:36 arrdem: TEttinger: https://github.com/clojure/tools.emitter.jvm/blob/054873c0f1e553c9941b4675b31b42d8c1eed654/src/main/clojure/clojure/tools/emitter/jvm/emit.clj#L66

22:36 Bronsa: but if the time spent traversing/transforming is still significant it might mean that we need to rethink the emission thing alltoghether -- maybe the current representation is just too expensive?

22:36 arrdem: yeah who knows. only way to find out is to benchmark that thing.

22:37 which involves rewriting half the bloody emitter to avoid `~@ concats

22:37 TEttinger: unicode! who put unicode in this code! (λ AST → Options) → Bytecode

22:37 Bronsa: yup

22:37 arrdem: that would be me

22:37 like.. last yeart

22:37 *year

22:37 TEttinger: arrdem, but that's Scala's turf

22:38 you'll start a gang war

22:38 arrdem: TEttinger: FITE ME U NERD

22:38 I like my type signature docstrings thnx

22:38 TEttinger: http://scalaz.github.io/scalaz/scalaz-2.9.0-1-6.0.1/doc.sxr/scalaz/Kleisli.scala.html

22:38 I have that bookmarked under IDEAL SCALA CODE

22:39 intuitive and clear.

22:39 def <=<[C](k: C => M[A])(implicit b: Bind[M]): Kleisli[M, C, B] = ☆(k) >=> this

22:39 it hurts me.

22:40 arrdem: Bronsa: you still using those UTF8 rewrite rules you gave me last summer?

22:41 Bronsa: and yeah I don't know what we'll have to do if this representation is just too slow.

22:41 I want to play with building a data flow model for JVM bytecode that we can use as yet another intermediary target for writing a real peephole optimizer, but that's a ways out.

22:44 Bronsa: arrdem: haven't changed my emeacs setup in years

22:44 i know those rewrite rules mess with how my code is indented but I kinda sorta don't really care :P

22:45 arrdem: Bronsa: this typifies your code style yes :P

22:46 Bronsa: arrdem: yeah. the current representation doesn't really buy us that much over directly emitting bytecode

22:47 arrdem: Bronsa: I mean... I love TEMJVM just for the existing representation because it's a friggin clojure datastructure I can muck with and understand, but yeah we could build something good for a lot more leverage.

22:47 Bronsa: I think the unchecked locals patch is gonna be dead easy, just a sec

22:48 Bronsa: it was definitely invaluable when writing it. Couldn't imagine debugging emission bugs without the data representation

22:49 but i'm not too sure it's the best approach. doesn't buy us enough benefits to justify the performance hit

22:49 arrdem: I would have given up on Oxcart but for it...

22:49 Bronsa: dunno. I'd like to be happy with the analyzer infrastructure before investing time refactoring/rewriting the emitter

22:49 arrdem: Bronsa: I mean I think anything else we do would be a sources as leafs dataflow graph

22:50 so you have a tree of ops which have nth things on the stack which will be popped as children

22:51 your sources being constants and ILOADs

22:51 and your sinks being pops whether implicit or explicit

22:52 this would let you consider ops like checkcast to be pop 1 push 1 adding metadata, and now you can walk the dataflow path backwards to eliminate duplicate casts.

22:52 ^ this being the reason that I'm messing with any of this again actually

22:53 Bronsa: right, and stuff like intrinsics could be implemented in a less hackish way than it is now

22:57 arrdem: interestingly the flatten stuff gets us part of the way there...

22:58 if you squint really hard at the "can force thunks of 0 arguments" case

23:02 Bronsa: going to sleep now

23:03 arrdem: g'night thanks as always

23:05 mtamrf: what's an idiomatic way to express a nested for loop with side effects (dosync)?

23:13 arrdem: mtamrf: can doseq not do what you need?

23:13 mtamrf: note that doseq can go over multiple sequences and supports all of for's sequence expressions

23:14 justin_smith: mtamrf: dosync is for refs, you are likely thinking of doseq? or do you want a doseq of dosyncs? that almost sounds like a doctor seuss poem

23:14 (doc dosync)

23:14 clojurebot: "([& exprs]); Runs the exprs (in an implicit do) in a transaction that encompasses exprs and any nested calls. Starts a transaction if none is already running on this thread. Any uncaught exception will abort the transaction and flow out of dosync. The exprs may be run more than once, but any effects on Refs will be atomic."

23:18 mtamrf: typo - I did mean doseq

23:22 arrdem: aaand bronsa no longer idles on a proxy ok

23:23 whelp I think I found a two local fix to that issue rather than some huge rewrite..

23:33 TEttinger: nice arrdem

23:39 gganley: are there any meetups in MA that is should know about?

23:42 arrdem: aaaand Stackmap issues

23:42 fml

23:43 TEttinger: yeah turns out not checking casts is pretty easy :P

Logging service provided by n01se.net