#clojure log - Feb 14 2011

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

0:26 amalloy: chouser: i just got here but sexpbot seems to have been pretty quiet. what does he need to tell stu?

1:30 simard: why does (:bah #{:test 3, :bah "hey"}) return :bah instead of "hey" ?

1:30 danlarkin: you've constructed a set

1:30 not a hash map

1:30 simard: oh

1:31 is there a syntactic sugar for that ?

1:31 amalloy: simard: drop the #

1:31 &(map :bah [#{:bah 1} {:bah 1}])

1:31 sexpbot: ⟹ (:bah 1)

1:33 amalloy: an amusing alternative, i guess, is ##((juxt #{:k 1} {:k 1}) :k)

1:33 sexpbot: ⟹ [:k 1]

1:33 hsaliak: hello, if i need to generate a class that in which I need to override the super class's constructor, the only way to do this is via gen-class's :init right?

1:33 simard: nice, I'm a little confused about the keyword being a function though, is it the parser doing the work "as if" it were a function or is a keyword really a function ?

1:34 amalloy: simard: the latter

1:34 &(instance? IFn :some-kw)

1:34 sexpbot: java.lang.Exception: Unable to resolve symbol: IFn in this context

1:34 amalloy: &(instance? clojure.langIFn :some-kw)

1:34 sexpbot: java.lang.ClassNotFoundException: clojure.langIFn

1:34 amalloy: &(instance? clojure.lang.IFn :some-kw)

1:34 sexpbot: ⟹ true

1:35 amalloy: simard: evidence that the parser isn't doing magic: ##(let [k :keyword] (k {:k 10}))

1:35 sexpbot: ⟹ nil

1:35 amalloy: simard: evidence that the parser isn't doing magic: ##(let [k :keyword] (k {:keyword 10}))

1:35 sexpbot: ⟹ 10

1:36 hsaliak: proxy has no access to super, and it looks like deftype/defrecord only work on interfaces.

1:37 amalloy: hsaliak: what. you don't "override" a constructor. you provide your own constructor that calls the superclass constructor, and proxy lets you supply whatever args you want to super()

1:42 hsaliak: amalloy, what if i want to do further initialization code after calling the superclass's constructor? As you would in a normal java subclass constructor

1:44 amalloy: hsaliak: an init function of some kind seems right to me, but i dunno. i don't think this is the sort of java that clojure is very good at writing

1:47 hsaliak: amalloy, I feel the same way too, maybe i need to have another look at how to structure this in a way that's better suited to clojure

2:11 khaliG: is there a way to initialise a struct using a map?

2:22 amalloy: khaliG: just use an actual map. what benefits are structs giving you, if you're initializing them from a map and don't know which keys you'll be supplying?

2:37 khaliG: amalloy, that thought occured to me too..

2:41 amalloy, i do know what keys i a going to supplying though, it's just i'm reading a slurped form which throws away the struct info so i've to recreate it from just a map

2:43 amalloy: khaliG: ##(doc struct-map)

2:43 sexpbot: ⟹ "([s & inits]); Returns a new structmap instance with the keys of the structure-basis. keyvals may contain all, some or none of the basis keys - where values are not supplied they will default to nil. keyvals can also contain keys not in the basis."

2:43 amalloy: khaliG: ##(doc struct-map)

2:43 sexpbot: ⟹ "([s & inits]); Returns a new structmap instance with the keys of the structure-basis. keyvals may contain all, some or none of the basis keys - where values are not supplied they will default to nil. keyvals can also contain keys not in the basis."

2:47 khaliG: almost but not quite

2:47 because i have a map

2:49 ie (struct-map my-struct-type {:boom 4 :bar 4}) not (struct-map my-struct-type :boom 4 :bar 4)

2:50 amalloy: khaliG: apply

2:50 khaliG: tried using apply

2:51 amalloy: ah, but it thinks it's a seq of pairs, not a plain list

2:51 khaliG: yep

2:51 amalloy: (apply struct-map my-struct (apply concat {...}))?

2:52 khaliG: lets see

2:52 that works!

2:55 amalloy: indeed, though yuck :)

2:56 Scriptor: hey everyone, so I've been reading through http://blog.higher-order.net/2010/08/16/assoc-and-clojures-persistenthashmap-part-ii/

2:57 from the explanation, it makes it sound like a new root node+path is created with each assoc

2:57 eg: when assoc'ing a new key-value pairing, it finds the appropriate node, copies it and adds the pairing to its array

2:58 and then it copies each parent on the way back up

2:58 just wanted to make sure I got the idea right

3:00 khaliG: amalloy, so after all that, it prints the exact same thing in the repl. I wonder if it is the same thing really :/

3:01 amalloy: khaliG: structs print as maps, iirc. but if you check (class ...) it should be structmap rather than hashmap

3:01 khaliG: ah i see

3:01 amalloy: Scriptor: yeah that sounds accurate to me

3:02 ignoring what happens if the appropriate node is full

3:02 Scriptor: right

3:03 now to implement that

3:06 amalloy: Scriptor: writing a version for another language, or for educational purposes?

3:06 Scriptor: amalloy: another language

3:06 amalloy: cool. which?

3:06 Scriptor: PHP...:p

3:09 my main concern is that while Java probably optimizes all the copying pretty well (it's just references after all)

3:09 I'm not as confident about the zend engine

3:09 amalloy: Scriptor: you can try fairly hard to make php use references

3:10 Scriptor: right, &$var, but I've seen a few things about PHP's references being slow for some reason

3:10 haven't looked into it much

3:11 amalloy: hm

3:11 i've only read a bit of the php source, but if you want me to look into something in particular let me know

3:12 Scriptor: amalloy: great, I'll hopefully be getting into the gritty details soon

3:14 quick question, do java arrays have to be explicitly converted to a seq if you wanted to use them as such?

3:15 amalloy: &(map inc (int-array [1]))

3:15 sexpbot: ⟹ (2)

3:15 amalloy: looks like no

3:16 Scriptor: &(first (int-array [1]))

3:16 sexpbot: ⟹ 1

3:17 Scriptor: &(rest (int-array [1 2 3]))

3:17 sexpbot: ⟹ (2 3)

3:17 amalloy: Scriptor: just in case i've trained sexpbot to lie when i ask him a question? :)

3:18 Scriptor: amalloy: well, map could've been calling (seq) internally :)

3:18 amalloy: Scriptor: it's calling first and rest internally, i expect

3:19 Scriptor: right, and I just checked the source for first

3:20 what exactly is clojure.lang.RT?

3:20 amalloy: Scriptor: the runtime supporting language-level stuff

3:20 Scriptor: ah, runtime

3:22 ah, here we go: ISeq seq = seq(x);

3:22 from the source for first(), looks like it *does* call seq

3:23 amalloy: indeed

3:24 most of the basic sequence functions act on seqs

3:24 raek: all the fns that operate on sequences (has a 'coll' param) usually call seq on the argument

3:26 Scriptor: yep, but unless it's always lazy, I'd imagine looping through a sequence by constantly calling first/rest would have a large overhead, right?

3:26 Null-A: When I call read-line in the repl, it always returns nil

3:26 i can't figure out a way to get console input more generally

3:26 Scriptor: since it'd be converted to some seq for each call

3:27 amalloy: Scriptor: no

3:27 (seq some-seq) returns some-seq

3:27 Scriptor: oh, right

3:27 the meat of the conversion is only done once

3:27 amalloy: &(let [x (seq (range 10))] (identical? x (seq x)))

3:27 sexpbot: ⟹ true

3:30 raek: yes. an element of a lazy-seq is only forced once.

3:31 amalloy: raek: i don't think laziness/forcing are related to Scriptor's issue. if a lazy-seq created a new data structure every time you forced it, even if it didn't recompute the element, that would be inefficient

3:32 raek: a question of allocation, I see

3:33 Scriptor: raek: just had a mental slip-up, (rest (rest (int-array [1 2 3]))) would only convert the array to a sequence for the first call of rest

3:33 rata_: Null-A: in which repl are you calling read-line?

3:34 Null-A: rata_: actually, it works in the repl, but not in swank server repl

3:34 rata_: slime repl*

3:34 raek: Scriptor: yes

3:34 Null-A: rata_: also lein run, have read-line returning nil always

3:34 rata_: lein repl works

3:35 rata_: Null-A: yes... it doesn't work for me either, but swank repl is weird in some senses

3:35 Null-A: i think lein run is just broken

3:35 i've had so many problem with it

3:35 rata_: don't use it then ;)

3:35 amalloy: slime does funny business with the repl. you'll never get console input through it

3:36 rata_: I've had issues with threads in swank repl too

3:36 raek: the "conversion" wouldn't be a heavy operation though, since it will just create one of these: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/ArraySeq.java#L55

3:37 (without optimizations for primitives, an element of an array seq could be described as a (array, index) pair)

3:41 amalloy: the code duplication in those primitive optimizations make me sick. let me know when java supports treating primitives like objects :P

3:45 raek: homoiconism ftw!

3:46 khaliG: yea i've noticed if i print something in my clojure code it wont show up in the repl, something to do with threading?

3:46 Scriptor: primitives as objects would be a start :)

3:57 rata_: amalloy_: .NET has primitives as objects, doesn't it?

3:57 brehaut: it has value types that look a bit object like

3:57 and it has autoboxing

3:58 rata_: khaliG: it should show up, unless you're printing from a thread

3:58 khaliG: guess so

3:58 its from the swing thread

3:58 it's annoying because i cant print debugging info out to the repl

3:58 brehaut: rata_: http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx

3:59 rata_: khaliG: yes, it is... that cost me two hours some days ago searching for a bug in a swing app

3:59 brehaut: rata_: eric lippert's blog is a gold mine of 'how C#/.net actually does thing'

4:00 rata_: *costed

4:00 thanks brehaut, I'll read it

4:00 TobiasRaeder: morning

4:01 ejackson: Hello

4:07 raek: khaliG: (alter-var-root #'*out* (constantly *out*))

4:08 do that in your slime repl, and that repl will be the default *out* for clojure

4:08 khaliG: raek, oh wow, thats sweet!

4:08 any downside to doing this?

4:08 rata_: yes, I didn't know that

4:08 raek: by default, *out* is bound to the slime repl only for the repl thread (you can actually have multiple repls)

4:08 khaliG: i see

4:09 raek: you lose the reference to the original *out*

4:09 i.e. the one connected to the swank terminal

4:09 but that's no big deal, I guess.

4:10 khaliG: nod

4:10 sounds like it's harmless

4:11 raek: you can also use bound-fn and bound-fn* to let a function remember the *out* value. (if it is invoked in another thread, it will use its remembered values)

4:13 rata_: raek: and do you know how to let exceptions thrown in thread to appear in the swank?

4:13 *in other threads

4:14 khaliG: raek, good question

4:14 i get a lot of these silent exceptions thrown that i never find otu about, except to know something is wrong

4:14 rata_, even

4:15 raek: rata_: put a (try your-code (catch Throwable e handle-in-some-way)) in the code

4:15 khaliG: at the top level?

4:16 rata_: raek: that's in the case I'd know that an exception is being thrown, but some times you don't know

4:16 it just doesn't work

4:16 raek: at the top level of the code you run in another thread

4:17 (def handle-in-some-way (bound-fn [e] (.printStackTrace e *out*)))

4:17 or just skip the bound-fn part if you set the root value

4:18 to be certain, you should have something like this in all your calls that run in other threads

4:19 rata_: well, it's not a magic solution like the other one

4:20 raek: futures have a default solution built in

4:20 when you dereference them, they will throw the exception wrapped as the cause of a ExecutionException

4:23 ,(let [f (future (throw (Exception. foo)))] f)

4:23 clojurebot: java.lang.Exception: Unable to resolve symbol: foo in this context

4:23 raek: ,(let [f (future (throw (Exception. "foo")))] f)

4:23 clojurebot: #<core$future_call$reify__5500@1c8b313: :pending>

4:23 raek: ,(let [f (future (throw (Exception. "foo")))] @f)

4:23 clojurebot: java.util.concurrent.ExecutionException: java.lang.Exception: foo

4:24 rata_: I need to sleep... see you tomorrow guys

4:24 raek: futures are a great way of checking "you know that thing I wanted you to do in another thread, how did it go?"

4:24 rata_: good night

4:24 rata_: yes, futures are great... I just forgot to deref them last time

4:24 good night

4:25 (I didn't deref them because I didn't care about the return value, just the side-effects)

4:26 khaliG: i've been meaning to check out out futures but haven't had a use case for them yet

4:29 raek: khaliG: <shamelessPlug> http://blog.raek.se/2011/01/24/executors-in-clojure/ </shamelessPlug>

5:11 mattdw: anyone seen a problem where 'lein compile' hangs/never exits?

5:12 (it also happens during jar and uberjar, but I suspect that's still the compile step)

5:18 raek: mattdw: watch out for code with side-effect at the top level of your namespaces (e.g. code that starts a web server)

5:19 ideally, only code that results in defs should be at the top level

5:20 mattdw: ah I'll bet that's it

5:20 it's a def, but it's a web server ;)

5:21 perfect, thanks raek

5:21 raek: (you can also put that code in a function called -main and use genclass or lein run)

5:22 mattdw: yeah, I had -main, but I was deffing the server at the top-level

5:25 khaliG: raek, cool article, i just finished going through it :)

5:28 TobiasRaeder: are there any new openid libraries for clojure i just missed? (just found jopenid and openid4java which both seem ... not that nice)

6:17 ejackson: Was any way discovered of attaching messages to :pre and :post assertion errors ?

6:25 khaliG: hm i'd like to produce a vector using the FOR form..

6:28 AWizzArd: khaliG: for is LIST comprehension.

6:29 You could go with reduce

6:29 khaliG: ok, i'll read on reduce, cheers

6:29 AWizzArd: ,(reduce #(conj %1 (+ %2 1000)) (vector-of :int) (range 20))

6:29 clojurebot: [1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 ...]

6:30 AWizzArd: Instead of (vector-of :int) you can of course also just say: []

6:33 Chousuke: I think you should prefer into to reduce

6:33 ,(into [] (for ...))

6:33 clojurebot: java.lang.RuntimeException: java.lang.IllegalArgumentException: Wrong number of args (3) passed to: core$for

6:33 Chousuke: oops, didn't mean to put the , there :)

6:33 bsteuber: (why not just (vec (for ...))

6:33 Chousuke: that works too

6:33 I tend to forget vec exists :P

6:37 khaliG: :)

6:39 AWizzArd: The nice thing about reduce is that it will not consume too much memory.

6:39 Chousuke: it'll consume more than into :/

6:39 since it creates the intermediate vectors

6:39 AWizzArd: You think?

6:39 Ah ok

6:39 Chousuke: yeah, it's slower than into, because into uses a transient

6:40 vec does too I guess.

6:40 AWizzArd: Hmm, in principle vec could/should be the most efficient way, yes.

9:04 TimMc: technomancy: Any way to turn off warn-on-reflection for lein repl? Whenever I start it, I get a bunch of reflection warnings for dev or repl code.

9:05 (Alternatively, a way to turn it on just for lein compile/run.)

9:28 AWizzArd: TimMc: the best solution would be to type hint those modules and really eliminate the reflection warnings that way.

9:29 TimMc: AWizzArd: I type hint my own code. The problem is some dev-dependencies or some such.

9:34 khaliG: is there a nice clojure way of doing this: if (method. getName) returns nil use "Text" otherwise whatever the method returns

9:34 AWizzArd: khaliG: maybe if-let

9:35 ,[(if-let [x nil] :a :b), (if-let [x 5] :a :b)]

9:35 clojurebot: [:b :a]

9:35 raek: khaliG: there's a really neat clojure function called 'fnil'

9:36 khaliG: that sounds like what i'm after! :)

9:36 raek: it returns a new function like the one you pass it, but lets you "patch" what happens when you *pass* the function nils

9:36 so maybe it was not what you were looking for anyway

9:37 * raek slaps his forhead

9:37 khaliG: ooh

9:37 yea doesn't sound like it

9:37 raek: khaliG: (or code-that-mgith-return-nil replacement-value)

9:38 khaliG: i like it, thank you

9:39 TimMc: khaliG: What if the function returns false, do you still want the return value?

9:40 khaliG: TimMc, well it will be nil or a text, im sure of that

9:40 TimMc: OK, then you'll be fine.

9:41 khaliG: somethign like this (or (.getName table-model) "Exercise"))

9:44 one thing i really miss from Netbeans/enclojure in slime is who-calls a function

9:45 raek: khaliG: from swank-clojure readme: C-c C-w c: List all callers of a given function

9:46 khaliG: does that call slime-who-calls? that doesnt seem to work for me

9:46 "error in process filter: Wrong type argument: char-or-string-p, nil"

9:46 anyway it's not the end of the world

9:50 raek: could perhaps be new to the 1.3.0-SNAPSHOT swank-clojure version

9:50 or it requires some specific slime version

10:46 TobiasRaeder: anyone knows how to create a route in compojure which accesses a value from the path i.e. /somepath/:id and the complete request object?

10:54 raek: TobiasRaeder: see Destructuring the request section at https://github.com/weavejester/compojure/wiki/Routes-In-Detail

10:55 looks like the path variables gets added to :params

10:56 TobiasRaeder: @raek that would make sense, i will check it out. thanks

11:07 @raek works like a charm, tyvm

11:40 mattmitchell: anyone know of any existing code to do a batch insert with the clojure.contrib.sql lib?

11:50 ejackson: mattmitchell: no - I was looking for exactly that a while back.

11:51 mattmitchell: ejackson: yeah i'm thinking about writing to a file and executing LOAD DATA INFILE instead

11:51 ejackson: mattmitchell: yes, that is actually often the fastest way :) !

11:52 is ugly as sin though

11:52 mattmitchell: ejackson: yes :)

