#clojure log - Jan 24 2012

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

1:18 phil_: is it possible to create cyclic maps in clojure? i.e. A <-> B <-> A?

1:24 G0SUB: phil_: yes. using deftype.

1:25 muhoo: watching the clojure data structures talk on blip.tv, he does (identical? "foo" "foo") and gets false

1:25 &(identical? "foo" "foo")

1:25 lazybot: ⇒ true

1:25 muhoo: !

1:25 manuel_: hi

1:25 why does contains? return false on lists?

1:25 G0SUB: muhoo: literal strings are interned.

1:25 amalloy: ~contains?

1:25 clojurebot: Excuse me?

1:25 amalloy: contains?

1:25 damn it, who erased him?

1:25 manuel_: (contains? '(1 2 3 4) 1) => false

1:25 ~(contains? '(1 2 3 4) 1)

1:25 clojurebot: It's greek to me.

1:26 G0SUB: manuel_: contains? checks for the presence of the key. it should only be used on associative data-structures.

1:26 muhoo: G0SUB: yes, but my point is, he does something in his talk, it gets one result. i run the exact same thing in a repl, i get a different result

1:26 G0SUB: muhoo: who?

1:26 muhoo: rich hickey

1:26 manuel_: got it

1:26 G0SUB: muhoo: which talk?

1:26 manuel_: misleading name

1:27 common-lisp style

1:27 muhoo: it's the clojure data structures intro talk

1:28 G0SUB: muhoo: hmm. something like contains? on a list will be O(n). you really need a set for this job.

1:28 muhoo: G0SUB: wrong dude

1:28 i think manuel was asking about contains

1:29 G0SUB: muhoo: right. sorry.

1:29 manuel_: ^^

1:29 manuel_: so what i'm looking for would be (some #(= 1 %) '( 1 2 3 4 5))

1:29 G0SUB: manuel_: or (some #{1} '(1 2 3 4 5))

1:31 manuel_: uh how does that work?

1:32 G0SUB: manuel_: sets work as functions as well.

1:32 manuel_: ah got it

1:32 yeah thx

1:32 sorry i'm coming from CL (mostly) so getting a bit confused by the orthogonality

1:33 G0SUB: manuel_: true, the names & associated semantics can be confusing if you are used to CL.

1:33 muhoo: hashes are like functions too. clojure is trippy, especially coming from lisp

1:33 manuel_: but to be honest if the immutable/concurrency thing doesn't throw me off too much

1:33 G0SUB: muhoo: absolutely :-)

1:33 manuel_: i think i'm saying goodbye to CL

1:34 i had the hashes thing down

1:34 G0SUB: manuel_: I said goodbye to CL in 2009 itself ;-)

1:34 manuel_: heh

1:34 it's just too cumbersome when you need to do real life stuff with it

1:34 well for me anyway

1:34 G0SUB: I love CL implementations, especially SBCL & Clozure CL. the language, not so much.

1:34 manuel_: ccl is cool yeah, thank god that one came around

1:35 language i don't know, i'm just used to it

1:35 not that i've been programming CL professionally a lot during for the last years

1:36 G0SUB: manuel_: honestly, I still believe that CL gives the programmer an incredible amount of power. not sure if that's a good thing though.

1:36 manuel_: computers give the programmer an incredible amount of power

1:37 kedoodek: "Unix gives you just enough rope to hang yourself"

1:37 manuel_: i'm going to the CL meetup tonight though

1:37 hehe

1:42 muhoo: i'm ready to blow off all other languages and start using clojure for everything.

1:42 let's see if i can find a way to make money doing that though :-)

1:42 schleyfox: muhoo: do it

1:42 manuel_: the right tool for the right job

1:43 schleyfox: I just had an analysis task I was running on some of the supporting things for my company's ruby on rails application

1:44 clj_newb: (defn pop [] ... ) <-- creates an warning; how can I turn off the warning? I have a class (ns my.stack) ... and I really want the function to be called pop, so I can use my.stack/pop my.stack/push

1:44 schleyfox: I wrote an initial version in ruby, making use of the existing internal libraries we had for it

