#clojure log - Sep 15 2015

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

2:10 neoncontrails: ,(doc list*)

2:10 clojurebot: "([args] [a args] [a b args] [a b c args] [a b c d & ...]); Creates a new list containing the items prepended to the rest, the last of which will be treated as a sequence."

2:10 neoncontrails: When is this preferable to list?

2:15 jeaye: neoncontrails: When you're consing multiple items onto a list.

2:15 ,(list 1 2 (list 3 4))

2:15 clojurebot: (1 2 (3 4))

2:15 jeaye: ,(list* 1 2 (list 3 4))

2:15 clojurebot: (1 2 3 4)

2:21 neoncontrails: jeaye: That makes sense. Thanks!

2:23 jeaye: Sure.

3:26 instilled: the documentation of defrecord states that metadata is supported. Unfortunately I fail to access the metadata on a defrecord. How is this done?

3:53 mavbozo: instilled, (-> (Point. 3 4) (with-meta {:foo :bar}) meta)

3:53 instilled, ;= {:foo :bar}

5:05 iwo: hey, this is a really stupid question but... is there any better way to write: (do (side-effect-fn) nil)

5:06 kind of like dorun (returns nil) but not for seqs

5:07 mavbozo: iwo, rather than (do (println "foo") nil), you can just write (println "foo")

5:08 println is side-effecting function

5:08 iwo: I have a function that does something like: (if (...) (something) (do (increment-failure-metric) nil))

5:09 mavbozo: in this case, increment-failure-metric returns something :(

5:09 mavbozo: iwo, and you don't want the return value from increment-failure-metric?

5:09 iwo: so I end up having to explicitly add nil as the return value. I know it's probably stupid to try to find a function to do that, it just feels like there should be one :)

5:10 luma: why do you need to specifically return nil?

5:10 iwo: one option I was trying to find: a function that takes any arguments and always returns nil

5:11 luma: because the return value of my fn is obviously something completely different, and has nothing to do with metrics

5:11 talios: mmm mutation - something smells there

5:11 iwo: I guess the answer here is that I should move the metrics out of this function

5:11 basically I want: do-nil :)

5:15 TMA: now you have it: (defn do-nil [& _] nil)

5:15 talios: :)

5:15 luma: (def do-nil (constantly nil))

5:16 TMA: ,((constantly nil) 1 2 3)

5:16 clojurebot: nil

5:16 talios: TMA - mmm, doesn't iwo want it to RUN what he passes in, THEN return nil. that just returns will only

5:17 mavbozo: ,((constantly nil) (do (println "foo") :done))

5:17 clojurebot: foo\n

5:17 mavbozo: #((constantly nil) (do (println "foo") :done))

5:17 TMA: ,((constantly nil) (println "foo"))

5:17 clojurebot: foo\n

5:17 noncom: you should not be concerned with the return value if you disregard it in any case

5:18 TMA: ,((fn [& _] nil) (println "foo"))

5:18 clojurebot: foo\n

5:18 talios: I guess the bigger question is what does (something) return

5:18 noncom: for example, (swap!) is a very common operation and it always returns a value (most often not nil). it is used in so many places that treating it as a special case is unfeasible

5:18 TMA: talios: clojure does not seem to be lazy

5:19 talios: TMA - whats laziness got to do with it?

5:20 TMA: talios: arguments are evaluated even if they are unused; therefore any side effects are performed

5:20 TEttinger: TMA: ,((fn [& _] nil) (println "foo")) is calling that fn with nil

5:20 println returns nil

5:22 talios: TMA - him, I thought (if) was a special form, assumed it handled that case. easy enough to macro up a lazy (if~ ) or something tho

5:22 mungojelly: yeah clojure has laziness as a prominent strategy but not a basis is my impression

5:23 talios: it's probably one of the main things I dislike about clojure ( over tooling, and lack of types ) is the inconsistency in strictness

5:24 TMA: TEttinger: the whole invocation returns nil (regardless of the return value of any provided parameter forms); it first evaluates the arguments to (fn [& _] nil); during the evaluation any side effects are performed (in other words the argument forms are RUN); the values are then passed onto (fn [& _] nil) which ignores them and returns nil

5:26 mungojelly: the feeling seems to be, here we are on the jvm, we're going to play with all these messy toys here, so we're also going to have a functional laziness and keep it in a box and negotiate in various ways between that and the mess

5:26 mjg: messy toys?

5:27 mungojelly: things that are practically useful but hugely effectual or stateful or otherwise not ideal

5:27 TEttinger: TMA: I'm curious what the alternative here is. would you want to do a compile-time analysis of the whole program path to see where values produced by side-effecting functions are used, and not run the side effects if the values aren't used?

5:28 TMA: However, if clojure were lazy (in the Haskell style), the arguments would not be evaluated, because they were not used (you'd need to resort to some monad trickery to force them to be evaluated; but then Haskell is pure, there are no monadfree sideeffects)

5:29 mungojelly: yeah that sounds like real laziness, if it's never used it just doesn't happen in the first place, the eventual use is always what triggers everything behind it

5:30 iwo: I think what I'm after is: (defmacro do-nil [& body] `(do ~@body nil)) :)

5:30 TEttinger: also I suspect it would make the already slow clojure AOT compile process even slower

5:31 iwo, yep

5:31 talios: TEttinger - frege seems quite snappy to compile :)

5:31 I've not done anything large in it yet tho

5:31 TEttinger: don't know it

5:31 lazybot takes about 2 minutes to uberjar the relatively large program

5:31 talios: haskell for the jvm :)

5:32 TEttinger: that sounds kinda awful... isn't one of the biggest advantages of haskell the guarantees they have by their own type system and ecosystem in general?

5:33 talios: and that type system carries across. the FFI to java is rather controlled, and lifts nulls into Maybe's, and wrapps impure things into ST

5:34 TEttinger - https://www.youtube.com/watch?v=9V7w-RSC_1A - from this weekends FregeDay mini conf

5:34 mjg: Could one, as an experiment, write a macro which wrapped every form in (delay...) to simulate haskellesque laziness?

5:37 TEttinger: mjg: it would also need to deref the values before they're used, but it seems possible

5:42 mjg: That's a pretty steep overhead, right? But if it were implemented as a new reference type which was automatically forced on-demand, then it seems pretty similar to what haskell is doing.

5:42 just as an alternative to compile-time analysis, not suggesting you actually do this.

6:01 cydork: talios: frege is coming along nicely..

6:03 talios: cydork - yep, seems to getting more and more interest. esp. now theres the maven plugin, the lein plugin, the gradle plugin, and some experimental stuff I'm toying with with hazel. Now we just need libraries to build an ecosystem

6:04 cydork: talios: yep. just saw some article about the benchmarks.. which were on par with ghc