12:06 jcromartie: hi all

12:07 I'm revisiting this idea of a hash with history... where assocs and dissocs are done with a timestamp, and I'm wondering: why use a hash at all?

12:07 by hash I mean hash-map

12:07 Why not just a seq of times and values

12:08 technomancy: TimMc: you could set it to false in :repl-init-script maybe

12:09 AWizzArd: jcromartie: {ts1 va1, ts2 val2, ...} vs [ts1, val1, ts2, val2, ...]?

12:10 jcromartie: AWizzArd: no, not quite... the idea is a document (hash-map) stored as a sequence of values

12:10 dnolen: jcromartie: why not a vector of hash-maps states and use a zipper to navigate the different states?

12:10 jcromartie: zipper, eh

12:11 I might be over engineering this anyway, since the system will likely just use a RDBMS to store these documents anyway

12:11 AWizzArd: jcromartie: I don't really understand. You said: "Why not just a seq of times and values" which sounded like: I want no map but a seq. But now you want a map again?

12:11 jcromartie: sorry let me clarify

12:12 I started out wanting a hash-map to represent a "business object" type of "document" that had a history of values

12:12 like, an invoice

12:13 AWizzArd: Sounds okay so far.

12:14 jcromartie: so each version of the document is associated with a timestamp, and I made an interface that acts like assoc but also stores a timestamp, and allows you to grab the value at points in time