1:44 clj_newb: (defn pop [] ... ) <-- creates an warning; how can I turn off the warning? I have a class (ns my.stack) ... and I really want the function to be called pop, so I can use my.stack/pop my.stack/push (I',m not actualy implementing a stack; but the point is the overriding clojure.pop is on purpose; I just want to turn off the warning for this particular function)

1:45 schleyfox: It took 50 minutes to run in moderately optimized ruby (though the underlying library was to blame). I rewrote it in basically the same amount of code and it now finishes in under a minute

1:45 *rewrote it in clojure

1:45 kedoodek: what about the libraries?

1:45 did you rewrite them in clojure as well?

1:45 schleyfox: I switched to lower level java ones

1:46 but the analysis code + the shims to treat it like I did in ruby were equivalent to the ruby analysis code alone

1:47 muhoo: nice

1:47 manuel_: is there a way to get line numbers in error messages in clojure-swank?

1:47 in slime rather

1:48 i always get messages like "don't know how to create iseq from symbol" but no indication as to what iseq

2:07 scottj: manuel_: C-c C-k is the best way to get line numbers in errors

2:11 muhoo: huh. lots of interesting surprises

2:11 &(conj [ 1 2 3] 7)

2:11 lazybot: ⇒ [1 2 3 7]

2:12 muhoo: (conj '(1 2 3) 7)

2:12 &(conj '(1 2 3) 7)

2:12 lazybot: ⇒ (7 1 2 3)

2:12 muhoo: !

2:13 &(cons 7 [1 2 3])

2:13 lazybot: ⇒ (7 1 2 3)

2:13 muhoo: !!

2:14 the idea of consing someting onto the head of a vector and having it return a list is an intersting surprise

2:15 phil_: cons returns a sequence

2:16 conj is overloaded for all types

2:16 hiredman: cons is not the traditional cons

2:16 it doesn't create pairs

2:16 ,(cons 1 2)

2:16 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

2:16 hiredman: it just adds to the head of a seq

2:16 phil_: so conj on a vector appends to the end, conj on a list = cons

2:17 hiredman: nope

2:17 cons is for seqs, not lists

2:17 ,(list? (cons 1 '()))

2:17 clojurebot: false

2:17 hiredman: ,(seq? (cons 1 '()))

2:17 clojurebot: true

2:18 phil_: yea, i said so

2:19 but more specifically, conj's return value type is always that of its argument, while cons always returns a seq

2:19 correct?

2:21 amalloy: phil_: in general that's true, but it's stricter than is technically correct: conj can return whatever type it likes so long as it's an IPersistentCollection and it "makes sense"

2:23 brehaut: i kinda wish i had never taken on xml-rpc implementation as a project

2:23 phil_: amalloy: because every collection type defines its own conj, right? but is there a concrete example in the core data structures of conj returning an alternative type?

2:24 hiredman: array maps turn into hash maps if they have more than N keys

2:24 schleyfox: but that happens when they go over N=16 regardless of operation, I thought

2:24 phil_: ah good to know

2:24 amalloy: &(let [m (into {} (map vec (partition 2 (range 16))))] [(class m), (class (conj m [18 19] [20 21]))])

2:24 lazybot: ⇒ [clojure.lang.PersistentArrayMap clojure.lang.PersistentHashMap]

2:25 amalloy: schleyfox: relevance?

2:26 schleyfox: I suppose none

2:26 just curious about any conj specific variance

2:26 amalloy: also not actually true, although it could be if anyone had bothered to implement it

2:27 &(let [m (apply array-map (range 100))] ((juxt class count) (dissoc m 0)))

2:27 lazybot: ⇒ [clojure.lang.PersistentArrayMap 49]

2:28 schleyfox: curious and curiouser

2:29 amalloy: but the difference between hash and array maps is one that you may as well pretend doesn't exist, in which case there are no "interesting" examples of conj changing type of the entity

2:30 schleyfox: which is probably a good thing

2:33 muhoo: brehaut: why? is xmlrpc painful in clojure?

2:34 brehaut: muhoo: the spec is crap

2:35 if anything clojure makes it extremely clean inspite of the problems

2:36 muhoo: i have to guess that the spec for xmlrpc has to be better than the one for json

2:36 brehaut: hells no

2:36 replaca: I used xmlrpc from clojure and it wasm't too bad

2:37 brehaut: replaca: via necessary-evil or a java lib?

2:37 replaca: the worse prob is that I was talking to bugzilla which is written in perl so if something looks like a number it makes it a number

2:37 java lib

2:37 emezeske: how could the xmlrpc spec possibly be better than the json spec? ^_^

2:38 muhoo: replaca: the apache sax?

2:38 * emezeske ponders XML entity references.

2:38 brehaut: replaca: right. i've written a clojure / ring implementation of it

2:38 replaca: apache xmlrpc client

2:38 brehaut: to serve it?

2:39 brehaut: replaca: both

2:39 replaca: ahh, cool

2:39 brehaut: it uses clj-http for the client

2:40 replaca: https://github.com/brehaut/necessary-evil

2:40 replaca: yeah, this was old code

2:40 schleyfox: brehaut: good name

2:40 replaca: and it's been woking for over a year now, so I'm sure I'll leave it alone :)

2:41 especially since we'll probably ditch bugzilla anyhow this year

2:42 brehaut: replaca: that seems to be the best idea with xmlrpc

2:44 replaca: the whole low-level part of it (that pulls bugzilla data into clojure data structures set up the way I want them) is maybe 70-100 lines

2:45 maybe 2% of the code in the program

2:47 brehaut: for comparison the entire necessary evil is 475 lines

2:48 (client and server)

2:48 replaca: yeah, that sounds about right

2:49 a bunch of my code is weird date conversion stuff and the like

2:49 brehaut: hah yes

2:49 clj-time made life easier

2:49 once i worked out how to encode the craziness

2:49 unlink: What's the closest Clojure idiom for OOP? I'm looking to do something like (defn make-my-object [] (let [closed-over-field-a (ref []) other-closed-over-field (ref {})] (fn [param1 param2] method-body...)))

2:49 replaca: and bugzilla has other problems with time

2:50 and then making sure that things that should be strings really are strings (and not numbers)

2:50 brehaut: unlink: err. the first major idiom is to stop writing OO like code

2:50 phil_: whats a shorter way for (swap! x (fn [_] y))?

2:50 replaca: that's a perl prob, though, but xmlprc lets it happen

2:50 schleyfox: unlink: the closest (in the most literal sense) would be deftype

2:50 unlink: brehaut: Fair enough, but this time I really want it.

2:51 brehaut: phil_: (swap! x (constantly y)) but its not actually shorter

2:51 phil_: brehaut: but clearer, thx

2:53 brehaut: unlink: what is it you are trying to do. we cant make any suggestions with just what youve said

2:56 unlink: brehaut: I'm building an analysis platform which hosts generic, independent analysis workers which subscribe to and process real-time data feeds. That is the abstraction I'm structuring now -- enabling those workers to run, possibly with multiple instantiations, without sharing their private state

2:57 schleyfox: unlink: looked at storm

2:57 ?

2:59 brehaut: schleyfox: maybe jumping the gun a bit there

2:59 schleyfox: perhaps

2:59 brehaut: unlink: ok. so you dont actually want data hiding as much as polymorphism right?

3:01 unlink: brehaut: No, I want both. Clojure functions and maps with (static) vars would be great except I need to run multiple instances of the same worker at once, and their state must be independent

3:02 brehaut: unlink: independant state is different to encapsulation

3:02 what im asking is, are you doing the closure to hide the data or just to hold a ref?

3:02 unlink: true, I suppose that clojure's modules provide good enough encapsulation.

3:03 brehaut: whatever the case, id probably unify all the refs you have into a single map in a ref or atom

3:03 so that the data for the whole thing can be treated atomically

3:04 you can use the *-in family of fns to manage it trivially anyway

3:04 (update-in, get-in)

3:06 eg, (let [a (ref {}) b (ref {})] …) becomes (let [state (ref {:a {} :b {}))] …)

3:06 unlink: right

3:06 I'm more concerned with the closure itself, though.

3:06 brehaut: well its fine

3:07 i cant really suggest any more without knowing more about how you are structuring the rest of the program

3:08 AimHere: I see a line with lots of colons and empty curly braces and I immediately think of a fork bomb

3:35 Blkt: good day everyone

4:29 noidi: how can I println to stderr?

4:30 is there something handier than (binding [*out* *err*] (println ...))?

4:41 CmdrDats: noidi: (defmacro out-to-err [& body] `(binding [*out* *err] ~@body)) ?

4:42 haven't tested it, just wrote from the top of my head :P but then you should be able to just (out-to-err (println …))

4:42 AWizzArd: You could also (.write ^java.io.PrintWriter *err* "Hallo Welt")

4:43 (defn prerrntln [& args] (.write ^PrintWriter err (apply str args))) or something like that.

4:57 tsdh: AWizzArd: prerrntln, what a beautiful name. I'll call my first-born that way. ;-)

5:01 clgv: tsdh: try Atomfried for your first born ;)

5:03 tsdh: :-)

5:17 noidi: CmdrDats, AWizzArd: thanks. I only need stderr in one place so I'll just go with the binding, if there's no prerrntln (!) in clojure.core.

5:17 clojurebot: excusez-moi

5:21 AWizzArd: noidi: that is perfectly fine, it just is less efficient than calling “.write”.

6:16 Dotan_: hey guys, a long shot here - is there a guide showing "scheme to clojure" or anything close that someone familiar with scheme can use to boost up learning?

6:30 Kototama: hi, why does all my clojure files get compiled when building a WAR file with lein ring uberwar?

6:31 it creates a class per function, isn't that expensive?

7:02 tsdh: Kototama: Why do you think so?

7:16 Arafangion: Kototama: Some languages create an *object* per function.

7:22 raek: Kototama: clojure will create one class per (fn ...) expresion you eval. if you ahead of time compile your code, these classes will be stored in .class files

7:23 hrm, that was not totally accurate

7:25 before code is executed it's always compiled to jvm byte code

7:25 and each (fn ...) expression is compiled as its own class

7:26 when the code is evaluated (by running the compiled code) no new classes are created

8:03 samaaron: quick java question: when code creates a new object and assigns it to a private variable in the scope of a class, but not in any methods - how does that differ from not initialising the variable, and assigning to it in a constructor?

8:04 TimMc: Kototama: You can prevent the AOT generation of classes in your uberwar, but it will just happen again at JIT compilation, on the fly.

8:06 raek: samaaron: it is the same as assigning it from the constructor.

8:06 dnolen: samaaron: well, the latter has concurrency implications

8:07 main reason why deftype/record don't support constructors

8:07 raek: samaaron: on the bytecode level, all initializations happen in a constructor (<init>) or in the static initializer (<clinit>) for static fields

8:09 I assumed you were asking about what happens when you initialize a java field outside a constructor (syntactically)

8:10 class and instance fields are different from local variables on the byte code level

8:14 samaaron: raek: yes - the code i'm reading is initialising an instance field outside of a constructor

8:15 so, you're saying that on compilation, these external initilisations are moved inside of the constructor?

8:22 Kototama: tsdh: i just though loading so many classes would not be efficient for the JVM. Maybe i'm wrong

8:24 TimMc: how can I prevent aot when building a WAR?

8:24 tsdh: Kototama: I don't think there's much difference between loading thousands of classes with only a handful of members and loading a handful of classes with thousands of members each.

8:33 TimMc: Kototama: I wrote something to do this fo uber*j*ars, it could be expanded or imitated: https://github.com/timmc/lein-jit

8:34 Kototama: You can also modify your project to do this without any plugin help.

8:40 fbru02: hey guys i asked this at night, but couldn't figure it out I have sth like this : {"5" {"6" {"7" {"3" {:words {"close" 1}}}}}} I want to get to the {:words ...} hash what's the best way to do it ?

8:40 compj: get-in ?

8:41 fbru02: compj: fair enough but i don't know the sequence (i.e. 5 6 7 3)

8:45 raek: samaaron: yes

8:45 Kototama: TimMc: you mean modifying the project.clj ?

8:46 samaaron: raek: thanks. I just managed to find this post which appears to explain this stuff pretty well: http://www.artima.com/designtechniques/initializationP.html

8:47 TimMc: Kototama: Replace your core.clj with a loader.clj that calls it using clojure.main.

8:47 Kototama: look inside src/lein-jit or whatever.

8:48 raek: Kototama: the alternatives are loading those classes from files (aot) or compiling these classes from clojure source (in memory) and then load them (non-aot)

8:48 TimMc: fbru02: You don't know the sequence statically, you mean?

8:49 raek: this non-aot mode is sometimes called "jit compilation" which is a bit confusing IMHO, since there is already jit compilation on another level on the jvm

8:49 TimMc: We should call it OTF, On-The-Fly

8:50 raek: maybe the lein-jit plugin should be called lein-dont-force-aot

8:50 TimMc: yeah

8:50 * TimMc renames it, frustrates at most 4 people

8:50 raek: or the lein jit behavior could become the default

8:51 fbru02: TimMc: yeah

8:53 TimMc: fbru02: ##(let [path ["5" "6" "7" "3"] ds {"5" {"6" {"7" {"3" {:words {"close" 1}}}}}}] (get-in ds path))

8:53 lazybot: ⇒ {:words {"close" 1}}

8:53 TimMc: get-in isn't a macro, you just pass it the path

8:53 fbru02: TimMc: will try that :)

8:53 thanks

9:15 smokecfh: i'd like to browse through source code of a big clojure project -- any recommendations for that?

9:19 joegallo: any particular kind of project or library?

9:19 i mean, if you're familiar with http & java servlets, then maybe ring would be a good place to start for instance. but if that's greek to you, then maybe it wouldn't.

9:21 compj: an idea how I can add quaqua to a leiningen project and only add it to the jar when on a mac?

9:22 smokecfh: joegallo: anything big is fine, i'm especially interested in how well clojure scales when working in a team

9:23 joegallo: sadly, the biggest clojure project i know is closed source, but i can assure it works great on our team ;)

9:24 gtrak`: smokecfh: probably similarly to lisp, I imagine it depends on the team

9:36 kmicu: smokecfh: can you explain what do you mean by "programming language scales by team size"?

9:39 phil_: how can i insert (not replace) an element at a specific location in a vector?

9:39 conj always add to the end, assoc replaces the element at the given index

9:40 smokecfh: kmicu: in my experience (with java and common lisp mostly), the more restraining a language is, the easier it is to work in a team. i would like to see that this premise is incorrect.

9:40 phil_: adds*

9:43 dnolen: smokecfh: Clojure much more restrained then Java or Common Lisp

9:45 kmicu: smokecfh: Personally I don't see any correlation, but if you want browse some code, then 'closurescript one' source code is relatively big and has many deps.

9:45 compj: phil_: don't think there is something in the std lib, try a combination of split-at and concat

9:46 phil_: compj: really? why is that operation deemed so rare that its not even in the std lib?

9:46 dnolen: for the ClojureScripters, anything thoughts on this change? https://github.com/clojure/clojurescript/compare/115-internal-set-fields

9:47 allows set! on deftype/record fields declared ^:mutable

9:47 compj: maybe vectors aren't made for such use cases

9:48 phil_: dnolen: are you storing the mutables in the metadata?

9:48 compj: :/ the whole point of a vector is fast access to indexed elements imo

9:49 but ok ill think of something

9:49 dnolen: phil_: there is no reified metadata in CLJS, this is just at the level of the compiler

9:49 phil_: set! actually always let's you set fields, but this seems kind of nice both as documentation and a bit of sugar

9:50 clgv: phil_: but inserting in a persistent vector implies concatenation of two vectors which is currently not possible with sharing structure of both vectors in clojure

9:50 compj: phil_: yes, access to a indexed element, but that has nothing to do with inserting an element I think

9:51 clgv: phil_: concatenation with the current vector implementation need O(n) with n being the element count of the second vector

9:51 joegallo: my impression is that if you want to do something that's not very efficient, then clojure doesn't go out of its way to make that easy

9:52 but that's just an idle thought

9:52 phil_: clgv: ah i see

9:52 dnolen: joegallo: phil_: phil bagwell presented a data strucuture at the Clojure/conj that can work with persistent vectors that allows efficient insertion, but no ones taken up the enhancement

9:53 phil_: clgv: will have to look again at the low level implementation to see exactly why but ill take your word for it :) well then this explains things

9:53 joegallo: dnolen: yes, good point

9:54 phil_: dnolen: what does set! translate into on the js side? just a regular "a.x = y;"?

9:54 dnolen: phil_: yes

9:54 phil_: the compiler does some enforcement tho, not allowed to set locals

9:55 phil_: can you tell me where exactly in the code this translation takes place? i was looking at the cljs compiler recently in order to understand how assoc works on defrecords and was able to only imply what is happening by looking at the generated js code

9:56 dnolen: phil_: compiler doesn't do anything for assoc, that's all in CLJS

10:00 phil_: dnolen: well this happens in emit-defrecord in clj/cljs/core.clj, isnt that part of the compiler?

10:03 dnolen: phil_: yes defrecord spits out default implementations for a variety of protocols

10:05 phil_: dnolen: and what you did with set! works on all types?

10:05 dnolen: phil_: any deftype and defrecord yes

10:07 phil_: so you modified the compiler to support (or allow set!) but defrecord/type are just macros on the cljs side that expand and use the underlying mechanisms provided by the compiler?

10:07 (sorry for the dumb questions)

10:09 dnolen: phil_: yes. set! is allowed in Clojure if you declare mutable fields. This doesn't currently work in CLJS and this brings things more in line.

10:11 phil_: dnolen: cool, when is this going into master?

10:13 dnolen: phil_: just making sure no one is totally offended by it, probably later today.

10:15 phil_: dnolen: this is perfect, was contemplating on dropping to js for some heavy object manipulation, this will hopefully allow me to stay fully in cljs

10:16 dnolen: phil_: note that you can always (set! (.-property foo) ...), it's just unidiomatic.

10:18 phil_: dnolen: ok, will have to dive into things a bit more

10:20 dnolen: phil_: I've been thinking about the heavy object manipulation problem in CLJS as well. I want to experiment with the notion of transients in CLJS.

10:22 phil_: dnolen: yes, this would certainly simplify things... right now, if you want to do animations with timers or something it wont be very fast (judging by the generated js code), especially on mobile devices

10:22 i made a simple assoc test in a 3-way three of height 5-6 and it took almost 2secs for 1000 asoocs

10:23 (well, assoc-ins)

10:23 dnolen: phil_: true tho animations in JS is quickly becoming an anti-pattern especially on mobile devices that support CSS Transitions

10:23 phil_: (with simple compilation)

10:24 dnolen: yep, css3 is the way to go but if you want older browser support then you have to drop to timers

10:25 and unfortunately right now ie8 user base is big enough :/

10:25 lynaghk: dnolen, speaking of animation do you have any idea why doseq is so slow in cljs?

10:25 dnolen: lynaghk: allocation overhead

10:25 lynaghk: I remember chris granger throwing together a gist with some examples. I've found that it's something like 200 times slower than JS

10:26 dnolen: lynaghk: seqs just don't rock nearly as hard in JS as they do on the JVM

10:26 lynaghk: Do you have any nice tricks to get around that?

10:26 dnolen: lynaghk: for high perf JS code I think you'll want to write the critical bits with loop recur, dotimes, and mutable arrays/objects

10:26 same as Clojure really.

10:27 lynaghk: okay, I'll look into that

10:27 I was under the impression that doseq is just some sugar on something like loop recur

10:27 though that's just because I daydream a lot.

10:27 vimja: I'm trying to use a defrecord in another namespace; I've use'd the relevant namespace (test.my-record) and imported the class (test.my-record.Foo) but I can't figure out how to access the record. Any suggestions?

10:28 dnolen: lynaghk: I'm porting the Processing flocking animation from Clojure to CLJS, a benchmark for this stuff.

10:28 a good benchmark I mean

10:29 phil_: dnolen: is the code public? would like to take a look at high perf cljs code

10:29 dnolen: phil_: it will be, got some work to do yet.

10:29 phil_: thx

10:30 lynaghk: dnolen: yeah, that sounds great. I'd love to take a look at that to optimize my cljs visualization library

10:30 phil_: lynaghk: is your code public? :)

10:31 lynaghk: dnolen: also, if you want to use Cassowary there is a chromium guy who is also doing a JavaScript port focused on speed

10:31 dnolen: https://github.com/slightlyoff/cassowary-js-refactor

10:31 dnolen: cool!

10:32 lynaghk: yeah, apparently at the same time as I released mine. December was the dig-out-old-simplex-solvers month

10:32 phil_: it's not yet, but it will be released by March (in time for my Clojure/West talk)

10:33 phil_: lynaghk: allright, thx

10:33 lynaghk: phil_: it's basically a rewrite of D3 in ClojureScript that is more declarative and takes advantage of Clojure's semantics to do neat things. For instance, if you pass it data inside of an atom, it will update the DOM whenever the atom changes.

10:33 dnolen: lynaghk: slick!

10:34 lynaghk: Also, not tied to the DOM, so you can run it on the server. Or teh iPadz.

10:34 phil_: lynaghk: sounds cool, would love to take a look when its public

10:35 lynaghk: yeah, speaking of it I should probably get to work. Clients need their charts & graphs = )

10:36 phil_: haha, dito :D

10:37 pandeiro: lynaghk: that is very cool re: using atom watchers to update DOM... one of Clojure's very webapp-friendly features IMO

10:39 lynaghk: pandeiro: yeah, it's one of those things that's, "oh, I could've made this in JS with an object with getters & setters and callbacks" but you just never got around to it

10:39 A lot of ClojureScript kind of feels like that, and it really adds up to a nicer experience.

10:39 That there are all these neat things laying around for you to use already

10:40 phil_: is there a more idiomatic way of doing this: https://gist.github.com/1670753 i.e. a zipper changing global state whenever it is updated

10:41 like using core.zip or something

10:45 im basically trying to have an immutable global tree with the addition that every node can update its children (and thus the global tree) without having to know where exactly it is located in the tree

11:25 blcooley: Is anyone successfully using SLIME apropos with clojure-jack-in?

11:25 jebberjeb: #away

11:25 uh, sorry

11:26 blcooley: I can use the other SLIME documentation commands (C-c C-d d) but apropos gives me an assert error on descriptor

11:34 compj: blcooley: apropos works here

11:35 blcooley: compj:ok, thanks. probably just something in my setup I guess.

11:35 compj: do you have clojure swank 1.4.0 snapshot?

11:36 i think there were some commits recently

11:37 here this might be the difference https://github.com/technomancy/swank-clojure/commit/8637ccfec5fbfb85bf418f9be54465edb86699e5

11:38 blcooley: compj: aha, that's probably it. Thank you very much. Updating now.

11:38 compj: no problem :)

11:45 blcooley: compj: That did the trick. Thanks again.

11:46 compj: let's thank tavisrudd for the fix

11:46 blcooley: Indeed!

11:51 tavis: blcooley: it was just fixed yesterday

11:51 compj: has anyone else the buffer name *slime-repl nil* instead of *slime-repl clojure* in emacs?

11:51 stuartsierra: compj: yes

11:52 tavis: yep, also just fixed yesterday: https://github.com/technomancy/clojure-mode/pull/62

11:52 the fix is in there waiting to be pulled

11:52 stuartsierra: cool, thanks tavis

11:53 compj: I dived into the *slime-repl nil* problem for a while and I think I have a solution

11:53 tavis: another bug fix introduced it so hopefully I haven't reintroduced it

11:53 jonasen: Anyone been able to use goog.dom.query with ClojureScript? It's included in the closure zip file that the bootstrap script downloads.. But I don't know how to require it

11:53 blcooley: tavis: Thanks! Really helpful!

11:53 tavis: it's jack-in calling (slime-output-buffer) before the connection is open

11:54 jonasen: It's in the third_party folder

11:54 compj: https://github.com/technomancy/swank-clojure/blob/master/src/swank/payload/slime.el#L2058

11:54 phil: jonasen: look at the samples, i thinnk they use that

11:54 compj: I changed this handle to be synchron and it worked

11:55 although the comment says you shouldn't

11:56 jonasen: phil: I've only seen goog.dom used in the samples and not goog.dom.query. I'll have to take another look

11:57 tavis: compj: btw, were you having the nil issue prior to last summer? If so, it's not caused by what I thought.

11:57 compj: mh can't say, using it since september

11:59 tavis: well, fingers crossed. Good to know there's another way around it if my fix doesn't solve it for everyone.

11:59 compj: the implementation name seems to be set too late. the buffer gets created before the result from the connection-info request are there

11:59 tavis: exactly

11:59 clojure-jack-in was doing something too early

12:48 does clojure.contrib.profile have a new 1.3 home?

13:00 phil: are there any vids available from the last clojure/conj?

13:05 TimMc: tavis: Is it not listed on the contrib migration page?

13:06 ~clojure.contrib

13:06 clojurebot: excusez-moi

13:06 TimMc: clojurebot: Where did contrib go?

13:06 clojurebot: well... it's a long story: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

13:07 TimMc: tavis: Oh, looks like it's listed, but has no home in 1.3.

13:09 tavis: do you know of any good simple alternatives that would work well from a repl?

13:10 aside from `time`

13:30 jsabeaudry: Is there a way to have some kind of redirect in a clojure web application that will be transparent to the client?

13:32 Let me take a step back

13:34 I am hosting a web application on limited hardware. One of my http handlers is returning a binary stream but clojure is too slow to do the work. What I thought is that I could run a C server that does the work and my clojure webapp would just be a kind of proxy for that particular handler

13:34 Am I dreaming or is that feasible?

13:34 gtrak``: jsabeaudry: what's the source of the stream?

13:35 Twey: jsabeaudry: Is this binary stream static?

13:35 jsabeaudry: gtrak``, A FPGA but some processing is required on the stream

13:35 gtrak``: if it's a file, you can mmap it

13:35 * Twey blinks.

13:35 gtrak``: fun

13:36 jsabeaudry: so, how do you get the data for the stream?

13:36 TimMc: jsabeaudry: Your web server itself can run a reverse proxy that delegates as necessary.

13:36 muhoo: depends on how the device driver is implemented, i suppose

13:37 jsabeaudry: gtrak``, Most probably a non-seekable character device

13:38 TimMc, What would be a good lib for reverse proxying in clojure?

13:38 gtrak``: ah, so if you can't mmap, you'll have to buffer, but I guess you already know that? is that avoidable in C?

13:39 muhoo: there's a java trick to turn a char device into a filestream

13:39 probably would work in clojure too

13:39 gtrak``: if it works in java, it works in clojure

13:40 jsabeaudry: muhoo, Yes but I also need to do some processing on it

13:40 gtrak``: what kind of processing?

13:40 muhoo: i did this recently in java

13:40 jsabeaudry: muhoo, That is what causes the problem, because clojure/jvm is too slow

13:40 muhoo: i used a FileInputStream

13:40 read from that, then sent it out a FileOutputStream

13:40 jsabeaudry: gtrak``, signal processing,

13:41 gtrak``: right, i figured as much

13:41 srid: non-clojure question, but I figured people here may have some idea: is redis appropriate for storing a stream of real-time events (eg: from log files on many servers; think heroku pulse)? or is there something else that is more appropriate?

13:41 muhoo: i had to write a jni ttyserial.c to do it

13:41 (this was on android platform)

13:41 it was a PITA

13:42 gtrak``: jsabeaudry: well, if you're doing some algorithmic stuff, sounds like you'll want to optimize for your processor, you could also look into JNI or JNA for a C to java bridge

13:42 muhoo: +1 jni

13:42 ah

13:42 clojurebot: Huh?

13:43 gtrak``: jsabeaudry: there are ways to share data to C without copying

13:43 tavis: jsabeaudry: are you doing any post processing on the clojure side?

13:43 jsabeaudry: tavis, I don't plan too

13:43 gtrak``: without knowing much about your design, imo, I'd keep everything I can in java, like web stuff

13:43 by java I mean clojure

13:44 tavis: do you have another webserver sitting in front of your jvm?

13:44 jsabeaudry: I guess I'll go with TimMc's suggesting of running a reverse proxy on the server

13:44 muhoo: easier

13:45 jsabeaudry: tavis, No

13:46 gtrak``: jsabeaudry: interesting to me b/c in a past life I studied DSP/compArch :-)

13:46 muhoo: so, "slow" in the sense of latency?

13:47 in that case, http redirect, let the browser talk directly to the stream, less stuff in the way.

13:47 jsabeaudry: muhoo, No, too slow in terms of CPU usage

13:49 gtrak``: jsabeaudry: in general, unless you're writing vector code with custom simd stuff, java can be faster

13:50 jsabeaudry: gtrak``, Basically we are doing an instrument, the UI is web-based, runs on an arm7a platform the size of a credit card, some of the DSP is done on an FPGA and some on the arm. Lot's of fun stuff if you ask me.

13:50 gtrak``: or trying to take advantage of mem alignment, cache stuff, etc..

13:50 ah, arm

13:50 yea, I think on arm java the tradeoffs are different

13:51 actually never looked into it deeply, what about the jazelle stuff?

13:52 jsabeaudry: gtrak``, I checked quickly but it seems the architecture we are running on is not supporting it

13:53 In all cases, it's not a big deal to have some stuff running in C

13:53 All the drivers are written in C anyways

13:53 gtrak``: yea, so you want avoid writing web code in C

13:53 jsabeaudry: Exactly

13:54 Just that one handler will be in C and its just an application/octet-stream so no web stuff really

13:54 TimMc: So you just need to proxy data from C out across a binary HTTP response?

13:55 gtrak``: you have choices, if JNI works, use that, or you can use some kind of IPC, pipes, streams, sockets, etc... not sure how hard http would be in C

13:55 jsabeaudry: TimMc, Yes pretty much

13:56 TimMc: then it's probably easier to proxy from Clojure than accept a web request from C

13:56 muhoo: net socket is probably a LOT easier than jni

13:57 gtrak``: proxying a http request sounds wasteful to me, sockets would be trimmer

13:57 muhoo: if the c thing speaks tcp, probably easier to shovel bytes to cloujre via a net socket, then from clojure out to the browser, than to go dicking around with jni and opening char devices

13:59 emezeske: Is it possible to access unix domain sockets from Java? Those are always nice for efficient local proxies (and very simple from C).

13:59 muhoo: ah

13:59 http://nakkaya.com/2010/06/15/clojure-io-cookbook/

13:59 tavis: do you have access to unix domain sockets? If so you could do the initial request handling on the clj side and then sendmsg to pass the client socket off to c

13:59 muhoo: so, there's the socket way, and the file way, both in clojure :-)

14:00 gtrak``: awesome that you get to write clojure code on an arm, btw :-)

14:01 there's this: http://code.google.com/p/junixsocket/

14:02 apparently to use unix sockets you need native code

14:02 tcp sockets I guess you don't

14:02 muhoo: gtrak``: jsabeaudry: http://nakkaya.com/2010/06/15/clojure-io-cookbook/

14:03 gtrak``: muhoo: yea, I saw that, unix sockets are different

14:07 muhoo: ooh neat, there's some clojure sugar around the ugly java file io http://richhickey.github.com/clojure/clojure.java.io-api.html

14:07 lazybot: Nooooo, that's so out of date! Please see instead http://clojure.github.com/clojure/clojure.java.io-api.html and try to stop linking to rich's repo.

14:07 gtrak``: $botsnack

14:07 lazybot: gtrak``: Thanks! Om nom nom!!

14:09 muhoo: hm, google disagrees with the bot

14:11 TimMc: Google can suck my keyboard.

14:11 I'm so done with them. </rant>

14:12 muhoo: What really needs to happen is that site should be replaced by redirects. I think replaca is the one who can do that.

14:14 gtrak``: it's been talked about a lot

14:14 every page that someone can link to needs to be replaced by a redirect?

14:15 TimMc: right

14:15 It can be done with a META refresh or maybe some JS.

14:20 raek: refresh and js solutions do not preserve the "referer" header

14:20 in case you want that data in google analytics, for example

14:21 * raek saw all of the context

14:22 TimMc: Well, you could still get origin information off the original repo.

14:23 I'm not sure I can bring myself to care about "page stickiness ranked by origin" or other such abominations of analytics.

14:25 amalloy: jsabeaudry: is there a reason you can't just use nginx or some similar webserver to bypass the clojure app entirely in cases where you'd have it proxy to C?

14:27 Raynes: TimMc: I found that putting nude images of amalloy up on refheap took traffic away from the main content, thus not helping the cause at all.

14:27 TimMc: Raynes: I thought that was an iguana. :-P

14:28 amalloy: hahaha

14:28 TimMc: amalloy: That would require responding to HTTP in C.

14:30 jsabeaudry: amalloy, probably not, it is one of the possibility but I wonder if that might have some impact with regards to authentification

14:31 muhoo: is this thing linux on this arm?

14:31 just run lighthttpd or any of the many arm/busybox http daemons, i.e. for openwrt

14:32 iirc there is even an httpserver applet built into busybox

14:34 bhenry: &(doc if-let)

14:34 lazybot: ⇒ "Macro ([bindings then] [bindings then else & oldform]); bindings => binding-form test If test is true, evaluates then with binding-form bound to the value of test, if not, yields else"

14:39 jsabeaudry: muhoo, And run clojure as fastcgi?

14:41 tavis: jsabeaudry: the fd descriptor passing over AF_UNIX sockets approach I mentioned won't work in java: http://lifecs.likai.org/2010/05/passing-file-descriptor-over-unix.html

14:45 replaca: TimMc: so it turns out that github pages (which is what we use for the docs) doesn't support redirects

14:45 brehaut: replaca: you could use an html meta equiv

14:45 (not ideal though)

14:45 replaca: brehaut: I looked at that a while back and decided it would be better to just edit that pages

14:46 haven't gotten to it yet though :(

14:46 brehaut: replaca: i'd probably do both :(

14:46 replaca: yeah, I might

14:46 brehaut: search engines at least will respect the header

14:46 replaca: that would be a bonus

14:48 what I've really been waiting for is for github to support redirects, but I need to bother them more and maybe buy them some beer :)

15:02 the-kenny: What's the best way to stay updated on ClojureScript-Development? Like breaking changes etc.

15:03 stuartsierra: clojure-dev

15:03 TimMc: ^ the mailing list

15:04 the-kenny: Hm, okay

15:04 Thanks :)

15:05 stuartsierra: also just watch Git and read the commits

15:07 Raynes: $ git log

15:15 amalloy: Raynes: i think your shell is in another buffer

15:15 TimMc: Sorry, Mario.

15:16 Raynes: amalloy: I was responding to the-kenny, but yes, it is definitely elsewhere.

15:16 the-kenny: :D

15:45 sritchie: do you guys know how to add other repositories to leiningen's list when searching for plugins?

15:45 technomancy: this might be for you

15:46 Raynes: sritchie: Edit your hosts file. ;P

15:46 joegallo: https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L106

15:46 i think

15:46 sritchie: joegallo: this is for plugins, so it works outside of projects

15:47 Raynes: is that in ~/.m2?

15:47 joegallo: oh, my bad

15:47 probably some magic init.clj then, but i dunno

15:47 sritchie: Raynes: I don't know where to look for the file that sets up central and clojars

15:47 Raynes: sritchie: It was a bad joke. I was talking about http://en.wikipedia.org/wiki/Hosts_(file)

15:48 sritchie: nice, I'll just redirect clojars over and call it a day

15:48 Raynes: Heh

15:48 But that is a good question.

15:49 The plugin system is just a bizarre way to avoid a global project, it seems.

15:49 But what do I know?

15:49 * Raynes dons his dunce cap.

15:52 technomancy: sritchie: that's something we'll have a better answer for in lein2

15:52 sritchie: this is for an internal twitter lein plugin

15:52 so for now i should just have people install it manually?

15:52 rlb: technomancy: btw, happy to see you're working on lein for debian.

15:53 technomancy: rlb: that's mostly bablien

15:53 sritchie: technomancy: I'll have folks git clone and lein install

15:53 technomancy: sritchie: user-level repositories are basically build-poison in most cases

15:53 rlb: technomancy: ok, still happy ;>

15:53 technomancy: #1 cause of works-on-my-machine

15:54 sritchie: I agree

15:54 what do you think I should do here?

15:54 technomancy: but this is a special case

15:54 sritchie: for distributing a private plugin

15:54 y

15:54 eah

15:54 technomancy: I need to head off; can you start a mailing list thread?

15:54 samaaron: what's the simplest approach to compiling a nested set of dirs with .java files in?

15:54 TimMc: javac

15:55 samaaron: TimMc: can i just pass a root dir to javac?

15:55 TimMc: * poker face*

15:55 Raynes: TimMc: You can use Leiningen.

15:55 But you're not samaaron.

15:55 And I need to get more sleep.

15:55 samaaron: Raynes: i moved from javac to lein

15:55 but lein javac just created me an empty classes dir

15:56 Raynes: samaaron: Could you tell me about your project setup?

15:56 samaaron: my problem is that i don't know what's going on under the hood here

15:56 Raynes: I probably do. So start talking.

15:56 samaaron: Raynes: well, i have a dir with other dirs in

15:56 and in some of the other dirs are java files

15:56 Raynes: src/

15:56 ?

15:56 samaaron: yup

15:56 i'm assuming it's standard java layout

15:56 with a dir per package

15:57 Raynes: So, there is no Clojure stuff at all?

15:57 samaaron: not yet ;-)