6:05 talios: cydork - oh? got a link, I wonder if that in relation to the performance talk given at FregeDay

6:06 ( also next to that video I posted above )

6:06 cydork: talios: https://gist.github.com/vsts/57565f5b7d11df39541c

6:06 talios: could be interesting running some things thru JMH

6:06 cydork: talios: https://www.reddit.com/r/haskell/comments/3igird/frege_faster_than_haskell_ghc/

6:06 talios: ah yes that post.

6:31 seye: Hi. Am I correcting in thinking that it isn't possible to deref or ensure multiple refs at the exact same 'snapshot time'?

6:32 tomshacham: please could i have a nice example of a macro? something beyond "infix" that just allows (1 + 1)

6:33 sobel: seye: sounds like you might want to use a transaction

6:35 seye: this is within a transaction

6:36 gilliard: tomshacham: there's a lot of macros in clojure itself - look in core.clj

6:37 sobel: seye: you should be good. refs are connsistent inside transactions.

6:37 seye: are you familiar with the MVCC model?

6:37 seye: yes

6:38 sobel: that is the STM model for transactions

6:38 seye: i know :)

6:38 however

6:39 if i deref two refs within a transaction, it is possible for another transaction to commit between the two derefs, so the second ref may have a value different to the one that it had when i derefed the first one.

6:40 tomshacham: gilliard: thanks

6:40 sobel: your transaction shouldn't see that

6:42 are you concerned that the ref could be altered before your transaction ensures it?

6:50 seye: You are correct sobel, i'm relieved to say! I ran a test that made it look like it was failing, but it was actually retrying the transaction to keep if consistent and the output confused my slow brain!

6:51 sobel: whew!

6:54 seye: http://pastebin.com/6s5TuPNN

7:05 ane: I edited the Clojure wikipedia page a bit, can anyone check if the edits make sense? https://en.wikipedia.org/w/index.php?title=Clojure&type=revision&diff=681133095&oldid=680279119

8:43 chouser: ane: It's great to have all those citations. The word "force" might be a bit too strong since uncoordinated mutation is still available.

8:43 ane: perhaps "encourage" instead of "enforcing" and "forces"?

8:47 ane: yes!

8:48 i need to find citations for the second paragraph of the history section, but can't

8:48 i know he mentioned it in some video but i don't remember which one it was

9:03 dumbintel: Can someone explain atom's to me? Living Clojure's explanation is a bit abstract. Are they like pointers and refs like references?

9:04 chouser: atoms and refs and agents are all like pointers, but with semantics to control how they're updated

9:04 snowell: I found this answer to be helpful: http://stackoverflow.com/questions/9132346/clojure-differences-between-ref-var-agent-atom-with-examples

9:04 chouser: The semantics differ, which is why there are three different types.

9:05 snowell: Nice.

9:05 I would also recomment "The Joy of Clojure" ;-)

9:05 dumbintel: I think I get wrapped around state as a new idea. I'll start with that article.

9:07 mavbozo: chouser, will the 3rd edition contains core.async and transducers? :)

9:09 chouser: mavbozo: I suppose it should, shouldn't it.

9:09 noncom: dumbintel: atoms just store mutable state that is guaranteed to cause no concurrency issues on change, no order is guaranteed, they block thread until state change is successful. refs contain state and allow to change several refs in a particular order, providing all safety of atoms, they block too. agents are same as atoms but do not block, use for spin-off or long-term calculations

9:10 vars are used for programmatic entities, like functions, variables, not for data

9:11 dumbintel: i think it is safe to say that in over 90% of cases it is almost certain all your data can be handled with atoms.

9:14 mavbozo: heh, transducers.. let alone transducers, i'm still waiting for an example of a real world complexity UI built with core async.

9:16 dumbintel: Also, would you guys recommend a web front end or a swing front end for a game with chess-like elements meant to study A.I.

9:18 The interface would be static for the most part where dynamic elements are pieces, but even those are just simple images coming in and out of view.

9:40 noncom: wheres lazybot?

9:49 tmarble: I'm getting compilation errors (ClassAdapter.java) when building clojure from master... anyone seen this?

10:17 justin_smith: noncom: atoms do not block, they retry

10:17 noncom: they are a non-locking optimistic concurrency mechanism

10:17 noncom: refs also retry

10:17 noncom: agents lock rather than retry

10:18 noncom: justin_smith: hmmmmm, well, in my practice, if i swap an atom, the thread stops until the swapping is successful

10:18 justin_smith: noncom: this is important, because side effects inside swap!, or a mutable object inside an atom, can cause serious bugs because of retries

10:18 tolu: hi

10:18 justin_smith: noncom: that's because it blocks your thread until a retry succeeds

10:18 noncom: that is not the same as locking the atom

10:19 noncom: it blocks the caller, it does not lock the data

10:19 noncom: hmmmm... this is interesting, apparently there are subtleties for the terms

10:19 ah yes, blocks the caller, sure, but data is available. well, it blocks the calling thread.. that's what i meant..

10:19 tolu: hi

10:19 tmarble: maybe you're using an unstable branch?

10:20 tmarble: ah, master, quite probable

10:20 tolu: please I would like to add a value into a particular column of a vector without replacing the previous value. I did this (assoc [1 2 3 4] 1 8) ;;=> [1 8 3 4] but I want [1 8 2 3 4]

10:20 justin_smith: noncom: right, the important thing is to remember that it doesn't lock the data, it will retry, and that is why side effects inside a swap! call, or mutable objects inside an atom, will cause bugs

10:20 tmarble: noncom: I've even tried JDK 6 and the args used in the latest Hudson build http://build.clojure.org/job/clojure/lastBuild/console

10:21 the only difference is that I'm using maven 3 (could be a showstopper?)

10:21 tolu: I did this (assoc [1 2 3 4] 1 8 ) ;;=> [1 8 3 4] but I want [1 8 2 3 4]

10:21 justin_smith: tolu: vectors don't support that directly, you'll likely need to coerce to a sequence, do sequence ops, then create a vector again

10:21 or you can use something like a finger-tree that can do that directly

10:21 noncom: yeah, this i know. probably had to mention also, but the reply was getting big already. however, what i said, does not contradict what you're saying. what you're saying is an expansion of my saying, so i think, that will not break the space-time continuum this time :D and when he learns more, he'll also accomodate the wisdom you're mentioning! :)

10:22 tolu: simplest solution in one line would be something like (concat (take N col) [8] (drop N+1 col))

10:22 tolu: or fingertrees, yeah, they're cool

10:23 tolu: noncom: and justin_smith: thanks

10:23 justin_smith: ,(let [v [1 2 3 4]] (apply conj (subvec v 0 1) 8 (subvec v 1))) ; another way

10:23 noncom: ah, it should be (drop N col) i guess

10:23 clojurebot: [1 8 2 3 4]