12:14 so this is designed for assoc-style modification

12:15 AWizzArd: If you use a sorted-map then you can even say: "Computer, give me all events that occured between t1 and t2".

12:15 subseq

12:15 jcromartie: yeah

12:15 but what I'm thinking is some kind of general purpose ref-like object that lets me do that with anything, like a number or a string

12:15 so basically a ref but with history

12:16 and it would be great if I could use @ or deref and some simple way to modify it

12:16 but I guess the question is: is this over thinking it

12:16 it seems useful

12:17 chouser: jcromartie: I think it's a value, not an identity

12:17 and as such could be stored in whichever reference object makes sense (atom, ref, etc.)

12:18 jcromartie: so then maybe it's better to just build on a ref

12:21 chouser: Well, idependant of ref. Something more like assoc than like swap!

12:22 dnolen: jcromartie: to me a sorted-set with it's values sorted on timestamp seems ideal, (conj doc-timeline doc)

12:22 jcromartie: yeah

12:22 but it all goes down the tubes when the database gets involved anyway

12:22 so... :(

12:22 dnolen: jcromartie: I don't see why.

12:23 jcromartie: at least, that's my experience with interfacing with a DB

12:24 dnolen: jcromartie: what do you see as the issue here?

12:24 jcromartie: let's say I have a million documents, with ten versions each

12:24 I don't want to manage that across Clojure and the DB

12:25 but maybe it could load lazily on dereferencing some version that only represents the "current" value

12:25 dnolen: jcromartie: still unclear, what is there to manage that's any different from any other DB + programming language ?

12:25 jcromartie: well, because it's not just the current state of an object

12:26 unless the documents (just an ID) are in one table and the changes over time (including the implicit latest) are in another table

12:26 pdlogan: jcromartie: here's some food for thought re: values with history... both PDFs unfortunately...

12:26 jcromartie: that might make more sense

12:26 pdlogan: hillside.net/plop/plop98/final_submissions/P63.pdf

12:26 jcromartie: :P

12:26 chouser: jcromartie: https://gist.github.com/826197

12:27 pdlogan: www.manfred-lange.com/publications/TimeTravel.pdf

12:27 chouser: just as a thought

12:27 jcromartie: Very nice, chouser

12:27 chouser: please excuse the underscore

12:28 jcromartie: In the end, I want to eliminate the accidental state

12:28 we handle invoices, and currently have lots of highly denormalized state

12:28 there are lots of "states" within the state, like we talk about "what state is the bill in"

12:29 and that is always, invariably, a real mess

12:30 and even then, we don't store ENOUGH state!

12:30 so the history is what really matters

12:36 thanks for the papers, pdlogan

12:37 oh look, Smalltalk :)

