#clojure log - Oct 15 2010

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

0:10 hiredman: clojurebot: scala is <reply>see: http://harrah.github.com/browse/samples/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala.html#65760

0:10 ping?

0:10 clojurebot: PONG!

0:15 _rata_: how can I have multiple mutually-referencing objects in one atom?

0:29 LauJensen: Good morning all

0:36 kmc: hi LauJensen :)

0:37 notsonerdysunny: Good morning LauJensen

0:37 does any of you have trouble with logging into clojuredocs.org?

0:38 if I try to login with my google-openid it very often hangs.. I would be lucky if I get in..

0:41 LauJensen: Never even heard of clojuredocs until now :)

0:42 notsonerdysunny: I think it would be a nice place to contribute while we learn to use the stuff ourselves

0:42 It has been around for a while now

0:43 we can add the things which we try out as examples for others to see and learn

0:43 very nice model I think

0:44 LauJensen: Just signed in without any problems

0:45 Interesting project

0:45 notsonerdysunny: :) thats nice ..

0:45 but I have trouble

0:45 did you use your google openid?

0:47 LauJensen: I dont think I got it from google, just openid.com

0:49 ohpauleez: ,(isa? #{1} #{})

0:49 clojurebot: false

0:49 ohpauleez: ,(isa? #{} clojure.lang.PersistentHashSet)

0:49 clojurebot: false

0:49 ohpauleez: According to the doc, this only works if they are =

0:49 notsonerdysunny: ,(supers (class #{}))

0:49 clojurebot: notsonerdysunny: Gabh mo leithscéal?

0:49 notsonerdysunny: ->(supers (class #{}))

0:49 sexpbot: ⟹ #{clojure.lang.IObj clojure.lang.IFn clojure.lang.Seqable java.util.Set clojure.lang.IPersistentCollection java.lang.Runnable clojure.lang.Counted java.lang.Object clojure.lang.IEditableCollection clojure.lang.APersistentSet clojure.lang.IMeta clojure.lang.AFn java.io.Serializable clojure.lang.IPers... http://gist.github.com/627632

0:52 ohpauleez: So how do you see if a child is the same type/subtype?

0:52 Do I just do = on type()? That seems too verbose

0:56 amalloy: morning all

1:02 LauJensen: morning amalloy

1:16 kmc: hi amalloy

1:16 ohpauleez: good morning amalloy

1:24 kmc: a friendly bunch here

1:24 more greetings than other channels :)

1:24 amalloy: i know! it's almost like i'm living the dream of my youth: have friends

1:25 kmc: haha

1:26 ubii: anyone going to clojure-conj?

1:32 amalloy: apparently it's going to be more like an identity than a conj...

1:39 ubii: just curious how many attendees they planned for

1:39 looks like they still have some tickets left

1:39 amalloy: i suspect a lot of the people who are going are in bed

1:40 since it's late at the conj site

1:40 ubii: yep, figured

1:40 will ask again in the morning

1:44 kmc: north carolina eh

1:45 $350 eh

1:45 err $250

1:45 amalloy: kmc: you're on the east coast. you could practically walk there

1:46 kmc: Walking directions to Durham, NC: VA-49 S. 697 mi. 9 days 4 hours

1:46 amalloy: and the conj starts...in about 10 or 11 days?

1:46 hiredman: 8

1:47 amalloy: kmc: better get walking

1:47 replaca: ubii: yeah. I'm going. why?

1:48 ubii: was just curious how big of a crowd they were expecting, as I am thinking of going

1:48 replaca: I think it's going to be about 200.

1:48 ubii: wow, bigger than what I thought

1:48 replaca: That should be a really nice size gorup

1:49 Lots of interaction between folks

1:49 I think it's going to be a lot of fun. (Assuming you're a geek like the rest of us ;))

1:51 ubii: 20+ years in IT, guess that makes me geek enough :)

1:51 just wish that I would have found out about the conference sooner, so I could have made arrangement to go

1:52 s/arrangement/arrangements

1:53 replaca: well, we'll miss you.

1:53 I know they did everything they could think of to make sure interested floks would know about it

1:54 *folks - wow I'm tired tonight :)

1:55 ubii: well, I have have been so busy with work the last 9 months or so that I haven't been able to do much with clojure lately, hence the reason I just found out about the conference

1:56 replaca: yeah, I've hd that sort of thing happen to me as well

1:56 luckily not this time

1:57 ubii: been stuck doing mostly ruby, html, css, and javascript, when I would prefer to have been working with clojure :(

1:57 replaca: still only a few clojure jobs out there, but there are beginning to be more and more

1:58 _ato: heheh, you can do much worse than having to work in Ruby :-)

1:58 replaca: ain't that the truth

1:58 ubii: just started to force myself to spend what little extra time I have to continue to learn clojure and hopefully start using it in the work that I do

2:00 true, I could be stuck doing .Net development

2:00 or COBOL, like what my wife does :)

2:00 Crowbar7: ohh christ COBAL\

2:01 ubii: hmm, I wonder which would be more painful, visual basic or COBOL?

2:01 Scriptor: I don't think vb is that bad at all nowadays

2:01 amalloy: perl-compatible basic cobol-script

2:02 ubii: what little vb experience I have was from the pre .Net days

2:03 have had to work with C# and ASP.NET a bit and really did not like it

2:03 Crowbar7: the .net is better the nthe PHP I have to use

2:04 wtf PHP calling classes starts with the same sign as a variable

2:04 Scriptor: calling classes?

2:04 Crowbar7: $class->function

2:04 Scriptor: so you mean method calls?

2:04 Crowbar7: yeah

2:04 sorrt

2:04 Scriptor: or class::function()

2:04 amalloy: Crowbar7: you mean $object->function? class::function()

2:04 Crowbar7: more or less yeah

2:05 Scriptor: well, that makes sense

2:05 amalloy: yeah

2:05 Scriptor: an object is a variable, and you're calling a method on that object

2:05 amalloy: not standing up for php's $ syntax here, but it's totally consistent

2:05 Scriptor: one of the few times it *is* consistent, mind you

2:06 Crowbar7: what is not consistant is it's function naming scheme for core functins

2:06 functions

2:06 ubii: have to say that I would take Perl over PHP

2:06 Crowbar7: ^^

2:06 Scriptor: I'd definitely take Perl 6

2:06 Crowbar7: I would take JAVA even over PHP

2:07 Scriptor: eh, I think I'd prefer dynamic languages for web dev

2:07 Crowbar7: I hate it so much, but maybe working with it 80% of the time does not help.

2:07 LauJensen: Did you guys try #clojure-casual ? :)

2:07 Crowbar7: :0

2:07 p

2:07 :p

2:08 I'm going to try writing an asterisk lib in clojure just for fun to be honest.

2:08 if it actually works I might put it in clojars

2:10 ubii: LauJensen: sorry, we will stop yacking about these other inferior languages :)

2:14 I wonder if there are any plans to record the presentations and make them available online, for folks who are not able to attend the conference

2:15 LauJensen: np

2:15 amalloy: ubii: i heard someone say yes, or slides at least, but that is a non-authoritative answer

2:15 LauJensen: ubii: It has been requested by several Europeans, but I dont know if the host can make it happen yet

2:19 ubii: it would be cool, if they could, as I am not sure that I will be able to make it to the conference

2:19 Bahman: Hi all!

2:19 amalloy: hey, this is a nice feature. i can attach :arglists metadata even to vars that aren't explicitly functions

2:20 LauJensen: Bahman: Hey

2:21 Bahman: LauJensen: Hey.

2:23 ubii: hmm, the conference is an 18 hour drive from where I live and if I drive 120mph, than that is only a mere 9 hours :)

2:25 actually, I would fly, but I am sure that with it only a week away, that the flights will be pricey

2:26 amalloy: hrm. i found some of my old code which is doing (apply concat (for ...)). can anyone think of a reason not to use mapcat there?

2:33 Derander: I'm coming from ruby. I see the analogues of most of the sequence manipulation stuff I'm used to. Map, reduce, some, all good stuff. I cannot for the life of me find "each" though

2:33 replaca: ubii: you might be right, but why not check anyway. You might be surprised

2:33 Derander: How can I call a function on each element of a list?

2:34 replaca: ubii: especially if you stay over sat. night

2:34 amalloy: Derander: that's the same as map, in a functional language

2:34 ubii: replaca: not too worried about the cost of the flight, the biggest concern is the lack of available rooms at the Hilton

2:34 looks like they are completely booked on the 21st and 22nd

2:34 amalloy: ie, if the function you want to call doesn't have side effects

2:34 Derander: amalloy: even if I don't care what the return values are?

2:35 amalloy: Derander: the idiomatic way then would be doseq

2:35 replaca: ubii: yeah, probably means you'd want to look around for a cheap car, unless there's another hotel right next door

2:35 Derander: amalloy: aaahaaaaaa.

2:35 amalloy: ,(doseq [x (range 3)] (print x))

2:35 clojurebot: 012

2:35 replaca: I don't know the area, but you might want to check that out

2:35 Derander: amalloy: thanks, I didn't look under "force evaluation of sequence" in the clojure api

2:35 that's exactly what I want

2:36 ubii: replaca: I will look into my options in the morning

2:36 amalloy: Derander: the other possible solutions are dotimes, doall, and dorun, depending on what data structure you already have

2:36 (anything with side effects either starts with do, or ends with !, as a general rule)

2:36 clojurebot: () invokes the form inside, but there is an implied str call. The semantics are different inside the interpolated string, necessarily so.

2:36 Derander: good to know

2:36 amalloy: clojurebot: wtf?

2:36 clojurebot: I don't understand.

2:37 Derander: I am writing a queueing doodad. It pulls a list of changed files and dispatches them to callbacks

2:37 and I was just trying to figure out a way to actually call the goddamn function

2:37 s

2:37 amalloy: hahaha

2:37 ,(doc dorun)

2:37 zkim: ola

2:37 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. dorun can be used to force any effects. Walks through the successive nexts of the seq, does not retain the head and returns nil."

2:38 amalloy: is probably better than doseq for your case

2:39 Derander: amalloy: I have a list of files that have changed that I want to pass off to another handling function

2:39 amalloy: ,(let [x (map println (range 4))] true)

2:39 clojurebot: true

2:39 LauJensen: Worth a read: http://stackoverflow.com/questions/3906276/whats-the-difference-between-cake-and-leiningen#3939930

2:39 amalloy: ,(let [x (map println (range 4))] (dorun x) true)

2:39 clojurebot: true

2:39 0 1 2 3

2:39 Derander: from my brief reading, isn't dorun more for force-generating a lazy sequence?

2:39 yeah, my list isn't lazy

2:39 amalloy: if your list isn't lazy, then what's the problem?

2:40 Derander: well, I'm not sure how to call a function on each element of a list in clojure

2:40 in ruby I'd say [1,2,3].each {|e| puts e}

2:40 amalloy: sure

2:40 in clojure it would usually be map, but map is lazy

2:40 Derander: oooooooooh

2:40 amalloy: or, you could use doseq to construct the map and consume it all at once

2:41 or, use map to make it, and dorun to force it

2:41 Derander: okay. I was missing that part

2:41 in ruby I'd only use map if I wanted to transmute a seq

2:41 LauJensen: amalloy: doseq to construct the map ?

2:41 amalloy: LauJensen: to uh...construct the seq

2:42 oh

2:42 LauJensen: with doseq which is intended for side effects?

2:43 amalloy: ,(doseq [x (range 4)] (print x))

2:43 ,(dorun (map print (range 4)))

2:43 clojurebot: 0123

2:43 0123

2:43 amalloy: are the two things i'm suggesting

2:43 Derander: all is well now

2:43 amalloy: yeah, but now LauJensen is telling me i'm wrong

2:43 Derander: superfically doseq does what I want it to without any extra code

2:44 amalloy: yeah, i think doseq is a drop-in replacement for each

2:44 LauJensen: amalloy: Im just saying, doseq is for side-effects, so if you actually want to generate a return, use 'for'. Otherwise you're back in imperative land

2:44 its the word 'generate' that doesnt fit

2:44 ,(doseq [x (range 5)] x)

2:44 amalloy: LauJensen: which is why i said generate *and consume*

2:44 clojurebot: nil

2:44 LauJensen: ,(for [x (range 5)] x)

2:44 clojurebot: (0 1 2 3 4)

2:44 kmc: you could use dorun with map, right?

2:44 LauJensen: kmc: sure

2:44 amalloy: kmc: yeah, i suggested that

2:44 kmc: ,(dorun (map print [1 2 3]))

