#clojure logs

2015-07-27

00:39justin_smith(inc TimMc)
00:39lazybot⇒ 101
01:15rhg135I wish you were joking
04:44tgoossensI have a function (defn blah [q] (.query conn q) (.close conn)) But i need the output of the query. Just us a let?
04:45tgoossens(the query output must be the return value, but close conn must come after obviously)
04:56H4nstgoossens: (defn blah [q] (with-open [conn (open-conn)] (.query conn q))) may be an option
04:56H4nstgoossens: but if query can't ever fail, use a simple let.
04:57tgoossensH4ns, thanks!
07:46noncomis 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
07:46noncomsure, the post is about CL, but that made me to think about Clojure destructuring too
07:47noncomi suppose the implementations can be comparable..
07:55wasamasanope
07:55wasamasado your own benchmarks and write a blog post
08:29expez(let [rdr (LineNumberingPushbackReader. (FileReader. path))] ...) I'm leaking file descriptors here, right?
08:30schmirexpez: yes
08:30schmirexpez: use the with-open macro
08:31expezmhmm
08:35jeayeI'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.
08:36jeayeIdeally, the projects would hit a nice sweet spot between trivial and too much of a time investment to understand fully. Suggestions?
08:44hellofunkjeaye: 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
09:20Leonidashi
09:20LeonidasI have a macro like this:
09:20Leonidas(defmacro nest [sym] `(defmacro ~sym [& more#] (~sym more#)))
09:21Leonidasunfortunately, I'd like to actually unquote-splicing more# but it doesn't work, since it is not in a quasi quote
09:21Leonidaswhat can I do?
09:23Leonidas(apply does not work, since sym is most likely a macro)
09:30expezLeonidas: 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 :)
09:31tsdhLeonidas: That can't work. Basically, you want to know the actual arguments to your macro in its very own definition.
09:31tsdhexpez: Macros writing macros is where the fun starts! ;-)
09:33tsdhexpez: "Let over Lambda" is a really entertaining book doing all these sorts of multi-stage programming.
09:34expeztsdh: That's next on my reading list. Going through On Lisp now :)
09:34tsdhexpez: Have fun! :-)
09:34Leonidasexpez: it gets better. I'm writing a macro to write a macro to replace existing macros :-/
09:35tsdhLeonidas: Awesome!
09:35LeonidasI have mastering clojure macros open too, but didn't get that much time to read it
09:35LeonidasLOL is on my reading list as well, though.
09:37tsdhLeonidas: 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.
09:42Leonidastsdh: the problem is that i have to call this ~sym macro I got passed with varargs
09:45tsdhLeonidas: Well, I think I simply don't get the context.
09:47Leonidastsdh: I want to replace the macros of clojure.tools.logging with timbre macros.
09:47Leonidas(redef info) should re-def clojure.tools.logging.info with taoensso.timbre.info
09:48LeonidasIf I replace them by hand-written macros if works just fine, but that's a lot of boilerplate
09:49LeonidasI have macros like (defmacro errorf [& more] `(taoensso.timbre/errorf ~@more))
09:50Leonidasand would like to replace the errorf part with the argument of the redef macro
09:56tsdhLeonidas: Hm, I think you can just build the expansion by hand in the generated macro instead of using quasi-quote.
09:56tsdh(defmacro nest [sym]
09:56tsdh (let [args (gensym "more")]
09:56tsdh `(defmacro ~sym [& ~args]
09:56tsdh (list* '~sym ~args))))
09:57tsdhLeonidas: Of course, the expansion is an infinite recursion here but that has been in your initial example, too.
09:57Leonidastsdh: yes, I'm rewriting the symbol in my actual code, I just left it out to reduce the noise.
09:57Leonidaswill try
10:06Leonidastsdh: this fails, it says it can't take the value of the macro
10:07Leonidasoh, wait
10:07LeonidasI missed the quote
10:09Leonidastsdh: whee, works. thank you a lot! I will have to study this code more in depth
10:09tsdhLeonidas: You're welcome!
10:14xificurCwhen 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:15tsdhxificurC: That namespace hasn't been created properly before, i.e., with (ns your.ns ...).
10:16tsdhxificurC: 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:17tsdhxificurC: So compile your namespace before changing to it, or require it from the repl.
10:17xificurCtsdh: I have this under src/xml_palettes/core.clj http://sprunge.us/RYjY
10:18tsdhxificurC: Yeah, then (require 'xml-palettes.core) before you (in-ns 'xml-palettes.core).
10:18xificurCtsdh: I see, thanks!
10:18tsdhxificurC: Or compile it in your environment, e.g., with C-c C-k in CIDER.
10:18xificurCusing inf-clojure
10:19tsdhxificurC: That probably also has a binding for that but I don't know it.
10:20xificurCthere's only C-c C-l for load file, not sure if that's the same
10:21xificurCyeah, that seems to work, thanks tsdh
10:44dnolenBronsa: 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:48Bronsadnolen: 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:49Bronsait'll just work when pulled in by the new cljs and not work if pulled in by older versions
11:11dnolenBronsa: ok, thanks!
11:33noncom|2,(concat '(1 2 3) {:a 1})
11:33clojurebot(1 2 3 [:a 1])
11:33noncom|2ummmm... how can that be?
11:34justin_smith,(seq {:a 1}) ; because this
11:34clojurebot([:a 1])
11:34justin_smitheach entry is a two element vector
11:34noncom|2ah!
11:34noncom|2whoops, i was thinking i started sliding..
11:34noncom|2mixed up concat with conj..
11:34noncom|2it should be conj..
11:35justin_smith,(conj '(1 2 3) {:a 1})
11:35clojurebot({:a 1} 1 2 3)
11:35noncom|2yeah, the order is backwards coz it's a list
11:35justin_smith,(into '(1 2 3) {:a 1})
11:35clojurebot([:a 1] 1 2 3)
11:35noncom|2hmmmm
11:38hellofunkjustin_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:41justin_smithhellofunk: it's been working fine for me
11:41justin_smithhellofunk: using sente to do it
11:43hellofunkjustin_smith: is sente basically an abstraction over the http-kit websocket support?
11:43justin_smithhellofunk: it is protocol based, it abstracts http-kit and aleph iirc
11:43justin_smithit definitely has more than one supported backend
11:44justin_smithhellofunk: it lets you use websockets pretty much as if it were core.async
11:44hellofunkjustin_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:45justin_smithhellofunk: you can directly provide clojure datatypes, it covers the serialization / deserialization, and hooks it up to core.async channels
11:45justin_smithalso it has routing facilities
11:46hellofunkword
11:46justin_smithif 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:47justin_smithon my next project I plan on trying the plain websocket route - I started with sente on this one and it just worked
11:48hellofunk"it just worked"... ? you mean Apple invented it?
11:49justin_smithit behaved as expected, at first
11:49justin_smithsince then I have had to intrusively extend the serializer, and put my own routing layer on top...
11:49justin_smithstuff that makes me think I could start from scratch next time :)
11:50justin_smithhellofunk: it suffices if all you need is one button
12:09arrdemjustin_smith: so um fair warning gonna harass you about websockets eventually (tm)
12:10justin_smitharrdem: cool
12:11justin_smitharrdem: 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:12arrdemjustin_smith: nice!
12:12justin_smithotherwise 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:12arrdemDRY
12:13justin_smithright - 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:13justin_smithbecause 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:14justin_smith(which is starting to happen to me now that we add kafka messaging alongside the websockets... ugh).
12:14arrdemsure. 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:14justin_smitharrdem: turns out, managing two party communication is 1/3 as complex as managing 3 party communication
12:14arrdemnow you have a distributed system. merry christmass.
12:15justin_smitharrdem: indeed, don't I know it
12:15justin_smitharrdem: I would have settled for a puppy, much less work
12:15justin_smithand my distributed system doesn't like belly rubs
12:15arrdemhaha
12:16arrdem'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:16justin_smithin 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:17justin_smithI've been perusing the Lynch Distributed Algorithms book for guidance / orientation, which helps
12:18justin_smitheven 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:18arrdemhave you written up or even just found a good Clojure network simulator?
12:18justin_smithhmm
12:18justin_smithno, I have not
12:18arrdemI've got some fun ideas for vector clock based systems but I haven't actually built out anything to prototype them
12:19arrdemlol @ activation energy
12:22justin_smitharrdem: do jepsen or rymann do any of this, or do they do their simulation / interferance on an OS level?
12:22justin_smithsorry, riemann
12:24arrdemjustin_smith: I can't quite tell but it looks like jepsen is probably a framework for doing exactly that sort of simulation testing
12:25arrdemjustin_smith: presumably it is and once aphyr gets the talk "done" it'll stablilize :P
12:25justin_smitharrdem: I think it uses linux kernel / system calls to do the "simulation" - so it is OS level simulaiton
12:25justin_smithwhich may suffice ?
12:26justin_smitharrdem: https://github.com/aphyr/jepsen/blob/master/doc/lxc.md
12:27arrdemjustin_smith: right so this is a framework for spinning up and then partitioning networks of vms
12:27justin_smithexactly
12:28arrdemhum. 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:28arrdemanyway. pleny of other yaks
12:57clojer_How do I get a Reagent app uberjar to serve gzipped js files?
13:12SeyleriusHrm. How do I turn an clj-time interval into a decimal fraction of days?
13:13Seylerius596.23 days, for example.
13:24joegalloSeylerius: (in-days the-interval)?
13:28amalloyjustin_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:29justin_smithamalloy: oh, wow... umm a would be 0 I think, b would be the range... c and d nil?
13:29justin_smithwild guess there
13:29amalloyc and d are unbound, it turns out
13:29amalloybut you don't get an error from the let-binding if you don't try to use c or d
13:29amalloyyou can just write any old junk after an :as
13:30amalloy,(let [[x y :as z 1 2 3 whatever] (range 5)] [x y z])
13:30clojurebot[0 1 (0 1 2 3 4)]
13:30justin_smithamalloy: I'm surprised how close I was to right there- but also surprised that those values are unbound rather than nil
13:31justin_smith(given the other behaviors I have seen)
13:31amalloyjustin_smith: destructure just stops processing the binding list once it gets to :as
13:31amalloyso it doesn't create bindings for those
13:31Bronsaunbound is slightly better than nil in this case
13:31justin_smithamalloy: hidden comment feature!
13:31Bronsaat least you get a runtime error rather than nothing
13:31amalloyyeah
13:31justin_smithBronsa: yeah, I would rather have seen unbound errors in the other misuses of destructure
13:32kavkazDoes the condition map in a function, specifically for the :pre key, have an effect? Or is it purely for documentation?
13:32justin_smithI 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:33Bronsa,((fn [a] {:pre [(string? a)]} a) 1) ;; kavkaz
13:33clojurebot#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:33justin_smithkavkaz: it has an effect if assertions are on, whether assertions are on is a vm level thing outside clojure's control
13:33Bronsajustin_smith: there's actually clojure.ore/*assert*
13:33justin_smithBronsa: oh, wow
13:34justin_smithBronsa: 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:35Seyleriusjoegallo: I'll try that, thanks.
13:35kavkazBronsa, 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:35kavkazI know it wouldn't be idiomatic and it will be confusing, but in theory I could do that right?
13:36justin_smithkavkaz: it pays attention to the :pre and :post keys - you can put anything in there, but why?
13:36amalloythat wouldn't be anything like let. it wouldn't create any bindings
13:36justin_smithkavkaz: it isn't like let because it doesn't create bindings you can usefuly refer back to does it?
13:36Bronsayeah sure -- there's actually a vm thing for the `assert` statement in java but we don't use that
13:37justin_smithBronsa: I had figured that since it was raising an AssertionError, turning off assertions would turn it off
13:37kavkazOh 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:53amalloyi 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:57arrdemI believe that is indeed the official test command
13:57Bronsaamalloy: it's supposed to work
13:58Bronsaamalloy: maybe you had some stale files in target/ or an unclean git history?
13:59amalloythe git history is clean, i'm exactly on latest master. stale files in target sounds like it is probably right
14:00amalloyBronsa: thanks, it all works fine after deleting target. i wonder how old that stuff was
14:02joefromctcan 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:02joefromctany tips appreciated.
14:02arrdemamalloy: probably pre-1.7 printing changes
14:19justin_smithjoefromct: 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:25joefromctjustin_smith: that looks interesting, thanks i'll check it out.
14:26justin_smithjoefromct: I've been experimenting with onyx and like it so far. The project lead is pretty responsive if you need help getting oriented.
14:41pepijndevosHow 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:42arrdemHas anyone messed with a "server" command mode for leiningen where you get a repl for issuing lein commands rather than a Clojure repl?
14:43justin_smitharrdem: lein 1.x had this and 2.x does not for reasons which are reasonable but forgotten by me
14:43justin_smitharrdem: of course you can do that easily with boot
14:43arrdemjustin_smith: sure. ok. maybe time for some mail list archeology later then.
14:44justin_smitharrdem: hyPiRion might remember why long running lein executing various tasks stopped being a thing
14:44amalloyarrdem: it was called lein interactive, if this helps your searching
14:46arrdemhttps://groups.google.com/forum/#!msg/leiningen/whV-VUdKSWM/O9H7cUQbGF8J
14:49reuigergHi! 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:49reuigergelegant 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:56justin_smithreuigerg: the first part of your question was too long and it got cut off by IRC
14:57reuigergSorry - I'll re-ask more briefly
15:00reuigergI'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:00reuigergwebapp? What are some great texts to read, in order to understand how to do this? Like a screencast or tutorial.
15:03justin_smithreuigerg: first half was cut off again
15:03reuigergShortest 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:03reuigergSorry :(
15:03justin_smithreuigerg: it's OK, wanted to make sure we weren't missing essential stuff...
15:04justin_smithI 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:05reuigergI 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:06justin_smithreuigerg: a) don't store a password, store the bcrypt hash b) use the bcrypt hash-verification function on login
15:07justin_smithand do this over ssl, of course
15:07justin_smiththere's not a lot of moving parts there
15:08justin_smithif 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:09reuigergjustin_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:10expezreuigerg: you might want to check out Buddy
15:10justin_smithI try, hopefully it's helpful
15:10expezreuigerg: https://github.com/funcool/buddy it's easier to pick and choose from buddy than it is from friend
15:11reuigergjustin_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:11ed-greuigerg, I found a useful Friend tutorial @ https://github.com/ddellacosta/friend-interactive-form-tutorial
15:12ed-greuigerg, I'm in the same boat you are.
15:12justin_smithreuigerg: 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:12reuigergexpez: I see. Have been fighting with both Friend a couple of days, but havent figured it out
15:12reuigerged-g: cool! Thank you! Will read :)
15:12justin_smithreuigerg: 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:14reuigergjustin_smith: valid point
15:17reuigergTo you all who answered: thank you for helping a guy confured in an unfamiliar but exciting labyrinth of parens
15:17cmarquesWhat's the preferred way of doing function stubbing when testing with clojure.test?
15:19justin_smithcmarques: 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:19justin_smithotherwise there is with-redefs
15:19amalloyarrdem: 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:20cmarquesjustin_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:20justin_smithcmarques: yeah, sounds like a good use case for with-redefs, unless you want a test db
15:21justin_smithcmarques: or you could have a middleware that supplies the db access function, which could be replaced with a non-db replacement while testing
15:21justin_smithwhatever is cleaner in your use case
15:22cmarquesjustin_smith I am looking at with-redefs, seems to do what I need. Thanks for your help!
15:24justin_smithcmarques: as with any with-foo, be super careful about scope+ laziness leading to unexpected results
15:24justin_smithbasically, either do your work inside the body, or force anything lazy before returning it
15:25cmarquesI see, I'll keep that in mind!
15:34crazydiamondHi. If I have (defn f [a b] (+ a b)), can I get '(+ a b), i.e. the body?
15:34justin_smithno
15:35justin_smithwell, you can from #'f
15:35crazydiamondso, I should have code in a first place
15:35justin_smithbut not from the value of #'f
15:35amalloyjustin_smith: not even from #'f really
15:35hiredmandepends what you mean by having (defn f [a b] (+ a b))
15:35justin_smith,(defn f [a b] (+ a b))
15:35hiredmanif you run that through eval (the compiler) then you don't have it
15:35clojurebot#'sandbox/f
15:35hiredmanyou have compiled byte code
15:35justin_smith,(:source #'f)
15:35clojurebotnil
15:35justin_smithahh
15:36crazydiamondaha
15:36hiredmanif you actually have (defn f [a b] (+ a b)) then
15:36amalloyjustin_smith: source reads the .clj file
15:36justin_smithright, I forgot
15:36crazydiamondI tried to get it with clojure.repl/source and got "Source not found"
15:36hiredman,(-> (defn f [a b] (+ a b)) (nth 3))
15:36clojurebot#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:36hiredman,(-> '(defn f [a b] (+ a b)) (nth 3))
15:36clojurebot(+ a b)
15:37crazydiamondok, got it. thanks!
15:37TEttinger,(-> '(defn f [a b] (+ a b)) (nth 3) eval)
15:37clojurebot#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:37TEttinger,(-> '(defn f [a b] (+ a b)) eval)
15:37clojurebot#'sandbox/f
15:37TEttinger,(f 3 4)
15:37clojurebot7
15:37TEttingernice clojurebot!
15:37TEttinger(inc hiredman)
15:37lazybot⇒ 81
15:37hiredmanclojurebot: source?
15:37clojurebotsource is http://github.com/hiredman/clojurebot/tree/master
15:38hiredmanmeh
15:38hiredmansource is misleading
15:47devnewbhi 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:48cmarquesjustin_smith: Just solved the problem with with-redefs, works beautifully! Thank you!
15:49devnewbI’ve tried something like : (println "merged : " (async/<!! (async/reduce merge {} some-chan)))
15:50justin_smithcmarques: (async/reduce conj [] some-chan) is less interesting, but has fewer gotchas
15:50justin_smithcmarques: cool, glad to hear it worked out
15:55devnewbjustin_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:57justin_smithdevnewb: 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:57justin_smith,(merge {:a 0} {:a 1} {:a 2})
15:57clojurebot{:a 2}
15:57justin_smith,(merge-with + {:a 0} {:a 1} {:a 2})
15:57clojurebot{:a 3}
15:58devnewbjustin_smith: ah, thanks
15:58devnewbI was misunderstanding merge
15:58devnewbshould have read the docs more
16:09justin_smith(inc docs)
16:09lazybot⇒ 2
16:12vasHi 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:17vasmaybe it's a mail issue o.O
16:20oddcullyvas: if you send your email synchronously, then there could be an overhead for establiching everything to make the mail go out
16:20oddcullyvas: things like authing and reverse lookups on hosts etc
16:21vasoddcully: 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:24justin_smithvas: you could put the send in a future (and be sure to come back and check the future for errors later)
16:25dagda1_when working with a binary tree clojure devs use zippers?
16:25dagda1_would clojure devs
16:26justin_smithdagda1_: that is one approach. If you are just navigating one a recursive function might suffice.
16:26amalloydepends what you are doing with the tree. usually not
16:26dagda1_amalloy would you just use a map?
16:26amalloyconveniently the same answer applies: depends what you are doing with the tree. usually not
16:27vasoddcully: I added a line to my apache config "ProxyBadHeader Ignore" and it works... =|
16:28vasjustin_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:29dagda1_well that cleared things up......glad I asked
16:29justin_smithvas: put the future somewhere where you can access it later (perhaps an atom). You can test if it has returned with realized?
16:29justin_smithvas: if you access the value, it will throw the exception it caught, if any
16:30justin_smithso you can put your exception handling code in a function (maybe another future...) that comes back later and checks that it was successful
16:31justin_smithof 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:32oddcullyvas: 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:32amalloydagda1_: 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:34oddcullyvas: 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:37dagda1_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:41amalloyyou 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:42justin_smithdagda1_: hell, I think that flip could be done with get-in / update-in
16:42justin_smithgranted, that's after a skim, maybe that's too simple
16:42amalloyjustin_smith: for *all* nodes at depth N? seems a bit tricky
16:43justin_smithahh, yeah, so maybe recursion + update-in, right
16:53crazydiamondHwdy get all subsequences of a vector? Like [1 2 3] -> [[1 2 3] [1 2] [2 3] [1] [2] [3]]?
16:57amalloyyou forgot []
17:02crazydiamondamalloy, where? :)
17:02crazydiamondah, yep
17:02crazydiamond0-length one
17:06amalloyanyway 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:07crazydiamondamalloy, thanks. I was thinking about two nested loops
17:07amalloyin a functional language, you usually want to be thinking about recursion instead
17:08amalloy(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:10crazydiamondin the meantime, I wonder why Rich Hickey made that (loop ...) explicit, but not e.g. transformation of tail recursion into loop/recur style
17:10crazydiamond(though, I bet one might construct complex enough macro for it)
17:14scriptorcrazydiamond: as I understand it, they wanted recur to be explicit so that it could be used as desired
17:14scriptorotherwise, since there's no actual TCO
17:15scriptorit'd be somewhat unclear when a function gets optimized or not
17:15crazydiamondaha, make sense
17:17akkadcrazydiamond: jvm limitations? stack overflow
17:29crazydiamondamalloy, do you think this is good enough solution for my problem? or overcomplicated? http://dpaste.com/2DYXPPW
17:31amalloyyou didn't like the partition suggestion? it is a much simpler way to write your all-subvecs-of...
17:31amalloy,(partition 3 1 (range 5))
17:31clojurebot((0 1 2) (1 2 3) (2 3 4))
17:33crazydiamondah... yep
17:33crazydiamondI was thinking it returns only first one
17:33crazydiamondlol
17:34crazydiamondthanks for help!
17:37amalloyanyway, 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:37lazybot⇒ ([] (0) (1) (2) (3) (0 1) (1 2) (2 3) (0 1 2) (1 2 3) (0 1 2 3))
17:43crazydiamondI'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:50joefromctdoes 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:50joefromct(from others)
17:53hiredmanI haven't used it in a while, what class not found exception?
17:55hiredmanI think I had to add a few hadoop artifacts as provided dependencies when I used it
17:55joefromcthiredman: yeah, i think thats what i did wrong. i bet i added hadoop stuff, but incorrect versions for my cluster or something .
17:56hiredmanhttps://github.com/damballa/parkour/blob/master/doc/intro.md
17:56hiredmancould be
17:56joefromctyeah, i copied those dependencies verbatum
17:56joefromct*verbatim
17:56hiredmanah, and if you are on emr, it needs to be 2.2.0
17:56hiredman(or it did last time I was)
18:01joefromcthiredman: 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:01joefromctweird
18:01joefromct*wierd
18:01hiredmanyeah it shouldn't pull them in
18:02hiredmanthat is what provided means, it means whatever environment the project runs in will provide them
18:02joefromctso, if it's in my user profile, and i put ":provided" , i need to add to my classpath manually or something ?
18:02hiredmanI don't think so
18:02joefromcti guess i need to read up on that
18:02joefromcti haven't used :provided for anything i've done this far
18:03amalloyi don't think you want a provided dependency in your user profile. that sounds weird
18:03hiredmanthe parkour local running should take care of it for testing, and the cluster will provide them for deploying
18:03joefromctok. i'll just have to somehow be sure that my cluster "provides" that stuff at the same version and whatnot i guess.
18:18GuthurHi, I was wondering if anyone has used Javelin with Reagent
18:19GuthurI 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:19Guthurhas anyone found a nice pattern for this
18:32michaniskinGuthur: you can check out https://github.com/HostelRocket/aspis for ideas
18:34michaniskinoh nevermind, i thought it was a different thing
18:34jonathanjis there something like (update) or (update-in) that operates on vectors?
18:35hiredman,(update-in [0 1 2 3] [0] inc)
18:35clojurebot[1 1 2 3]
18:35jonathanjhrm, and if i have nested vecs? [["a" 0] ...]
18:35hiredman,(update-in [0 [0 0] 2 3] [1 0] inc)
18:35clojurebot[0 [1 0] 2 3]
18:37jonathanj,(map #(update-in % [1] inc) [["a" 0] ["b" 1]])
18:37clojurebot(["a" 1] ["b" 2])
18:37jonathanjbut i was hoping for something more elegant
18:38hiredmanyou asked for something like update-in, and you got update-in exactly
18:39jonathanjno need to be defensive, i'm just trying to write better code
18:40justin_smithjonathanj: so what thing would be "like update-in but for vectors" and more elegant than using update-in with a vector?
18:40jonathanji meant more elegant than map with an anonymous function
18:40amalloyjonathanj: ##(doc for)
18:40lazybot⇒ "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:41amalloyis usually prettier than map with a lambda
18:42TEttinger,(mapv (juxt first (comp inc second)) [["a" 0] ["b" 1]])
18:42clojurebot[["a" 1] ["b" 2]]
18:42hiredmanI 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:42TEttingerno anonymous functions, tricky as heck
18:43hiredmanit sounds like want you want is more like an a tree transform library like xlt or whatever for xml
18:43TEttingeranonymous functions can be more elegant that point free style when it's abused like I did
18:43hiredmanI am sure someone has written such a thing for clojure, but writing your own shouldn't be that hard either
18:44TEttingerclojure.zip might be a good starting point?
18:44jonathanji guess i want something like lenses
18:50TEttingerjonathanj: 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:50jonathanjTEttinger: yes, thank you, i found those upon searching for lenses in clojure, i'm busy reading through the series right now
19:13bjarndoes 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:14hiredmanuse the str function
19:15hiredman[(str "select * from " table-name " where foo = ?") 5]
19:17bjarnwow, that should have been way more obvious than it was five minutes ago
19:18bjarnwait, you mean the standard library will help with that???
19:18lazybotbjarn: How could that be wrong?
19:18bjarnthanks!
19:50shayne_Can you reference a let defined var from within a fn passed as an argument to the righthandside of that let declaration?
19:51spieden_shayne_: i'm pretty sure the function will close over it. you can reference symbols defined within the same let in any case
19:52shayne_e.g. (let [xyz (foo (fn [] (... xyz)))])
19:52hiredmanno
19:53hiredmanthe simple way to refer to that is as a recursive let binding
19:54hiredmanthe way to reason about it is ((fn [xyz] ....) (foo (fn [] (... xyz))))
19:55shayne_hiredman - new to this, mind elaborating a little?
19:55hiredman(which is not to say the forms are equivilant, but it correctly guides the intuition in this case)
19:55shayne_thanks chewing on that
19:57hiredmansome 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:00shayne_hireman: a little more color on what I'm trying to do: (let [id (addListener obj (fn [] (...) (...) (removeListener obj id)))])
20:01shayne_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:02shayne_hiredman* ^^
20:12futuroit 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:16shayne_furturo: close, but I actually do want the most recent reference to remove the listener's callback from its own callback
20:18futuroIt doesn't?
20:20shayne_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:23futuroeverything 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:30shayne_futuro: given the let method I described or another suggestion?
20:31futurogiven the let method you described
20:33shayne_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:36futuroyou'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:38futuroif 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:39shayne_with: (let [id 0 id (addListener obj (fn [] (...) (removeListener obj id)))]) id: is always 0
20:42futurodoes addListener return a value?
20:42shayne_futuro: yes
20:42justin_smithfuturo: that wouldn't change how id is assigned - the initial value will always be shadowed
20:42shayne_futuro: Here's my workaround: (def id 0) (set! id (addListener obj (fn [] (...) (removeListener obj id))))
20:42justin_smiththough the addListener call will not be able to use it's own return value in that lambda
20:43justin_smiththat's terrible - def should not be used that way
20:44shayne_justin_smith- just a workaround
20:44shayne_and I know it's terrible... bleck
20:44futurojustin_smith: id is not shadowed before the binding inside of let, but every reference afterwards it will be
20:44shayne_I really felt like this was something I was overlooking, because this pattern is so simple in other languages.
20:45futuro,((fn [x] (let [x (inc x)] x)) 1)
20:45clojurebot2
20:46futuroshayne_: 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:46shayne_the problem is the lambda is passed into the expression that returns the value it needs to capture
20:46shayne_again consider the JS... var id = obj.addListener(function() { ...; obj.removeListener(id); });
20:47justin_smithfuturo: shayne_: the answer is to use a promise
20:47shayne_there's no immutability
20:47shayne_err... mutation
20:47shayne_justin_smith: right
20:47shayne_justin_smith: doing that now
20:47justin_smith(let [id (promise)] (deliver id (fn [] ... (something @id))))
20:47justin_smiththat's how you do it
20:48justin_smithshayne_: you understand the problem with using def right? def only creates globals, it doesn't do local scope
20:49justin_smitherr, by globals I mean vars at the top level of a namespace, of course
20:50shayne_justin_smith: was just playing with the code, but a good reminder
20:51justin_smithshayne_: 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:00arrdemBronsa: ping
22:03Bronsaarrdem: pong
22:05namradoes somenone know a vim command to move n lines up or down?
22:06namrathe motion docs don't provide any info
22:06justin_smithnamra: <x>t<y> where x and y are numbers
22:07justin_smithnamra: never mind, that is wrong
22:07namrajustin_smith: sorry didn't state my question clearly, i just want to move the cursor
22:08justin_smithnamra: oh, <x>j or <x>k to move x lines down or up
22:08justin_smiththere is also Control+f and control+b for moving by screens
22:09namrajustin_smith: yes those are the key commands. but they don't work as commands.
22:09justin_smithoh, I misunderstood
22:09arrdemBronsa: got a minute to look at the ns-publics TANAL tree with me? trying to understand what the desired output bytecode is.
22:10Bronsaarrdem: yeah sure
22:11arrdemBronsa: https://www.refheap.com/107106 trimmed tree of only the relevant lambda
22:12Bronsaarrdem: are you trying to understand why temjvm explodes on ns-publics?
22:13arrdemBronsa: da
22:13arrdemand fix...
22:13Bronsaarrdem: I thought I already mentioned the reason
22:13Bronsaarrdem: it's not an analysis bug
22:13arrdemBronsa: maybe last year I didn't find it in my notes.
22:14Bronsaarrdem: no i mean, I remember mentioning it like 3 days ago in slack I might have not highlighted you though
22:14arrdemBronsa: yeah I don't remember that
22:15Bronsaarrdem: look at the source code for ns-publics -- it's something like (fn [^Var v] (if (instance? Var v) (.something v)))
22:15arrdemBronsa: yep
22:15arrdemBronsa: I get what's going on here, my real question is "is there something silly we could/should do so this just works"
22:16Bronsaarrdem: 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:17arrdemBronsa: gotcha. OK.
22:17Bronsaarrdem: can't estimate how much work that'll be. might be tricky
22:18arrdemBronsa: but for that it'd get us another step towards CinC I can't honestly say it's a feature
22:19arrdemor rather but that
22:19Bronsaerr, what?
22:20arrdemthere is no point to that change but to make loading core work
22:20Bronsayeah
22:20arrdemtempted to special case the eval of that AST to eval a less silly AST...
22:21Bronsaarrdem: I mean, clojure.org explicitely states that type hints are not enforced so I take the blame for this
22:22arrdemBronsa: yeah. OK. I'll take a look at this and see what I can do while remaining a Clojure compiler.
22:22Bronsa(I still think that there's no good reason not to enforce type hints)
22:22namrajustin_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:22arrdemyou and me both
22:23arrdembut if we ever figure out how to do emitter configs that's something a user could toggle
22:23Bronsayes
22:23arrdems/emitter configs/modular emitters/g
22:24arrdemany thoughts on that? I threw some stuff at the wall but nothing I thought would really be performant.
22:24arrdemkinda tempted to prioritize usability over perf
22:24Bronsathis particular use case could even be done as an AST rewrite without touching the emitter I think
22:24Bronsarewrite pass*
22:24arrdemI mean you just drop the local tags or retag to Object
22:25arrdemwhich we could do by default...
22:25Bronsayeah, and move the cast to the interop point
22:26arrdemright that's what I was going to try. don't do any casting or typing until you interop and then checkcast.
22:26Bronsathat's what compiler.java does, yeah
22:26arrdemsimplest stupidest thing that could possibly work...
22:26Bronsahas the disadvantage of requiring a checkcast for every interop form
22:27arrdemso one thing I've been thinking about is that the JVM bytecode we emit really hides the stack as a dataflow graph
22:27arrdemdon't know how to do this yet, but given a dataflow representation of generated code fixing stuff like that is dead easy
22:27Bronsaarrdem: depending on how bored I get next week I *might* try and refactor/rewrite the casting/boxing mess in t.a.jvm
22:28arrdemBronsa: please do, it'll probably improve my test coverage as well <3
22:28arrdemanyway I'm gonna keep banging on cleaning up the emitter for fun
22:29arrdemhopefully 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:30arrdemso if there are others I should know about speak now :P
22:31TEttingeryaaaay bug fixes
22:31Bronsaarrdem: other than the reflector stuff in the analyzer, I'm not aware of any other
22:33Bronsaarrdem: 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:34arrdemBronsa: I seem to recall from your previous investigations that we're wasting a _lot_ of time in concat right now.
22:34arrdemBronsa: hence the flatten stuff that does a single pass loop unrolled conj! with no intermediary datastructures
22:34Bronsayeah, that definitely dominates time
22:35TEttingeruh, is this the flatten that is
22:35TEttinger~flatten
22:35clojurebotflatten 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:35arrdemTEttinger: no this is my own flatten impl that is more domain specifi
22:35arrdem*c
22:35TEttingercool
22:35TEttingerI wouldn't bother to optimize clojure.core/flatten
22:36arrdemTEttinger: https://github.com/clojure/tools.emitter.jvm/blob/054873c0f1e553c9941b4675b31b42d8c1eed654/src/main/clojure/clojure/tools/emitter/jvm/emit.clj#L66
22:36Bronsabut 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:36arrdemyeah who knows. only way to find out is to benchmark that thing.
22:37arrdemwhich involves rewriting half the bloody emitter to avoid `~@ concats
22:37TEttingerunicode! who put unicode in this code! (λ AST → Options) → Bytecode
22:37Bronsayup
22:37arrdemthat would be me
22:37arrdemlike.. last yeart
22:37arrdem*year
22:37TEttingerarrdem, but that's Scala's turf
22:38TEttingeryou'll start a gang war
22:38arrdemTEttinger: FITE ME U NERD
22:38arrdemI like my type signature docstrings thnx
22:38TEttingerhttp://scalaz.github.io/scalaz/scalaz-2.9.0-1-6.0.1/doc.sxr/scalaz/Kleisli.scala.html
22:38TEttingerI have that bookmarked under IDEAL SCALA CODE
22:39TEttingerintuitive and clear.
22:39TEttinger def <=<[C](k: C => M[A])(implicit b: Bind[M]): Kleisli[M, C, B] = ☆(k) >=> this
22:39TEttingerit hurts me.
22:40arrdemBronsa: you still using those UTF8 rewrite rules you gave me last summer?
22:41arrdemBronsa: and yeah I don't know what we'll have to do if this representation is just too slow.
22:41arrdemI 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:44Bronsaarrdem: haven't changed my emeacs setup in years
22:44Bronsai know those rewrite rules mess with how my code is indented but I kinda sorta don't really care :P
22:45arrdemBronsa: this typifies your code style yes :P
22:46Bronsaarrdem: yeah. the current representation doesn't really buy us that much over directly emitting bytecode
22:47arrdemBronsa: 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:47arrdemBronsa: I think the unchecked locals patch is gonna be dead easy, just a sec
22:48Bronsait was definitely invaluable when writing it. Couldn't imagine debugging emission bugs without the data representation
22:49Bronsabut i'm not too sure it's the best approach. doesn't buy us enough benefits to justify the performance hit
22:49arrdemI would have given up on Oxcart but for it...
22:49Bronsadunno. I'd like to be happy with the analyzer infrastructure before investing time refactoring/rewriting the emitter
22:49arrdemBronsa: I mean I think anything else we do would be a sources as leafs dataflow graph
22:50arrdemso you have a tree of ops which have nth things on the stack which will be popped as children
22:51arrdemyour sources being constants and ILOADs
22:51arrdemand your sinks being pops whether implicit or explicit
22:52arrdemthis 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:52arrdem^ this being the reason that I'm messing with any of this again actually
22:53Bronsaright, and stuff like intrinsics could be implemented in a less hackish way than it is now
22:57arrdeminterestingly the flatten stuff gets us part of the way there...
22:58arrdemif you squint really hard at the "can force thunks of 0 arguments" case
23:02Bronsagoing to sleep now
23:03arrdemg'night thanks as always
23:05mtamrfwhat's an idiomatic way to express a nested for loop with side effects (dosync)?
23:13arrdemmtamrf: can doseq not do what you need?
23:13arrdemmtamrf: note that doseq can go over multiple sequences and supports all of for's sequence expressions
23:14justin_smithmtamrf: 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:14justin_smith(doc dosync)
23:14clojurebot"([& 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:18mtamrftypo - I did mean doseq
23:22arrdemaaand bronsa no longer idles on a proxy ok
23:23arrdemwhelp I think I found a two local fix to that issue rather than some huge rewrite..
23:33TEttingernice arrdem
23:39gganleyare there any meetups in MA that is should know about?
23:42arrdemaaaand Stackmap issues
23:42arrdemfml
23:43arrdemTEttinger: yeah turns out not checking casts is pretty easy :P