12:37 <3

12:37 pdlogan: (yep - some good ideas still hidden in the Smalltalk world)

12:38 jcromartie: I really like Pharo and Seaside. I wish there was something as nice as Seaside for building web apps in Clojure... I'm toying with stateful components in compojure

12:38 but it's still nothing like the control flow that Seaside gives you

12:39 but even Avi Bryant, who wrote Seaside, admits that the future is in fully client-side UI with server-side controllers and storage

12:40 pdlogan: jcromartie: yeah, and so we wish there were something as good at control flow... for javascript!

12:41 jcromartie: enter Clamato: http://clamato.net/

12:41 by Avi :)

12:41 pdlogan: btw re: seaside, there are similar systems for CL and Scheme that could apply to clojure, e.g. http://double.co.nz/scheme/modal-web-server.html

12:41 jcromartie: but still very beta

12:41 I have a hard time getting my head around making the server wait across HTTP requests

12:41 because it's just so updside-down

12:42 not just the server waiting, but one block of code waiting for the next HTTP request

12:43 I bet a macro for web app control flow would go a long way

12:43 pdlogan: "waiting across requests" amounts to hashing a closures and the hash keys round-trips to the browser associated with various URLs.

12:43 (and I apparently need coffee)

12:44 re: macros, yes... see http://www.paulgraham.com/vwfaq.html

