#clojure log - May 29 2013

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

0:48 muhoo: life is but a dream, shebang, shebang

0:56 technomancy: leiningen 2.2.0 is out; will do a proper announcement tomorrow

0:56 Ember-: cool man!

0:57 supersym: sweet

0:58 sinistersnare: technomancy: is there a changelog? sounds fun

0:59 technomancy: sinistersnare: sure: https://github.com/technomancy/leiningen/blob/e4b66b2b/NEWS.md

0:59 sinistersnare: technomancy: thanks! cool stuff

1:04 amalloy: technomancy: does the first bullet point there mean i can now disable the ten-page essay that gets printed when i do `lein repl`?

1:05 technomancy: amalloy: yeah! :repl-options {:welcome (prn)} or something

1:05 amalloy: that's going straight into ~/.lein/profiles.clj

1:06 technomancy: it's only 5 lines now at least =)

1:06 will be even shorter once https://github.com/trptcolin/reply/issues/114 is fixed

1:06 amalloy: because of the last bullet point?

1:06 technomancy: ayup

1:06 which also means apache httpclient won't be screwing up your dependency trees any more

1:06 tomjack: :repl-options {:welcome (print-essay! (find-printer :amalloy) {:pages 10})}

1:07 lucky for you I only run `lein repl` like once a day

1:07 technomancy: tomjack: next version we'll have lazybot integration so you can $mail amalloy every time your repl starts

1:07 amalloy: i think i'll finally be making the move from slime/swank to nrepl soon

1:07 technomancy: someone's working on the inspector, which warms my heart of stone

1:08 amalloy: i worked on four ritz/nrepl issues today, hoping to get rid of the behaviors that, compared to swank, are awful

1:08 don't much care about the inspector, personally

1:09 technomancy: the refusal to honor the namespace declared in the buffer until you force an explicit compile was really horrible

1:09 thankfully it appears to begone

1:10 amalloy: technomancy: i don't know what that is. what i've noticed is kinda the opposite: i can't C-c C-k a file until i've used C-c M-n to switch into its namespace

1:11 technomancy: hm; haven't seen that myself

1:11 holo: hi

1:11 nkhodyunya: Will it be good time investment to read metaobject protocols and let over lambda or any other kind of lisp book in order to make myself better clojure user? It's a question couse i'm very slow on technical reading, e.g. learning clojure with clojure programming book took me around 6 month (after working through SICP for 1 year) and i have long "read later"" list.

1:11 amalloy: conceivably could be a ritz issue, rather than nrepl itself

1:12 nkhodyunya: those are the two books i'd recommend. if you've already read them, you should be in excellent shape

1:12 more reading is never bad, but it's hardly critical

1:13 holo: nkhodyunya hey, i'm going to read SICP too when i have the time

1:15 are let forms still idiomatic if used in middle of a defn, e.g.?

1:16 amalloy: absolutely, holo

1:17 the only place they're not very common is inside of some other operation, like (+ 10 (let [x 2] (* x x)))

1:17 even there they're not *wrong*, you just need to make sure it's more readable than the alternative

1:20 holo: (inc amalloy) ; thanks!

1:20 lazybot: ⇒ 57

1:20 tomjack: huh, clojure-complete eh

1:43 sinistersnare: (inc amalloy)

1:43 lazybot: ⇒ 58

1:43 sinistersnare: what?

1:43 clojurebot: What is 2d6

1:43 sinistersnare: (help)

