#clojure log - Aug 15 2011

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

0:03 leo2007: is there something like macrolet for clojure?

0:03 amalloy: leo2007: in c.c.macro-utils, which i think is now org.clojure/tools.macro or something

0:03 leo2007: thanks

0:09 fmeyer: exit

0:32 Drakeson: is it possible to `require' relative to the current namespace, similar to python's "from .submodule import Things" ?

0:32 amalloy: no

0:34 Drakeson: but would such a feature make sense?

0:40 I mean, would it be possible to modify #'clojure.core/load-lib to support this feature?

0:42 amalloy: it's certainly possible. bet you ten dollars a patch wouldn't be accepted, though

1:03 jsoft: In java its got what looks like some kind of typcast, ie NameClasspair foo = (NameClassPair) blah.next(). How do I do the typecast in clojure?

1:04 amalloy: you don't have to

1:05 jsoft: Hmm.

1:20 :(

1:20 Argh

1:20 Why does my brain not get along with java.

1:35 chewbranca: anyone successfully following a CouchDB _changes feed with the clutch clojar?

1:39 I'm running into the same issue as here: https://groups.google.com/forum/#!topic/clojure-clutch/vqkzG1aqpUw

1:58 Pupeno: How do you add a second library, both with :as, to the require part of ns?

2:00 found it.

3:02 dsantiago: How do you set a property in leiningen in a file so that it's available with System/getProperty?

4:34 lnostdal: maybe i should just compile emacs 24 from source myself .. no one else is seeing leaks using the build from http://emacs.naquadah.org/ ? (natty)

7:14 joshc_: Does anyone know why when I'm using defn and defining a docstring, the doc command works but there does appear to be any doc metadata on the function?

7:22 morphling: joshc_: try (meta #'your-function) instead of (meta your-function)

7:24 joshc_: That worked, thanks. I'm trying to use Marginalia, but it seems to be unable to detect any of my docstrings.

7:24 morphling: something with meta data on the function and not the var, I think, but I'm not sure, better ask again when someone more knowlegable is around

7:26 joshc_: Thanks, will do

7:28 algernon: marginalia has some troubles detecting docstrings at times. from what I've gathered so far, it might have to do something with clojure 1.3 (but then, I've been using clojure for like two and a half weeks so far, on and off :P)

7:33 joshc_: I'm running 1.2.1 and for some reason when I run marginalia against itself, it works no problem, but will only detect regular comments when run against my code

7:41 manutter: I would have thought Marginalia would extract the docstrings directly from the source rather than from function meta

7:41 Are your docstrings formatted the same way as Marginalia's as far as line breaks in the source code, etc?

7:43 kencausey: http://groups.google.com/group/marginalia-clj/browse_thread/thread/23a424ed9fbedb4a

7:43 related?

7:43 * algernon has no idea how marginalia works, but simply changing the (ns foo) at the top of the file managed to break it in a reproducible way

7:43 algernon: (and my issue is related to the above link, I filed issue #55)

7:45 joshc_: I tried all three styles of line breaks, and tried copying in a function from the marginalia source, still didn't work

7:46 algernon: it's probably not the formatting of the function itself, that breaks marginalia.

7:47 * manutter probably needs to dig into marg internals before commenting on this issue then.

7:47 algernon: In my case at least, it wasn't. I trimmed down my (ns) and marginalia began to work.

7:48 joshc_: algernon I think we have the same problem (issue 55) I have a bunch of requires in my code

7:49 algernon: joshc_: try removing them and see if that unbreaks marginalia. If nothing else, we'll know that it's the same underlying issue then

7:49 joshc_: Will do

7:52 algernon: I cleaned out my ns and everything worked

8:05 algernon: I added a comment to issue #55

9:12 PPPaul: test

9:32 TimMc: PPPaul: Your test worked.

9:32 PPPaul: awesome!

9:34 TimMc: "Thank you for experimenting with Wikipedia. Your test worked, and it has been reverted or removed. Please use the sandbox for any other tests you may want to do. Take a look at the welcome page to learn more about contributing to our encyclopedia."

9:34 ^ what I think of whenever someone writes "test"

10:22 kephale: namespace question, i am refactoring what was a single file into separate files, but i would like 'use to bind symbols from the separate file to the original name (for backwards compatibility), how does one do this?

10:24 manutter: do you actually need/want separate namespaces? If you're just breaking up the files for easier maintenance, you can use (in-ns) to load the symbols directly into their old namespace

10:25 zmaril: If I were using noir and mongo, how should I set up the database? I have very little prior experience with backend and the MVC model is new to me

10:25 manutter: if you want separate namespaces though, I don't see why you can't use/refer them from the original file

10:25 kephale: well, i kind of do want the namespaces separated, in-ns is the best alternative

10:25 manutter: zmaril: what do you mean by set up the db?

10:26 kephale: (use) should be ok as long as the separated-out file isn't using or requiring the original file

10:26 zmaril: manutter: Like I see how to create a new db with mongo, but I am unsure of where to create it and how to pass it around in a functional way.

10:26 manutter: or is that what the problem is

10:27 kephale: well, use isn't binding the symbols from the new smaller NSs the way i am looking for, use case:

10:27 manutter: zmaril: ok, that's not too hard. Create a namespace for your db, and make a create-db function that does all the initial setup and returns some kind of db object that you can pass around

10:28 kephale: (ns foo) had (defn botmaker [] …) now botmaker was moved to (ns foo.bots), now calling (use 'foo) does not provide botmaker

10:28 zmaril: Let me give that a shot then

10:28 kephale: given (ns foo (:use [foo.bots]))

10:28 manutter: zmaril: you can probably find some tutorial examples if you google around

10:29 zmaril: manutter: most of them are single page things about how to get up and running on herkou

10:29 manutter: kephale: wonder if you would have better luck calling an explicit (refer 'foo.bots.botmaker)?

10:30 kephale: manutter: well thats what i was thinking, but some of the NS's have a looot of things defined

10:30 raek: kephale: you are pretty much stuck with either using (load-file) + (in-ns) or releasing a new major version...

10:30 manutter: kephale: I'm kinda out of my depth here, so I'm groping around for ideas

10:30 kephale: i was thinking about a hack that looked for all symbols in a namespace and aliased them

10:31 manutter: kephale: that's kind of the way I was leaning (in my blissful ignorance)

10:31 kephale: manutter & raek: ah, ok, i might putter at that aliasing hack

10:31 raek: kephale: there is a macro called 'immigrate' in contrib, but it doesn't really work that well

10:31 kephale: raek: oh cool!

10:32 it just has to work well enough : P

10:32 raek: if backwards compability is essential, using load-file to "include" additional files into the namespace is probably the best idea

10:32 binding won't work reliably, since you have to vars for the same value (only one of them will be rebound)

10:33 kephale: well, that makes it a bit harder to become forwards compatible, since all future code should really switch to use/require on the new namespaces

10:33 manutter: zmaril: the one-page examples are probably not a bad start, but if your app gets more complicated then separating out the db stuff will be easier to maintain

10:33 kephale: with the opening 'ns call and all

10:33 manutter: zmaril: the basic approach should remain the same though

10:34 raek: well, new major version is what I would recommend

10:34 kephale: raek: heh, i'd love to… unfortunately its not my call

10:35 but immigrate (which seems to be require + a loop of interning) does look like it might hold me over, i'll poke around

10:35 raek: compojure used immigrate initially, but stopped later, IIRC

10:36 load-file + in-ns will allow you to structure the implementation better, but doesn't expose the "new API"

10:38 kephale: ooo immigrate seems to be working like a charm thus far

10:38 duck1123_: There's also potemkin, but that works on a var by var basis

10:39 kephale: well, i'm hoping i can just leave this "depricated" file that used to have everything, and just use it for the immigrate call, then anything new can be written with the new API

10:39 duck1123_: but provided you pass it a var, it works with 1.3

10:40 kephale: potemkin looks like it wraps intern?

10:40 leo2007: How to configure lein to run the latest snapshot of clojure?

10:41 raek: heh, then any problems that might be caused by 'immigrate' will only affect the users of the old API...

10:41 duck1123_: leo2007: just edit your project.clj and ref the vewer version

10:41 raek: an incentive to upgrade

10:41 leo2007: duck1123_: thanks.

10:42 kephale: raek: yeah, perfect : P

10:43 leo2007: duck1123_: where is clojure installed by lein?

10:43 duck1123_: It's in your mvn repo ~/.m2

10:44 manutter: leo2007: or, depending what you mean by "installed," in your project's lib/ directory

10:44 duck1123_: lein just uses maven's dependency resolution under the hood, which makes it handy

10:45 manutter: Good point, as a Maven user, I tend to forget about lib/

10:45 raek: leo2007: they are downloaded to the local maven repo in ~/.m2 . the ones you use in your particular project are copied over to the lib/ directory. (in the future, they might be symlinks instead)

10:46 so you have one environment per project. (but the jars are cached in your local repo)

10:46 leo2007: raek: thanks.

10:46 mattmitchell: what's the best way to select non-empty values from a map... kinda like select-keys except selecting only non-blanks ?

10:47 raek: mattmitchell: one way is to use the (into (empty m) (processing-function m)) pattern, where processing-function might be filter, for instance

10:48 leo2007: what's the version for clojure upstream from git repo?

10:48 raek: the filter predicate would receive one argument which is a vector (a map entry, actually) of the form [key value]

10:48 leo2007: I need it so that lein can pull it in

10:48 duck1123_: (into {} (filter (fn [[k v]] (identity v)) {:m 1 :n nil}))

10:48 mattmitchell: raek: cool let me try that out

10:50 raek: duck1123_: you could replace (identity v) with just v there... >/(

10:50 *:-)

10:50 mattmitchell: very cool, thanks

10:50 duck1123_: good point.

10:50 raek: gah. accidentally switched keyboard layout in the middle of the smiley...

10:51 duck1123_: I guess that comment about "if you type (identity you don't know what you're doing" applies

10:51 raek: ,(into {} (filter val {:m 1 :n nil}))

10:51 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalStateException: replace already refers to: #'clojure.string/replace in namespace: sandbox>

10:51 raek: ,filter

10:51 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalStateException: replace already refers to: #'clojure.string/replace in namespace: sandbox>

10:51 duck1123_: clojurebot is still messed up

10:52 manutter: oh, sadness

10:52 raek: ,((resolve (symbol "ns-unmap")) *ns* 'resolve)

10:52 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalStateException: replace already refers to: #'clojure.string/replace in namespace: sandbox>

10:52 manutter: ~bot-bandaid

10:52 clojurebot: Huh?

10:52 manutter: well, I tried.

10:53 Hodapp: :(

10:53 raek: anyway... (into {} (filter val {:m 1 :n nil})) => {:m 1}

10:56 leo2007: the latest beta version of clojure is [org.clojure/clojure "1.3.0-beta1"]

10:57 I think the nightly build version is "1.3.0-master-SNAPSHOT"

11:03 PPPaul: is there a simple way to to see if 2 arrays share a certain value somewhere in them?

11:04 arrays = seq

11:04 duck1123_: first question, is there anyway you can represent them as sets?

11:06 lucian: PPPaul: i think you could make them sets and intersect them, as duck1123 suggests

11:06 duck1123_: if you know what the value is, you could test that they each contain the value

11:07 PPPaul: actually, the values i'm looking for are in a seq too

11:07 i guess i want to test if 3 seqs have the same values

11:08 duck1123_: Then I would definitely looking into making them sets

11:08 PPPaul: ok

11:08 i haven't played with sets yet]

11:09 duck1123_: Lots of fun stuff http://clojuredocs.org/clojure_core/clojure.set

11:11 PPPaul: :D

11:13 raek: (let [a (set [1 3 2]), b #{1 2 3}, c #{3 2 1}] (= a b c)) => true

11:13 manutter: ,(println "test")

11:13 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalStateException: replace already refers to: #'clojure.string/replace in namespace: sandbox>

11:14 manutter: ##(println "test")

11:14 lazybot: ⇒ test nil

11:15 PPPaul: thanks a lot!

11:33 timvisher: hey all

11:34 i'm looking for reading i can do on functional code smells.

11:34 anyone have any suggestions?

11:34 wastrel: what does it mean functional code smells

11:35 timvisher: code smells in the sense of Fowler's Refactoring

11:35 hopefully that wasn't a reference to Silence of the Lambs. :)

11:36 wastrel: are you familiar with Fowler's book?

11:36 wastrel: no

11:36 * ejackson is sad to admit that his own code might be an olfactory adventure for timvisher...

11:37 timvisher: ah

11:38 well, code smells are just things in code (structure, method length, variable names, coupling, etc.) that, when done in a certain way, should 'look ugly' or 'smell bad' to you when you see them and encourage you to refactor

11:38 a simple example that is cross-cutting accross all languages and idioms would be methods or functions that do many things. You probably want every function to do only one thing, do it well, and be tested for that

11:39 so that when you compose it later on, you can easily understand what you're doing

11:39 however, a lot of the smells in fowler's book are more geered toward OO, i was wondering if anything like that had been done for functional

11:39 ejackson: sorry to hear it! ;)

11:40 ejackson: i regard it as I do cheese

11:40 timvisher: hah

12:01 dnolen: damn

12:02 ,(subvec [1 2 3] 1)

12:02 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalStateException: replace already refers to: #'clojure.string/replace in namespace: sandbox>

12:02 dnolen: &(subvec [1 2 3] 1)

12:02 lazybot: ⇒ [2 3]

12:02 dnolen: no more rest on vectors for me.

12:03 chouser: oh? why's that?

12:03 dnolen: subvec 1 does the same thing while preserving the vector type (yes, i was being a little over the top :)

12:04 chouser: yeah, subvec is really nice.

12:05 dnolen: ugh, http://blog.dhananjaynene.com/2011/08/cperformance-comparison-languages-styles-and-vms-java-scala-python-erlang-clojure-ruby-groovy-javascript/

12:06 people who don't know the language they're benchmark should not benchmark

12:08 upwardindex: Does clojure run on openjdk?

12:08 st3fan: dnolen: looks like they forgot to compile the clojure code

12:10 dnolen: st3fan: no those numbers are accurate for that kind of code.

12:10 calling count on range is *LINEAR*

12:10 upwardindex: dnolen: I think the key part of the article is "I can’t write the fastest possible code across all this languages."

12:10 chouser: ugh. wasn't always.

12:10 st3fan: dnolen: oh oops. i did not look at the code.

12:10 dnolen: upwardindex: "I don't know Clojure so I'm going to write some crap"

12:11 st3fan: well, correct his code and ask to run the bench again :)

12:11 upwardindex: dnolen: I found this to be generally more accurate: http://shootout.alioth.debian.org/

12:12 dnolen: upwardindex: you don' t need to tell me, I consider myself a minor Clojure perf expert :)

12:39 lucian: upwardindex: except it's extremely biased

12:39 and mostly useless

12:40 upwardindex: lucian: biased towards what?

12:40 lucian: upwardindex: towards numeric processing code

12:40 it has extremely small synthetic benchmarks

12:41 dnolen: lucian: numeric processing is good indicator of the performance of much higher level benchmarks

12:41 lucian: it's very hard to benchmark worth-while things between languages (like a template language compiler)

12:41 dnolen: you can't implement Clojure in Clojure without very, very good numeric perf

12:41 lucian: dnolen: sure you can

12:41 upwardindex: lucian: true, however i found it matches my experience with the 2-3 languages im most proficient with

12:41 lucian: dnolen: i think it's not a good indicator at all, although it may be useful

12:41 dnolen: lucian: you can and lose performance, Clojure is performance oriented.

12:42 lucian: dnolen: my point is that the benchmark tests something almost entirely irrelevant to what mosts of us actually do

12:42 dnolen: lucian: because you benefit from it.

12:42 lucian: but someone needs to do the work that you benefit from

12:43 lucian: dnolen: really, read the code on those benchmarks for several languages. you'll change your opinion

12:43 dnolen: lucian: I have, and I do stuff like that all the time.

12:57 timvisher: anyone know if anything's been written about common lisp/functional anti-patterns and smells?

12:57 something along the lines of the first few chapters of Fowler's Refactoring?

12:58 ejackson: timvisher: the next Clojure book, authored by you.... ?

12:58 timvisher: lol

12:58 a bunch of people just told me the same thing at lunch

13:02 i'm actually thinking i'm just going to have to work my way through MM. fogus and houser's book again

13:05 ejackson: yeah, i guess you're looking for (map not (extract-practices joy-of-clojure))

13:07 timvisher: ejackson: basically. :)

13:08 * timvisher sighs. Another project that I won't ever have time to do.

13:08 timvisher: in a completely unrelated turn of events, anyone watch any of my VimGolf in Emacs videos?

13:14 jfields: wjat

13:15 sorry...

13:16 what's the easiest way to convert {"bob" {"accounts" {"NGM1" {"lynx-available" true, "account" "acct"}}, "default-account" "xyz"}, "joe" {"accounts" {"NGM1" {"lynx-available" true, "account" "acct"}}, "default-account" "asd"}} to {"bob" {:accounts {"NGM1" {:lynx-available true, :account "acct"}}, :default-account "xyz"}, "joe" {:accounts {"NGM1" {:lynx-available true, :account "acct"}}, :default-account "asd"}}

13:16 note the 2nd and 4th level keys are keywords in the version I'm looking for.

13:26 TimMc: jfields: You want all the non-top keys to go string -> keyword?

13:26 some kind of tree-walk inside an (into {} (map ...))

13:26 jfields: no, unfortunately, only the keys at depth 1 and 3.

13:27 yeah... I'm looking through the source of clojure.walk now... thanks. =)

13:27 lobotomy: hmm, would get-in work?

13:49 jfields: my solution, feedback welcome: http://www.pastie.org/2376311

13:53 amalloy: i'd call it depths instead of indexes

13:58 and probably pull the duplication of (hv v) outside of the (if) so you don't have to repeat it. neat little corecursive solution, though

13:59 duck1123_: if it makes you feel better, clojure.core has (identity in it too

13:59 &(macroexpand '(.getClass Class))

13:59 lazybot: ⇒ (. (clojure.core/identity Class) getClass)

14:14 jfields: amalloy, thanks for the feedback.

14:50 gtrak`: is there a way to do some custom global lein config that overrides what's in a project.clj? for instance, I want to ignore a certain dev-dependency (so I don't have to ask everyone else to change it)