12:45 jcromartie: yay

12:45 macros FTW

13:10 TobiasRaeder: anyone knows a java/clojure http client that doesn't use a java.net.URI? i need to make a get request to a url containing |

13:12 jcromartie: have you tried encoding the pipe as %7C?

13:12 TobiasRaeder: yeah then facebook complains the code is supposedly wrong

13:16 jcromartie: where is the |

13:16 in a parameter value? anchor part?

13:18 TobiasRaeder: parameter value

13:24 jcromartie: and what does your final encoded URL look like?

13:35 khaliG: anyone familiar with clj-time? i'm wondering if there is a way to find the number of days in a month from clj-time or do you need to go into jodatime for that

13:44 ejackson: khaliG: don't see it directly. But you can construct and interval over the month easily using the fact that interval is open on the right. Then just use in-secs and divide by (* 60 60 24) ?

13:45 khaliG: sounds like a good idea, was just doing that atm

13:45 ejackson: :)

14:07 amalloy: ejackson: a time library that makes you (/ x 60 60 24) yourself seems kinda misguided

14:08 ejackson: you're right, i'm sure there's a better way to do that

14:08 i just didn't happen to know off hand

14:08 amalloy: AWizzArd: oh neat, i didn't know about vector-of

14:09 ejackson: amalloy: it would be trivial to do the same thing as I suggested to get the magic number

14:10 (let [magic-number (in-secs (interval today tomorrow)] ...)

14:11 amalloy: hah

14:12 kjeldahl: I think I figured out why my ring wrap-reload with enlive deftemplate wasn't reloading when I changed the underlying template (html) file.

14:12 Avoid gen-class. Found a clue here: http://stackoverflow.com/questions/3902545/force-clojure-reload

14:13 amalloy: ejackson: and i'm not really in a good position to criticize: i'm responsible for the last code snippet of the uuid section of http://wiki.apache.org/cassandra/FAQ#working_with_timeuuid_in_java

14:14 ejackson: oooh magic number kabuki fest

14:14 :)

14:14 amalloy: i like that it ends with COOOOOOL

14:14 ejackson: lol

14:15 i like: 0x01b21dd213814000L

14:15 amalloy: yeah, that's the disgusting part

14:15 but it's 100% correct, so who am i to argue

14:16 i'll try to find an excuse to use graham's number in a clojure program

14:16 ejackson: too right

14:26 albertid: anyone from clj-sandbox arround?

14:35 amalloy: albertid: no, but i've written ~1/2 of clojail, which is another sandboxing lib

14:39 albertid: ah, didn't know that one, looks nice too

14:41 amalloy: albertid: so feel free to switch, or if you have general sandboxing questions i may be able to help

14:41 i think Licenser is responsible for clj-sandbox, but i'm not sure

14:42 scode_: I have a macro that generates multiple top-level forms (it's a defmy-type-of-test which autogenerates deftest:s). What is the idiomatic way to do so? I did `(let [] ,@(...)) but the "useless" let feels ugly.

14:42 dnolen: scode_: you have do

14:43 (do ...)

14:43 scode_: Ah. That feels cleaner.

14:43 Thanks :)

14:46 amalloy: scode_: it's not just cleaner, it's more correct. iirc (do a b c) causes each arg to be compiled after the previous is run, while (let [] a b c) compiles them all then runs them all

14:47 (i believe this is only true at the actual top level, so if you were doing this in a function instead of a macro it probably wouldn't matter)

14:47 scode_: I was about to ask about that since normally all is compiled first, but right - the top-level is special.

14:47 Subtle difference there.

14:48 amalloy: yes, it can matter if a is a macro that b depends on

14:48 or probably for other reasons as well but i don't know what they are :P

14:48 scode_: :)

