#clojure log - Aug 29 2011

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

0:02 ibdknox: haha yeah I just found that out

0:02 I created several rows of those

0:02 and they're destroying

0:02 amalloy: yeah

0:03 whereas if you have a big group of orange guys, they tend to all attack one enemy, and then take time recharging

0:03 haha wait, i don't even like tower-defense games, why am i doing this?

0:03 ibdknox: lol

0:03 cuz it's AWESOME

0:04 ;)

0:04 amalloy: fo sho

0:04 ibdknox: it was fun

0:04 lots of learning. I had never used canvas before

0:04 and never really written a game

0:11 michaelr525: hello!

0:18 icey: ibdknox: i think it's pretty fun; i like the geometry of it

0:18 ibdknox: icey: haha, drawing those in code was interesting

0:18 icey: the rects are obviously really easy

0:19 icey: ibdknox: do you think you'll try a clojurescript port later?

0:19 ibdknox: icey: the purple teleporting ones too some drawing

0:19 icey: I was thinking about it

0:19 icey: I don't know that clojure works very well for games though

0:20 icey: ibdknox: trying to think of any games that were written using a functional lang

0:20 amalloy: $google purely functional games

0:20 lazybot: [prog21: Purely Functional Retrogames, Part 1] http://prog21.dadgum.com/23.html

0:21 ibdknox: yeah, I've read through those

0:21 I might still do it anyways

0:21 just to see what it's like

0:22 I definitely missed parts of clojure while doing it

0:22 amalloy: well, let's hope you find out it's *not* like chewing on glass

0:22 ibdknox: I used underscore.js to get some of the functional stuff, but it's just clunky compared to clojure

0:23 amalloy: lol does he say that in there?

0:23 amalloy: who what?

0:23 oh. no, that was me

0:23 ibdknox: sounds painful

0:24 * ibdknox makes a mental note not to do it ;)

0:26 amalloy: ibdknox: the number of enemies per wave does keep going up, though, right? ie if i stop building new towers i should lose eventually, even if it takes a few years?

0:26 ibdknox: amalloy: yes

0:26 amalloy: and they get progressively beefier

0:27 though that multiplier seems too low

0:28 icey: 2 things would make this awesome: an ability to delete blocks, and a way to share final tower configuration with friends

0:29 (like a url to a savegame)

0:29 ibdknox: icey: yeah, I wanted to do deletes and upgrades, but there's no simple way to handle clicks on a canvas

0:29 icey: ibdknox: wow, that blows

0:29 ibdknox: icey: I basically have to do collision detection with the mouse cursor

0:29 that's how the hovers work

0:30 icey: having all the baddies take a single route makes me want to challenge people with stuff like "how long can you last with just 100,000kb"

0:30 actually, probably much less than that

0:31 amalloy: much less, yeah

0:31 icey: 5k, 10k maybe

0:32 amalloy: i've spent less than 100k, and on wave 31 i didn't see an enemy survive long enough to enter the screen

0:33 100k...kb. ibdknox, you're a horrible person for using units like "274000kb"

0:36 ibdknox: haha

0:36 just to screw with you ;)

0:45 akhudek: oh man, that's too bad

0:46 my clojureql hack only works with persistent database connections :/

0:46 tldr: would love to have the autogenerated id of an inserted record returned somehow

1:08 MasseR: mudge: There's the JVM startup time, or if you keep the jvm running, the jvm doesn't update it's path, which might also cause problems

1:08 But you could look into jark and/or nailgun

1:42 furd: Is the 1.3 beta 2 known to be much slower than 1.2.1?

1:43 I'm doing Project Euler and one of my programs runs in 1.9 seconds in 1.2.1 and 20 seconds in 1.3.0-beta2

1:44 hiredman: furd: care to share?

1:44 furd: I'll put up a gist

1:55 https://gist.github.com/1177848

1:56 wastrel: seconds

1:56 furd: seconds

1:58 hiredman: get rid of the (int ...) calls

1:58 amalloy: and don't use an int-array either

2:00 furd: Is that just general coding practice advice or would that have any kind of impact in going from 1.2.1 to 1.3.0?

2:01 amalloy: both

2:01 furd: I appreciate any kind of coding practice help as I definitely need it

2:01 hm

2:01 amalloy: 1.3 defaults to using longs instead of ints

2:01 hiredman: and defaults to primitive longs

2:02 amalloy: so your arithmetic does a lot of back-and-forth from long to int, and possibly from boxed to unboxed as well

2:05 furd: Hm okay I'll try writing it with that in mind and see if that gets the times more in line with each other

2:05 I was just very confused as I rewrote the sum-divisors function to be much faster and was getting much longer times

2:06 Until I realized I had decided to try 1.3

2:09 Thank you very much!

2:24 scottj: where is goog.dom.query in closure's api docs?

2:28 amalloy: furd: if you're interested, i wrote a solution that is short but not very fast: https://gist.github.com/1177884

2:31 furd: Ooh awesome thanks I will try to absorb what I can from that!

2:31 ibdknox: scottj: it's a port of dojo's query stuff

2:32 furd: I got rid of the primes-to function by using the contrib.lazy-seqs prime generator

2:32 https://gist.github.com/1177848

2:32 And the difference is now 2.3 seconds in 1.2.1 to 17.3 seconds in 1.3.0-beta2

2:33 scottj: ibdknox: when I require just pinot.html I get an error saying goog.dom.query not provided

2:33 ibdknox: scottj: grab the goog-jar.jar that came down as a dependency and put it in clojurescript/lib/

2:33 remove the goog.jar

2:33 that's in there

2:34 furd: amalloy: Thank you very much, I've never used letfn before so some reading is in order!

2:34 scottj: ibdknox: add that to README?

2:34 amalloy: meh, it's just defn but lexically scoped instead of global

2:34 ibdknox: scottj: it's on the mailing list, and it will be

2:35 clojurescript's bootstrap doesn't package up all of closure, sadly