14:52 I see there's a ~/.lein/init.clj file I can stuff code in

14:53 ejackson: gtrak: i know that can be used to store your binary repository credentials and lein will fetch them from there

14:54 gtrak`: I'd like to globally override a version of a dev-dependency just for my box... maybe there's some api call to hook into?

14:55 amalloy: interesting. is there any clear reason that (for [x (range 10) :when (even? x)]) is illegal? specifically, it requires a body instead of allowing an implicit nil like (fn) does

14:56 i found myself wanting to use for just to count a sequence, and nil would have been fine

15:01 TimMc: Wait, what are you trying to do?

15:02 raek: gtrak`: maybe you could install a new custom version of the dependency locally

15:03 or install it as a plugin

15:03 amalloy: TimMc: me or gtrak?

15:03 raek: which dependency is it?

15:03 gtrak`: lein swank

15:03 TimMc: amalloy: You. You want (nil...) ?

15:03 amalloy: TimMc: (count (for [x some-seq, y some-seq, :when (some-condition x y)] ...))

15:03 TimMc: so you can (count..) it?

15:03 ah

15:04 amalloy: i don't care about the elements, i just want to see how many pass a condition

15:04 and was a bit annoyed to have to put in a body, is all

15:04 raek: don't know a way to add the :excludes option globally

15:04 gtrak`: everyone else uses lein 1.5, I use 1.6, which is broken on swank-clojure 1.2, I'd like to workaround it automatically for myself instead of fiddling with project dependencies or asking them to change