1:44 (println `swag)

1:44 (println "swag")

1:44 ")

1:44 :(

1:45 holo: ,(println "swag")

1:45 clojurebot: swag\n

1:46 sinistersnare: wat

1:47 ,(println "wat")

1:47 clojurebot: wat\n

1:47 sinistersnare: whats up with the ','

1:47 metellus: (because sometimes people want to say parentheticals)

1:47 sinistersnare: metellus: so how do you use the lazybot?

1:47 i can do

1:48 (inc amalloy)

1:48 lazybot: ⇒ 59

1:48 sinistersnare: and that works

1:48 but when i want to print something i need a ','?

1:48 n_b: &(prn "Like this") I think

1:48 lazybot: ⇒ "Like this" nil

1:48 metellus: or inline ##(print "like this")

1:48 lazybot: ⇒ like thisnil

1:48 sinistersnare: are those clojure symbols? or something specific to lazybot?

1:48 metellus: inc is a special case

1:49 they're all specific to the bot

1:49 just triggers to tell the bots "somebody wants you to evaluate some code here"

1:49 n_b: well, #(stuff) is an anonymous function, I had thought lazybot's trigger was #, but I'm not sure if it actually works if you do e.g. ##((#(inc %) 1))

1:49 lazybot: java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn

1:51 metellus: too many parens? ##(#(inc %) 1)

1:51 lazybot: ⇒ 2

1:51 n_b: yup

1:52 paredit has forever spoiled me in matching parens

1:55 sinistersnare: :\

1:56 amalloy: n_b: you just have to use paredit+erc

1:56 n_b: I'm one of the dirty vim users amalloy

1:56 amalloy: not something i actually do, but i think technomancy swears by it

1:57 sinistersnare: i use sublime text...

1:57 n_b: I think he also swears by w3c, no? Once in a while I like to take a break from my text editor (though I'd likely be more productive if I didn't)

1:58 metellus: n_b: paredit works well in vim?

1:58 amalloy: n_b: w3m, you mean? i think he actually uses knokeror. but either way, yes, technomancy is a bit of a fanatic

2:00 n_b: metellus: Now that I'm on trunk and not some super outdated version, yes. Has full support for all the popular vim+clojure plugins, slurps and barfs with the best of them

2:01 amalloy: A quick Google says that seems right. And I could deal with being branded a fanatic to be half as talented as he is ;)

2:02 metellus: that's great, I'll have to look into using it

2:02 n_b: metellus: the biggest issues with current vim/clojure solutions are really support for proper REPL buffers, and dealing with long-running operations without blocking the main thread

2:03 akurilin: I'm playing around with clojure.tools.trace and I'm trying to understand what exactly "tracing" is doing in this case. What does it mean to "trace a value"? For example, I can see it println whenever my ring request is "modified" (in th mvcc way, I guess).

2:03 sinistersnare: random question: hows clojure in clojure going?

2:28 technomancy: amalloy: I don't actually use paredit in ERC; I only joke about it

2:28 show-paren-mode on the other hand, is invaluable

2:29 also: conkeror is different from konqueror

2:32 callen: technomancy: Raynes told me about you using Conkeror yesterday. Why not vimium? You'll get to use a real browser then.

2:33 technomancy: chromium's extension mechanism has offended my intelligence on a repeated basis

2:33 callen: technomancy: fair. I take it Conkeror is more holistic with the keyboard integration?

2:34 technomancy: I forget, do you use XMonad too?

2:34 technomancy: callen: instead of being purely additive, conkeror replaces all the existing UI

2:34 it's just another javascript application that uses gecko as a rendering engine

2:35 yeah, I use xmonad

2:35 callen: technomancy: LA is neat, great weather. I think the sunlight is making my mood noticeably cheerier.

2:36 technomancy: it's true; there are pockets of livability in LA

2:36 callen: that's a good way of putting it.

2:36 technomancy: unfortunately they didn't overlap with regions of reasonably-priced housing last I checked

2:37 (which was a while ago)

2:37 callen: technomancy: prices seem slightly lower than the bay area, which is not flattering.

2:38 technomancy: when I was in LA I hated sunny weather

2:38 callen: the benefit seems to be being able to get a place within walking distance of the beach that is reasonably affordable.

2:38 technomancy: I was further inland though, so the coastal breezes didn't moderate the temperature

2:38 callen: technomancy: yeah the breezes make allllll the difference. I don't normally like hot weather either.

2:38 I'm in west hollywood and have been hanging out along the coast.

2:39 the valley would be Hell itself for me.

2:40 technomancy: gotta head off; catch you fine folks later

4:09 dbushenko: hi all!

4:10 how do you localize a clojurescript web application?

4:19 supersym: dbusenko..I use stringtemplate atm

4:22 there are 2 clojure wrappers but they are outdated though

4:27 dbushenko: yeah, but is there any more or less standard technology to store localized strings?

4:37 supersym: standard? no

4:37 that is the best next to perfect you'll get though, context free

4:38 you can use json for the strings

4:38 or .property files

4:41 dbushenko: or pure clojure :-)

4:47 Morgawr: hello everyone... I was wondering, are there resources for common design patterns/good application architecture pratices for Clojure or other lisp-like languages? Because I'm building a game engine (somewhat) with ClojureScript and while not unfamiliar with game development, I find it a bit hard to keep it clean and easily re-usable with Clojure as I lack this basic knowledge

4:50 dbushenko: Morgawr: I don't think so since design patterns are usually just wrappers arond language weaknesses

4:51 but in Clojure with code-as-data and macros you can avoid typical code

4:51 but still you can learn some good coding practicies from classical lisp books such as "On lisp" and others

4:51 Morgawr: yes, I understand, probably "design patterns" is a too well established definition. I'm more looking for common programming/development practice for large re-usable algorithms/solutions

4:52 I've read a few books and stuff and mostly they are all theoretical with small examples that fit well for solving one problem but don't "click" well together in a large application, not sure if you understand what I mean

4:52 dbushenko: sure I understand :-)

4:53 I don't think that you'll find any good books on best clojure practicies since its a young technology

4:53 and really rapidly developing

4:53 but you can read classical lisp books: LoL, PAIP, On Lisp and others -- they are good

4:53 SICP especially

4:54 Morgawr: dbushenko: I'll give them a go, thanks

4:54 dbushenko: also I'd recommend you to read some clojure code from open source projects

4:54 usually it worth time

4:56 Morgawr: yeah,that's how I learned how to develop a small game with ClojureScript, it was fun

4:59 dbushenko: is it deployed anywhere? can I see it?

4:59 clgv: Morgawr: there are indeed design patterns in functional languages as well. borrowing terminology from Peter Norvig, most of them are invisible or formal

5:01 Morgawr: dbushenko: https://github.com/Morgawr/ld26 here's the source code and http://www.morgawr.eu/ld26/index.html here is the game, keep in mind it was developed in only 48 hours (And I had never really written anything this big in Clojure)

5:01 clgv: any resource for that?

5:01 clgv: Morgawr: one example for a formal pattern is "memoization" (implement once, use everywhere). another example for an invisible pattern is the "strategy pattern" which consists of using first class functions in clojure

5:02 Morgawr: http://norvig.com/design-patterns/

5:02 Morgawr: clgv: thanks! I appreciate it!

5:02 dbushenko: Morgawr, that took you just 48 hours???

5:02 lazybot: dbushenko: Oh, absolutely.

5:02 dbushenko: NICE!

5:02 clgv: Morgawr: I use it for a lecture last semester

5:02 Morgawr: dbushenko: yeah, lots of lack of sleep

5:09 ddellacosta: how do I compare a Java object with another in Clojure? This is for a test, I don't care about exact identity, just that it has the same type and state.

5:09 clgv: ddellacosta: use (.equals ob1 obj2)

5:10 ddellacosta: clgv: okay, thanks!

5:15 dbushenko: clgv: do you teach clojure at the university?

5:16 clgv: dbushenko: we had a lisp course using sbcl - the choice of my boss. maybe it'll be clojure in the next course

5:16 dbushenko: wow!

7:11 Morgawr: is there really an advantage with using defrecord instead of just a normal hashmap? I mean, in the end it just plays out like any hashmap (with assoc for keys, keys aren't even fixed and can be added/removed, etc etc)

7:12 I mean, like performance-related advantages or some special functions to keep the handling of records cleaner than a bunch of (assoc ..) calls?

7:12 dbushenko: yes

7:12 its the performance benefit

7:12 since defrecord creates a class, access to its members is faster than to the hash-map

7:12 Morgawr: does this also work for ClojureScript?

7:13 dbushenko: don't know, cljs is still in development

7:13 they add features and optimizations often

7:13 so you'd really look into the source code and figure that out

7:13 Morgawr: alright, thanks

7:14 dbushenko: btw, the source code of the cljs is rather clear so give it a chance

7:14 Morgawr: so the only real difference (at least in pure Clojure) is the underlying memory representation?

7:14 dbushenko: yes

7:14 Morgawr: ok

7:14 IamDrowsy: records also give you type so you can use protocols with

7:26 noncom: weavejester: hi! so, about the state in a game-engine, did you make your choice?

7:27 weavejester: noncom: Yep, I'm having success with an FRP implementation I cooked up (http://github.com/weavejester/reagi)

7:28 Morgawr: weavejester: you're making a game engine?

7:29 weavejester: Morgawr: Yep, for a game. I'll probably open source the game engine part of it eventually, but it'll be a while.

7:30 Morgawr: ah nice, I'm working on something like that as well, what type of game?

7:30 weavejester: Sandbox/bloxel type thing

7:30 Morgawr: I'm tackling a point-and-click game project with ClojureScript and developing a library on the side (pretty much collecting useful features and abstractions)

7:31 still at the very early stages though, mostly planning. I'm trying to see if I can recycle good practices from my previous game (from Ludum Dare, it's not the best coding ever in 48 hours.. hehe) or if I should approach it differently

7:32 weavejester: Morgawr: Me too. I've only done maybe 1 month of work

7:35 Morgawr: is it possible, in Clojure, to change the value of a symbol bound with a (let ) ?

7:36 weavejester: Morgawr: You can rebind it with an inner let

7:36 But you can't mutate the value in place

7:36 noncom: Morgawr: I would say this is a design flaw if you want do like this.

7:37 Morgawr: I was just thinking about manipulating the state of a closure

7:37 weavejester: Morgawr: You can't change a value sent to a closure

7:37 You could use an atom

7:37 noncom: Morgawr: hmmm, refer outside

7:37 weavejester: But there's likely a better way of doing it

7:39 Morgawr: noncom: what do you men with "refer outside"? As weavejester said, I've always used an atom for such things and wanted to know if there's a better option. I'm reading this lisp book referencing common lisp and they talk about closures and changing their values to pass state around

7:40 noncom: Morgawr: yeah,weavejester said it better. I think that Clojure is far more into immutability than CL.

7:41 Morgawr: it's just that sometimes you need to have some permanent state passed around (without polluting the global state), so my best bet is to just go with an atom?

7:41 I try not to do this often, usually I just try to flow from function to function keeping the parameters immutable within each step, but sometimes you can't really avoid it

7:42 noncom: Morgawr: afaik LISP initially has no special attitude for immutability and what is true for other lisps is not always true for Clojure.. but that's no surprise:)

7:42 weavejester: Morgawr: Using atoms when necessary is probably okay

7:42 Morgawr: But there are usually alternatives

7:43 Like having a function that takes a state and returns a new state

7:43 Morgawr: weavejester: yes, that's what I mean with "flowing from function to function", I usually try to have most of my state-defining code with (-> state (func1) (func2) (func3)) etc etc

7:44 weavejester: Morgawr: What do you need the atom for, out of interest?

7:44 Morgawr: I try to use atoms only for global resource identifiers (like in my case, images and audio files to be loaded asyncronously thanks to shitty javascript hehe) and game data found in files (like settings or scripts which will be themselves also instances of ClojureScript language)

7:44 ^ pretty much that hehe

7:45 weavejester: Loading files asynchronously sounds like something more like a promise

7:45 Morgawr: as I am approaching it now, I have a bank of resources and identifiers, I pass the identifiers around but load the actual resources into this global bank (which is an atom) and then retrieve them when I need to render them on screen

7:45 promises aren't implemented in ClojureScript afaik because javascript is single threaded

7:46 I use an onload function which has a closure on the actual resource to be loaded

7:46 noncom: Morgawr: strange you say about single-threaded. Afaik being insanely multithreaded is even an obstacle in writing for NodeJS

7:46 Morgawr: https://github.com/Morgawr/ld26/blob/master/src/cljs/ld26/image.cljs#L24 this is an example of what I mean, taken from my Ludum Dare game

7:47 noncom: I'm talking about javascript on browsers, they are single threaded but rely heavily on async calls

7:47 weavejester: I think an atom's probably the right tool, but it could be wrapped up in something akin to a memoize

7:47 noncom: since every other func you write runs on it's own!

7:47 Morgawr: oh, ok i have no much exp w/ it

7:47 Morgawr: so technically on a browser with ClojureScript, if you were to implement a promise and wait for it to be fulfilled, you would block forever

7:48 there are some theoretical race conditions with async calls as far as I know but an atom is all you need to solve them

7:48 weavejester: It looks like you're essentially implementing a future, in that you're waiting for the image to load before you can use it.

7:49 Morgawr: yes, but that's all thanks to Javascript and how it's implemented

7:49 you either load everything statically in the page (cumbersome) or you load them dynamically at runtime (like what normal people would do in games)

7:49 the problem is that as soon as you assign the "src" field of an image (or audio file, or whatever) it starts loading it

7:49 and then calls an onload() function you have provided once it's done

7:50 so you need to provide that function yourself (a lambda with a closure over the image identifier, in my case)

7:50 weavejester: Is there something equivalent to clojure.lang.IDeref in ClojureScript?

7:50 Morgawr: you mean a dereferencing operator? like '@'?

7:51 weavejester: Morgawr: Right

7:51 Morgawr: that's what I use to dereference atoms, I'm not really an expert with Clojure (yet) , that's why I'm studying a lot on how to apply all this stuff properly

7:51 most of my practices are unorthodox

7:54 weavejester: It feels like promises are needed in ClojureScript to deal with cases like this

7:56 Morgawr: yes but promises in ClojureScript would block infinitely because you'd be waiting for another thread to fulfill such promise but that will never happen because it's single-threaded

7:56 at least that's how I understand it

8:01 broquaint: Morgawr: WRT managing state in clojurescript - http://www.chris-granger.com/2012/12/11/anatomy-of-a-knockout/

8:02 Morgawr: broquaint: nice, thanks! I'll read it all

8:20 broquaint: np :)

8:25 manutter: weavejester: I think I understand FRP better after reading your reagi code than any of the other explanations I've seen.

8:26 noncom: weavejester: so you basically wrap all state so it looks like access to an immutable state.

8:26 weavejester: manutter: That's assuming I've understood it correctly ;) - there are still some parts like switching I don't think I completely understand.

8:28 noncom: Well, it's more like… the results of an event stream can always be calculated from its inputs

8:28 So it's functional; the output only depends on the inputs.

8:33 noncom: weavejester: that's rather vague. since boolean logic that underlies computers is deterministic, output always depends on inputs no matter what. when they say opposite, they usually mean that there is some "hidden" input which is not listed explicitly as a function's param???

8:33 lazybot: noncom: Yes, 100% for sure.

8:34 Morgawr: I think it's more about side-effects, though

8:34 noncom: Morgawr: that's the same thing, just from the opposite POV

8:35 weavejester: noncom: To be more precise then, the output of an event stream is only affected by the values pushed into it.

8:35 In the same way that the return value of a pure function is only affected by its arguments.

8:36 Done right, there shouldn't be any side-channels. It's a more constrained way of reacting to events.

8:40 noncom: weavejester: i think that the first two examples from the reagi readme should be coupled then to show how this works.. because still it all looks more like a convention (to me). currently the third example looks more like a fancy way to write perform "inc"..

8:41 sorry if i am stupid, i just try to understand

8:41 weavejester: No, no. You're right; the examples don't really show off what it can do very well.

8:42 dnolen: Morgawr: weavejester: that's the point of core.async - you can't really have proper promises in CLJS

8:42 Morgawr: yup

8:43 supersym: reading Hackers and Painters by Paul Graham, I assume more here have :D ... truly inspiring, so much pieces fall into place

8:44 dnolen: Morgawr: re: defrecord, it has performance benefits in CLJS

8:45 weavejester: noncom: Something like this is a slightly more useful example: https://gist.github.com/weavejester/dccd00f8be0cf7c4dfe9

8:45 Morgawr: dnolen: alright, great to know! thanks

8:46 * Morgawr wonders how to apply defrecord knowledge to a full component based entity system like the one posted earlier

8:46 Morgawr: looks like I have a lot of research to do, all these options... amazing

8:47 dnolen: Morgawr: you might want to pick austinh's brain when he's around - he's been developing his next game in CLJS

8:48 Morgawr: http://pettomato.com/

8:49 Morgawr: dnolen: great, thanks. I've see a lot of different small games deveoped in cljs and everybody always follows a slightly different approach (same goes for normal game development)

8:57 mefesto: Good morning all.

9:09 I'm playing around with ClojureScript for NodeJS and I'm getting an error regarding this line: (set! *main-cli-fn* -main)

9:09 says unable to resolve symbol: *main-cli-fn*

9:09 is this an old tutorial and this is now called something else by chance?

9:12 dnolen: mefesto: I see *main-cli-fn* in core.cljs, what tutorial are you following?

9:12 mefesto: dnolen: http://dannysu.com/2013/01/14/clojurescript-for-nodejs/

9:12 I'm using the latest lein-cljsbuild

9:13 and here is my source code: https://www.refheap.com/15129

9:15 dnolen: mefesto: do you have the right extension on your file? .cljs and *not* .clj

9:15 mefesto: dnolen: ugh i bet that's it ...

9:16 * mefesto slaps himself

9:16 mefesto: dnolen: yeah that was it :)

9:16 dnolen: thanks.

9:16 dnolen: mefesto: cool

9:18 mefesto: no worries, I've been bit by that before. The error about *main-cli-fn* not being defined was the clue.

9:24 mullr: Has anybody given any thought to linear systems by way of core.logic? CLP(R), I guess. I've seen the finite domain package, but I'd like to have floats.

9:27 gdev: I'm rewriting some of my java kata in clojure, so I guess this would be a code kata review: https://gist.github.com/gdeer81/5667796 any feedback appreciated.

9:28 it's only one of them so it's only a few lines of code

9:34 ro_st: so, i know i can give sort-by a key fn and a comparator

9:35 but what if i want to sort by a juxt of several key-fns, and use a different comparator for just one of the key-fns?

9:35 xeqi: gdev: it seems like a direct translation. I bet you could come up with something simpler/more-clojure-ish with drop and (reduce + ...)

9:35 ro_st: (sort-by (juxt :name :title :date) (comp - compare) coll) ; i only want the comparator for :date - name and title ascending, but date descending

9:36 my guess is that this is not something sort-by can do for me

9:36 and that i'll have to use sort-by for the first two, do some sort of group-by, and then sort again with the descending comparator

9:38 noncom: weavejester: still i do not understand what's different from doing same stuff w/o wrapping it into behaviors

9:38 gdev: xeqi: yeah that's what I was afraid of. =o drop and reduce you say? I'll give it another go

9:38 weavejester: noncom: Well, (a) it's more difficult, and (b) this way you can be sure there's no side channels.

9:39 xeqi: gdev: well, I missread the description originally, but the manual recursion still feels weird

9:39 noncom: weavejester: i guess i'll be waiting for something you write with it and maybe i look and see :)

9:39 weavejester: Once you start putting together more complex transformations of event streams, doing the equivalent with atoms is significantly harder.

9:39 dnolen: mullr: I would like a CLP(R) implementation, but I don't intend to embark on that myself. Would be happy to help along any contribution towards that goal.

9:40 noncom: weavejester: possible i do not have enough experience to extrapolate this on real complex usecases

9:40 mullr: dnolen: ok, thanks for the reply. Perhaps one day, far in the future, when I'm better at core.logic I'll have a go.

9:41 gdev: xeqi: yeah I searched for examples of backtracking strategy in clojure but it was getting late and just did a translation

9:41 noncom: thank you for the explanation though, it'll get me going

9:42 gdev: should I try using core logic to get all the possible combinations of numbers I'd need and then compare that to the given array?

9:43 weavejester: noncom: I guess, to use an analogy, it's the same reason you'd want to use map/filter/reduce instead of manually writing loops with loop/recur.

9:43 dnolen: mullr: heh sure, though core.logic isn't as fancy as it seems :)

9:44 weavejester: Not only do map/filter/reduce make things easier, but you can also string them together

9:44 gdev: dnolen: are the core logic koans being maintained? was having an issue with them earlier.

9:46 dnolen: gdev: I don't know, I contributed a bit but haven't followed along in a long while

9:47 gdev: dnolen: yeah I just now noticed the last commit was a year ago =]

9:47 dnolen: gdev: you could probably get fancier since core.logic has CLP(FD), but if you haven't done much core.logic it's a massive distraction

9:48 gdev: dnolen: life's an adventure, I'll check it out =D

9:48 xeqi: gdev: this problem speaks to me as "are there any sublists of this list starting at this index that sum to target". something like (any? #(= (sum %) target) (sublists (drop start lst))). If sublists can be generated lazily then I don't think you'll need backtracking

9:50 but that does ignore the code level requirements in the kata, which are kinda weird to have

9:52 tomjack: weavejester: still going to claim reagi is not functional, though the behavior stuff does look cool

9:54 gdev: xeqi: yeah it was just supposed to be an example of using recursion and not using loops. in java it's hard make an example that isn't overly complicated but still uses recursion. Since clojure is, for lack of a better term, good, a lot of this kata is going to feel odd

9:55 however, since this is just for my own benefit, following the constraints of the kata is at my own discretion

9:56 weavejester: tomjack: Why isn't it functional?

9:57 I mean, it uses state behind the scenes

9:57 tomjack: well 'functional' is a vague word. but I claim it's not FRP. 'FRP' is ambiguous though :(

9:58 weavejester: But the output of an event stream depends only on its input.

9:58 tomjack: (def sum-e (r/reduce + e))

9:59 the value of @sum-e depends on when I ask, right?

10:00 or rather, it depends on when I run (r/reduce + e) I guess?

10:02 weavejester: tomjack: On the contents of the event stream e

10:02 Sematically event streams are similar to a lazy seq, except that they don't block.

10:03 tomjack: I think that should be the case, it doesn't appear to be

10:04 weavejester: Derefing an event stream (i.e. getting the latest value) isn't pure, but while you're inside the stream it is.

10:05 tomjack: https://www.refheap.com/c6e52472564b32ca0e3fe2ad4

10:06 weavejester: tomjack: Well, that's true. There are some parts that are less pure for efficiency.

10:07 tomjack: I guess you can be careful to do things in such a way that that doesn't screw you up?

10:07 weavejester: tomjack: I assume that the event streams are all setup before pushing

10:07 Otherwise I'd have to cache all of an event stream in memory

10:08 tomjack: yeah :(

10:08 weavejester: Haskell etc. don't have that problem because it's all precompiled

10:09 tomjack: well Reactive's Reactive is a true monad

10:09 weavejester: Same problem with defs in clojure I guess. In theory they don't change. In practise you can redef.

10:09 I guess I'm not aiming for complete purity :)

10:09 tomjack: (but Reactive caches it all in memory like a lazy seq)

10:10 weavejester: tomjack: Don't the Haskell frameworks warn about time leaks? That would imply they don't "hold onto the head"

10:11 tomjack: a time leak happens because you can hold onto the head

10:11 (like we get space leaks with lazy seqs)

10:12 anyway, I think you understand what I mean now when I say 'not FRP', so I'll stop saying it from now on :). also regardless, reagi looks pretty cool, and beautifully short

10:14 weavejester: tomjack: Yeah, but Reactive would need to know when *not* to hold onto the head, right?

10:15 tomjack: Whereas in Clojure, because of how it evaluates things in series, that would be harder to achieve.

10:15 tomjack: I take your point that Reagi isn't pure FRP, though :)

10:16 tomjack: But I'd probably still use the term "FRP" because we tend to refer to Clojure as "FP", even though it isn't pure.

10:30 tomjack: weavejester: I think that is close to the tricky part

10:30 noncom: weavejester: yeah.. interesting :)

10:30 tomjack: ideally you wouldn't have to know when not to hold on

10:30 the GC will just collect the head when you stop holding it

10:31 but I think it is tricky..

10:31 weavejester: tomjack: Yeah… not sure how one would do that, though...

10:31 tomjack: thinking about it, I agree this deserves to be called "FRP" and I'd call what I want "first-class FRP"

10:31 i.e. FRP with first-class events/behaviors

10:31 elm comes to mind, where they bake in your assumption that everything's wired up beforehand as part of the compile to js

10:32 and I think a few haskell 'FRP' attempts have had second-class events

10:32 weavejester: Yeah, I get what you mean

10:33 There might be a better solution than Reagi, but at least it's in the right ballpack :)

11:32 silasdavis: is ther a standard way to send a json object as 'get data' in the URL of a GET request?

11:33 is it a weird thing to do; there seems to be much more use of form-encoded strings?

11:34 justin_smith: the idiomatic thing is if you need to send a data structure what you are doing is probably a better match for POST

11:34 is there a reason it has to be GET?

11:34 llasram: The CouchDB API uses query-strings with (usually tiny) JSON objects. You just JSON-encode then URL-encode. Nothing magical

11:35 But as justin_smith is suggesting, it isn't very common

11:38 justin_smith: maybe it is foolish, but I like to respect the failed dream of the semantic web, including each of GET / POST / PUT / DELETE having its own specific function

11:38 silasdavis: justin_smith, it's not destructive, it doesn't change anything

11:38 justin_smith: so the json object is a nested query object?

11:38 silasdavis: yeah that's sort of why I don't want to POST

11:38 gfredericks: GET allows a body actually

11:39 it's probably a weird thing to do though

11:39 justin_smith: gfredericks: how many web servers respect that?

11:39 gfredericks: seven

11:39 justin_smith: lol

11:39 gfredericks: I think security people might even flag such things

11:40 not sure why exactly

11:40 justin_smith: obscure feature ... abused feature

11:40 happens pretty frequently

11:40 gfredericks: in clojure too; since 2012 defstruct is only used by convicted felons

11:42 llasram: *snort*

11:43 TimMc: justin_smith: Don't forget PATCH!

11:44 justin_smith: wow, never heard of it, it is like swap! for web services

11:44 gfredericks: which is a much saner way of doing updates

11:45 justin_smith: definitely

11:45 gfredericks: I definitely faked it in couch by hand a few times

11:45 TimMc: swap! assoc

11:45 I guess you could encode other functions

11:45 justin_smith: a web server could even implement it as an atom

11:45 gfredericks: TimMc: speaking of which let's work on an embedded edn-processing subset of clojure

11:45 I'm looking for a better name than "clem"

11:46 TimMc: gfredericks: Explain?

11:46 gfredericks: all the pure functions on data in clojure.core -- so you could do things like have a remote service that takes update code, or a command line utility that transforms edn

11:48 edn : clojure-forms :: clem : clojure-code

11:48 TimMc: This would be an extraction of Clojure persistent data structures + manipulations?

11:48 gfredericks: exactly

11:48 no host stuff, no vars, no generic I/O

11:49 so as an embedded language you can run things relatively safely without having to sandbox

11:49 could be implemented on various platforms with the same semantics

11:49 I keep waffling back and forth on whether I think it would be genuinely useful or only in theory

11:50 TimMc: No lambdas?

11:50 gfredericks: yes lambdas

11:51 ToxicFrog: lambdas \o/

11:51 TimMc: Lazy seqs?

11:51 Oh, I guess nothing infinite.

11:51 gfredericks: eh you could

11:51 TimMc: EDN wouldn't stand for it.

11:51 justin_smith: for a command line tool, I think jvm is pretty much out of the question

11:51 gfredericks: it wouldn't?

11:51 justin_smith: sadly

11:51 TimMc: (except for... streamign EDN!)

11:52 gfredericks: you could have them in memory at least

11:52 but it'd be more of an implementation detail than it is in clojure

11:52 solussd: does anybody know why nrepl inserts a bunch of whitespace immediately after evaluating an expression in emacs? (using nrepl-jack-in)

11:52 gfredericks: justin_smith: this is why I think it'd be cool to implement clem in C or haskell :)

11:52 solussd: *and before printing the result

11:52 justin_smith: gfredericks: awesome idea

11:52 a haskell clojure backend would be sweet

11:53 and I imagine, relatively easy to implement

11:53 thorwil: solussd: well, it doesn't do that, here

11:53 justin_smith: I looked at that c backend, it looked very rudimentary. I was looking for something I could use in signal processing code

11:53 thorwil: am i suffering from previous definitions, or does a :require in ns with :only still make everything else from the required ns available, if called with the full path?

11:54 TimMc: gfredericks: I'd want to do some reworking of the coll and seq semantics.

11:54 gfredericks: TimMc: yeah that seems fine

11:54 justin_smith: thorwil: I think :only only affects the :as clause? not sure though

11:54 gfredericks: conj on a map should not take a map as a second arg :)

11:55 justin_smith: thorwil: I know I have used libs in a repl that I never required, but code I required had required, by spelling out the full namespace

11:56 gfredericks: TimMc: what do you think about loop? and lazy-seq? do we need them?

11:56 can we do proper tail recursion?

11:56 thorwil: usually i either require an ns with :as, or use :refer. but now i realize i'm clueless regarding pretty much all other options

11:57 justin_smith: thorwil: yeah, I just reproduced it - you can use any code clojure has loaded by spelling out the full ns, even if you have not directly required it in the current ns

11:58 not that doing so in actual code is a good idea, but when lazy in a repl it works

11:58 thorwil: i have a function "string" in "tlog.interface.validate". what can i do so i can call it as either valid/string or valid-string?

11:59 justin_smith: (:require [tlog.interface.validate :as valid]) gives you valid/string

12:00 thorwil: of course, though i would have liked to express that i'm only interested in that one thing from that ns

12:00 justin_smith: (:require [tlog.interface.validate :rename {string valid-string}]) gives you valid-string (according to docs, I have never used the feature)

12:01 oh wait, the above was for :use not :require

12:01 thorwil: thanks, bbiab

12:02 justin_smith: (require '[clojure.set :refer :all :rename {union grand-union}]) <- that works in my shell

12:03 which makes me realize how much easier updating our old libs that used clojure.data.json could have been

12:03 gfredericks: oh man I don't even know about :rename

12:04 justin_smith: yeah, I wish I had known about :rename

12:05 as god is my witness, I will never have to suffer from a lib writer's shitty naming decisions again

12:05 gfredericks: hm

12:05 does it only work with :refer?

12:05 justin_smith: dunno? I will try

12:05 gfredericks: looks like it

12:06 justin_smith: that is much less useful

12:06 too bad

12:08 though you can always do (:require [foo.bar.baz :as baz :refer [quux] :rename {:quux baz-q}]) or something like that - serves a similar function to requiring the namespace prefix, though not is elegant

12:25 TimMc: gfredericks: I guess it all depends on what not-clem's intended usage is.

12:28 gfredericks: TimMc: i.e., performance constraints?

12:29 I wonder if the no-vars purity thing would allow smarter compiler things

12:34 justin_smith: one bonus if the project took off: it could be used for smarter clojure parsing / high level manipulation of clojure code in editors

12:35 gfredericks: eh?

12:35 how so?

12:35 oh I wonder if there are any major downsides to defining the syntax to be pure edn as well?

12:35 would mean no regexes

12:35 justin_smith: some basic transforms could be used to aid editor syntax awareness (as a helper task)

12:35 gfredericks: no metadata would probably be a big limitation too

12:36 justin_smith: even emacs current clojure mode awareness has flaws and corner cases

12:36 gfredericks: justin_smith: you mean by embedding clem in an editor that is not itself written in clojure?

12:36 haha clem in elisp would be fun

12:37 justin_smith: or letting the editor use it, the way vim uses clang to parse c

12:37 gfredericks: hmm

12:37 justin_smith: actually clem in elisp would be a double win for us emacs users, yeah

12:38 next step after that, re-implement emacs using an FRP arcitecture (how many "redo emacs in a better language" projects are there again?)

12:53 ohpauleez: reiddraper: Have you signed an Clojure CA? (I'm curious if you're interested in migrating some of the ideas in simple-check to test.generative and data.generators)

12:53 reiddraper: ohpauleez: yes and yes

12:53 ohpauleez: reiddraper: Cool, keep me posted

12:54 reiddraper: ohpauleez: will do. simple-check is still in it's infancy, mostly just a promising sketch at this point

12:55 ohpauleez: Cool, for sure. I've been digging through the code - nice stuff for sure. All ideas start somewhere

12:55 reiddraper: ty

13:18 TimMc: reiddraper: I've been reading through the GNU Privacy Handbook, and I think I'll probably need another month before I'd feel comfortable telling people how to make and manage their own keys.

13:18 reiddraper: TimMc: that's reassuring ;)

13:23 TimMc: The guide is outdated as far as UI goes, but still relevant I think.

13:23 http://www.gnupg.org/gph/en/manual.html <- 14 years old

14:07 tieTYT2: I i develop in clojure and clojurescript for one app, should they have separate project.clj's?

14:08 ohpauleez: I don't think there's a hard rule - I typically leave them together.

14:08 tieTYT2: k, didn't even know that was possible

14:08 ohpauleez: I've broken them apart when they were really two separate applications that happen to work together nicely

14:15 bhenry: can i make a library's resources be accessible on the referring web-app's classpath?

14:16 tieTYT2: what's a referring web app?

14:16 bhenry: tieTYT2: a webapp that uses the library

14:17 tieTYT2: yeah they're automatically accessible

14:17 if the library can use them, you can access the resources, assuming the resources are in the library's jar

14:18 bhenry: so my library has /resources/public/library/js/blarg.js and what needs to be done for the app using my library to be able to serve up localhost:3000/library/js/blarg.js ?

14:19 tieTYT2: oh that's a different thing from what I thought you were asking

14:19 let me think

14:19 this sounds like a maven overlay, but not exactly

14:20 bhenry: i've been thinking about it for awhile

14:20 hiredman: really?

14:20 just use wrap-resource or whatever the ring middleware is called

14:20 tieTYT2: http://stackoverflow.com/questions/4732965/exposing-resources-from-jar-files-in-web-applications-tomcat7

14:21 yeah be aware I only know java, not too good with clojure

14:21 i'd listen to hiredman

14:21 bhenry: hiredman: thanks. i'll look into it

14:22 weavejester: bhenry: This is how I do it: https://github.com/weavejester/hiccup-bootstrap/blob/master/src/hiccup/bootstrap/middleware.clj

14:22 bhenry: weavejester: that's great thanks.

14:34 gfredericks: how do I set an http proxy for a leiningen repository?

14:35 the sample project.clj doesn't seem to have any attributes that look relevant

14:36 kephale: ccw folks (cemerick?): is there a variable/way of detecting if a source file is being run from CCW? the intention is to run -main if the file was evaluated with CCW's "load file in REPL"

14:37 cemerick: kephale: you could check for the existence of ccw's tooling namespaces (all start with ccw.* IIRC)

14:39 gfredericks: unless there is only https://github.com/technomancy/leiningen/wiki/HTTP-Proxies and you can't do it in the project.clj at all

14:40 abp: ##*clojure-version*

14:40 gfredericks: &*clojure-version*

14:40 lazybot: ⇒ {:major 1, :minor 4, :incremental 0, :qualifier nil}

14:41 kephale: cemerick: works like a charm, thank you

14:41 abp: oh ok. now i'm sad.

14:42 amalloy: abp: why?

14:45 abp: amalloy: No clojure 1.5.1 for the bot. as-> etc

14:46 amalloy: .*clojure-mode*

14:46 ,*clojure-mode*

14:46 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: *clojure-mode* in this context, compiling:(NO_SOURCE_PATH:0:0)>

14:46 amalloy: god

14:46 abp: :D

14:46 amalloy: ,*clojure-version*

14:46 clojurebot: {:interim true, :major 1, :minor 6, :incremental 0, :qualifier "master"}

14:47 abp: all right, thanks.

14:49 mefesto: im playing around with cljs + nodejs + socket.io and have a basic websocket thing going. am i able to use socket.io for a commandline *client* as well or does the client part require a browser to work?

15:10 edtsech: As an Emacs beginner I've created simple Clojure Emacs setup for other beginners https://github.com/edtsech/clojure-emacs-setup if you would like to try emacs for clojure development check this out. Feedback is welcome.

15:11 tieTYT2: edtsech: cool, thanks

15:12 i want to group by field1 if it exists, *otherwise* group by field2 and if neither exist, put it in its own group. How do you go about doing that? Is that a group-by #(or field1 field2 (identity %)) data)

15:15 justin_smith: tieTYT2: would you use field1 from one map and field2 from another?

15:15 hyPiRion: ohooh

15:16 ,(group-by (some-fn :foo :bar identity) [{:foo "foo" :bar "bar"} {:bar "bar" :hurm 1} {:something :else}])

15:16 clojurebot: {"foo" [{:foo "foo", :bar "bar"}], "bar" [{:bar "bar", :hurm 1}], {:something :else} [{:something :else}]}

15:19 tolitius: is there a good way (besides documentation) to specify dependencies of "the thing" deployed to clojars? I'd like to publish a jar of https://github.com/tolitius/highlander but it depends (might depend) on zeromq to be installed in order to run.

15:19 antares_: tolitius: for native dependencies, no, besides bundling them in for all platforms

15:21 tolitius: antares_: hm.. that would not be too clean, especially given the fact that zeromq needs both: itself and java bindings.. built for a particular platform

15:21 justin_smith: tolitius: have an assertion that looks for the dep, and gives the URL to get it if it is absent?

15:21 at the top of your init or -main if such a thing exists I guess

15:21 antares_: tolitius: it's not "clean" and usually very painful but that's what some projects do

15:22 justin_smith: ship with a vm of linux configured to run said service :P

15:23 technomancy: yeah, the only way that works consistently is to depend on a jar with .so files and such in it

15:23 there are no language-specific tools that do this well as far as I know

15:24 tolitius: technomancy: interesting, and then they would be resolved by reusing a classpath that points to that jar.. ?

15:24 *they = ".so"s

15:25 justin_smith: and if it is a cluster, ship a cluster? :)

15:25 technomancy: tolitius: leiningen will unpack the .so files for the proper OS/arch if you run with it; otherwise you can do it at runtime, which I think is what overtone and penumbra do

15:25 (in order to still work with uberjars)

15:25 I think everyone rolls their own systems for runtime unpacking =\

15:25 justin_smith: you could publish build rules for a port file / .deb / arch aur / whathaveyou and tell people to install the package to get the deps

15:25 tolitius: antares_: I know Storm is trying to get away form zeromq for this and other reason, so yea, it is a problem

15:26 technomancy: debs are crappy for this since you need root and can only install one version at a time

15:26 antares_: tolitius; have you tried JeroMQ?

15:26 tolitius: it's a pure Java impl endorsed by the ZeroMQ lead dev

15:26 nightfly: Vague question, but how many messages per second can a message queue route?

15:26 tolitius: antares_: yea.. slow..ish

15:26 tieTYT2: justin_smith: nope

15:26 hiredman: someone just released a netty transport for zeromq

15:27 mabes: antares_: do you have personal experience with jeromq?

15:27 technomancy: nightfly: depends on what kind of delivery guarantees you need

15:27 antares_: mabes: nope but it seems to be fairly actively developed and used. I doubt ZeroMQ guys would support it otherwise.

15:27 tieTYT2: hyPiRion: how does that work, is some-fn part of core?

15:27 antares_: hiredman: link?

15:27 hyPiRion: tieTYT2: yeah

15:27 (doc some-fn)

15:27 clojurebot: "([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps]); Takes a set of predicates and returns a function f that returns the first logical true value returned by one of its composing predicates against any of its arguments, else it returns logical false. Note that f is short-circuiting in that it will stop execution on the first argument that triggers a logical true result against the original predicates."

15:27 technomancy: also it depends on how many erlangs you have: http://bitfission.com/images/erlangs.png

15:28 hiredman: https://github.com/spotify/netty-zmtp

15:28 tieTYT2: ah thanks

15:28 justin_smith: tieTYT2: if you need to use the same selector on all args, some-fn is not what you want (if that was what your nope was about)

15:28 hiredman: "This is a ZeroMQ codec for Netty that aims to implement ZMTP/1.0, the ZeroMQ Message Transport Protocol."

15:28 mabes: antares_: well, my understanding is that while zmq is endorsing jeromq they aren't supporting it: http://stackoverflow.com/questions/14491000/is-jeromq-production-ready

15:29 tolitius: antares_: yea, JeroMQ it has a good idea: e.g. 0mq protocol compliant without a need to install 0mq ".so"s, but it is not as fast as native..

15:29 tieTYT2: justin_smith: then what, should I use or like I was?

15:30 antares_: tolitius: are you trying to reach roflscale?

15:30 justin_smith: I think there is a way to do it with condp

15:31 antares_: tolitius: many people would take tens of thousands of msg/s as a pretty good throughput, so convenience may be more important for them than reaching the performance of the native library

15:32 tolitius: antares_: right, I agree. I had a couple of customers that needed a several mil a second

15:32 tieTYT2: justin_smith: what's the problem with my attempt?

15:32 tolitius: but still staying in JVM

15:32 antares_: tolitius: fair enough :)

15:32 tolitius: 0mq is really great for that

15:32 + some design thinking of course

15:35 solussd: anyone know of any pedestal tutorials aimed at current users of MVC app frameworks? Whie I understand, conceptually, how pedestal web apps work, I'm struggling with building anything in it.

15:37 enquora: solussd: I archived a bookmark on a blog post, let me see if I can find it

15:40 justin_smith: tieTYT2: so is field1 a var that may be nil?

15:40 tieTYT2: yes

15:40 justin_smith: *a binding

15:40 ahh, yeah, so that is what you want

15:40 tieTYT2: the or?

15:40 justin_smith: yeah

15:40 tieTYT2: cool, thanks

15:40 justin_smith: I misunderstood the question

15:41 and the somefn would give an npe when it gets to the one that is nil

15:41 tieTYT2: it's not actually a var, it's more like this (fn-to-get-field1 %)

15:41 justin_smith: yeah

15:41 that is why I tried to correct myself to a more general term

15:42 tieTYT2: ok thanks for the help

15:43 justin_smith: I am playing around with frp, trying to build something from scratch in order to really grok it (though I may just use someone else's lib later once I get it)

15:44 piranha: solussd: are you talking about client-side of pedestal? If so, have you seen http://squirrel.pl/blog/2013/05/16/getting-started-with-pedestal-on-client-side/ ?

15:44 justin_smith: if I have inputs to the frp nodes from multiple threads (say a network socket driving one, a gui driving another, midi device driving a third), how to best synchronize when individual parts of the network want to mutate the network (change who listens to what for example)

15:45 I was just passing a big network data structure around, and using run as an arg to swap!, but then the same message may produce side effects twice - I want the messages to only propagate once

15:45 or is allowing nodes in frp to mutate the set of connections just doing it wrong?

15:46 tieTYT2: if nobody can help you, maybe you can get help in #haskell

15:46 justin_smith: heh, I have been chatting with a haskell using friend about this on jabber

15:47 tieTYT2: i also find it hard to figure out what it is

15:48 everyone tells you you're doing it wrong, nobody shows how to do it right

15:48 justin_smith: well I decided I was doing it wrong when I realized I had to worry about state and race conditions, that was kind of a red flag

15:49 solussd: piranha: i had not, thanks.

15:50 justin_smith: maybe what I think requires change of state ("have the mouse click do something different next time") are better done as a message queue for something that is consumed by the other thread

15:50 but still I feel like there should be something cleaner here

15:53 melipone: hello! What's the best way to save a map containing other objects (such as functions) to a file?

15:53 tieTYT2: justin_smith: maybe this will help: http://www.youtube.com/watch?v=nket0K1RXU4

15:53 but it's a time investment

15:54 justin_smith: tieTYT2: thanks! I'll watch it while eating lunch

15:54 tieTYT2: i'm not sure if it will help, but it's a clear explanation

15:54 with sample code

15:54 justin_smith: haskell?

15:54 clojurebot: "you have to see features like that in the context of Haskell's community, which is something like Perl's community in the garden of Eden: detached from all shame or need to do any work." -- ayrnieu

15:54 tieTYT2: no, clojurescript

15:54 here's where I posted that: http://stackoverflow.com/a/16618078/61624

15:54 justin_smith: oh, awesome

15:55 tieTYT2: the SO link has a link to the source code

15:55 perhaps skip directly to the source code

15:59 amalloy: melipone: you can't serialize functions in a readable way

16:03 enquora: solussd: dunno if this will help, but for what it's worth, despite extreme attraction to cljs, I've yet to see any guidance on structuring a non-trivial app so I'm using it just for libraries. http://squirrel.pl/blog/2013/05/16/getting-started-with-pedestal-on-client-side/

16:05 melipone: amalloy: I just want to save and load them back

16:05 amalloy: that's an accurate description of what i just said you can't do

16:06 you can write/read forms/expressions, but not functions

16:06 melipone: amalloy: oh, okay

16:08 loliveira: how do I access in my project a variable defined in project.clj? This is a fragment of my project.clj and I'd like que access the variable :server.

16:08 :profiles {:prod {:server "server.prod"}

16:08 :dev {:server "server.qa"}}

16:15 tieTYT2: justin_smith: also just found this: http://engineering.prezi.com/blog/2013/05/21/elm-at-prezi/

16:19 llasram: loliveira: Is this in a lein task, or in your application proper?

16:20 loliveira: it is both a repl task and ring uberwar task

16:20 seangrove: tieTYT2: Was a great video, thanks

16:22 weavejester: loliveira: I wrote a library called environ where configuration can be specified via the project.clj file

16:22 llasram: loliveira: Not completely following... So when you use `lein`, it launches one JVM which loads leiningen + plugins and reads the project map etc, then if you're running a task which has to actually load your code (like `repl` or `run`) it launches another JVM to actually load your code

16:22 weavejester: loliveira: However, it won't translate over to an uberwar. For that you'll need to use system properties or environment variables.

16:22 llasram: If you want to have stuff in your project.clj that you can access in the latter context, then weavejester's library is what I was going to point you at

16:23 tieTYT2: seangrove: np

16:23 technomancy: amalloy: you tease

16:23 tieTYT2: that video is a little over my head actually

16:24 amalloy: technomancy: hush! no one can know of our secret lovechild serializable-fn!

16:24 *gasp* i've said too much

16:26 konr: is there any lib cooler than swiss-arrows? https://github.com/rplevy/swiss-arrows

16:26 loliveira: llasram: i'd like to be able to run 'lein with-profile dev repl' and generate an war that connect in the right server using 'lein with-profile dev ring uberwar'

16:27 weavejester: what will happen if I generate my war with the rolling command: 'lein with-profile dev ring uberwar'?

16:28 ohpauleez: konr: some-> as-> cond-> or https://github.com/LonoCloud/synthread

16:28 weavejester: loliveira: It'll compile the uberwar with the dev profile, but the configuration won't be hardwired into the war, which is what I'm guessing you want.

16:28 In general hardwired configuration is a bad idea.

16:29 loliveira: weavejester: how do you suggest I should resolve this?

16:32 weavejester: loliveira: Which server are you deploying the war to?

16:32 loliveira: jetty

16:33 jetty-distribution-9.0.3.v20130506

16:34 weavejester: loliveira: Is it a requirement to deploy as a war?

16:38 loliveira: weavejester: yes. And I can not change this. =(

16:38 weavejester: loliveira: That's okay. I just wanted to check, because the alternatives are a lot easier :)

16:39 loliveira: weavejester: =)

16:40 konr: ohpauleez: awesome!

16:41 weavejester: loliveira: Hm, it looks like there's a configuration file for wars that Jetty uses. I guess that would be the official way of conifguring the war.

16:43 loliveira: weavejester: it might work, but i loved the idea that I could concentrate all config in one place (project.clj) =(

16:44 weavejester: loliveira: It makes sense not to do that when deploying to a (dare I say) more sane environment. :)

16:44 technomancy: project.clj is not designed for runtime application configuration

16:44 there are ways to make it work, but that's not what it's meant for

16:45 loliveira: weavejester: you convinced me. I'll look for alternatives. thank you. =)

16:45 weavejester: loliveira: I guess you could add a resource file that would only be included in your uberwar in production.

16:46 loliveira: You could add an extra directory to :resource-paths in a :prod profile, and then add a configuration file in the resource path.

16:47 loliveira: weavejester: sounds nice. How do I select the right file to send to war?

16:47 technomancy: agreed.

16:48 weavejester: loliveira: Well, you could have something like: :profiles {:prod {:resource-paths ["resources" "config/prod"]}}

16:48 technomancy: weavejester: did you see the new :uberjar profile in lein 2.2?

16:48 might want to support something similar for uberwars

16:48 weavejester: technomancy: Nope. What's that?

16:48 technomancy: Oh, a profile just for uberjars, I guess?

16:48 loliveira: weavejester: it just what I wanted. ty.

16:49 technomancy: yeah, gets applied implicitly

16:49 weavejester: That's a good idea

16:49 clojurebot: One idea I had was to parameterise Keyword with the key it looks up. :a is of (Keyword :a). But that has other issues.

16:49 technomancy: weavejester: lets you add :main what.ever without contaminating regular dev time with AOT

16:49 weavejester: technomancy: Yeah. I like that idea.

18:11 akurilin: In clj, what's a good way to swap method implementations for unit testing purposes? For example, I have a compojure route that ends in an email being sent through some AWS infrastructure. In development, I would probably want to replace that last part with something else more testable.

18:14 justin_smith: akurilin: postmark has a drop in test version of its emailer

18:14 mpenet: ,(doc with-redefs)

18:14 clojurebot: "([bindings & body]); binding => var-symbol temp-value-expr Temporarily redefines Vars while executing the body. The temp-value-exprs will be evaluated and each resulting value will replace in parallel the root value of its Var. After the body is executed, the root values of all the Vars will be set back to their old values. These temporary changes will be visible in all threads. Useful for mockin...

18:14 mpenet: that could do it

18:14 justin_smith: you can just make a version of the email function that verifies the types / content of the args and gripes if they are weird

18:15 akurilin: justin_smith, how would I "inject" that version of the function?

18:16 justin_smith: personally I prefer to rewrite my functions so anything I wouldn't want to happen at test time is a parameter and not baked in, but that probably isn't to everyone's stylistic preference

18:16 nightfly: dynamic vars ftw

18:16 justin_smith: so instead of (defn send-mail [from to body subject] ...) I write a function (defn send-email [from to body subject emailer] ...)

18:16 hiredman: nightfly: no

18:16 * nightfly likes the CL way

18:17 hiredman: nightfly: no

18:17 mpenet: imho with-redefs really seems like the sane solutions here

18:17 weavejester: I'd be inclined to choose an implementation via a configuration.

18:18 hiredman: the best solution is to base behaviour on passed in information, but if you can't do that then with-redefs

18:18 weavejester: In the same way that a database URL can point to a local (maybe embedded) database during developmnent, and a remote one in production.

18:18 akurilin: mpenet, for with-redefs, I include the function I want to override in the namespace where my tests are, and then everything contained with that with-redefs will basically use the new version? Am I understanding that correctly?

18:20 hiredman, weavejester : what would you recommend as an elegant way to select between two implementations if I were to go the environ route and check for development/production/test etc?

18:20 I feel like there must be something better than an if statement.

18:20 mpenet: not exactly: see examples here http://clojuredocs.org/clojure_core/clojure.core/with-redefs . It redefines vars for the body of the redef, and restores them once the body executed

18:20 nightfly: with-redefs is pretty much dynamic scoping

18:20 hiredman: use carica, it comes with a config override deal exactly for tests

18:21 mpenet: nightfly: not really , the change is visible to *all* threads

18:21 hiredman: https://github.com/sonian/carica#testing

18:21 mpenet: nightfly: but other than that yes, very similar

18:22 weavejester: akurilin: It sounds like what you want is polymorphism over configurations

18:22 So either multimethods or protocols

18:23 What you want is a "send-email" function that changes implementation based on a configuration, I'd guess.

18:23 mpenet: akurilin: For different setups via config, Environ is very handy

18:24 but weavejester can tell you more about it than me probably :)

18:24 technomancy: if it's just changing for test then with-redefs is better than a multimethod

18:24 with-redefs works great with clojure.test fixtures

18:26 akurilin: So, if I'm understanding that correctly, the idea would be to basically replace the email sending logic with clojure.test (is) calls?

18:27 technomancy: no, you would replace it with a function that saves the args off to an atom or something

18:27 _{^_^}__: someone asked me what the crowning difference between observer pattern and frp was

18:27 i couldn't answer

18:27 now im curious

18:28 technomancy: (let [delivered (atom [])] (with-redefs [send-email #(swap! delivered conj %&)] (do-stuff) (is (= [...] @delivered))))

18:28 akurilin: ^

18:30 akurilin: technomancy, basically the issue is that there's really no easy way of passing back the values that are at the bottom of that call stack that we want to test, because that whole call chain ends in a side-effect, so one's best bet is to basically "extract" them and test them.

18:30 yes?

18:30 clojurebot: yes isn't is

18:31 technomancy: thanks clojurebot

18:31 akurilin: I love that guy :)

18:31 technomancy: but yeah, what you described is basically on-target

18:31 akurilin: technomancy, great, thank you.

18:32 technomancy: often people ask how they can mock functions out and get pointed to midje when all they really need is with-redefs =\

18:32 akurilin: I'm actually considering moving off of clojure.test, it's annoying that it doesn't print out the test case names by default

18:32 I don't know if there's some out-of-the-box way of having that happen.

18:33 technomancy: lein test will print the deftest names when there's a failure

18:33 hiredman: akurilin: you mean when they pass?

18:33 seems useless

18:33 (they definitely get printed out when they fail)

18:33 akurilin: I guess mine is a corner case, I had one test case take 20 seconds every 4-5 runs and I couldn't tell which one it was

18:33 justin_smith: technomancy: not to mention also any (testing "foo" ...) forms

18:34 technomancy: akurilin: (is (< (- (System/currentTimeMillis) start-time) 5000))

18:35 akurilin: technomancy, that's definitely the most straightforward way. I went the long route and wrapped every test in a profiler call.

18:35 Which worked out ok, I discovered each test case takes 30ms, yuck.

18:36 justin_smith, (testing "foo") doesn't actually print anything either until it fails, right?

18:36 justin_smith: yeah, but it is helpful for extra context when you have more than one is clause in a deftest

18:37 akurilin: Since we were on the carica/environ topic, I'm a bit puzzled that neither documentations really shows you how to switch between different environments that one creates configs for. Basically I get how to make that config file, but how do I switch between multiple? Is that purely lein profile based?

18:37 justin_smith: if you want something printed every time, why not println?

18:37 technomancy: akurilin: with carica it's just based on the classpath

18:38 akurilin: justin_smith, sure, that's quite doable.

18:38 hiredman: carica doesn't have environments or profiles

18:38 technomancy: it's outside the scope of carica to manage the classpath

18:38 justin_smith: you could even write a macro wrapping deftest that prints the name of the defined test

18:38 hiredman: generally you have a set of default configs that get backed in to your jar/uberjar

18:38 technomancy: presumably something is launching either `java -cp ...` or `lein run ...`; it's that tool's responsibility

18:39 hiredman: and then you might have some other tool (chef, puppet, etc) write out overrides somewhere and put those overrides on the right place on the classpath for your app

18:39 akurilin: So what you'se saying is that the best bet is to let project.clj choose the right config file depending on profile?

18:39 in the lein case.

18:40 technomancy: akurilin: based on the classpath, which is a function of the :resource-paths of the currently-active profiles (if you want to get pedantic)

18:40 decaf: nrepl client in emacs has great completion support. can I bring this to .clj file editing?

18:40 technomancy: decaf: M-TAB should work in clojure-mode if you're connected to nrepl

18:41 justin_smith: with many wms that has to be escape-tab, sadly

18:41 unless you are like me and pick wm based on which one can be made not to steal meta

18:44 akurilin: technomancy, So if I wanted to have a couple of separate config files based on environment, would you recommend that I just add their respective folders in the :resource-paths of each profile I'm interested in? And then, as hiredman suggested, make sure I build the uberjar with the production environment.

18:45 technomancy: akurilin: exactly

18:45 akurilin: uberjar will strip out the default profiles for you actually

18:46 akurilin: Am I making this too Railsy or is that reasonable?

18:47 I can never tell the difference between them just doing things right and me not knowing a better way :)

18:47 technomancy: if you need multiple environments, "check a file on the classpath" is a tried-and-true JVM-friendly way to do it

18:47 most people don't need anything beyond resources/ and dev-resources/ directories

18:47 akurilin: technomancy, ok that's great to know.

18:48 I gotta mail this log to myself, you guys have shared so many pearls here with me today.

18:49 technomancy: better than sharing perls

18:50 hiredman: ~#95

18:50 clojurebot: 95. Don't have good ideas if you aren't willing to be responsible for them. -- Alan J. Perlis

18:51 akurilin: For a one VM scenario, is there actually a significant benefit to uberjarring my project for production? My use case is really basic, and I've been able to get away with just fetching the repo with git and running the web app straight from source.

18:51 technomancy: akurilin: repeatable deployments and faster boot time

18:51 using git on production is sloppy

18:52 flu-: +1

18:53 akurilin: It certainly does take a while to boot on a micro instance.

18:54 hiredman: micros suck

18:54 Raynes: technomancy: What do you mean?

18:54 'using git on production'

18:54 decaf: if anyone else is looking for tab completion: https://raw.github.com/genehack/smart-tab/master/smart-tab.el

18:56 technomancy: Raynes: well, resolving dependencies on production nodes is sloppy

18:56 dependency resolution isn't completely deterministic

18:56 abp: akurilin: Recently I used weavejester's environ to get a profile.clj setting or environment variable. So on dev machines I add :env {:my-project-env :dev} to lein profile.clj, on servers set MY_PROJECT_ENV=live etc. Then in /resources I have a base config.clj and one dev_config.clj, live_config.clj etc. that overwrite parts of config.clj, according :to my-project-env, when loaded via carica.

18:56 Raynes: technomancy: Don't understand the correlation between dependency resolution and git on production here.

18:56 hiredman: I had clojurebot (3-4 jvm services) running on a t1.micro, I have it half moved over to a cheaper node on non-aws virtualized hosting and the node is way more responsive with even more jvms running on it

18:57 akurilin: abp, do you have a repo for reference? That'd be really cool.

18:57 technomancy: Raynes: it's an implied correlation. if you're freezing jars in a build environment, you've got some way to ship files out... why not use that for application source as well as jars?

18:58 if you've got one way of getting jars to production and another way of getting source to production, that sounds unnecessarily complicated

18:58 abp: akurilin: Could whip up a sample, don't have anything public by now.

18:59 technomancy: if there were no such thing as version ranges, snapshots, or unreliable maven repositories, then dependency resolution could be strictly deterministic and everything would be peachy

18:59 unfortunately existence is suffery

18:59 suffering

18:59 papachan: i just have installed leiningen 2.2

19:00 akurilin: abp, I think it'd be valuable to more than just me, since it's not something I've seen much in public repos at this point and it's very much relevant to almost every web app out there.

19:00 abp, your description above is good enough for me though :)

19:00 papachan: how i can start with this feature:Isolate target paths by profiles?

19:01 technomancy: papachan: you don't have to do anything

19:01 it just works that way by default

19:01 papachan: technomancy: ok let me try :)

19:03 abp: akurilin: I'm at it.

19:04 akurilin: abp, kudos! Even better, you can turn that into a neat blog post.

19:04 abp: akurilin: I don't have a blog. :x

19:04 akurilin: abp, Ah! Well, one step at a time then! :)

19:42 Sintendo: how can i split up my code across files?

19:42 abp: Sintendo: Create files and write code. :)

19:43 Sintendo: http://clojure-doc.org/articles/language/namespaces.html

19:44 amalloy: i'm amazed that a document that long doesn't mention the -/_ conversion

19:45 abp: amalloy: They don't?

19:45 amalloy: having just read it, i can tell you that it is not mentioned

19:45 abp: amalloy: I got caught by it when doing my first experiments two years ago and saw multiple people stumble since.

19:46 amalloy: everyone trips on it sometime

19:46 Sintendo: what do i do with those? filename conatins a - in my case

19:47 hyPiRion: use _ instead

19:48 abp: amalloy: http://clojure-doc.org/articles/language/namespaces.html#namespaces_and_class_generation there it is. ;)

19:48 hyPiRion: ,(munge "a.namespace.foo-bar")

19:48 clojurebot: "a.namespace.foo_bar"

19:49 Sintendo: so i must rename the file?

19:49 amalloy: each _ in the filename must correspond to a - in the namespace, and vice versa

19:50 abp: Sintendo: Yes, underscores in filenames, dashes in namespaces.

19:50 Sintendo: Could not locate lru_cache__init.class or lru_cache.clj on classpath

19:51 oh wait, i figured it out

19:51 thanks everyone

19:52 Is there a way to import private functions anyway?

19:53 hyPiRion: private functions from java or clojure?

19:53 Sintendo: clojure

19:53 hiredman: well java doesn't have functions, it has methods

19:53 Sintendo: I guess not?

19:54 hyPiRion: Sintendo: Well, you could refer to the var

19:55 ,(#'clojure.core/>1? 1)

19:55 clojurebot: false

19:55 hyPiRion: ,(#'clojure.core/>1? 2)

19:55 clojurebot: true

19:55 Sintendo: well, i guess it's easier to just make them public

19:56 hyPiRion: yeah

19:56 Sintendo: thanks

19:56 abp: hiding my functions, so I can call on vars

19:57 benkay: datomic chan x-post: I have a "balance" i update in place in datomic, but when I query for that balance, I keep getting a list of the past balances. what's the idiomatic query format to request just the most recent datom?

19:57 abp: Sintendo: Not making fun of you, just thought it's a funny phrase. :)

19:58 benkay: bueller?

19:59 Sintendo: No problem dude, thanks for the help!

20:06 technomancy: it's basically a slap in the face that clojure's "could not find foo_bar.clj" message doesn't check for foo-bar.clj and advise you to rename it

20:06 * technomancy avoids estimating the economic cost of wasted hours

20:08 hiredman: benkay: my guess is you are defining a new entity and a new balance everytime you think you are "updating" the balanace

20:10 benkay: like you are trying to upsert, but inserting instead

20:11 benkay: hiredman that's totally possible. i'm definitely *trying* to upsert but i haven't quite wrapped my head around the syntax yet.

20:11 hiredman: you may need a :db/unique :db.unique/identity on whatever attribute you intend as a "primary key"

20:11 abp: technomancy: That's true for many of clojures exceptions until you know'em or at least how to diagnose. Also it's not easy to ignore unhelpful stacktraces and just find your mistake when still learning.

20:12 benkay: hiredman i *just* saw that in the halloway upserting gist that's floating around :)

20:13 hiredman: otherwise the only primary key is the entity id, which is often not known and basically treated as a gensym in transactions

20:18 technomancy: abp: yeah, that one is just outstanding in how easy it would be to offer helpful advice

20:21 benkay: thanks hiredman.

20:27 abp: hiredman: When will carica with middleware support be released?

20:27 hiredman: leathekd: ?

20:28 I don't know

20:29 leathekd: abp: I'll see what I can do. I don't believe there is anything else pending for 1.0.3

20:31 abp: leathekd: Cool, thanks. I've just written some middleware.

20:32 leathekd: Nice. What did you make?

20:33 technomancy: middleware?

20:33 hiredman: https://github.com/sonian/carica#middleware

20:34 technomancy: nice

20:40 abp: leathekd: I'm generalizing some environment-based config merging I wrote a while ago.

20:40 Wrote about it earlier in here.

20:40 Using middleware it's basically no code.

20:52 dnolen: bbloom: you look at React?

20:57 leathekd: abp: Cool, glad Carica is working out for you.

21:03 justin_smith: slightly OT: I am deploying a ring app to tomcat, and I am seeing messages about the app shutting down, but nothing in catalina.log indicating how or why it stopped - short of putting debug printouts all through my app is there something I can do to see what exactly is happening in tomcat when it autodeploys my war?

21:28 bbloom: dnolen: the new thing from facebook/instragram? not yet really

21:28 dnolen: did you? thoughts?

21:29 dnolen: bbloom: I didn't think it was very interesting until I read they operate on a virtual DOM model to minimize touching the real DOM for perf reasons.

21:29 bbloom: dnolen: yeah, the DOM is just slow: period.

21:31 we got lucky that the founders of the WWW escaped the brain dead OOP wave of the 90s, but that doesn't change the fact that the DOM is effectively a big mutable bag of callbacks (even internally) with naively O(N^3) algorithms that are arguably NP hard to optimize in the general case facing interactive mutation

21:31 :-P

21:32 also, i was instantly turned off by the XML preprocessor thing

22:04 amalloy: bbloom: n^3? what algorithm are you thinking of?

22:05 bbloom: amalloy: layout when js code is constantly updating positions & styles

22:06 i'm playing fast and loose with the formalities of that…. my point is that it's hard & made much harder by the fact that things are changing, animating, etc

22:16 ohpauleez: Is David Pollak in here?

22:18 pandeiro: would ring.middleware.json-params interfere with ring.middleware.multipart-params? i'm wrapping my entire app handler in compojure's site middleware, along with wrap-json-params on some API routes, and my multipart form POST requests are never getting added to :params/:multipart-params. can't figure out why not...

22:19 brehaut: pandeiro: i recall that they both consume :body, so yes they would

22:19 pandeiro: ring is *mostly* functional; :body is the exception, and can only be consumed once.

22:19 pandeiro: brehaut: makes sense

22:20 brehaut: pandeiro: however, it should respect your content type header?

22:20 pandeiro: huh, right, it should

22:20 but let me step back one step

22:20 even if the json-params are only being applied to some routes, that middleware would consume the body for any route?

22:21 that doesn't make sense actually because the multipart POST route comes before the json api routes

22:21 brehaut: if those routes are called, and content tpye matches, yes

22:21 pandeiro: but route specific handlers as setup by defroutes short circuit, right?

22:21 i noticed the source of routes or routing uses 'some'

22:22 brehaut: yeah

22:23 pandeiro: k i'm still at a loss then... must be something else i am doing

22:31 dnolen: wow as-> cond-> really allow you remove some serious grossness

22:36 pandeiro: ha

22:37 ring-multipart-params won't handle the input[type=file] if there is no name attribute

22:48 bbloom: dnolen: https://github.com/brandonbloom/ascribe <- a very early version of the attribute grammar thing i was showing you. I linked some of the literature in the readme if you're interested at all. lots more work locally in branches that i'm putzing with

22:49 dnolen: bbloom: link doesn't work?

22:49 bbloom: dnolen: lol try again

22:50 dnolen: apparently making it public took a second...

22:52 phyrephox: so i'm building a webapp using clojure and clojurescript

22:52 and i'm wondering if i can have some crossover code

22:53 that's the same code in clojure/clojurescript, but it does something different in clojure than in clojurescript

22:53 i.e. there's a macro in the crossover code, and it generates one set of code in CLJ and another set of code in CLJS

22:53 is this possible?

22:55 hmm, maybe i can use cljsbuild conditional comments?

22:55 hiredman: http://dev.clojure.org/display/design/Feature+Expressions

22:57 phyrephox: so this is a patch and/or an experimental feature? doesn't seem too useful

22:57 seems like a nicer solution than the cljs build comments though, that's for sure

22:58 dnolen: phyrephox: known pain point, maybe core.async will push it along, unclear

22:58 phyrephox: cool thanks. i actually think i can accomplish what i want to using the ;*CLJSBUILD-REMOVE*; thing

22:59 not an ideal solution, but once a better solution comes along i don't think it'll be too hard to refactor

22:59 dnolen: so much craziness in my projects to remove w/ as-> cond->

23:04 bbloom: dnolen: what about as-> and cond-> ?

23:04 dnolen: bbloom: remove repeated bindings to the same name in a let

23:05 which actually bit me a couple of times because it's not very functional

23:05 bbloom: heh, yeah, i find when you just stick a * or a ' on the end it can be confusing… especially around version*** three or so :-P

23:05 usually better to come up with clearer names or split up the function

23:22 TimMc: gfredericks: Are you sure that what you want for clem isn't Erlang? :-)

23:28 bbloom: i <3 clojure's data types so much

23:28 where other people painstakingly create these data models & hand code all these behaviors in to them, i just grab some maps and vectors & everything just frickin works

23:46 tomjack: "Declarative" then the second example is "A Stateful Component" hmm

23:47 dnolen: bbloom: that feature of Clojure cannot be understated

23:48 bbloom: dnolen: it's totally mind altering. i don't even know how i used to write software like a year ago :-P

23:50 dnolen: tomjack: yeah overall not interesting. But I think the virtual DOM + requestAnimationFrame could be promising for CLJS

23:50 or for some CLJS lib

23:50 I mean

23:51 tomjack: I really don't understand "virtual dom"

23:52 dnolen: tomjack: touching the DOM is expensive so you manipulate a virtual representation instead

23:53 you accumulate changes, then you do a bulk update

23:53 alisdair: all problems in computer science can be solved with another layer of indirection

23:54 tomjack: dnolen: so that's pretty much just "use data" right

23:55 dnolen: tomjack: yes

23:57 xeqi: wonder how that helps with Phil Karlton's problems

23:58 bbloom: dnolen: as you know, i've been experimenting with that bulk update model. so far it seems pretty nice, but i've only made small prototypes

23:58 dnolen: bbloom: yeah that's I mentioned it to you earlier

23:58 that's why

Logging service provided by n01se.net