2:35 furd: ah okay

2:37 scottj: ibdknox: thanks

2:38 amalloy: furd: my solution is a little silly, looping through all the numbers twice, because i started out misunderstanding their definition of amicable numbers

2:44 furd: amalloy: Nice to see another way of doing it anyway

2:45 amalloy: I've never programmed functionally before and I just started with Clojure about a week ago, all the examples I can get are great

2:46 Though I'm still really confused as to why my fairly simple, now efficient prime generating code takes so much longer in 1.3

2:48 amalloy: yeah, i dunno

2:54 furd: Is there some place I should submit the gist?

3:01 ibdknox: scottj: added

3:36 tsdh: Is there a way to write readable clojure structures to a file so that I can load it back later? (spit "foo" [1 2 3]) writes [1 2 3], but (spit "foo" (doall (take 10 (iterate inc 0)))) writes clojure.lang.LazySeq@25b1c106...

3:37 ibdknox: ,(doc pr-str)

3:37 clojurebot: "([& xs]); pr to a string, returning it"

3:37 ibdknox: ,(pr-str (map inc [1 2 3]))

3:37 clojurebot: "(2 3 4)"

3:38 tsdh: ibdknox: Ah, great. That does the trick!

3:39 Ok, and a related thing: Is there a way to define a costom read/print syntax for arbitrary objects?

3:43 amalloy: tsdh: http://amalloy.hubpages.com/hub/Dont-use-XML-JSON-for-Clojure-only-persistence-messaging is an article i wrote a while ago about both of those topics

3:47 tsdh: amalloy: Great, thank you.

5:56 MasseR: How come I get "No matching method: symbol"

6:05 Macros weren't as simple as I thought :P

6:21 (defmacro foobar [key] '(let [x# ~key] (name x#)) works as expected. If called with (let [y :helloworld] (foo y)) returns "helloworld", but I can't get the "helloworld" out if I unquote that expression

6:22 For example (defmacro foobar [key] (let [x (gensym)] `(let [x ~key] ~(symbol (name x))))

6:30 Chousuke: MasseR: you need to do `(let [~x ~key] (symbol (name ~x)))

6:31 MasseR: keep in mind that x is in the local scope of the syntax-quote form so ~x evaluates to whatever gensym returned

6:34 nizze: Hi! I have been doing OO (in dynamic languages, e.g. Ruby) for last 5 years and now I think about software through OO gogles

6:34 goggles

6:35 Noh, Clojure "does not do OO" or it's not the Clojure way. How to get rid of OO way of thinking and start thinking Clojure way?

6:35 I'd like to have some concrete examples like how to build a blog in Compojure.

6:42 thorwil: nizze: you could have a look at https://github.com/ibdknox/Noir-blog

6:43 nizze: thorwil: Thanks!

6:43 I'm currently reading the Joy of Clojure by @fogus one of the best IT books, heck the best IT book I have stumbled upon.

6:45 Chousuke: nizze: I think it helps to have others critique your code

6:45 kaiwren: nizze: Read the SICP. Do the exercises. It'll help hugely with the OO centric view *and* help you write better OO FWIW.

6:46 nizze: kaiwren: Really? I'll add it to my reading list. What would be a good Scheme environment to use with the book? DrScheme?

6:47 miclorb: is there a dedicated room for leiningen or kosher to chat here about it?

6:47 kaiwren: nizze: They suggest a few things in the intro. You can use whatever editor you prefer, actually.

6:47 nizze: Thanks!

6:48 Chousuke: also you can try reminding yourself to do a double-take on any design/implementation decision you make and consider if it's using enough FP tools. For Clojure in particular, you will want to avoid loop, overusing defrecord, most of the mutation facilities; and use lots of small, independent functions, lazy sequences and clojure-provided functions to work with them

6:48 nizze: Okay.

6:49 thorwil: nizze: afaik DrScheme is no more (if you don't dig out an old version). I think I read that DrRacket and Racket's Scheme profile have some incompatibilities with SICP

6:49 Chousuke: You'll need some mutation of course but lots of people try to emulate actual mutation with them and end up having lots of atoms and refs everywhere. that's not usually a good thing :)

6:55 thorwil: good thing i have no clue about atoms and refs at all ^^

7:02 nizze: Thanks. I'll really have to dig to SICP then (right after JoC) how about the Grahams book? Is it any good?

7:04 pyr: nizze: it seems people use racket for scheme these days

7:04 nizze: the grahams book seems to be hard to find

7:05 are there release notes anywhere for clojure 1.3.0beta2 ?

7:05 nizze: pyr: thanks.

7:06 thorwil: you mean this: http://www.paulgraham.com/onlisp.html ?

7:06 pyr: yes

7:07 i'm a bit of a bitch, but these kind of books i enjoy reading in paper form

7:08 thorwil: well amazon offers 18 used from $89.10 ... makes reading on screen more attractive than usual ;)

7:08 pyr: yep

7:19 robermann: pyr: http://dev.clojure.org/display/doc/1.3

7:20 pyr: robermann: thanks

7:21 wunki: I can't seem to install clojure-1.2.0 from clojars. Is it down? Or is it my connection?

7:30 robermann: ho committato sulla M061N il merge dalla M060N

7:30 Netpilgrim: wunki: The artifact is also in maven central.

7:31 robermann: ops, sorry, wrong tab :)

7:33 wunki: Netpilgrim: I'm using leiningen and a project.clj, can I redirect it to maven central? (just started clojure)

7:35 Netpilgrim: wunki: Sorry, I've never used leiningen, only maven. I had assumed that leiningen also looks in the central repository by default.

7:35 wunki: Netpilgrim: np, thanks for the suggestion

7:36 Netpilgrim: I'd find it quite odd if Leiningen's artifact lookup did not default to maven central. Perhaps someone else here can comment on that?

7:42 wunki: You can try adding maven central manually to your leiningen config. The URL is http://repo1.maven.org/maven2/.

7:43 wunki: Netpilgrim: Thanks, will try it

7:45 Netpilgrim: Speaking about Leiningen, could someone explain to me the advantage of using it over Maven?

7:46 manutter: The advantage is that if you don't already know maven, it's a lot easier to pick up leiningen

7:48 Netpilgrim: manutter: OK. But Leiningen probably supports fewer features?

7:49 manutter: Well, I think it uses maven under the hood, so it's more like a simplified interface

7:51 Netpilgrim: manutter: Sounds like a good idea for people who haven’t used Maven before. I was just wondering if I was missing something by sticking to Maven.

7:52 manutter: The only thing you might be missing is some of the lein plugins like lein noir and lein midje

7:53 Netpilgrim: manutter: I don't know the plugins. But if Leiningen is just a wrapper for Maven, wouldn't it be better to write plugins for Maven and then just use them through Leiningen like the rest?

7:55 manutter: Well, that might be an opinion question :)