15:13 apexi200sx: msg NickServ identify gasher

16:09 arkh: to do a simple HTTP GET, one can do the following: (slurp (URL. "http://www.google.com")). Is there something equivalent/similar for POST?

16:10 here's the simplest thing I have so far: (slurp (.getInputStream (doto (.openConnection (URL. "http://www.google.com")) (.setRequestMethod "POST"))))

16:12 jcromartie: arkh: it doesn't really matter how simple it is if you can put it in a function, is it?

16:12 err, does it

16:14 arkh: You're right - I think I just wanted to make sure I wasn't missing something in the libraries. It would be like using (with-open ...) if slurp could do the job just fine.

16:15 or, a more harsh example would be driving file io from java when with-open is available.

16:15 brehaut: arkh your best choice for all http is the clj-http library

16:17 arkh: hmm ... it's more than what I need but maybe I'll use that

16:17 rata_: hi

16:19 brehaut: morning rata_

16:20 rata_: hello brehaut

16:22 ohpauleez: dnolen: Nice quick post, and thanks for linking to that paper

16:28 TimMc: technomancy: :repl-init-script doesn't help -- the reflection warnings come from Lein or something.

16:31 dnolen: ohpauleez: np, a good read. Clojure agents, which always have confused me, seem particularly well suited to this style of computation.

16:32 ohpauleez: awesome!

16:50 technomancy: TimMc: ok, go ahead and create an issue for that then

16:51 if you can provide a patch I will send you an official leiningen sticker, otherwise I'll try to get to it before 1.5.0

17:51 kencausey: Is the status of PersistentQueue about the same in 1.3 as in 1.2? i.e. use clojure.lang.PersistentQueue/EMPTY as the foundation?

18:13 TimMc: technomancy: Haha, cool.

18:13 scode_: What is the idiomatic way to do constructors with deftype? Do you just defined a function that initializes an instance?

18:15 rata_: scode_: I'd think so

18:15 scode_: Ok. So i'm not missing some way of directly hooking up a constructor with deftype itself?

18:22 dnolen: scode_: there was some talk about that, but rhickey had modularity concerns, so nothing was decided upon.

18:22 scode_: Ok. Thanks.

18:23 amalloy: scode_: i don't think so. and it's fairly painless to call the init function yourself: (doto (MyObj.) (.init args))

18:24 pdk: (doc doto)

18:24 clojurebot: "([x & forms]); Evaluates x then calls all of the methods and functions with the value of x supplied at the front of the given arguments. The forms are evaluated in order. Returns x. (doto (new java.util.HashMap) (.put \"a\" 1) (.put \"b\" 2))"

18:25 scode_: amalloy: Sure, just trying to be idiomatic. :)

18:45 AWizzArd: amalloy: yes, it is now one year old but seems to still be secret, though it is indeed useful (efficient and documentation of code).

18:55 TimMc: Aha, get-in has different behavior from assoc-in and update-in when a zero-length keys collection is passed in.

18:55 ,(get-in {:foo [4 {:bar 5}]} [])

18:55 clojurebot: {:foo [4 {:bar 5}]}

18:56 TimMc: ,(update-in {:foo [4 {:bar 5}]} [] identity)

18:56 clojurebot: {nil nil, :foo [4 {:bar 5}]}

19:00 amalloy: TimMc: i imagine get-in is implemented as (reduce get m ks), while update-in is implemented as (assoc m (first ks) (some-recursive-call))

19:01 $source get-in

19:01 sexpbot: get-in is http://is.gd/BqhsBt

19:01 TimMc: bingo

19:02 I understand the differences in their behavior -- it comes down to implementation -- but I'd like them to not have surprising behavior in the base case.

19:03 amalloy: hm. assoc-in could use a quick refactor, to (assoc m k (if ks ...))

19:05 TimMc: I'll just make some helper functions for my own project, but out of curiosity, how would that get changed in Clojure? That is, who decides?

19:07 Is Hickey the benevolent dictator, or is it a sort of committee?

19:13 amalloy: TimMc: mostly rich, but the core team has influence

19:44 simard: aren't integers supposed not to overflow ? (ie.: (* 1000000000 100000000000000000)

19:45 brehaut: it depends

19:46 i would expect a default big integer not to

19:46 simard: doesn't look like it's defaulting to big integer here

19:47 brehaut: what version?

19:47 simard: hum svn 1.3.0

19:47 git that is

19:47 brehaut: there you go then

19:47 simard: or is it

19:47 companion_cube: ,(* 1000000000 100000000000000000)

19:47 clojurebot: java.lang.ExceptionInInitializerError

19:47 brehaut: *clojure-version* will tell you

19:47 simard: so what do I need

19:47 companion_cube: ,(* 1000000000 100000000000000000L)

19:47 clojurebot: Invalid number: 100000000000000000L

19:47 simard: yeah it's 1.3.0

19:47 brehaut: simard: if you dont know what is in 1.3 you should be using 1.2

19:48 1.2 is stable

19:48 simard: I see..

19:48 brehaut: 1.3 has very significant changes to the numerics support

19:48 simard: why did I do that update anyway

19:48 brehaut: in particularit defaults to primative integers with error-on-overflowing operations

19:48 and bigints as an option

19:49 ,*clojure-version*

19:49 clojurebot: {:major 1, :minor 2, :incremental 0, :qualifier ""}

