#clojure log - Jun 14 2011

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

0:21 [mattb]: what's the function to use a vector as arguments to a function instead of as a vector?

0:22 jedi: apply?

0:23 [mattb]: hmm thanks

0:26 ahh perfect thanks

2:08 Vinzent: When I'm adding ring's middleware wrap-file, e.g. (wrap-file "public"), it throws exception unless directory public is in the project root, but I have to place this folder in the 'war' for gae

2:11 I've look in the source and it looks like there is no way to specify other root directory. Is this a bug or am I missing something?

2:57 I've got following exception when tried to run `lein appengine-prepare`: Exception in thread "main" java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :name (actions.clj:117). The code works when I'm compiling it in emacs\slime, but throws the same exception when compiling with lein.

2:57 Here is the code: http://paste.lisp.org/display/122617

2:59 So, it looks like the macro doesn't expands when it compiled with lein. Leiningen 1.5.2 on Java 1.6.0_24; appengine-magic 0.4.1; swank-clojure 1.3.1. Any ideas?

3:04 hoeck: Vinzent: no ideas, I'd try to isolate the problem further, e.g. trying wether other macros are expanding or not expanding, or putting a println trace into the macroexpansion code

3:05 Vinzent: or cleaning old classes first? (but I assume lein does that already before each compile)

3:08 Vinzent: hoeck, cleaning does not help, let me try it with the new project...

3:09 by the way, lein compile takes more time than it should usually take, and CPU load is near 0 all the time, that's strange

3:14 hoeck: Vinzent: compared to (what means 'usually')?

3:15 Vinzent: hoeck, compared to other projects approximately the same size

3:16 hoeck: other appaengine-magic projects?

3:18 macroexpansion/compilation happens in a full clojure environment, so macros may do blocking io, start other processes ...

3:18 Vinzent: maybe... I'm not sure. Maybe it's just subjective impression

3:19 Yes, I've checked it, other project also compiles long

3:55 Null-A: I just wrote a LLVM frontend in clojure :)

4:14 Vinzent: Well, now i've got java.io.InvalidClassException: com.google.appengine.api.datastore.dev.LocalDatastoreService$Profile; local class incompatible

4:40 tsdh: What's the proper way to set *print-length* for my tests?

4:43 Vinzent: tsdh, fixtures?

4:43 tsdh: Vinzent: I don't even know what that is. Any pointer?

4:44 raek: tsdh: do you mean in a test framework or when tring stuff at the repl?

4:45 Vinzent: tsdh, if you are using clojure.test - http://richhickey.github.com/clojure/clojure.test-api.html

4:45 tsdh: raek: Yes, clojure.test tests.

4:45 Vinzent: Thanks.

4:46 raek: tsdh: why do you need to print in your test code?

4:46 tsdh: you can change the value of the var with 'set!' and 'binding'

4:47 Vinzent: My appengine app works with dev_appserver.sh, but after deploying on the google servers throws java.lang.NoClassDefFoundError: Could not initialize class aquatour.app_servlet

4:47 tsdh: raek: I don't. But I have a failing test that asserts the equality of two large maps. Since they are not equal, that'll print both on the console which is really not helpful.

4:50 raek: tsdh: a (set! *print-length* 5) at the top of the test file might be a workaround

4:50 tsdh: raek: I'm just checking fixtures, which might be better here, cause I don't want to change anything just because of the test files get loaded.

4:56 (use-fixtures :once (fn [f] (binding [*print-length* 5] (f)))) does the trick. Thanks, Vinzent.

4:57 Vinzent: tsdh, np

4:59 tsdh: When I have a seq of the form ([k v] [k v] ...), what's the best way to transform it into a map? (apply hash-map (flatten myseq))?

5:00 Vinzent: (into {} ([k v] [k v] ...))

5:01 tsdh: Vinzent: Thanks

5:04 Vinzent: I've ran `lein appengine-prepare`, then launched dev_appserver.sh and all works good, but I've got following exception after deploying it to the google servers: java.lang.NoClassDefFoundError: Could not initialize class aquatour.app_servlet. Full stacktrace can be found here: http://pastebin.com/R5bcaDPG. What the promlem might be?

5:05 I've googled that such exception can be thrown when some restricted classes are in use, but I've remove all things that possibly might use IO or threads

5:11 gko: Hey, I have problems with log4j... I have many loggers, and sometimes, stuff that should go in file A goes in file B and vice-versa... (I use directly Java interop, not clojure wrapper)

5:31 hoeck: Vinzent: and the war contains an aquatour/app_servlet.class ?

5:56 clgv: I have a recursion of a function f via an indirection of function g, like: 1 x call(f) -> 1 x call(g) -> k x call(f)

5:56 how can I implement that one easily without blowing the stack?

5:56 bendlas: clgv: have a look at trampoline

5:56 clgv: I can't eliminate function g since the code would get really awkward then

5:57 bendlas: ,(doc trampoline)

5:57 clojurebot: "([f] [f & args]); trampoline can be used to convert algorithms requiring mutual recursion without stack consumption. Calls f with supplied args, if any. If f returns a fn, calls that fn with no arguments, and continues to repeat, until the return value is not a fn, then returns that non-fn value. Note that if you want to return a fn as a final value, you must wrap it in some data structure and un...

5:58 clgv: bendlas: I thought about that but it doesnt quite work here. it seems more fitting for direct mutual tail recursion

5:59 ohz there is an error in it. g only calls f on a finite sequence as long as f failed to do its job

6:00 bendlas: i don't quite understand

6:00 can you explain by example?

6:00 clgv: I could try to do it the lazy-way to avoid the stackoverflow.

6:01 I have a tree I do walk and change the elements in there. clojure.walk can't be used unfortunately.

6:01 bendlas: have you looked at zippers?

6:02 clojure.zip

6:02 clgv: I did, but didn't find any example that might work on my case. you know good examples for the use of zippers?

6:03 Vinzent: hoeck, war contains lib/aquatour.jar, which contains aquatour/app_servlet.class. Sorry for the delay, I was afk

6:03 bendlas: I've only seen a presentation about it, but you seem to be able to move in any direction in the tree and replace elements

6:03 while getting the modified tree lazily afterwards

6:04 clgv: I am not quite sure that the code will get easier/shorter with the navigation approach in this case

6:05 bendlas: ok, so you're doing the tree recursion yourself and try to not consume stack .. alright

6:06 clgv: yes. since I do not know whether the tree depth remains small enough

6:06 bendlas: i figure the easiest way in that case, is to build a tree of lazy seqs

6:07 clgv: &(doc for)

6:07 sexpbot: ⟹ "Macro ([seq-exprs body-expr]); List comprehension. Takes a vector of one or more binding-form/collection-expr pairs, each followed by zero or more modifiers, and yields a lazy sequence of evaluations of expr. Collections are iterated in a nested fashion, rightmost ... http://gist.github.com/1024621

6:11 bsteuber: I noticed http.agent has gone from the contrib standalone alpha - do you know where it went?

6:11 hoeck: Vinzent: if lein did that, its probably ok, though I remember that putting jars inside jars was not really possible (thats why uberjar exists), but google appengine might do things differently

6:49 Vinzent: hoeck, there is no jars inside jars; I have only dirs/class-files in aquatour.jar (and war is just a dir too). Appengine-magic generate all this files

7:28 clgv: &(doc cons)

7:28 sexpbot: ⟹ "([x seq]); Returns a new seq where x is the first element and seq is the rest."

7:29 clgv: is there an actual english verb for "cons"

7:29 ?

7:29 manutter: iirc it's just an abbreviation for "construct"

7:30 as in "construct a list out of these two nodes"

7:30 the closest English verb would be "prepend" I guess

7:31 clgv: ah right. prepend sounds fine :)

7:31 prepend to s.th.?

7:32 manutter: right

7:32 "prepend x to seq to produce a list"

7:32 or whatever, haven't had my coffee yet, dimly mixing Clojure vocab with LISP vocab

7:32 clgv: just found a use case for when-let with more than one binding

7:33 Somelauw: I decided to give setting up swank + clojure + cake + slime another go.

7:33 Is this the right place to ask questions about setting that up?

7:33 manutter: sure

7:33 but i'm not the one who can answer them :)

7:34 Somelauw: Okay, well I installed cake and followed the instructions here: https://github.com/ninjudd/cake/wiki/Swank

7:34 So I entered cake swank -r 4007 in a terminal.

7:35 And in emacs I entered slime-connect, I choose and as a port I entered 4007.

7:35 clgv: Somelauw: I heard about a starterkit and a tutorial how to use it here several times. maybe you can search the logs of this channel for the link

7:35 Somelauw: Emacs said versions differ and asked me whether I wanted to contrinue.

7:36 I confirmed.

7:36 I tried entering 5 and pressing enter, but nothing happened.

7:36 I already have emacs starterkit installed.

7:36 bsteuber: Somelauw: so you have a repl?

7:36 manutter: Did you get a slime buffer with a user=> prompt?

7:37 (aka a repl, like bsteuber said)

7:37 Somelauw: yes

7:37 Well when I restart it entering 5 and pressing enter works.

7:38 And entering println will echo #<core$println clojure.core$println@1ea3f672>.

7:38 So those work.

7:38 But entering (println "hello") will make it hang.

7:39 the-kenny: I think I had a problem like this some months ago

7:39 Can't say what fixed it, sorry. Probably a re-installation of slime

7:39 Somelauw: Maybe it will hang as soon as I use parentheses?

7:39 Does emacs have an update-slime-version-command or something?

7:40 bsteuber: Somelauw: are there any error messages in the *Messages* or *slime-events* buffer?

7:40 manutter: Might be a version mismatch -- are you using [swank-clojure "1.2.1"] or [swank-clojure "1.3.1"] in your dev-dependencies?

7:40 the-kenny: Somelauw: Oh, I have a possible fix for this in my .emacs: (setq slime-redirect-inferior-output nil)

7:41 Somelauw: Try M-S-: and enter the stuff I wrote above, then restart the slime connection

7:41 Somelauw: Yes, messages say: Versions differ: 2010-12-02 (slime) vs. 20100404 (swank)

7:43 manutter: Sorry, I meant the swank-clojure version -- you can safely ignore the Emacs warning about slime version vs swank version