7:55 Netpilgrim: manutter: Since I know neither Leiningen nor the plugins, I'm not offering one. :)

7:55 manutter: It's easy to write lein plugins in clojure, not sure how hard it would be to write a maven one

7:59 Netpilgrim: manutter: From the Leiningen FAQ: “Leiningen only uses the dependency resolution parts of Maven”. So there is no way to use Maven plugins.

8:00 manutter: aha, there you go then

8:00 raek: lein has maven central by default. you don't need to add it.

8:01 and clojure is not on clojars, but in another maven repo (which lein knowns about)

8:01 wunki: which artifact are you adding to the project.clj?

8:02 wunki: raek: I narrowed it down to "lein-ring"

8:02 raek: which has a dependency on clojure 1.2.0

8:02 raek: that seems to hang the "lein deps" process

8:10 kzar: I'm doing this puzzle: http://4clojure.com/problem/26#prob-title . I've written a function that works fine but I used defn to define it. Problem is defn turns out to be forbidden. How can I define a function that can refer to itself for recursion without defn? This is what I have http://paste.lisp.org/display/124341

8:11 Netpilgrim: kzar: (fn name [...] ...)

8:12 raek: kzar: you can have a "named anonymous function": (fn f [...] ...), where f can be used in the body to access the function itself

8:13 you don't need to use that very often, except for sandboxes like in 4clojure

8:19 kzar: raek: Aha thanks

8:19 It's like a constant variable and a good boyband, a named anonymous function

9:06 chouser: dnolen: Surely IPersistentVector (a type name) is *less* generic than 'vector?' (a function), not more?

9:20 pyr: the noir features for clojurescript seem really cool

9:25 michaelr525: helloooo

9:31 saml: hey, how can I compile clojure file and run it?

9:32 i want to put a clojure compiler/interpreter in an OSGi container. clojure files are storied in JCR

9:32 not sure how modules would work

9:35 stevenfx: saml: Compile clojure to class?

9:35 saml: no.. i'm not familiar how clojure interpreter works.. does it compile to bytecode?

9:36 stevenfx: saml: Yeah i think so check http://clojure.org/compilation

9:36 saml: tahsnk

9:37 stevenfx: saml: No problem

10:04 chouser: brb

10:05 heh, wrong window

11:21 TimMc: amalloy_: Did you make a more advanced findfn at some point?

11:21 I seem to remember some variant.

11:34 $findargs 1 2 3

11:37 kzar: Anyone see a better way of doing the rotate puzzle http://4clojure.com/problem/44 ? Here's my solution http://paste.lisp.org/display/124344

12:07 TimMc: kzar: Basically the same as mine, though I used (concat (drop n col) (take n col))

12:11 kzar: TimMc: How 'bout this, my shot at the longest-increasing one http://paste.lisp.org/display/124345

12:12 Not pleased with it really, works though

12:12 TimMc: kzar: https://gist.github.com/1178735

12:12 (final solution to rotate puzzle)

12:13 kzar: What is longest-increasing's problem ID?

12:13 kzar: http://4clojure.com/problem/53

12:16 TimMc: thanks

12:17 Ah, I don't have a solution for that one yet. I've been sort of poking around randomly.

12:17 kzar: Yea me too, that one's a puzzler anyway

12:17 at least it was for me

12:26 manutter: woohoo, made it onto page 1 of the 4clojure "Top Users" list :)

12:27 joly: nice :) I was there and stopped for a while, but I started working on the problems again

12:28 manutter: yeah, these guys got me going again

12:29 Now I have to learn graph theory for problem #89.

12:33 pdk: nah

12:33 just copy paste euler's solution :p

12:34 kzar: The trick to a lot of the puzzles is to do (source restricted-function) and paste it in, goes against the point though

12:34 manutter: Heh, that's no fun!

12:35 joly: oops, I read that as visiting every node once

12:40 Mike|home: Can Clojure maps take a default value if a key is missing?

12:41 Bronsa: ,(doc get)

12:41 clojurebot: "([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present."

12:41 Mike|home: Thanks Bronsa. Awesome.

12:41 Bronsa: np

12:43 scgilardi: get-like calls also allow a default value. (:contents monolith :stars)

12:44 joly: nice, didn't realize that worked also

12:45 * srid is watching the talk "Simplicity Ain't Easy" by Stuart Halloway and taking notes along (enjoying the debunking of contemporary views on simplicity)

12:46 dnolen: ibdknox: cljs-watch is amazing btw. makes writing ClojureScript really fun.

12:46 ibdknox: dnolen: :)

12:46 dnolen: it's the colors right? ;)

12:47 dnolen: ibdknox: I got match working w/ ClojureScript yesterday.

12:47 Bronsa: lol

12:47 ibdknox: sweet!

12:47 Mike|home: What's cljs-watch, dnolen?

12:47 ibdknox: Mike|home: http://github.com/ibdknox/cljs-watch