10:23 noncom: subvec is faster on vectors, right?

10:23 justin_smith: I forgot about subvec!

10:23 yeah

10:23 *almost forgot

10:24 tolu: cool

10:24 mungojelly: whatever topic you ask about on freenode you get an answer that's too specific and too detailed and too picky and too particular, it's a great place to learn things :)

10:24 justin_smith: heh

10:25 mungojelly: it's because someone can come back and say "you said atoms locked and thanks to retries I bought 100 porsche's from amazon.com when I was only supposed to buy 1"

10:26 mungojelly: you have to answer with not only the current situation in mind, but others your answer will likely be extended to

10:26 noncom: tmarble: well, sometimes master branch of a repo can contain something that does not compile... although i did not look into clojure repo and can't say more

10:26 mungojelly: those are the beneficent reasons, and then there's that it gets boring explaining the same thing over and over so you look for more interesting perspectives on them :D

10:27 noncom: yeah :D

10:27 sounds like we can make a library for that

10:28 mungojelly: isn't there a doubly linked list around here you should ask for if you want cheap inserts. i don't know how to ask for it i just remember rich hickey or someone saying doubly-linked lists are something we get.

10:29 justin_smith: ,(defn vinsert [e index v] (apply conj (subvec v 0 index) e (subvec v index)))

10:29 clojurebot: #'sandbox/vinsert

10:29 justin_smith: ,(vinsert 8 1 [1 2 3 4])

10:29 clojurebot: [1 8 2 3 4]

10:29 justin_smith: sweet!

10:30 mungojelly: sounds like finger trees

10:30 mungojelly: ok fine i will google finger trees

10:30 justin_smith: that vinsert works, but is O(n) with the size of (count v) - index

10:31 where fingertrees are log or something

10:34 noncom: justin_smith: please remind me, you were saying it is possible to lay effects on sampled instruments in overtone... is that by re-routing the synth output through a fx and into the output

10:34 ?

10:34 justin_smith: yes

10:34 mungojelly: ok i think i sorta understand what a finger tree is now, but i'm not entirely grokking how that lets you make a persistent double-list

10:35 this overtone thing sounds fun maybe i should move that up my list of things to look at

10:35 noncom: cool, sounds as straight as any DAW, not sure why I was thinking too much about it

10:36 mungojelly: sure, it's pretty awesome actually

10:36 sobel: overtone is somewhat powerful but there are some areas you're totally on your own

10:37 justin_smith: noncom: in my experience it takes a while for all the routing and stuff to be intuitive, especially when you don't have a pretty antialiased rendered picture of the "wires" and "processing units" as if they were physical objects in a studio

10:37 noncom: and then there's a log of people who still have problems even with the logic of routing the physical objects...

10:37 but it's basically just plumbing

10:37 s/log/lot

10:38 noncom: true story - functional program first appealed to me because it follows the same cause and effect rules that audio processing gear does

10:39 noncom: that is, good code is only effected by its input, and you should be able to reason about what any subgraph does independently of the chain

10:39 noncom: yes, this is so true. actually, sound making in this way is functional programming in disguise!

10:40 mungojelly: i think we talk a lot about these things as pure ideal concepts but really they're more aesthetic

10:40 justin_smith: except for reverb - you have to cheat a little bit for things like reverb :P

10:41 mungojelly: like around here there's lots of talk about being functional, oh we should be functional, what do the functions do, they advance the state of The Thing, oh what's in the thing, a bunch of states sending messages to one another, objects. but at least you can rewind them when they fall over the same as usual. ;)

10:41 justin_smith: mungojelly: it's not just aesthetic - it's a set of rules for abstractions that compose well for the pragmatic reason that you want your code to be easy to think about

10:41 noncom: well, delay then too needs some cheating, but i think this can well be tied with functional programming

10:41 justin_smith: and it turns out that there is an aesthetics to things that follow that logic, sure

10:42 noncom: yeah, I mean really even filters have a phase (time) shift, but yeah, big picture it's functional or something very close to it

10:42 mungojelly: but what i mean is that things can so easily be put inside of one another in these systems, that you can only know the style of something by looking at the style of all of its details

10:43 noncom: yeah

10:43 justin_smith: mungojelly: ideally you shouldn't put state inside something funcitonal - it's OO where you hide the details on the inside

10:43 xtrntr: hi, trying to copy this code and make it work

10:43 http://programming-enchiladas.destructuring-bind.org/rm-hull/6857333

10:43 justin_smith: haha, funcitonal

10:44 xtrntr: i'm not sure how does the web server render the canvas

10:44 document-ready?

10:44 justin_smith: xtrntr: the server does not render anything

10:44 the browser renders the canvas

10:44 mungojelly: there's that old saying about how every system that's not lisp ends up having a poorly implemented poorly documented lisp in it, but also i think it goes the other way around, the pure functional programs all write imperativeness into themselves somewhere in order to do that.

10:44 xtrntr: justin_smith: ah

10:44 justin_smith: mungojelly: as long as it's real imperative and not OO, you're fine

10:45 xtrntr: xtrntr: sorry, i'm not very familiar with web programming, which function is the link between clojurescript and the browser?

10:45 noncom: xtrntr: clojurescript is translated into javascript and executed as a plain web page script

10:45 justin_smith: mungojelly: and it's more nuanced than that. Ideally functional code should not contain state, and stateful objects should be at the top level, connected to each other by functional plumbing

10:46 xtrntr: it must be document-ready right? i found it in the jquery docs

10:46 justin_smith: mungojelly: of course in order to compute anything at all, state is going on in registers and such, but the idea is that you can have an effectively stateless interface despite that

10:46 noncom: i find that in the real world, when you go through the levels of the system, it oscillates between OO and FP, morphing

10:46 xtrntr: now i have to link the js or cljs file in my index.html file?

10:46 noncom: xtrntr: iirc document-ready means that all page data was received by your broewser and it is ready to be rendered

10:47 justin_smith: xtrntr: the generated js should be linked, yes

10:47 xtrntr: the cljs compiler will arrange for your -main to be called when the page loads iirc

10:47 xtrntr: you might be able to get more detailed answers from #clojurescript

10:48 noncom: xtrntr: still, why did not you try luminus? :) it would already be clear to you if you've simply examined the code generated by the template

10:48 xtrntr: ah, sorry to bother you guys

10:48 i actually copied the code into luminus, but as a newbie everything seems very strange and unfamiliar

10:48 noncom: a game drawn on a canvas is little more than a simple page script

10:48 xtrntr: i'm ok with lisp syntax, but never did web programming

10:48 into a limunus created project*

10:48 noncom: web creeps me out a little too :)

10:49 so, then you could simply copy the scripts into the project and let them draw on a canvas that you create

10:50 xtrntr: ah

10:50 i'm not very sure what that means