2:45 Derander: (doseq [file (filter #(>= 0 (.compareTo last-check (Date. (last-modified %)))) (list-desktop-files))] (process file)) is the code that I'm running

2:45 clojurebot: 123

2:45 kmc: ah, i missed it

2:45 LauJensen: amalloy: nothing is generated, its a naive loop

2:45 kmc: ,(defn mapM_ [f & xs] (doseq (apply map f xs))) ;)

2:45 clojurebot: DENIED

2:45 amalloy: ,(doc pos?) ; Derander might want this instead of >= 0

2:45 clojurebot: "([x]); Returns true if num is greater than zero, else false"

2:46 Derander: amalloy: unless the doc lies, that doesn't include zero

2:46 yeah, I need it

2:46 amalloy: oh right

2:46 Derander: it'd be a sweet replacement otherwise

2:47 sweeet. now all I have to do is write my callbacks

2:48 amalloy: LauJensen: how is that semantically different from a lazy seq, which never realizes more than one element at a time?

2:48 Derander: the plumbing is done, now all i have to do is build a house?

2:49 Derander: exactly

2:49 the fun part

2:49 amalloy: true that

2:49 Derander: first clojure project: engage

2:51 amalloy: Derander: hosting it on github?

2:51 Derander: if I ever finish anything

2:51 right now it's all over 10 lines of code

2:51 all of

2:52 amalloy: heh, i shared a repo that was only 8 lines the other day

2:52 Derander: :P

2:53 amalloy: i like to get version control as soon as there's a single line, because i tend to mess stuff up and then forget how to fix it

2:53 LauJensen: amalloy: How is what different?

2:53 Chousuke: you should at least make a local git repo :P

2:53 amalloy: LauJensen: a simple loop/recur

2:53 Chousuke: it's easy to push to github later

2:54 LauJensen: amalloy: loop/recur vs doseq are similar in that you can have local changes, ie side-effects. Its not what I would call idiomatic to functional programming however (though can still be pure)

2:55 amalloy: LauJensen: oh for sure, avoid them if at all possible

2:56 LauJensen: amalloy: Yea, and rarely is it not possible. Most loop/recur cans be replaced by reduce, unless you need short-circuiting of some kind. doseq shouldnt be used for any kind of generation, only side-effects

2:56 Derander: okay, I'm sorry

2:57 amalloy: haha

2:57 Derander: if I have a list of conditions that I want to check against, how should I iterate through them idiomatically?

2:57 (filter #(and (not (= ".DS_Store" %)) (not (= ".localized" %))) (seq files))) is the current line

2:57 gargh. it's so mind bending

2:57 LauJensen: looks good

2:57 amalloy: do you want the first true one, or all of them or what?

2:58 Derander: I want it to do that, but I want to have a lot more files that I'm blacklisting

2:58 basically I want to be able to pull from a list, (".DS_Store" ".localized" "screw_this_file")

2:58 can I do something like (not (in bad-word-list file))?

2:58 amalloy: ,(not-any? #{'a 'q 7} [4 6 8 0])

2:58 clojurebot: true

2:58 amalloy: ,(not-any? #{'a 'q 7} [4 6 'q 0])

2:58 clojurebot: false

2:58 Derander: oh.

2:58 gah.

2:58 sorry to waste your time

2:59 amalloy: haha no

2:59 it's fun

2:59 LauJensen: Derander: you can put your criteria in another function (filter meets-requirements? seq)

2:59 amalloy: plz ask moarrrr

2:59 LauJensen: afk

2:59 amalloy: Derander: my not-any? is using a set #{1 5 6} as a function

2:59 Derander: amalloy: yeah

2:59 amalloy: when called as a function, sets check whether they contain the argument passed

3:00 k

3:01 Derander: okay, trying to write my own version

3:01 amalloy: all righty. don't hesitate to ask for as much or as little advice as you want

3:02 Derander: well, I've got another question

3:02 when should I use a set vs a list?

3:02 the docs don't state the performance characteristics

3:02 lists are just linked lists, aren't they?

3:02 amalloy: lists are just linked lists, yes

3:02 Derander: are sets faster for lookup?

3:02 amalloy: sets are arrays when they're small, and trees when they're big

3:03 Derander: oooh, they're sneaky.

3:03 basically I'm wondering if I shouldn't make my list of bad files a set

3:03 because then I get the nifty syntax which you used in your example above

3:03 amalloy: you should, 100%, because of the way sets act as predicates

3:03 Derander: alright then

3:04 seems to work

3:04 sweet.

3:04 amalloy: the other thing you should consider (though not for this usage) is vectors, which are often better at being lists than lists are

3:05 Derander: I have noticed an abundance of vectors in clojure code that I read

3:05 I never use them because I'm used to elisp

3:05 amalloy: you want a summary of the difference between vecs and lists?

3:05 tobiasraeder: Morning everybody :)

3:05 Derander: amalloy: if you write it I'll read it

3:05 amalloy: heh

3:07 lists have fast insert/delete at the front, O(n) random-access, and slow-but-not-awful insertion/deletion from the middle

3:07 Derander: okay

3:07 amalloy: vectors have fast insert/delete at the back, O(1) random access, and awful insert/delete from anywhere else

3:08 Derander: so basically linked list vs array

3:08 amalloy: not quite, because arrays don't have fast appends

3:08 Derander: oh, right.

3:08 amalloy: and clojure lists don't have fast appends, unlike linked lists

3:09 Derander: alright, thank you. that helps

3:09 amalloy: because the list is immutable, it can't just tack something onto the end of the list; it has to copy every object in the chain to give it a new next pointer

3:09 Derander: oooooooooooooh. I was wondering why.

3:09 amalloy: tricky, isn't it

3:10 Derander: I am very unused to immutable data structures

3:10 amalloy: so was i, three months ago :P

3:10 but having vectors&lists is nice. for something that in elisp/CL you would have to build in backwards order and then reverse at the end, in clojure you can just build with a vector instead of a list

3:11 Derander: makes sense

3:11 amalloy: rich's immutable datastructures are the masterworks that make clojure possible

3:12 kmc: you can fast-append to the beginning, but not the end, of a persistent singly-linked list

3:12 i'm not sure whether Clojure's lists have this property

3:12 amalloy, indeed, i was so excited when i first heard about hash tries

3:13 amalloy: kmc: they do have this property

3:13 Derander: thank you for the information. I need to go to sleep now or I'll be worthless for programming tomorrow

3:13 kmc: has anyone here read Okasaki's book _Purely Functional Data Structures_?

3:13 Derander: Adiós

3:13 amalloy: buenas noches

3:14 holy cow, the source for doseq is monstrous

3:15 and for is even worse

3:26 ,(let [times (atom 0)] (dorun (pmap (memoize #(do (swap! times inc) (Thread/sleep 2000) %)) (repeat 10 1))) @times)

3:26 clojurebot: java.lang.Exception: No such namespace: Thread

3:27 amalloy: ,(let [times (atom 0)] (dorun (pmap (memoize #(do (swap! times inc) (. java.lang.Thread sleep 2000) %)) (repeat 10 1))) @times)

3:27 clojurebot: 4

3:28 amalloy: does anyone know a way to make pmap/memoize smarter? it's wasting cpu resources computing the same function four times in an attempt to memoize it

3:30 Chousuke: I suppose you could add a lock or something, so it blocks if the cache is being updated

3:30 raek: ,(let [times (atom 0), f (memoize #(do (swap! times inc) (. java.lang.Thread sleep 2000) %)), _ (f 1)] (dorun (pmap f (repeat 10 1))) @times)

3:30 clojurebot: 1

3:31 Chousuke: btw, (. java.lang.Thread sleep 2000) is better written as (Thread/sleep 2000)

3:31 amalloy: Chousuke: see above. i tried that but clojurebot doesn't like it

3:32 Chousuke: ah, right.

3:33 amalloy: wasn't sure whether he was annoyed by the / or the lack of java.lang so i just switched both

3:33 ,Boolean/TRUE

3:33 clojurebot: true

3:33 amalloy: ,(Boolean/valueOf "true")

3:33 clojurebot: true

3:34 amalloy: man wth clojurebot? why not Thread/sleep?

3:34 Chousuke: It might just be doing some security checks.

3:34 and failing :p

3:34 amalloy: heh

3:34 raek: ,Thread

3:34 clojurebot: #<clojurebot$eval4127$fn__4128 hiredman.clojurebot$eval4127$fn__4128@7c31af>

3:34 amalloy: ,(java.lang.Thread.)

3:34 clojurebot: #<Thread Thread[Thread-1856,5,main]>

3:35 Chousuke: huh, why does Thread return a function

3:35 amalloy: ,(meta (var Thread))

3:35 clojurebot: {:ns #<Namespace sandbox>, :name Thread}

3:36 Chousuke: ,(Thread)

3:36 clojurebot: java.lang.Exception: DENIED

3:36 amalloy: heh

3:36 Chousuke: I suppose Clojurebot is using the interpreter.

3:36 raek: -> (Thread/sleep 1000)

3:36 sexpbot: java.lang.SecurityException: Code did not pass sandbox guidelines: ()

3:37 amalloy: ->(. Thread sleep 1000)

3:37 sexpbot: java.lang.SecurityException: Code did not pass sandbox guidelines: ()

3:38 amalloy: exciting. can we inject code to clojurebot by instantiating a Thread with some unsafe Runnable object?

3:38 raek: ,(def x 5)

3:38 clojurebot: DENIED

3:39 raek: ,(java.lang.Thread. (fn [] (def x 5)))

3:39 clojurebot: DENIED

3:40 raek: ,(-> x def)

3:40 clojurebot: DENIED

3:41 raek: ,((resolve (symbol "eval")) '(+ 1 2))

3:41 clojurebot: 3

3:41 amalloy: raek: slick

3:42 but i think it maps eval to a safer eval

3:43 raek: ,((resolve (symbol "eval")) (read-string "(def x 5)"))

3:43 clojurebot: #'sandbox/x

3:43 raek: ,((resolve (symbol "eval")) (read-string "(ns-unmap 'sandbox 'Thread)"))

3:43 clojurebot: nil

3:43 raek: ,(Thread/sleep 1000)

3:43 clojurebot: java.lang.Exception: No such namespace: Thread

3:43 amalloy: ,Thread

3:43 clojurebot: java.lang.Exception: Unable to resolve symbol: Thread in this context

3:44 amalloy: ,(. Thread sleep 1000)

3:44 clojurebot: java.lang.Exception: Unable to resolve symbol: Thread in this context

3:45 raek: ,((resolve (symbol "eval")) (read-string "(import 'java.lang.Thread)"))

3:45 clojurebot: java.lang.Thread

3:45 amalloy: ,(proxy [java.lang.Thread] [])

3:45 clojurebot: java.lang.IllegalStateException: Var null/null is unbound.

3:47 amalloy: ,(. java.lang.Thread sleep 100)

3:47 clojurebot: nil

3:49 amalloy: ,(.join (. java.lang.Thread (currentThread)) 100)

3:49 clojurebot: nil

3:49 amalloy: ,(.join (. java.lang.Thread (currentThread)) 30000)

3:49 clojurebot: Execution Timed Out

3:53 amalloy: ,(let [threads (make-array java.lang.Thread 20)] (. java.lang.Thread enumerate threads) (dorun (map print threads)))

3:53 clojurebot: #<Thread Thread[main,5,main]>#<Thread Thread[pool-1-thread-1,5,main]>#< Thread[Smack Packet Writer (0),5,main]>#< Thread[Smack Packet Reader (0),5,main]>#<Thread Thread[Smack Keep Alive (0),5,main]>#<Thread Thread[Smack Listener Processor (0),5,main]>#<OutputThread Thread[class org.jibble.pircbot.OutputThread-Thread,5,main]>#<Thread Thread[pool-2-thread-1,5,main]>#<Thread Thread[pool-1-thread-2,5,main]>#<TimerThread Thread

3:54 amalloy: aha. and we could call .destroy on all of those

3:57 ,(reify Runnable)

3:57 clojurebot: #<sandbox$eval11118$reify__11119 sandbox$eval11118$reify__11119@121bcf2>

4:01 amalloy: ,eval

4:01 clojurebot: #<core$eval clojure.core$eval@1415815>

4:02 amalloy: ,(.run (reify Runnable (run [this] (eval "(def q 1)"))))

4:02 clojurebot: DENIED

4:02 AWizzArd: http://xkcd.com/722/

4:03 amalloy: ,(.start (java.lang.Thread. (reify Runnable (run [this] (eval "(def q 1)")))))

4:03 clojurebot: DENIED

4:03 amalloy: meh

4:04 yangsx: hi, in my project.clj, I specifies ':resources "data"' to include the data subdirectory into the jar file, but all the files are put directly into jar without the path, can I specify the path in the resulting jar?

4:04 amalloy: yangsx: just put them in subdirectories under data

4:05 eg data/foo/bar/baz.jpg should be in the jar under foo/bar/baz.jpg

4:11 yangsx: amalloy: Maybe I'm doing it wrong. I read the data in a let form in code. That is, for my code it's data/foo, in the jar file it's foo. Maybe I should use a ref to read the data.

4:12 amalloy: i guess i don't understand. and sorry, gotta head out

4:18 svdberg: any users of vimclojure here?

4:19 kryft: No, but I will become one once I actually start writing clojure. :)

4:20 raek: yangsx: one way of doing it is to put the data/ dir in resources/

4:23 xkb: I'm trying to run the repl from inside vim, using the ns i'm editting

4:23 but that doesnt really work

4:23 classpath only shows clojure jars

4:23 raek: i'm not aware of any way of adding a prefix to the resulting path in thst case

5:39 tobiasraeder: is it possible to read the contents of a symbol into a vector inside a macro?

5:39 as in being able to (map #(dostuff) contents-of-the-symbol)

5:40 carkh: if i understood you question well, i'd say no

5:41 your*

5:41 do you have an example ?

5:43 tobiasraeder: yes, one second

5:43 AWizzArd: What are the "contents of a symbol"?

5:44 carkh: if your macro call looks something liek this : (my-macro some-symbol) then some-symbol is totally opaque at macroexapansion time

5:45 tobiasraeder: http://gist.github.com/627922

5:45 like that

5:45 contents of a symbol as in my case a vector that is bound to the symbol

5:45 carkh: well your macro can see the value of fields at macroexpansion time and use it

5:46 tobiasraeder: and how do i do that exactly?

5:46 carkh: just put ~fields in place of <content-of-fields>

5:47 xkb: what does ~fields do?

5:47 carkh: let me test that though =/

5:47 notsonerdysunny: is there a way to search backwards through the history from the slime repl like we would do at a readline enabled terminal using control-r

5:48 tobiasraeder: @carkh seems like thats exactly what i was looking for and just beeing blind. i'll try if i can get it to work, thank you

5:48 @notsonderdysuny no idea :/

5:49 @carkh ah dread, i forgott one thing let me change the gist quick

5:49 carkh: notsonerdysunny: try alt-p

5:49 tobiasraeder: @carkh i edited the gist if you dont mind checking it again

5:50 carkh: tobiasraeder: mhh you know i don't like that macro at all

5:51 it could be a function

5:51 i think that's not exactly what you want let me come back to you in a few

5:51 tobiasraeder: @carkh the actual case is a bit more complex and deals with alot of java interop class/interface generation

5:51 okay, thanks

6:02 carkh: tobiasraeder: how about something like this http://gist.github.com/627945

6:03 but i really don't like it

6:04 tobiasraeder: yeah that might work

6:04 carkh: does this really needs to be done at compilation time ?

6:04 tobiasraeder: ill try to rework the class-name "-fields" into a map and just store the fields their

6:05 yeah its part of some really huge java interop stuff

6:05 i gotta grab some food, thank you for the input. if you care i'll let you know what i come up with in the end

6:09 carkh: http://gist.github.com/627945

6:09 sur i'd love to

6:09 sure*

6:41 xkb: any tips to improve this code: http://github.com/svdberg/clojurelisa/blob/master/src/clojurelisa/core.clj?

6:41 I'm planning to use it in a presentation on Clojure

6:42 its a fork from a blog-post, and I'm trying to make it more idiomatic

6:44 edbond: ,(doc remove)

6:44 clojurebot: "([pred coll]); Returns a lazy sequence of the items in coll for which (pred item) returns false. pred must be free of side-effects."

6:44 edbond: ,(doc replace)

6:44 clojurebot: "([smap coll]); Given a map of replacement pairs and a vector/collection, returns a vector/seq with any elements = a key in smap replaced with the corresponding val in smap"

6:45 edbond: xkb: why not use remove and replace ^^ in remove-item and replace-item?

6:46 xkb: good tip

6:46 thanks

6:46 hmm.. only the predicate is a bit harder

6:47 as I need the nth item in a seq

6:52 edbond: then remove-item is ok

6:55 xkb: closing brackets don't need a new line

6:57 xkb: ok removed the two or three I found :)

7:39 jjido: What is the license of clojure.jar? Can I just package it in my project along with the readme.txt?

7:40 carkh: xkb: (def gen-pixels (grab-pixels gen-image)) inside a function, that's very bad style

7:40 cemerick: jjido: Clojure uses the EPL license.

7:41 Whether that's compatible with your project depends upon your project's license.

7:41 jjido: Eclipse, I read that. I use LGPL

7:41 carkh: xkb: same for defn inside functions

7:42 cemerick: I know the GPL and EPL don't play nice together. Not sure about LGPL.

7:47 hiredman: http://gist.github.com/628066

7:48 notsonerdysunny: what are symbol macros?

7:57 xkb: carkh: was afk for a while, and just read your remark

7:58 I thought I removed all defn within functions :?

7:58 oh within the multimethod?

7:58 carkh: yes

7:59 xkb: should I use letfn?

7:59 carkh: and there are many defs in other functions too

7:59 xkb: or just factor them out?

7:59 carkh: well that's for you to decide =P

7:59 xkb: :)

8:00 what's the tradeoff anyway, between a let and a def within a function scope?

8:00 I usually use let bindings

8:00 carkh: a def will modify the toplevel var

8:00 same for a defn

8:00 xkb: but the guy who originally wrote this uses def all the time

8:00 ah

8:00 carkh: that's like introducing global variables

8:00 xkb: so even within a function scope it introduces a top-level binding?

8:00 nasty

8:01 carkh: iirc it all started with recompiling stuff on the fly (which i dislike a lot too)

8:01 yes it does

8:01 you can use binding if you want to redef stuff with a dynamic extent

8:02 or let for lexical scope

8:02 xkb: and stuff like in source-image? the file-chooser is within the do scope

8:03 carkh: you need to use let for the fileshooser

8:04 xkb: I somehow got something in my head not to use let with doto

8:04 carkh: also that's nitpicking but ... your closing parenthesis should not be on a line by themselves

8:04 xkb: that's wrong app/. :)

8:04 carkh: hey, I like nitpicking :)

8:04 carkh: =)

8:05 i think we need to call hiredman to the rescue then !

8:47 solussd_: why isnt a record a function of its keys?

8:49 or field names i guess

8:55 tobiasraeder: it should be

8:55 iirc it implements ilookup so that should work

8:56 ,(defrecord myrecord [name])

8:56 clojurebot: DENIED

8:56 tobiasraeder: anyway if you (:name (myrecord. "testname")) it returns "testname"

8:57 or did i get wrong what you were looking for?

8:57 AWizzArd: He wanted ((HisRecord. "x") :name)

8:57 solussd_: i'm looking for ((myrecord. "testname") :name)

8:58 e.g. maps are functions of their keys

8:58 ,({:name "Joe"} :name)

8:58 clojurebot: "Joe"

8:58 tobiasraeder: yeah, got that wrong i guess

8:58 solussd_: so, while that works fine with a struct created w/ defstruct, it's a no-go w/ a record. :/

8:59 *defined w/ defstruct

9:01 guess I'm just wondering why

9:02 G0SUB: solussd_: because it doesn't make any semantic sense

9:02 solussd_: records are not functions of their keys. they are just a bunch of fields.

9:03 solussd_: if you need IFn like behavior, go ahead and implement that protocol for your custom type.

9:05 AWizzArd: solussd_: also records don't eval to themselves

9:05 When you eval a record, for example in a macro, it becomes a map.

9:05 solussd_: ok

9:06 dnolen: solussd_: maybe it's just me but the lack of IFn seems to me like an oversite

9:06 solussd_: http://gist.github.com/628148

9:06 solussd_: dnolen: that's what it feels like to me. Doesn't feel very idiomatic- feels more 'java-interopish'

9:06 stuartsierra: It is deliberate, but debatable.

9:10 _fogus_: You can say that again.

9:29 fhd: Hi. Can I somehow create anonymous types with instance variables?

9:29 stuartsierra: fhd: yes, with reify

9:29 fhd: I can create top level types with deftype, but I'd rather have them anonymous. proxy doesn't seem to support that

9:29 stuartsierra: Okay, I'll take a look!

9:30 stuartsierra: reify doesn't have instance variables per se, but it creates closures over locals

9:30 AWizzArd: And proxy not?

9:30 stuartsierra: I forget

9:30 AWizzArd: k

9:30 fhd: stuartsierra: I do explicitly need instance variables, sadly. An API requires that.

9:31 stuartsierra: oh then you need deftype

9:31 but it can't extend concrete classes

9:31 fhd: stuartsierra: Yeah, and it works. But the types aren't anonymous, this bothers me a bit.

9:31 stuartsierra: you could gensym the names :)

9:31 AWizzArd: Interesting it would be if I want to make a deftype for a new stream. As java.io.OutputStream is not an Interface I can't inherit from it in a deftype.

9:33 fhd: So anonymous classes with instance variables are not possible in Clojure?

9:33 jave: hello

9:33 stuartsierra: an anonymous class really just has a generated name, even in Java source

9:34 fhd: stuartsierra: Yeah, but I can create as many as I want at runtime, because it appends a number.

9:34 stuartsierra: Um, not at runtime I guess...

9:34 stuartsierra: exactly

9:34 Java doesn't create classes at runtime

9:35 fhd: stuartsierra: Then I should find a way to work around this. Thanks :) Such a weird API, I'll rewrite that in Clojure one day :)

9:35 stuartsierra: yeah, sounds weird. who uses public instance variables anyway?

9:36 fhd: stuartsierra: This project: http://github.com/spullara/mustache.java

9:36 stuartsierra: I think that's been ported to Clojure already

9:37 fhd: stuartsierra: You think? That would really make my day

9:37 It's so weird, I'm really one step from rewriting it myself...

9:37 Plus it's not on Maven Central...

9:38 stuartsierra: http://github.com/cgrand/moustache

9:38 jave: I'm doing some xml stuff with enlive but its a little bit awkward

9:38 fhd: stuartsierra: Isn't that something completely different? I stumbled across that too, but it doesn't seem to have anything to do with the Mustache template language.

9:38 jave: I have to do some workaroudns like adding xml headers and namespaces, is there some existing xml frontend to enlive?

9:38 stuartsierra: dunno, never used any facial hair libraries

9:38 fhd: stuartsierra: :)

9:39 stuartsierra: I like my frameworks clean-shaven.

9:39 fhd: stuartsierra: I haven't shaved in days, and I partly blame this library :)

9:39 stuartsierra: Maybe you're a budding Longbeard.

9:40 fhd: stuartsierra: Not yet :)

9:40 cemerick: stuartsierra: hah! :-D (re: clean-shaven)

9:40 Does anyone know of a free geocoding web service that doesn't have TOS restrictions like Google's?

9:41 jave: openstreetmap?

9:43 fhd: By the way, is unit testing common in Clojure? I know there are quite strong opinions on TDD, so I'm wondering.

9:43 cemerick: jave: it's certainly a map, but I dont' see an API?

9:43 jave: oh it has apis

9:43 cemerick: (not= unit-testing TDD)

9:44 stuartsierra: TDD isn't necessary in Clojure because Clojure code always works. :)

9:44 fhd: cemerick: Hence my question

9:44 stuartsierra: How about unit testing then? :)

9:45 jave: cemerick: I havent actualy coded anything m yself, but maybe you can have a look at the java client, its open source

9:45 cemerick: fhd: clojure.test is all about unit tests.

9:45 fhd: cemerick: Yup. And because clojure.test is pretty good, I thought unit testing might be real popular

9:45 stuartsierra: You can do TDD in Clojure with clojure.test or Lazytest or ClojureCheck or ...

9:45 cemerick: jave: its API seems to be defined by the HTML export from the map. Ick.

9:46 jave: well there are all sorts of apis to the data

9:46 cemerick: I'd like to match the awesomeness of e.g. (-> "http://maps.googleapis.com/maps/api/geocode/json?address=Holyoke,%20MA&sensor=false" slurp clojure.contrib.json/read-json)

9:46 jave: maybe have a look at the josm client

9:47 well, I dont think openstreetmap is so much about api awesomeness. its about making user contributed maps

9:47 and thats how I use it

9:48 cemerick: OK. I was looking for a geocoding API. Anyway, thanks.

9:48 fhd: I use clojure.test extensively in every one of my projects, and it seems to be very widely used in general.

9:49 fhd: cemerick: Hm, I see. Do you use it test-first or test-later style?

9:49 cemerick: I probably tend towards a 20/80 mix, respectively.

9:50 fhd: tangential Q: do you have much of a ruby background?

9:51 fhd: cemerick: I found that the REPL fulfils most of my TDD needs, so I didn't miss it so far

9:51 cemerick: No, I'm mostly Java/C++

9:52 cemerick: bummer; there goes my TDD stereotype ;-)

9:53 fhd: cemerick: Sorry :) I'm not a TDD expert though, just discovered it a while ago

9:53 cemerick: I've done a bit of Emacs Lisp before, and I couldn't imagine doing TDD with it at all, so I didn't really try it with Clojure

9:54 cemerick: Never got into it myself. Seems to me that testing simple stuff should be...simpler than TDD. And testing complicated stuff often ends up being...more complicated than TDD can support.

9:55 stuartsierra: That's what I'm trying to fix with Lazytest, don't think I've succeeded yet

9:55 _fogus_: I have a nice little segment in my talk about TDD :-)

9:55 fhd: cemerick: TDD is really nice for static languages, where you can't quickly test a function. Also leads to real nice object oriented design IMO

9:56 cemerick: But in Clojure, there's the REPL, so it's super easy to test specific functions. And it's functional, so creating object-oriented design is a bit weird

9:56 cemerick: _fogus_: looking forward to it

9:56 fhd: cemerick: I did get interested and ask some questions regarding how I could do specific things, and it seems to work technically. But I don't find it very nice

9:57 cemerick: stuartsierra: I'm afraid I've not looked at lazytest one bit. :-(

9:57 _fogus_: REPLs do not help much with regressions

9:57 stuartsierra: cemerick: no worries

9:57 It's still evolving somewhat

9:57 fhd: _fogus_: That's true, the confidence from TDD is definately mising

9:57 cemerick: I'm a little behind on the cutting-edge clojure hackery from the past few months.

9:57 fhd: _fogus_: Then again, I haven't refactored my Clojure code much, so I don't really care

9:58 _fogus_: fhd: I'm confused. :-(

9:58 fhd: _fogus_: About what? :)

9:59 _fogus_: fhd: TDD, unit testing, refactoring... I'm not sure what we're talking about anymore. :(

10:00 stuartsierra: _fogus_: buzzword compliance

10:00 fhd: _fogus_: Well, TDD is basically unit testing + refactoring IMO

10:00 _fogus_: Kent Beck says, in a nutshell, that it helps create good designs because it encourages refactoring by providing confidence through loads of test cases

10:01 * cemerick grumbles @ Kent Beck in that case :-(

10:01 _fogus_: fhd: Oh I see. I doo TDD, but without the Ds

10:02 fhd: _fogus_: :)

10:02 cemerick: "Good design" does not come from a random walk through test failure.

10:03 fhd: cemerick: Well, the nice thing about TDD is that you use test cases to write "how" you want to use an API, and then you start writing the API.

10:03 cemerick: The weird thing about TDD is that you basically start writing crap, hard coding everything, only slowly moving towards an actual solution

10:03 cemerick: And then refactoring the hell out of that until you like it.

10:03 cemerick: Yeah, I understand the idea, and I've done that to some extent, but that's not helping with design, it's simply codifying it ahead of its implementation.

10:04 fhd: cemerick: True. I actually do that most of the time, TDD or not.

10:04 _fogus_: I like to write apps with the API that I am going to design.

10:05 lpetit: It has almost seemed to me (after having done that myself too, not denying my past errances :-) ), that doing TDD is easier when you already know the "field", the application domain of your problem.

10:05 fhd: All in all, I'm not really convinced by TDD. It does have some good points, and the designs created by it are often actually quite nice. But I don't think it works well in all languages, as Beck claims

10:05 lpetit: And hard to do in unknown fields/territories.

10:05 fhd: lpetit: Definitely.

10:06 lpetit: With clojure, once you know your "field/domain" well, you have the tools to go very high in abstractions, removing all the bits of code redudancy you find. Including your test suite.

10:07 And once you know your application domain well, it makes less sense to "rewrite in TDD style" from scratch a new application.

10:07 fhd: lpetit: Yeah, I read somebody making this point: In functional programming, you write "what" you want, not "how" that should be achieved. Such code doesn't require tests.

10:08 stuartsierra: Great, so I've been wasting my time on test frameworks when I could have been writing real code.

10:08 fhd: Although confusing at first, I found it pretty nice that I don't have to bother with object-oriented design in Clojure. Makes things so much easier

10:08 lpetit: no, you will need tests. REPLs "on the fly" tests are volatile

10:09 stuarsierra: of course you're just kidding, but I didn't see this smiley of you saying so at the end of your sentence ;-)

10:10 stuartsierra: :)

10:10 _fogus_: stuartsierra's world is crashing down around him

10:10 stuartsierra: typical

10:10 fhd: Sorry for starting this :)

10:10 I'm still trying to make my mind up on these issues, being pretty new to FP.

10:11 I've never done testing _without_ TDD, actually, so I wouldn't really know how to approach that :)

10:11 lpetit: fhd: it's the nice effect of using a language with less accidental complexity. But when you will be facing problems with more essential complexity, the need for designing things will come, again (but then, you'll add software complexity as you add problem domain essential complexity, and that's a big win)

10:11 jave: arent macro arguments supposed to not be evaluated?

10:11 stuartsierra: jave: not in the macro itself

10:12 they usually get evaluated eventually

10:12 fhd: lpetit: Well, I find Clojure design _much_ _much_ easier than OO design for the simple problems I'm tackling.

10:12 lpetit: jave: you can see macros as functions "eating" source code

10:13 jave: its odd, because I'm using some macros from Enlive. but I need to clone and modify one of the macros

10:13 lpetit: jave: ... digesting source code, and returning source code :-)