7:43 (There's a trick for turning off the warning, but I forget what it is.)

7:44 I'm talking about the :dev-dependencies line in .cake/project.clj (step 2 of the Cake How-To at https://github.com/ninjudd/cake/wiki/Swank)

7:45 Somelauw: the-kenny: It didn't work. I did it by slime-disconnect, slime-connect. I didn't restart my swank.

7:45 manutter: You should be using swank-clojure "1.3.1" instead of version "1.2.1" -- the wiki is slightly out of date

7:45 Somelauw: manutter: I was using 1.2.1

7:45 I was doing what the wiki said.

7:45 manutter: try changing your project.clj, then pick up with step 3 of the wiki

7:45 the-kenny: Somelauw: hm :( I'm pretty sure this line fixed this bug for me a few months ago

7:45 Somelauw: I will try 1.3

7:47 manutter: And just by the way, you might also be interested in jark -- http://icylisper.in/jark/start.html

7:49 clgv: manutter_ what do you use jark for?

7:50 manutter: right now just quick one-offs

7:50 Somelauw: It works for a single command and then it closes the connection Lisp connection closed unexpectedly: connection broken by remote peer

7:50 manutter: I actually only use leiningen/emacs for serious development

7:51 Somelauw: hmm, sounds like something is amiss in your setup

7:51 Somelauw: why is this program so painful?

7:51 manutter: what version of emacs are you using?

7:51 Somelauw: emacs 23.1.1

7:51 clgv: manutter: jark sounds interesting - just read its "why?" page

7:51 manutter: Somelauw: you said you have some kind of starter kit installed in emacs?

7:51 Somelauw: Exactly: GNU Emacs 23.1.1 (x86_64-pc-linux-gnu, GTK+ Version 2.22.0) of 2011-03-04 on yellow, modified by Debian [2 times]

7:53 manutter: clgv: I do like the basic premise of jark, and I'd like to write some local scripts that take advantage of it

7:54 in all honesty, though, it's just a big shiny hammer looking for a nail right now

7:54 for me anyway

7:55 Somelauw: manutter: yes, starterkit

7:56 manutter: Somelauw: I'm not sure I've heard of that one, but it makes me suspicious

7:57 raek: Somelauw: how did you install slime?

7:57 Somelauw: http://eschulte.github.com/emacs-starter-kit/

7:58 manutter: It might be perfectly good code, but even perfectly good code can be incompatible with other perfectly good code, if you know what I mean

7:58 clgv: manutter_ after reading through the page, I'd say the scripting is the most interesting part of this project :=

7:58 raek: Somelauw: I recommend this version: https://github.com/technomancy/emacs-starter-kit

7:59 Slime does not do releases, so it breaks for swank-clojure quite often

7:59 Somelauw: raek, I don't remember exactly. I installed it a long time ago to make it work with CL.

7:59 raek: to me it sounds like you have a "too new" version of slime

8:00 manutter: clgv: Yeah, it's got some interesting possibilities.

8:00 Somelauw: raek: that was the version I got. I installed it by doing a checkout from git and following the instructions.

8:00 raek: with the new clojure-jack-in approach, swank-clojure comes bundled with a version of Slime that works

8:01 Somelauw: slime or emacs-starter-kit?

8:01 manutter: Somelauw: it looks like the starter kit is tuned more towards CL than Clojure, and that may be where the incompatibilities are coming from

8:01 Somelauw: raek: how to get the new clojure-jack. Is there a single script or something that fixed everythin.

8:01 manutter: more towards CL/elisp, I should say

8:02 raek: Somelauw: it is a part of the newest clojure-mode.el which uses leiningen to start the swank server

8:02 Somelauw: raek: emacs-starter-kit. I don't remember how I installed slime. I think you can just do package-install slime or something.

8:02 raek: installing it from package-list-packages soudns right

8:02 the OS packet manager version of slime is what I know causes problems

8:02 manutter: Somelauw: I'm guessing all your starter-kit stuff is going to be either in your .emacs file or your .emacs.d directory

8:03 If you want to experiment, you should be able to back those up somewhere safe, then nuke them and install clean/empty versions.

8:03 Somelauw: I don't know how I installed it. It might be the case that I installed it by aptitude. Actually I will check what aptitude says when I search for slime.

8:04 raek: Somelauw: re "clojure-jack-in": http://technomancy.us/149

8:04 Somelauw: Okay. It seems like I installed slime by aptitude.

8:04 raek: but since you use cake, it might not be what you were looking for

8:06 manutter: judging from the cake install wiki, I'd guess that the slime/swank stuff should be compatible with clojure-jack-in

8:06 raek: Somelauw: that is probably it. here's another tutorial (non clojure-jack-in and cake/lein neutral): http://dev.clojure.org/display/doc/Getting+Started+with+Emacs

8:06 Somelauw: I hardly know the difference. I heard cake doesn't start a new process every time. So that was the reason I choose cake over leiningen.

8:07 manutter: leiningen only pays the start-up penalty when you first launch swank, so in practice I haven't found it that big of a handicap

8:08 Somelauw: Okay, there is a lot of information. (Maybe too much). And it's hard to judge which information is out of date or not and information from different websites isn't compatible with each other.

8:08 manutter: That's definitely true

8:08 Somelauw: Maybe I should delete anything emacs / clojure / swank related and follow one website that definitely works and is completely up to date and everything.

8:08 manutter: #clojure is the best answer I've found for that problem :)

8:09 Yeah, back up your ~/.emacs and ~/.emacs.d

8:09 then you can create new, empty ones and start from a clean slate

8:09 you can always go back just by restoring your backups

8:09 raek: Somelauw: phil's recent post and the dev.clojure.org wiki are the most up to date, imho

8:12 Somelauw: Are they compatible with each other?

8:15 manutter: I'd go with Phil (technomancy) as far as swank-clojure is concerned, since he's da man, but the dev.clojure wiki should be compatible with what he says

8:15 Somelauw: I will first try to remove slime by aptitude and then install with package-install from within emacs first? If it doesn't work, I will folow Phil's post step by step I think.

8:16 manutter: I've gone back and ripped out a bunch of emacs stuff so I could follow Phil's post from scratch, and it has worked pretty well for me

8:16 I think I did have to hand-edit my .emacs to get the changes to stick, though

8:17 that was just (add-to-list 'load-path "~/.emacs.d") (require 'clojure-mode) though

8:19 raek: Somelauw: the only difference from the old and new (clojure-jack-in) approach is that you don't have to install Slime anymore and that you can start the swank server and connect to it in one step

8:20 but how to install clojure-mode should be compatible

8:20 the jack-in approach doesn't really care _how_ clojure-mode is installed

8:20 Somelauw: I don't need slime anymore?

8:20 manutter: You don't need to manually install it any more

8:21 Somelauw: What if it is already installed?

8:21 raek: clojure-jack-in loads it from the swank-clojure jar, which includes a fitting version

8:21 Somelauw: that I don't know :)

8:21 manutter: Yeah, I'd be suspicious that you might have issues if there was an incompatible version already installed

8:21 I think I'd do the apt-get remove slime just to be safe

8:22 raek: Somelauw: having the slime debian package would probably cause problems

8:23 currently, this new feature seems to be bound to leiningen: https://github.com/technomancy/clojure-mode/blob/master/clojure-mode.el#L833

8:24 * the-kenny loves the comment "graaaahhhh--no closures in elisp (23)"

8:25 manutter: heh, saw that

8:25 Somelauw: I'd recommend trying leiningen instead of cake, I think it may make life easier for you

8:26 I think cake is for people who already know and love rake (Ruby)

8:26 then again, you could be one of them, so ymmv

8:27 Somelauw: I am not a ruby programmer.

8:28 Anyway, when removing slime from aptitude it still isn't completely removed for some reason.

8:28 Maybe I should rename my emacs.d

8:28 manutter: Sounds like a good idea

8:29 also rename your .emacs, if there's any code in there at all

8:30 raek: for me, emacs-started-kit does not load if I have a .emacs file present

8:30 so I put personal customizations in ~/.emacs.d/<username>.el instead

8:33 void_: do you people use Sandbar? (https://github.com/brentonashworth/sandbar)

8:33 manutter: I've used it, but I'm considering a switch to Swing Security

8:34 void_: I would like to implement simple auth for admin interface

8:34 manutter: listen do me, doh... SPRING Security

8:35 void_: isn't that Java lib?

8:35 because google "spring security clojure" gives me nothing

8:35 manutter: http://static.springsource.org/spring-security/site/

8:35 yeah, it's a java lib

8:35 shouldn't be too hard to put a wrapper around it

8:35 void_: meh I dunno :P

8:35 looks to java-ish

8:36 manutter: Somebody on this channel was saying it was dead simple

8:36 void_: oh

8:36 manutter: I think it was fogus

8:36 clgv: void_: write your own clojure wrapper ;)

8:36 manutter: or maybe cemerick

8:36 but it was somebody whose name I recognized

8:37 Sandbar is interesting though, and I've got it working without too much trouble

8:37 void_: clgv: actually I find that to be the easiest, just add header asking for http-basic-auth ... but then again, I don't feel like hacking right now, just want to see it working ;)

8:37 manutter: The problem I had with it was if something goes wrong, good luck trying to trace back through all the macro-generated code to figure out where you went wrong

8:38 clgv: manutter: sounds like they need more debug info on errors. maybe a task for :pre :post?

8:39 do bigger projects use *assert* and :pre, :post really?

8:40 manutter: I couldn't say

8:40 Somelauw: Maybe I would appreciate a good commandline debugger for clojure like gdb or something.

8:40 Anyway that jack-in mode thing is working.

8:40 manutter: :D

8:41 I haven't dared try the command line debuggers yet

8:41 Somelauw: Unfortunately, I renamed my emacs.d so my starterkit is gone.

8:41 manutter: George Jahad has some good stuff going on but I found it all a bit intimidating

8:41 Somelauw: Maybe I will rename my emacs.d again one day and try to merge them.

8:41 For now I am done.

8:41 manutter: google for cdt (clojure debugger toolkit) -- I think that's what it's called

8:42 but I'm using that good old-fashioned debugger: println

8:42 :)

8:42 Somelauw: Does clojure have some sort of (eval (user-input)) command for debugging or something, so I can print random variables?

8:42 Like a breakpoint?

8:43 manutter: It's not built into the repl, but I think cdt supports that

8:43 void_: Somelauw: you can just say '(clojure.main/repl)'

8:44 &#"string"

8:44 sexpbot: ⟹ #"string"

8:44 void_: &"string"

8:44 sexpbot: ⟹ "string"

8:44 void_: what's the # at the beginning?

8:44 Somelauw: It prints user=>nil

8:45 void_: Somelauw: well, for me it starts repl

8:45 wherever I call it

8:45 very useful for debugging

8:45 manutter: void: #"foo" is a regular expression

8:45 void_: oh yeah

8:45 right

8:45 next time I'll just do this:

8:45 &(type #"foo")

8:45 sexpbot: ⟹ java.util.regex.Pattern

8:46 void_: I saw # at many places and I'm quite confused

8:46 manutter: The (clojure.main/repl) command launches a new repl -- it's useful if you're running, say, a remote web server or something, but it doesn't really do much if you run it from within the repl

8:46 it just returns nil

8:46 Somelauw: void_, okay that works as well

8:46 the-kenny: For remote stuff, starting a swank-server is very useful

8:47 Somelauw: But I was already inside a repl.

8:47 manutter: right, I think you and void_ were talking slightly at cross-purposes

8:47 void_: the-kenny: swank-server is emacs integration thingie, right?

8:47 the-kenny: void_: Yes

8:48 void_: the-kenny: is there any way to use it from command line? (I'm not using emacs)

8:48 but I would very much like that: Start a clojure app, and just connect to it and control it.

8:48 the-kenny: void_: Yeah, that's what swank does :) However, I'm not aware of any command line swank client.

8:49 void_: ha! https://github.com/astine/swank-client

8:49 the-kenny: heh, nice catch.

8:50 void_: I feel so lame for not using emacs right now :)

8:50 the-kenny: You are ;-P

8:50 manutter: lol

8:51 Somelauw: I use it right now (but I don't feel comfortable using it)

8:54 * cemerick is lame too, then ;-)

8:55 clgv: what does cemerick use?

8:55 cemerick: Eclipse + ccw

8:56 clgv: lol right. obviously. I feel so lame for not considering context information ;)

8:56 Somelauw: Also when I want to launch the clojure repl another time. Can I just do switch to a project and do clojure-jack-in?

8:56 Well, thanks for helping me getting it to work.

8:56 manutter: Somelauw: you should, but on my system, I had to add a couple lines to .emacs

8:57 They were real simple, though: (add-to-list 'load-path "~/.emacs.d") (require 'clojure-mode)

8:58 Somelauw: But when creating a .emacs, will it ignore my .emacs.d which contains clojure-mode?

8:58 clgv: cemerick: I talked to you about nrepl and ccw lately but forgot that for the moment of the question... ;)