10:50 so the scripts are located in my src directory, but how do they get loaded into the browser?

10:50 justin_smith: oh man I have so many layers right now - cljs in the browser, interacting with 3.js in the same browser (and sometimes those interactions are a bit odd) then clojure on the server, talking via kafka to another set of clojure servers running onyx to balance tasks, then other clojure servers doing REST style http queries...

10:50 xtrntr: i'm trying to understand how the pieces fit together

10:51 justin_smith: xtrntr: the clojurescript compiler takes your clojure code and turns it into js file(s)

10:51 noncom: justin_smith: wow

10:51 justin_smith: xtrntr: then that js file is loaded into an html page which is served to the client, and the client runs the js

10:51 noncom: xtrntr: also, if you're following luminus template, your source should be under src-cljs

10:51 justin_smith: noncom: yeah, it's kind of wacky

10:52 noncom: justin_smith: i wish i had a job like that...

10:52 justin_smith: noncom it's fun until the deadlines loom...

10:52 noncom: oh deadlines...

10:53 justin_smith: and also, when things break in a system that distributed, figuring out how it broke is like a game of clue

10:53 "It was a reagent component, in the browser, with the websocket!"

10:53 "no, it was the onyx task, in the amazon cloud, with the core.async channel!"

10:54 noncom: actually, that's pretty fascinating

10:54 then you start thinking if some greater structure can be imposed on things...

10:54 justin_smith: noncom: bugs that I would sort out in a minute or two locally can turn into a thirty minute sleuth job of resuscitating and replaying events from the kafka log...

10:55 noncom: sure, they get lost in the sea of changes

10:55 justin_smith: and of course I as the backend / infrastructure guy am trying to prove the frontend cljs code is broken, and the frontend folks are trying to prove my infrastructure fucked up...

10:55 xtrntr: justin_smith: should i include the document-ready in the same script where the -main function is called?

10:56 justin_smith: noncom: well, the cool thing is that with kafka all messages are stored for a while (and are fully readable as edn data in our usage) so we really can replay and recreate bugs

10:56 xtrntr: why do you need document-ready?

10:56 noncom: interesting

10:56 xtrntr: to draw the maze and stuff

10:56 justin_smith: noncom: kafka is like a hybrid of a logging system and a message queue

10:56 noncom: xtrntr: yeah, document-ready is used if you're programming very bare javascript...

10:57 xtrntr: if you look at core.cljs, provided to you by luminus, you will see, that it is far simpler

10:57 tmarble: noncom: had crufty *.java files in the tree! Now builds with JDK 6 + mvn2 and JDK 8 + mvn3

10:58 justin_smith: well, that maze example is using document-ready so maybe it has something to do with that design...

10:58 dm3: is there a way to edit and eval source of project's dependencies in Emacs with CIDER? I found how to navigate to a read-only buffer with cider-find-ns...

10:58 xtrntr: do you mean core.clj?

10:58 sorry, i'm trying to learn by copying and pasting

10:59 i'll work backwards from a working example

10:59 noncom: xtrntr: if you're so unfamiliar with web, why don't start small? there's really tonns of web-specific stull to know when coming from non-web world...

10:59 justin_smith: xtrntr: for starters, make sure you have a project that is set up to run the clojurescript compiler

10:59 xtrntr: i thought copying and pasting is the lowest rung there is?

10:59 justin_smith: xtrntr: as dnolen mentioned in #clojurescript, you should probably start with some of the basic clojurescript docs

11:00 noncom: xtrntr: maybe you should try first creating a simple web page and get it rendered, then add some cljs to breathe some life into it. there are innumerable example out there, under 100 loc

11:00 justin_smith: xtrntr: copying and pasting won't help if you aren't even running the right compiler

11:01 xtrntr: you mean the options in my project.clj when you say compiler?

11:01 alright i'll read some stuff before i get back here

11:01 dnolen: xtrntr: working backwards is a huge waste of time IMO. Just read the Quick Start and get the fundamentals down first.

11:01 justin_smith: (inc dnolen)

11:09 xtrntr: i get this error when i try to compile

11:09 Caused by: java.io.FileNotFoundException: Could not locate monet/canvas__init.class or monet/canvas.clj on classpath.

11:09 but i've included the monet dependency in project.clj

11:10 and the example on the github page uses it no problem

11:10 https://github.com/rm-hull/monet

11:20 oddcully: xtrntr: monet is cljs - the error looks like one from clj?

11:21 xtrntr: ahhh

11:21 sorry that was it

11:21 i was using cljs code in a clj file ...

11:21 ._.

11:21 i hope i'm not the first one to make such a mistake

11:22 justin_smith: xtrntr: I think if you slow down and look at some of the basic cljs docs this stuff will be much easier

11:22 xtrntr: okay :)

11:31 mungojelly: yes everything stateful is all bunched up nicely on to a top coordination layer and everything's beautiful-- which is just what makes that stateful layer so effective as a library for the next thing to build on and we're off to the races again :/

11:57 joefromct: if i def a variable in a repl session in a function, can i delete it and try again?

11:57 justin_smith: joefromct: you can just use def again

11:57 joefromct: basically i have a function that tests if a varibale is nil, and if not it def's it

11:57 i'm sure there is a more functional way to do this

11:57 sobel: defonce

11:58 slightly different but may be what you intend

11:58 lodin_: joefromct: Why do you want to do that?

11:58 joefromct: sobel: ah, thanks. I'll look into it.

11:58 well, i can't define a spark context into sc twice

11:58 justin_smith: yeah, use defonce for that

11:58 joefromct: a spark context is i guess the session on a cluster, and i'm testing my program "bootstrapping" i guess

11:59 ok thank you

11:59 justin_smith: joefromct: well, either defonce, or don't put it in a def at all, and use a proper system building lib like stuartsierra/component

12:00 joefromct: justin_smith: yeah, baby steps, but i'll put that on the research/to-do list.

12:00 not sure i totally understand what a system building lib is at the moment.

12:00 sobel: it's so easy to try out libs with clojure. i don't even hesitate if i get a good recommendation here.

12:01 justin_smith: joefromct: the idea is that if you have stateful resources, instead of defining them at compilation time as defs, you can initialize them in a system startup procedure, then pass them to the code that needs to use them via the same startup

12:01 joefromct: justin_smith: simple enough, and makes perfect sense. thanks i'll look into it.

12:01 justin_smith: sounds like something a scheme person would love.

12:02 or i guess any lisper

12:02 justin_smith: joefromct: among other advantages, you would avoid the problem where if you try to make an uberjar, your top level spark connection will run while compiling the code (which might not be something you want)

12:02 joefromct: pretty much :)

12:03 joefromct: so, i just yanked the text from this irc chat into org-capture and put component as an org-task based on justin_smith's recommendation.