15:57 Raynes: In your project.clj, set :java-source-path to "src"

15:57 samaaron: ah, i'd set :java-source to "src"

15:57 Raynes: If you end up mixing clj files and Java files in the same source path, you'll need to use the latest 1.x branch of Leiningen because I fixed some issues with that there.

15:58 samaaron: Raynes: ah cool, thanks for the heads up

15:59 is there a simple way of adding an extra lib dir with jar deps?

16:00 not all the deps to this project are in maven...

16:07 jeremyheiler: samaaron: could you install the jars into a local maven repo? or do you simply want them distributed with the project?

16:08 samaaron: jeremyheiler: eventually they'll go in a local maven repo - but just to bootstrap things it might be easier to bundle the jars with the src

16:08 technomancy: samaaron: if it's not in a repository it's not a real dependency

16:08 samaaron: technomancy: i don't quite understand the sentiment of that statemnt

16:09 how can you have a non-real dependency?

16:09 technomancy: that would be a "works by accident" situation, I guess

16:09 samaaron: currently the jars are stored in the project's repo

16:09 which isn't ideal

16:10 but not all of those jars are available in maven - I assume they're bespoke libs

16:11 so i thought it a good start to separate the maven libs from the bespoke libs until we get a local maven repo set up

16:11 technomancy: samaaron: have you tried the private-s3-wagon?