8:59 cemerick: I can't expect people to retain a catalog of what I use for tools.

8:59 Though some might say I make it hard for them to forget… ;-)

9:01 manutter: cemerick: do you by any chance use Spring Security for web apps?

9:01 cemerick: manutter: I do, yes.

9:01 clgv: cemerick: but if you do development for it, it's not too far-fetched ;)

9:02 manutter: we were just talking about Sandbar, and I mentioned I thought I heard someone say they used Spring Sec for auth

9:02 there's no clojure lib for it, right?

9:03 cemerick: No, but I'm not sure what a clojure wrapper would bring to the party.

9:04 manutter: I haven't actually tried to do anything in it yet, but from my initial reading it seems like most of the config is done in XML files, right?

9:05 so maybe a lein plugin to map a more clojure-y syntax to the proper XML?

9:05 cemerick: Yeah, probably 80% of the work.

9:05 * cemerick screams silently

9:05 cemerick: transliterating XML to sexprs silly IMO

9:06 manutter: heh, ok fair enough

9:07 cemerick: I mean, having that would probably make spring-security the first choice for clojure web apps (being able to choose from N authentication mechanisms out of the box is very handy), but it's cringe-worthy nonetheless.

9:07 manutter: So basically you just import the jar and set up the xml file and spring security does the rest

9:07 as it is now, I mean

9:08 is that all there is to it, or am I missing something?

9:09 cemerick: If you have your user information in a form it has an implementation for (e.g. a "standard" user table in a sql database), then yes.

9:09 Otherwise, you need to implement one interface and refer to it in the XML.

9:09 manutter: yeah, that does sound pretty painless.

9:09 cemerick: http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/core/userdetails/UserDetailsService.html

9:10 the-kenny: <clojure>(ns foobar) (defn bla [] 42)</clojure>

9:10 manutter: I think I'm going to switch my app from Sandbar to spring-sec

9:10 cemerick: I'll probably blog about spring-security at some point. It's been pretty nice to work with, and is *very* deep feature-wise.

9:11 One of those domains where I'm happy to have some clear "templates" to follow for various options — I'm no security expert, and being able to google "openid spring-security" (or whatever) and get a step-by-step is a win for me.

9:12 manutter: Yeah, it's nicer (and safer) to be able to use an industrial grade auth system instead of having to roll your own.

9:12 raek: Somelauw: if you installed clojure-mode using package-list-packages, it gets loaded automatically

9:13 manutter: Yeah, I installed clojure-mode manually, that's why I had to manually edit my .emacs

9:14 raek: Somelauw: and yes, having a .emacs will cause emacs-starter-kit to not load, so put that stuff in .emacs.d/<your user id>.el instead

9:17 clgv: for a tree consisting of maps is there any "diff-tool", e.g. (diff map1 map2) ;=> {[:foo :bar] {10 20}, [:alpha] {0.5 0.1}} or something similar

9:19 manutter: not that I know of, but I just got a great idea for a question for 4clojure.org...

9:19 hoeck: clgv: that is an active research topic :)

9:20 I found some promising papers, but had no time implementing them so far

9:21 one of them http://portal.acm.org/citation.cfm?id=1600197&dl=ACM&coll=DL&CFID=27504367&CFTOKEN=97907319

9:21 clgv: hoeck: ah well. "research" almost sounds too much in this case. I would just need a literal comparison ;)

9:22 manutter: You mean something analogous to the way "intersection" works on sets?

9:22 hoeck: clgv: a naive approach then would be to 'diff' a flattened tree or 'diff' the same notes

9:22 raek: wasn't there a clojure test framework that shows the diff if an assertion fails?

9:23 chouser: yeah, lazy-test does that

9:23 clgv: hoeck: yeah a naive approach is desired. I don't care about possbile reordering in collections that have no order constraints or anything more advanced ;)

9:23 clojurebot: You don't have to tell me twice.

9:23 clgv: clojurebot: I did not talk to you! :P

9:23 clojurebot: Titim gan éirí ort.

9:24 manutter: we need a botsmack to go along with botsnack

9:30 clgv: hmm trying to find the diff-code in lazytest... but it's not that easy.

9:30 raek: clgv: https://github.com/clojure/clojure/blob/master/src/clj/clojure/data.clj#L104

9:30 report.clj uses that one

9:30 clgv: :added "1.3" is a little problem ;)

9:32 but I can copy the whole thing for noew.

9:32 raek: hrm. does lazy-test work with clojure 1.2?

9:32 clgv: I don't know.

9:34 Somelauw: raek: I installed clojure-mode this time by cloning the git like the website said.

9:38 I will try to get it work with starterkit another time.

9:38 clgv: clojure.data/diff seems promising :)

9:40 Somelauw: I think I have been logged in for 2 hours now.

9:42 clgv: I like it :)

9:42 manutter: ,(doc clojure.data/diff)

9:42 clojurebot: Gabh mo leithscéal?

9:43 clgv: manutter: it is clojure 1.3

9:43 manutter: Ah, that explains why the docs are in Gaelic :)

9:46 clgv: manutter: I simply copy&pasted it for now ;)

9:49 except one could specialize it for the only-map case to have a shorter output. it's quite verbose atm ;)

9:49 void_: in compojure, is there any way of getting request URI other than this: (GET "/" [request] (println request))

9:49 I need request URI in my layout, and I don't want to pass it to layout from each function that handles request

9:59 manutter: void_: I think there's something useful in the compojure wiki on destructuring

9:59 I remember seeing an example for how to get the uri, but I don't remember the code off the top of my head

10:02 edoloughlin: void_: (GET "/" {uri :uri} (println uri)) ; should do it - you're destructuring on the request map itself

10:03 void_: I know, the thing is I don't want to do that all the time

10:03 I'm looking for something like global request object?

10:03 I think I'll have to create a middle ware

10:04 edoloughlin: void_: probably.

10:04 gfrlog: void_: you're trying to get the ring request object in a compojure route?

10:06 void_: nevermind I might not have much to add

10:10 void_: do you usually write a middleware for layout?

10:17 gfrlog: void_: One time I handled it with a view macro. So all my views started with (defview ...)