12:04 emacs is amazing. i don't need a computer anymore just an emacs machine.

12:04 and cider.

12:04 justin_smith: heh

12:24 mungojelly: i just learned defonce yesterday, i'd seen it a few times in the days before that, and i misread it as de-fonce, i was wondering what foncing was and how it removed it, i noticed it was coded defensively so i thought maybe it was a pun on defence

12:25 ane: lol

12:27 joefromct: does anyone have any experience with flambo vs sparkling? What the trade offs are between them?

12:29 sdegutis: Is it common to get the initialized fields of a defrecord all map-like using their keyworded names?

12:30 Like, (:bar (Foo. "this is the bar field"))

12:39 mavbozo: sdegutis, it's common in my usage

12:39 sdegutis: Thanks. Anyone else can add to this?

12:45 eLobato: hi there channel. I was wondering if there are any best practices on how to use clojure.test to test read/write to a file? I'm trying to find some expectations/mock framework but I didn't find anything conclusive, help?

12:54 lodin_: sdegutis: Yes, it is common. But if you use a record you probably have a reason, and you might consider providing a functional API for it via protocols, including stuff that happens to be stored directly in the record. That makes you free to adjust the implementation accordingly, and extend other data that is equivalent in content but not in structure to the protocol.

12:55 sdegutis: lodin_: in this case I'm using defrecord to switch between a live implementation and an in-memory implementation for when running tests

12:56 lodin_: they both conform to an abstract defprotocol which my code uses as if it were the thing itself

12:57 lodin_: sdegutis: Then for "private" code that knows it is working on a particular record, then I think it's perfectly fine.

12:57 sdegutis: Okay that makes sense.

12:57 Since not every record will have that same key.

12:58 lodin_: Right.

12:58 sdegutis: If I want to make it public, I should make a getter for it.. like (uri [this] uri)

12:58 As ugly as it is, that's the right way.

12:58 lodin_: sdegutis: I believe so. Others might disagree.

12:59 sdegutis: In practice I often only access record fields in protocols implementations, and then I don't need to use keyword access. To update the record I of course use keywords with assoc etc.

13:00 Inside the protocol implementations, that is.

13:00 sdegutis: Thanks.

13:01 lodin_: sdegutis: It great that Clojure lets you start with a map and then transition to a record. That way you don't have to model everything up front, as long as you realize that your old code only works with your "first" record that you then created a protocol for.

13:05 sdegutis: :)

13:10 mavbozo: speaking of defrecord, I just read defrecord docstring again and stumbled on few paragraphs. But currently I am interested in this paragraph: "Two constructors will be defined, one taking the designated fields followed by a metadata map (nil for none) and an extension field map (nil for none), and one taking only the fields (using nil for meta and extension fields). Note that the field names __meta and __extmap are currently reserved and should not be us

13:10 ed when defining your own records."

13:11 what is the example of 1 constructor that is "taking the designated fields followed by a metadata map" ?

13:14 justin_smith: mavbozo: (->Foo 1 2)

13:14 mavbozo: what confuses me again is the next paragraph that describe the factory functions ->TypeName and map->TypeName

13:14 justin_smith: mavbozo: that's what that is describing

13:15 ->TypeName is the one that takes the designated fields

13:15 mavbozo: justin_smith, so the "constructor" and "factory function" terms refer to the same thing?

13:16 justin_smith: afaik yes

13:16 well, the constructor is the one that refers to it as a class directly, I thought

13:17 lodin_: justin_smith: What about the metadata map?

13:17 justin_smith: (TypeName. x y)

13:17 lodin_: not sure about that part, is it an optional arg?

13:18 mavbozo: trying (Foo. 1 2 ^{:name :foo}) in the repl throws Unmatched delimiter RuntimeException

13:19 justin_smith: what about without ^

13:19 mavbozo: no matching ctor found for class user.Foo

13:19 IllegalArgumentException

13:22 rhg135: ,(do (defrecord Foo []) (Foo. {} nil))

13:22 clojurebot: #sandbox.Foo{}

13:23 rhg135: ,(do (defrecord Foo []) (meta (Foo. {:i-has-meta true} nil)))

13:23 clojurebot: {:i-has-meta true}

13:26 rhg135: also takes an extmap, which can be nil

13:27 lodin_: What's in the extmap?

13:28 Bronsa: the extra fields you assoc to a record that weren't declared

13:28 ,(defrecord x [a])

13:28 clojurebot: sandbox.x

13:28 Bronsa: ,(.__extmap (map->x {:a 1 :b 2 :c 3}))

13:28 clojurebot: {:b 2, :c 3}

13:29 rhg135: yup, they are usually hidden

13:30 lodin_: Ah. So map->x looks up what's a field and what's not and effectively splits the map?

13:31 rhg135: theoretically

13:31 idk the implementation

13:32 Bronsa: yes

13:32 it actually dissocs the known fields from the map

13:33 mavbozo: ah, so i misunderstood the paragraph. my first try should be (Foo. 1 2 {:name :foo} nil) ;; remove the caret ^ and add nil

13:34 rhg135: yup

13:34 mavbozo: rhg135, Bronsa thank you

13:34 Bronsa: yeah you basically get Record(declared-args*) and Record(declared-args*, meta, extmap)

13:36 phaseNi: Hello, how do I access member classes from a java class?

13:36 rhg135: Parent$Child

13:37 phaseNi: I must be doing something super wrong, because that isn't working

13:37 (new Parent$Child) should work, correct?

13:37 lodin_: I guess this is here just for the implementation, and that assoc etc make use of it? In user code you can just do (-> (->Foo ...) (with-meta metamap) (into extmap)), right?

13:38 Bronsa: lodin_: yes

13:38 phaseNi: is Parent a fully qualified classname?

13:39 rhg135: java.util.Map$Entry

13:39 ,java.util.Map$Entry

13:39 clojurebot: java.util.Map$Entry

13:39 phaseNi: Bronsa: BAM! Thanks :)

13:40 Bronsa: phaseNi: importing foo.Bar doesn't import foo.Bar$Baz

13:40 if you want to write Bar$Baz instead of foo.Bar$Baz you'll have to import it

13:41 rhg135: they're essentally different classes alltogether

13:42 phaseNi: Yeah I figured

13:42 rhg135: for naming

13:42 phaseNi: It was $ that I was really missing all this time

13:43 thank you rhg135 and Bronsa

13:43 rhg135: is there better docs for this now

13:44 I recall tripping on this

13:44 phaseNi: Actually I found nothing of help

13:45 rhg135: what a bummer

13:45 phaseNi: The interop doc doesn't even mention import

13:45 rhg135: I know

13:46 I gess you could read the code

13:46 phaseNi: :P

13:46 now to figure out proxy...

13:47 rhg135: it's not bad