16:11 samaaron: technomancy: no - i haven't heard of it

16:11 technomancy: it's pretty easy to set up a private repo now: https://github.com/technomancy/s3-wagon-private

16:11 Raynes: technomancy -- makin' hard stuff easy and easy stuff avoidable.

16:12 technomancy: (the plugin-ness of it will be more streamlined in 1.7.0)

16:12 samaaron: sure, but this isn't a personal project

16:12 technomancy: samaaron: meaning you currently don't have a corporate aws account?

16:13 samaaron: meaning i'm sure i'm not allowed to stick these jars on non-uni servers

16:13 and i also know that they're working on deploying a local maven repo

16:13 so i was just thinking of something that works for now

16:14 i.e. have a non-maven-lib with non maven jars

16:14 which would also be in the classpath

16:14 technomancy: it can be done, but it's strongly discouraged

16:14 samaaron: until those libs are available in a local maven repo

16:14 technomancy: you can specify file:// URLs in :repositories

16:14 as a temporary measure

16:15 samaaron: technomancy: what's the motivation for strongly discouraging the practice?

16:15 technomancy: samaaron: git is absolutely wretched at storing binary files

16:15 samaaron: yeah, that's very true

16:15 technomancy: it's just the wrong place for artifacts

16:15 weavejester: technomancy: Is the lein-survey yours?