10:13 jave: and it doesnt behave the same way

10:13 fhd: lpetit: Object responsibilities, tell-don't-ask, design patterns... that's really a load of accidental complexity :)

10:13 lpetit: fhd: normal, functions are simpler building blocks than classes.

10:13 AWizzArd: Does gen-class support mutable fields as deftype does?

10:14 lpetit: fhd: tell don't ask is interesting, but probably for *true* asynchronous message-passing systems, a la Erlang.

10:14 _fogus_: Erlang is the *only* OO language!

10:14 lpetit: AWizzArd: you can specify a "state", and generally you'll place a ref or an atom there

10:14 fhd: OMG

10:14 jave: oh noes, language wars...

10:15 _fogus_: :p

10:15 fhd: jave: Should be quick. This is the clojure channel :)

10:15 jave: :)

10:16 AWizzArd: lpetit: So gen-class won't have an as efficient field access as deftypes.

10:16 jave: I'm happy so long as I dont have to code in a language thats physically harmfull

10:16 clojurebot: make a note of http://scienceblogs.com/goodmath/2006/11/the_c_is_efficient_language_fa.php it is yet another article about picking c or c++ for performance being naive

10:16 AWizzArd: But deftypes can't inherit from other classes.

10:16 fhd: But I'm really impressed by Clojure so far. I just wanted to do a few quick experiments, but I ended up using it for a larger project.

10:16 Plus I'm giving a talk about it next week :P

10:16 AWizzArd: fhd: in Köln?

10:16 lpetit: AWizzArd: indeed

10:17 fhd: AWizzArd: Ja, aber in meiner Firma

10:17 AWizzArd: k

10:18 stuartsierra: By the way, anybody noticed that swank-clojure doesn't display errors in Clojure 1.3 ?

10:18 lpetit: fhd: interestingly enough, the set of reasons I came to clojure isn't equal to the set of reasons I'm staying with clojure. I discovered a lot *beyond* what attracted me first.

10:18 AWizzArd: stuartsierra: right

10:18 jave: clojure repl errors sometimes arent very helpful

10:18 AWizzArd: I end up typing *e all the time :)

10:18 lpetit: stuarsierra: no

10:24 edbond: does structs deprecated in 1.2 ?

10:24 xkb: Another question regarding my code at http://github.com/svdberg/clojurelisa/blob/master/src/clojurelisa/core.clj

10:24 I think the use of the multimethod mutate is not very benificial here..

10:24 do you agree?

10:30 rhickey: bindings now get automatically conveyed to future calls and agent sends

10:30 http://github.com/clojure/clojure/commit/b1bed1b1c936855801e6d6dd40e649fddb6c039d

10:30 stuartsierra: holy cow!

10:32 AWizzArd: Hmm, I am trying to grasp what this means.

10:32 stuartsierra: I don't know if I like that or not. I was getting used to saying "don't use binding"

10:33 Don't get me wrong, I'm impressed.

10:34 But how far down the chain does it go?

10:34 AWizzArd: stuartsierra: what does this update do with bindings under the hood?

10:34 jjido: is there a limit to the level of continuations in a CPS program? I am at hundreds and only getting started...

10:34 stuartsierra: If I do (binding [...] (send ... A)) and the action A sends another action, does it inherit the same bindings as A?

10:34 rhickey: some notes here: http://dev.clojure.org/display/design/Improve+Binding

10:35 AWizzArd: Oho, looks like the Confluence Wiki :)

10:35 rhickey: stuartsierra: all sends inherit the bindings at the point of send

10:35 stuartsierra: ok

10:36 AWizzArd: Oh very interesting indeed.

10:41 stuartsierra: Is this leading us down the road of first-class environments?

10:41 rhickey: no

10:41 stuartsierra: ok

10:42 good

10:42 rhickey: e.g., no locals in this environment

10:42 stuartsierra: ah, yes

10:44 Why do you always change the language while I'm trying to write a presentation? :)

10:44 rhickey: these benefits convey to pmap, which uses future calls

10:46 AWizzArd: userland use of bindings should be unaffected by this, but this is much more efficient than manual rebinding a la bound-fn

10:47 AWizzArd: Sounds good, I will download that version tonight.

10:48 rhickey: stuartsierra: I'll go back to sitting on my hands :)

10:48 stuartsierra: heh

10:48 lpetit: rhickey: good news !

10:48 stuartsierra: Just restrain yourself from making any earth-shattering changes for the next week, if you can, ...

10:48 lpetit: erm, not you sitting on your hands, of course :-)

10:49 xkb: stuartsierra: are you working on a presenation for clojure-conf? ;)

10:49 stuartsierra: you betcha

10:49 xkb: nice :)

10:49 * rhickey should be working on presentations, instead working on Clojure...

10:50 edbond: http://faustus.webatu.com/clj-quick-ref.html#struct says structs deprecated in 1.2. Is this correct?

10:50 * lpetit should follow rhickey's advices

10:50 lpetit: rhickey: still didn't write a macro to automate the unrolling of first args ;-)

10:52 rhickey: lpetit: they all end up being slightly different - I haven't spent the time to see what really could be generalized

10:53 lpetit: rhickey: oh

10:53 ok

10:53 * lpetit just discovered the existence of the confluence wiki, and how full of interesting items it seems to already be

10:53 stuartsierra: edbond: structs are replaced by deftype / defrecord

10:54 rhickey: lpetit: we're still in the process of getting it all configured, confluence jira etc

10:55 lpetit: rhickey: ok. but let apart the configuraiton, the titles of the other wiki pages seem interesting (though I will not have time to dig into them right now)

