#clojure log - Feb 18 2010

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

0:06 chouser: lancepantz: your probably can just say data instead of (into {} date)

0:07 lancepantz: i'll give it a shot

0:07 chouser: if data is a seq of k/v pairs, like '((k1 v1) (k2 v2) ...) then that inner into is not needed

0:27 TheBusby: hmm, any idea clojure might say that a method doesn't exist in java interop when it should?

0:27 specifically,

0:27 specifically, $ cd projects/robot/

0:27 $ ls

0:27 findbug robot.clj

0:27 er, sorry

0:27 I mean, specifically, "No matching method found: getPixels for class sun.awt.image.ByteInterleavedRaster"

0:30 chouser: that may mean the arguments you're trying to pass in are of the wrong type

0:30 TheBusby: ahh, found it, an arity issue

0:31 too many things called getPixels inheriting from one another...

1:12 slyphon: if i have a map, is it possible to call struct-map with the k/v pairs in that map as arguments?

1:13 without using a macro?

1:31 dnolen: slyphon: (apply struct-map foo (flatten (vec {:bar 1 :baz 2})))

1:32 flatten is from clojure.contrib.seq-utils

1:32 slyphon: ahhh

1:32 i was looking for that

1:35 i wound up doing ( let [m {:foo 1 :bar 2}] (apply struct-map blah (interleave (keys m) (vals m)))

1:36 nteon: hi folks

1:37 I was hoping someone could tell me why line 25 works, but 26 throws an exception in this: http://fpaste.org/w62B/

1:48 hiredman: nteon: "an exception" surely it is a certain type of exception

1:49 and the exception comes with a helpful message

1:49 nteon: hiredman: yes sir: http://fpaste.org/U7dA/

1:51 hiredman: there is no var var-string

1:52 ,(read-string "#'foo")

1:52 clojurebot: (var foo)

1:52 hiredman: ,(read-string "#'my-var-string")

1:52 clojurebot: (var my-var-string)

1:53 hiredman: var does not eval it's arguments, it is a special form

1:53 ,(doc resolve)

1:53 clojurebot: "([sym]); same as (ns-resolve *ns* symbol)"

1:53 hiredman: ,(let [x '+] (resolve x))

1:53 clojurebot: #'clojure.core/+

1:55 slyphon: hiredman: hey, if i have (:foo "bar" :baz "spam") how can i turn that into a map?

1:56 hiredman: ,(apply hash-map '(:foo "bar" :baz "spam"))

1:56 clojurebot: {:foo "bar", :baz "spam"}

1:56 slyphon: OHHH

1:56 hiredman: ,partition

1:56 clojurebot: #<core$partition__5241 clojure.core$partition__5241@1ed0577>

1:56 slyphon: ty

1:56 hiredman: ,(map vec (partition 2 '(:foo "bar" :baz "spam")))

1:56 clojurebot: ([:foo "bar"] [:baz "spam"])

1:56 slyphon: i'm not sure how i missed that

1:56 hiredman: ,(into {} (map vec (partition 2 '(:foo "bar" :baz "spam"))))

1:56 clojurebot: {:foo "bar", :baz "spam"}

1:56 slyphon: hahahaha

1:57 hiredman: ,(doc zipmap)

1:57 clojurebot: "([keys vals]); Returns a map with the keys mapped to the corresponding vals."

1:57 slyphon: yeah, i don't have the keys & vals in separate lists though

1:58 though, wouldn't be too hard to do that

1:58 hiredman: ,(let [x '(:foo "bar" :baz "spam")] (zipmap (take-nth 2 x) (take-nth 2 (rest x))))

1:58 clojurebot: {:baz "spam", :foo "bar"}

1:58 slyphon: are hash-maps ordered?

1:58 nteon: hiredman: I might partly be having a trouble with the new vocabulary. I don't understand why the initial binding *aux-xml-1* can be used with var, but not var-string

1:59 hiredman: nope

1:59 slyphon: ok

2:00 just checking

2:00 hiredman: nteon: *aux-xml-1* is the name of a var

2:00 there is a sorted map

2:00 sorted-map

2:00 * slyphon nods

2:00 slyphon: how about structs?

2:00 hiredman: nteon: var-string is not

2:01 slyphon: structs area slight omptimization (under certain circumstances) of maps

2:01 slyphon: i'm only asking because in the REPL it seems to display things in the order i defined the struct in

2:02 hiredman: the implementation might have some ordering, but not guaranteed

2:02 slyphon: ok, that's what i expected

2:02 thanks

2:05 nteon: hiredman: so what is var-string, a binding? how would I get the var for a binding? (you suggested resolve before, but I can't seem to use that right)

2:05 ah, a symbol not a binding

2:07 hiredman: locals don't have vars

2:07 vars only exist in the global scope

2:07 nteon: hiredman: so there is no way to use a local with meta?

2:08 hiredman: not a locla name

2:08 you can attach readtime metadata to the symbol that is the name

2:09 but it is not accessable at runtime

2:10 nteon: maybe I'm missing something, but this seems to make metadata less attractive to me (I'm probably just misusing it)

2:11 hiredman: I think you must be missing something

2:11 what did you want with metadata?

2:12 you cannot pass local names beyond their scope, or really pass them at all, they are not reified entities

2:12 nteon: I must be :)

2:12 hiredman: the compiler could just translate local names into numbers for an array access

2:13 (it doesn't)

2:14 nteon: basically I want to test that I'm processing chunks of xml correctly. So my thought was to define a var as a string of xml and attach metadata with the correct values I want to be parsing out. I could just use a map instead, with :xml, :name and :equation keys

2:15 that would work just fine, I suppose I wanted to use metadata because 'it was there'.

2:15 hiredman: if you take a strict λ calculus view bound variables are subject to renaming under one of the sbstitution rules (alpha? beta?)

2:16 fyi :user and :import can use and import more than a single thing at a time so you can collapse those seperate uses

2:17 (:import (java.io StringReader ByteArrayInputStream))

2:17 :use

2:17 nteon: hiredman: ah! good to know

2:18 ,(doc ns)

2:18 clojurebot: "([name & references]); Sets *ns* to the namespace named by name (unevaluated), creating it if needed. references can be zero or more of: (:refer-clojure ...) (:require ...) (:use ...) (:import ...) (:load ...) (:gen-class) with the syntax of refer-clojure/require/use/import/load/gen-class respectively, except the arguments are unevaluated and need not be quoted. (:gen-class ...), when supplied, defaults to :name correspon

2:19 nteon: what does the :reload-all do? lein inserted that

2:19 I have an inkling, I imagine reloads it when its reevaluated in a repl session

2:21 hiredman: http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/require

2:25 nteon: hiredman: thanks. I had looked up use which wasn't as useful

2:26 hiredman: ,(doc find-doc)

2:26 clojurebot: "([re-string-or-pattern]); Prints documentation for any var whose documentation or name contains a match for re-string-or-pattern"

2:26 nteon: I always forget about that one.

2:35 LauJensen: Morning team

2:36 Raynes: LauJensen: Morning teammate.

2:45 qed: Morning teamsters

2:53 Raynes: LauJensen: Teach me to speak German.

2:54 qed: Nein

2:54 LauJensen: Raynes: It takes quite some time to learn, that are almost as many small grammar rules as there are stars in the universe - using 'almost' a little lightly

2:54 qed: yeah.. a billion trillion grammar rules seems excessive

2:54 Chousuke: heh, sounds like finnish

2:54 Raynes: Heh, sounds like a crappy language. :|

2:54 LauJensen: Plus there's the added bonus of them exchanging v for f, and adding a letter which you probably haven't seen before, but are 2 nested S's :)

2:54 Chousuke: we have grammar rules for everything because they made one for every exception :P

2:54 LauJensen: Raynes: No its great, finnish is very poor though

2:55 qed: i love finnish folk music

2:55 gregh: clearly you should learn esperanto, there's like 12 grammer rules total

2:55 LauJensen: I cant decide if dutch is good or not, because speak it implies spitting and drooling a lot, so I cant make out all the sounds

2:55 * qed rolls eyes

2:55 Raynes: Or we could all just learn lojban.

2:55 qed: those fake languages are a nice onanistic enterprise

2:55 Chousuke: Also consonant gradation if not fun in Finnish

2:58 http://www.stanford.edu/~laurik/fsmbook/exercises/FinnishConsonantGradation.html I'm glad I didn't have to learn these rules in school :/

3:02 Raynes: Hrm. How did tabs get mixed in with my spaces in my Clojure code. :o

3:02 I thought Emacs converted tabs to spaces.

3:04 gregh: yeah, the tabs made kind of a mess

3:05 Raynes: LauJensen: Do you buy any chance know how to make Emacs convert tabs to spaces by default?

3:06 Would save me a google search.

3:06 gregh: Thanks for fixing it. I had no idea.

3:06 LauJensen: M-x tabify ?

3:07 (setq-default indent-tabs-mode nil) to use as standard I think

3:07 Raynes: It's untabify you were thinking of.

3:07 Thanks.

3:07 I'll try that.

3:08 LauJensen: Only happy to help out my Texan friend

3:08 Raynes: Alabamian. Texas is only fake rednecks. :D

3:08 Texans are*

3:13 hiredman: depends which walmart you are in

3:14 TheBusby: haha

3:14 LauJensen: Raynes: I like what Putin said "There's really no point in criticising America, the results speak for themselves"

3:15 Raynes: Hah.

3:22 hiredman: of course, at that point someone raised their hand and said "sir, you could replace 'america' with the name of any other country and it would still be true" and then putin raised an eyebrow and the voice of decent vanished and support was unanimous

3:23 LauJensen: sure

3:24 hiredman: http://blogs.timeslive.co.za/minor/files/2009/08/putin-and-his-horse.jpg

3:24 LauJensen: All nations fail remarkable at many levels, but Americas slogan has always been Bigger is Better - even in failure :) We have had bubble bursts here in Europe as well, but I mean, when America goes, it goes all out

3:25 Anyway, we shouldnt make this a political discussion, the results speak for themselves :)

3:25 hiredman: LauJensen: bigger what?

3:27 LauJensen: failures?

3:28 hiredman: bigger failures than what?

3:29 LauJensen: I think you just triggered my bike-shed-o-meter

3:29 :)

3:30 hiredman: I think you like the sound of your own voice, but lack any real insight or understanding

3:31 this is not a bikeshed

3:32 LauJensen: what defines a bikeshed then ?

3:32 hiredman: http://www.freebsd.org/doc/en/articles/mailing-list-faq/bikeshed.html

3:33 LauJensen: ah youre a BSD guy ?

3:33 hiredman: it's a term that originated in the freebsd community

3:36 LauJensen: Yes I know

3:37 Anyway , My comment earlier was a reference to the fact, that America is something like the slow kid in the class - Massive debt, massive spending, massive wars, etc. The current worldwide economical crisis originates from your financial market

3:39 bosie: i have been looking at the y-combinator and really don't understand what you need it for

3:40 anyone has an article with a good explanation? :)

3:41 hiredman: bosie: it's a formal way of introducing recursion into the λ calculas, it's not needed in clojure, or really any language I know of

3:42 bosie: hmm

3:44 hiredman: LauJensen: that is hopelessly naive

3:44 lus

3:47 bosie: god i hate my internet connection lately

3:50 avarus: good mirnong

3:50 eh morning

4:00 fullets: Is there a Clojure equivalent of common lisp's #'search?

4:01 hiredman: what does search do?

4:01 fullets: Finds a sequence in a sequence

4:01 hiredman: clarify

4:01 fullets: Like (.indexOf "hello" "el"), but for any sequence

4:02 hiredman: I'd look in seq-utils

4:04 I kind of doubt it exists

4:04 fullets: Doesn't look like it

4:05 hiredman: clojure and contrib seem to avoid O(n) (or greater) unless it can be done lazily

4:05 I guess you could iterate rest and map partition

4:06 but that wouldn't get you the "index" (of a non-index collection :() just the sequence which you already have

4:06 index

4:06 indexed

4:08 Chousuke: I suppose for (search [1 2] [5 4 1 2 3 4 5]) it might be useful to return (1 2 3 4 5)

4:12 ,(first (filter #(= [5 6] (take 2 %)) (iterate rest [3 4 5 6 7 8])))))

4:12 clojurebot: (5 6 7 8)

4:13 Chousuke: one problem with that is that I it never ends if the common sequence is not found :P

4:14 fullets: I just found java.utils.Collections/indexOfSubList, which looks like it'll suit my purposes

4:14 hiredman: :(

4:15 I am sure it will work, it just seems like a horrible idea

4:15 Chousuke: it might work on a vector

4:15 hiredman: I guess it would make more sense there

4:16 fullets: Works on seqs too. I never said it was a good idea - it's meant to be fast to type, not run :P

4:16 hiredman: :(

4:17 horrible

4:31 AWizzArd: Moin moin

4:34 ulfster: moin

4:37 esj: yello

4:45 LauJensen: hey

4:45 avarus: hi LauJensen

4:53 ulfster: if anyone is interested, i just put the start of my first clojure project on github, it shall one day be an online multiplayer version of the popular board game Carcassonne, http://github.com/ulf/carc

4:54 i am still getting started, so most of the code is probably ugly as hell ;)

4:56 avarus: who said the hell is ugly

4:58 Chousuke: ulfster: first problem: you have a single-segment namespace

5:00 avarus: org.ulfster.incredible.game would be better?

5:00 Chousuke: yes

5:00 ulfster: will fix that

5:00 avarus: ok

5:00 ulfster: thanks

5:00 Chousuke: anything but a single-segment namespace :)

5:00 ulfster: makes a lot of sense :)

5:01 hiredman: ulfster.game would be fine

5:01 Chousuke: it's not just collision-prone. Just a couple days ago there was a person here with a gen-class problem and it was fixed by doing away with a single-segment namespace :P

5:03 ulfster: also, camelCase is not very idiomatic naming for most things. you should use foo-bar instead

5:03 except for things exposed as java methods

5:06 furthermore, you should avoid using nested refs (it's difficult to produce a consistent snapshot of them), and instead of (ref-set r (assoc @r :foo ...)) you can do (alter r assoc :foo ...)

5:08 for a simple game like carcassonne, one map inside a ref should be enough mutability. You really don't need to have a separate mutable players list or anything as a part of the already mutable game state.

5:09 ulfster: so generally i should limit the mutable parts as much as possible?

5:09 Chousuke: it'll be less granular, but it'll make the coordination logic a lot simpler, since you can just write most of the game logic as pure functions.

5:09 yes.

5:10 you should only increase granularity if it becomes a bottleneck

5:11 Raynes: I use double and so on segment namespaces.

5:11 Mostly just double and triple.

5:11 Chousuke: and in general, most of your logic functions should not care about refs at all, only the values.

5:12 so eg. add-player should be just a pure function creates a new game state. And then in your game loop you have some state handling procedures which call (alter game-state add

5:12 oops

5:12 (alter game-state add-player ...)

5:13 ulfster: i see

5:13 thanks for the suggestions

5:13 Chousuke: It's basically all about isolation

5:13 ulfster: will try to incorporate that prior to extending the functionality

5:13 thats real good practice, never did a real project in FP

5:13 Chousuke: most of the game logic is expressible as pure transformations. You should isolate those from the actual state-changing logic as much as is feasible

5:16 you'll benefit from pure functions in that you can just define a struct or whatever representing some "state" value in a repl and then run your functions on it and see if they produce correct output

5:16 and you won't need to reset the state between tests, because there actually is no state :)

5:52 esj: is it really the case that on windows elements of the classpath are seperated by ; not : ?

5:52 hiredman: yes

5:53 esj: this is upsetting leiningen...

6:00 so much for my cunning plan to get around the horror of windows by simply working in cygwin

6:05 spariev: I want to load some clojure code from file, process it with clojure.walk, and then save back with modifications

6:05 I believe I can load it with (read), it's the save part that puzzles me

6:06 any hints ?

6:06 AWizzArd: ,(print '(def x 100))

6:06 clojurebot: DENIED

6:06 AWizzArd: ,(print '(foo x 100))

6:06 clojurebot: (foo x 100)

6:06 hiredman: you'll want pr

6:07 AWizzArd: spariev: you can just print your code, using pr or pr-str at some places maybe.

6:07 hiredman: AWizzArd: please don't use print

6:07 AWizzArd: hiredman: it's just a placeholder

6:07 hiredman: ,(print "foo")

6:07 clojurebot: foo

6:07 AWizzArd: yes

6:07 hiredman: ,(pr "foo")

6:07 clojurebot: "foo"

6:07 AWizzArd: that’s why pr or pr-str etc are better suited

6:07 spariev: well, it seems obvious now ) thanks guys

6:08 AWizzArd: You can use binding to bind *out* to a file, or you can just spit your lists out

6:09 spariev: yep, this code-as-data thing takes some time to wrap head around

6:10 AWizzArd: Btw, what are you doing with it? :)

6:10 Something like GP?

6:10 spariev: nope, refactoring tool - http://groups.google.com/group/clojure-dev/browse_thread/thread/51988b3dd591c96c

6:12 AWizzArd: cool stuff

6:12 spariev: I hope I'll have "free" time for it

6:14 * esj grins. Take that classpath !

6:28 jperras: what's the go-to resource for a pure clojure-based priority queue?

6:33 japowl: anyone here using the leiningen native-deps plugin dnolen put on clojars?

6:36 TheBusby: ,(let [ [a b] [1 2] ] a)

6:36 clojurebot: 1

6:37 TheBusby: ,(map (fn [ [a b] %1] a) [1 2])

6:37 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--7888$fn

6:37 TheBusby: hmm, how exactly do fn's support destructuring?

6:38 AWizzArd: jperras: if you want queues just use the ones from http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html

6:39 ulfster: please look into your priv.

6:39 triyo: TheBusby: http://clojure.org/special_forms look at let form

6:40 jperras: AWizzArd: thanks

6:41 TheBusby: triyo: destructuring is only mentioned under "let" and hence doesn't have an FN examples

6:42 no luck on wikibooks for examples either, which is why I brought it up here

6:44 I think I've just provided the example that what works for let doesn't appear to work for fn

6:44 doh

6:47 ,(map (fn [[a b] %] a) '([1 2] [3 4]))

6:47 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--7898$fn

6:49 TheBusby: For reference in case someone googles, (map (fn [[a b]] a) '([1 2] [3 4]))

6:59 triyo: ,(map (fn [[a b]] (str a " - " b)) '([1 2] [3 4]))

6:59 clojurebot: ("1 - 2" "3 - 4")

7:00 TheBusby: I'm slowly learning that it's probably better to grep through contrib that google or read the docs...

7:02 triyo: that destructures each element (vec) in seq and then binds first vec item to a and the second to b.

7:02 TheBusby: triyo: thank you ;)

7:04 triyo: function argument binding can be a bit tricky at first as there is quite a few different ways to go about it. Lately, I've seen people create macros that closelly ralte to how python func argument binding works.

7:04 TheBusby: also have a look at http://stuartsierra.com/2010/01/15/keyword-arguments-in-clojure

7:06 though thats more about keyword argument handling

7:09 TheBusby: is there an RSS feed that tracks clojure related blog posts like emacsen?

7:10 triyo: planet clojure http://planet.clojure.in/

7:10 underdev: are the Hudson snapshots suitable for development, or is it recommended to use the stable releases? Usecase: learning clojure, not production

7:13 Raynes: underdev: They are stable, though the newer features aren't documented in tutorials yet.

7:13 Such as deftype and defprotocol, but there is enough documentation on the assembla pages to fix you up for the most part.

7:14 underdev: Raynes: ty

7:14 Raynes: I mean, it's bleeding edge and all, but nobody really ever has problems with the snapshots.

7:14 underdev: okay, great. exactly what i wanted to know :)

7:21 AWizzArd: Hi rhickey. Did you have another wake-me-up-moment this night? ;)

7:23 rhickey: AWizzArd: I think I've divulged enough about my sleeping pattern this week

7:23 AWizzArd: yeah

7:28 About the Cells example v1: why would one use a Cell for conjing those numbers onto the vector, vs using a transient?

7:28 rhickey: AWizzArd: direct transients are going away

7:29 AWizzArd: And why would one use a locked-cell, as in example v2?

7:29 rhickey: the data structures will remain but the sharing policy has moved into the cell

7:29 AWizzArd: you would never as in the example, since it is a local, but anytime you might use the cell in multiple threads

7:30 AWizzArd: So, when I have n threads that want to conj numbers onto the celled vector, then a locked-cell would be the right container.

7:31 But in which situation would I not want to use an atom or agent or ref?

7:31 rhickey: or a ref, atom or agent, depending on the other factors

7:31 AWizzArd: we discussed this yesterday a lot

7:32 AWizzArd: I think it still left some people a bit puzzled.

7:32 rhickey: locked cells allow for coordination, like refs, and serialized activity, like agents, but are synchronous, like atoms

7:33 plus, they support transience

7:33 so, whenever you want that set of features, use a cell

7:33 AWizzArd: okay, so a locked cell offers features of all those other reference types

7:41 Which of those features go away for non-locked cells?

7:47 rhickey: let's say I have some useful program P, which I control through a pipe. P takes only one input at a time, so it needs serialized input (agents so far). But then I need to know its return value, as soon P outputs them. Here I have a problem with agents: The thread that sent it away won't capture Exceptions, and I can not read the guaranteed correct agent value.

7:48 I could (await my-agent) and then deref it. But between awaiting and dereferencing it some other thread could have sent another job to my-agent and now I get that value.

7:48 Can Cells help here?

7:50 In principle I would like to have: (let [x (send my-agent foo 1 2 3)] ...) with x having the right value, but blocking as long the agent is busy.

7:50 okay, maybe this is more like a queue...

7:53 But could Cells maybe do that? When there is a global locked-cell C and we (let [x (in-cells [C] (>> conj! C (call binary here)) @C)] ...) then this may give the right result.

7:54 Only that instead conj! we would maybe replace the current value.

7:54 Instead of pass, is there some kind of set! operator?

8:06 Seems not many people are sure if Cells can do that...

8:13 rhickey: AWizzArd: you could always pass #(do % 42)

8:14 but yes, cells are synchronous, and serialized

8:14 simultaneous calls to the same cells block

8:17 AWizzArd: Good. And if my cell fn throws an exception, then the thread doing the in-cells call can catch it, yes?

8:17 rhickey: yes

8:30 AWizzArd: rhickey: okay good, thanks, this makes things more plausible, and I have ideas to try it out in my production code.

8:46 _fogus_: Is there a metadata best-practices somewhere? (from a struct impl perspective)

8:48 * _fogus_ realizes that last sentence might not parse

8:48 Raynes: _fogus_: Yep, his name is rhickey and he's sitting just down the row from me. ;p

8:50 _fogus_: Raynes: Understood.

8:56 bosie: anyone in here participating in the google ai challenge

8:56 http://csclub.uwaterloo.ca/contest/index.php

8:59 Raynes: Nope. Too intimidating. :p

9:01 bosie: Raynes: huh?

9:01 sign up with a fake name and fake email ;)

9:01 Raynes: :p

9:07 grzm: 'lo. I'd like to include a java file in my clojure project. I'm using leiningen for management, emacs/slime/swank-clojure for development. swank-clojure-project works: when I call (System/getProperty "java.class.path") in the slime repl, I get the expected classpath

9:08 I added the .java file to src. I used the lein-javac plugin to compile the .java file, and I see the corresponding .class file in classes.

9:09 However, when I attempt to call a (static) method on the class defined in the .java/.class file, I get a "No such namespace: <class>" error in the repl

9:09 How can I further debug this? What might I be doing wrong?

9:16 triyo: grzm: I didn't see all your messages. You just wish to call static method on class?

9:17 ,(map #(Character/isDigit %) "12a34")

9:17 clojurebot: (true true false true true)

9:17 grzm: triyo: yup, which I'm trying to do with (Class/staticMethod arg)

9:17 triyo: what you missed: I'd like to include a java file in my clojure project. I'm using leiningen for management, emacs/slime/swank-clojure for development. swank-clojure-project works: when I call (System/getProperty "java.class.path") in the slime repl, I get the expected classpath

9:17 I added the .java file to src. I used the lein-javac plugin to compile the .java file, and I see the corresponding .class file in classes.

9:18 triyo: you using "lein repl" to test? Just want to make sure your class is on classpath

9:19 oops sorry missed above

9:20 whats your :import look like?

9:21 grzm: triyo: :) that's probably it. I haven't one. let's give that a shot

9:21 chouser: if you use the full name of the class, you don't need an import.

9:22 triyo: hehe, you need to import Java classes first unless you use fully qualified names

9:22 jcromartie: Apparently I have been spoiled by the plain REPL's exceptions when loading code...

9:22 Raynes: Haha.

9:23 jcromartie: if I do (use 'foo) in my REPL, I get a simple one-line message that tells me where the problem is

9:23 in Slime the original source file isn't even listed

9:23 at least not in the first 87 lines

9:23 OK, nowhere

9:23 the REPL says java.lang.Exception: Unable to resolve symbol: entity-id in this context (messages.clj:38)

9:24 am I doing something wrong?

9:25 grzm: chouser: triyo: I was using the full class name (at least as it's defined in the .java file). How might the class name get transformed into something else?

9:26 well, using (ns user (:import ClassName)) worked. Why didn't (ClassName/staticMethod args) prior to import?

9:26 triyo: thanks for the pointer, btw

9:27 chouser: is ClassName in the default (unnamed) Java package?

9:28 grzm: chouser: I don't know, which makes me suspect not

9:28 chouser: grzm: what's the full name of the class, package and all?

9:28 triyo: grzm: in your java class did you define "package .../"

9:28 jcromartie: Is there some way to get the same REPL error messages in Slime?

9:29 grzm: chouser: triyo: the class is one I downloaded: http://people.apache.org/~yonik/code/hash/Hash.java

9:29 I haven't modified that file at all

9:30 arkrost: Hi! I'm looking through clojure source, but I can't find implementation of in-ns function. Tell me please in what file I shold searching.

9:30 chouser: ok, that's your problem. I'm actually surprised you got it working at all.

9:30 triyo: no package so default package used

9:30 chouser: grzm: Java discourages and Clojure doesn't really support classes in the default package.

9:30 stuartsierra: arkrost: in-ns is a special form, it's handled by the compiler

9:33 grzm: chouser: so, I should maybe make src/util/Hash.java, and define the package to be util

9:33 Raynes: jcromartie: Maybe your question should be asked on the swank-clojure ML? I'm interested in the answer as well. technomancy|away is... away, and he's your best bet. :p

9:34 jcromartie: Raynes: yeah maybe... it's very curious that the plain old REPL can give me a one-line answer as to where the error is coming from, but swank can't

9:34 chouser: grzm: yes, that would clean things up for you.

9:34 Raynes: jcromartie: What's even more curious is the fact that people seem to ignore that fact. I think we're missing something.

9:34 jcromartie: yeah

9:34 maybe

9:35 it's inexcusably bad, if it were the default state of swank/slime then nobody would be able to use it

9:35 so I can only assume it's not the way it usually works

9:35 but then again nobody is saying "it works for me!"

9:35 grzm: chouser: thanks :) let's see how I can screw this up :)

9:35 chouser: people do complain about clojure errors all the time. I hope it's not slime's fault all along.

9:36 jcromartie: chouser: well like I said, the plain old REPL in my terminal gives me a one-line error with the source file and line, Slime doesn't list the orginating file or line at all

9:36 chouser: arkrost: http://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lang/RT.java#LID212

9:36 Raynes: It's slimes fault when the Clojure REPL actually answers correctly.

9:37 chouser: right, unless most people using slime have it configured differently.'

9:37 Raynes: Indeed, which is my point.

9:37 Though, I'm pretty sure my install is standard.

9:38 jcromartie: on another tangent: how do you guys organize your tests?

9:41 yeah my swank setup is straight from ELPA

9:41 recent, too

9:41 grzm: chouser: that seems to work. Thanks!

9:41 triyo: thanks for your help as well

9:44 jcromartie: is there a way to try to coerce a map into a struct?

9:44 Raynes: You can ask very nicely,.

9:45 chouser: into

9:45 into is how you convert from just about anything to any of clojure's persistent structures.

9:47 jcromartie: ah

9:47 AWizzArd: you will have to provide fake args

9:48 (defstruct foo :a :b :c) and then (into (struct foo nil nil nil) {:a 1, :b 2, :c 3})

9:48 jcromartie: struct-map works

9:48 (into (struct-map s) some-map)

9:48 AWizzArd: yes great

9:48 I already forgot about struct-map

9:49 jcromartie: did you guys see this presentation? http://www.slideshare.net/smartrevolution/how-a-clojure-pet-project-turned-into-a-fullblown-cloudcomputing-webapp

9:49 it's good

9:50 * _fogus_ reading about "Java: The Good Parts" http://www.kev009.com/wp/2009/10/java-the-good-parts/

9:51 triyo: _fogus_: only one part, Clojure on JVM

9:56 jcromartie: triyo: hah hah

9:59 triyo: jcromartie: well I'm a bit bias; what I meant to have said was: the JVM.

9:59 :)

10:04 ~JVM

10:04 clojurebot: No entiendo

10:05 triyo: ~jvm

10:05 clojurebot: Titim gan éirí ort.

10:06 triyo: hmm "Titim gan éirí ort." -> "May you fall without rising." in Gaelic

10:06 powr-toc: I'm using promise/deliver to make a JFrame dialog box block on the users answer (the deliver happens in the actionListener). It seems like a really nice pattern... would anyone argue otherwise?

10:11 AWizzArd: powr-toc: sounds good

10:11 oh btw..

10:11 rhickey: is it planned that there will be a way to have something like await-for for Cells?

10:12 jcromartie: I'm trying to do (defn find ...) in this namespace, and I've used (:refer-clojure :exclude [find])

10:13 chouser: AWizzArd: cells are synchronous. you don't get control back until the operation is done

10:13 jcromartie: but requiring another namespace that uses that namespace results in an error about clojure.core/fin

10:13 find

10:13 AWizzArd: ,(/ (* 12000 36000000) 1024 1024 1024)

10:13 clojurebot: 52734375/131072

10:13 AWizzArd: ,(double (/ (* 12000 36000000) 1024 1024 1024))

10:13 clojurebot: 402.3313522338867

10:14 jcromartie: my test namespace is like so: (ns foo.test.bar (:use clojure.test [foo.bar :as bar]))

10:14 and requiring that test namespace fails when loading the foo.bar namespace

10:14 which can be loaded by itself just fine

10:14 AWizzArd: chouser: I see

10:15 jcromartie: never mind, I should be requiring instead of using

10:15 (use '[foo :as bar]) doesn't really work, does it?

10:15 AWizzArd: yes, use is very comfortable, but sooner or later a require pays off

10:16 jcromartie: I didn't realize it was just ignoring the :as

10:16 AWizzArd: jcromartie: in your (ns ...) you can have: (:require [clojure.contrib [def :as d] [pprint :as p]])

10:16 chouser: jcromartie: no, it works. you get the alias *and* all the vars referred

10:17 jcromartie: oh, nice :)

10:17 arohner: jcromartie: I've noticed the same behavior. Slime doesn't print the line number where the error occurred

10:17 chouser: I frequently do (:use '[foo :as bar :only []]) to get just the ns alias

10:17 arohner: it is a slime problem

10:17 AWizzArd: funny

10:18 * chouser postpones again relearning emacs.

10:18 AWizzArd: chouser: don’t :)

10:18 You even can program it in Lisp

10:18 jcromartie: arohner: sounds like it might be a major Clojure adoption obstacle

10:18 zaphyr: elisp can only vaguely be described as a lisp ;)

10:18 chouser: not a good lisp. And I don't want my clojure error message to be worse.

10:18 messages

10:18 AWizzArd: chouser: It's a nice lisp for this specific use.

10:21 _fogus_: chouser: I've been using Emacs for a couple years... I expect to be a novice any day now.

10:21 triyo: _fogus_: doesn't it take ten to reach that level?

10:21 * dnolen has used Emacs for 5 years, still hardly knows it. But paredit is enough for him.

10:22 _fogus_: triyo: NOOOOO!

10:22 I thought I was so close

10:24 triyo: _focus_: I know what you mean. Here is a quote by an emacs expert: "Well, the short answer is, you should learn Emacs by using it for about a decade.", easy as that

10:24 chouser: I wonder if I can write an elisp macro to create lexical variables.

10:24 cemerick: chouser: isn't that what (:require [foo :as blah]) is for?

10:25 chouser: cemerick: yes, but if you use require and then later decide there's one function you'd like to use without the alias, you're stuck.

10:25 cemerick: ah

10:25 that seems like a bad idea anyway

10:25 implies to the reader that fn a and fn b from the same ns are from different ns'

10:25 triyo: heheh _focus_.... I mean _fogus_

10:26 chouser: cemerick: on one project I was kept shuffling libs back and forth between the :use and :require blocks as I went along before deciding that was stupid and started doing :use :only [] everywhere.

10:27 _fogus_: chouser: Yegge tried that same thing

10:27 chouser: oh dear. nevermind then...

10:27 :-)

10:28 AWizzArd: oh, you were serious about that

10:28 Hali_303: hi

10:29 AWizzArd: Hello Hali_303

10:31 _fogus_: ,(let [x 1] (let [x-inner 2] (let [x-yet-another-inner 3] [x x-inner x-yet-another-inner])))

10:31 clojurebot: [1 2 3]

10:31 _fogus_: ^^^ lexical scope in elisp

10:31 ;-)

10:32 chouser: hm. I guess the problem isn't so much being able to use lexical scope as it is trying to understand elisp code of others that frequently uses dynamic scope.

10:35 Hali_303: what's an easy way to persistently store clojure data structures?

10:35 for example, how do I store a list of maps? do you use an RDBMS or object database for that?

10:35 AWizzArd: A simple one is to just print them into a file which you can then later (read).

10:36 Hali_303: hm. and what if I have a Date in a map that is not String serializable?

10:36 AWizzArd: You can define printers on any data type for serialization.

10:36 This is okay if we are talking about a few MB of data.

10:37 Hali_303: AWizzArd: how do I do that exactly?

10:38 AWizzArd: Let's say you have a map {:a 1, :b 2}

10:38 cemerick: _fogus_: emacs *and* linux? World of pain, that is. ;-)

10:38 AWizzArd: ,(pr {:a 1, :b 2})

10:38 clojurebot: {:a 1, :b 2}

10:38 triyo: Hali_303: mongoDB with congomongo clojure lib is pretty good option. All really boils down to your requirements. There are newmerious ways, NoSQL, RDBMS, file+serialization.

10:38 AWizzArd: or you can use pr-str and spit that output into a file.

10:39 ,(pr-str {:a 1, :b 2})

10:39 clojurebot: "{:a 1, :b 2}"

10:39 AWizzArd: For simple things this is an okay approach. For a full blown app you probably want to use a “real database”.

10:41 _fogus_: cemerick: After dealing with MS Word, I no longer feel pain like a nomal human.

10:41 cemerick: clearly

10:42 _fogus_: actually, this mostly means that you'll never finish the book -- 45 minutes / hour will be taken up with babysitting synaptic and fixing .emacs ;-)

10:43 Raynes: cemerick: Netbeans is for skiddies. :p

10:45 cemerick: skiddies?

10:46 _fogus_: cemerick: I require approval of Congress to change my .emacs

10:48 mattrepl: _fogus_: you're just furthering the Washingtonian stereotype. =)

10:52 cemerick: Raynes: oh, I got it now (after looking it up). Try to keep stuff like that to yourself.

10:52 _fogus_: mattrepl: Not true... typical Washingtonians use Vi. ;)

10:55 mattrepl: _fogus_: heh, that's believable

10:57 rsynnott: _fogus_: but just a simple majority or one of those wacky supermajorities? :)

11:01 AWizzArd: rhickey: about your Cells gist: is it true that because you extended Strings in lines 149-151 with the Editable Protocol Cell values become inside cell operations such as >> automatically a StringBuilder? And that's why you type hint c in examples s1 - s4 as #^StringBuilder?

11:02 rhickey: AWizzArd: yes

11:02 AWizzArd: oh great, then I think I understand 95% of that

11:03 The Editable Protocol is for "making things transient", while the Transient P. is for reading such objects.

11:03 rhickey: each cell has 2 parts - a transient part and a value part. Those protocols are used to get one from the other

11:03 AWizzArd: Excellent. Damn, this seems to be *the* store for my DB.

11:04 Great great, I will switch from atom + lock + in-lock-atom to locked-cells

11:04 Only missing piece is the Sentry protocol.

11:06 chouser: yeah, that's kinda goofy. Locks and Threads *are* Sentrys

11:07 rhickey: how is that goofy?

11:08 chouser: isn't there a possibility that one might want to provide a cell with a different policy, but still using a ReentrantLock?

11:08 but even if not, it feels odd.

11:09 I would expect a sentry to have a lock or a thread, not be one.

11:09 rhickey: chouser: you can always make an object that holds one of those, at the cost of creating another object

11:10 chouser: hm, yeah I see.

11:10 you don't think if feels at all odd though?

11:10 it

11:10 rhickey: think of it this way - image if sentry was an interface in the JVM and Threads and Locks implemented it. If you wanted different behavior you would have to wrap an instance

11:11 Protocols just let you inject that interface, but admittedly, only once

11:11 AWizzArd: When would I want to extend a class with the Sentry P.?

11:11 rhickey: AWizzArd: you should consider Sentry and implementation detail for now

11:11 an

11:11 AWizzArd: ok fine

11:12 So, the idea about POJOs was to extend on Transient, and have this constructing new instances of the POJO, yes?

11:13 rhickey: AWizzArd: there will also be a way to specify to/from transient fns per cell

11:13 AWizzArd: Very very interesting, I think I got it by now and can start to use them. This will beautify my ugly hacks and make the system easier as well.

11:16 rhickey: chouser: actually, I think it's awesome to be able to build a protocol on an existing class, and leverage the fact (in the case of Thread) that an instance is already around. Single-threaded cells need to be extremely cheap. Furthermore, the potential exists to add compiler support to single-threaded cells that would detect that they don't escape and get rid of the cell entirely

11:18 but in any case people should consider the sentries as opaque. The only critical feature is that given one, you can create another cell with the same policy

11:22 AWizzArd: I will just ignore that Protocol for now and see later if I care about it.

11:33 Ah, interesting way to sort the cells to lock in a way that can't produce a dead lock.

11:39 jcromartie: Are there any functions that describe a struct definition?

11:40 or should I inspect an empty instance for keys?

11:40 i.e. (keys (struct-map my-struct))

11:40 StartsWithK: just check the keys

11:49 somnium: is there something like autotest for clojure?

11:51 StartsWithK: somnium, what is autotest?

11:52 dakrone: autotest monitors a file for changes and reruns your test suite

11:52 somnium: it watches source files for changes, runs tests, zeros in on fails, and has hooks for dorky ">_< tests failed" popups

11:54 tomoj: I'd think it would need to be hooked to whatever you use for development

11:54 that or nailgun

11:54 otherwise running the tests would be too slow

11:57 somnium: I was thinking something like $ lein autotest&

11:58 a simple one is really trivial to write in ruby/python, does the jvm make it harder?

11:59 tomoj: hmm

12:00 I think you wouldn't want to just reload the changed files like the ruby ones do

12:00 dakrone: does the JVM have hooks to watch when a file changes?

12:00 tomoj: actually, that would probably work fine

12:01 no, you have to do that yourself

12:02 http://jnotify.sourceforge.net/

12:02 chouser: there's some inotify (for linux) code in clojure-jna

12:03 tomoj: nice

12:03 StartsWithK: lisppaste8, help

12:03 tomoj: apparently java 7 will be able to do it

12:03 http://java.sun.com/developer/technicalArticles/javase/nio/#6

12:05 StartsWithK: somnium, http://paste.pocoo.org/show/179796/

12:05 fdaoud: i always get caught by this:

12:05 StartsWithK: and "projects" should be i guess "test" inside your project directory

12:06 but that will be slow, as jvm will need a restart

12:06 fdaoud: doing (map (fn [x] (something-with-side-effects x)) [....]) doesn't do all the side effects

12:06 is the solution just (doall (map ...)) ?

12:07 StartsWithK: fdaoud, yes, but check doseq macro also

12:08 fdaoud: StartsWithK: oh, cool, thanks

12:15 StartsWithK: that's much nicer

12:19 stuartsierra: First draft of a new testing framework: http://paste.lisp.org/+21G4

12:20 fdaoud: stuartsierra: pre-ordered your book :)

12:20 stuartsierra: fdaoud: Wow, cool, thanks!

12:20 jlilly: Is there somewhere that I can just download all the clojure documentation?

12:20 I'm going to be taking a flight later today and wouldn't mind having it handy if I need it.

12:21 dakrone: jlilly: you could save http://richhickey.github.com/clojure/clojure.core-api.html as a pdf? would that work for you?

12:22 jlilly: I think that'll do it. :) Thanks

12:22 jasapp: don't forget doc is your friend

12:22 the-kenny: stuartsierra: What's your new book?

12:22 dakrone: stuartsierra: I don't understand your usage syntax, you give the tests each 2 contexts, but then give the suite 1 context?

12:23 defn: stuartsierra: awesome presentation on rubyconf -- ive been waiting for that for 3 months now and it was worth it

12:23 StartsWithK: jlilly, wget -krmnp -E -X/page,/message --no-check-certificate -P <target>https://clojure.org

12:23 defn: s/on/at

12:23 StartsWithK: i think it should still work

12:23 stuartsierra: defn: I've never been to RubyConf.

12:23 StartsWithK: <target> - output directory

12:24 jlilly: I just printed the above page to pdf. That has basically what I was looking for.

12:24 thanks though.

12:24 stuartsierra: defn: Maybe you mean Stuart Halloway?

12:24 jlilly: next question.. when in the repl, how can I change the active namespace to something other than user?

12:24 arohner: jlilly: (in-ns 'foo)

12:24 stuartsierra: the-kenny: My book, mostly by Luke Vanderhart, from Apress, will come out in a few months.

12:24 jlilly: rokk.

12:24 dakrone: (ns foo)

12:24 defn: oh god sorry stuartsierra

12:25 stuartsierra: dakrone: The purpose of a Suite is to define certain contexts that only run once for the entire suite, not once per test.

12:25 defn: no worries, it's confusing

12:26 arohner: does anyone have experience with hibernate?

12:27 fdaoud: the-kenny: http://www.apress.com/book/view/1430272317

12:27 arohner: I'm looking for a better ORM solution, and I'm alternating between writing my own, and doing to hibernate what lein did to maven

12:27 dakrone: so how is (def t1 (Test '[a b] [c1 c2] '[(integer? a) (integer? b)])) supposed to be read? Define t1 as a test mapping a to the result of c1, b to the result of c2 and test the interger-ity of a and b?

12:27 *integer-ity

12:28 stuartsierra: dakrone: Yes. It compiles to something like (fn [a b] (assert (integer? a))...)

12:28 But you won't need to write it like that when I'm done.

12:28 dakrone: stuartsierra: so, then why is the suite context needed for this example at all then?

12:29 stuartsierra: dakrone: Just to demonstrate

12:29 dakrone: oh okay, I guess I was getting mixed up wondering why the context wouldn't do anything for that example

12:31 I think it looks cool, but I'm wondering, isn't contextual testing supposed to be something that's alleviated with immutable functions since they don't require state?

12:32 stuartsierra: dakrone: Yes, but the real world has state in things like databases.

12:32 For unit testing of pure functions, there's no context.

12:32 dakrone: that's true, setup is definitely nice for that

12:32 what kind of changed syntax are you thinking?

12:32 stuartsierra: But you could still use contexts to set up a data structure and then run a bunch of assertions on it.

12:33 dakrone: Everything should nest, i.e. (suite (test ...) (test ...) (test ...))

12:33 cemerick: stuartsierra: what is the objective with the new test lib?

12:33 dakrone: stuartsierra: (def c3 (Context (def my-url "http://clojure.org"))) would allow using that var in all tests if passed as a Suite context then?

12:33 stuartsierra: cemerick: Cleaner separation of setup/teardown and assertions.

12:34 dakrone: no

12:34 cemerick: stuartsierra: nifty. Are you aiming for compat with clojure.test at all?

12:34 stuartsierra: dakrone: Contexts only produce values.

12:34 cemerick: I could probably write a compatibility layer, but in the core, no.

12:35 dakrone: okay, can you give an example where the Suite context would be used and how?

12:35 stuartsierra: dakrone: Opening a database connection.

12:35 dakrone: Creating a temporary directory.

12:36 dakrone: would you return the handle? or are contexts designed not to return anything used?

12:36 stuartsierra: A Context consists of two functions, :before and :after.

12:36 The :before function returns a value to be used in a test. The :after function is called on that same value and does clean-up.

12:37 fdaoud: arohner: do you love hibernate?

12:37 arohner: fdaoud: no, never used it before last night

12:37 stuartsierra: Since Tests know about their Contexts, you can run a test outside of its Suite and still get the proper setup/teardown. But when you run the whole Suite, the setup/teardown only gets executed once.

12:37 arohner: I'm trying to figure out whether it would be a good base for an ORM

12:37 for a clojure orm

12:38 fdaoud: arohner: hibernate is complicated and I find that when you go off the beaten path, you end up wasting more time fighting with it than you saved for the easy stuff

12:38 dakrone: okay, I see, so if you ran t1 (in your example) by itself, it'd run the c1 and c2 setups, but if you ran the s1 Suite, it'd only run c1 once for both t1 and t2, is that right?

12:39 arohner: fdaoud: thanks

12:39 fdaoud: arohner: also, given that Clojure works so well with lists/maps instead of objects, I don't think Hibernate would be a good fit

12:39 arohner: but that's just my opinion.

12:48 arohner: fdaoud: that is useful. my current problem is I'm not too interested in writing the SQL queries to make an ORM efficient

12:49 left outer join, etc

12:49 jlilly: http://pastie.org/831116 -- anyone have suggestions on how I can fix clojure.contrib installation? Running on trunk atm.

12:49 technomancy: jlilly: unless you're hacking on contrib itself I'd recommend getting it from build.clojure.org instead

12:50 jlilly: :-/

12:50 let's say I wanted to completely ignore your advice (as well founded as it likely is)...

12:51 is this an issue with contrib not being 100% stable on the master branch?

12:51 technomancy: clojurebot: restfn?

12:51 clojurebot: excusez-moi

12:51 fdaoud: arohner: are none of the orm solutions for clojure to your satisfaction?

12:51 technomancy: ,RestFn

12:51 clojurebot: java.lang.Exception: Unable to resolve symbol: RestFn in this context

12:51 technomancy: ~RestFn

12:51 clojurebot: I don't understand.

12:51 technomancy: clojurebot: botsmack!

12:51 clojurebot: Huh?

12:51 technomancy: ...

12:51 Chousuke: technomancy: what are you looking for?

12:52 stuartsierra: That's a bug, I think.

12:52 jlilly: Chousuke: the pastie I put above, where maven can't build clojure contrib

12:52 fdaoud: technomancy: sometimes it's better to talk to humans ;)

12:52 arohner: fdaoud: which ones are there? I've only seen http://github.com/duelinmarkers/clj-record

12:52 technomancy: Chousuke: I thought clojurebot had a nice anwser for the restfn problem since it's such a faq

12:52 Chousuke: technomancy: hmmh

12:52 stuartsierra: technomancy, Chousuke: I'm not sure that's the same bug.

12:52 The pastie shows it's downloading the latest Clojure snapshot.

12:53 A couple of people have reported this. But Hudson shows no errors.

12:53 jlilly: stuartsierra: I also tried it by specifying a recent checkout and build of clojure from trunk.

12:53 stuartsierra: jlilly: Try a mvn clean first.

12:53 technomancy: yeah, I've got no idea about contrib specifically; I just saw that error and it made me think of a bytecode/clojure version mismatch

12:53 stuartsierra: jlilly: Or just use the snapshot JARs on build.clojure.org

12:53 fdaoud: arohner: clojureql, clojure.contrib.sql, congomongo

12:54 jlilly: also, is it possible to make maven cache the things it downloads so things don't take as long?

12:54 stuartsierra: jlilly: It does that automatically.

12:54 arohner: fdaoud: AFAI understand, clojureql and contrib.sql are about generating queries, and congomongo is for mongoDB

12:54 jlilly: hrm. alright. Suppose I'm just being impatient.

12:55 technomancy: clojurebot: botsmack is <reply>Owww!

12:55 clojurebot: Ik begrijp

12:55 jlilly: stuartsierra: mvn clean fixed the issue, it looks like.

12:55 thanks.

12:57 stuartsierra: jlilly: np

13:04 AWizzArd: What again was the syntax for :pre asserts?

13:08 jcromartie: wow, Compojure + MongoDB testing is so much faster than Rails + *SQL testing :)

13:09 dakrone: AWizzArd: (defn foo [a] {:pre [(not (nil? a)) (not (= 0 a))]} ... )

13:10 AWizzArd: thx

13:10 jcromartie: why is this faster?

13:10 dakrone: np

13:11 jcromartie: AWizzArd: I dunno, I've just always had really slow test in Rails

13:11 Clojure feels faster overall

13:11 but the lack of a gigantic framework and twelve bazillion plugins and magical metaprogramming might be part of it

13:11 five thousand gem dependencies to load

13:11 etc.

13:13 qbg: Random question: Didn't Clojure use to support CL-style defns (with regards to docstrings)?

13:15 arkrost: hi! I can't understand in what siyuations I can't use commute instead of alter. Can someone show code example?

13:18 qbg: If you were multiplying a matrix in a ref, you couldn't use commute because matrix multiplication isn't commutative.

13:19 BrandonW: arkrost: i had the same exact question a couple of weeks ago

13:20 if you perform operations with alter

13:21 you are guaranteed that the order of the operations is correct. it will execute the same path that your code designs them

13:21 if anything fails, it rolls back the entire transaction, and performs the transaction again

13:21 if you have commute operations, and the transaction fails

13:21 it doesn't roll back the entire transaction

13:21 it just executes the commute function calls again, and tries to submit the transaction again

13:22 AWizzArd: jcromartie: oki, i see

13:22 mapcat is lazy, yes?

13:22 BrandonW: in this way, commute operations will offer a more efficient use of time than alter, since commute won't have to roll back transactions, but alter will

13:31 jlilly: if I have (:require clojure.contrib.combinatorics) in my ns macro, do I need to prefix the functions inside there that I want? for instance combinatorics/combinations or anything?

13:32 danlarkin: jlilly: require doesn't refer

13:37 chouser: in other words, yes.

13:40 AWizzArd: Btw, when we say that Cells are cooperative like refs, serializing like agents and synchronyzing like atoms, do we then really need to mention the atoms? Aren’t refs also synchronized?

13:42 chouser: i guess you could say cooperative and synchronous as refs are.

13:43 AWizzArd: Yes.

13:49 hiredman: how are cells cooperative?

13:49 chouser: you can lock multiple locked-cells with a single in-cells

13:52 AWizzArd: hiredman: (in-cells [cell1, cell2, c3, ..] (bar 'foos))

13:53 jcromartie: "somnium.congomongo" is really hard to type :)

13:53 BrandonW: jcromartie: did you try other nosql databases before you started with mongo?

13:54 jcromartie: mostly because 16/18 of the letters are under my right hand

13:54 hiredman: make a namespace a.b that has a macro like refer-clojure for sominium.congomongo

13:54 jcromartie: I always pick namespaces based on QWERTY letter distributions

13:54 technomancy: jcromartie: that must really bug dvorak users

13:54 hiredman: (a.b/mongo)

13:54 jcromartie: BrandonW: I looked at them but I was impressed by Mongo's track record and successful installations

13:55 BrandonW: I didn't *try* anything else

13:55 BrandonW: i've looked at most of them briefly, as i was going to play around on a personal project with one just to dip my feet in the water, so to speak

13:55 jcromartie: Mongo seems focused and supported

13:55 BrandonW: yeah i had narrowed down between mongo and voldemort

13:55 chouser: what is required to leverage keyword callsite caching for my own class

13:55 ?

13:55 BrandonW: but i've read the same thing you just said-- how mongo is well supported and painless to install

13:55 hiredman: ooo

13:56 that is an interesting question

13:56 jcromartie: BrandonW: oh man, talk about painless... download the binaries and set up the permissions on /data/db

13:56 you're done

13:56 you want security between hosts? set up SSH tunneling

13:56 no users necessary

13:56 no permissions on the db itself necessary

13:56 (by default)

13:57 BrandonW: it is the perfect time, too. i was originally going to just use postgres, but that has always been a pain to set up for me. i like how most of what i read on nosql datastores says it is drastically smaller and less complex to set up initially

13:57 chouser: I have a bunch of final classes provided by a java lib, and want to provide an ILookup object for each with as much performance as possible.

13:57 BrandonW: kind of buys in with the whole linux philosophy of doing one thing very wel

13:59 jcromartie: BrandonW: yeah I think so

13:59 but do consider what kind of data you're going to be using

13:59 stuartsierra: Is there a compiler macro to get the current line of the current file?

13:59 jcromartie: you are going to have to enforce every constraint you want on the data in *your* code

14:00 BrandonW: if you need constraints and transactions, and if you're thinking about handling money or other "important" data then look elsewhere... the MongoDB project says so themselves

14:00 BrandonW: yeah, well it is a personal project anyways

14:00 chouser: ,@clojure.lang.Compiler/LINE

14:00 clojurebot: 0

14:00 jcromartie: then go for it, see how it works

14:00 stuartsierra: thx

14:00 BrandonW: it is not going to need scalability or anything special

14:00 i just wanted to try it out :)

14:00 jcromartie: heh

14:01 chouser: stuartsierra: I can't remember if there's something better or not

14:01 stuartsierra: ok

14:12 somnium: jcromartie: ah, I use dvorak. and autocomplete :)

14:13 jcromartie: that'll do it :)

14:13 jasapp: somnium: are you still looking for a clojure bson encoder / decoder?

14:13 jcromartie: but seriously... 88% one-hand on QWERTY is something special

14:14 jasapp: I got distracted over christmas, but I've got a pretty rough version hacked up

14:15 jlilly: in a for statement, I have a function which is returning a list of 2 item lists. What appears to be wrong with this syntax? (for [[r1 r2] (combinations myitems 2)] <body>) ?

14:15 I'm getting a null pointer exception. (combination myitems 2) results in ((item1 item2))

14:15 I would expect that r1 would be item1 and r2 would be item2. Am I missing something?

14:16 the-kenny: jlilly: ((i1 i2)) or (i1 i2)

14:16 jlilly: the-kenny: it returns ((i1 i2))

14:16 ie: its a list of combinations(lists)

14:16 the-kenny: for the first, you'd need [[[r1 r2]] (fun)] in for

14:17 in your example, r1 is (item1 item2) and r2 is nil

14:17 somnium: jasapp: sure

14:17 chouser: ,(for [[r1 r2] '((i1 i2) (i3 i4))] {:r1 r1, :r2 r2})

14:17 clojurebot: ({:r1 i1, :r2 i2} {:r1 i3, :r2 i4})

14:18 somnium: jasapp: is it on github?

14:18 jasapp: were you interested in the bson wire protocol too?

14:18 the-kenny: whoops..

14:18 jasapp: not yet, at the rate I'm going, it'll be a week or two still

14:19 jlilly: ,(for [[r1 r2] '((i1 i2))] (do (println (format "My thing 1: %s, Thing 2: %s" r1 r2))))

14:19 clojurebot: (nil)

14:19 rhickey: other than the breakage - what do you think of havingto say (map! a-side-effecting-fn ...)

14:20 boojum: ,(inc (Integer/MAX_VALUE))

14:20 clojurebot: java.lang.ArithmeticException: integer overflow

14:20 chouser: instead of (doall (map impure-fn ...)) ? Or would map! still be lazy?

14:20 somnium: jasapp: no hurry, so far only one person has had any performance complaints

14:20 boojum: ,(map inc [Integer/MAX_VALUE])

14:20 clojurebot: (2147483648)

14:20 rhickey: chouser: still lazy

14:20 jlilly: ,(for [[r1 r2] '((1 2))] (println (format "r1: %s, r2: %s" r1 r2)))

14:21 clojurebot: (nil)

14:21 jlilly: hrm. that's not what my repl is returning :(

14:21 jasapp: was that alexyk?

14:21 somnium: jasapp: Ive been focused on other things, but steady contributions trickling in, which is cool

14:21 jasapp: yeah :)

14:21 jlilly: mine is returning... (r1: 1, r2: 2\n nil)

14:21 rhickey: I'm going to add mapv (or something) to map into vector, best for non-lazy

14:21 jlilly: though I suppose that's correct as clojurebot won't spit out printlines.

14:22 rhickey: chouser: trying to tease out when a seq is transient-able, never when based on side-effects

14:22 jasapp: I've just done some simple encoding benchmarks, and it's about 4 times faster than the java version

14:22 chouser: mapv instead of (into [] (map ...)) ?

14:22 rhickey: most of the seq fns could recursively detect transient-ability, but I need to know about side-effects

14:22 jasapp: just doing things like strings and integers

14:22 rhickey: chouser: yes, just shorthand for that

14:23 somnium: jasapp: wow, now that sounds really promising

14:23 jasapp: like I said, it's still pretty rough right now, but I'll let you know when it's suitable for public consumption

14:24 rhickey: chouser: the plan I had for making transient versions of ordinary seqs doesn't work, as lazy-seq-iter will have to retain head in a closure

14:24 chouser: ah, ok.

14:25 rhickey: so instead, the macro will generate code that will create either a LazySeq or LazySeqIter depending on the recursive transience of the passed colls

14:25 chouser: you probably missed my question earliery: what is required to leverage keyword callsite caching for my own class?

14:25 I have a bunch of final classes provided by a java lib, and want to provide an ILookup object for each with as much performance as possible.

14:26 so analysis done at runtime, and you'd get a single object -- one or the other instead of both as with earlier plan

14:27 jcromartie: hmm, why can't I seem to find the encodeBase64String static method in the Apache Base64 encoder?

14:27 rhickey: chouser: right, but still some kinks like side-effects and the fact that cols might be passed and not seqs

14:27 jcromartie: I mean, it's in the docs

14:27 somnium: jasapp: let me know when its suitable for hackery even, sounds very cool

14:27 jcromartie: but I get No matching method: encodeBase64String

14:28 am I doing this wrong? (Base64/encodeBase64String (.getBytes "foo:bar"))

14:28 rhickey: chouser: to get keyword lookup you need to implement IKeywordLookup, and return ILookupThunks for any keywords for which you want direct lookup

14:28 the-kenny: jcromartie: maybe you supply the wrong type of data as the argument?

14:28 I'd try a type-hint

14:29 chouser: rhickey: ok, thanks.

14:29 jcromartie: the-kenny: hmm, I'm using decodeBase64 just fine, though

14:29 jasapp: somnium: sure thing

14:30 jcromartie: hm, weird, it must be the codec version I have or something

14:30 rhickey: chouser: you won't be able to implement IKeywordLookup without access to the Java lib

14:33 chouser: rhickey: I'll have access to the Java lib at macroexpand time.

14:33 rhickey: chouser: no, I mean the ability to make those classes implement the interface

14:34 chouser: but I should be able to create an object at runtime that wraps a particular instance of a Java lib class, and delegates.

14:35 so (:foo javaobj) can't work, but (:foo (wrapmacro javatype javaobj)) should

14:36 and I think will still make sense for my use cases.

14:40 rhickey: chouser: I take that back, there is more to keyword lookup - kind of hardwired to deftype right now

14:45 chouser: hm...

14:46 lancepantz: hey chouser, remember that line you were talking to me about last night?

14:46 (defn to-seq [data] (into {} (for [[k v] (into {} data)] [k (if (instance? java.util.LinkedHashMap v) (to-seq v) v)])))

14:47 you suggested removing the inner into

14:47 chouser: I suppose my macro could generate a defprotocol with a method for each of the java class's methods, then generate a deftype to implement them as simple calls on the wrapped java instance.

14:47 lancepantz: yes

14:47 lancepantz: chouser: so it worked, but i don't understand why, i was hoping you could explain

14:48 because data the first time there is't a seq

14:48 its a LinkedHashMap

14:48 chouser: (into {} ...) doesn't return a seq either, it returns a map. Probably a hash-map

14:48 lancepantz: so is clojure coercing the k/v from the java datastructure

14:48 yeah, i'm sorry, thats what i mean

14:48 map not seq

14:48 but it's a clojure map

14:48 not a java primitive

14:49 chouser: lancepantz: 'for' calls 'seq' on each of the collections you give it.

14:49 'seq' knows how to return sequences for much more than just clojure collections. It can do Java Maps, strings, etc.

14:49 ,(map int "abc")

14:49 clojurebot: (97 98 99)

14:50 lancepantz: ok, yeah, that's what i wasn't aware of

15:19 Hali_303: when doing a (:use somnium.congomongo), it throws a classnotfoundexception. How to find out what class is missing? (using slime)

15:22 Licenser: hmm hmm hmm

15:23 how can it be that code (once executed in pmap once in map) behaves entirely different?

15:23 stuartsierra: Licenser: dynamic context

15:23 Licenser: hm?

15:23 somnium: Hali_303: are you typing that into the repl?

15:23 Licenser: can it be that something ghat was set using binding isn't the same over al pmap instaces?

15:23 stuartsierra: Licenser: thread-bound Vars won't propagate to calls from pmap

15:23 Hali_303: somnium: yes

15:24 somnium: Hali_303: then it should be (use 'somnium.congomongo)

15:24 Licenser: hmm so how can I make the content of this stuff I have in binding the same in all instances of pmap?

15:25 stuartsierra: (fn [x] (binding [*some-var* ...] (function x))

15:25 I think there's a contrib macro for that.

15:25 Hali_303: somnium: I can do that, but then (mongo! does not work

15:26 Licenser: hm what I have is: (binding [*v* ...] (pmap #(some stuff that uses *v* %) list stuff)))

15:26 hiredman: well that is obviously not going to work

15:26 abscondment: Hali_303: can you catch & inspect the exception?

15:26 Licenser: hiredman: obviousely not no :P but intuitively I'd expect that

15:26 hiredman: binding is thread local, pmap executes things on other threads

15:27 Licenser: so what I'd have to do is make a function with a cosure around it?

15:27 hiredman: no

15:27 a function is a closure

15:28 if closures were the answer that would solve it

15:28 Hali_303: abscondment: how?

15:28 hiredman: but closures don't close over dynamic scope

15:29 Licenser: so I am very confused now

15:29 hiredman: (let [*v* *v*] #(some stuff that uses *v*)) will work because it captures the dynamic scoped value of *v* in the lexical scope binding it to the name *v*

15:29 somnium: Hali_303: what is the error message slime shows?

15:29 Licenser: ah hiredman thanks I'll try that

15:30 Hali_303: somnium: ahh. nothing. I'm a retard :D

15:30 hiredman: it's not something for trying, it works

15:32 Licenser__: hiredman: nah he does tell me he does not know *v*

15:32 since it's from a different namespace :P

15:33 hiredman: Licenser__: then you did it wrong

15:33 Licenser__: hiredman: yap likely, that is why I'm a bloody beginner :P

15:35 hiredman: so you have a var that you have dynamically rebound?

15:37 Licenser: hiredman: I use it for logging, there is a function (log ) that writes into *log*

15:37 * Licenser feels totally stupid :( gnaw

15:38 hiredman: (pmap (let [*log* *log*] #(do stuff with logging)) list-of-stuff)

15:38 brandonw: don't worry Licenser I'm right there with ya :D

15:38 * Licenser high 5's brandonw

15:39 brandonw: clojure definitely has a learning curve coming from more procedural oo languages

15:39 so cool once stuff starts to click, though :)

15:39 chouser: do you understand dynamic scope and lexical scope? if not, that's a good place to start.

15:39 perl has both. closures too.

15:40 hiredman: :(

15:40 why would you mention that?

15:40 chouser: :-)

15:40 that's where I learned all three!

15:41 Licenser: chouser: dynamical scope=it figures what it is when he comes there, lexical scope=it figures what it is during parsing

15:41 at least that is how I understood it :P

15:41 hiredman: lexical scope is creation time and dynamic is call time, and closures close of lexical scope

15:41 over

15:44 * Licenser feels stupid

15:45 brandonw: http://en.wikipedia.org/wiki/Scope_(programming)

15:46 think of lexical scope as what you define a symbol in the scope of reading the code

15:46 inside a function

15:46 dynamic scope isn't related to where it is defined, but rather by the last thing that defined it, like a thread-local binding

15:47 hiredman: you can actually think of it as a single scope with the dynamic scope as a mutable environment frame at the bottom of the stack

15:47 brandonw: that is very confusingly worded

15:47 brandonw: it's scope isn't local to a function, its value is whatever last successfully changed the value, which could be anywhere on that thread (not necessarily where the symbol was defined)

15:48 hiredman: brandonw: still confusingly worded

15:48 * somnium suddenly wonders why so many lisps still use car and cdr

15:48 Licenser: I understand the problem but my brain right now failes to wrap around a solution o.o

15:48 hiredman: so you can get stickers like "my other car is a cdr"

15:48 somnium: :D

15:49 * kotarak thinks that after clojure other lisps feel old.

15:50 brandonw: yes hiredman your explanation is definitely better

15:51 except i don't understand what you mean by 'single scope'

15:53 does clojure offer a stack of dynamic bindings? or is it only like you said hiredman: a single mutable frame

15:54 chouser: brandonw: theres a stack, but you can only see the current one

15:55 brandonw: how would you pop off the last binding off the dynamic stack?

15:55 chouser: you leave a (binding ...) scope

15:55 brandonw: ah yes, that makes sense

15:56 kotarak: brandonw: I think the pop doesn't return the map. So you can't push it again, to fix the stack.

15:56 brandonw: i'm thinking in a procedural way again.. assuming each change to the binding is an actual change

15:56 right

15:56 i recall reading that somewhere, too, i think

15:57 chouser: brandonw: well you can do that but you'd better know exactly what you're doing.

15:57 (doc push-thread-bindings)

15:57 clojurebot: "([bindings]); WARNING: This is a low-level function. Prefer high-level macros like binding where ever possible. Takes a map of Var/value pairs. Binds each Var to the associated value for the current thread. Each call *MUST* be accompanied by a matching call to pop-thread-bindings wrapped in a try-finally! (push-thread-bindings bindings) (try ... (finally (pop-thread-bindings)))"

15:57 Licenser: so I've a ns that declares *log* a function that binds *log* to a ref and then calls another function in another ns that calls pmap with some functions that write to *log*. If I do it like this it fails since *log* isn't the right *log* if I do (let [*log* *log*] it failes since it does not know *log* yet if I use (let [*log* my-ns/*log*] it doesn't work since it's a different *log* then I bound :(

15:58 kotarak: Licenser: guessing: bound-fn?

15:58 Licenser: *Reads on that*

15:58 kotarak: (doc bound-fn)

15:58 clojurebot: No entiendo

15:58 kotarak: clojurebot: :(

15:58 clojurebot: Pardon?

15:59 brandonw: wait

15:59 i just noticed

15:59 the prefix , was removed from clojurebot interaction?

15:59 kotarak: doc always worked without. no?

15:59 brandonw: oh, it might have

15:59 kotarak: (inc 1)

15:59 ,(inc 1)

15:59 clojurebot: 2

15:59 brandonw: okay, you're right

16:00 Licenser: thanks kotarak I see if that helps me ^^

16:00 brandonw: just coincidence that this was the first time i was looking at a doc call

16:00 kotarak: Licenser: you scenario sounds like a valid use case.

16:00 Licenser: kotarak: my scenario sounds like total mess to me when explaing int :P

16:00 kotarak: Licenser: (pmap (bound-fn [x] ...) blabla)

16:02 hiredman: kotarak: if the let is failing I don't see how bound-fn could work

16:02 the let takes the value from the dynamic environment, and bound-fn would capture and restore the dynamic environment

16:03 so if one fails because the value you want is not in the dynamic env so would the other

16:05 Licenser: if you intend to capture the value of *log* you have to, you know, bind *log* to that value first

16:05 Licenser: hmm sounds like an idea hiredman now I figure how :P

16:06 kotarak: Licenser: do you have some code to paste?

16:06 Licenser: kotarak: yes like 2 dozent files :P let me see if I can extract the important stuff

16:06 hiredman: Licenser: it sounds like you are building a circular dependency

16:07 Licenser: hiredman: shouldn't be no

16:07 hiredman: namespace a.a uses and calls functions in namespace b.b and functions in namespace b.b use and depend on vars from namespace a.a

16:07 that is a circular dependency

16:09 Licenser: but I've a utils namespace (for logging stuff) a frontend namespace and a abackend namespace

16:09 th

16:09 hiredman: so?

16:09 are you or are you not doing what I just described?

16:09 Licenser: I'll post something one second

16:09 hiredman: you description of what you are doing earlier is exactly that

16:10 your

16:13 Licenser: http://gist.github.com/308078

16:13 that is about what I'm doing

16:13 now *log* is empty after run :(

16:15 kotarak: Licenser: you need bound-fn, because the let does not change the binding in utils

16:16 Licenser: *googles for an bound-fn example*

16:16 hiredman: kotarak: binding changes the binding for *log* from utils

16:17 kotarak: Licenser: (pmap (bound-fn [x] (log x)) (range 1000))

16:17 hiredman: which does not carry over the pmap

16:17 hiredman: kotarak: right, but that has nothing to do with thelet

16:17 let

16:17 kotarak: Licenser wrote something about let somewhere above.

16:18 hiredman: the issue with the let is *log* cannot be resolved in backend

16:18 Licenser: someone suggested let

16:18 hiredman: I did

16:18 kotarak: Ok. I'm confused.

16:18 Licenser: odd thing is: boundfn does not work either

16:18 hiredman: kotarak: I am not

16:19 kotarak: hiredman: good for you

16:19 Licenser: *tries something*

16:19 ah there we go

16:20 problem was that I bound'fn in the inner map not in the outer map

16:21 kotarak: hiredman thank you two a hell lot for your patience

16:21 I really appriciate it :)

16:21 kotarak: Licenser: gern geschehen

16:21 Licenser: kotarak: :D

16:22 heh trairig ist nur, dass pmap langsamer ist als map :P

16:22 hiredman: I still think you are going to end up in a circular dependency, you've just delayed it

16:23 Licenser: narf wrong language sorry

16:23 kotarak: Licenser: for small problems. The idea of pmap is that the mapped funciton is expensive. For cheap functions the thread spawn overhead dominates

16:23 Licenser: hiredman: I acutally fixed one by moving stuff to the untils thing

16:23 I had the impression that they use a thread pool so the spawn time is minimal?

16:24 chouser: minimal is more than none

16:24 kotarak: Licenser: well, there's a thread called for each item in the seq. So for cheap function "(log x)" pmap *will* be slower.

16:25 jcromartie: Is there a way to apply middleware to all of the routes in a compojure app?

16:25 Licenser: kotarak: that is why I used batches

16:25 jcromartie: I've tried unsuccessfully

16:26 somnium: jcromartie: (decorate the-app with-my-awesome-middleware) is the usual way, do you have multiple defroutes clauses?

16:26 jcromartie: somnium: no, just one defroutes

16:26 that's easy enough though

16:26 somnium: then decorate should work

16:26 jcromartie: I was using decorate-with

16:27 err, wait... not sure what was going on there

16:33 Licenser: is there a way to see how many transaction rollbacks I have?

16:34 chouser: nothing non-invasive yet, afaik

16:34 Licenser: aww :(

16:34 because I've the feeling that is an isue right now

16:35 concidering that when using pmap my entire time goes from 100s to 200s even usign batches

16:36 kotarak: Licenser: how about sending to an agent?

16:36 hiredman: not big enough batches

16:36 stuartsierra: Licenser: if your logging function does I/O, you could be screwing your throughput.

16:36 Licenser: no logging isn't what is the issue I think

16:36 chouser: or increment an AtomicInteger

16:36 Licenser: at least not this :P

16:37 the problem is surely the map that is one big ref so if a unit (I code a game) moves any any other unit acceses the map in the same time it goes all boom I fear

16:37 propably should make each field a ref

16:38 chouser: Licenser: you can try using an AtomicInteger to count your retries, but of course that may change the behavior

16:39 Licenser: *scratches head how to handle this best

16:40 chouser: *nods* that's an idea but I feel I already know where the issue is, as some a unit moves every other unit will have to retry the entire thing

16:40 but enough clojure for today, sadly work is calling tomorrow :(

16:40 thank you all for your help!

16:40 You're a great bunch of community!

16:58 hiredman: geez

17:00 arohner: somnium: does congomongo support db-refs?

17:04 somnium: arohner: the java-driver has a db-ref class

17:05 arohner: somnium: k. looks pretty easy to write a wrapper for it

17:05 lancepantz: i do not see a way to access the nth item in a sequence, am i missing something?

17:05 arohner: ,(doc nth)

17:05 clojurebot: "([coll index] [coll index not-found]); Returns the value at the index. get returns nil if index out of bounds, nth throws an exception unless not-found is supplied. nth also works for strings, Java arrays, regex Matchers and Lists, and, in O(n) time, for sequences."

17:05 somnium: arohner: since its a convention for a map with {:collection ... :id ...} Im still not convinced of their utility, but maybe Im misunerstanding

17:06 arohner: somnium: I'm hardly an expert on mongoDB, but I think it's for "joins". if you have a bunch of objects that "point" at the same obj, you can save duplication

17:06 or if you modify the objecting being pointed at

17:09 somnium: arohner: right, what I dont get is that a map like {:name "bob" :friends [#someid #someid]} seems more or less equivalent, but without the extra type

17:10 lancepantz: thanks again arohner

17:10 that one's not in my book :/

17:11 kotarak: lancepantz: http://clojure.org/API

17:12 lancepantz: still need to know what the function is called

17:13 kotarak: lancepantz: skimming over it, clicking on interesting sounding/strangely looking/unfamiliar functions, I always find something interesting. :)

17:13 lancepantz: agree

17:13 arohner: somnium: how do you fetch by id?

17:16 somnium: arohner: (fetch :things :where { :_id #<ObjectId abcdefgh...> })

17:16 arohner: huh, that wasn't working for me

17:17 but :_id (ObjectId. "abdef...") does

17:17 somnium: arohner: have to make an Id object

17:18 someone suggested adding an (object-id ...) fn, but its the same length as the java constructor :/

17:18 arohner: I slightly prefer (object-id ...) over (ObjectId. )

17:18 somnium: at first I tried auto-coercing them, but it got confusing

17:18 arohner: the other nice thing is you don't have to import it

17:19 somnium: on the server usually have the id objects, but receiving json need to wrap

17:19 true, I can go ahead and add it

17:23 lpetit: rhickey: would you mind if I use the clojure logo as the logo for the counterclockwise project on google code ? (would be better that the "out-of-the-box" logo) : http://code.google.com/p/counterclockwise

17:23 redwyrm: if functions are side-effect free, then that means you can't call any Java library functions that have side effects (such as windowing stuff), right?

17:23 unless it's not in a function

17:25 rhickey_: lpetit: the Clojure logo should only be used to refer to Clojure itself

17:26 dakrone: are there any html-stripping libraries for clojure?

17:26 lpetit: rhickey_: that's what I wanted to check with you. Thought it could be more "visual" for people to remind them of clojure, but you're right of course.

17:33 piccolino: Am I correct in my understanding of the docs for the function read that it will take a string representation of a clojure form, and give you back the actual form without evaluating it?

17:34 technomancy: piccolino: not quite; it actually takes a reader which provides the string

17:34 piccolino: Oh, right. But the rest is correct?

17:34 hiredman: read-string takes a string

17:35 piccolino: Ah, there we go.

17:35 Just had to scroll down a bit more.

17:35 Thanks guys.

17:36 hiredman: you can get the reader to eval stuff

17:36 Chousuke: bind *read-eval* to false to prevent that

17:36 if course it doesn't matter if you control the input completely

17:37 piccolino: Yeah, I want it to not eval stuff.

17:37 Chousuke: but eg, someone might pass you a string "(foo bar #=(take-over-system))" :P

17:38 the #= reader macro is a way to eval things at read time

17:38 piccolino: Ah, I see.

17:45 powr-toc: has anyone here used clojure.contrib.http.agent ?

17:47 * tomoj raises hand

17:47 powr-toc: tomoj: was it any good? :-)

17:47 tomoj: I like it

17:48 have to be kinda careful or you end up with a lot of trouble debugging

17:48 hiredman: I think stuartsierra said it needed to die a thousand deaths

17:49 powr-toc: hiredman: yeah, I seem to remember seeing him mention that... Being the author what was his problem with it? :-)

17:49 tomoj: if you treat it like a synchronous library and just try to call result on the agent as soon as you create it, and then your handler blows up, it's ugly to debug

17:49 hiredman: powr-toc: I think he hates contrib

17:50 which I understand, it's a giant pile of stuff

17:50 powr-toc: hiredman: it sure is :-)

17:51 tomoj: I shouldn't need it to read a page... I just want a place to send outbound post requests to

17:52 tomoj: so asynchrony is what I want

17:53 by that, I mean non-blocking

17:54 dakrone: any NLP fans in here?

17:55 tomoj: powr-toc: should at least work then

17:56 (http-agent "url" :method "POST" :body "post body")

17:56 powr-toc: what happens if an exception is thrown inside the agent?

17:56 tomoj: dakrone: I'm a fan

17:56 not an expert

17:57 powr-toc: then the agent has errors, which you can see with agent-errors

17:57 done? and error? are helpful too

17:58 dakrone: tomoj: cool, I'm working on a clojure-opennlp library

17:58 tomoj: awesome

17:58 I have dreamed before of replacing nltk

17:59 unfortunately my nlp TA doesn't want to read clojure code so I have to use python :(

18:00 powr-toc: tomoj: Am I right in thinking each request is effectively an agent?

18:01 tomoj: yep

18:01 powr-toc: makes sense

18:02 dakrone: tomoj: check out http://gist.github.com/308172

18:02 super rough, anyway

18:03 tomoj: awesome

18:03 my next homework assignment is a pos-tagger

18:15 jcromartie: I wish int coerced strings into integers

18:24 dakrone: jcromartie: http://pastie.org/831753

18:25 jcromartie: :) ahead of you

18:25 dakrone: :)

18:29 alexyk: ,(->> (remove nil? [nil nil 1.0 2.0]) (apply max))

18:29 clojurebot: 2.0

18:29 alexyk: (->> (remove nil? [nil nil]) (apply max))

18:30 well, java.lang.IllegalArgumentException: Wrong number of args passed to: core$max (NO_SOURCE_FILE:0)

18:30 can't it just say nil?

18:32 I need a -->>-ble way to apply max to non-zero args or return nil

18:35 dakrone: ,(first (->> (vector (remove nil? [nil 1])) (apply max)))

18:35 clojurebot: 1

18:35 dakrone: ,(first (->> (vector (remove nil? [nil nil])) (apply max)))

18:35 clojurebot: nil

18:35 dakrone: alexyk: how about that?

18:36 not exactly the same, since it would return a list without the (first ..)

18:36 alexyk: hmm

18:36 hiredman:

18:37 alexyk: hiredman: is it the ellipsis of disapproval?

18:37 hiredman: yes

18:37 alexyk: hiredman: (macroexpand ...)

18:37 dakrone: there are probably much better ways to do it, I'm still learning clojure entirely, so take hiredman's advice over mine

18:37 somnium: wasnt that some artifact from Lord of the Rings?

18:37 hiredman: dakrone: that does not work

18:38 dakrone: it's not a matter of better ways to do it

18:38 it just doesn't work

18:38 dakrone: hiredman: bleh, you're right

18:38 alexyk: yeah

18:38 dakrone: my fault, sorry

18:39 hiredman: ,(-> [nil nil] (remove nil?) (apply max 0))

18:39 clojurebot: java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn

18:39 hiredman: ,(->> [nil nil] (remove nil?) (apply max 0))

18:39 clojurebot: 0

18:39 hiredman: bleh

18:39 alexyk: ah, sticking 0 works

18:40 slyphon: hrm

18:41 do you have a set of things you import into your repl when you're working on something? in addition to the code you're working on, that is

18:41 somnium: alexyk: is the stuff you did with the cursors on github?

18:41 slyphon: is there a convention for including that stuff?

18:41 * slyphon is thinking of an .rc like file in other interactive shells

18:41 somnium: slyphon: user.clj

18:41 dakrone: yea, a user.clj

18:42 in your classpath

18:42 slyphon: oh sweet

18:42 ahhh

18:42 ok, that makes sense

18:42 do you normally work from the context of the user namespace, and import/use stuff from the other namespaces?

18:43 i've been switching to the ns of my project and mucking about

18:43 alexyk: somnium: kind of, in the guts of another project

18:43 somnium: I'll send you a link

18:47 slyphon: somnium dakrone: thanks! that's way more convenient :)

19:08 nathanmarz: anyone here familiar with clojure.contrib.logging? - it's not finding log4j even though it's in my classpath

19:10 slyphon: nathanmarz: i set it up with apache-commons + log4j last night but it "just worked"

19:10 nathanmarz: slyphon: did you just include those jars in your classpath?

19:10 slyphon: pretty much

19:11 nathanmarz: the odd thing is that if i copy-paste the source of clojure.contrib.logging into my repl it works

19:11 slyphon: i'm pretty new to this, though so i'm afraid i'm not gonna be able to be much help

19:11 that is odd

19:12 technomancy: nathanmarz: earlier versions of c.c.logging had bugs that would cause the logging impl to get hard-coded at compile-time

19:12 slyphon: also, *impl-name* will tell you what implementation it's using, i found that helpful

19:12 technomancy: java logging is such a mess. I have used three different libraries that provide abstraction between different logging backends, but I've only used two backends.

19:13 slyphon: haha

19:13 nathanmarz: my project.clj has this as dependencies: :dependencies [[org.clojure/clojure "1.1.0"]

19:13 [org.clojure/clojure-contrib "1.1.0"]]

19:13 technomancy: and one of the two was by accident, due to the aforementioned bug

19:13 nathanmarz: it should be fixed in that version; must be another problem.

19:13 slyphon: hah

19:13 technomancy: i tried out the new project by the guy that wrote log4j, it was pretty good

19:14 but, i mean, then again, it's a friggin *logging library*

19:14 technomancy: if I had to do it from scratch again, I'd just write a wrapper around log4j instead of using c.c.logging

19:14 heh

19:14 slyphon: i really like the 'spy' function

19:14 *that* is something i've wanted in other langauges for a long time

19:15 so, if i'm going to change the state of a java object, it doesn't make a difference if i have a ref pointing to that object or not

19:15 in terms of concurrency concerns

19:16 so, what do you do to synchronize access?

19:16 i'm specifically working with a socket, here

19:17 not all at once, now

19:18 somnium: slyphon: you can put it an agent to serialize access

19:18 * slyphon hrms

19:19 slyphon: ok, that should do it

19:19 didn't think of that, thanks

19:19 raek: i've been thinking about trying out cells (the new reference primitive) on these sort of things...

19:19 slyphon: it's different from (dosync) right?

19:20 dosync only cares if the ref itself changes

19:20 somnium: slyphon: its async, just send or send-off

19:21 * slyphon nods

19:38 raek: which version of clojure is this intended to be run in? http://gist.github.com/306174

19:39 hiredman: master I imagine

19:39 raek: I get "Cannot assign to non-volatile: val" in 1.2.0-master when I evaluate (deftype ThreadCell ...

19:40 hiredman: master from git?

19:40 raek: yes

19:40 maybe I need build a newer version

19:42 hiredman:

19:42 "master from git" implies the latest from git

19:42 so don't say "yes I have that" unless you have the latest

19:44 raek: ok, that was not a very clear utterance of mine... :)

19:44 anyway, what I had was a less-than-a-week old version of master

19:46 hiredman: well, the gist is less-than-two-days old

19:47 raek: I guess I didn't realize how quick things change... :)

19:48 it works with master from git, I see now

19:48 thanks

19:49 lancepantz: anyone mind looking at http://github.com/lancepantz/clj-yaml and seeing if you can figure out why 'lein test' doesn't work?

19:56 chouser: oooo... metadata on local from an outer scope are available to macros that expand inside.

19:56 * chouser hatches a plan

19:57 technomancy: lancepantz: lein test only supports clojure.test not clj-unit

19:57 lancepantz: ah

19:57 cool

19:57 thanks for the project btw man

19:59 technomancy: glad you like it

20:00 hiredman: chouser: did you ever figure out keyword call site caching?

20:00 well then

21:14 * jcromartie sighs

21:30 jcromartie: no offense to Dan Larkin, but I went back to http://richhickey.github.com/clojure-contrib/json.write-api.html after banging my head against the wall adding datatype handlers to clojure-json

22:19 is there a more idiomatic way to turn a map into a keyword vector than (reduce into [] m)

22:19 ,(reduce into [] {:foo 1 :bar 2})

22:19 clojurebot: on vacation?

22:20 clojurebot: [:foo 1 :bar 2]

22:21 http://haacked.com/images/haacked_com/WindowsLiveWriter/IConfigMapPathIsInaccessibleDueToItsProt_1446B/works-on-my-machine-starburst.png

22:27 Raynes: http://stackoverflow.com/questions/2245985/compile-clojure/2246577#2246577 "Thank you so much, you are amazing."

22:29 JonSmith: i need to download lein

22:33 jcromartie: When did Google start returning results without all of the words in the query?

22:34 TheBusby: when did they not?

22:34 jcromartie: for a long time

22:35 if I search with "compojure" in the query I can get results that clearly never had "compojure" on the page

22:35 TheBusby: I think you may be mistaken, or are you using "+keyword" syntax?

22:35 jcromartie: no, except for stop words, they always returned results that matched all of the words in the query

22:35 TheBusby: if you search for elephant, you'll find pages that only refer to packaderm

22:36 I don't think they've ever supported "all pages that include all keywords" as the default behaviour

22:36 google derives most of their logic from links, hence keywords aren't valued as highly

22:37 hence you can google for "evil dictator" and the first hit may be the whitehouse.gov

22:37 Raynes: LOL

22:39 wilig: Hopefully a simple question: If a have a function that requires 3 arguments and a sequence of three things is there a way to call the function with the sequence? Without split out each one?

22:40 TheBusby: wilig: do you have an example of what you might be looking for?

22:40 jcromartie: wilig: apply

22:41 ,(apply + [1 2 3])

22:41 ,(apply str [1 2 3])

22:41 clojurebot: 6

22:41 "123"

22:41 jcromartie: seriously, what's up with clojurebot

22:41 BrandonW: i thought he said that the function requires 3 arguments?

22:41 wilig: jcromartie: duh! Thanks.

22:41 TheBusby: apply should work for N arguments

22:41 BrandonW: oh okay, nevermind

22:42 i thought apply worked on the basis that it can apply the first two arguments, then the result of that to the 3rd arg, then the result of that to the next.. etc.

22:42 jcromartie: that's reduce

22:42 BrandonW: oh okay

22:42 jcromartie: oh wait

22:42 no

22:42 BrandonW: (doc apply)

22:42 clojurebot: "([f args* argseq]); Applies fn f to the argument list formed by prepending args to argseq."

22:42 BrandonW: (doc reduce)

22:43 hiredman: ,((reduce partial + [1 2 3]))

22:43 clojurebot: "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val is supplied, returns the re

22:43 6

22:43 dnolen: _ato: you around?

22:43 BrandonW: ok you are right, jcromartie

22:47 Raynes: Apply just takes the elements out of the sequence and lays them neatly in a row in front of the fnmonster so he can gobble them up.

22:48 TheBusby: so ((reduce partial + [1 2 3]) 4) would end up being (+ 4 (+ 3 (+ 2 1)). What is the common use case for something like this?

22:50 slyphon: where's the "cell" stuff?

22:50 chouser: slyphon: just in a gist

22:50 slyphon: oh

22:50 bummer

22:56 chouser: you can use it though

22:56 just load the file. :-)

22:56 * chouser hasn't tried that yet.

22:56 slyphon: do you have a link?

22:56 chouser: http://www.shadyurl.com/

22:56 no. not that

22:57 try this: http://gist.github.com/306174

22:58 TheBusby: What is "magic" here? (magic - [4 5 6] [1 2 3]) => [3 3 3)

23:01 BrandonW: the magic of functional programming, of course!

23:02 drewr: TheBusby: map

23:03 BrandonW: if i was looking to learn more about clojure, should i get one of paul graham's books, go through SICP, or wait for the new clojure books to arrive?

23:03 TheBusby: drewr: thanks! I didn't realize you could use map like that

23:05 drewr: BrandonW: depends on what kind of knowledge you have already

23:05 BrandonW: this is my first foray into both lisp and functional programming

23:05 i forgot to say, i already went through Programming Clojure

23:09 drewr: start writing code and see what kinds of issues you run into along the way

23:09 though joyofclojure.com has been great so far, so get that when it comes out

23:19 TheBusby: For dealing with nested structures, how can you do this? (-> [1 2 3 4] (partial #(nth %2 %1) 3))

23:20 ,((partial #(nth %2 %1) 3) [1 2 3 4]) ;; Works

23:20 clojurebot: 4

23:24 jcromartie: OK so doing a with-json middleware using (decorate routes with-json) doesn't work

23:24 because whatever is returned by the route handler is converted into a response map as it goes up the chain of middleware

23:24 I think

23:25 i.e. I can't return a simple map from a handler and expect my with-json middleware to take care of it

23:29 JonSmith: are there any html generating frameworks for clojure that are higher level than converting vectors into html?

23:30 i'm using clj-html and it is really good, but i keep ending up with stuff that seems kind of awkward

23:33 i'm just having trouble conceptualizing managing all of the different pieces of webpages that i want to put together, and normally that means i need some macros or a higher level abstraction

23:34 konr: Anybody here does automatic stock trading?

23:34 BrandonW: exit

23:34 whoops

23:40 jcromartie: JonSmith: there's Enlive

23:40 but that doesn't generate HTML, it transforms it

23:41 JonSmith: yeah

23:41 i'm hoping to get 1 level up the abstraction level

23:41 if that makes any sense

23:44 jcromartie: can you work with functions that generate the HTML-generating code?

23:44 macros, etc?

23:44 that's what lisp is all about after all

23:44 JonSmith: yeah that's kind of what i'm doing write now

23:45 right now*

23:45 i'm working the clj-html and making a bunch of functions that expand into templates

23:45 i guess i can build a lower level of utility functions and work my way up

23:47 i guess the problem is that i build lisp code programmatically all of the time using macros and backquote and stuff, but i'm not seeing an obvious way to do a similar thing with html

23:48 I guess mostly because i think i'll run into efficiency problems and there is nothing quite like unsplice

23:49 not unsplice, splice

23:49 anyway i'm rambling

Logging service provided by n01se.net