19:50 brehaut: ,(* 1000000000 100000000000000000)

19:50 clojurebot: java.lang.ExceptionInInitializerError

19:51 simard: ok fixed, thahnks

19:51 just a question thought, what's the rationale behind that change ? am I gonna have to "unlearn" stuff whenever 1.4.0 comes out ?

19:52 brehaut: simard: the TL;DR omiting heaps of vital context version: performance is a priority

19:53 simard: talking about performance, how does clojure compare to "other languages" ?

19:53 brehaut: it depends

19:53 simard: is it as slow as python ? :)

19:53 brehaut: no

19:53 simard: good

19:53 brehaut: it is possible to be as fast as java

19:54 in 1.2 this requires some fairly unidiomatic code

19:54 in 1.3 that is much less so

19:54 simard: I see, well I have to agree with performance being a priority then

19:55 it's fun to have a nice language to play with... but not at all cost

19:55 brehaut: and re:breaking changes i believe 1.3s primatives changes are the first real breaking change in the language

19:55 in 3ish years

19:57 * technomancy can recall three breaking changes, but the only one that happened after 1.0 was trivial to update your code for.

19:58 technomancy: ^ changing from meta to meaning #^

19:58 (which was a really good change)

19:59 brehaut: the lazy-seq change was pre 1.0?

19:59 * brehaut has forgotten when 1.0 and 1.1 came out

19:59 technomancy: yeah, and also the moving of package nesting levels (clojure.clj -> clojure/core.clj)

20:00 ancient history

20:00 pdk`: hm

20:00 can we expect existing code that doesn't worry about type hints or java interop to work in 1.3

20:00 just with all our formerly autoboxed numbers being direct primitives

20:01 brehaut: depends if they are going to overflow ;)

20:01 technomancy: there are also binding changes

20:07 jkdufair: i'm using clj-json to serialize clojure objects to json, but need to represent the metadata also, probably including the classname of objects. has anyone done anything like this?

20:09 TimMc: I don't suppose there's a function like map that takes 2 elements from the input list at a time?

20:10 brehaut: ,(map identity (partition 2 (range 10)))

20:10 clojurebot: ((0 1) (2 3) (4 5) (6 7) (8 9))

20:10 TimMc: Aha, partition...

20:10 Thanks, brehaut.

20:12 technomancy: clojurebot: partition

20:12 clojurebot: Excuse me?

20:12 technomancy: clojurebot: partition is probably not what you want; see partition-all.

20:12 clojurebot: In Ordnung

20:12 technomancy: TimMc: ^^

20:14 TimMc: technomancy: I think I'm fine. I do a check for even-length collection ahead of time, which is a requirement for the input.

20:14 technomancy: oh, ok. it's just a naming mistake that trips up a lot of people... too late to fix in Clojure unfortunately.

20:20 fdaoud: trying to load a namespace with a dynamic name using (use). it works if the ns exists. I want to return nil if it does not exist. right now I catch the FileNotFoundException. Is there a cleaner way?

20:21 I thought find-ns would work but it returns nil even if the name is valid.

20:35 pdk`: this is unique

20:36 i got a project that crashes immediately with a null pointer doing lein run

20:36 but runs fine with lein repl

20:36 main- works too

20:40 TimMc: pdk`: What happens if you do lein compile?

20:40 (I have no idea what the result would mean either way.)

20:41 pdk`: returns no errors

20:41 for some reason

20:41 the project name has a dash

20:41 but lein put an underscore in its place in src\project-name

20:42 that and i'm still having these fn issues with irclj

20:42 TimMc: I think that's standard.

20:42 pdk`: keep getting "no text to send" if i try to use send-message for an :on-join event handler in fnmap

21:02 TimMc: pdk`: Is the NullPointerException in your code or somewhere in lein?