10:57 stuartsierra: page on Modularity could be updated for ccw : it's now using the clojure.osgi project, and doesn't use the "eclipse buddies" mechanism anymore (but note that *currently*, clojure.osgi is still dependent on some Equinox aspect, though it's an implementation detail that could be gotten rid of when I or aav has the time to work on it)

10:57 clojure.osgi v1.2.10 to be precise. (1.2 means "compatibility with clojure 1.2", 10 is just a classical version counter)

10:57 fhd: Gotta go, bye

11:05 stuartsierra: lpetit: thanks, updated

11:06 lpetit: stuartsierra: that was quick !

11:06 stuartsierra: anything to avoid writing this presentation :)

11:14 lpetit: stuartsierra: modularity page again. What does it mean to "work fine in Glassfish" ? In which scenario ? One clojure jar per webapp's WEB-INF/lib/ I guess ? Maybe being more explicit on this could help ...

11:18 even git-revert is simpler than reverting with svn !

11:21 tobiasraeder: is there a way to put quotes into doc strings?

11:22 wooby: tobiasraeder: you can escape them like \"

11:23 tobiasraeder: ah okay, i guess emacs just screwed me over then :D

11:25 lpetit: tibiasraeder: install paredit.el, and you'll just be able to type " again inside a literal string to automatically get the \ for free (though not at the end of the string => then you'll have to escape paredit and type \ manually)

11:25 Is it me that just gave an advice for emacs ? Wow, must be sick .. :-)

11:27 Nooo, that's just a false sign of peace before the conj .... Embrace and Extend, gnarl gnarl gnarl ... :-E

11:29 dpritchett: I'm messing around in vimclojure and I notice that Meikel has bound <C-Up> to "UpHistory" but not <C-K>

11:29 any reason I shouldn't rebind C-K as well? I try not to use the arrow keys

11:32 tobiasraeder: @lpetit thanks a ton, using paredit but wasnt aware of that

11:57 ohpauleez: Does anyone know if there are videos of StrangeLoop?

11:59 defn: ohpauleez: they are filming a lot of it

11:59 but not /all/ of it -- which talk were you hoping to see?

12:00 ohpauleez: ah awesome, thanks defn. No one in particular, just wanted to thumb through them and watch the ones that seem interesting

12:00 lypanov: anyone know how to get vimclojure to print out output from commands executed on the cmdline on the go rather than buffering it all?

12:00 defn: yeah fortunately/unfortunately they cost of the ticket didn't permit a lot of the perks some confs have

12:00 ohpauleez: I skipped StrangeLoop for conj, and had to cancel the conj trip because of work

12:00 defn: oh no!

12:00 i met chouser yesterday which was cool

12:01 ohpauleez: Awesome!

12:01 cemerick: rhickey: that's a helluva change!

12:01 defn: i drove to strangeloop so i could handle the cost of flying down to conj

12:01 cemerick: Get them all out of the way now, plz. ;-) (sorry, chouser, _fogus_ )

12:02 ohpauleez: cemerick: Don't be sorry, they get a free second edition now :)

12:02 lypanov: You want to pipe the output to another shell/console?

12:02 rhickey: cemerick: well, it's been a known wart for a while, must be removed to make way for easier parallelism

12:02 ohpauleez: instead of the designated buffer?

12:02 lypanov: ohpauleez: just into the buffer at the time its happening rather than queuing it up.

12:03 ohpauleez: (when using "send top level")

12:03 cemerick: rhickey: for sure, it's a welcome change. I can't think of any immediate downsides -- do you know of any?

12:03 _fogus_: cemerick: I don't follow

12:03 ohpauleez: Ahh, Yeah, I don't know how to do that. I think it's based on the semantics (Looks for the exit code of the process)

12:03 rhickey: so, who's ready for a bifurcation of vars into dynamically rebindable and not?

12:04 jjido: does Clojure have a function to compare two Comparables? < does not work

12:04 lpetit: rhickey: would affect REPL user xperience ?

12:04 rhickey: cemerick: no downsides, as the perf is nearly ideal, one thread local reference, no copies, no cost dependent on number of vars

12:05 ohpauleez: _fogus_: He wants all the changes out of the way for writing the book.

12:05 rhickey: lpetit: in what way?

12:05 lpetit: rhickey: *you* tell me :-)

12:05 rhickey: redefinition, I mean

12:05 jjido: rhickey: sounds interesting

12:05 cemerick: rhickey: perhaps a bifurcation would mean that this non-dynamically-rebindable thing won't be called a var...?

12:05 notsonerdysunny: ->(when-first [[x y z] [1 2 3 4 5]] (+ x y z))

12:05 sexpbot: java.lang.UnsupportedOperationException: nth not supported on this type: Integer

12:05 lpetit: rhickey: and potentially need for reevaluation of all dependent code ?

12:05 notsonerdysunny: ,(when-first [[x y z] [1 2 3 4 5]] (+ x y z))

12:05 clojurebot: notsonerdysunny: Pardon?

12:06 notsonerdysunny: ->(when-first [[x y z] [1 2 3 4 5]] (+ x y z))

12:06 sexpbot: java.lang.UnsupportedOperationException: nth not supported on this type: Integer

12:06 cemerick: _fogus_: just (foolishly) joshing the other authors :-P

12:06 notsonerdysunny: the above expression is return nil on my computer

12:06 I was expecting it to return 6

12:06 _fogus_: cemerick: Thankfully, we can still squeeze in edits. ;-)

12:06 rhickey: I have new ideas about how to make the non-dynamically rebindable vars still 'update-able', for the only viable usage - redefinition of fixed/enhanced functions

12:06 notsonerdysunny: can somebody clarify what is happening here..

12:06 lpetit: rhickey: maybe I should have first aksed: I don't see the use cases

12:06 rhickey: so no re-eval required

12:07 lpetit: ok

12:07 rhickey: but the perf benefits of direct/static binding

12:07 lpetit: seems like everybody is *working hard* not to produce conf slides ... :)-

12:08 rhickey: cemerick: naming-wise, I'm thinking var and dynamic-var

12:08 cemerick: dynamic being something you ask for explicitly

12:08 lpetit: "consts" could be misleading ?

12:08 rhickey: defdynamic

12:09 arkh: how do I import multiple classes from the same packege in a ns declaration? (e.g. something like this (ns my-namespace :import [java.util Date Timer])

12:09 _fogus_: lpetit: Done mine. :-)

12:09 cemerick: holy breakage, batman :-P

12:09 rhickey: lpetit: const might be something else altogether

12:09 replaca: lpetit: I'm writing mine! But I'm way behind my ambitions as well :)

12:09 rhickey: cemerick: no breakage except for dynamic rebinding of fns

12:09 cemerick: rhickey: right

12:09 Not that I'm arguing against the breakage.

12:09 rhickey: so, I'm here to listen to the moaning around that loss

12:10 ohpauleez: arkh: (:import (java.util Date Timer)) should work

12:10 rhickey: arguably, mocking frameworks should be doing root rebinding

12:10 * cemerick sits, waiting to glower at the moaners

12:10 lpetit: _fogus_, replaca: good for *you* :-)

12:11 ohpauleez: (ns my-ns (:import (java.util Date Timer))) (arkh)

12:11 rhickey: dynamic fns used for e.g. error handling could still be created, explicitly

12:11 dynamic binding for monkey-patching will die a deserved death

12:11 arkh: ohpauleez: I receive the following with that: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Keyword

12:12 lpetit: rhickey: and clojure.osgi which currently dynamically rebinds clojure.core/load ... :-

12:12 cemerick: ,(binding [+ -] (+ 10 10)) ; But this is fun! :-P

12:12 clojurebot: 20

12:12 lpetit: :-/

12:12 cemerick: oh, right, core is static these days

12:12 hiredman: dynamic binding is also used a lot for stubbing out functions for testing

12:12 rhickey: lpetit: that's monkey patching IMO

12:12 hiredman: + is inlined

12:13 lpetit: rhickey: for sure :-)

12:13 rhickey: hiredman: see above, root rebinding more suitable, no?

12:13 cemerick: ,(binding [+ -] (apply + [10 10]))

12:13 clojurebot: 0

12:13 cemerick: true enough

12:13 ohpauleez: arkh: take a look at: http://gist.github.com/628461

12:14 Is your :import in a s-expr?

12:14 hiredman: rhickey: yes, well, our tests have started moving down the road of using this with-var-root macro that alter-var-roots and then restores

12:14 arkh: ohpauleez: no - that was the problem, then : ( - Thank you

12:14 ohpauleez: arkh: happy to help

12:14 rhickey: hiredman: exactly

12:15 hiredman: I am not sure which I dislike more, alter-var-root or binding

12:15 lpetit: rhickey: I see root-rebinding as even more "monkey patching" than "call-stack bound rebinding", non ?

12:15 s/non/no/

12:15 sexpbot: <lpetit> rhickey: I see root-rebinding as even more "monkey patching" than "call-stack bound rebinding", no ?

12:15 rhickey: lpetit: root rebinding is not something you would leave in place, just for testing

12:17 * _fogus_ hides his root-rebinding code

12:19 rhickey: root rebinding will be possible, but it will be expensive as it will force all var caches to reload on next use

12:19 so, doing that on code reloads/evals is fine, doing that in tight loop is not

12:19 replaca: alter-var-root is great for setting up the program environment (processing command line args, reading param files and setting global parameters, etc.)

12:20 Purism is situational :)

12:21 rhickey: I'm trying to find the middle ground between bind-once of ML and the high-cost of anything could change at any time, the latter being not very functional

12:21 in this model non-dynamic vars would be presumed constant throughout a fn body

12:21 _fogus_: rhickey: I needed it to simulate record invariants. No tight loops involved

12:22 hiredman: huh

12:22 rhickey: this facilitates caching var contents

12:22 thread binding is reserved for explicit dynamic vars

12:22 lpetit: indeed, when anything can be rebound, it's hard to agree with blog posts which say that clojure-only functions only rely on the input arguments !

12:22 hiredman: the binding propagation will make my scope implementation that uses binding work across threads

12:22 rhickey: on fn entry, a guard is tested that checks for _any_ var root alteration, reloads cache if needed

12:23 this way, you can reload without re-evaluating downstream consumers

12:23 ohpauleez: this change sounds pretty god to me

12:23 good

12:23 rhickey: but most of the overhead of dynamism is removed

12:23 ohpauleez: I appreciated the walkthrough rhickey

12:24 rhickey: hiredman: supporting resource scopes was one of the goals for the thread binding improvements

12:25 but right now we all pay a high price for ever-possible dynamism

12:25 jjido: rhickey: is "at function entry" the right place?

12:25 rhickey: I'm quite stoked, as this new model will avoid much of the brittleness of direct linking and static

12:26 jjido: where else?

12:27 jjido: there is talk of providing access to safepoints for alternative langs, might be a few releases of JDK away...

12:27 jjido: rhickey: it could be user-specified

12:27 lpetit: sounds reasonable. and the semantics make sense, don't they ? (def not-rebindable) (defdynamic *rebindable*) . Now really no more arguing on adding or not CL-like ++ earmuffs around not-rebindable ...

12:27 rhickey: jjido: what would the choices be?

12:28 jjido: rhickey: nondynamic function, dynamic

12:28 cemerick: lpetit: I think I may be one of just a handful that ever used ++ anyway.

12:28 lpetit: heh

12:28 rhickey: +ick+

12:29 jjido: to what purpose?

12:29 jjido: not sure ;)

12:29 lpetit: will read the rest on the logs, must drive home. cu buddies

12:29 rhickey: jjido: non-dynamic == can't call fixed functions

12:29 * lpetit hopes he didn't misuse "buddy" word

12:30 jjido: rhickey: I didn't understand that

12:30 hiredman: done? for promises as has been a sore point

12:30 rhickey: jjido: if you don't really have a use case, nevermind

12:31 hiredman: or actually await-for for promises

12:31 rhickey: hiredman: ?

12:31 jjido: rhickey: ok.

12:32 hiredman: rhickey: a way in core to await on the delivery of a promise with a timeout would be nice

12:32 rhickey: hiredman: yes, it's on the agenda awaiting a good design

12:33 hiredman: right, I am running through the new (to me) wiki

12:33 rhickey: ah

12:33 hiredman: lots of excellent stuff

12:33 (as per the usual)

12:34 a compiler that explicitly passes state, sounds like a job for clojure.contrib.monads

12:34 rhickey: hiredman: that blocking calls page is not ok by me yet

12:35 hiredman: ah

12:35 fliebel: Any Overtone hackers in here?

12:38 rhickey: hiredman: the idea has support, that design, not

12:38 carkh: Lazy seqs + bindings : would it be possible to somehow attach bindings to closures ?

12:38 or would that make these lexical instead

12:39 rhickey: carkh: you could, but the cost of establishing per seq step might be too high

12:39 carkh: attaching at closure instanciation time (tho i don't know know what's under the hood)

12:40 right

12:40 rhickey: so, I'm still thinking about that but have delivered the first half (thread pool support)

12:41 carkh: to me the lazy seqs part is most important, but i can live with it as it is right now

12:41 kumarshantanu: hi, is there any clojure.contrib for dealing with conversion of keyword to/from camelCase strings?

12:41 or any project for that matter

12:41 carkh: kumarshantanu: i'd love to see that, and also for SQL type naming

12:43 rhickey: so, no strong objections to defns becoming not-dynamically (thread-locally) rebindable?

12:43 kumarshantanu: carkh: SQL type naming as in database-agnostic types? :string {:limit 30} --> VARCHAR(30)

12:44 carkh: rhickey: to me rebinding these is bad style anyways

12:44 fliebel: rhickey: I missed most of this, but just defns, or any def?

12:44 cemerick: rhickey: a msg to clojure-dev pointing at the transcript might flush out a principled objection *shrug*

12:44 rhickey: any def, there will be a defdynamic

12:44 fliebel: sounds good to me :)

12:45 carkh: kumarshantanu: nope just :hello-world becoming "hello_world" it's all easy, but it would be nice to have this kind of convertions all in the same place

12:45 rhickey: but you mean not even with the binding macro ?

12:46 rhickey: carkh: the binding macro would only work with defdynamic vars

12:46 carkh: wew that's pretty destructive for old code

12:48 rhickey: carkh: really?

12:48 presume we can easily make defs of *foo* dynamic

12:48 hiredman: well, using *foo* and binding all over the place is pretty horrible, so destroying it is good

12:48 carkh: hiredman: it is, but sometimes that's the best tool

12:49 technomancy: that is going to hurt testability badly. right now one of the things that makes clojure code easy to unit test is that you can rebind some of the functions it relies on.

12:49 kumarshantanu: carkh: I am writing some code and need camelCase to/from keyword conversions -- might as well write something and factor it out

12:49 hiredman: carkh: rarely

12:49 rhickey: dynamic is only being removed as the default, not as an option

12:49 technomancy: if you have to indicate what can be rebound, you will start to need things like dependency injection

12:49 kumarshantanu: rhickey: technomancy: that's spot-on -- mocking dependencies is the biggest use case

12:49 rhickey: technomancy: how so?

12:49 hiredman: technomancy: well there will be root rebinding apparently

12:49 e.g. with-var-root or something

12:50 technomancy: ok, maybe I don't have enough context; I should wait till I hear more.

12:50 rhickey: truly mocking/stubbing/injecting something requires more power than binding anyway, as that only affects one branch

12:51 everyone needs to be clear we are only talking about rebinding, not redefing

12:53 an aPI option is to trigger dynamics from the earmuffs (def *dynamic-foo*) == dynamic

12:53 carkh: hiredman: i have this now becoming rather large web application, i use binding at the top of the url matching tree as soon as i know the customer in order to "binding" the currency he uses, i can't imagine passing such a value trough all function calls without passing a state mage-object which in the end is not any better than rebinding vars

12:53 AWizzArd: So, in principle this only shadows older bindings, and releases them when the body closes.

12:53 carkh: mage->mega

12:53 rhickey: that will minimize breakage for anyone using the convention

12:54 cemerick: please no sniffing of var names to hint semantics

12:54 rhickey: let's not argue about dynamic vars, they have obvious utility and are used by Clojure itself, and are not going away under this proposal

12:55 cemerick: significantly reduces the breakage, and ensures the naming convention

12:55 jkkramer: could a warning be issued?