16:15 technomancy: but if you're working around bureaucratic policies then I have some sympathy =)

16:15 weavejester: aye; hope to have the results summarized within a week

16:16 samaaron: technomancy: well, it's only a short-term solution - I'll be rebuilding it all in Clojure anyway

16:16 technomancy: samaaron: just be aware you may want to rewrite that stuff out of your history down the line if you continue to use that same git repo

16:16 weavejester: technomancy: Your shell command for finding most-used subcommands has a bug

16:16 technomancy: It strips out commands in the 100s and 10s

16:17 technomancy: samaaron: I saw a project using jars-in-git that had just switched to git 3 months ago and had already bloated the repo size up to 300MB

16:17 samaaron: technomancy: understood

16:17 technomancy: weavejester: yeah, it's fairly flawed. if you have multiple shells open you can't really trust your history.

16:17 weavejester: plus it doesn't work with zsh

16:17 taking it with a huge grain of salt

16:17 weavejester: technomancy: It worked okay with my zsh

16:18 technomancy: Well, except for removing the first 4 lines, but that was egrep

16:18 technomancy: heh

16:20 TimMc: I still don't understand how history interacts with multiple shells.

16:20 samaaron: is there a difference between Sun JDK and Open JDK libs? javac is crying about not being able to find javax.servlet.http.HttpServletRequest

16:20 TimMc: I think sometimes they get reused, too...

16:21 jeremyheiler: samaaron: HttpServlerRequest is in java ee

16:21 amalloy: TimMc: it's just a total mess. i don't trust it at all

16:21 jeremyheiler: so, not part of the std dist

16:21 Somelauw: Why even have the difference between sun and open jdk? It's just confusing anyway.

16:21 samaaron: jeremyheiler: I thought ee was just some marketing hype

16:21 geoffeg_c: amolly: http://stackoverflow.com/questions/8992997/initializing-elements-of-a-map-conditionally-in-clojure you put the let around the defn? does that make the fn scoped inside the let? :)

16:21 samaaron: is it an extension to the JDK libs?

16:21 TimMc: Somelauw: Sun (well, Oracle) is being a bastard about licensing right now. I'm glad to have the OpenJDK.

16:21 jeremyheiler: samaaron: it's a separate lib, yes.

16:22 TimMc: Also, I think at v1.7, OpenJDK is the reference impl

16:22 jeremyheiler: well, it's mutltipe separate libs...

16:22 samaaron: jeremyheiler: separate lib as in apt-get java-ee or a maven dep?

16:22 jeremyheiler: samaaron: you want servlet-api.jar

16:22 maven dep

16:22 samaaron: nice

16:22 amalloy: i don't think i understand either the question there, geoffeg_c

16:22 TimMc: geoffeg_c: No, it just means the defn seems some locals no one else does.

16:22 *sees

16:23 samaaron: technomancy: thank you so much for lein search :-)

16:23 technomancy: samaaron: yeah once I wrote that I wondered why I had taken so long =)

16:23 geoffeg_c: hmm, nice.. i guess :)

16:24 samaaron: hmm, so the question now is which version of the servlet-api to go for...

16:24 jeremyheiler: what servlet container are you deploying to?

16:24 samaaron: jeremyheiler: is tomcat a servlet container?

16:25 TimMc: geoffeg_c: Do you *need* to know users' gender? At least allow an :unspecified.

16:25 jeremyheiler: usually you mark "servlet-api" as a compile time dep, and thenuse the servlet-api.jar bundled with tomcat (in your case) be used at runtime.

16:26 samaaron: jeremyheiler: sounds swanky, but i'm not sure what you mean by marking as a compile time dep

16:26 cemerick: jeremyheiler: you mean "provided"

16:26 jeremyheiler: cemerick: yes, my bad

16:26 samaaron: perhaps i'm doing totally the wrong thing, but i'm currently attempting to compile my java code so tomcat can run it

16:26 but i'm really shooting in the pitch black darkness with all this

16:27 jeremyheiler: samaaron: you're on the right track. The problem is that you need servlet-api.jar to compile, but your servlet container (this case tomcat) provides one for you, so you don't need to distrubute your war with the servlet-api.

16:27 cemerick: samaaron: If you're using ring, you don't need to worry about it; it already depends on servlet-api transitively.

16:27 samaaron: cemerick: i will be using ring in the rewrite

16:27 but right now i just need to get this old java fecker working and fix some bugs

16:28 jeremyheiler: so do i need to compile with the same servlet-api that ships with tomcat?

16:29 mattmitchell: what's the best way to turn a collection into a hash-map, where the key is the index of the item in the collection?

16:29 jeremyheiler: samaaron: the same version, es.

16:29 yes*

16:29 samaaron: also, i see no evidence of war on the server

16:29 it just seems that the compiled libs are put in a tomcat-friendly dir structure where tomcat knows where to look

16:30 the-kenny: mattmitchell: (into {} (map-indexed identity seq)) or something like that

16:30 amalloy: mattmitchell: map-indexed vector?

16:30 samaaron: WAR.. HUH! What is it good for?

16:30 jeremyheiler: if you put a war file into the "webapps" directory, then tomcat will auto deploy it aka, unpackage it.