12:47 dnolen: Mike|home: it watches your ClojureScript files and recompiles them when they change. saves a lot of time.

12:47 Mike|home: Sick. =o

12:48 ibdknox: dnolen: were there any gotchas with getting match to work in cljs?

12:51 I think I might try to redo my nodeknockout entry from this weekend in clojurescript

12:51 Mike|home: ibdknox: Just poked around your website. You're very impressive.

12:51 ibdknox: lol

12:51 Mike|home: thanks haha

12:51 so soon we may have a cljs tower defense game :)

12:53 dnolen: ibdknox: the only problem is that ClojureScript data types and Clojure data types are different. cljs.core.IVector not clojure.lang.IPersistentVector. I added 2 lines to the ClojureScript compiler and it just worked.

12:53 ibdknox: dnolen: sweet

12:54 dnolen: ibdknox: yeah, bringing all the matching machinery to JavaScript is pretty cool.

12:54 ibdknox: dnolen: I saw you did a post on that this weekend, I still haven't caught up with everything after the nko.

12:54 dnolen: yeah, it's impressive really

12:55 dnolen: I wonder how it performs... did you try profiling it at all?

12:59 dnolen: ibdknox: no I should. I don't think it'll be particularly fast (though I don't think it'll be slow either).

12:59 Of course a lot of the work around primitive arrays / bits, is irrelevant for ClojureScript, and you not going to get anywhere near what the JVM can do anyhow.

13:11 duncanm: hey dnolen

13:11 dnolen: did you have anything to do with that Irene tracker on nytimes.com, it's really pretty

13:16 dnolen: duncanm: I didn't work on it but I sit right next to the people that do.

13:33 joly: $findfn inc {:a 4 :b 5} {:a 5 :b 6}

13:33 lazybot: []

13:33 Somelauw: #python-forum

13:34 (type, please ignore)]

13:34 manutter: Shun! Shun the unbeliever!!!

13:34 :)

13:34 technomancy: ~guards

13:34 clojurebot: SEIZE HIM!

13:35 amalloy: TimMc: Mec wrote $findargs

13:35 $findarg map % [1 2 3] [2 3 4]

13:35 lazybot: [clojure.core/unchecked-inc clojure.core/inc]

13:43 cch1: Anybody have strong midje-fu here?

13:43 amalloy: ~anyone

13:43 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.

13:44 cch1: So, using midje, I want to mock (provides) a function that takes keyword arguments.f

13:45 amalloy: dnolen: i don't think i understand the red-black matcher at all. i mean, i guess it's the matching that's more important than the tree (which is just an example). but it reads to me like you're saying that a red node with a red child is balanced, which is untrue

13:45 cch1: First, it seems that the provides would need to list the keywords and their values as positional arguments... but isn't that going to fail since the order of the keywords can't be guaranteed?

13:46 ...and, how can I avoid specifying each and every possible keyword arg if I'm only interested in one?

13:46 even using "anything", that's too much detail.

13:54 manutter: cch1: part of your answer is that you can safely omit any keyword arg you're not interested in

13:54 dnolen: amalloy: it might be wrong, was just using the pattern supplied in a issue report.

13:55 amalloy: https://github.com/swannodette/match/issues/35

13:55 manutter: cch1: but I haven't worked with midje provides so that might not apply

13:55 cch1: manutter: are you sure? If I pass the args like this: "f :a 1 :b 2 :c 3" then mocking is going to require that I do something like (f :a anything :b anything :c 3) even if I don't care about :a and :bv

13:57 manutter: cch1: actually, I'm not sure at all, I just thought I'd take a stab at it (in my ignorance) and see if anybody more knowledgeable chimed in :)

13:57 Somelauw: This probably gets asked a lot (maybe it should even be put in the clojure faq) but does anyone know why clojure does not have letrec (a scheme construct)?

13:58 manutter: but I would definitely try calling it with (f :c3) and see if it blew up

13:58 Somelauw: what does letrec do? Assign to a struct-ish thing?

13:59 joly: I believe the standard let behaves like scheme's letrec

13:59 Somelauw: manutter: Assign multiple vars at once which could use each other.

14:00 joly: No, the standard let is like let* in scheme.

14:00 letfun is a bit like letrec, but only works for functions

14:00 amalloy: (letfn)

14:00 Somelauw: lazy lists / streams can be mutually recursice as well

14:00 recursive *

14:02 joly: Somelauw: oh yeah, thanks. You should be able to do it with a combo of let and letfn then?

14:02 Somelauw: And clojure doesn't seem to cover that use case for local variables.

14:02 Not easily at least.

14:12 joly: No, it is not that easy.

14:13 joly: then perhaps the answer to the original question is "because let and letfn are sufficient for the vast majority of cases"

14:15 laker: hello, does anyone know good books about writing a compiler for a functional language? except the SPJ ones...

14:15 * coopernurse proxy support is like magic

14:16 dnolen: laker: I've heard good things about Lisp In Small Pieces and Appel's compiler texts.

14:18 Somelauw: joly: I think the reason is technical. letfn seems like a poor man's letrec to me. But I am not sure.

14:19 laker: dnolen: those don't cover things like pattern matching/ algebraic data types, but thanks anyway =)

14:19 amalloy: i think it's just that letrec is hard to implement and let/letfn cover a huge majority of cases

14:20 joly: Somelauw: I agree with amalloy

14:20 dnolen: laker: the pattern matching literature seems to be easily accessible on the web. I used Luc Maranget's paper from 2008, quite good.

14:21 laker: dnolen: i'll check that out, thanks

14:22 dnolen: laker: you might find this interesting, github.com/swannodette/match/, sources cited at the bottom.

14:22 laker: dnolen: those are great, thank you