15:04 ibdknox: amalloy: why not filter?

15:05 amalloy: ibdknox: because (for) does the nice nested-iteration of xs,ys

15:05 ibdknox: amalloy: gotcha

15:07 raek: gtrak`: so you want something like :excludes but global?

15:08 oich: I am new to clojure. On http://webnoir.org the getting started and tutorial pages show running the web server and then show some lisp code, but don't say where (what file? what path?) to put the code. do you know where?

15:08 gtrak`: yes, generically, it'd be cool to intercept the map created in a project.clj that lein uses and munge it up a bit

15:08 ibdknox: we need to just convince everyone to remove lein-swank from their project dependencies

15:08 and use the wonderful lein plugin install to do it locally for themselves

15:09 amalloy: (inc ibdknox)

15:09 lazybot: ⟹ 1

15:09 amalloy: or the global cake project, which is what i do

15:09 ibdknox: or that :)

15:09 gtrak`: raek, I want to write a bit of code that says, if dev-dependencies has swank-clojure, then override its version..

15:09 ibdknox: gtrak: the simple solution would be to remove the jar from lib

15:10 amalloy: gtrak`: why are you still using swank-clojure 1.2?

15:10 make everyone upgrade, problem solved?

15:11 gtrak`: sure

15:11 still surprised I can't do it with some code

15:14 raek: gtrak`: if your project depends on for example intancter, you can exclude its swank-clojure dependency: [incanter "1.2.3" :exclusions [swank-clojure]]

15:15 you have to do this for every library that pulls in the bad dependency, though

15:15 gtrak`: right, that's not really what I'm talking about though, would like to override it globally without touching the project.clj

15:16 ibdknox: We should log issues against all the libs that have swank-clojure as a dep

15:16 gtrak`: or having to remember to run some command each time, etc..

15:16 ibdknox: just to start removing this problem entirely

15:18 upwardindex: I'm trying to do "lein deps" with [ring/ring‑core "0.3.9"] in my project and I errors POM for 'ring:ring‑core:pom:0.3.9:compile' is invalid. Any idea what I'm doing wrong?

15:19 gtrak`: I think I would have to mess with the defproject macro to do it

15:20 upwardindex: http://clojars.org/repo/ring/ring-core/0.3.9/ seems to exist and everything

15:20 gtrak`: ah, this should be simple, I think I can provide a function in a var that filters the project, any chance they would pull in something like that?

15:31 sleepynate: upwardindex: is there a conflicting dependency, by chance? i know frequently i've had to move back from 1.2.1 to 1.2.0 to satisfy a lot of deps

15:31 upwardindex: sleepynate: That might be it, i'll try reverting to 1.2.0

15:32 sleepynate: upwardindex: especially contrib. the website says contrib is still 1.2 :)

15:32 upwardindex: sleepynate: Unfortunately, no difference on 1.2.0

15:34 sleepynate: I'm doing a lein search ring to see if it can find it

15:37 sleepynate: upwardindex: the version on clojars is 0.3.11

15:39 upwardindex: sleepynate: Same thing with 0.3.11, something very basic must be broken with my setup

15:39 Is there a way to test a clojure/leiningen installation?

15:40 To make sure that everything is working as it should?

15:41 Ah one thing I wasn't sure about: Is OpenJDK fine or should I use another VM?

15:41 sleepynate: i use openjdk generally without issue

15:42 the easy way to test is to create a new blank project with "lein new derp", then add contrib as a dependency, and lein deps

15:43 if those download and compile properly, clojure itself and leiningen should be functioning properly

15:43 upwardindex: sleepynate: exactly what I did except instead of adding contrib I added ring/ring-core

15:43 MasseR: upwardindex: Otherwise openjdk seems to work, but clojurescript is unusable with it (and while it is so, I refrain from clojurescript)

15:43 upwardindex: ill try with contrib

15:44 sleepynate: oh yea. i should add that i've never touched clojurescript yet

15:44 so if that's what you're shooting for i have no idea

15:45 https://github.com/weavejester <-- this fellow is in charge of packaging ring-core among a number of others. perhaps he knows more (assuming your standard setup is working)

15:46 upwardindex: sleepynate: Yay, clojure-contrib works!

15:49 xandrews: is there a way to list an agent's watch functions?

15:49 sleepynate: fwiw, ring/ring-core builds find for me against org.clojure/clojure 1.2.1

15:50 java version "1.6.0_22"

15:50 OpenJDK Runtime Environment (IcedTea6 1.10.2) (6b22-1.10.2-0ubuntu1~11.04.1)

15:51 0.3.9 and 0.3.11

15:51 raek: upwardindex: maybe you could try deleting everything in ~/.m2

15:51 upwardindex: raek: I'll try that right away

15:52 sleepynate: yea. that will force maven to fetch everything anew

15:56 upwardindex: raek: same behavior, let me paste the output I'm not too familiar with maven maybe something will catch your eye

15:58 Here is the output i get http://pastebin.com/XbyRhHWX

15:59 And that is on: Leiningen 1.6.1 on Java 1.6.0_22 OpenJDK Client VM

15:59 sleepynate: yea this totally looks like a dependency thing

16:00 you only have org.clojure/clojure and ring/ring-core ?

16:00 in project.clj?

16:00 upwardindex: sleepynate: no I have clojure-contrib also

16:00 sleepynate: that I added earlier to test

16:01 sleepynate: should I paste my project.clj?

16:01 sleepynate: can't hurt

16:03 upwardindex: http://pastebin.com/NVRD5R89

16:04 sleepynate: that builds for me

16:05 upwardindex: something must be wrong with my environment