16:30 amalloy: &(into {} (map-indexed vector '[a b c d e]))

16:30 lazybot: ⇒ {0 a, 1 b, 2 c, 3 d, 4 e}

16:30 the-kenny: &(into {} (map-indexed identity '[a b c d e]))

16:30 lazybot: clojure.lang.ArityException: Wrong number of args (2) passed to: core$identity

16:30 mattmitchell: ahh map-indexed! thanks

16:30 samaaron: jeremyheiler: sounds a bit pointless - unless i want to email the whole thing or somethign

16:30 the-kenny: Gnah :/

16:30 technomancy: samaaron: the only thing harder than resisting making jokes about .war files is resisting making jokes about .ear files.

16:31 jeremyheiler: samaaron: it makes remote deployment easier.

16:32 m0smith: hi all

16:32 mfex: &(zipmap (range) [:a :b :c :d]) mattmitchell

16:32 lazybot: ⇒ {3 :d, 2 :c, 1 :b, 0 :a}

16:32 m0smith: has anyone done any work in using Clojure within a JSP? maybe a taglib?

16:32 the-kenny: Ah, that's nice too

16:32 mattmitchell: mfex oh that's nice!

16:33 TimMc: m0smith: I was trying that out at work, but Enlive has terrible documentation.

16:33 Somelauw: ,(into {} (keep-indexed vector [:a :b :c :d])) ; Wait that is actually longer

16:33 clojurebot: {0 :a, 1 :b, 2 :c, 3 :d}

16:34 TimMc: I'll probably give it another shot in a month or so.

16:35 Raynes: I've tried to read Enlive docs/tutorials, but I mostly just get a headache and forget about it.

16:35 Somelauw: and has already been poste

16:35 Raynes: Not sure how I feel about a templating tool where it is appropriate to spend half a tutorial talking about scraping a website with it.

16:36 m0smith: Thanks TimMC

16:37 I am really more interested in having HTML with tags. or clojure scriptlets or some such

16:37 Not too interested in re-inventing that wheel

16:37 brehaut: Raynes: its definately worth pushing through the headache

16:37 Raynes: brehaut: Well, I expect someone will write something about it that isn't insane at some point. I'll definitely start paying attention then.

16:38 brehaut: Raynes: noted

16:38 technomancy: brehaut: yes, but that forces everyone else who might help in the future to go through the same headache =)

16:39 brehaut: technomancy: sadly true

16:39 technomancy: every time I start a new project I intend to try enlive, spend a few minutes looking at docs, and go back to hiccup.

16:39 brehaut: fwiw cemerick et al's book has a brief but clear introduction to enlive

16:39 technomancy: I'm strongly biased towards self-evident code.

16:39 cemerick: I've never quite understood the grumbling about enlive. If you know CSS…

16:40 brehaut: much expanded, actually.

16:40 brehaut: cemerick: oh, fantastic!

16:40 * brehaut looks forward to the final pdf

16:40 cemerick: The whole rough cuts thing never worked out so well. What's up there is probably 6 months old.

16:40 Raynes: My book will have a much better cover than his.

16:40 Which makes it a better book by far.

16:40 technomancy: cemerick: it's not the selectors; it's the transformation macros

16:40 cemerick: …and less than half the content.

16:40 brehaut: cemerick: how much XSLT had you done before enlive?

16:41 cemerick: oh wow, that is very stale

16:41 cemerick: technomancy: it's (nearly) all function-based at this point.

16:41 brehaut: too, too much

16:41 brehaut: oh yeah, it used to be heavily macro voodoo right?

16:42 cemerick: Yeah

16:42 technomancy: cemerick: in that case it's the out-of-date examples and docs I guess

16:42 brehaut: cemerick: i think of enlive as xslt done right rather than php done better

16:42 cemerick: it was the migration from that to where it is today that prompted cgrand's macro talk at the first conj

16:43 brehaut: technomancy: i think the biggest impedance to getting the hang of enlive at the moment is starting off with deftemplate

16:44 cemerick: brehaut: what, as in, where to put the template files?

16:44 brehaut: cemerick: partly, but also that its structured doc -> seq of strings

16:44 rather than structured -> structred

16:44 sorry about the typos

16:45 cemerick: well, that's the *last* step, not the first

16:45 brehaut: right, but if you go in thinking 'i want to template some stuff' its easy to get off on the wrong foot with it and make your life much harder than it needs to be

16:46 TimMc: cemerick: There's still a carpload (not correcting that typo) of macros, and no docs on them indicating how they should be used.

16:46 It's all macro-source-reading.

16:48 brehaut: theres only 14 macros?

16:48 to several hundred functions

16:49 13 if you dont count sniptest

16:49 cemerick: TimMc: I don't think that's true on either count.

16:49 TimMc: cemerick: It was several months ago, last time I tried it.

16:50 "does foo" is not sufficient doc -- "takes a fn and produces a transformer which does foo" is much better

16:50 brehaut: TimMc: have you seen brian maricks tutorial in the wiki?

16:51 https://github.com/cgrand/enlive/wiki/Table-and-Layout-Tutorial%2C-Part-1%3A-The-Goal

16:51 TimMc: Yeah, I couldn't get through it.

16:53 brehaut: i presume that goes doubly for dnolans tutorial then?

16:53 s/ans/ens/

16:53 pandeiro: i found dnolen's easier to 'get into'... but then i didn't use enlive on anything afterwards and have forgotten everything already

16:54 TimMc: Which is that?

16:54 brehaut: https://github.com/swannodette/enlive-tutorial/

16:56 TimMc: That was better, once I skipped past the scraping.

17:05 ordnungswidrig: is there a way to know if read encountered an eof in the middle of a form?

17:06 I mean "[1 2 3]" vs. "[1 2"

17:06 brehaut: ,(read-string "(inc 1")

17:06 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

17:06 Somelauw: That is a very generic error to catch

17:07 brehaut: has a fairly boring consistent string though

17:07 Raynes: You can catch it and check the message.

17:07 If the message isn't right, rethrow.

17:07 Somelauw: ,(read-string "1/0")

17:07 pjstadig: or just don't catch it and see what magic happens

17:07 clojurebot: #<ArithmeticException java.lang.ArithmeticException: Divide by zero>

17:07 hiredman: if you get the cause it's a lispreaderexception

17:07 Raynes: There ya go.

17:08 Somelauw: &(instanceMember (ArithmeticException. "") RuntimeException)

17:08 lazybot: java.lang.RuntimeException: Unable to resolve symbol: instanceMember in this context

17:08 ordnungswidrig: ,(let [r (new java.io.PushbackReader (new java.io.StringReader ":a 1"))] (read r) (read r))

17:08 clojurebot: 1

17:09 ordnungswidrig: (let [r (new java.io.PushbackReader (new java.io.StringReader ":a ["))] (read r) (read r))

17:09 TimMc: ordnungswidrig: You might check to see how the REPL handles this.

17:09 Somelauw: &(instance? (ArithmeticException. "") RuntimeException)

17:09 lazybot: java.lang.ClassCastException: java.lang.ArithmeticException cannot be cast to java.lang.Class

17:09 TimMc: since it knows when a form is complete.

17:09 ordnungswidrig: ,(let [r (new java.io.PushbackReader (new java.io.StringReader ":a ["))] (read r) (read r))

17:09 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

17:09 ordnungswidrig: ,(let [r (new java.io.PushbackReader (new java.io.StringReader ":a"))] (read r) (read r))

17:09 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

17:09 Somelauw: &(instance? RuntimeException (ArithmeticException. "")) ; Sorry, I am not that good at writing working code

17:09 lazybot: ⇒ true

17:10 m0smith: ,( + 2 3 4)

17:10 clojurebot: 9

17:10 Somelauw: But I made my point

17:10 m0smith: &(+ 1 2 3)

17:10 lazybot: ⇒ 6

17:10 Licenser: ordnungswidrig use the reader eof parameter

17:10 &(doc read)

17:10 lazybot: ⇒ "([] [stream] [stream eof-error? eof-value] [stream eof-error? eof-value recursive?]); Reads the next object from stream, which must be an instance of java.io.PushbackReader or some derivee. stream defaults to the current value of *in* ."

17:10 TimMc: m0smith: You can /msg lazybot for that too,

17:11 Licenser: ,(let [r (new java.io.PushbackReader (new java.io.StringReader ":a"))] (read r false :eof))

17:11 clojurebot: :a

17:11 Licenser: ,(let [r (new java.io.PushbackReader (new java.io.StringReader ":a ["))] (read r false :eof))

17:11 clojurebot: :a

17:11 Licenser: ,(let [r (new java.io.PushbackReader (new java.io.StringReader ":a ["))] (read r false :eof) (read r false :eof) )

17:11 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

17:11 Licenser: hrm

17:11 amalloy: Licenser: that's for "no forms left", not "incomplete form"

17:11 Licenser: I think the pushback reader was allowing unfinished forms, hence the pushback part

17:12 amalloy: no way

17:12 the pushbackreader is just so it can parse, for example, "abc(1)" - it can't know the symbol is done until it hits (, but it has to put the ( back in the stream

17:13 Licenser: hrm

17:14 ordnungswidrig: i think i will to have to add some meta information to my files like a checksum or "number of expected forms"

17:15 or I can peek using the pushbackreader if more is to come

17:16 TimMc: Trying to figure it out from here: https://github.com/clojure/clojure/blob/1.3.x/src/clj/clojure/main.clj

17:19 OK, I think the secret is that the REPL just calls read, and since there is no EOF on stdin, it just blocks until a full form comes in.

17:19 If you give it a file or string reader, it knows right away once it reaches the end of the input.

17:19 clj_newb: Is there a better way to concatenate two strings than #(apply str (concat %1 %2)) ?

17:20 cemerick: (str a b)

17:20 clj_newb: ,(str "thanks," " " "cemerick"))

17:20 clojurebot: "thanks, cemerick"

17:20 TimMc: &(.concat "abc" "def") ;-)

17:20 lazybot: ⇒ "abcdef"

17:21 clj_newb: this is embrassing; I even had the function in my example

17:21 Raynes: That's satanic.

17:21 clj_newb: why is using the .concat part of Java.String wrong?

17:22 while we're taling abot strings; is there a better way to take the first 10000 chars of a string rather than (apply str (take 10000 ...)) ?

17:22 TimMc: &(let [ss ["abc" "def"]] (String/format (apply str (repeat (count ss) "%s")) (to-array ss)))

17:22 lazybot: ⇒ "abcdef"

17:23 cemerick: clj_newb: you'd need to hint the call properly to avoid reflection; it can't be used with a HOF; it can only be used to concat two strings

17:23 TimMc: clj_newb: .substring, although it won't allow GC of the rest of the string while you hold it.

17:23 brehaut: ,(subs 10 "abcdefghijklmnopqrstuv")

17:23 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String>

17:23 brehaut: ,(subs "abcdefghijklmnopqrstuv" 10)

17:23 clojurebot: "klmnopqrstuv"

17:23 TimMc: (or is that split?)

17:23 brehaut: ,(subs "abcdefghijklmnopqrstuv" 0 10)

17:23 clojurebot: "abcdefghij"

17:23 clj_newb: TimMc: that could be a problem; I am trimming a log this way

17:23 i.e. only keeping the most recent 10000 chars of it

17:24 if it doesn't allow the GCing of the rest of the string, I will be one unhappy clojure programmer

17:24 brehaut: TimMc: substring does the thing you mean

17:24 clj_newb: doe substring create a new string?

17:24 does it keep a refernece to the old string?

17:26 haderach: so I just tried installing emacs clojure-mode, but M-X slime connects me to sbcl. How do I point it at the right Lisp?.3

17:26 Somelauw: I solved it by downloading clojure-jack-in, but there might be other ways.

17:27 technomancy: haderach: either M-x clojure-jack-in or M-x slime-connect; the swank-clojure readme has a pretty good (I like to think at least) overview

17:28 brehaut: clj_newb: the docs for substring dont actually mention it. its probably an implementation detail, though i do remember readingthat sun/oracle java does just return a new string with a pointer to the same chunk of memory

17:29 technomancy: it doesn't create a new string; subs and subvec are both potential memory leaks if you don't keep that in mind

17:30 TimMc: I used a WeakReference to check; whatever I'm using for .substring allows GC.

17:30 (let [s (apply str (range 10000))] (def w (WeakReference. s)) (def ss (.substring s 10 20)))

17:31 Then I ran (count (take 1e6 (range))) and checked (class (.get w)), it had become nil.

17:31 And that's (import 'java.lang.ref.WeakReference) for those following along at home.