12:55 carkh: rhickey: huh the earmuff thing seems a bit too magical

12:57 rhickey: (defdynamic no-earmuffs) will be considered bad karma though

12:57 defn: 11:55 < jkkramer> could a warning be issued?

12:57 carkh: wouldn't it make sense to take the reverse option of going defstatic or def for dynamic as it is now ?

12:57 rhickey: watning about what?

12:57 warning

12:57 cemerick: rhickey: Granted, but it's still bad. Not as bad as the -void-methodName black magic, but still bad.

12:58 rhickey: cemerick: alternatives for breakage reduction welcome

12:58 jkkramer: "i'm making *your-def* dynamic but you should really use defdynamic"

12:59 danlarkin: my vote is against the name of a var influencing its behavior

12:59 carkh: and give us an error when trying to binding a static var

12:59 rhickey: jkkramer: yes, more likely if we intend to deprecate the earmuffs==dynamic as a transition feature only

12:59 jkkramer: right

12:59 rhickey: carkh: tat is certain

12:59 that

13:00 carkh: so why not defstatic+def instead of defdynamic+def ?

13:00 hiredman: def would not be the same as static

13:00 carkh: just like you need to specify that function is static and get dynamic by default

13:00 hiredman: in the case of defdynamic+def

13:01 rhickey: carkh: because it's not static, there is a lot of code that presumes namespaces contain vars, dynamic vars will be Vars by inheritance if not by mode

13:01 jjido: Could we define an auto-dynamic variable pattern?

13:01 hiredman: it would just not be bindable, which is not the same thing

13:01 cemerick: rhickey: I don't have any alternative breakage mitigation suggestions at the moment. Adding and then taking away magical var names seems even worse than adding them at all, though.

13:01 jjido: using a regex

13:01 rhickey: cemerick: even if it never makes a release?

13:02 jjido: That way you can use the earmuffs, dyn-something or whatever pattern you like

13:02 cemerick: rhickey: that changes the calculus significantly

13:04 amalloy: i don't understand the objection to carkh's proposal. leave def the way it is, and introduce a defstatic; that gives you access to the new language "feature", while not breaking old code that assumes it can rebind something

13:05 cemerick: amalloy: people wanting speed is more common then people wanting dynamic rebinding

13:06 ohpauleez: cemerick: I totally agree, but I kind of like the suggestion myself

13:07 as far as migration is concerned. That said I really only use dynamic binding in the cases already mentioned and am fine working around them

13:09 hiredman: amalloy: that proposal rests on a faulty understanding of the choices and tradeoffs involved

13:09 cemerick: The same dynamic applied to the prim stuff: people care way more about perf in common cases than the generality of arbitrary precision.

13:09 carkh: tss ok static might not be the best word

13:09 but you get the idea

13:10 ohpauleez: cemerick: I actually thought of that as the counter example. People don't care about auto-promotion most of them time (in fact, I'm sure they rarely expect it), but when they want it, it's there

13:11 cemerick: ohpauleez: the same applies here -- rebinding is rarely used, but defdynamic is there when you need it

13:11 jjido: I like that Clojure can calculate factorial of 10000.

13:12 ohpauleez: I completely agree. I only use rebinding in the situations listed already, and I'm fine being explicit about them

13:12 I retracted my statement from before

13:13 carkh: you might not have a big code base to take into account maybe .. *cries*

13:13 ohpauleez: You can't please everyone :)

13:13 jjido: carkh: but you can use refactoring tools on your code can't you?

13:13 carkh: what tools ?

13:14 ohpauleez: or a macro!

13:14 carkh: all i have is good old emacs

13:14 ohpauleez: I thought emacs had everything?

13:14 :)

13:14 jjido: ohpauleez: exactly!

13:15 ohpauleez: carkh: sed will fix it for you

13:16 all of this aside, do we really need the special *binding-name-that-is-now-dynamic* trick?

13:16 I understand this change will break some projects, but those projects depend on an earlier version on clojure

13:17 _fogus_: This appears to break only one example in JoC, so I say it's a win. :-)

13:17 ohpauleez: Awesome!

13:21 amalloy: i agree it seems wrong to treat *vars* specially, but as indicated above i don't really understand the issues, so feel free apply a grain of salt

13:29 fhd: Hi. I'm about to do some string conversion in Clojure. I'd usually just read the string line by line and then add the modified lines to a StringBuilder.

13:29 However, that's quite imperative. Any hints on how to do this more elegantly in Clojure?

13:30 Specifically, I'm parsing a file and replacing some magics in it by the respective entries in a map.

13:32 kumarshantanu: fhd: Google's Guava is a nice library -- but it's Java

13:32 rlb: may need more details, i.e. can the pattern you're looking for span lines? Are you dealing with a *lot* of data overall? per-doc?, etc.

13:33 fhd: rlb: I'm not really worried about efficiency ATM. It's rather small files, a few hundred bytes.

13:33 rlb: The patterns cannot span lines.

13:33 rlb: fhd: slurp, replace the pattern, then dump?

13:33 fhd: rlb: Well, it's several patterns. There are tags in the file, like '{{SOMETHING}}'

13:34 rlb: fhd: or if you don't want to hold the whole doc in memory, use a line-seq, etc.

13:34 fhd: Then I want to replace each of these with the map value for the key :SOMETHING

13:34 rlb: I thought about just doing a few replaces, but that would be ~10 string replacements on each complete file. Don't find that too elegant.

13:35 rlb: how many items in the SOMETHING domain?

13:35 (max)

13:35 fhd: kumarshantanu: Does Guava have functionality for that? I'm actually trying to do it as Clojure-style as possible, but if there's something I can reuse...

13:35 rlb: Hm, I'd guess each item will usually pop up once or twice. And there should be up to 10 different items

13:36 kumarshantanu: fhd: Guava lets you read from a file line by line -- nice API

13:36 rlb: you could use a map (or doseq if you only want one line in memory at a time), and a function that just replaces all the patterns in that line before passing it on (via return or write)

13:36 rhickey: _fogus_: what breaks in JoC?

13:36 fhd: rlb: Yeah, that's pretty much how I'd do it in Java. But I thought this was kinda weird in Clojure

13:37 rlb: (doseq [line (line-seq file)] (write-line ...))

13:37 kumarshantanu: fhd: see this example -- http://www.copperykeenclaws.com/googles-guava-java-the-easy-parts/ (Files.readLines...)

13:37 amalloy: fhd: i'm in favor of rlb's proposal. just define a write-line function that does the necessary replacements

13:38 fhd: amalloy: Hm, OK I guess.

13:38 I somehow thought there was some funky function for this in Clojure :)

13:38 amalloy: write-line can use reduce on a list of replacements to avoid writing .replace more than once

13:38 fhd: I'll just use StringBuilder then

13:39 amalloy: Hm, I'll look at that

13:40 nishant: Can I do a require :as from the REPL?

13:41 fhd: rlb: Why would I use doseq here? Isn't map fine too?

13:42 rlb: fhd: map should be fine as long as you don't hold on to the head of the result

13:42 amalloy: ,(let [replacements [["a" "A"] ["b" "B"]]] (reduce (fn [str [from to]] (.replaceAll str from to)) "at bat"))

13:42 clojurebot: java.lang.UnsupportedOperationException: nth not supported on this type: Character

13:42 rlb: (or as long as you don't care if each doc's completely in RAM at some point)

13:43 and it's more flexible if you ever need that

13:43 fhd: rlb: I didn't really understand any of that, but I guess I'll just use doseq :)

13:43 amalloy: ,(let [replacements [["a" "A"] ["b" "B"]]] (reduce (fn [str [from to]] (.replaceAll str from to)) "at bat" replacements))

13:43 clojurebot: "At BAt"

13:43 rlb: fhd: map returns a sequence containing the result

13:43 i.e. (line-1 line-2 line-3)

13:43 fhd: rlb: Ah, I see

13:44 amalloy: fhd: see above for a reduce/replace recipe

13:44 fhd: rlb: And doseq returns nothing and just does stuff?

13:44 rlb: doseq doesn't -- it's not a functional op

13:44 it's just for side-effects

13:44 fhd: amalloy: Thanks, pretty nice

13:45 rlb: fhd: but since map is lazy, and line-seq is lazy, then map won't keep everything in ram either, as long as no one holds on to the head of the result.

13:46 fhd: rlb: I don't really get the "holding onto the head" thing

13:46 rlb: i.e. (doseq [line (map ...)] (print line))

13:46 amalloy: ,(nth (range) 100000000)

13:47 clojurebot: Execution Timed Out

13:47 amalloy: ,(let [x (range)] (nth x 100000000))

13:47 clojurebot: Execution Timed Out

13:47 amalloy: fhd: the first of those examples will work, eventually, in a real repl

13:47 rlb: fhd: with a lazy seqence, the items of the sequence aren't computed until they're needed, so you can traverse an infinite list in finite memory as long as you don't hold on to the head of the list.

13:47 amalloy: because as soon as it's done with an element it can be GCed

13:48 fhd: rlb: So by holding onto, you mean keeping a reference to the element?

13:48 amalloy: the second one won't, because x is still referring indirectly to every element in range

13:48 rlb: fhd, right

13:48 i.e. (def ints (all-integers)) is *bad*, even if all-integers is lazy

13:48 fhd: rlb: Ah, I see. If I would hold references, all memory would eventually be consumed.

13:48 rlb: but (doseq [i (all-integers)] (prn i)) is fine

13:49 well, for some definition of "fine"

13:49 _fogus_: rhickey: rebinding an exception handler defn (and example in the final chapter)

13:49 rlb: it won't run out of ram at least

13:49 amalloy: rlb: well, fine except you're printing an infinite sequence :)

13:49 _fogus_: s/and/an

13:49 stuartsierra: eventually you'll run out of paper

13:49 rlb: nah, just electrons

13:50 rhickey: _fogus_: so, exception handlers are still valid uses of dynamic fn vars (and the original motivation for allowing dynamic fns), but will have to be explicit about the dynamism

13:51 _fogus_: rhickey: It's the only use case that we mention. :-)

13:51 rhickey: I'm considering retaining support for the :dynamic true metadata for this purpose, as a second set of dynamic def variants seems like a waste

13:52 _fogus_: you can slap :dynamic true on that now (harmlessly) and it might still work

13:52 rlb: fhd: easy way to play around with infinite lists in clojure is via cycle, repeat, or repeatedly.

13:52 _fogus_: rhickey: A footnote might be in order... we do not have enough of those.

13:53 ;-)

13:53 !!! http://twitter.com/amitrathore/status/27464468779

13:54 rhickey: nice!

13:55 kryft: Told where?

13:55 rlb: fhd: another thing to keep in mind is that if you're not used to laziness, execution may not happen when you expect it to. i.e. it happens when each element of the list is *consumed*. If the list is never consumed; no execution...

13:55 amalloy: kryft: at strangeloop

13:56 fhd: rlb: I guess I'll take the chance :)

14:03 _fogus_: Hmmm, just realized that the wording in the Var section might need to be adjusted also.

14:06 fhd: Are private functions in Clojure mostly a way to make people coming from Java happy or is their use encouraged?

14:07 rlb: fhd: it's not a problem, just the way laziness works, but I imagine it can be surprising

14:07 amalloy: fhd: i think they're encouraged. don't clutter namespaces with functions nobody will want

14:08 if someone (use)s your library, they don't want tab-completion for your process-portion-of-file function

14:08 fhd: amalloy: Probably. I was mostly wondering because I don't think there's such a mechanism in other Lisps, so I thought it might not be Lisp-y

14:09 carkh: it is also encouraged to only use the symbols you need

14:09 rbanffy: Hi folks. Total newbie installed Clojure from ELPA. I would like to use 1.2 instead of 1.1. What can I do?

14:09 carkh: (:use [mynamespace :only [frobnicate])

14:10 technomancy: rbanffy: try the swank-clojure readme; sounds like you found some out-of-date docs

14:11 rbanffy: technomancy: Where can a *total* newbie find it?

14:12 fhd: carkh: Hm, I always use evertything.

14:13 amalloy: fhd: i do too, but it's a filthy habit, just like it is in java

14:13 i just can never remember the syntax for using selectively

14:13 qed: I thought proxy was deprecated for some reason.

14:14 Guy Steele just said to learn clojure.

14:15 amalloy: qed: your thunder has been stolen already

14:15 fhd: amalloy: Well, I kind of like .* in Java :P Hardly ever had any problems with that, and it's IMO worth removing ~100 files from each file.

14:16 qed: amalloy: I think that was me actually.

14:16 I'm defn.

14:16 amalloy: qed: are you fogus too? :P

14:16 qed: Haha. :F

14:16 amalloy: fhd: .* is convenient if you're not using a decent IDE, but it means (for example) if you see a strange class like MagicDoStuff in the code, you don't know what package it's from

14:17 but eg Eclipse will manage all the imports for you so that anyone readong your code knows exactly what classes come from where

14:18 fhd: amalloy: Yeah, but I'm usually on Emacs. Someone using Eclipse can actually see where the file is from by holding the cursor over it :) Well it's probably a matter of taste in the end.

14:21 amalloy: fhd: search google for "java style guide import .*", the first N hits say DONT DO IT

14:23 jjido: amalloy: because of name clashes?

14:24 rbanffy: technomancy: I see slime-lisp-options points to 1.1 Is there an easy way to change that?

14:24 amalloy: jjido: meh. that's only really a problem for java.util.Date :P. it just makes the code harder to read if you're seeing it for the first time

14:26 i mean yes, it's obviously a style issue since the compiler doesn't care, but so are newlines

14:26 fhd: amalloy: There's reasons for both approaches, that's why I called it a matter of taste. The topic is quite controversial on the web apparently.

14:27 technomancy: rbanffy: yeah, you don't need swank-clojure.el, just clojure-mode and slime-repl

14:28 rbanffy: technomancy: That's confusing. All I wanted was to make M-x slime give me 1.2...

14:31 fhd: Hm, but there's one problem. When I make functions private, I cannot call them from the REPL for testing purposes anymore.

14:31 opqdonut: fhd: you can say (in-ns 'foo)

14:31 then they should be visible

14:31 fhd: opqdonut: Great, thanks

14:32 amalloy: or just (ns foo), which expands to the same thing

14:32 opqdonut: mmm yeah

14:32 fhd: amalloy: Isn't (ns) already included in (use)?

14:32 amalloy: fhd: no. use is a combined require/refer

14:33 opqdonut: yep

14:33 use imports the given ns into the current ns

14:33 ns or in-ns changes which ns you are in

14:33 fhd: opqdonut: Ah, okay

14:33 opqdonut: this affects the visibility of private stuff and also where defs go

14:43 duncanm: if i have a map {:a 1 :b 2} and i just want to keep the same map but increment all the vals by one, how should i write that?

14:43 fhd: Can I turn a keyword into a string?

14:44 e.g. :name -> "name"

14:44 duncanm: ,(str :foo)

14:44 clojurebot: ":foo"

14:44 fhd: wow

14:44 jkkramer: ,(name :foo)

14:44 clojurebot: "foo"

14:44 duncanm: even nicer

14:44 fhd: Thanks :)

14:45 mrBliss: ,(into {} (for [[k v] {:a 1, :b 2}] [k (inc v)]))

14:45 clojurebot: {:a 2, :b 3}

14:45 duncanm: mrBliss: that's kinda messy...

14:45 mrBliss: duncanm: indeed

14:46 duncanm: mrBliss: in my mind, what i want to do is to 'map' over the vals of a map and get back a map (and not a list of vals)

14:47 mrBliss: duncanm: unfortunately, that's not how seqs work :-( I've needed this too

14:48 amalloy: ,(let [m {:a 1 :b 2}] (zipmap (keys m) (map inc (vals m))))

14:48 clojurebot: {:b 3, :a 2}

14:50 mrBliss: amalloy's version is faster on my machine

14:50 amalloy: really? i wonder why

14:51 anyway you could easily write a generic map-over-vals function and then use that all over

14:51 mrBliss: zipmap is loop and recur and for is a bit messier. Also I create a new vector for every element in the map

14:54 hiredman: ,(doc fmap)

14:54 clojurebot: "clojure.contrib.generic.functor/fmap;[[f s]]; Applies function f to each item in the data structure s and returns a structure of the same kind."

14:56 amalloy: aha, nice

14:59 fhd: amalloy: Remember your replaceAll code from earlier? It works fine, but I don't really understand it. What does (fn [str [from to]] do?

15:00 amalloy: I presume it are the two values passed in from resume, but I don't really know that syntax

15:02 amalloy: fhd: do you understand destructuring yet?

15:03 fhd: amalloy: Haven't heard it in the context of Clojure yet, so I guess no

15:03 amalloy: k

15:03 in binding forms like let and fn args, instead of just plain variable names you can give sequences

15:03 that says "the thing that you will bind to this is a sequence; break it down and assign its elements to the variables i name"

15:04 fhd: amalloy: Ah, so the second argument is a vector?

15:04 amalloy: ,(let [[a b c] (range)] b)

15:04 clojurebot: 1

15:04 fhd: I see, cool.

15:05 amalloy: since reduce is iterating over a seq of [from to] vectors, and tracking a single string as the result, the signature of the reduction function is [str [from to]]

15:05 fhd: Because reduce always passes two strings in, I see

15:05 Pretty clever

15:05 amalloy: indeed, destructuring is amazing

15:06 fhd: But most of the time I look at Clojure code, I feel like it's far too clever for me

15:06 And when I happen to write clever stuff myself, I feel like an evil genious. Well, at least evil.

15:06 Does that change with time? :)