16:06 sleepynate: rm project/libs/*.jar

16:06 then rm ~/.m2/repository/*

16:06 then lein deps

16:06 if that doesn't work, no idea :)

16:07 (though i'm by no means an expert)

16:08 upwardindex: ah there is no "libs" folder in my project folder, could that be the problem?

16:08 sleepynate: lib, sorry

16:09 amalloy: &(doc when-first) is a neat function that i always forget exists. just mentioning it here as a sort of public service announcement

16:09 lazybot: ⇒ "Macro ([bindings & body]); bindings => x xs Same as (when (seq xs) (let [x (first xs)] body))"

16:09 upwardindex: sleepynate: same no lib folder, do i have to create it?

16:09 sleepynate: upwardindex: shouldn't

16:10 leiningen should create it

16:10 i assume you're on linux?

16:11 amalloy: ah, irc, one of the few places where "i assume you're on linux" isn't some sort of weird joke

16:11 upwardindex: sleepynate: yes, kubuntu

16:12 never thought going through the clojure tutorials would be so hard

16:12 amalloy: upwardindex: have you tried 4clojure.com? it'll let you get started learning without having to install stuff

16:13 sleepynate: amalloy: well, he mentioned he was using openjdk :)

16:14 upwardindex: amalloy: no, looks like a nice set of exercises, however it will only delay the inevitable :D

16:14 xandrews: if anyone was interested in how to list watch fns of an agent, this will do the trick: (.getWatches a)

16:14 sleepynate: upwardindex: what's your java -version ? and what version of kubuntu ?

16:14 amalloy: upwardindex: you can be our 1,001st user. just missed the chance to be #1000, i guess

16:15 upwardindex: java version "1.6.0_22"

16:15 OpenJDK Runtime Environment (IcedTea6 1.10.2) (6b22-1.10.2-0ubuntu1~11.04.1)

16:15 OpenJDK Client VM (build 20.0-b11, mixed mode, sharing)

16:15 sleepynate: huh

16:15 same as me

16:17 amalloy: this is fun. it's like the thing those ruby dudes do

16:17 amalloy: sleepynate: what is? debugging someone's openjdk, or starting on 4clojure?

16:17 sleepynate: 4clojure

16:18 c'mon, the ruby guys don't know how to debug a stack trace ;) </playful>

16:18 dsantiago: Is there some place you can stick a Java properties file to have it automatically be loaded and have its properties available via System/getProperty?

16:18 amalloy: yeah, it's genuinely a good learning tool for all levels of experience. i've been humbled by a number of really-cool tweeted solutions

16:19 dsantiago: I thought this was possible, but I can't seem to google up any docs for that.

16:19 sleepynate: amalloy: love when that happens :D

16:20 amalloy: i will play more later. good work and thanks for the community asset

16:27 sjl: Anyone know if Slimv has an issue tracker or mailing list somewhere?

16:28 upwardindex: ring/ring-core doesnt work but ring/ring-jetty-adapter does. Closing in on the problem....

16:33 Wow, something is definitely broken, I can lein deps [ring "0.3.11"] which in turn requires ring/ring-core but not ring/ring-core directly

16:33 Am I going crazy or what?

16:36 amalloy: upwardindex: well, that version of ring is depending on ring-core 0.3.11, not 0.3.9

16:36 and while 0.3.9 appears to exist, i can imagine it might be broken

16:36 upwardindex: amalloy: thats the thing i only switched to 0.3.9 because 0.3.11 was not working

16:36 amalloy: but not the issue seems to be resolved

16:37 amalloy: not sure what the solution has been

16:38 sleepynate: thanks for your help the issue is finally resolved, not exactly sure why or how...

16:58 eskatrem: quick question: what is the clojure equivalent of for(int i=0;i<10;i++) { for(int j=0;j<10;j++) { //do stuff}} ?

16:59 lobotomy: ,(for [i (range 2) j (range 3)] [i j])

16:59 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalStateException: replace already refers to: #'clojure.string/replace in namespace: sandbox>

16:59 lobotomy: hmm, what

17:00 &(for [i (range 2) j (range 3)] [i j])

17:00 lazybot: ⇒ ([0 0] [0 1] [0 2] [1 0] [1 1] [1 2])

17:00 amalloy: lobotomy: clojurebot has been on a bender for about 24 hours now

17:00 eskatrem: thanks lobo

17:01 TimMc: eskatrem: "do stuff"?

17:01 amalloy: eskatrem: lobotomy is right as long as you realize he means "// return stuff", not "//do stuff"

17:01 TimMc: or compute stuff?

17:01 amalloy: TimMc: cooperative ninja?

17:01 TimMc: :-)

17:02 lobotomy: what's the proper way to do stuff then? doseq?

17:02 e.g. if there's print or whatever

17:02 amalloy: yes. better, of course is to try not to do stuff

17:03 schlecht: is there an idiomatic way to make the following less clunky? "(- {:key map1} {:key map2})"

17:03 amalloy: &(let [stuff-not-done (for [x (range 10)] (println x))] 10) ;; doesn't print anything

17:03 lazybot: ⇒ 10

17:03 schlecht: I'm looking at something like (- map1 map2 key)

17:03 amalloy: schlecht: that will throw an exception anyway

17:04 eskatrem: sorry, what's the & ford?

17:04 amalloy: do you mean to use ( instead of {

17:04 eskatrem: *does

17:04 dont know how I typed "ford"

17:04 schlecht: amalloy: oups

17:04 amalloy: yes, but that was not my problem

17:04 amalloy: eskatrem: your left hand was one letter too far right :P

17:05 eskatrem: amalloy: hmm true :s

17:05 schlecht: amalloy: I mean something like: (- {:a 1 :b 2} {:a 1 :b 3} :b) == -1

17:06 dnolen: ,(apply - (map :key [{:key 10} {:key 5}]))

17:06 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalStateException: replace already refers to: #'clojure.string/replace in namespace: sandbox>

17:06 dnolen: &(apply - (map :key [{:key 10} {:key 5}]))

17:06 lazybot: ⇒ 5

17:07 dnolen: &(reduce - (map :b [{:b 10 :a 9} {:b 5 :a 3}]))

17:07 lazybot: ⇒ 5

17:08 schlecht: dnolen: hey, kinda obvious once you think about it :-) Thanks

17:10 TimMc: eskatrem: The & is so the bot will pay attention.

17:11 eskatrem: TimMc: Ok, I was wondering if it was a clojure command of some kind...

18:14 sleepynate: eskatrem: you can put your "do stuff" in that last square brackets

18:15 well, you don't need the squre brackets unless you want vectors

18:16 &(for [i (range 3) j (range 3) k (range 3)] (+ i j k))

18:16 lazybot: ⇒ (0 1 2 1 2 3 2 3 4 1 2 3 2 3 4 3 4 5 2 3 4 3 4 5 4 5 6)

18:17 sleepynate: &(apply - (for [i (range 3) j (range 3) k (range 3)] (+ i j k)))

18:17 lazybot: ⇒ -81

18:17 sleepynate: etc

18:18 eskatrem: sleepynate sorry, I am not an english native speaker. square bracker is [ ] ?

18:18 sleepynate: yea

18:18 that would be if you wanted vectors

18:19 eskatrem: ok so basically its

18:20 (for [i (range 2) j (range 3) k (range 4)] (;do stuff))

18:20 sleepynate: (for [implicit let statement] (do this) )

18:20 right

18:20 ShreeMulay: Hello everyone! Quick question: If I want to build restful services in clojure, what are the recommendations? Got links?

18:21 tremolo: https://github.com/mmcgrana/ring

18:21 ibdknox: ShreeMulay: http://www.webnoir.org

18:21 eskatrem: and if I want to put several stuff inside my loop its gonna be

18:21 (for [i (range 2) j (range 3) k (range 4)] (do (stuff1) (stuff2)))

18:22 ?

18:23 ShreeMulay: checking out Noir -> I'ven't come across this before (that I remember)...

18:23 sleepynate: yes, but the return will always be a list of the last result returned from your do

18:23 erm

18:23 ibdknox: ShreeMulay: it's built on top of Ring and Compojure

18:24 ShreeMulay: @ibdknox sweet!

18:24 ibdknox: ShreeMulay: and should you need any help, I'm the author :)

18:24 amalloy: sleepynate: whoa what, implicit let statement? fors bindings are pretty different from a let

18:25 eskatrem: do not attempt to perform any side effects in a (for); as i said earlier it will just make you sad later

18:25 ShreeMulay: ibdknox: thanks!

18:25 eskatrem: amalloy: yes you said it yersterday, but...

18:25 amalloy: ShreeMulay: there's also http://github.com/flatland/wakeful

18:26 use a doseq if what you want is side effects

18:26 ShreeMulay: ibdknox: Does it do html5 and support including javascript easily?

18:26 eskatrem: Man, it's hard to get a grisp on clojure, I could do those euler problems so easily in a non functional language, but with clojure ... :'-(

18:27 ibdknox: ShreeMulay: it's a full service webstack. To my knowledge it can do anything the web can do.

18:27 tremolo: ShreeMulay: I suggest looking into hiccup and ClojureScript also

18:27 ibdknox: tremolo: Noir uses hiccup by default :)

18:27 amalloy: it's hard to imagine an http server that somehow forbade html5 in its output

18:27 tremolo: idbknox: Ahh, cool. Didn't know that

18:28 ibdknox: amalloy: pfft, who wants html5? ;)

18:28 ShreeMulay: hiccup's cool!

18:29 amalloy: (defn output [input] (apply str (remove #{\5} input))) ;; first draft of html5 un-support

18:29 * ibdknox goes to add that to his "make-old-school" middleware

18:30 ibdknox: for all your retro-web needs! On the roadmap is support the blink tag and doubling your margins in all browsers...

18:30 amalloy: (assoc-in resp [:headers "Content-Type"] "ISO 8859")

18:30 ibdknox: oh man

18:31 amalloy: I can't tell you how long I fought with character encoding shit back in the day when we were writing PHP websites

18:31 eskatrem: amalloy: yes, *somehow* I can use def inside a doseq more easily

18:31 tremolo: idbknox: how about auto generation of "under construction" animated gifs?

18:31 amalloy: ibdknox: i did the same, back in the day when i was working at a php shop

18:32 ibdknox: tremolo: I'll accept a patch as long as it actually has a pickaxe in it somewhere. ;)

18:32 tremolo: haha

18:33 amalloy: i still get emails from them with "you<big mess>ve got new messages!" or whatever

18:33 ibdknox: hahaha

18:34 the worst part about it is we were working on a site that dealt with wines... all those special characters and multiple database formats each with a different encoding...

18:34 such a disaster

18:34 amalloy: jeez

18:34 ibdknox: that was my last project with that company ;)

18:36 sleepynate: amalloy: sorry i know nothing about the inner workings of the for macro... just that it works like a let

18:36 eskatrem: here is my code for the 4th euler problem: https://gist.github.com/1148056 it works but I'd like to know if my code is "proper clojure" or just some random crap that happens to return a result, can someone have a quick look?

18:36 ibdknox: sleepynate: there are lots of things you can do in a for that you can't do in a let

18:36 amalloy: sleepynate: it has the same *structure* as a let (plus some special features like :when)

18:36 ibdknox: sleepynate: like :when

18:38 sleepynate: ok

18:38 i'm coming from clisp :)

18:38 amalloy: eskatrem: https://gist.github.com/1148071

18:39 any time you find yourself writing (do___) or (def) inside a function, stop and think *really hard* about whether you need to

18:39 sleepynate: amalloy: juxt is like haskell's flip?

18:39 amalloy: &((juxt inc dec) 1)

18:39 lazybot: ⇒ [2 0]

18:39 amalloy: (ie, no)

18:40 ordnungswidrig: sleepynate: (jux inc dec) => (fn [x] [(inc x) (dec x)])

18:40 eskatrem: amalloy: for the second time your neat code is like a slap in my face

18:40 ibdknox: juxt is awesome

18:40 underutilized I thikn

18:40 think*

18:40 amalloy: ibdknox: i use it enough to average out for everyone

18:40 sleepynate: ordnungswidrig: ahh ok

18:40 * amalloy attends Juxtaholics Anonymous

18:41 ibdknox: haha

18:41 outliers ftw

18:41 ShreeMulay: what about netty vs jetty vs mongrel2? any thoughts anyone?

18:41 sleepynate: amalloy: so that's largest palindrome you gist'd ?

18:41 amalloy: sleepynate: yeah

18:41 sleepynate: ok cool. thanks

18:41 ibdknox: netty for persistent connections, jetty for anything else, I can't comment on mongrel

18:42 amalloy: eskatrem: maybe a language thing, but it sounds like you find my code insulting rather than helpful

18:43 ibdknox: lol

18:43 sleepynate: haha

18:43 ordnungswidrig: *g*

18:43 ibdknox: I think it's a language thing ;)

18:43 eskatrem: amalloy: not at all, I mean: your code is so neat in comparison mine seems stupid, it makes me feel how much I have to learn

18:43 ShreeMulay: ibdknox: would you expand on "persistent connections"?

18:43 amalloy: k, just checking

18:43 eskatrem: actually I am really admirative

18:44 ordnungswidrig: eskatrem: just keep practicing. thinking functional is an ongoing journey.

18:44 eskatrem: and, OK, I dont know what juxt is...

18:44 ibdknox: ShreeMulay: if you need to have websockets or long polling

18:44 ShreeMulay: where you keep an open socket, you want netty because it's nonblocking io

18:44 amalloy: eskatrem: well, it's arguable whether juxt makes my code actually more readable; i was going for "short to write"

18:45 ibdknox: ShreeMulay: Jetty would force you to have a thread for every single connection, which is very limiting

18:45 eskatrem: quick question, do you think I should write a blog about "noob point of view: my discovery of clojure and functional programming"

18:45 ibdknox: ShreeMulay: Jetty will outperform Netty in normal http traffic though

18:46 ordnungswidrig: eskatrem: do it.

18:46 jamiltron: eskatrem: yes please

18:46 eskatrem: inside a for, :let is equivalent to "(let ... " in lisp?

18:46 ordnungswidrig: next blog will be "semi-noob point of view: how to teach point-free-style from point-less-style"

18:46 ShreeMulay: ibdknox: as I understand it, it would be easy to switch from jettty to netty and vice versa via simple line changes, right? I'm planning on building restful services that would allow mobile apps to access backend data (I thinks)...

18:46 sleepynate: ahh i see. hyperpolyglot says clj's (for) is like scheme's for*/list