17:37 ...and split, also.

17:37 pyr: swank-clojure is still the way to go with emacs, right ?

17:37 the-kenny: pyr: yup.

17:38 gf3: awkward

17:39 Somelauw: why did they all go?

17:39 TimMc: OpenJDK 64-Bit Server VM 1.6.0_20

17:39 hiredman: there goes the irccloud

17:39 TimMc: Netsplit?

17:39 gf3: TimMc: nah, IRCCloud just sucks, they go down often

17:40 TimMc: OK. I have joins/nicks/parts/quits turned off, so I didn't see what happened.

17:40 the-kenny: Yup, I like the idea, but there's too much downtime.

17:40 amalloy: TimMc: that surprises me - it's fairly clear from the source (of openjdk6, anyway) that substring shares the char[]

17:40 the-kenny: And the site gets awfully sluggish after some hours

17:40 trgv: hi :)

17:40 TimMc: amalloy: Weird.

17:40 amalloy: oh, i see. you were checking that the String is no longer referred to, and it isn't

17:41 but the larger char[] it contained is still referred to

17:41 TimMc: Ah!

17:41 Sneaky.

17:41 Welp, there goes that method.

17:41 amalloy: And split has the same problem? (While you're in there.)

17:42 trgv: i'm trying to code this algorithm http://weblog.jamisbuck.org/2010/12/29/maze-generation-eller-s-algorithm with no luck, someone could give a hint please ? =D

17:42 amalloy: TimMc: it looks that way

17:43 String.split delegates to Pattern.split, which calls String.subSequence, which seems to do the same sharing as substring

17:44 TimMc: All this structure sharing on splitting would be nicer if the GC could be told what portions of an array were still in use.

17:44 Like, "give me a subarray and feel free to trim the rest as necessary".

17:53 mr_rm: i've built a maven uberjar with all my dependencies, including clojure and some <code>.clj files (not compiled). does anyone know the way to call a function inside one of my clj files?

17:54 i tried: java -cp uber.jar clojure.main -i /my/file.clj -e "(func)"

17:55 technomancy: mr_rm: you can try clojure.main -m my.ns

17:55 but it'll only work on the -main function

17:56 mr_rm: technomancy: ok, i'll put the entry point in "(defn -main []...)" and see what happens :) thanks

17:56 technomancy: also, -m requires clojure 1.3

17:56 mr_rm: technomancy: oh... bummer. this is 1.2.1

17:57 di-csuehs: what does a graph look like in clojure? What do you pass as 'g' to the clojure-contrib.graph funcitons?

17:57 technomancy: well I did submit the patch before 1.2 was released. =\

17:58 mr_rm: technomancy: my jar is self-executable with a java main() wrapper right now but i was just wondering if i could call individual functions from the command line

17:58 technomancy: mr_rm: you can always use ns-resolve on the args you get.

18:00 mr_rm: technomancy: right but i'm not intending the wrapper to be a general caller. i want to distribute it always calling the main entry point. i was just wondering if there is some syntax for clojure.main that would let me call any arbitrary function inside an uncompiled clj file inside the jar

18:00 technomancy: yeah, it's a shame that didn't make it into 1.2 =\

18:01 mr_rm: technomancy: ok. i appreciate your response

18:03 technomancy: no problem

18:04 mabes: what is the correct way of using lein-multi? I'm seeing various ways: https://github.com/technomancy/doric/blob/5d996a777535f060581b350b710971187b108800/project.clj https://github.com/danlarkin/clojure-json/blob/6d7f28e58a2cd81a0e26a6c966d75b6310b638ad/project.clj

18:06 clj_newb: you know what else is fricking awesome? I can have keywords not only of the form :foo but alfo of the form :foo-bar .... it's just so nice

18:06 [end rant]

18:06 sometimes I use clojure; and I just don't understand why other langauges have all these weird limiitations

18:07 technomancy: mabes: they're both correct; what do you mean?

18:08 mabes: technomancy: I guess I'm unclear what the best practice is.. from your project above it seems that you are listing 1.3 as a dep.. so if a 1.2 person includes it they will have to exclude that dep.. where as with the json example no dependency is listed but both are tested..

18:09 technomancy: oh, sure. I'd say it's best to list your minimum required clojure version as a :dependency and list newer ones under :multi-deps

18:10 or start using lein2 where that functionality is built-in with profiles!

18:10 mabes: oh really... that sounds nice..

18:10 technomancy: it's still a bit early

18:10 mabes: I'm just patching clj-time so I probably won't do that in this case but for my own projects I can start trying it out

18:10 technomancy: but if you're feeling adventurous...

18:11 really really early, I guess I would say.

18:11 mabes: heh

18:11 technomancy: more like if you've got some time and you don't mind helping out or aborting your effort. =)

18:13 mabes: i.e. you like shaving yaks ;)

18:13 amalloy: technomancy: perhaps your "preferred" clojure version as the actual dep, rather than minimum

18:14 technomancy: amalloy: you mean if you like having newer features available for convenience during dev time?

18:14 dunno; seems like it would be too easy to commit code that uses them by accident

18:15 amalloy: no, just like as a description of intent: "clojail was written for 1.3, but as you can see from lein-multi it also supports 1.2.1"

18:16 which is very different, in terms of how confidently users will use a given version, from the converse

18:16 technomancy: I'm still reeling from the betrayal of maven version ranges; haven't settled on The Right Thing yet.

18:17 Raynes: clojail actually didn't work for pre 1.3 until Alan bitched me into making it 1.2 compatible.

18:17 :p

18:17 technomancy: seems like using the lowest by default keeps you honest

18:19 amalloy: i don't buy that at all: there are breaking changes in each direction. if you have 1.2 as your "canonical" version you can accidentally check in something that depends on dynamic vars, for example

18:20 technomancy: yeah, but 1.3 is supposedly an exception to the rule

18:20 in theory all consecutive 1.x releases will be additive

18:21 I guess it makes sense if your two versions are 1.2 and 1.3 though

19:04 semperos: way to see documentation for functions at cljs repl?

19:11 Raynes: What is 'clojure.repl/doc', Alex.

19:12 amalloy: does cljs have docstrings? i thought it didn't even have vars

19:14 dnolen: amalloy: the data is there, somebody just needs to make it work