10:18 ilyak: ,(flatten #{1 3 7 9})

10:18 clojurebot: ()

10:18 ilyak: Why?

10:18 clojurebot: why not?

10:18 ilyak: Because

10:18 gfrlog: ,(doc flatten)

10:18 clojurebot: "([x]); Takes any nested combination of sequential things (lists, vectors, etc.) and returns their contents as a single, flat sequence. (flatten nil) returns nil."

10:18 gfrlog: ,(sequential? #{1 3 7 9})

10:18 clojurebot: false

10:19 gfrlog: undefined behavior I guess

10:19 ilyak: ,(doc sequential?)

10:19 clojurebot: "([coll]); Returns true if coll implements Sequential"

10:19 gfrlog: apparently flatten is only meant for sequential things

10:19 ilyak: Doesn't make sense, to be fair

10:19 gfrlog: ,(flatten (seq #{1 3 7 9}))

10:19 clojurebot: (1 3 7 9)

10:19 ilyak: As Orwell said

10:19 \

10:20 "I understand how but I don't understand why"

10:20 or whatever

10:20 Okay, I'll map seq it for sure

10:20 gfrlog: :) I don't understand it either, but I suspect there's a reasonable reason

10:20 ,(flatten "what about strings?")

10:20 clojurebot: ()

10:21 ilyak: flatten should be (fn [arg] (flatten (map seq arg)))

10:22 (dump-to #{} '(1 2 3) [4 5 [6 [7 8]]] #{1 3 7 9}) -> #{1 2 3 4 5 6 7 8 9}

10:22 my victory weapon

10:23 It's kind of map plus flatten plus into merged into a glob of happiness

10:24 gfrlog: oh dear

10:24 ilyak: Kind of "I love perl"

10:25 gfrlog: :)

10:25 ilyak: "I can write perl in clojure"

10:25 gfrlog: what do you get for (dump-to "" (range 20))?

10:25 ilyak: JK

10:25 #<CompilerException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IPersistentCollection (NO_SOURCE_FILE:0)>

10:25 But it's a cool idea

10:26 definitely need to evaluate

10:26 gfrlog: what the heck do you got going on? nested sets?

10:29 ilyak: Have a function returning a list of of x-es each containing a set of y-s

10:30 gfrlog: if I were writing flatten I would say it's unclear what you want in that case

10:30 ilyak: But now I see that dump-to can replace a lot of code

10:30 gfrlog: since (reduce merge ...) would give you something different from (flatten (map seq ...))

10:31 ilyak: ,(merge #{1 2 #{3 4}})

10:31 clojurebot: #{1 2 #{3 4}}

10:31 ilyak: ,(flatten #{1 2 #{3 4}})

10:31 clojurebot: ()

10:31 ilyak: sigh

10:31 I really want this to work

10:32 My dump-to fails too :(

10:33 I like blanket operations like dump-to because they are declarative in the essense

10:33 You start to think in the terms "I want `foo'" instead of "I need to do krible, krable, bumble to produce `foo'"

10:39 manutter: ,(doc clojure.walk/walk)

10:39 clojurebot: "([inner outer form]); Traverses form, an arbitrary data structure. inner and outer are functions. Applies inner to each element of form, building up a data structure of the same type, then applies outer to the result. Recognizes all Clojure data structures except sorted-map-by. Consumes seqs as with doall."

10:41 manutter: ,(clojure.walk/walk seq flatten '(1 2 3) [4 5 [6 [7 8]]] #{1 3 7 9}) )

10:41 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (5) passed to: walk$walk

10:41 manutter: ah, cut-n-paste

10:42 ,(clojure.walk/walk seq flatten '((1 2 3) [4 5 [6 [7 8]]] #{1 3 7 9}))

10:42 clojurebot: (1 2 3 4 5 6 7 8 1 3 ...)

10:42 manutter: ilyak: ^^^

10:43 clgv: manutter: not bad ;)

10:44 finally another example of clojure.walk except from prewalk/postwalk

10:45 ,(clojure.walk/walk seq flatten #{1 2 3} [4 5 [6 [7 8]]] #{1 3 7 9}) )

10:45 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (5) passed to: walk$walk

10:45 clgv: ah k lol

10:45 manutter: clgv: that's three separate forms, wrap it in a list

10:45 I did the same thing :)

10:45 clgv: ,(clojure.walk/walk seq flatten '(#{1 2 3} [4 5 [6 [7 8]]] #{1 3 7 9})) )

10:45 clojurebot: (1 2 3 4 5 6 7 8 1 3 ...)

10:46 joly: ,(clojure.walk/walk seq flatten '((1 2 3) #{1 3 5 #{7 9}}))

10:46 clojurebot: (1 2 3 1 3 5 #{7 9})

10:47 manutter: doh, walk does not consider a set of sets to be a nested data structure

10:47 joly: :(

10:48 offby1: :( indeed

10:49 Maybe it's afraid that it'll encounter the set of all sets that do not contain themselves.

10:49 manutter: ,(seq #{1 2 3 #{4 5}})

10:49 clojurebot: (1 2 3 #{4 5})

10:50 manutter: ,(seq (seq #{1 2 3 #{4 5}}))

10:50 clojurebot: (1 2 3 #{4 5})

10:58 clgv: offby1: roflmao!

10:59 offby1: write that ones definition down in clojure ;)

11:00 stuartsierra: ,(into #{} (flatten '((1 2 3) irc://irc.freenode.net/#%7B1 3 5 irc://irc.freenode.net/#%7B7 9}}))

11:00 clojurebot: Unmatched delimiter: }

11:01 chouser: whoa, what?

11:01 manutter: I think that was an irc client cut-n-paste glitch?

11:02 offby1: I blame stuartsierra's cat.

11:02 stuartsierra: ,(flatten #{1 3 5 #{7 9}})

11:02 clojurebot: ()

11:02 stuartsierra: flatten doesn't understand seqs.

11:02 I mean sets.

11:03 manutter: ,(sequence? #{1 2 3})

11:03 clojurebot: java.lang.Exception: Unable to resolve symbol: sequence? in this context

11:03 manutter: doh

11:03 stuartsierra: ,(sequential? #{ 1 2 3})

11:03 clojurebot: false

11:03 manutter: I knew that...

11:04 offby1: that makes sense; sets are unordered, but flatten returns an ordered sequence, right?

11:04 stuartsierra: Try this: (defn flattener [x] (filter (complement coll?) (rest (tree-seq coll? seq x))))

11:04 ilyak: What's the cleanest way to figure out whether something is a collection in clojure?

11:05 stuartsierra: (flattener '(((1 2 3) #{1 3 5 #{7 9}})))

11:05 ;;=> (1 2 3 1 3 5 7 9)

11:05 ilyak: stuartsierra: It should accept [&x] not [x]

11:05 stuartsierra: I just copied `flatten` and replaced `sequential?` with `coll?`.

11:06 anyway, have fun, see y'all later

11:08 clgv: '-> is a macro pipe. is there something similar as a function?

11:08 joly: interesting, works with maps too

11:10 the-kenny: clgv: comp?

11:10 manutter: clgv: I think it has to be a macro, because -> re-writes the form

11:11 the-kenny: ,((comp :foo :bar) {:bar {:foo 42}})

11:11 clojurebot: 42

11:11 clgv: I hate it that I cant put an anonymous fn in ->

11:12 maybe I have to patch it^^

11:12 or use additional paranthesis

11:14 I wanted to thread the initial value param into a reduce

11:14 I guess I write a wrapper function for it, since I'll use it two times

11:15 ilyak: => (dump-to #{} 1 '(2 3) [4 5 [6 [7 8]]] #{1 3 #{7 9}})

11:15 #{1 2 3 4 5 6 7 8 9}

11:15 That's my weapon of victory

11:16 No need to flatten, no need to concat

11:16 I'm thinking of adding identity filter

11:16 so no need to (filter identity) ever too

11:16 clgv: ilyak: swiss army knife? ;)

11:18 ilyak: (dump-to #{} 1 '(2 3) [4 5 [6 nil [7 8]]] #{1 3 #{7 9}}) => #{1 2 3 4 5 6 7 8 9}

11:18 clgv: "I like perl"

11:21 clgv: ilyak: but when exactly do you need to throw away all structure?

11:22 ilyak: clgv: For example, when I have a function x -> y and a sequence of x's

11:22 clgv: I had only the other problem that flatten was throwing away too much structure since I only wanted "to flatten one level"

11:22 ilyak: (dump-to #{} (map x->y xs))

11:23 clgv: ilyak: I don't get it

11:23 dnolen: ,(apply concat [[1] [2] [3] [4 [5]])

11:23 clojurebot: Unmatched delimiter: )

11:23 clgv: is you function building structure you don't want?

11:23 dnolen: ,(apply concat [[1] [2] [3] [4 [5]]])

11:23 clojurebot: (1 2 3 4 [5])

11:24 clgv: dnolen: did that as solution to it but with reduce as far as I remember. ;)

11:28 ilyak: clgv: No, but every operation adds one layer of collections

11:28 since I don't have monads

11:28 Therefore I have to flatten it earlier or later

11:29 clgv: you know mapcat?

11:32 ilyak: Yeah, perhaps mapcat will do

11:32 Perhaps not when I have two such collections

11:33 I'll have to do concat mapcat

11:33 clgv: I think your functions are somehow implemented strangely when you don't get the structure you need in every step

11:34 ilyak: => (dump-to #{} 1 '(2 3) [4 5 [6 nil [7 8]]] #{1 3 #{7 9}} (Collections/singleton 10))

11:34 #{1 2 3 4 5 6 7 8 9 10}

11:34 even

11:35 clgv: They're just a -> b

11:36 and I need [a] -> [b] most often, or [[a]] -> [b]

11:37 raek: ,(for [x (range 10), :when (odd? x), :let [y (* x x)]] (+ x y)) ; for can also be an alternative to mapcat if you only use it to skip some elements

11:37 clojurebot: (2 12 30 56 90)

11:37 ilyak: I know

11:37 Perhaps it is

11:38 I'm just trying to create a wide abstraction to forget about some narrow tools

11:38 Cozey: Help! Jesus. I've spend hours trying to run a compojure app under ring with jetty, and now jetty whines about not SessionManager. anybody here know something about it ?

11:41 raek: Cozey: are you using the latest versions of both?

11:42 Cozey: Compojure 0.6.3 - is still using jetty6 - so not the newset

11:43 also, Compojure does not use HttpRequest.getSession(), since it normally uses it's own session mechanism (ring sessions)

11:43 raek: Cozey: if you look in the lib/ directory, do you have mixed versions of ring artifacts?

11:43 Cozey: but I have a scenario where I use 3rd party code in java (implementing servlet Filter) and it wants to do a plain old getSession

11:43 clgv: ilyak: but just as an remark: for me it sounds a bit unhealthy to build unspecified datablobs and then flatten them completely and hope that the right values fall out

11:44 Cozey: nope; ring 0.3.8 all the way jetty 6.1.26, compojure 0.6.3

11:44 I googled and it seems session configuration needs some kind of jetty 'WebContext', but I think ring jetty adapter completely bypasses this mechanism

11:47 basically jetty adapter uses first scenario http://docs.codehaus.org/display/JETTY/Embedding+Jetty

11:48 but then there is http://docs.codehaus.org/display/JETTY/SessionIds

11:48 some xml session configuration for jetty - but how to use it in ring-adapter scenario is beyond me

11:49 ilyak: clgv: In fact, I'm kind of imitating jquery's $()

11:49 which sounded dangerous but in fact turned out to be awesome

11:50 clgv: ilyak: maybe it's totally alright - I based my remark only on what I understood from your explanations ;)

12:14 rmarianski: Cozey: i wrote a ring jetty adapter that adds in a servlet to the request map

12:14 Cozey: https://github.com/rmarianski/ring-jetty-servlet-adapter

12:18 Fossi: been there, done that... :)

12:18 it's a bit hackish though that it isnt supported by ring in the first place

12:21 ilyak: What's the difference between :while and :when in (for?

12:23 chouser: as soon as :while is false, that loop ends

12:23 if :when is false, that iteration is skipped but the loop continues to the next one anyway

12:25 ilyak: Thanks

12:26 I miss :except

12:26 :when (not (something val)) is not cool

12:26 also wrote my own reject as filter not

12:28 chouser: 'remove'?

12:32 ilyak: chouser: Cool, thanks

12:32 no need to reject

12:33 flatten

12:33 has (filter (complement sequential?)

12:34 I guess it should instead have (remove sequential?

12:34 (defn flatten [x] (filter (complement sequential?) (rest (tree-seq sequential? seq x))))

12:35 I would say one can rewrite it as (defn flatten [x] (remove sequential? (tree-seq sequential? seq x)))

13:05 Cozey: ok. figured it out. one needs to add a SessionHandler as well as ServletHandler (containing clojure routes) to Server

13:25 redinger: Early registration has opened for Clojure Conj 2011: http://clojure-conj.org

13:26 manutter: drooooooool....

13:27 I missed it last year

13:34 amalloy: redinger: sweet. sad i missed last year's

13:34 redinger: amalloy: Hopefully we'll see you this year!

13:35 amalloy: redinger: for sure. now that i'm doing clojure for work i don't have much excuse

13:37 halfprogrammer: Is it allowed to send functions as optional keyword parameters?

13:37 s/allowed/ok

13:37 sexpbot: <halfprogrammer> Is it ok to send functions as optional keyword parameters?

13:38 amalloy: halfprogrammer: i don't understand the question, but the answer is yes

13:38 halfprogrammer: https://gist.github.com/1025409

13:38 amalloy: Can you please look at the gist?

13:39 amalloy: halfprogrammer: your recur is wrong in the first version

13:39 (recur (next lst) obj :testfn testfn), i think should work

13:39 myexists1 expects keyword args, and you're recurring without them

13:40 halfprogrammer: Mismatched argument count to recur, expected: 3 args, got: 4

13:40 amalloy: but i've never tried recurring with varargs so let me know if it fails

13:41 halfprogrammer: the code does not get compiled if I include :testfn

13:41 amalloy: yeah, i guess recur doesn't support varargs

13:42 * halfprogrammer wants default values for arguments in clojure

13:42 halfprogrammer: :(

13:43 amalloy: halfprogrammer: https://gist.github.com/1025420

13:43 gfrlog: (apply recur my-args)

13:44 halfprogrammer: gfrlog: how do i capture capture all the variables into my-args?

13:45 Should I go ahead and build such a list myself?

13:45 gfrlog: halfprogrammer: I apologize, it was a joke :)

13:45 you can't do that

13:45 halfprogrammer: :P

13:46 gfrlog: halfprogrammer: I think if you really want varargs w/ recur you have to change your function to take a single argument (list of args) instead

13:46 halfprogrammer: which is not too hard syntactically, thanks to destructuring

13:46 * halfprogrammer is so sleepy that he is not even able to get jokes :(

13:47 amalloy: halfprogrammer: does my gist make it clear that you can pass functions?

13:47 halfprogrammer: gfrlog: Of course that is doable and even amalloy's solution will work

13:48 amalloy: Your gist works thanks!

13:49 I really don't understand what was wrong with my my-exists1?

13:50 amalloy: halfprogrammer: recur is fairly primitive, and & {...} is a new-ish language feature. they don't seem to play nice together

13:50 halfprogrammer: amalloy: hmm

13:53 amalloy: if you replaced recur with my-exists1? it would probably also work

13:53 but blow the stack for large lists, of course

13:54 halfprogrammer: let me check if things work ok with my-exists1? instead of recur...

13:55 amalloy: yup, it works fine

13:56 amalloy: whew. it's always a relief when my untested assertions turn out to be true

13:56 halfprogrammer: lol

13:57 Is someone looking into this 'bug'?

13:57 With no support for default arguments in the language this would be irritating for recursive function.

13:58 dnolen: halfprogrammer: recur is like a goto, it not a real function call (otherwise would consume the stack). the whole vararg rest thing only applies to function calls.

13:58 halfprogrammer: did you try (recur (next lst) obj [:testfn testfn]) ?

13:59 halfprogrammer: (recur (next lst) obj [:testfn testfn]) doesn't compile

14:01 jweiss: isn't there a function in core, that given [1 2 3] will return [[1] [1 2] [1 2 3]]?

14:01 halfprogrammer: Information about number of possible keyword parameters will be available in the compile time itself right.

14:02 gfrlog: $findfn [1 2 3] [[1] [1 2] [1 2 3]]

14:02 sexpbot: []

14:02 amalloy: &(rest (reductions conj [] [1 2 3]))

14:02 sexpbot: ⟹ ([1] [1 2] [1 2 3])

14:02 jweiss: ah reductions

14:02 that is what i was trying to think of, thanks amalloy

14:03 gfrlog: Are there any clojure libraries for doing BDD-style testing of an html-ring-app?

14:03 because if not I'm about to try to make one

14:03 chouser: gfrlog: you've looked at midje?

14:04 gfrlog: chouser: no sir, but if google delivers then that is about to change

14:04 dnolen: halfprogrammer: (recur (next lst) obj {:testfn testfn}) works

14:04 chouser: google shall

14:04 amalloy: dnolen: that's bizarre

14:04 gfrlog: chouser: thanks for the tip

14:05 dnolen: amalloy: why?

14:05 halfprogrammer: dnolen: awesome. I don't know how you came up with that!

14:06 dnolen: halfprogrammer: well I looked a lot at IFn and the various tricks the compiler does to uphold to rest arg *fiction*

14:06 amalloy: it implies that loop is being replaced with (let ... (loop* )) rather than (loop* ... (let)), doesn't it? his loop binding-vec has an & in it

14:06 halfprogrammer: :P

14:06 lol

14:07 amalloy: oh, but he's not using loop, he's using the function as his recursion point directly

14:07 that makes it less bizarre

14:08 &(macroexpand '(loop [x 1] (recur (dec x))))

14:08 sexpbot: ⟹ (loop* [x 1] (recur (dec x)))

14:08 amalloy: &(macroexpand '(loop [[x] [1]] (recur (dec x))))

14:08 sexpbot: ⟹ (let* [G__9884 [1] vec__9885 G__9884 x (clojure.core/nth vec__9885 0 nil)] (loop* [G__9884 G__9884] (clojure.core/let [[x] G__9884] (recur (dec x)))))

14:12 gfrlog: looked at midje...think I'm going to try making my own thing

14:13 trptcolin: speclj is another solution that's more familiar to folks coming from Ruby

14:14 gfrlog: hmmm :-/ I'm not so much interested in the style of the tests as I am in a bunch of html assertions and manipulations

14:15 it's something I made before that felt terribly intuitive and simple

14:16 jweiss: anyone know of a clojure test harness for functional testing? all the frameworks i've seen are unit tests only.

14:17 i'd like something like testng for java, but not dependent on precompiled classes with java annotations

14:18 halfprogrammer: Almost midnight here @India. going to bed. see you guys l8r!

14:18 gfrlog: bye

14:21 amalloy: @india? i'm not sure that makes sense even on twitter

14:21 gfrlog: he could have had a friend named India that he was speaking to

14:23 or maybe he's advocating for a simpler set of english preposition usage rules

14:25 dbgster: Hi all, is there a particular book that stands out amonst the closure books that you would reocmmend?

14:26 thearthur: joy of clojure

14:26 technomancy: inc

14:26 thearthur: and xlojure in axtion

14:26 manutter: dbgster: for introductory clojure I like clojure in action

14:27 joy of clojure for more intermediate/advanced understanding

14:27 amalloy: same. unless you're new to all of: lisp, functional programming, and the jvm; then JoC may not be right

14:27 thearthur: halaways book is very well written but perhaps out of date

14:27 manutter: Land of Lisp is kind of fun in a general what-the-heck-are-all-those-parens sort of way

14:28 thearthur: are there rumors of a 2nd edition

14:28 gfrlog: amalloy: so JOC will introduce any two of those topics but not all three? :)

14:28 amalloy: *halloway

14:28 dbgster: manutter: i'm looking at JOC, is it a poor choice for a beginner book? it doesn't say its an interm. level?

14:28 manutter: Clojure In Action = "clojure how", JOC = "clojure why"

14:29 amalloy: it was my first (and so far only) clojure book, so you can definitely do it

14:29 but it aims to be deeper and spends less time on complete basics

14:29 manutter: I wouldn't say JOC is a poor choice for a beginner

14:29 dbgster: how's the market for clojure? does this language go hand in hand with java or you can do clojure w/o being profecient in java

14:29 thearthur: i say screw the 'how' and go strit for the why

14:29 manutter: but personally I think Clojure in Action is a bit more beginner-oriented

14:30 technomancy: I was really not impressed by the sample chapters of Clojure in Action that I read

14:30 dbgster: amalloy: cool, I see ok. I think i need a (((begingger))0))) book :)

14:30 thearthur: clojure made java accessable to me

14:30 technomancy: I actually ended up more confused about multimethods than when I started

14:30 gfrlog: the effect of java knowledge an the ability to learn clojure sounds like a fascinating question

14:30 s/an/on

14:30 sexpbot: <gfrlog> the effect of java knowledge on the ability to learn clojure sounds like a fascinating question

14:30 technomancy: maybe it's better now; this was right around when the first drafts were appearing

14:30 manutter: There's also the new Programming Clojure title on O'Reilly "Rough Cuts"

14:31 technomancy: but it was in dire need of editing and simple fact-checking at the time

14:31 chouser: technomancy: heh, ouch.

14:31 manutter: um, "Clojure Programming" on O'Reilly

14:31 hiredman: I think http://clojure.org/rationale and rich's videos on blip.tv are the best places to start

14:31 amalloy: technomancy: that's amit's book, right?

14:31 technomancy: I think so

14:32 hiredman: ~blip.tv

14:32 clojurebot: blip.tv is http://clojure.blip.tv/

14:32 manutter: dbgster: whatever book you choose, keep the #clojure channel handy and you should be ok :)

14:33 chouser: So it's now: PC, PC, CP, CiA, and JoC, by Halloway, technomancy, cemerick, rathor, and fogus, respectively, right?

14:33 redinger: dbgster: If you want web resources, we are maintaining a list of current links here: http://clojure.com/reading.html

14:33 I think you mean stuartsierra, not technomancy

14:33 dbgster: redinger: cool thanks.

14:33 what's the market like? are you guys doing clojure all day every day?

14:33 amalloy: i was gonna say, i didn't know technomancy had written a book

14:34 technomancy: well if videos qualify, there's FPwC

14:34 redinger: And don't forget Raynes book

14:34 technomancy: which was technically the first commercial documentation published for Clojure

14:34 cemerick: chouser: s/technomancy/stuartsierra

14:34 chouser: ah, sorry

14:34 technomancy: I beat halloway by like two weeks =)

14:34 cemerick: And Luke, though I don't think he's ever been in here…

14:35 redinger: dbgster: We do have teams doing clojure all day, every day

14:35 chouser: dbgster: I do Clojure all day at work, most days, and then most evenings and weekends too. :-P

14:35 dbgster: chouser: no comment :)

14:35 hiredman: ditto

14:36 chouser: technomancy: ah, perhaps that's what I was thinking of. That was very well received.

14:36 dbgster: is it in demand? is there a specific industry that uses it? I remember some email company used it for spam checking etc. which I thought was intersting.

14:36 hiredman: although, I have to admit, I have gotten fairly busy outside of work so non-work related clojure output has suffered

14:36 jhickner: anyone using jark? getting a weird error on OSX

14:36 redinger: dbgster: http://dev.clojure.org/display/community/Clojure+Success+Stories

14:37 technomancy: chouser: it's gotten a bit dated, but not as much as you'd expect.

14:37 problem is videos are a lot harder to update than PDFs

14:37 cemerick: dbgster: a very partial list: http://dev.clojure.org/display/community/Clojure+Success+Stories

14:38 dbgster: redinger: yeah that is how I first learnt of closure, some company was looking for clojure devs (remote telecommute work) so I looked into it first at that point :)

14:38 redinger: FPwC & labrepl were the main resources I used to dive in

14:38 manutter: jhickner: I've used jark, but not on os x. What's your error?

14:39 thearthur: runa and weatherbill are both looking for clojure devs right now

14:40 jhickner: the repl works fine, but when running a script I get an error

14:40 jark ➔ ./factorial.clj 10

14:40 #<CompilerException java.io.FileNotFoundException: Could not locate #<CompilerException__init.class or #<CompilerException.clj on classpath: (NO_SOURCE_FILE:0)>

14:40 technomancy: is jark really using ocaml?

14:40 cemerick: That's the plan for the launcher, last I knew.

14:40 Didn't think they'd gotten that far yet…

14:40 technomancy: oh, it's still roadmap territory

14:40 still, mad respect.

14:41 manutter: jhickner: that is an odd one, sounds like a bug in jark

14:42 hmm, though on second thought, how are you invoking the script?

14:42 jhickner: #!/usr/bin/env jark at the top of the script

14:43 then ./factorial.clj 10

14:43 manutter: nailgun server started via jark vm start?

14:43 jhickner: yes

14:44 dbgster: manutter: wait, the CIA book isn't even released yet

14:44 cemerick: dbgster: wha? It's been in print almost a year IIRC?

14:44 manutter: dbgster: you can get it electronically thru the early access program

14:44 No, it's been available in MEAP for about that long but it's not officially released yet

14:45 cemerick: oh, sorry, sorry, was thinking of Practical Clojure.

14:45 redinger: I wonder what cemerick's been reading all this time

14:45 dbgster: yeah I'm on amazon at it says june 28th

14:46 manutter: Go to Manning Publications you can get in on the Early Access Program (MEAP) if you want it right away

14:46 though at this point that, what, 2 more weeks?

14:46 cemerick: redinger: at the moment, Automata Theory by Hopcraft and Ullman.

14:46 redinger: woah

14:47 cemerick: and The Futurological Congress on the fiction side, tho I just started that last night

14:47 manutter: I forget what I'm reading now. I got as far as "Footnote 1: see Footnote 1" and haven't been able to get any farther.

14:48 technomancy: did you know if you click on "did you mean: recursion" at http://www.google.com/search?q=recursion enough times, it gives you a stack overflow?

14:48 manutter: jhickner: everything looks right to me, I'm not sure what's going on with your jark setup

14:48 cemerick: I fantasize about book blogging more often, but other things get in my way…

14:49 jhickner: ok, thanks. I'll post it on the mailing list and see what happens

14:49 dbgster: cemerick: is fantasize the best word to describe it? :)

14:49 chouser: technomancy: if that statement was a prank, I'm totally falling for it.

14:49 redinger: technomancy, chouser yeah, I'm thinking he's going to get me with the definition of gullible next

14:49 cemerick: dbgster: I'm guess I'm weird? :-P

14:50 dbgster: i dream of writing a book, and selling it via pdf :)

14:50 technomancy: chouser: totally not true! sorry.

14:50 err--that is to say, if you don't get a stack overflow, it means you're running a browser compiled with --enable-tco! congratulations.

14:52 hiredman: technomancy codes upsidedown wearing moonboots to keep blood flowing to his face, which he needs due to skin graft he got to go into hiding after writing a build system

14:52 stuartsierra: wow

14:53 hiredman: now you see why the keyboard pants are a must have

14:53 stuartsierra: totally

14:53 technomancy: hey--that was ... I mean ... the grafts are healing.

14:55 amalloy: technomancy: yeah, surprisingly credible prank. i was sorely tempted to try it

14:59 gfrlog: are there any libraries for writing clojure code while holding a baby?

14:59 TimMc: There's an email thread going on here at work about whether to use Clojure for some DSL-ish stuff in our Java codebase...

14:59 Cross your fingers!

14:59 stuartsierra: gfrlog: I expect you want GOO.

15:01 redinger: M-x newborn-clojure-mode in emacs

15:02 gfrlog: somebody make me a vim plugin

15:02 stuartsierra: gfrlog: I always read your nickname as "girl frog." Don't know why.

15:03 Raynes: redinger: Aw, you remembered me. <3

15:03 gfrlog: stuartsierra: that's the nicest thing anyone's ever said to me

15:03 stuartsierra: I'm sorry to hear that.

15:04 gfrlog: :}

15:04 I always assumed the most common misreading would be grr-flog

15:05 TimMc: giffer-log

15:05 raek: gopher-log

15:05 gfrlog: I prefer to mash as many consonants together as I can manage

15:06 stuartsierra: No wonder you like vim.

15:06 Raynes: Oooh, burn.

15:06 * raek is probably biased towards rodent-oriented network protocols

15:06 gfrlog: what emacs does it too you just gotta hold down command-alt-meta to make it work

15:07 stuartsierra: True. That's why Emacsers are usually frustrated amateur musicians.

15:07 gfrlog: if I had an extra finger that hovered over my command-alt-meta key, maybe I'd consider that a feasible solution

15:08 * stuartsierra has just discovered the limit to which inoffensive sarcasm can be conveyed in text chat.

15:09 trptcolin: someone should hook up electronic piano pedals as command/alt/meta

15:09 stuartsierra: 'been done

15:09 amalloy: trptcolin: it's been done

15:09 stuartsierra: I've even considered buying the foot pedals for it.

15:10 trptcolin: lol @emacs

15:11 TimMc: amalloy: Shouldn't be hard to make an auxiliary "keyboard" for USB with M^ and C^ foot pedals.

15:11 gfrlog: I only use photoshop for coding

15:11 manutter: "Just hold down Control-Shift-Sustain while typing the 9 key..."

15:11 stuartsierra: http://www.kinesis-ergo.com/fs-savant-elite.htm

15:12 TimMc: Beautiful.

15:13 Haha, they support macros.

15:13 gfrlog: oh he's lying down with the pacifier. Now I have a split moment to type out all the code I've been imagining for the last half hour

15:13 TimMc: gfrlog: Pair program with the kiddo.

15:13 stuartsierra: TimMc: of COURSE they support macros!

15:14 technomancy: gfrlog: it's amazing how that kind of situation lets you focus

15:14 gfrlog: technomancy: focus during or between holdings?

15:14 technomancy: gfrlog: the "hey, I've actually got a moment" feeling

15:15 gfrlog: ah yes

15:15 oh I think it might be over now

15:15 technomancy: well I hope you got some awesome code out

15:15 gfrlog: no I chatted on #clojure instead

15:15 TimMc: Too busy chatting, no code.

15:17 gfrlog: TimMc: he suggested pair programming as well, but I said "No pairing until you can hold your head up on your own."

15:18 TimMc: Have him work the modifier keys.

15:19 gfrlog: that's a good compromise

15:19 technomancy: gfrlog: http://www.flickr.com/photos/technomancy/2231407627/

15:20 gfrlog: technomancy: very nice

15:21 justinko: technomancy: by the time he's 10, instead of mowing your lawn he can write all your code :)

15:26 gfrlog: plan B: pace around room while watching math lectures on youtube

15:28 bdesham: is there a function like dotimes which will iterate through a set instead of a list of integers?

15:29 technomancy: bdesham: doseq

15:29 bdesham: technomancy: thanks

15:34 jweiss: does the pprint lib know when you pass it source code? or do you have to tell it somehow

15:34 for me it prints too much on one line

15:34 stuartsierra: I don't think it knows how to format Clojure source code.

15:35 hiredman: it has a code formatter, dunno if it is any better

15:36 what always bugs me is it derefs vars, otherwise I would replace prn in the repl with pprint in a second

15:36 jweiss: stuartsierra: from http://richhickey.github.com/clojure/clojure.pprint-api.html "Out of the box, pprint supports a simple structured format for basic data

15:36 and a specialized format for Clojure source code."

15:36 stuartsierra: oh

15:36 jweiss: just doesn't say how to use it

15:37 hiredman: you bind some dingus to something

15:37 stuartsierra: hiredman: Can I quote you on that?

15:37 hiredman: please do

15:38 jweiss: hiredman: any idea how to get it to format code? i don't know how it could tell otherwise whether it's a regular list or actual code

15:39 hiredman: I believe you bind http://clojure.github.com/clojure/clojure.pprint-api.html#clojure.pprint/*print-pprint-dispatch* to http://clojure.github.com/clojure/clojure.pprint-api.html#clojure.pprint/code-dispatch

15:41 jweiss: hiredman: will try, thx

15:42 meh, looks the same

15:42 hiredman: right, I don't believe it comes out much different

15:47 jweiss: you'd think that it could at least put each expression within a (fn [] ...) or (defn [] ...) on a newline

15:48 dnolen: jweiss: it comes out well enough for macroexpansion, but certainly not something I would rely on for producing well formatted code.

15:49 prior to pprint it was impossible to debug large macros.

15:49 jweiss: dnolen: is there another lib that formats it a bit better? (besides emacs) :)

15:50 dnolen: jweiss: not that I'm aware of, pprint works well enough for it's intended use. there may be more knobs in there I haven't looked at pprint too closely. it does support most of cl-format so you can probably bend it to your will with some effort.

15:51 jweiss: dnolen: ok thanks

15:53 cemerick: holy crud, people actually attempt to install Clojure via apt/rpm? 0_0

15:54 jweiss: cemerick: linux people don't like jars :)

15:54 or maven

15:55 and i don't blame them

15:58 cemerick: jweiss: in any case, trying to stuff a peg into a square hole isn't doing anyone any good

15:59 jweiss: cemerick: well, i'm not sure about that. if I wanted to see what clojure is all about on my fedora system, i would first do "sudo yum install clojure" and play around w the repl.

15:59 unfortunately the rest of the clojure infrastructure would happily ignore my installation and download it again from maven

16:00 but at least people can check out clojure somewhat with their native package manager

16:00 cemerick: At that level, any of the web-based REPLs would be a better sandbox.

16:01 jweiss: cemerick: in some cases, i guess. you can't read files or do anything with local resources that way

16:01 some would argue that that it's maven and java trying to stuff a round peg in a square hole but i guess that is all semantics

16:02 cemerick: Which is correct depends on whether you care more about the package manager or whatever else you're doing.

16:02 rpm/apt maintainers have made hashes of ruby and python languages and libraries as well, so this isn't without precedent.

16:03 gfrlog: There's not a shortcut for (:require [a.b [foo :as foo] [bar :as bar] [baz :az baz]]) is there?

16:03 * cemerick gets off his OT hobby horse

16:07 jweiss: cemerick: i am not exactly sure what it is about python and ruby that rpms work for them, but not java or clojure.

16:08 cemerick: jweiss: They don't, AFAIK; thus easy_install & pip & rvm & …

16:09 jweiss: cemerick: they do, i'm working on a ROR project now that uses rpms for its deps

16:10 dnolen: jweiss: is that a common approach in the ROR world ?

16:10 * jweiss works at red hat - full disclosure

16:10 jweiss: no ^

16:11 dnolen: jweiss: my impression so far is that accepted python and ruby dependency management is the PITS

16:11 jweiss: dnolen: you mean the built in ones? pip, rubygems?

16:11 dnolen: jweiss: yes

16:12 jweiss: yeah i've seen rubygems do some annoying stuff

16:12 gfrlog: bundler pretty good

16:12 dnolen: gfrlog: we use that and I think it's pretty lame for the most part.

16:12 gfrlog: bundler pretty lame

16:13 cemerick: gfrlog: sycophant ;-)

16:14 dnolen: but perhaps it's the interaction between gems + ROR + bundler that troubles me.

16:14 gfrlog: ruby is 95% black magic

16:17 dnolen: oh add rvm to that list.

16:18 gfrlog: rvm: because as a rails dev you don't otherwise do enough bash-hacking

16:20 pjstadig: people like to bash gems, but dependency management is hard...let's go shopping

16:21 gfrlog: it is hard. But I always thought rubygems were weird in contrast with java, by installing things at the system level

16:21 half the point of RVM is to make it stop doing that :)

16:21 pjstadig: i'm just saying people like to complain about <INSERT DEPENDENCY MANAGER HERE>

16:22 gfrlog: pjstadig: what kind of shopping?

16:22 pjstadig: guns?

16:22 no too violent

16:22 pillows

16:23 gfrlog: then we'll create a dependency management system based on a violent metaphor?

16:23 pjstadig: https://github.com/technomancy/roast-beef

16:24 gfrlog: I learn something new most of the times

16:28 pjstadig: i like to dig deep into the technomancy archives

16:28 bdesham: pjstadig: I assumed that was for clojure for a second and got confused

16:28 pjstadig: there's also http://rubyforge.org/users/technomancy/

16:28 gfrlog: naw then it would have been called roast-beefjure

16:29 pjstadig: gfrlog: more likely a character from literature

16:29 gfrlog: is that a clojure-specific trend?

16:30 pjstadig: just a more recent technomancy trend i think

16:30 amalloy: pjstadig: roast beef is a character in achewood

16:30 pjstadig: amalloy: true

16:30 redinger: Which is a far cry from literature

16:31 pjstadig: hehe

16:31 amalloy: he even mentions that in the readme

16:31 so i speculate that this is not a new or clojure-only trend

16:31 * the-kenny calls his next project "zaphod beeblebrox"

16:31 gfrlog: I'm going to elect that project president

16:31 technomancy: if you don't think achewood is literature you haven't read the supplementary material in "A Home for Scared People"

16:32 nor the Great Outdoor Fight

16:34 jweiss: I gave up on pretty-printing code from clojure; it's much, much easier to do from elisp

16:34 because you can treat it as a string and as a data structure at the same time

16:35 jweiss: technomancy: that's kind of ironic that clojure isn't as good at printing itself out as elisp

16:35 unfortunately i won't have emacs available where i want to print this stuff out

16:35 i'll be running my code via command line

16:35 technomancy: replaca may have further comment

16:35 amalloy: why is that ironic? clojure is a compiled language, and elisp is a language for writing a text editor in

16:36 technomancy: also: you can totally run elisp in a batch context

16:36 we do it at work for a pre-commit hook

16:36 jweiss: technomancy: actually that may be something i might want to try

16:36 hiredman: "we"

16:36 * technomancy whistles idly

16:37 jweiss: i could also use htmlize to make pretty html logs

16:37 technomancy: htmlize is the cats

16:37 jweiss: "the cats"? is that good? :)

16:37 technomancy: I ... I'm not sure. I think so.

16:37 * jweiss isn't up on all the lingo the kids use these days

16:38 amalloy: heh. so ironic, because it's old slang

16:38 jweiss: ah, then i'm not up on all the lingo the old farts used either

16:38 amalloy: http://en.wiktionary.org/wiki/cat%27s_pyjamas

16:39 technomancy: http://facepwn.com/posters/cats-allyourbase.jpg

16:45 jweiss: hm, trying to get emacs to render my clojure snippet in clojure-mode and the htmlifying it and sending it to stdout might be beyond my elisp abilities, but worth a shot

16:46 technomancy: it'd be a lot easier to write to a file than stdout

16:46 jweiss: ok that too

16:48 cemerick: Is this all to get Clojure syntax highlighting in html?

16:49 jweiss: cemerick: well sorta, i have automated tests in clojure, and i'd like to use technomancy's serializable-fn to save the source of what it's executing. my aim here is to have automated tests BE the written procedure - not have code and separate english steps to execute the tests

16:50 cemerick: Gotcha; thought maybe you were just looking to post something pretty on a blog or something.

16:50 But I can see you wanting to have more control over presentation than e.g. syntaxhighlighter would provide.

16:50 jweiss: cemerick: no, i've used htmlify to do that already

16:51 gfrlog: why is the compiler unable to resolve pprint in this context? :(

16:52 hiredman: cause you did you experimenting at the repl

16:52 which auto 'uses pprint these days

16:52 gfrlog: oh ah ha

16:53 thx

16:54 dbgster: is peepcode's clojure screencast worthy?

16:59 cemerick: technomancy: I just noticed that incanter switched to lein, big win. :-) Is that the largest OSS project you know of using lein?

17:00 manutter: dbgster: it was when I watched it, haven't looked at it lately

17:01 dbgster: manutter: cool, I think I need some visual help to get up and running. thanks

17:01 technomancy: cemerick: I think it's the largest, yeah.

17:02 I wonder how the multi-module stuff is working out for them

17:08 redinger: dbgster: He also released a blog post with some updates since the peepcode: http://technomancy.us/136

17:10 dbgster: redinger: yes saw that thanks.

17:10 gfrlog: given a black-box ring-app-function, is calling it and mocking a multipart-browser-file-upload hard?

17:22 thearthur: anyone here using nailgun?

17:24 Raynes: cemerick: I'm guessing you haven't got around to that survey yet.

17:27 cemerick: Raynes: :-( Tomorrow, I promise.

17:28 Raynes: cemerick: I'll hold you to it this time. ;)

17:28 cemerick: Raynes is a slavedriver. :-P

17:36 amalloy: clojurebot: Raynes?

17:36 clojurebot: if it's not one thing it's another

17:41 lonstein: this might be obscure, anyone using cdt w/slime+emacs on osx and worked around the lack of tools.jar? it's not present under the Apple 1.6.0 or the OpenJDK 1.7.0.

17:42 google is not helpful other than to show that others hit this

17:45 amalloy: lonstein: install a jdk instead of a jre?

17:46 lonstein: that's the first thing I checked :)

17:49 brehaut: lonstein: if it exists in the default install, its not easy to find

17:52 sdeobald: Does anyone know of a way to get an interesting list of callers / stacktrace in clojure?

17:52 brehaut: (use 'clojure.stacktrace)

17:52 sdeobald: (.getStackTrace (Thread/currentThread)) returns a lot of ...ah.

17:52 hugod: lonstein: you shouldn't need tools.jar on osx

17:52 sdeobald: brehaut, Cheers.

17:52 Raynes: I just look very, very closely.

17:52 brehaut: sdeobald: the function 'e' is useful

17:54 lonstein: in this regard osx is a bit odd. it's not needed according to apple and not present even as a stub jar

17:54 sdeobald: brehaut: That is useful. Though I'm looking for exception-less debugging.

17:55 (map #(.getMethodName %) (-> (Thread/currentThread) .getStackTrace)) ;; I was expecting this to give me a useful call stack but no dice.

17:57 amalloy: sdeobald: i think you need to .fillInStackTrace or something

17:57 because that's an expensive operation

17:58 but i'm probably very wrong about several parts of that suggestion

17:59 sdeobald: amalloy: Heh. :) I'll check it out. Thanks.

18:25 brehaut / amalloy: I wound up with this, if you're interested. https://gist.github.com/1026083

18:25 I'm sure there's something smarter out there but it does the job.

18:26 amalloy: sdeobald: the doall is a noop there

19:10 TimMc: Hey, Clojure Conj registration is open!

20:02 justinko: in the clojure repl, how do you access "history"? normally, this achieved by using the arrow keys

20:03 technomancy: the built-in clojure repl is not what you would call usable

20:03 justinko: I'm finding that out

20:03 what do u recommend?

20:03 technomancy: you can use it with rlwrap, but it's more common to use a tool like leiningen

20:05 justinko: oh perfect, "lein repl" is what I needed, thanks

20:05 didn't realize you can use it standalone

20:11 technomancy: it's new-ish I guess

20:15 dbgster: when in console, is it possible to fix a line?

20:15 i.e. if I miss a bracket, can I fix it or I have to start all over?

20:15 amalloy: if you use the raw, lowest-level repl, like java -jar clojure.jar, then no

20:15 but if you're doing that you should stop

20:16 dbgster: amalloy: I did homebrew install clojure, then I run: clj

20:17 what should I be doing then?

20:17 other than saving to a file

20:17 hiredman: use lein

20:17 clojurebot: lein

20:17 clojurebot: lein is http://github.com/technomancy/leiningen

20:17 amalloy: throw away the homebrew install

20:17 hiredman: ^-

20:19 amalloy: though i'm surprised that clj doesn't at least include jline or rlwrap

20:19 dbgster: amalloy: y? lein can't work side by side?

20:20 amalloy: probably. so? lein works side by side with pascal, but you should use lein to run your clojure

20:23 dbgster: amalloy: ok i'll read up on it, i'm basically just reading a clojure book and hacking along in repl

20:23 raek: dbgster: Clojure is a bit unconventional if you compare it to Python or Ruby. The clj launcher script variants are not very useful for more that a Hello world program.

20:24 As of now, Clojure does not have any official launcher script.

20:24 * dnolen far prefers cake's repl to lein repl for trying stuff out.

20:24 brehaut: i use cljr for my messing about repl

20:25 dnolen: brehaut: cljr is cool, but yucky on OS X

20:25 dbgster: amalloy: lien seems to be a generator, setup up project files etc. and then it helps loading into rehl also right?

20:25 technomancy: jark is another standalone repl tool

20:27 dbgster: is there a strong similiarity between clojure and erlang? i.e. knowing one compliments the other

20:27 raek: both are functional, I guess

20:27 hiredman: not particularly

20:28 dbgster: this stuff is very cool so far, its opening up parts of my brain I've never used in programming :)

20:28 raek: dbgster: erlang has more focus on inter-process concurrency and clojure on in-process concurrency

20:28 justinko: shouldn't this work?

20:28 (re-groups (re-matcher #"[a-z]+" "foo"))

20:28 java.lang.IllegalStateException: No match found (NO_SOURCE_FILE:0)

20:29 raek: ,(re-find #"[a-z]+" "foo")

20:29 clojurebot: "foo"

20:30 raek: justinko: I think you need to send the matcher to re-find (or simply send the regex directly to re-find)

20:30 justinko: also, re-find sends its internal result though re-groups before it returns it

20:31 dbgster: i'd hate to see clojure interview questions!

20:31 justinko: raek: the docs say re-groups takes a "matcher" single argument

20:31 raek: re-find and re-seq are the only re- functions I use

20:33 justinko: raek: I'm just trying to make re-groups work - playing around

20:33 raek: ,(re-groups (re-find (re-matcher #"([a-z])([a-z]+)" "foo")))

20:33 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.util.regex.Matcher

20:34 raek: ,(re-groups (.find (re-matcher #"([a-z])([a-z]+)" "foo")))

20:34 clojurebot: java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.util.regex.Matcher

20:34 amalloy: dbgster: why would you hate to see clojure interview questions?

20:34 * raek realizes that he has no idea when the functions other than re-pattern, re-find and re-seq should be used

20:35 justinko: ,(re-groups (.find (re-matcher #"([a-z])([a-z]+)" "foo")))

20:35 clojurebot: java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.util.regex.Matcher

20:36 justinko: haha I thought clojurebot was a real person pasting the output

20:36 that is awesome

20:37 raek: ,(re-groups (doto (re-matcher #"([a-z])([a-z]+)" "foo") .find))

20:37 clojurebot: ["foo" "f" "oo"]

20:37 raek: yay!

20:37 dbgster: amalloy: must be some nasty questions, mind twisting, just saying from someone who is on page#43 of their first clojure book

20:38 amalloy: dbgster: asking arcana as interview questions is just as bad in clojure as in some other language

20:38 raek: .find changes the Matcher in-place and returns true if it matched

20:38 * raek prefers the functions that hide the mutation

20:39 justinko: raek: that doesn't quite match the documentation, does it?

20:39 raek: justinko: which sentence are you thinking about?

20:41 justinko: raek: "Returns the groups from the most recent match/find"

20:41 raek: first you step the Matcher to the next match, then you call re-groups on the Matcher to fetch the groups of its current match

20:41 justinko: raek: okay, so you need to "find" matches first

20:41 raek: exactly

20:41 justinko: raek: you can't just pass a matcher

20:42 without finding first

20:42 raek: these stateful APIs are not very ideomatic in clojure

20:42 justinko: yes, so then you can call .find again on the Matcher to go to the next match and call re-groups on the Matcher to get the groups of that match

20:43 justinko: raek: thanks

20:44 raek: re-seq could probably be implemented like (defn re-seq [m] (letfn [(step [] (lazy-seq (when (.find m) (cons (re-groups m) (step)))))] (step)))

20:45 ...if it took a matcher instead of a regex and a string

20:45 (defn re-seq [re s] (letfn [(step [] (lazy-seq (when (.find m) (cons (re-groups m) (step)))))] (step

20:46 eh.

20:46 justinko: raek: I'm just starting to learn clojure, not that far yet

20:46 raek: re-seq is the next function in the book

20:47 raek: that one is straight forward

20:47 raek: a very useful one

20:48 also, the combo of if-let and re-find is very nice: (if-let [[_ as bs] (re-find #"(a+)(b+))] ...)

21:28 justinko: wow, so I can't find the differences between "conj" and "merge" on maps

21:28 amalloy: &(conj {} {1 2 3 4})

21:28 sexpbot: ⟹ {3 4, 1 2}

21:29 amalloy: hm. i thought that might fail. but there are no big differences i guess

21:29 conj is just more general-purpose; merge is specific to maps

21:31 symbole: According to the docs, merge can take multiple maps and it itself uses conj.

21:31 justinko: amalloy: hmmm, so internally, merge uses conj....

21:32 ,(conj {:a 1 :b 2} {1 2} {3 4})

21:32 clojurebot: {3 4, 1 2, :a 1, :b 2}

21:34 justinko: conj can take multiple maps, and both can take multiple vectors, not sure what the differences are...

21:35 amalloy: justinko: does it matter? use merge if you're conceptually merging maps, and conj if you're doing something else

21:36 eg ##(let [m {1 2 3 4}] {:assoc (assoc m 10 20), :merge (merge m {5 4 1 10})})

21:36 sexpbot: ⟹ {:assoc {10 20, 1 2, 3 4}, :merge {5 4, 1 10, 3 4}}

21:36 justinko: amalloy: well, it just bothers me that the differences are not clear

21:36 symbole: https://github.com/clojure/clojure/blob/f86db9cc68773dd3e4a166c1ff7b81e4a98aa602/src/clj/clojure/core.clj#L2268

21:37 amalloy: justinko: what is the difference between map and juxt? they do similar things, but different, and that's okay

21:39 justinko: amalloy: as long as they have differences, I'm fine with that. I'm coming from Ruby, where there are aliases for so many function names. It's kind of annoying: "collect" is an alias to "map" <-- why?? where is the value add?

21:40 symbole: When writing an API, is it better to store data such as hostname and port inside special vars, or is it better to pass a data structure that contains that data to all the functions?

21:40 amalloy: justinko: i wouldn't be surprised if merge were written before conj learned some new tricks for working with maps

21:41 justinko: amalloy: yeah, that kind of stuff is to be expected I guess...

21:41 amalloy: and merge has a nice pair in ##(doc merge-with), which has no real conj-equivalent

21:41 sexpbot: ⟹ "([f & maps]); Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with the mapping in the result by calling (f val-in-result val-in-latter)."

21:41 amalloy: so having merge[-with] has nicer symmetry than conj/merge-with

21:42 justinko: amalloy: good point

21:56 so basically, clojure's sequence is ruby's Enumerable

21:59 gfrlog: if you don't think about it too hard, then yes.

22:00 justinko: gfrlog: yeah, just read some more. Sequences are a much higher abstraction than Enumerable

22:01 gfrlog: I have a hard time drawing any connections between clojure and ruby at all anymore

22:02 justinko: gfrlog: I consider that a good thing :)

22:02 gfrlog: yeah me too

22:03 justinko: as I learn more, clojure IS starting to appear as a "next generation" language, as they say

22:04 gfrlog: you use clojure in your day job?

22:05 Scriptor: is the state of clojure survey up?

22:06 dnolen: justinko: Enumerable is stateful tho right?

22:06 gfrlog: justinko: yep. lately almost exclusively. the rest is ruby and java(coffee)script

22:09 justinko: dnolen: yes. Enumerable is a class that provides methods to array (vectors), hash (map), etc.

22:09 dnolen: justinko: that's a huge difference between Clojure sequences and Iterator/Enumerable - statefulness.

22:10 (next seq) don't blow away anything.

22:11 justinko: dnolen: yeah, I was referring to the fact that they operate on multiple data types

22:11 dnolen: justinko: yes, that's part of the problem, in Ruby and other langs statefulness is part of the protocol.

22:11 gfrlog: I don't think anything about enumerable is inherently stateful

22:11 justinko: state-fulness aside

22:11 gfrlog: I think it depends on the underlying data structure

22:12 which, in ruby, is usually stateful

22:12 dnolen: gfrlog: as far I understand in Ruby and Python and Objective-C and Java, they are stateful by design.

22:12 gfrlog: but you could easily create immutable data structures that mix in enumerable

22:13 dnolen: certainly the language trends that way, but I'm saying that ruby's enumerable specifically is not inherently stateful

22:13 it's state-neutral

22:13 justinko: that's right, i thought Enumerable might have contained bang (!) methods

22:14 gfrlog: I don't think enumerable has anything that's not derived from #each

22:14 because that's how you use it if you want to include it in a custom class -- you just have to implement #each

22:14 dnolen: gfrlog: ah you're right, Enumerable interface is not stateful.

22:15 gfrlog: but all that aside, ruby programmers use stateful data structures almost exclusively :)

22:15 at least in my experience

22:18 justinko: gfrlog: your company uses clojure for back-end, rails for front-end?

22:20 dbgster: less than and larger than seemed revered.

22:20 gfrlog: justinko: no, most of the clojure I've done has been web-apps

22:20 dbgster: (> 5 10) to me reads: 10 > 5

22:20 gfrlog: so the clojure and ruby are kind of disjoint

22:21 justinko: utilizing compojure?

22:21 gfrlog: dbgster: maybe it makes more sense when you think of the multiargs case?

22:21 i.e., > says "these numbers are in descending order"

22:21 justinko: yep

22:22 dbgster: gfrlog: but then if it is (< 5 10) it means the are in desc order?

22:22 gfrlog: no, ascending

22:23 the height of the symbol gets larger as you move from left to right, and so do the numbers

22:23 dbgster: ok so at least its consistant...hmmm... this is a basic operation, this has to stick in my head somehow :)

22:23 and it reads right to left correct?

22:23 gfrlog: dbgster: it's okay, I have to do a double take every time I use it too :)

22:24 brehaut: dbgster: read it as 'increasing rightward'

22:24 dbgster: actually if you read it right to left, it makes sense.

22:24 gfrlog: dbgster: I'm not sure what you mean. If you think of < meaning "less than", then it means "first arg is less than second"

22:24 dbgster: (< 5 10) means: 5 < 10

22:25 < is greater than

22:25 brehaut: dbgster: does thinking about (< 1 2 3) and (< 1) both = true help you?

22:25 dbgster: brehaut: this is how it helps reading it now: 1 < 2 < 3

22:26 Scriptor: yep, if (+ 1 2) is (1 + 2) then (< 1 2) would be 1 < 2

22:27 brehaut: i personally prefer to discard the greater than / less than terms because they have an inherent binary nature that isnt cleanly mapped onto the actual operator

22:30 dbgster: there isnt' a single clojure job in my area hehe

22:34 gfrlog: ,(-> "" vector list hash-set)

22:34 clojurebot: #{([""])}

22:51 duck1123: What is the right way to wrap my lazytest tests. I used to use robert-hooke, but lately it's been giving me a NPE

22:52 basically, I want to make sure they're all executed in my :test environment

22:54 miwillhite: hey…has anyone here gotten cucumber working with clojure?

22:54 I'm having issues getting it to see jruby currently…

22:55 duck1123: what are you using to run it? (lein, mvn?) I had something kinda working with maven

22:55 miwillhite: lein

22:55 duck1123: but I turned it off because I didn't have any features yet

22:55 miwillhite: (btw I'm brand new to clojure, no java experience…coming from ruby/js)

22:56 duck1123: I try to stick to maven for all my projects, so I can't help, sorry. I guess we're both on a testing kick tonight

22:56 miwillhite: heh…thanks anyway

22:56 whats the advantage to maven over lein?

22:57 duck1123: maven has a lot more structure. lein is great for simple projects, but if you're building a big massive project, you appreciate all the other stuff maven gives you

22:58 miwillhite: cool okay

22:58 duck1123: it's a matter of taste for me, personally

22:59 gfrlog: miwillhite: I tried to get cucumber working and failed

22:59 maybe a month ago

23:00 miwillhite: its blowing up in cuke4duke when trying to hit org.jruby.Main

23:00 duck1123: I couldn't figure out how to get it to launch my server so I could send requests to it

23:01 miwillhite: I got the environment setup and everything installed…after wrestling with it for a while…

23:02 I think its something to do with the classpath

23:02 and could be the fact that I'm rvm's jruby

23:02 but this stuff is still beyond me at this point

23:03 gfrlog: miwillhite: I don't think cucumber+clojure is done very often. Since you're new to clojure, is it possible for you to use something more popular at first, like clojure.test?

23:04 miwillhite: oh sure, I just thought I'd try my luck. I like to dive into the deep end sometimes…even if I need a little help getting out.

23:04 Plus, starting from ground zero with this app idea it would be nice to be able to write it up in features

23:04 gfrlog: I'm speculating here, but I think cucumber might be mildly philosophically incompatible with clojure

23:05 miwillhite: heh…that thought had occurred to me

23:05 gfrlog: with the possible exception of testing web apps

23:05 which is probably what you're trying to do with it

23:05 miwillhite: yep

23:05 duck1123: same here

23:05 miwillhite: I still think cucumber is a nice too for fleshing out ideas

23:05 *tool

23:05 gfrlog: the reason I say incompatible is that cucumber seems inherently stateful to me

23:06 it would be more clojure-like to treat your web app as a function rather than something you're using in a browser

23:06 * miwillhite digesting

23:07 gfrlog: it fits in nicely with how ring works -- are you familiar with ring?

23:07 miwillhite: not too any great extent…got my app running on the web, thats about it

23:07 duck1123: gfrlog: there's still a benefit to having an even higher level of testing than ring interactions

23:08 gfrlog: duck1123: I agree, I've actually been messing with this myself lately

23:08 I think it can be done more functionally than cucumber

23:09 duck1123: so is anyone still using lazytest? I wanted something like rspec, but I'm thinking my problem right now is more easily solved in clojure.test

23:09 gfrlog: in one of my apps I had some test helpers that allowed me to write something like:

23:09 (->

23:09 (GET "/foos/new")

23:09 (submit-form-with {:name "Charlie"})

23:09 (should-be-successful)

23:09 (should-see "Charlie"))

23:09 seancorfield: miwillhite: did you try this tutorial? https://github.com/mjul/cucumber-tutorial

23:09 it has installation steps with lein (but i haven't tried it - just found it via google)

23:10 miwillhite: seancorfield: yes, that is the particular version I am using (there are several). Its blowing up in one of the dependencies

23:12 I hate relying on jruby for this though…

23:12 I'll probably pull back…write the features as an exercise to describe the basic app, then just use clojure-test to work it out

23:16 duck1123: gfrlog: If you're ever willing to extract some of that, I'd love to look at it

23:17 I'm curious of what people think of my framework: https://github.com/duck1123/ciste

23:17 That's what I'm using for my site, just extracted

23:27 miwillhite: very cool duck1123, I'll have to try this one out

23:30 duck1123: I haven't written all the documentation up, so do look at the code

23:31 miwillhite: will do, thanks for sharing :)

23:32 duck1123: I'm writing an app that passes both http requests and xmmp packets through the same framework

23:32 I just discovered lamina recently, so there'll be some neat new stuff soon

23:39 seancorfield: miwillhite: hmm, i tried to follow the install instructions here https://github.com/cucumber/cuke4duke and ran into a rubygems incompatibility

23:40 bundler requires RubyGems version >= 1.3.6

23:40 since i don't use ruby, i don't know what to do at that point (apart from google of course)

23:42 hmm, working thru upgrading rubygems :)

23:44 ok, got this error, giving up on rubgem stuff /Library/Ruby/Site/1.8/rubygems/dependency.rb:247:in `to_specs': Could not find bundler (>= 0) amongst [] (Gem::LoadError)

23:45 duck1123: see if this helps: GEM_HOME=~/.m2/repository/.jruby GEM_PATH=~/.m2/repository/.jruby gem install bundler

23:45 wait, you're not using rvm

23:46 I don't know if you need that, but I doubt it'd hurt

23:48 seancorfield: i'd already run that command duck1123

23:48 trying to follow this https://github.com/cucumber/cuke4duke

23:48 maybe i should try the non-rvm path

23:49 ah, i think there's a ~ missing

23:51 duck1123: oh yes, there are several

23:51 go to the raw version of the readme

23:52 seancorfield: now i get Could not locate Gemfile

23:54 *sigh* following the chain of dependencies further

23:57 ok, i sympathize with miwillhite - this is a crazy chain of dependencies :)

23:57 time to watch TV and forget about computers for a while methinks!

Logging service provided by n01se.net