14:25 amalloy: &(macroexpand '(letfn [(x [] 1)] (x)))

14:25 lazybot: ⇒ (letfn* [x (clojure.core/fn x [] 1)] (x))

14:25 amalloy: man. no wonder i was having so much trouble reading the compiler's impl of letfn - the syntax for letfn* and letfn are different

14:31 Somelauw: letfn*?

14:32 theignorati: lein jar is starting jetty in my compojure project.. what's happening

14:33 amalloy: Somelauw: letfn is just a macro over letfn*, which is the real compiler primitive

14:33 manutter: theignorati: you have code in your main file that launches a server on compile, I'm guessing?

14:35 theignorati: good point

14:36 hiredman: https://gist.github.com/1179073

14:37 Somelauw: ok, thanks. I hope letrec will be added in a future version.

14:37 hiredman: seems unlikely

14:37 is there a real use for letrec that is not covered by other features

14:38 amalloy: hey hiredman, i don't understand this. (eval (macroexpand '(letfn ...))) works, but if i copy the output of macroexpand and paste it to the repl i get "clojure.lang.Compiler$MetaExpr cannot be cast to clojure.lang.Compiler$ObjExpr". i've checked and none of the macroexpanded forms have any metadata on them, so the copy/paste should be copying everything that's relevant

14:39 technomancy: amalloy: slime macroexpand or clojure macroexpand?

14:39 amalloy: technomancy: clojure

14:39 technomancy: oh, huh.

14:39 amalloy: i think so, anyway. maybe i'm using the slime one and don't know?

14:39 hiredman: amalloy: I think letfn* is only legal inside the compiler e.g. the compiler can macroexpand and produce it, but you cannot pass it in

14:39 technomancy: I just know you can't always trust slime's C-c C-m

14:40 amalloy: technomancy: yeah, definitely not using that

14:41 Somelauw: hiredman: Yes. recursive lists, mutually recursice lists or even a mutual recursive list and function.

14:41 hiredman: Somelauw: those aren't uses of letrec, those are lists of things you can do with letrec

14:41 amalloy: haha

14:41 hiredman: like, is there some problem you want to solve that you cannot solve without it?

14:42 theignorati: lein run works, but the jar produced by lein jar throws a classnotfoundexception for the class with my main method, what am I doing wrong?

14:42 hiredman: (no euler problems please)

14:42 theignorati: upgrade lein

14:42 theignorati: I just did

14:42 I think

14:42 I just ran lein self-install

14:42 technomancy: hiredman: are you implying that euler is not a valid use case because some of us have homework to do here

14:43 err... that didn't really translate through my punctuation-removal filter

14:43 theignorati: 1.6.1

14:43 technomancy: there should be a comma after case

14:43 hiredman: theignorati: you are missing :gen-class

14:43 amalloy: technomancy: no, the self-important anger really came through

14:43 Somelauw: hiredman: No, but that doesn't mean it has no merit.

14:43 amalloy: "No TIME for commas, I have euler problems to solve!"

14:44 technomancy: amalloy: absolutely

14:44 hiredman: Somelauw: *shrug* it is not needed

14:44 michaelr525: hello!!

14:45 technomancy: amalloy: did you see my juxt fan club submission? http://p.hagelb.org/seajure-address.html

14:45 amalloy: technomancy: holy smokes, variable-width font? is that on purpose?

14:45 theignorati: cheers

14:46 technomancy: amalloy: it's a bug in htmlfontify; I've discussed it with the owner

14:46 it's not a variable-width font, it's just two different fonts getting pulled in

14:46 err--discussed it with the author

14:47 hm; I guess there are only two juxts in there; I could probably sneak another one in

14:47 amalloy: technomancy: the second one is crying out for help

14:48 technomancy: the second defn, or the defn that evaluates to 'second when called?

14:48 amalloy: the second juxt

14:48 the comical ((apply juxt (for ...)))

14:50 technomancy: crying out for help as in "dear odin please release me from this torment" or "that could really use some changes"?

14:50 amalloy: the first. never change it

14:51 technomancy: excellent

14:51 I think you could almost figure it out all in your head except for the part about knowing the length of what (doc a) outputs

14:53 amalloy: technomancy: -main is calling (b) (d) (c) (e), yeah?

14:53 i guess i don't even know what order sort-by sorts in. this is hard without a compiler

14:53 technomancy: true, that's pushing it as well

14:54 possibly relying on implementation details

14:54 it's (a) (c) (b) (d)

14:54 amalloy: see, that's just poor knowledge of the ascii tables. i thought 96 was a, in which case it all comes out right

14:54 Bronsa: how can i transform [{0 1} {0 2}] into [[0 [1 2]]]?

14:54 technomancy: since (a and c) and (b and d) sort to the same position, it's a bit arbitrary

14:55 oh, yep

14:55 amalloy: technomancy: i think it's actually not arbitrary - java.util.Collections.sort is guaranteed stable, last i checked

14:55 dnolen: Bronsa: merge-with

14:56 technomancy: well... it's arbitrary in that they could have implemented it to sort differently and still be entirely reasonable

14:56 Bronsa: thanks

14:58 amalloy: Bronsa: there are an infinite number of ways to make that transformation. you don't provide enough data to clarify what you expect to happen if, say, there's another map {1 5}

14:59 Bronsa: amalloy: i need to unify all the vectors with the same first

14:59 amalloy: &(doc group-by)

14:59 lazybot: ⇒ "([f coll]); Returns a map of the elements of coll keyed by the result of f on each element. The value at each key will be a vector of the corresponding elements, in the order they appeared in coll."

15:03 TimMc: technomancy: What versions of Clojure does that mess work in?

15:03 technomancy: TimMc: only tested in 1.2 I guess. trouble in 1.3?

15:04 TimMc: Haven't tried.

15:04 technomancy: (doc second)

15:04 clojurebot: "([x]); Same as (first (next x))"

15:04 TimMc: I don't have a 1.3 installation.

15:04 technomancy: should still work in 1.3

15:05 amalloy: technomancy: there's still time to change the docstrings in 1.3

15:05 (first (rest x))