19:14 clj_newb: I need help on the right term to search for. I'm on OSX. I'm creating a GUI in Clojure via Awt/Swing (it's a JFrame). I want the Frame to "jump to the front of the screen", i.e. be on top of all other windows. What is ther right term I'm loking for? (focus is not it)

19:16 Raynes: Oh, cljs.

19:16 clj and cljs are too similar.

19:23 sandbox`: hello. I'm trying to test a record that implements a protocol, and i would like to stub out one of the protocol's functions. is there a way to do this? does this make any sense?

19:26 i've tried with-redefs but it doesn't seem to be doing anything in this context

19:44 benares_98: what's the simplest way to install clojure on mac osx?

19:45 technomancy: clojurebot: how do I install clojure?

19:45 clojurebot: Gabh mo leithscéal?

19:45 technomancy: >=\

19:46 benares_98: clojure isn't an application that you interact with as an end user; it's just a library that you include with the software you write.

19:46 amalloy: http://stackoverflow.com/questions/5983427/how-to-install-clojure-on-ubuntu-10-04-from-github-repo-with-no-clojure-jar is about ubuntu but just as relevant on macos

19:47 technomancy: you mean macosecks?

19:47 amalloy: i like to leave you an opening to say that; you do so enjoy it

19:47 technomancy: I should let you know that it's appreciated.

19:49 benares_98: thanks, I'm looking to install several packages for my wife so she can join me for an clojure/overtone meetup tomorrow.

20:22 adam_: is anyone here programming clojure with monads?

20:22 brehaut: adam_: yes

20:23 ~anyone

20:23 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

20:23 tavis: adam_: google for Konrad Hinsen or Roman Gonzalez for a start

20:23 brehaut: also Jim Duey

20:25 tavis: yeah, Jim wrote an awesome tutorial series

20:26 brehaut: adam_: alternatively, just ask your question

20:26 tavis: note the contrib module Jim talks about has been replaced by clojure/algo.monads

20:37 * technomancy misread a "Monad tutorial for Clojure users" link as "XMonad tutorial ..." this morning and was mildly disappointed.

20:39 brehaut: technomancy: theres another one?

20:39 (tutorial that is)

20:39 technomancy: I think it was Konrad's

20:39 brehaut: ah right

20:40 didnt think we needed any more

20:41 technomancy: if there's one thing I learned from Haskell users it's that there's always room for one more blog post about monads.

20:41 brehaut: lol

20:42 tavis: not just them: http://www.meetup.com/vancouver-scala/events/41968702/ tomorrow night

20:42 er, Thurs

20:42 brehaut: tomrrow night isnt thursday?

20:43 you sir are living in the past

20:43 tavis: damn true

20:44 I once flew home from NZ on xmas just after dinner and arrived home for second xmas dinner a day later

20:44 brehaut: excellent

20:44 tavis: but second had lots of snow

20:47 brehaut: is that a good thing?

20:47 phil_: is there a way to make the compiler print a warning whenever a defrecord doesnt implement all of its protocol functions?

20:48 tavis: brehaut: not when your car is buried at the airport - it was

20:49 brehaut: tavis: oh

20:49 dnolen: phil_: nope

20:49 mattmitchell: could someone explain the reason why one of these macros works and the other doesn't? https://gist.github.com/1674116

20:49 dnolen: phil_: seems like something handy for the analyzer to do though

20:50 mattmitchell: I'm confused as to why the & arg works, but I can't pass a list in for the same result?

20:50 hiredman: mattmitchell: it's not the same

20:50 you have a quoted list and some symbols

20:50 phil_: dnolen: is that generally regarded as useless or is it just not high on the priority list?

20:50 hiredman: (a quoted list of symbols)

20:51 mattmitchell: hiredman: i feel like i've been down this road before, please continue :)

20:51 hiredman: mattmitchell: (x (one two)) will fail in the exact same way

20:51 phil_: dnolen: because i think that a "record is abstract" or w/e warning would eliminate a lot of bugs

20:51 hiredman: mattmitchell: well go write a lisp interpreter with quoting and macros so you know what you're doing next time

20:52 mattmitchell: hiredman: that's a great idea

20:52 hiredman: have fun

20:52 amalloy: wait what, why wouldn't (x (one two)) work in the second case?

20:52 it should expand to (let [one 1, two 2] (str one two)), which looks valid to me

20:53 hiredman: amalloy: but look at the call to str

20:53 actually, that might fail very oddly

20:53 (but it will)

20:53 (str quote (one two))

20:53 ,quote

20:53 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: quote in this context, compiling:(NO_SOURCE_PATH:0)>

20:53 amalloy: hiredman: i took out the quote

20:54 as did you, i think. (x (one two)) works fine with second definition

20:54 agreed (x '(one two)) is rubbish, but nobody seems to be arguing about that

20:54 hiredman: oh, right the let

20:54 mattmitchell: ahh ok

20:55 dnolen: phil_: I don't think it's a large source of bugs. But no it doesn't look like it's a high priority. Yet another gap that the community can easily fill.

20:56 hiredman: phil_: if your protocol is large enough to forget functions then maybe your protocol needs to be broken up

20:57 phil_: hiredman: i agree, but still, are there many use cases where it is desirable to have a half-baked defrecords lying around?

20:57 defrecord*

22:04 thelittlelisper: So what is the most interesting Clojure project you've seen lately and why?

22:04 brehaut: that is such a broad question

22:06 avout, core.logic, counter clockwise?

22:06 clojurescript?

22:06 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.IPersistentStack>

22:07 thelittlelisper: Cool - why are they interesting?

22:07 brehaut: you have google. the relevant sites are self explainatory

22:08 and will do a better job explaining than i will

22:09 thelittlelisper: :) I've seen them - I can see they're new and fresh - I was asking for personal preferences and associated reasoning

22:09 Why do you find them interesting?

22:09 brehaut: because they are doing cool stuff

22:20 skelternet: is anyone here familiar with the clojure-contrib.graph package?

22:33 jkkramer: skelternet: somewhat, got a specific question?

22:34 skelternet: I've been googling for usage and trying to understand what form the graphs should be in. I'm looking at the graph.clj source now.

22:35 so, the best specific question I have at the moment is, "What is a g(raph) in clojure?"

22:38 jkkramer: skelternet: in general, they could be represented in many ways — a collection of edges, a map of nodes to a set of neighbor nodes, etc. c.c.graph uses a struct of :nodes and :neighbors. see https://github.com/clojure/clojure-contrib/blob/master/modules/graph/src/main/clojure/clojure/contrib/graph.clj

22:39 skelternet: you should be aware that use of clojure.contrib is discouraged. unfortunately, there's no go-to replacement for clojure.contrib.graph as far as I'm aware

22:39 skelternet: you could check out https://github.com/jkk/loom but I haven't upgraded it to 1.3 yet. maybe I should do that…

22:41 skelternet: Thank you! I feel less disoriented. I saw the calls to (:neighbors in (get-neighbors but I didn't see anything describing what it was expecting.

22:41 I've run across mention of loom.

22:41 jkkramer: yeah, seems to be only documented in code comments

22:42 skelternet: Ha! was that tongue-in-cheek?

22:42 if so, sorry I missed the comments

22:43 jkkramer: not intentionally :) they're easy to miss

22:43 skelternet: found directed-graph in a defstruct

22:44 yes. I'm still adjusting to the language. subtle in some ways since it eschews the ceremony.

22:45 I'll take a closer look at loom

22:45 this is all recon. I'm not sure the science project will gain any traction or sponsorship in the day job.

22:48 whoa…:neighbors is not a necessarily a collection…it's a function that takes a node

22:53 jkkramer: clojure is cool like that. collections and functions are often interchangeable. collections can implement the function interface

22:55 skelternet: Thank you for loom.

22:55 Are you looking at Neo4j or the other graph db's in your other work?

22:56 jkkramer: loom was kind of an excuse for me to play with protocols & records, and get familiar with writing functional algorithms. it's relatively untested in real-world code

22:57 Raynes: There is a graph DB written in Clojure: https://github.com/flatland/jiraph

22:58 jkkramer: written by some upstanding gentlemen

22:58 * Raynes suddenly wishes he worked on Jiraph more.

22:59 skelternet: it is a wonderful age to be a software geek. *sobs of joy*

22:59 Tokyo Cabinet, eh.

23:01 jkkramer: loom is upgraded to 1.3 now, FWIW

23:01 Raynes: skelternet: tokyo cabinet is just one layer -- there can be others.

23:02 skelternet: Thanks! Now I feel a little pressure to actually use it. :) I have to ask….what did you have to change?

23:02 Raynes: Jiraph is currently going under a semi-rewrite and amalloy is writing an in-memory STM layer.

23:02 undergoing*

23:02 Wow, sentences are hard.

23:02 amalloy: nah, the STM layer was done ages ago

23:03 Raynes: It hasn't been *that* long since STM commits were rolling in.

23:03 skelternet: Not sure I understand the question.

23:04 skelternet: I'll look at it on git… the upgrade to clojure 1.3 seemed really quick so I'm wondering if it was so resilient and beautiful code it just worked.

23:04 jkkramer: oh, that was for me

23:05 I just had to change the dependency to 1.3, and then make add a :dynamic metadata thing to a var

23:05 s/make//

23:05 Raynes: Oh.

23:06 skelternet: When you're responding to a specific person, it is helpful to prefix your message with that person's nickname. Usually this is no trouble because IRC clients can typically tab-complete IRC nicks.

23:06 Like I just did there.

23:07 jkkramer: making code 1.3 compat isn't very hard if you're not using clojure-contrib

23:07 skelternet: all: I know that. I apologize. I was sloppy. Please accept my apologies.

23:07 muhoo: ,(quote foo)

23:07 clojurebot: foo

23:08 Raynes: skelternet: It's fine. I just got a little confused. :)

23:09 skelternet: sorry Raynes. I forget you can't see what direction I'm typing in. ;)

23:10 I'm still reading about jiraph

23:51 muhoo: what's the & operator do, as in [loc f & args] ?

23:51 skelternet: vargs?

23:51 it's the rest of the args

23:51 muhoo: skelternet: thanks

23:51 skelternet: optional, if I recall

23:51 jayunit100: why is it that the 2nd expression in doseq is NOT prefixed with a # ?

23:51 (doseq [[index word] (map vector

23:51 (iterate inc 0)

23:51 ["one" "two" "three"])

23:52 i would think that the expression part would be an anonymous function.

23:53 (doseq [i [1 2 3 4]] (print i))

23:53 skelternet: is doseq a special form or a macro?

23:53 jayunit100: (doseq [i [1 2 3 4]] #(print i)) ;;<--- this does not run properly.... because of the #.

23:53 doseq is a macro

23:54 I guess im confused what the purpose of declaring an anoynmous function is ?

23:54 if we can just express the same thing in a Closure.

23:55 amalloy: those words generally mean the same thing, so you'll have to clarify

23:55 jayunit100: well... in clojure - i would think that

23:55 (doseq [i [1 2 3 4]] (print i))

23:55 dnolen: skelternet: a macro

23:55 jayunit100: should have the same result as

23:55 (doseq [i [1 2 3 4]] #(print i))

23:55 but it doesnt

23:56 amalloy: jayunit100: that would be true if (print i) were the same as #(print i), but obviously they're not

23:56 jayunit100: yes - one is a closure, the latter is an anoynmous function

23:56 amalloy: no

23:56 jayunit100: Ahh duh .

23:57 amalloy: the former is an expression causing something to be printed; the latter is an expression which evaluates to a function (closure, if you prefer)

23:57 jayunit100: no they are not because closures are blocks that only exist in scope of the code in which they occur.

23:58 yes @amalloy thats a good explanation

23:59 skelternet: How can I use macroexpand to show what doseq is doing?

23:59 dnolen: ,(macroexpand '(doseq [_ 10]))

23:59 clojurebot: (loop* [seq_33 (clojure.core/seq 10) chunk_34 nil count_35 ...] (if (clojure.core/< i_36 count_35) (clojure.core/let [_ (.nth chunk_34 i_36)] (do) (recur seq_33 chunk_34 count_35 (clojure.core/unchecked-inc i_36))) (clojure.core/when-let [seq_33 (clojure.core/seq seq_33)] (if (clojure.core/chunked-seq? seq_33) (clojure.core/let [c__3921__auto__ (clojure.core/chunk-first seq_33)] (recur (clojure.co...

Logging service provided by n01se.net