18:47 eskatrem: yeah actually it's good, it will force myself not to give up

18:47 sleepynate: ordnungswidrig: ooh, you vicious ;)

18:47 ordnungswidrig: clojure's for smells like common lipsps loop

18:47 sleepynate: *g*

18:47 sleepynate: ordnungswidrig: yes and no

18:47 eskatrem: what's point-free-style?

18:47 amalloy: ordnungswidrig: yes, it's closest to loop. the difference is that loop is heavily imperative and for is heavily functional

18:47 ibdknox: ShreeMulay: Ring's abstraction makes that relatively painless, though I've never tried to run noir on top of aleph, it *should* work

18:48 ShreeMulay: aleph is built on top of netty and provides a generic asynchronous net library

18:48 ShreeMulay: Noir uses Jetty by default

18:48 sleepynate: amalloy: yea, my instinct for clisp's "loof for" is control monad

18:48 amalloy: eskatrem: i advise not to worry about point-free style. it is a siren song to distract people like me from using let statements

18:49 sleepynate: i don't know enough haskell to understand that

18:49 ShreeMulay: ibdknox: how do we send these private messages in irc?

18:49 sleepynate: amalloy: basically what you said

18:49 amalloy: ShreeMulay: /msg ibdknox you're my hero

18:49 sleepynate: amalloy: and why i say "yes and no" to ordnungswidrig's "code smell" comment

18:52 ibdknox: amalloy: lol

18:52 oh the boost to the ego

18:52 lol

18:53 amalloy: ibdknox: you have to get used to the adulation, with noir and brepl

18:53 ibdknox: haha

18:53 amalloy: I'm more excited about Pinot to be honest

18:54 ShreeMulay: what's brepl?

18:55 amalloy: man, i remember when i was new to clojure, i scoffed at (for...) as pointless sugar over map

18:55 now everything i write has a (for) in it

18:56 sleepynate: (= __ true)

18:56 do it. DO EET!

18:56 amalloy: (apply > (for [x (range 1000)] (- x)))

18:57 &(apply > (for [x (range 1000)] (- x)))

18:57 lazybot: ⇒ true

18:57 ibdknox: ShreeMulay: it's a browser connected repl for ClojureScript

18:57 sleepynate: \o/

18:57 amalloy: *chuckle*

18:57 ShreeMulay: does aleph require netty?

18:58 ibdknox: yes

18:58 ShreeMulay: :P

19:02 amalloy: incidentally, what do people think about adding some euler problems to 4clojure? it's a bit tricky because we tell you the answer and ask for code, whereas euler asks for the answer

19:03 mdeboard: eh.

19:04 ibdknox: amalloy: euler problems are much more math-centric I think

19:04 eskatrem: what's 4clojure?

19:04 mdeboard: I agree with ibdknox

19:04 ibdknox: eskatrem: http://www.4clojure.com/

19:05 amalloy: anyway, eskatrem, i think what would help you most at the moment is a mastery of (let) and/or (loop). you're doing all these (def)s in places where they're just evil

19:05 eskatrem: I remember when I was 17 or so I wrote in basic a program to break down a integer into a product of prime numbers. it took me 1 hour, and now I am struggling with the same in clojure

19:06 ibdknox: eskatrem: this is a different way of thinking

19:06 you should try 4clojure

19:06 eskatrem: Now I get that a def inside a loop is bad, but I dont see why

19:06 amalloy: eskatrem: it's a side effect: you're telling the computer *how* to do something instead of *what* to do

19:07 eskatrem: hmmm

19:07 I need to ponder that, amalloy

19:07 tufflax: amalloy about adding project euler problems to 4clojure: how would that work exactly? I don't get it

19:08 eskatrem: 4clojure is cool I think

19:09 duck1123: ibdknox: do you know what it was about pinot that causes the "can't recur here"? Giving it another shot today

19:09 ibdknox: an older version of clojurescript has a problem with my macros

19:09 amalloy: tufflax: well, problem 4 could be something like "given a min, max, and filtering function, return the largest palindrome number which satisfies the filter and is a product of two numbers between min and max"

19:10 duck1123: Ok, cause I re-enabled the middleware again, and that's what I'm getting

19:11 eskatrem: how long have you guys been programming in functional programming?

19:11 amalloy: for example, my gist works out to something like "create the products of all 3-digit numbers, and find me the largest number which satisfies the following criteria", while yours is more like "set i to 0; set j to 0; set tmp to i*j; check if it's a palindrome and is larger than our largest palindrome; if so reset our largest palindrome. now set j to 1...."

19:12 ibdknox: duck1123: it's hard for me to reason about your setup

19:12 duck1123: one thing to try would be just create a noir project and see if it even works there

19:12 if not, it'll be easier for me to figure out why

19:13 duck1123: I got errors on OSX with that sample project, but it passed after an explicit clean

19:13 Haven't tried it on Ubuntu yet

19:14 ibdknox: yeah i had to clean a couple of my projects too

19:14 amalloy: mutability is contagious in that way; because you handle things like (def) yourself, you can't use the built-in (max) to compute the maximum, and instead have to maintain it yourself

19:15 tufflax: amalloy so you would try do steer people towards functional programming by modifying the problem just a litte bit?

19:15 amalloy: tufflax: no, it's just there should be multiple test cases, where euler tends to have a single problem and a single answer

19:15 tufflax: oh right

19:17 eskatrem: 4clojure is getting hard... and then it becomes so tempting to use the repl

19:17 amalloy: eskatrem: please, use the repl! it's good for you