15:06 amalloy: haha not yet

15:07 check out http://rosettacode.org/wiki/Fibonacci_sequence#Clojure for the thing that most recently made my jaw drop (i wrote the description at the bottom to help me understand it)

15:09 fhd: OMG

15:09 I wonder if I'd be better at understanding this stuff if I had studied maths instead of CS :)

15:10 amalloy: probably not. you just have to get used to functional programming

15:11 fhd: amalloy: I really like it so far, but I realised just recently that functional programming wasn't OOP with closures :P

15:11 Adamant: amalloy: laziness is awesome, huh? :)

15:11 amalloy: heh

15:11 Adamant: it's not the laziness so much as the clever way of maintaining metadata that you throw away before giving out the result

15:12 Adamant: not holding onto the head and intermediate results? yeah

15:12 amalloy: i feel like i've fully grokked it now that i've written some code that comverts to/from base N that uses the same idiom

15:13 rlb: fhd: destructuring can also be useful when defining multiple function bodies, i.e. (defn foo ([x] x) ([x [y z]] (+x y z)))

15:13 fhd: rlb: Basically overloading, huh?

15:13 rlb: it allows more sophisticated argument matching

15:13 fhd: rlb: Yeah, I imagine it can make for real beautiful signatures

15:14 amalloy: fhd: depends on your notion of beauty. if you nest too deeply it starts to become unreadable

15:15 and there are more advanced features for destructuring. for example:

15:15 ,(let [f (fn [{a :name, b :age}] ) (str a b))] (f {:age 9}))

15:15 clojurebot: Unmatched delimiter: )

15:16 fhd: amalloy: True. But I find it more explicit than passing an array or a collection that contains two elements

15:16 amalloy: ,(let [f (fn [{a :name, b :age}] (str a b))] (f {:age 9}))

15:16 clojurebot: "9"

15:16 fhd: I need Clojure highlighting for irssi

15:17 Hm, that's essentially named parameters

15:18 amalloy: fhd: well, named parameters are a special case of map destructuring

15:18 mrBliss: fhd: Emacs comes with ERC

15:18 fhd: mrBliss: Haha :) Although an Emacs user, I was never a big fan of using it as an OS :P

15:19 amalloy: you can do map destructuring in more complicated ways, for example pull apart a map that's inside a vector

15:19 fhd: amalloy: Is that whole destructuring thing Clojure-only or general Lisp? I never did advanced stuff in Emacs Lisp, so I wouldn't know

15:20 amalloy: i believe CL has it but it's way less pretty/convenient

15:20 mrBliss: ,(let [{:keys [a b c]} {:a 1 :b 2 :c 3}] [a b c])

15:20 clojurebot: [1 2 3]

15:20 fhd: I believe the variable parameter lists in Emacs use something similar

15:20 amalloy: lisp has &rest and &keys

15:21 fhd: Yeah, that's it. Then it's not destructuring

15:21 amalloy: and i think a destructuring-bind function that does stuff like clojure, but it's just harder to get at (like most lisp things)

15:21 Adamant: CL, please

15:21 amalloy: argh, i said CL last time

15:21 Adamant: I don't like the conflation of 'Lisp' with CL

15:22 amalloy: Adamant: it's a pretty...Common...mistake :)

15:22 Adamant: not that I don't like CL, but unless they plan to create another standard, formal or informal, it's a dead language

15:22 ohpauleez: amalloy: haha that was a good one

15:22 Adamant: oh yeah

15:22 so good it's good while still being bad :P

15:22 also, you must now put on the sunglasses while background music plays "YEeeoowww!!!!!"

15:23 amalloy: i prefer the drum sting while the audience groans

15:23 Adamant: hey, that works :P

15:24 fhd: When using line-seq, can I somehow preserve (to re-add) the EOL characters?

15:25 mrBliss: ,(interleave [1 2 3] (repeat "\n"))

15:25 clojurebot: (1 "\n" 2 "\n" 3 "\n")

15:25 mrBliss: replace [1 2 3] with your (line-seq ..)

15:26 fhd: mrBliss: Well, I would like to preserve the EOL chars exactly as they appear, if possible

15:26 mrBliss: i.e. whatever stile the file uses, plus add one to the end or not

15:26 mrBliss: yeah I just saw it too

15:26 fhd: s/stile/style/

15:26 sexpbot: <fhd> mrBliss: i.e. whatever style the file uses, plus add one to the end or not

15:26 fhd: now that's neat

15:27 mrBliss: do you mean keeping \r\n or \n?

15:27 fhd: mrBliss: Yeah. If they're mixed, I'd like to keep them mixed. Don't want to play cop here.

15:31 technomancy: rbanffy: if you're still around, the short version is that it's very awkward to launch clojure processes from elisp because of the fact that the classpath must be known up front. so it's best to launch it with lein/cljr/etc and connect from Emacs

15:35 hsuh: why (= 1M 1.0M) is false?

15:36 amalloy: ,(map class [1M 1.0M])

15:36 clojurebot: (java.math.BigDecimal java.math.BigDecimal)

15:36 amalloy: hm. dunno hsuh

15:36 ohpauleez: yeah, that's what I thought too

15:37 amalloy: it may be that bigdecimal keeps track of how much precision it's recording

15:37 eg, for scientists 1 != 1.00

15:38 ,(map #(.precision %) [1M 1.0M])

15:38 clojurebot: (1 2)

15:39 amalloy: hsuh, ohpauleez: ^^

15:39 ohpauleez: ahh, for sure

15:40 hsuh: ok, but there should be some way of testing something like this without knowing the precision,no? (ok i see that zero? works for 0.00000M but anyway...)

15:40 _rata_: hi

15:42 raek: if you convert them to the same type, you can always compare them

15:43 hsuh: ,(= (bigdec 300M) (bigdec 300.000M))

15:43 clojurebot: false

15:43 lrenn: ,(= 0 (.compareTo 1M 1.0M))

15:43 clojurebot: true

15:45 hsuh: ,(zero? (- 1.0M 1.000M))

15:45 clojurebot: true

15:46 raek: I'm not sure, but maybe java's requirements on .equals has something to do with this

15:46 hsuh: ok

15:46 raek: this was changed pretty recently too

15:48 _schulte_: so acording to http://clojure.org/lazy filter is not fully lazy, is that still the case?

15:48 amalloy: _schulte_: that proposal is very old

15:49 _rata_: how can I have multiple mutually-referencing objects in one atom?

15:49 fhd: Is there anything similar to "instanceof" in Clojure?

15:50 amalloy: ,(instance? 1 Integer)

15:50 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Class

15:50 _rata_: fhd, instance?

15:50 _schulte_: amalloy: but is filter still non-lazy? I have some out-of-memory errors that would indicate that something in the take/filter/map/pmap/filter/repeatedly stack is not lazy

15:50 amalloy: ,(instance? Integer 1)

15:50 clojurebot: true

15:50 amalloy: no, filter is lazy

15:50 fhd: Ah, great

15:50 amalloy: ,(supers (class {})) ; also sorta useful maybe

15:50 clojurebot: #{java.util.concurrent.Callable clojure.lang.IMeta clojure.lang.Counted clojure.lang.Seqable java.lang.Runnable java.io.Serializable clojure.lang.APersistentMap clojure.lang.ILookup java.lang.Object clojure.lang.Associative clojure.lang.IEditableCollection clojure.lang.IPersistentMap clojure.lang.IObj java.util.Map clojure.lang.IPersistentCollection java.lang.Iterable clojure.lang.AFn clojure.lang.IFn}

15:51 _schulte_: amalloy: ok, thanks, on a related question then, do you know of a way to explicitly free an object, currently the GC is throwing out-of-memory errors because it's working too hard

15:51 amalloy: _schulte_: the GC will free things that aren't referenced anymore. can you post a gist or something so we can see what the problem is?

15:52 hsuh: ,(or (> 1M 1.0M) (< 1M 1.0M) (= 1M 1.0M))

15:52 clojurebot: false

15:52 raek: http://www.assembla.com/wiki/show/clojure/Enhanced_Primitive_Support <-- mentions something about equality for number types

15:53 hsuh: tks

15:53 _schulte_: amalloy: sure, see http://gist.github.com/628831, something in this loop is running out of memory, the idea behind the code is to cycle through thousands of objects, dumping them to STDOUT and quitting after `out-num' successfull ones have been found

15:53 any ideas/feedback are much appreciated

15:54 plathrop: Do people tend to deploy their Clojure apps with some way to connect and get a repl inside the application?

15:54 So you can do live changes?

15:55 hsuh: raek: tl;dr: is not a simple problem :)

15:55 raek: for development, I always run a swank server in the clojure instance

15:57 for the projects that I have running but not currently developing, I keep a repl in a screen, just in case

15:58 hsuh: raek: but do you change stuff or its more for peeking around?

15:59 aavram: Hello, I'm having an issue getting the links to work in labrepl somewhat like as described here : http://github.com/relevance/labrepl/issues/issue/13 . I have tried removing the lib directory and ~/.m2/repository/ but still can't get the links to work. Any suggestions?

15:59 amalloy: _schulte_: how long does evaluate-asm take to run? it looks like you may be spawning zillons of threads at once before any of them complete

15:59 raek: in my IRC bot, I change stuff all the time

15:59 _schulte_: amalloy: <=8 seconds

15:59 hsuh: raek: i dont know if that is considered production :)

15:59 _schulte_: amalloy: ok, thanks, I'll try removing the pmap

16:00 plathrop: raek: I do the same in development and was thinking it would be cool when you actually deploy the app to have the ability to connect to arepl.

16:00 raek: well, I wouldn't consider that project production either

16:00 _schulte_: it'd be nice to be able to specify a threadpool size for pmap...

16:00 amalloy: your code mostly looks like it's fully lazy, so pmap is the only culprit that comes to mind

16:01 raek: a web app I made is running in the background, but I rarely touch that

16:01 _schulte_: great thanks, I was confident in the lazyness until I saw the clojure.org/lazy page which implies that the clojure core isn't quite lazy

16:01 hsuh: plathrop: that sounds like fun, being able to fix things on the fly and impress people... but on think it would be very popular IRL

16:01 raek: but it is neat to be able to inspect variables when it's running, if I need to

16:02 plathrop: It was a useful trick when I was using list.

16:02 lisp even

16:02 Common lisp even :-P

16:03 hsuh: plathrop: that habit can be transferred to clojure, no prob i guess