13:47 Bronsa: phaseNi: if you don't need to extend a concrete class you'd rather be using reify than proxy

13:47 rhg135: ^!!!

13:48 phaseNi: ohhh

13:48 clojurebot: Titim gan éirí ort.

13:48 phaseNi: nifty

13:48 thanks

13:48 mavbozo: rhg135, clojure-doc.org mentioned it http://clojure-doc.org/articles/language/interop.html#imports

13:48 Bronsa: it has better syntax and better performances

13:49 mavbozo: kudos to clojure-doc.org contributors

13:49 phaseNi: Yeah, I was reading http://clojure.org/java_interop

13:49 it is indeed in the other doc

13:49 rhg135: ,(reify Object (toString [_] "a"))

13:49 clojurebot: #object[sandbox$eval25$reify__26 0x116ce57d "a"]

13:51 rhg135: won't anyone think of the performance

13:53 I've seen proxy too often in the wild

13:53 Bronsa: really?

13:54 rhg135: ppl new to clojure

13:56 mungojelly: *earmuffs* means you might change the value of something?

13:56 rhg135: yes, usually dynamic

14:01 justin_smith: mungojelly: specifically that a var can be dynamic in scope

14:03 rhg135: it's just a convention though, right

14:03 mungojelly: yes what i'm reading is a style guide, it wouldn't have to tell you you had to if you had to

14:04 should i really say io! around i/o

14:04 justin_smith: mungojelly: if it would be erroneous to send the same io repeatedly

14:04 or to read more than once for one input

14:04 mungojelly: that makes sense and yet i don't think i've read "io!" in any code yet? maybe i wasn't looking for it yet

14:05 rhg135: but if you don't ppl will be very dissapointed in you to say the least

14:06 not use *stuff*

14:07 mungojelly: i'm glad clojure uses earmuffs for something they're pretty

14:09 rhg135: clojure is aesthetically pleasing

14:10 fantazo: clojure is a lisp. so it must be aesthetically not pleasing. this is the unwritten rule of bullshittery, it must be true!

14:10 justin_smith: fantazo: also, parenthesis cause cancer

14:11 fantazo: justin_smith, and small penises too.

14:11 rhg135: along with c++ is da best

14:12 mungojelly: clojure takes away all those ugly parentheses and instead you get some pretty -> and ->> and way too much knowledge of which things take arguments in which places

14:13 i've heard a lot of "but sequence arguments should go at the end! then it's great!" which is clearly just blaming the victim :p

14:13 rhg135: wrap it all in maps!

14:13 justin_smith: mungojelly: the arg placement order is predictable for sequential and associative args (sadly it is not consistent with string/regex)

14:15 rhg135: knowing the api is nice

14:16 makes you more productive in any language

14:20 nooga: ah, that's why I wanted flip-args function

14:20 mungojelly: ok so i was trying to decide between {:grid {[0 0] :a} :tiles {:a {:quality "value"}}} or just {[0 0] {:name :a :quality "value"}} that is whether to put a level of indirection, i guess i'm leaning towards the latter, maybe "make this tile a copy of this other one" would be a better efficiency hack anyway if it needs that

14:21 i think -<><:p seems useful! it seems to be like a joke, but i think that's because you don't realize all the stuff you're used to is just as weird :p

14:25 rhg135: premature optimization

14:36 mungojelly: well i also thought it might be a premature optimization to bother to reduce the datatype to a finished model like that, maybe it should just be a sinkhole of tile insertions

14:37 then i wouldn't have to check anything when you insert tiles or add grids or anything, just i'd have to sort through the updates for the latest news

14:41 rhg135: indirection usually adds power, but lowers performance