19:18 eskatrem: hmm, if the question if (= __ (conj '(2 3 4) 1)), I can just enter to the repl (con '(2 3 4) 1) to see what it produces

19:18 amalloy: so? you've succeeded, by learning what that form evaluates to

19:18 nobody demands that you "figure it out"

19:19 jhulten: its only cheating if you don't learn anything

19:19 amalloy: (inc jhulten)

19:19 lazybot: ⟹ 1

19:19 eskatrem: hmm ok

19:19 sleepynate: jhulten: which is why i scripted a bot in clojure to automatically answer the questions for me :o

19:19 wait...

19:19 shit.

19:19 duck1123: That's one of the nice things about functional programming, it's easy to just run a fn, no heavy objects to set up to get it to run

19:19 eskatrem: &(conj '(2 3 4) 1)

19:19 lazybot: ⇒ (1 2 3 4)

19:19 Raynes: amalloy: Integrate try-clojure into 4clojure.

19:19 amalloy: Raynes: do it yourself, in cljs

19:19 ibdknox: lol

19:20 jhulten: sleepynate: If you managed that, you probably solved all the hard ones already.

19:20 ibdknox: good luck :-p

19:20 amalloy: ibdknox: it'll be a breeze with brepl, amirite?

19:20 tufflax: Hm, I kinda like project euler where they only require an answer. some problems can be done completely by hand, that's one reason. But also sometimes your code is just a mess after you have experimented. I just like that getting the answer is the only thing that matters. But anyway, I don't really see the point of making pe problems into 4c problems unless you really want more problems.

19:20 Raynes: amalloy: Seriously, it probably wouldn't be that difficult. Might be a good project for Carin.

19:20 ibdknox: amalloy: easy as pie. :D

19:20 eskatrem: hmm not cool, the stuff returned bu lazybot makes 4clojure return an error

19:22 amalloy: ##(1 2 3 4) is not the same as ##'(1 2 3 4)

19:22 lazybot: (1 2 3 4) java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

19:22 (quote (1 2 3 4)) ⇒ (1 2 3 4)

19:23 eskatrem: oh I get it

19:24 sleepynate: #(..) creates a macro?

19:24 tufflax: no a function

19:24 eskatrem: actually I knew the first one but I failed the second one all along, and 4clojure didnt tell me my answer for the first one was right

19:24 sleepynate: nvm reading :)

19:24 amalloy: eskatrem: it should turn the light green for each test you pass

19:26 eskatrem: amalloy: the question I was trying to solve (solved now) has two sub questions, when I put the first answer right and the second one wrong it doesnt make the first light green

19:31 is a *set* automatically sorted?

19:31 ibdknox: no

19:32 eskatrem: but a set is not ordered then?

19:32 tufflax: no... should it be? :P

19:33 there are sorted sets

19:33 ,(sorted-set 12 6 1 2)

19:33 clojurebot: #{1 2 6 12}

19:36 eskatrem: , (= #{1 2 3} #{3 2 1})

19:36 clojurebot: true

19:36 amalloy: hey, someone woke up clojurebot

19:37 eskatrem: so when clojure compares a set, it doesnt take into account the order

19:37 amalloy (ooops)

19:37 amalloy: eskatrem: there *is* no order

19:37 i mean, yes, internally they are necessarily stored in some order

19:38 but as an API, sets don't have an order

19:38 &#{3 2 1}

19:38 lazybot: ⇒ #{1 2 3}

19:39 eskatrem: ok, so *as a convention* clojure orders a set to show it, but that's all?

19:39 amalloy: no, it only gets ordered by coincidence

19:39 &(set (range 35))

19:39 lazybot: ⇒ #{0 32 1 33 2 34 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31}

19:43 amalloy: eskatrem: small integers happen to come out sorted, but that's just luck

19:43 eskatrem: ,#{0.3 -1 2.5 0.1}

19:43 clojurebot: #{-1 0.3 2.5 0.1}

19:44 eskatrem: ok, double values are not coming out sorted

19:44 Raynes: &(sorted-set 3 2 4 1023 30)

19:44 lazybot: ⇒ #{2 3 4 30 1023}

19:45 eskatrem: ,(= (sorted-set 0.3 1.2 0.1) #{0.3 1.2 0.1})

19:45 clojurebot: true

20:01 eskatrem: Guys, 4clojure is coool!!

20:01 amalloy: *laugh* glad you like it

20:01 source is at http://github.com/dbyrne/4clojure if you're interested

20:02 eskatrem: i bookmark that link

20:03 a lady made that! I am impressed

20:05 tremolo: xb

20:05 amalloy: eskatrem: new to github? she's the most recent committer, but it's not a one-person project

20:05 tremolo: hah, emacs fail... sorry about that

20:06 amalloy: https://github.com/dbyrne/4clojure/contributors

20:07 eskatrem: surprising to find two of the top contributors here...

20:09 tufflax: it is? :p

20:10 eskatrem: good work guys, I find myself impressed by my progress

20:11 here is my code for Nth:

20:11 (fn [x n] (loop [y x, i 0]

20:11 (cond (= i n) (first y)

20:11 :else (recur (rest y) (inc i)))))

20:11 (ok, I copied it from a sample code amalloy gave me yesterday)

20:12 amalloy: hey, i didn't write nth for you. now you know how loop works, so you wrote a good implementation of nth

20:13 eskatrem: yeah, but I feel I blantantly copied the loop mechanism from your code

20:13 st3fan: why cond instead of if?

20:13 eskatrem: still I am proud of my nth

20:13 amalloy: st3fan: probably because he copied the loop from an example i gave that had three branches :)

20:13 eskatrem: st3fan: because amalloy did so in a code he sent me yesterdasy

20:14 st3fan: :-)

20:14 amalloy: stealing is a tradition of open source. help yourself to my stuff

20:14 st3fan: where do you live?

20:14 eskatrem: uk

20:14 st3fan: i'll come and pick up your pc ok? :)

20:14 tufflax: lol

20:14 eskatrem: gonna go to sleep soon actually

20:15 amalloy: har har

20:17 st3fan: when i open-source my computer itself, you'll be the first person i call

20:19 st3fan: with your open source phone?

20:20 eskatrem: that's neat, my count function is timing out...

20:20 st3fan: i have some code too that hangs the thread

20:20 for no obvious reason

20:21 amalloy: your end condition is probably broken, because you're using rest and never seqing the result

20:22 eskatrem: (fn [x] (loop [y x, i 0]

20:22 (cond (= y nil) i

20:22 :else (recur (rest y) (inc i))

20:22 )))

20:22 that's my code, I guess (= y nil) must be somehow screwed uo

20:22 up

20:22 amalloy: &(rest [])

20:22 lazybot: ⇒ ()

20:22 amalloy: &(= nil ())

20:22 lazybot: ⇒ false

20:23 amalloy: &(= nil (seq ()))

20:23 lazybot: ⇒ true

20:23 eskatrem: ohhh

20:23 st3fan: eskatrem: oh don't but those closing braces there please

20:23 baaaaaaad style

20:23 amalloy: st3fan: it's true, but there are only so many things you can focus on at a time

20:23 eskatrem: you mean, a bunch of closing brackets in the same time is bad?

20:24 amalloy: i figure he'll eventually see enough code with parens right that he'll figure it out

20:24 st3fan: ok

20:24 amalloy: eskatrem: just the opposite. a line that contains only closing brackets is bad

20:25 eskatrem: hmm I thought closing brackets where like } in C, in C it's cool to have a line containing }, AFAIK

20:26 tufflax: but, at least as far as i'm concerned, i don't want my code to remind me of c or anything like it

20:26 amalloy: *chuckle*

20:32 eskatrem: when I submit an answer, is my code stored somewhere?

20:39 st3fan: i'm working on a little dsl for web services

20:39 to do APIs very similar to Amazon Web Services

20:41 mdeboard: eskatrem: no, just whether you solved it or not

20:41 eskatrem: alright, thank you

20:43 amalloy: mdeboard, eskatrem: untrue. we save your most-recent correct solution

20:44 eskatrem: ooh, neat

20:44 amalloy: eskatrem: try going back to a problem you've already solved - your answer is there

20:45 sritchie: is there some way to catch an exception thrown for an undefined var?

20:46 I'm trying to add a prepend-tasks hook in project.clj for native-deps, but native-deps requires deps to be run first

20:47 amalloy: sritchie: those happen at compile time, don't they? you can't really catch them because they happen before your code runs