21:03 pdk`: i'll try again

21:03 the message itself is less than helpful

21:03 it's at NO_SOURCE_FILE:1 which is just awesome

21:03 "at clojure.lang.Compiler.eval etc etc"

21:04 and i'm still pondering why tf i can't send messages to channels with irclj

21:04 it just goes NO TEXT TO SEND LOL if i use send-message

21:04 granted this is inside an :on-join method for the fnmap being passed to create-irc

21:13 criminy

21:13 even if i stick a sleep in there it still cant send the msg

21:17 tomoj: don't think anyone's likely to be able to help without code

21:47 TimMc: So, I've got this graphical application. Should I have one global (def *state* (ref ...)) that is nested maps, or a bunch of def'd refs instead?

21:48 A bunch of them need to see each other -- some are GUI components with event handlers that mutate state and each other.

21:52 The global structured object incurs more verbose code in order to access the parts.

21:54 simard: how do I get the definition of a keyword ? say.. :test

21:54 ie.. the function associated to it

21:54 brehaut: TimMc: it depends on how you need to access stuff. if you have one big ass map (which is fine), but need to change two parts at once from different places, you need to break it down.

21:54 simard: in what respect?

21:55 simard: well I was told (I believe) that the reason you could do (:test {... :test 4

21:55 was because :test was a function

21:55 brehaut: it is

21:55 simard: how do I get its body

21:55 brehaut: ,(ifn? :keyword)

21:55 clojurebot: true

21:55 brehaut: you dont

21:55 simard: hum

21:55 brehaut: a function is anything that implements the iFn interface

21:55 frinstance ##(ifn? {})

21:55 sexpbot: ⟹ true

21:56 brehaut: ,(ifn? 1)

21:56 clojurebot: false

21:56 brehaut: so clearly maps are functions but numbers arent

21:56 simard: ifn then..

21:57 brehaut: you cant 'get the function' for it, it _is_ the function

21:57 rata_: simard: a keyword just search for itself in the set or map you give to it and returns the associated value

21:57 brehaut: simard: you can however use get

21:57 TimMc: simard: Clojure expands the notion of "function" beyond just lambdas.

21:58 simard: so that ifn interface, must define some... functions to implement

21:58 TimMc: A map is a function of keys to their values. A keyword is a function of maps (and records and structs...) to the value at that keyword.

21:58 rata_: raek: ping?

21:59 brehaut: simard: for keyword its probably some java code

21:59 TimMc: $source Keyword

21:59 sexpbot: Source not found.

21:59 TimMc: Worth a try. :-P

22:00 ANyway, it is clojure.lang.Keyword.

22:00 simard: ok so it's java defined, good enough

22:00 TimMc: simard: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Keyword.java

22:00 brehaut: https://github.com/clojure/clojure/blob/1.2.x/src/jvm/clojure/lang/Keyword.java#L104-217

22:01 simard: hehe

22:01 brehaut: its more complicated than that though

22:01 keywords have a callsite cache

22:01 to improve performance when used on records

22:01 (frinstance)

22:02 if you want a lookup function then you have 'get'

22:02 ,(get {:a 1} :a)

22:02 clojurebot: 1

22:02 brehaut: it performs exactly like a keyword, so its useless there

22:03 ,[(get {:a 1} :b 2) (:b {:a 1} 2)]

22:03 clojurebot: [2 2]

22:03 brehaut: but if you have non-objectish maps you'll need it

22:03 simard: ,(:sdfg {:sdfg32 54} 6)

22:03 clojurebot: 6

22:09 TimMc: brehaut: I think I'll go for a mixed approach for now, leaving GUI components as defs (so they can see each other) and consolidating actual state into maps and records.

22:12 brehaut: oh right

22:12 sorry yeah, keep your non-data stuff out of your data

22:22 TimMc: ah, OK

22:22 That makes more sense now.

22:23 brehaut: TimMc, as long as you are aware that its making a singleton UI ?

22:26 simard: what should I read as an advanced "tutorial" for clojure ?

22:26 could be a program..

22:28 amalloy: simard: hard to say, if you aren't specific on what an "advanced tutorial" means. maybe you want a particular topic, or what? otherwise just grab a random project from github

22:31 simard: hum I'd like to see some heavy macro language...

22:31 by heavy I mean, using macros to create a language atop of clojure

22:31 as is typical of lisp

22:31 brehaut: simard: thats not idiomatic clojure

22:31 simard: damn

22:31 amalloy: brehaut is right

22:32 brehaut: 'DSLs' are 95% composable functions and clj data literals

22:32 occasionally sprinkled with macros for convinence at the end

22:32 simard: dsl ?

22:33 brehaut: domain specific language: ie a mini-language created ontop of a host language

22:33 but. see: https://github.com/cgrand/enlive https://github.com/cgrand/moustache and https://github.com/cgrand/regex for examples of them

22:34 regex is the simplest and there is at least some slides around explaining the process

22:35 slides in question: http://vrac.cgrand.net/DSL.pdf

22:35 simard: so when you say "not idiomatic"... you mean.. discouraged, by what/who ?

22:35 amalloy: simard: discouraged because they're not composable. you have to use them exactly as the designer planned

22:35 you can't map over them, etc

22:37 simard: "Do you spot a pattern?" hahaha

22:38 brehaut: the associated video http://blip.tv/file/4522250

22:39 simard: what IDE do you use

22:39 emacs ?

22:39 amalloy: yes

22:39 brehaut: yes

22:39 ive also used eclipse with counterclockwise and its good too, but way heavier and im not a java person

22:39 simard: that's of course funny

22:39 :)

22:40 brehaut: im not sure why?

22:40 simard: well because clojure runs on java..

22:40 so do you use CEDET, or basic clojure-mode ?

22:40 (it'S an inclusive or)

22:40 brehaut: i use the emacs-starter-kit

22:41 and i dont use slime/swank etc though i hear it makes life much easier

22:41 simard: at least for lisp, dunno about clojure anywya

22:47 amalloy: simard: i use swank/slime and clojure-mode with paredit

22:47 tomoj: hooray

22:48 amalloy: tomoj: ?

22:49 fujin: emacs isn't an ide

22:50 simard: I know it's an OS

22:50 brehaut: its not an OS either, its a sentient text editor

22:51 tomoj: do you say it's sentient because it seems to have a mind of its own? :)

22:51 brehaut: yup :)

22:52 i need to enlist the help of qualified emacs wranglers like technomancy whenever i try to do anything new

22:53 fujin: It's pretty good having technomancy around ;)

22:54 fdaoud: is there a cleaner way than (try (use (symbol "some.namespace")) (catch java.io.FileNotFoundException exc nil)) ?

22:57 amalloy: fdaoud: i think ninjudd's clojure-useful has something like this written already

22:58 or maybe it's in cake

23:00 fdaoud: thanks amalloy

23:01 he's using a try-catch so I guess that's the way to go

23:01 amalloy: cool, glad you found it

23:01 fdaoud: btw brehaut you were right, (f1 (f2 (f3 (f4 f5)))) is just comp

23:03 brehaut: cool

Logging service provided by n01se.net