15:05 technomancy: noooo

15:05 TimMc: That'll teach those frequent upgraders.

15:08 amalloy: technomancy: d is really hard for me to fit into my head at once

15:09 the rest aren't so bad, aside from, as you say, having to know the length of (doc a)

15:09 technomancy: amalloy: once you can give f a name I think it should be more comprehensible

15:10 amalloy: one and two are just wrappers around key and that comp call so they can fit into the juxt call

15:11 amalloy: sure

15:12 technomancy: amalloy: this must be what writing 4clojure questions is like =)

15:12 amalloy: haha mostly writing 4clojure questions is like "damn it, i wish dbyrne would come back, he liked writing questions"

15:14 technomancy: rpartial isn't implemented because it wouldn't work with laziness, is that correct?

15:19 amalloy: the reason i haven't implemented it is i don't konw what it is

15:19 can't speak for anyone else

15:19 technomancy: (fn [f] (f key)) => (rpartial apply [key])

15:20 partial that fills in the args from the right

15:21 amalloy: i doubt if laziness is the issue. i think partial has to hold onto the argseq at least once anyway

15:22 &(let [p+ (apply partial + (range 1e6))] (p+ 10)

15:22 lazybot: ⇒ 499999500010 ; Adjusted to (let [p+ (apply partial + (range 1000000.0))] (p+ 10))

15:22 amalloy: oh, but of course that's taking up heap, not stack, so i'm never going to prove it with an overflow

15:28 TimMc: &(+ 1 (+ 2 (+ 3 (+ 4

15:28 lazybot: ⇒ 10 ; Adjusted to (+ 1 (+ 2 (+ 3 (+ 4))))

15:29 TimMc: I'm going to write an evalbot that uses ⇒ as its command prefix.

15:29 amalloy: TimMc: just fork lazybot and configure him that way'

15:30 then when you start flooding the channel i'll already know all the back doors to crash your bot

15:31 TimMc: haha

15:34 kzar: What am I missing here? ,(contains? [:a :b :c] :b)

15:34 clojurebot: Excuse me?

15:34 amalloy: contains?

15:34 clojurebot: contains? is for checking whether a collection has a value for a given key. If you want to find out whether a value exists in a Collection (in linear time!), use the java method .contains

15:34 kzar: ah

15:35 hiredman: kzar: read the docs for the functions you use

15:39 TimMc: contains? was named that way to teach you to read the docs

15:40 (I can't think of any better reason.)

15:40 kzar: TimMc: I suppose it makes sense with sets

15:41 TimMc: &(get (set (list 1 2 3 4)) 1)

15:41 lazybot: ⇒ 1

15:42 TimMc: &(get (set (list nil)) nil "nope")

15:42 lazybot: ⇒ nil

15:42 kzar: ,(contains? #{:a 2 :b 3} :a)

15:42 clojurebot: true

15:43 phenom_: ,(let [s1 "test"] (equals? "test" s1))

15:43 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: equals? in this context, compiling:(NO_SOURCE_PATH:0)>

15:43 amalloy: phenom_: you want either = or identical?

15:45 * babilen would have expexted contains? to be named has-key?

15:49 phenom_: amalloy: =

15:49 ,(let [s1 "test"] (equals "test" s1))

15:49 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: equals in this context, compiling:(NO_SOURCE_PATH:0)>

15:50 amalloy: ...

15:50 babilen: heh

15:50 phenom_: eeps, completely misread that

15:50 lol

15:57 michaelr525: hello

16:11 err

16:12 what tomcat is good for anyway?

16:13 suppose that i want to build a web site which should handle a lot of traffic and be able to scale, should i deploy to tomcat?

16:17 or should I just go for ROR frontend and clojure services like flightcaster did, if I recall correctly..

16:37 peteriserins: is there a function [[1 2] [1 3] [1 4]] -> [[1 1 1] [2 3 4]]?

16:38 hiredman: (apply (juxt (partial map first) (partial map second)) [[1 2] [1 3] [1 4]])

16:38 ,(apply (juxt (partial map first) (partial map second)) [[1 2] [1 3] [1 4]])

16:38 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: clojure.lang.ArityException: Wrong number of args (3) passed to: core$first>

16:39 hiredman: bleh

16:39 ,((juxt (partial map first) (partial map second)) [[1 2] [1 3] [1 4]])

16:39 clojurebot: [(1 1 1) (2 3 4)]

16:39 joly: ,(apply map vector [[1 2] [1 3] [1 4]])

16:39 clojurebot: ([1 1 1] [2 3 4])

16:41 joly: ,(apply vector (apply map vector [[1 2] [1 3] [1 4]]))

16:41 clojurebot: [[1 1 1] [2 3 4]]

16:42 peteriserins: joly: cool, how does it work?

16:42 ah I see

16:42 joly: peteriserins: magic ;) I remembered it from when someone asked earlier

16:43 peteriserins: and (vec (apply map .....)) is even shorter

16:43 amalloy: (apply vector x) => (vec x)

16:43 joly: remembered that too late :)

16:43 amalloy: though really, usually you don't need either, because a seq is fine

16:43 joly: yeah

16:43 peteriserins: sure

16:43 btw anybody made ClojureScript work with jsfiddle.net?

16:44 CoffeeScript works, and I'd assume it'd be neat to have this http://doc.jsfiddle.net/use/hacks.html

16:50 scottj: peteriserins: you mean being able to run clojurescript in a web ide like enviornment? coffeescript has a compiler that runs in browser, clojurescript doesn't.

16:51 chouser: I haven't polished this yet, but it might suffice: https://github.com/Chouser/cljs-svc

16:53 peteriserins: chouser: it says Copyright 2010 :)

16:53 dnolen: chouser: that's not live anywhere is it?

16:55 chouser: dnolen: no, not live

16:55 peteriserins: heh. oops.

16:56 amalloy: man. (loop for i from 1 to n collecting n). how can anyone want to write that instead of (range 1 (inc n))?

16:56 chouser: because that way you get more syntax.

16:57 a small price to pay for lack of composability

17:00 joly: is there a way to use memoize effectively without using def?

17:00 KirinDave: amalloy: Loop doesn't scale small well

17:00 amalloy: It was pretty slick back in 2003

17:00 amalloy: I mean, some pretty epically big programs were just an instance of loop

17:01 amalloy: joly: i hate to do this, but...yes, the effective way to do that is to use memoize but not def

17:01 not really sure how else to answer that question without more specifics

17:01 joly: amalloy: for use within something like... 4clojure answers :)

17:01 hiredman: the only question "def" is the answer to is "how do I def things?"

17:02 amalloy: joly: interesting. we don't have any problems where memoize would be very interesting

17:02 joly: amalloy: I'm trying to use it for one right now

17:02 amalloy: so i gathered. which one?

17:03 joly: 101, Levenshtein distance

17:03 amalloy: hiredman: "What is an example of something I shouldn't do at runtime?"

17:03 hiredman: ah, that too

17:04 amalloy: blech. okay, i confess i haven't actually solved levenshtein. the imperative algorithm generally uses some kind of matrix; is there a reason memoize is more expressive functionally?

17:05 joly: I have a dynamic programming example for it, and I usually do those using memoization if the memory requirements aren't large

17:06 beats having to manage a matrix myself, but I will if I need to

17:07 amalloy: i guess they're really just using the matrix for memoization

17:07 joly: I tried (let [f (memoize (fn [n] .... but the inside function doesn't seem to have access to f

17:07 amalloy: right

17:08 joly: ah well, guess I'll take another approach

17:09 amalloy: joly: the matrix solution is written to walk in a particular direction, and only need previous results from "behind" you. you can often do the same thing using iterate

17:11 joly: you can probably adapt something like https://gist.github.com/1140970

17:16 joly: amalloy: nice. My solutions tend to be long-winded; that one looks very concise

17:16 amalloy: joly: well, it's solving a totally different problem, of course. that helps

17:17 joly: true, but just thinking how I'd do Pascal's triangle, I'd get something a lot more verbose

17:18 Too much scheme ;) I'd like to work on being more idiomatic with my Clojure code

17:19 scode: What's an idiomatic way to use lazy-seq in cases where you're not recursing on the surrounding function?

17:19 I.e., I want to do what I do in https://gist.github.com/1179436 but without using the separate helper function.

17:20 But I can't recur inside a lazy-seq, and a (fn ...) inside a let cannot call itself.

17:20 chouser: fn's *can* call themselves

17:20 hiredman: you don't have a recur there

17:20 scode: Oh? Hmm. I must have screwed up somehow then.

17:20 chouser: (fn recurse-forever [] (recurse-forever))

17:20 scode: hiredman: I know, I'm recursing without recur due to lazy-seq.

17:21 hiredman: scode: then why are you asking about recur?

17:21 peteriserins: joly: you might find this useful http://pastebin.com/MAEsKSjM.

17:21 scode: chouser: Oh! I was using (let [name (fn .... which was the problem.

17:21 hiredman: I was asking about recursion, not recur.

17:21 chouser: Thanks!

17:21 hiredman: well the code you posted just works, so you don't have a problem

17:22 scode: hiredman: Like I said, I want to avoid using the separate function (that pollutes the namespace).

17:22 hiredman: chouser's solution is what I was after.

17:22 I had missed the non-anonmyous form of (fn ...)

17:22 dnolen: scode: you also have multiple arities

17:23 scode: dnolen: The example is contrived; in the real case I don't want to expose the parameters involved in recursion in the public interface of the function.

17:23 dnolen: I have a "list-blobs" in a blob store that will iterate over keys in an S3 bucket, and I want to do so lazily in a streaming fashion. The public interface takes no parameters.

17:24 dnolen: But yes, otherwise I would have done that (like range, partition etc in clojure core).

17:24 dnolen: scode: gotcha. you should look at letfn as well

17:25 amalloy: peteriserins: yuck

17:26 now i can't get the millionth fibonacci number without (a) causing a stackoverflow, and (b) causing all million of them to be held permanently on the heap?

17:26 scode: dnolen: thanks!

17:33 mjg123: ,(read-string "\"say \\\"aah\\\"\"")

17:33 clojurebot: "say \"aah\""

17:34 mjg123: That doesn't work in ClojureScript

17:34 Am I doing something wrong?

17:39 or - does it seem like a bug in clojurescript?

17:39 are cljs.reader/read-string and clojure's normal read-string supposed to behave the same?

18:00 devn: mjg123: the reader-fixes branch is 2 ahead of master FWIW

18:01 mjg123: devn: I'll try it.

18:01 devn: mjg123: it's also 54 behind, so you may want to merge it in

18:13 mjg123: devn: not fixed yet :(

18:13 thanks for the tip though

19:11 stirfoo: is this: https://github.com/frenchy64/Logic-Starter/wiki out of date?

19:13 manutter: stirfoo: at the rate dnolen is going I think everything is at least a little out of date :)

19:14 but that one should still be a good start, from what I've heard.

19:16 stirfoo: I wasn't sure if the wiki had not been updated. The first run* example will not work because it's given 5 args, but the core fn takes 3.

19:18 I've had a copy of the reasoned schemer on my desk for a long time but never got into it. I ran across core.logic and thought I'd give it a shot, with clojure instead of scheme.

19:18 manutter: I've only skimmed through the beginning of it so far, so I can't vouch for it personally

19:19 would like to work thru the Reasoned Schemer someday tho

19:19 I'm about 60% of the way through Land of Lisp at least, so maybe someday

19:22 stirfoo: manutter: I've picked that book up a couple of times and thumbed through it. I finished Joy of Clojure a couple months ago. Pretty good book, but some of it was just beyond my level.

19:24 manutter: well, sometimes you just skim and then put it aside for a while. The second reading is always better.

19:43 megaloman: Hello everybody. I'm am searching for a senior design project and am thinking about building a wrapper library for MT4j, Multitouch for Java, that sensibly provide multitouch event listening to clojure apps.

19:43 Does anyone know if there has been multitouch work in clojure already?

19:44 Or have any suggestions about whether MT4j is a good starting point?

19:56 scottj: stirfoo: https://github.com/frenchy64/Logic-Starter/wiki/_history doesn't look out of date

19:58 megaloman: not aware of any clojure wrappers,overtone has it in their roadmap with links to http://code.google.com/p/multitouch/ and http://code.google.com/p/sparsh-ui/

20:02 stirfoo: scottj: It's probably just me ;) I cracked the reason schemer open a while ago and looked at frenchy64's intro project to create a starting point. The examples from the book are working, which is really all I wanted in the first place.

20:06 dnolen: stirfoo: logic starter is definitely up-to-date, you should let ambrosebs know about bugs.

20:06 megaloman: scottj: Thanks.

20:07 dnolen: stirfoo: The Reasoned Schemer is a tough little read, but really fantastic.

21:23 [swift]: hi, i'm very new to clojure. i'm wondering if there is a clojure library function for "zip"? (ie, given two lists, return a list of tuples, where each tuple consists of one element from each of the lists) googling turns up a zipper library but not a zip function

21:24 amalloy: map

21:24 man, i need to come up with a spiel for clojurebot to give whenever someone asks where to find `zip`

21:24 [swift]: this is a common question i take it? =)

21:25 amalloy: from everyone coming from haskell, scala, or python, yes

21:25 clojurebot: python is ugly

21:25 amalloy: thanks clojurebot

21:25 [swift]: i admit, i'm coming from haskell AND python

21:25 amalloy: &(map list '(1 2 3) '(a b c))

21:25 lazybot: ⇒ ((1 a) (2 b) (3 c))

21:26 amalloy: clojurebot: zip?

21:26 clojurebot: zipper is http://clojure.org/other_libraries#toc5

21:26 [swift]: hmm, very nice!

21:27 amalloy: clojurebot: zip is not necessary in clojure, because map can walk over multiple sequences, acting as a zipWith. For example, (map list '(1 2 3) '(a b c)) yields ((1 a) (2 b) (3 c))

21:27 clojurebot: Alles klar

21:27 amalloy: zip?

21:27 clojurebot: zip is not necessary in clojure, because map can walk over multiple sequences, acting as a zipWith. For example, (map list '(1 2 3) '(a b c)) yields ((1 a) (2 b) (3 c))

21:27 amalloy: [swift]: c'est bon, or could i make it clearer?

21:27 [swift]: amalloy: no, that makes it clear! i just didn't expect map to have such an ability! thanks!

22:05 amalloy: so i wanted to write a with-test-tags macro that wraps a bunch of forms, and adds some metadata to each deftest form. i was going to do this with (macrolet [(deftest [name & args] `(deftest ~(vary-meta name assoc :tagged true) ~@args))] body) or something like that, but then deftest tries to expand again, indefinitely

22:06 i can instead expand to `(clojure.test/deftest), but then i can't nest with-test-tags incrementally adding more meta each time, because additional macrolets won't match the ns-qualified symbol

22:06 dnolen: hmm anyone else getting weird errors when using :require in ClojureScript ?

22:06 amalloy: does anyone see a solution to this?

22:58 * srid is trying out IntelliJ for clojure dev

23:14 srid: makes my macbookair cry. gave up.

23:18 technomancy: anyone want to try the new way-faster M-x clojure-jack-in before I cut the release?

23:25 all the adventurous swankers are absent tonight, it appears

23:25 oh well, here it is: https://github.com/technomancy/swank-clojure/commit/31058a

23:26 * technomancy apologizes if the word "swankers" is offensive

23:31 redinger: oh what the heck, I'll give it a try :)

23:31 technomancy: redinger: heh; thanks.

23:31 tomoj: I'm thinking, hey, I'm an adventurous swanker, I just haven't ever tried clojure-jack-in. oh.. wait

23:32 technomancy: just do a lein jar on the 1.3.x branch and symlink the result into ~/.lein/plugins

23:32 (you may need to remove the existing swank jar you have there)

23:32 patchwork: having woes with jdbc and postgresql, can anyone help with this one? http://stackoverflow.com/questions/7238238/clojure-postgresql-how-do-i-access-the-enum-values-from-the-jdbc4array-results

23:36 technomancy: my bad; looks like symlinking may not work, try copying instead?

23:38 hang on, it's not going to work out of a jar; oops

23:38 I was trying it with no swank jar in ~/.lein/plugins

23:39 redinger: that's too bad. I was looking forward to faster swanking

23:40 technomancy: half a minute; I think I've almost got it

23:42 hm; I think it's loading *too* fast now

23:42 the elisp is trying to connect before the clojure side is ready

23:43 ok, pushed; should work now

23:43 sarcher: random question. is there anything clojure provides that would make parsing / interpreting a large complex xml document (based on a schema) easier than normal java xml parsers?

23:44 technomancy: added a 0.1s delay which hopefully I'll be able to remove upon further investigation

23:50 redinger: error in process filter: load-file: File `/Users/redinger/.emacs.d/swank/slime-cdf283b4.elc' was not compiled in Emacs

23:50 didn't work for me

23:51 technomancy: huh; what os/emacs?

23:52 redinger: Lion, Emacs 24.0.50

23:54 technomancy: oh, I got it; I was mixing up the filenames.

23:54 pushed a fix

23:54 I hope this qualifies as your daily dose of adventure =)

23:55 srid: in enlive, how do I do multiple transformations? eg: both `content` and `set-attr` (mainly for setting href and content of the <a> tag)?

23:59 redinger: I get the same problem with that build

Logging service provided by n01se.net