16:03 fhd: In the body of a (for, I can add elements like this [:hello :world]. Can I also add two blocks of elements?

16:04 hsuh: slime repl lets me connect to a running swank, change namespace, redefine functions, its neat...

16:04 fhd: I tried [:hello :world][:foo :bar], but it just ignores one entry

16:05 _rata_: fhd, what do you want to do?

16:05 do you want to return the four values from (for ...)?

16:06 then [[:hello :world] [:foo :bar]] would do it

16:06 fhd: I have a list of replacements that looks like this [["hello" "world"]["foo" "bar"]] etc.

16:06 I only added one replacement on each execution of (for, so this worked. But now I want to add two entries

16:07 _rata_: That would create a new vector, like this: [[["hello" "world"]["foo" "bar"]]["normal" "replacement"]]

16:07 It's the code amalloy|afk gave me earlier

16:07 rlb: fhd: not sure you can easily preserve the ends as-is. You could either just pull in the whole doc and filter it via slurp and multiple string/replaces, or write your own lazy seq that keeps the endings. See (source line-seq). Of course the slurp approach will be more expensive.

16:08 raek: fhd: if I understood the problem correctly, you need to return a collection of things, and apply concat to the seq you get from for

16:08 fhd: rlb: I guess I'll leave it like this for now. Did some ugly (if (= line (last lines)) "\n") for now

16:09 raek: ,(apply concat (for [x (range 5)] (if (even? x) [x x] [x])))

16:09 clojurebot: (0 0 1 2 2 3 4 4)

16:09 fhd: raek: I don't think that's it

16:09 raek: the problem being "replacing certain elements with one elements and other with two"

16:09 fhd: Simply put, I want to return _two_ values from (for

16:10 raek: fhd: then you simply have to pair them together in some sort of collection

16:10 or do two separate fors

16:11 nishant: ,(doc concat)

16:11 clojurebot: "([] [x] [x y] [x y & zs]); Returns a lazy seq representing the concatenation of the elements in the supplied colls."

16:12 raek: ,(map (juxt inc dec) (range 10))

16:12 clojurebot: ([1 -1] [2 0] [3 1] [4 2] [5 3] [6 4] [7 5] [8 6] [9 7] [10 8])

16:13 raek: fhd: what is your desired input and output? can you provide an example?

16:14 fhd_: Hm. So that means I'll have to add my elements wrapped in another vector, than somehow flatten the whole thing and make pairs out of every two elements?

16:16 dpritchett: argh

16:16 i took a few months off from clojure and now i can't think functionally anymore

16:17 given a list of lists how do i return the list with the largest second element? ((1 1) (2 10) (3 4)) should return (2 10)

16:18 i'll bet i could do it with reduce

16:18 mrBliss: ,(apply (partial max-key second) '((1 1) (2 10) (3 4)))

16:18 clojurebot: (2 10)

16:19 fhd: Is it possible to somehow "flatten" a vector, i.e. turn [[[1 2]][3 4]] into [1 2 3 4]?

16:19 mrBliss: (doc flatten)

16:19 clojurebot: "([x]); Takes any nested combination of sequential things (lists, vectors, etc.) and returns their contents as a single, flat sequence. (flatten nil) returns nil."

16:19 fhd: oh

16:19 dpritchett: thanks

16:19 seancorfield: ,(flatten [[[1 2]][3 4]])

16:19 clojurebot: (1 2 3 4)

16:19 seancorfield: note that it returns a seq, not a vector

16:20 ohpauleez: protocol experts, can someone inform me why I'm seeing a NullPointer when eval'ing this file http://github.com/ohpauleez/net-ns/blob/master/src/net_ns/server/atom_mapper.clj

16:20 seancorfield: ,(apply vec (flatten [[[1 2 ]][3 4]]))

16:20 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (4) passed to: core$vec

16:20 seancorfield: hmm, i can never remember how to call vec :)

16:21 ,(vec (flatten [[[1 2]][3 4]]))

16:21 clojurebot: [1 2 3 4]

16:21 LaPingvino: vec works on seqs

16:21 more or less like str

16:21 fhd: I just realized that it's far more elegant if I use a regex instead of two patterns

16:22 seancorfield: ,(str "Takes " "any" " number of" " strings")

16:22 fhd: Phew, I really didn't want to use the flatten solution :)

16:22 clojurebot: "Takes any number of strings"

16:25 raek: fhd: if you only want to flatten one level, you can use apply concat

16:28 fhd: raek: But is that really the best solution for adding two or more elements to a list using for? By adding a vector with two elements and then flatten the whole thing later?

16:30 raek: fhd: so you have a sequence of things, you produce a part of a sequence from each element and want those sequence to be made into one big sequence?

16:31 fhd: raek: Well, I'm producing a totally different sequence from another one. The sequence I produce has several entries per value of the original sequence.

16:31 plathrop: Is clojure.contrib.mock the best mock library out there? Trying to add unit tests to code that calls out to Java objects, and I don't want to create real Java objects.

16:32 rbanffy: technomancy: Thanks. I know it seems to be a bit awkward, but, since swank can do it by itself, there must be some way to teach it to use a different set of .jars

16:33 raek: fhd: then I would recommend (mapcat f coll), which is the same as (apply concat (map f coll)), or using (apply concat (for ...))

16:33 ubii: does anyone know, if the Clojure-conf presentations will be recorded and made available online?

16:33 fhd: raek: i.e. removing exactly one "layer"? I'll do that then

16:33 raek: fhd: but to answer your question, yes. I would add them to a vector and use concat

16:34 also, concat is lazy

16:34 bmh: Any recommendations for a computational geometry lib? Java or Clojure

16:34 raek: as is for and map

16:35 fhd: raek: Wow, it works. Magical.

16:35 _rata_: how can I have multiple mutually-referencing objects in one atom?

16:36 ohpauleez: bmh: I would go with Clojure and call Java as needed

16:37 bmh: What specifically are you doing?

16:37 ohh, you're looking for a lib, my b

16:37 bmh: ohpauleez: That's the plan. 3d convex hull / delaunay triangulation on a sphere

16:38 ohpauleez: both those algos aren't bad to implement, but I'm digging around some code to see if I've used a library ever

16:40 bmh: Typically in the past I've just called out to Mathematica and matlab as needed

16:40 bmh: ohpauleez: oh geez! Ouch

16:41 ohpauleez: yeah, I'm not coming up with much

16:41 sorry bmh

16:41 bmh: I guess I can implement qhull

16:42 ohpauleez: yeah, it's pretty straight forward

16:42 bmh: even in 3d?

16:42 ohpauleez: if my memory serves me correctly

16:43 My old lab just did it on the JVM and published, "On the use of Computational Geometry to Detect Software Faults at Runtime"

16:44 fhd: Wow, accomplished quite a lot today, thanks to you guys! Cya.

16:45 bhenry: what would a ring handler look like if i want a link to make the browser ask the user to download a *.xls

16:47 amalloy: bhenry: the header for that is Content-Disposition=attachment, as i recall. google that and you'll probly find the right answer

16:47 bhenry: yeah i just dead. do i just give my handler a :headers key?

16:47 i just did*

16:48 amalloy: bhenry: probably. i don't actually use ring

16:48 raek: bhenry: include a {"Content-Disposition" "attachment; filename=foo.bar"} header

16:48 bhenry: raek: thanks.

16:49 when i first started using ring i made a template that takes a context map, and i forgot that i already have a headers key in there.

16:50 raek: bhenry: also remember to set the Content-Type to the correct MIME type

16:51 bmh: ohpauleez: found one: http://www.cs.ubc.ca/~lloyd/java/quickhull3d.html

16:52 ohpauleez: awesome!

16:53 raek: ohpauleez: I looked at your atom-mapper code, but I could find in the clojure docs that extend-type takes doc strings

16:55 ohpauleez: ahh, I didn't even think of that. Thanks raek . Let me try that out

16:56 mattrepl: is there a simple way to get the source path for where a namespace is defined on the class path?

16:58 ohpauleez: raek: That was it

17:01 raek: defprotocol takes docstrings though... (and is where (doc someprotocol-method) takes the docs from)

17:02 ohpauleez: I see that now, thanks!

17:03 raek: np :)

17:17 vIkSiT: wow, this place has *grown* in a month :)

17:26 bhenry: okay so query params come in as either a string or a vector. how can i idiomatically make a one item vector of the string when there is only one? i.e. (something string-or-vec) returns vector of string(s)

17:26 do i have to do a conditional to check if it's a vector or string and act accordingly?

17:27 gfrlog: ,(vector? [123])

17:27 clojurebot: true

17:27 gfrlog: ,(string? "haha)

17:27 clojurebot: EOF while reading string

17:28 raek: are you talking about ring? in that case, when do you get query params as a vector?

17:28 gfrlog: ,(string? "haha")

17:28 clojurebot: true

17:28 * rhickey got clojure and its tests to run with rebinding of non-explicitly-dynamic vars disallowed

17:29 bhenry: if the same param is used twice like opt=1&opt=2

17:29 opt comes in as ["1" "2"]

17:29 amalloy: ,(let [x "x"] (or (vector? x) [x]))

17:29 clojurebot: ["x"]

17:29 amalloy: oh that won't work :P

17:30 raek: ah, didn't know that ring.middleware.params/wrap-params could do that...

17:30 bhenry: raek i was surprised too, but i want to use it to my advantage

17:31 raek: ,(letfn [(vectorize [x] (if (vector? x) x [x]))] [(vectorize 1) (vectorize [1 2])])

17:31 clojurebot: [[1] [1 2]]

17:31 gfrlog: ,(doc letfn)

17:31 clojurebot: "([fnspecs & body]); Takes a vector of function specs and a body, and generates a set of bindings of functions to their names. All of the names are available in all of the definitions of the functions, as well as the body. fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+)"

17:32 gfrlog: clojure documentation does _not_ talk down to you

17:32 raek: yes, it feels a bit odd that r.m.p/assoc-param need to check whether the param is a vector in order to add more elements, and that the user then needs to check whether it is a vector again in order to use it...

17:32 :/

17:34 maybe this would have been better if it was split into two different wrap-params middlewares

17:36 to have an as simple as possible "data contract" (what the stuff that goes in and out of functions looks like), is essential in Clojure, IMHO

17:40 ohpauleez: ~seen stuartsierra

17:40 clojurebot: stuartsierra was last seen parting #clojure, 212 minutes ago

17:46 gfrlog: ,(format "%d hours, %d minutes" (quot 212 60) (rem 212 60))

17:46 clojurebot: "3 hours, 32 minutes"

18:06 ohpauleez: _fogus_: ping

18:07 raek: When speaking only in tautologies, you have to state facts, but also don't, or don't.

18:13 amalloy: ,((juxt quot rem) 212 60) ; <== gfrlog

18:13 clojurebot: [3 32]

18:13 gfrlog: ,(doc juxt)

18:13 clojurebot: "([f] [f g] [f g h] [f g h & fs]); Alpha - name subject to change. Takes a set of functions and returns a fn that is the juxtaposition of those fns. The returned fn takes a variable number of args, and returns a vector containing the result of applying each fn to the args (left-to-right). ((juxt a b c) x) => [(a x) (b x) (c x)]"

18:14 gfrlog: amalloy: awesome

18:14 there's no excuse for repetition

18:14 amalloy: juxt is a great trick. ever since i saw raek use it for the first time, i try to find juxt in every problem i solve :P

18:15 gfrlog: hmmmm

18:15 ,((juxt juxt juxt) juxt juxt)

18:15 clojurebot: [#<core$juxt$fn__3657 clojure.core$juxt$fn__3657@d1ea84> #<core$juxt$fn__3657 clojure.core$juxt$fn__3657@17baeb1>]

18:15 amalloy: lol

18:15 gfrlog: solved that problem

18:15 amalloy: ,((comp (juxt juxt juxt) juxt) juxt juxt)

18:16 clojurebot: [#<core$juxt$fn__3655 clojure.core$juxt$fn__3655@b56813> #<core$juxt$fn__3655 clojure.core$juxt$fn__3655@1c3c0fd>]

18:16 gfrlog: so much abstraction the poor JVM is going through and all we get are some hex codes

18:16 amalloy: a good lesson: everything is bits, eventually

18:16 raek: amalloy: :)

18:17 gfrlog: it'd be fun to have a program that takes a java object and creates a graph of the nested objects all the way down to primitives

18:17 I guess that's not necessarily acyclic though :(

18:17 raek: amalloy: (btw, what did I use juxt for that time?)

18:19 amalloy: raek: awww, i just looked at my logs and it was actually jkkramer; you told him how beautiful it was

18:19 ,(map (juxt first count) (partition-by identity [:a :a :a :b :b :c :d :d]))

18:19 clojurebot: ([:a 3] [:b 2] [:c 1] [:d 2])

18:20 raek: ah, yes... that one is really neat

18:20 gfrlog: ,(partition-by identity [:a :a :b :b :c :d :d])

18:20 clojurebot: ((:a :a) (:b :b) (:c) (:d :d))

18:20 Derander: ,(partition-by identity [:a :a :a :b :b :c :d :d])

18:20 clojurebot: ((:a :a :a) (:b :b) (:c) (:d :d))

18:20 Derander: lol.

18:20 ,(count (partition-by identity [:a :a :a :b :b :c :d :d]))

18:20 clojurebot: 4

18:21 gfrlog: ,(+ 4 12)

18:21 clojurebot: 16

18:21 Derander: ,(pow 4 12)

18:21 clojurebot: java.lang.Exception: Unable to resolve symbol: pow in this context

18:21 gfrlog: computers know the darndest things

18:21 ,(#(% %) #(% %))

18:21 clojurebot: java.lang.StackOverflowError

18:22 Derander: okay, so guids collide sometimes. Why can't one prefix a guid with the originating computer's name to avoid collisions?

18:22 gfrlog: some uuid schemes use that

18:22 Derander: is there a downside?

18:22 gfrlog: security I think

18:22 at least for a general implementation

18:22 Derander: because someone knows where something comes from?

18:22 gfrlog: yeah

18:22 Derander: oh, I don't give a rats ass about that

18:23 gfrlog: then you're probably fine

18:23 Derander: just writing a sync engine between my desktop & laptop. okay.

18:23 thanks. I was wondering if I'd gone insane and was missing something

18:23 gfrlog: I doubt you have to worry about collisions though

18:23 Derander: gfrlog: "In the OSF-specified algorithm for generating new (V1) GUIDs, the user's network card MAC address is used as a base for the last group of GUID digits, which means, for example, that a document can be tracked back to the computer that created it. This privacy hole was used when locating the creator of the Melissa worm[2]. Most of the other digits are based on the time while generating the GUID."

18:24 sorry for wall of text, but apparently that is basically what is done already

18:24 gfrlog: that's on wiki? that's where I read it

18:24 Derander: mmhm

18:24 gfrlog: I thought it said there were newer versions though

18:24 amalloy: Derander: yes, but there are a lot of other GUID/UUID types than v1. as it happens v1 is back in vogue now that cassandra uses them, but for quite a while they were out of fashion

18:25 Derander: yeah, I've never read anything but hate about guids in general

18:25 amalloy: v3 and v5 especially, for some reason

18:25 Derander: when they seem like a decent solution to a common problem

18:25 gfrlog: we should namespace guids

18:26 amalloy: ,(in-ns guids) ; this is gonna fail :(

18:26 clojurebot: java.lang.Exception: Unable to resolve symbol: guids in this context

18:26 amalloy: ,(ns guids) ; this is gonna fail :(

18:26 clojurebot: nil

18:26 amalloy: really?

18:26 gfrlog: what's the guids ns?

18:27 amalloy: ,(do (ns guids) *ns*)

18:27 clojurebot: #<Namespace guids>

18:27 amalloy: gfrlog: i dunno

18:27 just made it up

18:27 ,(do (ns guiasfdsds) *ns*)

18:27 clojurebot: #<Namespace guiasfdsds>

18:27 gfrlog: that's the easiest way to write code ever

18:28 arrummzen: How do I test for inequality in clojure?

18:28 amalloy: ,(not= 1 4)

18:28 clojurebot: true

18:28 arrummzen: =)

18:29 gfrlog: ,(if (zero? (- 1 4)) true false)

18:29 clojurebot: false

18:29 gfrlog: whoops backwards

18:29 that one always trips me up

18:29 amalloy: ,(not (zero? (- 1 4)))

18:29 clojurebot: true

18:30 amalloy: gfrlog: (if a true false) is a sin

18:30 gfrlog: lol

18:30 amalloy: ,(boolean 'a)

18:30 clojurebot: true

18:30 gfrlog: I was about to ask if that exists

18:30 in other languages you can use !!

18:30 amalloy: <== always one step ahead

18:30 gfrlog: which is fun

18:31 amalloy: try it in java :P

18:32 gfrlog: oh gross

18:32 but here goes

18:32 amalloy: ,(nth (iterate not 'a) 3)

18:32 clojurebot: false

18:32 gfrlog: !(ob==null || ob == false)

18:32 amalloy: ,(tale 5 (iterate not 'a))

18:32 clojurebot: java.lang.Exception: Unable to resolve symbol: tale in this context

18:32 amalloy: ,(take 5 (iterate not 'a))

18:32 gfrlog: that probably wouldn't compile

18:32 clojurebot: (a false true false true)

18:33 gfrlog: lol

18:33 why doesn't clojure have an eval-java function?

18:33 amalloy: gfrlog: it would compile if obj were a Boolean, i think

18:34 gfrlog: yeah

18:34 amalloy: ,(not (or (nil? Boolean/TRUE) (false? Boolean/TRUE)))

18:34 clojurebot: true

18:35 _ulises: evening folk

18:35 gfrlog: ,(= Boolean/TRUE true)

18:35 clojurebot: true

18:35 amalloy: ,(if (Boolean. "true") 1 2)

18:35 clojurebot: 1

18:36 amalloy: ,(if (Boolean. "false") 1 2)

18:36 clojurebot: 1

18:37 gfrlog: (println "DENIED")

18:37 dang comma

18:37 Derander: ,(println "DENIED")

18:37 clojurebot: DENIED

18:38 amalloy: ,(or (def x 1) (println 'DENIED))

18:38 clojurebot: DENIED

18:38 gfrlog: omg did it work?

18:38 amalloy: lol no

18:38 bmh: What's the correct way to turn a primitive matrix (i.e. int[][]) into a clojure collection?

18:38 Derander: no one knows

18:38 gfrlog: :)

18:38 amalloy: ,(seq (byte-array 10))

18:38 clojurebot: (0 0 0 0 0 0 0 0 0 0)

18:39 bmh: amalloy: wrong direction

18:39 oh

18:39 seq

18:39 gfrlog: ,(short-array 10)

18:39 clojurebot: #<short[] [S@f51f3b>

18:39 amalloy: ,(map seq (seq (make-array Integer/TYPE 3 3)))

18:39 clojurebot: ((0 0 0) (0 0 0) (0 0 0))

18:39 gfrlog: primitives are fun

18:40 kmc: i asked this before, but don't recall an answer; sorry if i missed it or something

18:40 how lightweight are Clojure threads?

18:40 gfrlog: I think they are java threads

18:41 kmc: ok

18:41 how lightweight are Java threads? ;)

18:41 gfrlog: dunno :)

18:41 they're not erlang I don't think

18:41 amalloy: not very

18:41 kmc: ok

18:41 so i can't spawn 100,000 of them?

18:42 amalloy: bad idea; maybe possible

18:42 gfrlog: time for erlang!

18:42 kmc: or ghc haskell

18:42 new IO manager in GHC 7.0 too

18:42 amalloy: ,(for [_ 10] (java.lang.Thread.))

18:42 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer

18:43 amalloy: ,(for [_ (range 10)] (java.lang.Thread.))

18:43 clojurebot: (#<Thread Thread[Thread-1979,5,main]> #<Thread Thread[Thread-1980,5,main]> #<Thread Thread[Thread-1981,5,main]> #<Thread Thread[Thread-1982,5,main]> #<Thread Thread[Thread-1983,5,main]> #<Thread Thread[Thread-1984,5,main]> #<Thread Thread[Thread-1985,5,main]> #<Thread Thread[Thread-1986,5,main]> #<Thread Thread[Thread-1987,5,main]> #<Thread Thread[Thread-1988,5,main]>)

18:43 gfrlog: (conj todo-list "port clojure to erlang" "learn haskell")

18:43 raek: kmc: clojure uses java's executor framework for agents and futures

18:43 Derander: amalloy: is it slightly dangerous that we can spawn threads on clojurebot?

18:44 raek: kmc: which means that all actions sent to agents with 'send' is handler by a fixed-size thread pool

18:44 amalloy: yes; it's a possible security hole we found last night

18:44 Derander: fuuuuuuun

18:44 amalloy: ,(for [_ (range 10)] (Thread.))

18:44 clojurebot: (#<Thread Thread[Thread-1990,5,main]> #<Thread Thread[Thread-1991,5,main]> #<Thread Thread[Thread-1992,5,main]> #<Thread Thread[Thread-1993,5,main]> #<Thread Thread[Thread-1994,5,main]> #<Thread Thread[Thread-1995,5,main]> #<Thread Thread[Thread-1996,5,main]> #<Thread Thread[Thread-1997,5,main]> #<Thread Thread[Thread-1998,5,main]> #<Thread Thread[Thread-1999,5,main]>)

18:44 kmc: cool raek

18:44 amalloy: oh. that didn't work before. i think raek blew up more of his security

18:45 gfrlog: ,(Thread. (partial println "haha"))

18:45 clojurebot: #<Thread Thread[Thread-2001,5,main]>

18:45 kmc: when you call (Thread.) with no argument like that, what thread does it actually spawn?

18:45 _ulises: hey all, I have a bit of an odd request: I am looking for a mentor to improve my knowledge of Clojure and functional programming (amongst other things) so if anybody is interested/up to the task, please take a look at http://pastebin.com/rn4h8Tk1 and let me know your thoughts :)

18:45 Derander: (Thread.)

18:45 ,(Thread.)

18:45 clojurebot: #<Thread Thread[Thread-2003,5,main]>

18:45 amalloy: threads don't do anything until you call .start

18:45 so these threads, i think, just get GCed immediately

18:46 Derander: ,(.start (Thread.))

18:46 clojurebot: nil

18:46 Derander: ,(.start (Thread. (partial println "hi")))

18:46 clojurebot: nil

18:47 gfrlog: the println is apparently invisible either way

18:48 amalloy: background threads don't have access to the terminal

18:48 iirc

18:48 raek: ,(.start (Thread. (bound-fn [] (println "hi"))))

18:48 clojurebot: nil

18:48 raek: the *out* binding is thread-local

18:48 amalloy: ,(doc bound-fn)

18:48 clojurebot: "([& fntail]); Returns a function defined by the given fntail, which will install the same bindings in effect as in the thread at the time bound-fn was called. This may be used to define a helper function which runs on a different thread, but needs the same bindings in place."

18:49 raek: that's why prints in other threads don't print in the slime repl in emacs

18:49 gfrlog: ,(.start (Thread. (.println System/out "okay")))

18:49 clojurebot: nil

18:49 raek: new thread gets the root binding of *out*, which is System/out

18:49 gfrlog: ,(.println System/out "then why don't they work?")

18:49 clojurebot: nil

18:50 amalloy: raek: but even in a repl println from a separate thread doesn't work

18:50 gfrlog: it gets blocked?

18:50 raek: ,(let [out *out*] (.start (Thread. (binding [*out* out] (println "hi")))))

18:50 clojurebot: hi

18:50 amalloy: oh, nice

18:51 raek: you can also do (alter-var-root #'*out* (constantly *out*)) to set the root binding of *out* to the one in the current thread

18:51 gfrlog: raek: is your *out* special in clojurebot, or also System/out?

18:52 amalloy: ,(let [out *out*] (.start (Thread. (binding [*out* out] (dotimes [n 10] (. java.lang.Thread sleep 5000) (println n))))))) ; does this timeout?

18:52 clojurebot: Execution Timed Out

18:52 raek: I don't know how clojurebot is implemented, but I believe *out* is bound to a fn that sends messages over IRC

18:52 *bound to a writer

18:53 gfrlog: oh, I mistakenly inferred you wrote it from some previous comment I've forgotten

18:53 amalloy: raek: i don't think it can be that simple, or my println would write at least once

18:53 raek: I write bots, but not clojurebot :)

18:53 clojurebot is hiredman's bot

18:54 amalloy: clojurebot: author?

18:54 clojurebot: Pardon?

18:54 amalloy: clojurebot: author is hiredman

18:54 clojurebot: Ack. Ack.

18:54 gfrlog: clojurebot: Pardon?

18:54 clojurebot: Huh?

18:54 gfrlog: clojurebot: Huh?

18:54 clojurebot: excusez-moi

18:54 rlb: Are there ways other than compile to make 1.2 startup much faster?

18:54 amalloy: clojurebot: source?

18:54 clojurebot: source is http://github.com/hiredman/clojurebot/tree/master

18:55 raek: anyway, println prints to whatever is in *out*. the default root binding of *out* is System/out wrapped in a PrintWriter.

18:55 amalloy: clojurebot: cake?

18:55 clojurebot: cheesecake is delicious.

18:55 amalloy: damn it. he won't remember when i tell him about cake

18:55 rlb: try cake

18:57 raek: http://github.com/hiredman/clojurebot/blob/master/src/hiredman/sandbox.clj#L123

19:00 rlb: amalloy: thanks, I know it might also be possible to use something like nailgun, but in this case I'm interested in speeding up standalone executable time.

19:01 amalloy: rlb, you could start the jvm in -client mode, but that won't make a very big difference. java is not a fast-startup language, and clojure is another layer on top of it

19:01 gfrlog: irb starts pretty fast -- maybe implement clojure in ruby

19:06 rlb: amalloy: right, client doesn't really help. An empty java program runs in about 0.1s here, a compiled empty clojure program, about 0.9s, so about 9x slower, and pushing a notable threshold wrt command-line interactivity.

19:07 I was just trying to determine if it might be feasible to use clojure for some command-line tools that needed to be fairly fast.

19:07 gfrlog: is the Integer constructor the preferred way to convert string to int?

19:08 rlb: gfrlog: that's reasonable.

19:09 plathrop: ,(contains? [:plathrop :foo :bar] :plathrop)

19:09 clojurebot: false

19:09 plathrop: What am I missing here about contains? I'd expect a true.

19:10 ohpauleez: plathrop: use some

19:10 plathrop: ,(some [:plathrop :foo :bar] :plathrop)

19:10 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Keyword

19:10 ohpauleez: (some #{"a"} ["a" "b" "c"])

19:10 raek: plathrop: contains? checks for keys. in arrays, the indicies are the keys

19:10 ohpauleez: ,(some #{"a"} ["a" "b" "c"])

19:10 clojurebot: "a"

19:10 ohpauleez: ,(some #{"d"} ["a" "b" "c"])

19:10 clojurebot: nil

19:11 plathrop: raek: ah, thanks for the explanation

19:11 raek: plathrop: either use sets (if you check whether an element is there more that once) or 'some'

19:11 ,(contains? #{"a" "b" "c"} "a")

19:11 clojurebot: true

19:12 raek: sets have constant time* membership tests

19:12 plathrop: I think sets is what I want. Thanks folks!

19:13 raek: ,[(#{"a" "b" "c"} "a") (#{"a" "b" "c"} "d")]

19:13 clojurebot: ["a" nil]

19:13 raek: also, you can use the set as a predicate directly, unless nil can appear in the set

19:33 Derander: 1.5 hours until weekend

19:33 I have never been more excited to get home and fire up emacs

19:33 amalloy: Derander: you need to get home to fire up emacs? they don't have ssh at your place of business?

19:33 Derander: oh, I'm working in emacs on a laptop

19:34 it's just that I'm not working on my own programs :-)

19:34 I'm @ work right now.

19:34 amalloy: well, just work on them secretly

19:34 Derander: there is a thought

19:34 amalloy: or while your actual work "compiles"

19:34 Derander: if only ruby compiled

19:35 amalloy: http://xkcd.com/303/

19:35 Derander: I only get to pull that excuse when I'm installing some library

19:35 that has c extensions

19:41 amalloy: Derander: you could recompile ruby. the latest version is much better

19:41 Derander: yeah, unfortunately I've already got 1.9.2 running :-(

19:53 bmh: is it possible to list two licenses in project.clj in a lein project?

19:59 maravillas: bmh: check out http://github.com/technomancy/leiningen/blob/master/sample.project.clj

19:59 the comment above the :license entry says :licenses is supported

19:59 bmh: maravillas: I did see that, but it doesn't have a use case. If I specify more than one :name it will explode

20:02 amalloy: bmh: i'd guess it's like: :licenses [{:name foo} {:name bar}]

20:02 maravillas: did you try :licenses [{:name ...} {:name ...}] ?

20:02 bmh: that sounds like a reasonable thing to try

20:02 maravillas: looks like lein pom just concats :licenses, :licences, and the single :license entry

20:03 single :license and :licence entries, that is

20:04 bmh: hooray

20:04 amalloy: maravillas: haha, so you don't need to use :licenses if you have two? you can use licenses and licences

20:04 er. but without any Ss

20:05 maravillas: yeah, seems to be aware of both spellings :)

20:05 http://github.com/technomancy/leiningen/blob/master/src/leiningen/util/maven.clj#L224

20:06 bmh: maravillas: very deferential to the Commonwealth, I suppose

20:08 technomancy: heh; nice. (that wasn't me)

20:08 * maravillas is digging to find out who it was...

20:10 maravillas: looks like michal marczyk

20:13 yayitswei: has anyone deployed a clojure webapp with nginx and can give me some pointers?

20:14 or if not that, a recommendation for the simplest way to deploy a web app

20:16 Raynes: yayitswei: In the simplest case, a simple proxy_pass will do the trick. I've had success with this: http://gist.github.com/629193

20:16 I'd stick around and help more, but I've got to take off. Good luck. <3

20:16 yayitswei: thanks Raynes

20:19 jeff__: hi all. i'm looking for some advice. what would be the most idiomatic way of processing a very long list/array of numeric data returning a result. the result itself is a bunch of different calculations, some of which are scalars and others are themselves lists. what i'm doing for now is (reduce my-function initial-state) where initial-state is a map which gets new values assoc'ed in my-funtion as appropriate. is this a good way to do

20:19 this?

20:19 clojurebot: this is not a bug

20:21 jeff__: actually, it's more like: (reduce my-function initial-state my-list-of-numeric-data)

20:40 _rata_: is there any problem to have a ref containing a vector of refs? (but the later aren't mutated)

20:45 quotemstr: Has anyone here worked with JUNG from Clojure? I want to write a program that manipulates a graph and makes a movie out of it, and Java has all the good libraries.

20:59 nollidj: at the slime repl, is there a way to break a running command and jump into a debugging mode?

21:00 i am wishing i had something like the integration gdb has with emacs, so that i can step ahead, examine the local environment, go up and down the stack, etc, within a running program

21:01 is there a way to get slime to do that?

21:02 * nollidj supposes everyone is elsewhere on a friday night

21:03 bhenry: nollidj: http://hugoduncan.org/post/2010/swank_clojure_gets_a_break_with_the_local_environment.xhtml

21:04 quotemstr: Awesome!

21:04 #!/usr/bin/clj works as expected!

21:04 Is there a performance penalty for doing that?

21:05 nollidj: bhenry: thanks. it's encouraging that some work is being done, but blegh. i hope this makes it into swank-clojure

21:05 so, is it true that atm there is no way within just emacs/slime/swank-clojure to set a breakpoint?

21:05 bhenry: it is.

21:06 if you're using swank clojure you should be able to put (swank.core/break) somewhere in your code

21:06 nollidj: thanks for the info. i'll see what debug-repl can do

21:07 ah, my problem is that somewhere in the program things just stall (cpu usage drops to 0%, memory allocation stops)

21:07 ordinarily, i'd send it a signal while running it in a debugger and step it forward to see what's going on

21:07 i will continue to sprinkle printlns or maybe some clojure.core/breaks

21:07 bhenry: oh i see. not sure how to go about that

21:07 nollidj: er, swank.core

21:07 thanks for debug-repl, though

21:08 bhenry: the article is about how that functionality from debug-repl is now in swank-clojure

21:09 nollidj: oh, that is good

22:26 dpritchett: evening

22:27 mabes: hello

22:30 jsanda: can someone show me an example of using the map fn on a map. i'm struggling a bit with how to do this

22:32 dpritchett: C-c M-p is supposed to load the namespace under my cursor into slime, right?

22:32 mabes: ,(map (fn [[k v]] [(str k) (inc v)]) {:foo 12 :bar 34})

22:32 clojurebot: ([":foo" 13] [":bar" 35])

22:33 mabes: jsanda: ^ destructuring the k,v is what you need to do

22:33 jsanda: that's what i'm struggling with

22:33 mabes: thx for the example

22:33 that helps

22:33 mabes: and if you need it to be a map you can use into

22:33 ,(into {} (map (fn [[k v]] [(str k) (inc v)]) {:foo 12 :bar 34}))

22:33 clojurebot: {":foo" 13, ":bar" 35}

22:37 Raynes: It might be cleaner to use for if you need to destructure something: (into {} (for [[k v] {:foo 12 :bar 34}] [(str k) (inc v)]))

22:38 mabes: yeah, good point

22:43 jsanda: Raynes: that does seem a bit more intuituve

22:43 thx for both examples

23:09 cemerick: Raynes: how's life lately? :-)

23:09 Raynes: cemerick: Fantastic. The excitement continues to build.

23:10 cemerick: good, good

23:11 Raynes: Yours? :>

23:11 cemerick: Hectic. Ever so slightly unpleasant, but hopefully that's temporary.

23:23 * dpritchett googles some more on how to get syntax highlighting in swank-clojure

23:29 bhenry: dpritchett: my slime repl using swank-clojure has the same highlighting as any of my clojure buffers. i didn't have to do anything special

23:29 just used emacs starter kit and elpa

23:30 dpritchett: i dont have the starter kit

23:30 i guess i could nuke everything and start over

23:30 but i'll miss my toolbars

23:30 rdsr: ,(partition 3 [1 2])

23:30 clojurebot: ()

23:31 rdsr: isn't this behaviour a little wierd?

23:31 mabes: ,(partition-all 3 [1 2])

23:31 clojurebot: ((1 2))

23:31 rdsr: oops I'm using the wrong fn

23:31 thnks mabes :)

23:31 mabes: rdsr: np, I knew exactly where you were going ;)

23:32 rdsr: hehe

23:32 _rata_: dpritchett, isn't it clojure-mode what you need?

23:33 dpritchett: clojure-mode doesn't work with the repl... bhenry seems to be right though

23:34 bhenry: dpritchett, there's got to be some hook out there

23:35 dpritchett: it's fine, i didnt' have much in my .emacs.d folder

23:35 so i'm rebuilding it

23:35 for the 3rd time today :)

23:35 technomancy: it's not in the starter kit

23:39 dpritchett: so technomancy do you have good highlighting in your swank repl?

23:39 technomancy: I do not

23:39 thats' how I know it's not in the starter kit =)

23:39 dpritchett: man

23:40 bhenry: dpritchett: apparently i'm retarded. i just checked and i don't either. my bad.

23:40 technomancy: (add-hook 'slime-repl-mode-hook 'clojure-mode-font-lock-setup) ;; there's the trick

23:40 makes the prompt non-highlighted though, which is too bad

23:40 still nice

23:40 I should put that in the readme

23:41 mabes: ahh, clojure-mode-font-lock-setup.. didn't think about that... I had only tried the major mode which didn't work out too well as you could imagine

23:41 dbleyl: hello

23:41 technomancy: would be more complicated if you still want to use slime with CL

23:41 dpritchett: clojure is my only slimy language at the moment

23:41 so i add that line to the end of init.el i guess?

23:41 technomancy: apparently there are still some greybeards who care about that; I'll let them come up with a form that works for it.

23:41 ja

23:41 dpritchett: i just evaled it in my scratch buffer and nothing looks different

23:42 technomancy: you'd have to reconnect for it to take effect

23:43 Derander: it took me far too long to learn about c-m-x.

23:43 far too many keystrokes wasted moving to the end of the top level sexp and then c-x'ing

23:43 dbleyl: Is there any way to influence the compiled java output of :gen-class? Trying to interop with a Java lib that expects a run method to be discovered thru reflection.

23:46 bhenry: technomancy: with that line my emacs loads up fine but then when i connect to swank i get an error in process filter about the font-lock part

23:47 dpritchett: looking much better now thanks technomancy and bhenry

23:47 bhenry: okay so i guess it worked for dpritchett, so i'm wondering what i did wrong

23:48 dpritchett: well i have a fresh install of the starter kit for one :D

23:48 and then i added the line phil mentioned to ~/.emacs.d/init.el at the end

23:49 bhenry: i added to the end of my .emacs.d/bhenry/init.el so ...

23:49 hmph

23:49 i guess since my brain falsely remembered having syntax highlighting in the repl it wasn't much of an issue for me to begin with

Logging service provided by n01se.net