20:48 instead you probably want to do like (when-let [my-var (resolve 'my-var-name)] ...)

20:50 sritchie: it works with eval, though I'm not sure that's the best form:

20:50 (try (eval `(do (require 'leiningen.native-deps) (append-tasks #'deps leiningen.native-deps/native-deps))))

20:50 with an appropriate catch statement

20:51 amalloy: sritchie: eval definitely looks wrong. does a resolve-based solution not work?

20:52 sritchie: amalloy: hmm, had trouble with it before, since I still needed to send the value of the var I obtain into append-tasks

20:53 though that's probably easy -- I'm blanking on the way to get at a value, given a var

20:53 amalloy: @

20:53 sritchie: ah

20:53 amalloy: a one-character solution to all your problems - who could ask for more

20:54 sritchie: haha, it's quite a panacea

20:54 trying it out now

20:55 yup, all's well… definitely beats eval

20:55 amalloy: thanks a lot

21:03 livingston: I wrote a bunch of tests with clojure.test and now realize the work equally well for another set of my code, it seems dumb to cut and paste when the only thing that changes is a *star* variable...

21:03 any good way to reference a set of tests and run them twice in different binding scopes?

21:05 eskatrem: I finished the 1st page of 4clojure. I am going to bed now. thanks everybody!

21:05 lucian: livingston: why not factor out a fn that takes that variable as an argument?

21:07 livingston: I could seemed odd of even have to repeat the tests if I could help it. then I'd have (deftest foo-test (is (foo A))) in one file and (deftest foo-test (is (foo B))) in another

21:11 lucian: livingston: i'd make a (defn is-foo ...) to import in both test files

21:12 livingston: lucian: I could imbed the "is" too it doesn't need to be inside deftest?

21:12 lucian: livingston: don't really know

21:13 livingston: the problem here is remembering to update both files ... I'll probably just macro around it... just was hoping for something slicker.

21:13 lucian: livingston: wouldn't a fn be enough? does it really need a macro?

21:14 depends on the context of is i guess

21:14 livingston: if I want them to register as a lot of different tests so it's easier to tease out where the failure is. I should look at clojure.test documentation more..

21:15 is doesn't need to be in deftest

21:24 technomancy: livingston: deftest generates function

21:24 *functions

21:25 if you (deftest my-foo-test) you can just call (my-foo-test) from another test

21:25 hiredman: ~ping

21:25 clojurebot: PONG!

21:25 amalloy: deftest is absurdly macro-heavy. an (is) that's not inside a deftest won't work

21:26 technomancy: amalloy: not actually true

21:26 maybe you're thinking of thrown? outside an is?

21:27 because that one's annoying

21:28 amalloy: technomancy: i don't think you're right. `is` is a symbol that's parsed specially by the deftest macro, not a macro/function that's actually defined

21:28 also, i just checked and i'm wrong about that

21:28 so never mind, technomancy

21:28 technomancy: ,(ns-resolve (doto 'clojure.test require) 'is)

21:28 clojurebot: #'clojure.test/is

21:28 technomancy: yay doto abuse

21:29 amalloy: $sed technomancy s/abuse/magic

21:29 lazybot: <technomancy> yay doto magic

21:29 technomancy: amalloy: thrown? is like that

21:29 amalloy: *nod*

21:29 i must have gotten them confused in my head somewhere

21:29 cemerick: Bots with sed. I'm going to go stock up on canned goods.

21:30 amalloy: cemerick: is that a sign of the apocalypse?

21:31 cemerick: amalloy: Close enough for me! :-D

21:33 livingston: sorry spaced out for a second...

21:34 I could call all the test from the second file but then I would still have to make sure I keep them synchronized.

21:35 amalloy: (ns a) (defn run-all-the-damn-tests [] (...)) (ns b (:require a)) (a/run-all-the-damn-tests)

21:35 livingston: basically what I have is two implementation of an API. I'd like to write all the API tests once, and then have both implementations check themselves against it.

21:36 so I found run-tests that allows me to call tests in another namespace... I think I can bind over my *star-var* and then call that, I was just about to test that.

21:36 cemerick: Bugger, nil-safe threading ops should be in core by now.

21:38 livingston: ideally I'd like the tests defined in the API test-namespace, but not run (how could they there's no implementation there) and then run for each of the implementations.

21:39 pwd

21:39 ^ wrong window

21:40 amalloy: livingston: c'mon, correcting it is no fun. you want to give someone a chance to jump in there with "#clojure"

21:40 livingston: sorry didn't realize that was protocol

21:40 st3fan: any compojure experts here? i have troubes getting a basic route to work

21:41 amalloy: ~anyone

21:41 clojurebot: Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help.

21:41 livingston: amalloy: lazybot or some bot should have yelled at me.

21:41 lol, like that

21:41 st3fan: i have this route: (GET "/ws" {params :params} (dispatch-action params))) .. i can call it with /ws?action=Foo but params is always an empty map

21:46 amalloy: st3fan: (a) there's a #compojure room, but i don't know how much traffic it gets; (b) do you have a middleware in place that will parse out the params for you?

21:47 st3fan: yeah i guess that is what i need

21:48 amalloy: if you don't have something like wrap-params intervening, nobody's going to put anything in that :params map

21:49 also (c) i can never remember the compojure syntax for (GET) stuff, so there might be something wrong with your {params :params} binding too

21:52 ShreeMulay: Anyone around that can help me solve a 4clojure problem? @ http://www.4clojure.com/problem/19#prob-title

21:53 I can't use "last" so I'm at a loss, eh...

21:53 jeremyheiler: What have you tried?

21:53 ShreeMulay: last

21:53 they don't want me using that, though...

21:54 and I really don't know enough, to be able to think of what next to try unfortunately... :(

21:55 jeremyheiler: $((peek [1 2 3]))

21:56 damn. what's the clojurebot syntax?

21:56 for running code

21:56 amalloy: ,

21:56 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

21:56 amalloy: or & for lazybot

21:57 jeremyheiler: ,((peek [1 2 3]))

21:57 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

21:57 livingston: do namespace names with hyphens get munged to underscore too? e.g. does foo.foo-core.bar-code become foo/foo_core/bar_code.clj ?

21:57 amalloy: ShreeMulay: the point is to reimplement last yourself

21:57 jeremyheiler: ,(peek [1 2 3])

21:57 clojurebot: 3

21:57 amalloy: livingston: yes

21:57 because they're java package names

21:58 jeremyheiler: Shree: As you can see, peeking on a vector gives you last

21:58 livingston: amalloy: thanks. great, time to mess with what in subversion...

21:58 jeremyheiler: however

21:58 ,(peek '(1 2 3))

21:58 clojurebot: 1

21:58 jeremyheiler: The same thing on a list doesn't work

21:58 this is because lists are designed for adding/removing from the front, where vectors were designed for adding/removing from the back.

21:58 Play with that thought for a bit

22:00 * amalloy wonders where jeremyheiler is going with this

22:00 jeremyheiler: ,(peek (vec '(1 2 3)))

22:00 clojurebot: 3

22:00 jeremyheiler: It's not good code, but it works

22:01 amalloy: meh. i'd classify that more as a "trick" than a solution to the problem - being able to implement `last` yourself is valuable

22:01 not that i'm against tricks

22:01 jeremyheiler: Yes, I agree

22:02 I was more-or-less playing golf with 4clojure lol

22:02 ruggeri: Any advice for newbies on defrecord? It's a shame print-dup doesn't produce something that can be you can call read-string on.

22:03 There's this defrecord2 guy

22:03 amalloy: ruggeri: it does in 1.3

22:03 ruggeri: Oh snap

22:03 Thanks; will check it out now

22:03 amalloy: jeremyheiler: the shortest solution for problem 19 is 8 characters long, and it's hysterical. any guesses?

22:05 cemerick: Everyone just uses snapshots, alphas, and betas anyway; Clojure should follow the path of chrome, version up to Ω-SNAPSHOT, and everyone can just ride HEAD. :-P

22:06 jeremyheiler: hmmm

22:07 ruggeri: yeah, records being second-class was about to super-depress me

22:07 amalloy: ruggeri: that said, "newbie" and "record" don't belong in the same sentence

22:08 they're an advanced feature, however appealing they look when you're coming from an OOP background

22:08 ruggeri: why do you say so? I want to implement me some multimethods

22:08 amalloy: ruggeri: so write some multimethods; you don't need protocols for that

22:08 (or records)

22:08 ruggeri: but what's my dispatch function? I would call something like class or type, right?

22:09 cemerick: records are a proper replacement of structs, which are reasonable for any "level" of usage, IMO.

22:09 ShreeMulay: peek is interesting - but can't figure out how to "reimplement last" cause, I frankly don't know enough clojure - haven't used it enough...

22:09 amalloy: (defmulti pluralize count) (defmethod pluralize 1 [objs] (str "1 thing: " (first objs)))

22:10 (defmulti pluralize 0 [_] "No things at all!") ;;etc

22:11 ruggeri: Fair enough; but what if I have two different dog objects, and they bark differently?

22:11 ShreeMulay: peek works for the vector... somehow, I've got to create a function... Is "peek" gonna' be part of the function I need to put together, guys?

22:11 on problem #19?

22:12 jeremyheiler: It's not

22:12 ruggeri: I want (bark big-dog) ; -> growl

22:12 (bark lil-dog) ; -> yip-yip

22:12 jeremyheiler: ShreeMulay: Look up how to use recur

22:13 amalloy: ruggeri: *shrug* you can make a record for that, and define a protocol for barking. or you can use a plain map, and a dispatch function that looks up the :kind-of-dog key in the map. or you can do any number of things

22:13 jeremyheiler: amalloy: I give lol

22:13 amalloy: jeremyheiler: rand-nth, and hitting the submit button ~40 times

22:14 jeremyheiler: hahaha

22:16 ruggeri: amalloy: yeah, definitely could manage a canonical mapping of dogs to bark behaviors

22:16 st3fan: hmm Clojure in Action has an compojure example that import compojure using (ns foo (:use compojure)) but when I try that I get an import error

22:17 ruggeri: amalloy: I'll start there; it'd be a pain for one-place to centralize every type of dog in existence for a huge project, but good idea to keep things simple maybe

22:17 amalloy: i think that the concept of "but someday i might have a thousand different kinds of dogs!" is overemphasized in OO code

22:18 ruggeri: amalloy: I hear you; makes sense

22:18 amalloy: i'm a fan of splitting things up when they need to be; i'm addicted to defmulti and i write protocols when they make sense

22:18 but they're not the sorts of things that give you a feel for how the language is different from (say) java

22:19 do some sequence manipulation, recursion, and function composition. those are things that you don't get much of in java

22:19 livingston: amalloy: I think that the concept that everything needs a class is over emphasized, why have one function and some configuration when you could have the land of 1000 classes

22:20 amalloy: anyway, i'm headed home. ta-ta

22:20 ruggeri: amalloy: night

22:20 livingston: later

22:21 jeremyheiler: later

22:24 ShreeMulay: KILL

22:24 QUIT

22:42 pcavs: how do people do reading files from the classpath?

22:49 technomancy: pcavs: clojure.java.io/resource

22:49 pcavs: technomancy: thanks

22:50 technomancy: sure

22:55 st3fan: is there a better way to update nested maps than nested assoc calls?

22:58 cemerick: st3fan: assoc-in and update-in

22:58 st3fan: thanks

23:00 oh assoc-in is nice

23:04 cemerick: st3fan: they work with any 'associative' as well…not just maps

23:04 ,(update-in [5 6 {:a [\b \c \d]} 7] [2 :a 1] str)

23:04 clojurebot: [5 6 {:a [\b "c" \d]} 7]

23:08 st3fan: yeah very cool

23:08 how do i test if a condition is true for each element in a vector?

23:09 amalloy: &(doc every?)

23:09 lazybot: ⇒ "([pred coll]); Returns true if (pred x) is logical true for every x in coll, else false."

23:09 st3fan: argh i was looking for each? :-/

23:13 livingston: stupid question, what's fncall in clojure ie. I have a list of functions I just want to map through them and call them.

23:13 (map (fn [x] (x)) functions) seems dumb

23:13 amalloy: $findfn even? [2 4 6] true

23:13 lazybot: [clojure.core/not= clojure.core/some clojure.core/distinct? clojure.core/every?]

23:13 amalloy: livingston: (

23:13 oh, i see

23:14 yes, i wish invoke would make it into core also. it doesn't really exist

23:14 livingston: so there's nothing?

23:14 amalloy: livingston: fwiw, #(%) is the shortest way to write it :P

23:15 livingston: I really despise that % syntax, I find it lending itself to too much confusion

23:15 amalloy: but (fn [f & args] (apply f args)) is a useful thing to have defined somewhere. i call it invoke because of IFn.invoke, but i guess funcall is more traditional

23:16 st3fan: you caught the use of $findfn for your benefit, right?

23:16 livingston: I don't need apply, they are thunks, with no arguments

23:17 in common-lisp is LISP2 so you need a fncall there was no (foo) to call the function in foo like you can in LISP1

23:18 is there anyway to deftest in a namespace but not have it called with clojure:test and only have the functions there to call with another namespace?

23:19 amalloy: livingston: i'm aware. if you look at it, you'll see i just wrote funcall

23:20 &(let [funcall (fn [f & args] (apply f args))] [(funcall +) (funcall + 1 2)])

23:20 lazybot: ⇒ [0 3]

23:20 amalloy: ie, it works for thunks or with args

23:21 cemerick: Just adding a single-arg arity to apply would be equivalent, no?

23:22 amalloy: cemerick: not equivalent to my definition, no, because (apply + 1 2) wouldn't work

23:22 perhaps equivalent to what livingston needs at the moment

23:22 livingston: yeah. it's equivalent, except for the list cons-ing

23:24 ... all this work just to call some tests twice *sigh* 4 hours in...

23:28 amalloy: hey livingston, can you point me at some public, preferably not-totally-trivial code you've written? i had the idea recently to look at how ye olde lispers write clojure

23:29 livingston: um, hum I don't know that I have any - but I am in the process of preparing a large library of code for dealing with RDF.

23:31 amalloy: I'm not exactly an old lisper but I was trained by them and programmed my entire dissertation in it.

23:32 the biggest thing that's kicking me in the pants is dynamic not lexical scope. there are a ton of cool tricks with lexical scope that get fubared by lazy-list / deferred evaluation in dynamic scope

23:34 amalloy: livingston: CL has the same scope rules as clojure, doesn't it? it's just that clojure has a lot more lazy bits

23:35 cemerick: How is the CL world doing these days in general? Anyone keep tabs on it?

23:35 livingston: amalloy: no dynamic vs. lexical scope for special variables that can be bound ove is a huge difference

23:35 cemerick: it's fine. AI people still use it as always.

23:35 amalloy: livingston: but clojure's lexical variables are the same as CL's, and clojure's vars are the same as CL's specials, i thought

23:35 livingston: every time you buy a plane ticket there's lisp under the hood ;)

23:36 cemerick: yeah, but every time I swipe my credit card, an AS/400 gets its wings. Not really a good barometer, perhaps. :-)

23:36 I wonder about its vector more than anything else. Growing, shrinking, etc.

23:36 I would think that the heat around Clojure and other FPLs must help.

23:37 amalloy: cemerick: functional? CL isn't exactly functional

23:37 livingston: lol

23:38 CL is plenty functional when coded well, although there are the people that call it hybrid or whatever.

23:38 cemerick: Exactly, no — but before state was a big concern, Lisps were always considered functional in the functions-are-first-class-values sense.

23:40 amalloy: i was just reading that in let-over-lambda, actually

23:40 cemerick: This floated by in the transom a few days ago; I'm not sure whether to interpret the results as positive or negative overall, tho. http://www.indiegogo.com/SBCL-Threading-Improvements-1

23:42 livingston: you have to remember that CL was standardized before file-systems/sockets/threads had any major standardization, consequently those things have been ideosyncratic in lisps

23:42 dnolen: cemerick: why negative?

23:43 livingston: but there are generally libraries that will present a layer over your specific implementation

23:43 cemerick: livingston: Right, I'm mostly looking at community participation / size / engagement / commitment.

23:44 livingston: depends on what's necessary for you to define a community.

23:44 cemerick: dnolen: I can see it both ways. (a) it's clearly a vital community ready to step up and support key contributions with hard cash vs. (b) The premier open source CL impl can garner "only" $9K to solve probably its most long-standing and most-griped-about problem?

23:45 grant_: man, how do you debug errors that have no source code line?

23:45 any tips or tricks aside from weeping and gnashing your teeth?

23:46 dnolen: grant_: what dev environment?

23:46 grant_: emacs, swank, clojure 1.3beta (i updated to see if it would make a difference... it didnt :( )

23:46 livingston: symbolic AI guys like it. (and I'm one) do I care that few games, websites, or mcdonalds ordering systems are written in it, not really. frankly if those guys all had their way everything would look like java, and we know what kind of fun that is ;)

23:46 dnolen: grant_: are you evaling fn's one at time or the whole file?

23:46 grant_: whole file

23:46 i stepped through evalling each one and they all evalled fine

23:47 dnolen: grant_: what is the exception?

23:47 cemerick: livingston: Willingness to lay out cash seems like a pretty unassailable metric of engagement. Fundraisers like that are one manifestation, another might be attendance figures at yearly confs, etc.

23:47 amalloy: grant_: that's not a whole file at once; that's one-at-a-time, over-and-over

23:47 grant_: clojure.lang.Cons cannot be cast to clojure.lang.IFn

23:47 i'm saying i did both that and whole-file evaluation

23:47 amalloy: okay

23:47 dnolen: &((cons 1 nil) 1)

23:47 lazybot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

23:47 livingston: SBCL is a popular open source lisp true. But Franz makes the Allegro compiler and they are doing quite nicely as a company.

23:48 dnolen: &((cons 1 ()) 1)

23:48 lazybot: java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.IFn

23:48 dnolen: grant_: ^

23:48 grant_: right

23:48 so i should be on the loop out for extra parens

23:48 livingston: with their lisp they created AllegroGraph which is as a far as I know one of the best of breed triple/quad stores (RDF/OWL etc.)

23:48 amalloy: grant_: or something quoted where it shouldn't be

23:49 grant_: but is there is a faster way to narrow this down besides manual inspection?

23:49 amalloy: grant_: read the stacktrace to see which of your functions are in it

23:49 cemerick: livingston: right — maybe all the real users of CL in industry are on Allegro and Lispworks. If they released sales figures, that'd make these sorts of judgements a lot easier… ;-)

23:49 dnolen: grant_: if there's no source line after C-c C-k it's happening during compilation so very certain to be a syntax error.

23:49 amalloy: and see if there are any clojure.lang.Compiler methods - if so it's a problem with macroexpansion

23:49 grant_: a syntax error??

23:49 cemerick: The fellow who wrote AllegroGraph lives a few miles from me. Very nice guy.

23:50 grant_: my only function appearing in the trace is my top-level main fn

23:50 oh yeah, i do see a Compiler method

23:51 livingston: cemerick: I think there are several "fellows" including the CEO of Franz who work on it.

23:51 pcavs: has anyone played around with noir?

23:52 livingston: cemerick: the people that use Franz lay out cash, the licenses are not cheap.

23:52 amalloy: &(let 1 2)

23:52 lazybot: java.lang.IllegalArgumentException: let requires a vector for its binding

23:52 cemerick: livingston: IIRC, he was the tech lead, anyway. *shrug*

23:52 amalloy: that one would be at compile-time as well

23:52 cemerick: memory fades, too :-P

23:52 livingston: cemerick: he's a nice guy too, John, right?

23:54 cemerick: livingston: Gary King is the one I know.

23:54 Man, it's been a while since I talked to him, too. :-(

23:54 livingston: also a nice guy, I've worked with him some too.

23:56 grant_: amalloy, dnolen: thanks guys, that helped!

23:56 dnolen: grant_: what was it?

Logging service provided by n01se.net