14:41 mungojelly: is there a better way to say (filter #(= (first %) [0 0]) coll)?

14:54 so which data structure do i want if i just want to toss a bunch of things shaped like {:xy-grid-pos [0 0] :tile-name "happy tile" :hex-color-string "#00FF00" :time-inserted 987298472938749} into it and then later i want to ask for all the ones where :xy-grid-pos is [0 0]

14:56 rhg135: I'd use a pair of a stack and a lookup table

14:57 But I'm not that experienced

14:57 mungojelly: is a stack something we get here that works differently than a vector?

14:58 rhg135: you can use a vector

14:58 ,(pop [1])

14:58 clojurebot: []

15:00 rhg135: ,( [] (conj 1) (pop) (conj 2 3) (peek))

15:00 clojurebot: #error {\n :cause "Wrong number of args (0) passed to: core/pop"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (0) passed to: core/pop"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 28]\n [sandbox$eval49 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval49 invo...

15:00 rhg135: ,(-> [] (conj 1) (pop) (conj 2 3) (peek))

15:00 clojurebot: 3

15:00 mungojelly: ok yay now i know (peek)

15:01 how many words do you think you need to learn to speak clojure

15:01 rhg135: alor works with lists

15:01 mungojelly: i'm guessing a few thousand

15:01 rhg135: ~100ish maybe

15:01 clojurebot: Huh?

15:02 rhg135: imo

15:02 mungojelly: there's something reasonable like that in the core, but then you have to know some libraries to understand the idiom around here, you need to know java even to understand lots of things

15:03 but we live in a world where java is mandatory, so i do know enough of that bull to get by

15:06 rhg135: do you mean words as in english?

15:06 mungojelly: i just mean as in like the human capacity for language

15:06 rhg135: ah

15:06 a lot

15:07 mungojelly: sometimes if there's multiple arities of something it only counts as one word because you can understand the pattern and it's not an extra burden, but sometimes it's two ideas and you learn them separately

15:08 rhg135: ideas, more than you should

15:15 sobel: i would not be too hasty in comparing programming languages to spoken languages

15:16 mungojelly: well i have a unique perspective on it as one of the only fluent speakers of lojban, which is the only language in a vast otherwise empty space between

15:16 sobel: no you don't

15:17 i know several long-time lojban speakers and one of theme is a PhD-EE and we've kinda gone there about languages

15:17 mungojelly: programming languages aren't really computer lanugages they're human languages for talking about computation, so like in terms of number of symbols for instance they're closer to our preferences than a computers

15:17 sobel: i'm open to new ideas but fairly skeptical that there are any in this topic

15:18 i disagree strongly with your characterization that they are not really computer languages

15:18 mungojelly: there's a general shortage of new ideas on every topic, for a few more years, i'm sure we'll feel very nostalgic about it

15:18 sobel: they do not talk about computation, they represent computation in somewhat human-readable symbols, but the orientation is computing not human communication. that's a fundamental divergence.

15:19 mungojelly: for instance if you say the same thing in clojure we can write various compilers to express that idea in various concrete forms to various virtual machines

15:20 sobel: gotta go

15:20 mungojelly: but the essential thing is its meaning to us, the computation we think it represents, if it turns out it doesn't do what we think it should in an edge case we'll "fix" what the computer understands from it whenever that's practical

15:24 oh ok i was confused, i don't have to choose which data structure i'm talking about, i can write to the sequence interface or the collection interface or whatever and it works with a variety of data structures from clients

16:00 lodin_: justin_smith: Regarding your question about using lenses in Clojure. I just wrote a piece of code where a lens would've been sweet.

16:06 rhg135: what's the recommended way to store state in clojure? (atom huge-structure), {:part-a (ref substructure)}, or else?

16:07 the first is convenient but it limits concurrency, the second is I'm not sure

16:32 mungojelly: ,(defn latest-tile [grid x y] (->> grid (filter #(and (= (:x %) x) (= (:y %) y))) (sort-by :time) (last)))

16:32 clojurebot: #'sandbox/latest-tile

16:32 mungojelly: i feel like i'm saying it wrong when i say "#(and (=" is that wrong?

16:33 lodin_: mungojelly: What would be wrong with it?

16:34 mungojelly: lodin_: i feel like there should be one word that means "filter for where these keys are that"

16:38 lodin_: mungojelly: Write your own contains-map?. :-)

16:38 ,(defn contains-map [a b] (= (select-keys a (keys b)) b))

16:38 clojurebot: #'sandbox/contains-map

16:39 lodin_: ,(defn contains-map? [a b] (= (select-keys a (keys b)) b))

16:39 clojurebot: #'sandbox/contains-map?

16:39 lodin_: Now, #(contains-map? % {:x x :y y}).

16:40 mungojelly: lodin_: i'm just trying to be idiomatic, it's polite and also there are many sensible pretty idioms around here :)

16:41 thanks for the example of select-keys that's just what i've been playing with now

16:43 lodin_: Could use clojure.set/superset? as well.

16:43 * lodin_ things using clojure.set would be prettier if the arguments was cast to sets automatically.

16:43 lodin_: *thinks, *were

16:44 dbasch: mungojelly: it sounds like you have the wrong data structure for what you’re trying to do, if you have to do a linear scan and then a sort to find the latest tile

16:45 mungojelly: dbasch: sure well "wrong" as in imperfect, what would you use?

16:45 dbasch: mungojelly: if you’re doing lookups based on coordinates, a map of maps

16:48 mungojelly: the point being, if you’re doing this all the time for a large number of things why not have constant-time access to your items

16:51 mungojelly: dbasch: map of maps like {0 {0 {:color "#00ff00"} 1 {:color "#009900"}} 1 {0 {:color "#009933"} 1 {:color "#00ff33"}}}?

16:52 dbasch: mungojelly: yes, where you have constant-time access to color (x, y) instead of having to search

16:53 mungojelly: but then i want it to be like {0 {0 #{{:color "#00ff00" :time 9837487} {:color "#009900" :time 873874}}}} hmm

16:53 lodin_: I have a bunch of delays that can take quite some time to realize. I want to print all realized delays and for that I can use realized? but I also want to wait for those that have been triggered. How would I do that best? (I do not want to trigger any delays unnecessarily.)

16:55 mungojelly: the question is whether the constant time access is worth breaking it up so it's unreadable. but i guess with a tiling system the number of tiles the user wants is, more tiles, mooooooooooooore. so i shouldn't be intentionally slow.

16:59 i don't know the answer to your question but thanks for teaching me "realized?" that's awesome

17:01 rhg135: ,(into {} (map (comp (juxt :name :doc) meta)) (ns-publics (the-ns 'clojure.core)))

17:01 clojurebot: {nil nil}

17:01 rhg135: meh!

17:01 dbasch: mungojelly: you may want the set to be a sequence ordered by time, unless you’re going to be mostly checking for contains?

17:02 rhg135: ,(into {} (map (comp (juxt :name :doc) meta)) (vals (ns-publics (the-ns 'clojure.core))))

17:02 clojurebot: {primitives-classnames nil, +' "Returns the sum of nums. (+) returns 0. Supports arbitrary precision.\n See also: +", decimal? "Returns true if n is a BigDecimal", restart-agent "When an agent is failed, changes the agent state to new-state and\n then un-fails the agent so that sends are allowed again. If\n a :clear-actions true option is given, any actions queued on the\n agent that were bei...

17:03 mungojelly: dbasch: i'm not trying to tune it to be performant in any way, it's mostly supposed to be easy to handle, the use case i'm targeting is the beginner who's about to write (* cell-size x) for the zillionth time, my toy gives you the tiles so you can play on top of the tiles

17:03 rhg135: it helped to read it thouroughly for me

17:12 lodin_: I guess I want future-done? except delay-done?.

17:12 hiredman: delays don't do that

17:13 a delay only runs when it is forced, and forcing a delay blocks until it is done

17:13 lodin_: hiredman: Hence the problem. :-)

17:13 hiredman: a future and future-done? is exactly what you want

17:13 lodin_: hiredman: future runs it, even if no one wants it.

17:13 hiredman: so you should be using futures and not delays

17:14 lodin_: Nope. I don't want to run anything until requested.

17:14 hiredman: 05:13 < lodin_> hiredman: future runs it, even if no one wants it.

17:14 oh, I misread that

17:15 lodin_: So the point of delay is precisely to only run what is requested, and cache the result.

17:15 ZimaBlue: future inside a function? "start working in another thread but only when someone asks you to". If multiple derefs possible, make the future memoize?

17:15 hiredman: lodin_: my take on this is, your situation is extremely unlikely to be unique, so if the functionality doesn't seem to match up with what you are doing, everyone else is solving it a different a way

17:16 lodin_: ZimaBlue: I don't follow.

17:17 hiredman: ZimaBlue: you could put a future in a delay

17:17 lodin_: But how would I query the future inside the delay ...?

17:17 hiredman: deref the delay

17:17 ZimaBlue: disclaimer I'm new to clojure and haven't been here for the whole conversation, but it sounds like you want to have the behaviour of "run in another thread and don't block, but only when someone specifically asks you to"

17:17 and I thought a future inside a function would do that

17:18 maybe it's inside a delay =/

17:18 lodin_: hiredman: Oh, you mean that I do two derefs.

17:18 hiredman: well you do a single deref to get the future, and then you can check to see if the future is done

17:18 lodin_: The delay creates the future and returns it. Then I deref again. If I want to query I deref the delay, and query the future.

17:18 That works.

17:52 phorse: Does anyone have experience converting large sql tables into excel docs? I'm using docjure and on a table with ~150,000 rows it hits the GC threshold and chokes.

17:58 noncom|2: phorse: maybe you can first dump it into csv with korma?

17:59 justin_smith: hi, are you here?

17:59 phorse: if even korma will choke, then maybe do it in chunks, like, by the id or sorts

18:02 phorse: I'm using yesql at the moment - does korma have csv conversion built in?

18:04 justin_smith: noncom|2: hello

18:04 noncom|2: phorse: i doubt it has csv built-in, but wo knows

18:05 phorse: Ok, so csv is basically a long string, as opposed to writing a long xml file.

18:05 noncom|2: justin_smith: hi! have you worked with secretary + reagent.session ?

18:05 phorse: Theoretically then, I don't need to hold the whole thing in memory at once, right?

18:05 noncom|2: phorse: yes

18:06 justin_smith: noncom|2: I used secretary but ended up replacing it with a home-brewed router

18:06 noncom|2: I don't think I have used reagent.session

18:06 phorse: Thanks, I'll play with that for a bit and see what I can see.

18:06 justin_smith: even xml can be streamed, if you try hard and believe in yourself, it's just trickier

18:07 noncom|2: justin_smith: alright, then another little question, do you have an idea, in a single-page app, if i have a subpage to view an entity and i want to let user view several entities, i suppose i should let him open several pages or will it go against single-page?

18:07 if, of course, this question makes any sense to you :)

18:08 justin_smith: noncom|2: I would make that "page" just be a component that can be sucked into a [:div] for reagent in a for loop

18:08 or are you thinking multiple tabs

18:08 noncom|2: well, the for loop will make a list and multiple tabs just require to render them to tab components, right?

18:09 justin_smith: right, generate a tab in each iteration of the for comprehension

18:09 noncom|2: very cool

18:11 thank you :)

18:19 lodin_: hiredman: I just found out that realized? block on delays if realization has begun, which makes sense I guess. I don't actually want that behavior, so the future in delay solution works well.

18:24 justin_smith: Did you see my lens comment above? I rewrote it to use megakorre/glasses (even though glasses is a snapshot release), and it was indeed pretty.

18:25 justin_smith: lodin_: no, I missed that

18:26 lodin_: justin_smith: You asked me the other day if I thought lenses were useful in Clojure, and just a moment ago I wrote some code that would benefit from a lens.

18:28 noncom|2: lenses are cool when you can put them into use

18:50 pseudonymous: Is there a way to disable leiningen's auto-update mania ? I would've thought that once all plugins were stored in ~/.m2 it wouldn't try to re-download everything

18:50 justin_smith: pseudonymous: are you using snapshots?

18:51 nothing that isn't a snapshot should be changing versions on you without your help

18:52 pseudonymous: Nope. I'm not. I've tried to package the entire program up into a docker container where 'lein deps' was run prior - so the deps do reside inside the container itself.

18:53 justin_smith: could it be a profile difference looked for different deps?

18:56 pseudonymous: justin_smith: shouldn't think so, until recently I only had a single profile (:dev) -- I'm in the *very* early stages of packaging this thing up

18:57 justin_smith: are you using a plugin like lein-ring that adds dependencies?

19:00 pseudonymous: justin_smith: Yup, I am, 3 plugins of which lein-ring is one of them. But lein-ring etc are fetched when I build the docker container (at which point I run 'lein deps' inside it)

19:03 Interestingly it does add a few additional things, but nowhere the number which it tells me it's fetching (of which quite a few were libraries I've seen it download during the container build process)

19:19 justin_smith: do you perchance have a lein project.clj which has a production and a dev profile which you use ? I think I must be mkaing a mistake somewhere (launching with 'lein with-profile prod ring server' - yet dev-only dependencies are fetched)

19:22 justin_smith: pseudonymous: the reaosn I ask is that lein-ring has different deps duiring jar creation

19:26 pseudonymous: justin_smith: I'm admittedly a bit lost there - I was naively hoping that by using lein I could be blissfully unaware of anything related to jars (very much why I'm not attempting the überjar method)

19:32 justin_smith: pseudonymous: lein-ring introduces deps, so if you do a different task with lein-ring it might just pull in different deps (other plugins do this too)

19:33 pseudonymous: the reason to do uberjar is that way you don't have to worry about whether lein goes and looks for more deps at runtime - because at runtime there is no lein, just the jvm and your uberjar, the deps are already there

19:34 pseudonymous: justin_smith: just another point of variation I would've loved to avoid. 2x because I've been in jar-hell many a times in years back when dealing with Java. Jars to me are like RPM dependency hell of the mid-nineties ^^

19:35 justin_smith: pseudonymous: you are using the jvm, there will be jars. Uberjar creation is more predictable than using lein in production is.

19:35 pseudonymous: But OK, I guess I'll need to take a deep breath, and figure out how in the world I can accomplish an überjar. I'm definitely too sleepy for that right now.

19:35 justin_smith: pseudonymous: "lein uberjar"

19:35 that's it

19:36 then java -jar your.uber.jar

19:36 pseudonymous: Well.. there must be a reason for the lein-ring plugin, right ? In the absence of that, I'll need to setup an entrypoint of some sort

19:36 justin_smith: lein ring uberjar

19:36 amalloy: lein ring fabricates an entry point for you

19:37 justin_smith: or lein ring uberwar if you want to run in a container

19:37 pseudonymous: Oh god, more JVM lingo. The beast rears its head

19:38 I'll give it a whirl tomorrow :) I'm thankful for the suggestions (and patience!)

19:38 amalloy: ~justin_smith is an agent of the beast

19:38 clojurebot: You don't have to tell me twice.

19:38 sobel: oh noes, jvm lingo

19:39 i gotta say, kudos to whomever decided it wise to overload the basic zip file for the jar spec

19:39 and basically knock off the tar cli

19:40 for all the gripes people have had creating and managing jars, they have no clue what hell they've been saved from by jars

19:42 justin_smith: ~justin_smith

19:42 clojurebot: justin_smith is sitting on a throne of flies.

19:42 justin_smith: haha

19:43 pseudonymous: sobel: you might say that, but 80% of my time programming servlet, JSP and whatever else we were dragged through during university was actually spent feeding the beast various jar files and seeing version differences among our group crash whatever example app of the week we were toiling away at. It's by far the least pleasurable environment I've ever come across (npm, pip, gem etc comes to mind)

19:53 justin_smith: pseudonymous: yeah, putting multiple people's projects into one runtime and expecting deps to be a sane thing is probably futile. But if it's a single project with lein managing things, in my experience that can work out pretty well.

19:54 pseudonymous: justin_smith: Seems do-able. The Luminus project's extensive documentation make it seem pretty easy (They really nailed it documentation-wise, superb job!)

20:06 creese: Has anyone got instrumentation working with New Relic?

20:51 kavkaz: What's up everyone

20:54 justin_smith: fixin some distributed systems

20:57 kavkaz: Just going to continue on my project now. Trying to find the right music for me to listen to... I've been kind of down and it's hard to find the music that's gonna fit me right

20:59 I may have found it (:

Logging service provided by n01se.net