#clojure log - Feb 15 2009

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

0:00 WizardofWestmarc: already tried type hinting I assume?

0:00 gnuvince_: WizardofWestmarc: it's everywhere.

0:01 I can process about a thousand files in less than four minutes, but I'd be really happy if I could bring that number down some more.

0:01 WizardofWestmarc: what sort of processing?

0:01 gnuvince_: http://github.com/gnuvince/clj-starcraft/tree/master

0:02 unpacking and decoding Starcraft replay files.

0:02 WizardofWestmarc: ah ha

0:02 how complicated is the sc files? I know at their core it's about time and commands entered by the players

0:04 gnuvince_: The format is a rather simple one, but it's packed, and that's a mess to unpack. Fortunately, a gentleman already wrote an unpacker in Java :)

0:04 The rest is basically just reading bytes and associating actions to players

0:05 ayrnieu: gnuvince - where do you get starcraft save files, to test on?

0:05 gnuvince_: ayrnieu: http://www.teamliquid.net/replay/

0:05 ayrnieu: oh. 'starcraft replay files'.

0:05 WizardofWestmarc: was gonna say, there are probably 10s to 100s of thousands of replay files on the 'net

0:06 gnuvince_: yeah

0:06 WizardofWestmarc: are you gathering statisticial info from them or purely a case of "this is cool!"?

0:07 gnuvince_: WizardofWestmarc: there is a tool for Windows called "bwchart" that gives you information and stats on the games you played

0:07 How many units were produced, your actions-per-minute rate, etc.

0:07 WizardofWestmarc: right

0:07 gnuvince_: But it's Windows only and requires an installation of Brood War

0:07 WizardofWestmarc: ah ha, ties into the player in windows

0:08 err in the game

0:08 gnuvince_: I would like to make a mini clone that would be cross platform and have no dependencies on Brood War itself.

0:08 WizardofWestmarc: ...which is just the engine >_>

0:08 makes sense

0:08 gnuvince_: The real goal is to teach me some Clojure and Java.

0:08 WizardofWestmarc: well of course

0:08 doesn't mean it can't have other uses as well ;-)

0:08 gnuvince_: But the side effect is nice enough to keep me going.

0:08 Of crouse

0:08 course*

0:09 WizardofWestmarc: I just wish the lib someone in here pointed me to had decent documentation (a java lib not a clojure one)

0:09 it looks interesting for what I'm messing with, but I can't find good docs, a few "ok" blog posts but that's it (openNLP if you're wondering)

0:09 gnuvince_: Well, time to head to bed

0:10 Good night gents'

0:10 WizardofWestmarc: later \m/

3:22 Lau_of_DK: Top of the morning gents

3:23 Raynes: Good morning old chap. ;)

3:23 Lau_of_DK: Mr. Raynes - What a pleasant surprise :)

3:24 Raynes: :p

3:32 tkadlubo: Morning, hope the weather is good wherever you live. I want to filter a define a lazy sequence by filtering another lazy sequence. Can I consume beginning of the generated sequence in the filtering predicate?

3:32 Lau_of_DK: I think so, but can you paste an example?

3:32 tkadlubo: Arrr, s/want to filter a/want to/

3:36 I mean specifically Erastotenes' sieve. Something like (def primes (filter prime? (range 2 limit))) where prime? predicate uses primes sequence.

3:36 Lau_of_DK: Yes that would return a lazy seq

3:37 tkadlubo: That's good. Thanks.

3:37 Lau_of_DK: np

3:37 ,(filter even? (range 2 10))

3:37 clojurebot: (2 4 6 8)

3:37 Lau_of_DK: If youre in emacs, you can do that directly in the REPL - Dunno how comfortable you are with the IDE yet :)

5:07 te: Anyone know anyone hiring clojure programmers?

5:12 Lau_of_DK: Anyone seen this before? java.lang.NoClassDefFoundError: clojure/lang/AFunction (iwish.clj:0)

5:12 [Thrown class clojure.lang.Compiler$CompilerException]

5:20 te: How hard would it be to implement something like TryRuby in clojure

5:21 Lau_of_DK: Ask Chouser, he already did it: http://clojurescript.n01se.net/repl/

5:26 Raynes: It seems that when it comes to writing something in Clojure, all you do is think about it and it's done.

5:26 It's magically.

5:26 magical*

5:26 Now, why in the hell didn't God write the universe in LISP. :|

5:27 vha4: god?

5:27 lisp?

5:38 Raynes: ,(interleave (take 10 (iterate inc 1)) (repeat 3))

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

5:39 Raynes: What happens if you make an infinite sequence. Clojurebot stops that right? >_>

5:45 Lau_of_DK: ,(println (iterate inc 0))

5:45 clojurebot: java.lang.OutOfMemoryError: Java heap space

5:45 Lau_of_DK: ,(loop [] (recur))

5:45 clojurebot: Execution Timed Out

5:45 Lau_of_DK: Yea he seems to be pretty robust

5:45 Raynes: :|

5:50 tkadlubo: Maybe garbage collector tuning methods weren't sandboxed away...

6:19 angol: hi! Is anyone here? Is there a downloadable documentation? I like programming outside the house/office. hence no internet connection? any help would be appreciated.

6:23 Raynes: There should be. :|

6:29 Lau_of_DK: When Clojure boorks because it says ClassNotFound clojure.lang.AFunction - whats the problem ?

6:30 cgrand: Lau_of_DK: did you try to clean and rebuild clojure?

6:31 Lau_of_DK: Thats actually what caused the problem - I was trying to get some interactive Compojure development going, but technomancys .el files didnt work, they gave some other obscure error whenever I tried to require something, so I updated, and now this @ cgrand

6:32 cgrand: at which point did you get that exception (before getting to the REPL?)

6:35 Lau_of_DK: java -cp $classpath clojure.lang.Script app/boot.clj

6:35

6:35 The script defines the cp and then fires that

6:36 http://github.com/technomancy/concourse/blob/51afbc7b94692407cec98de24ae76b91a86d730a/app/boot.clj

6:36 Boot looks alot like that

6:36 leafw: angol: Stuart Halloway is about to publish a book on clojure. Also, you may use 'wget' on a shell as a spider, to download the entire clojure.org website. In addition, you have built-in the (doc <name>) and (find-doc "<name>") functions.

6:45 Lau_of_DK: Ive found a jar that works now, how can I check its revision ?

6:45 orero: is it just me or read-line is broken? I tried it interactively and it complains that LineNumberingPushbackReader cannot be cast to BufferedReader. what gives?

6:46 Lau_of_DK: orero: You tried it from slime?

6:47 orero: Lau_of_DK: I use clojure-mode. same thing as far as the repl goes.

6:47 Lau_of_DK: Not quite, inferior-lisp doesnt redirect *in* and *out*, but slime does

6:47 orero: Lau_of_DK: then what *in* and *out* point to in the inferior-lisp?

6:48 besides, if read-line doesn't work, why does read work?

6:49 Lau_of_DK: (doc read)

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

6:49 Lau_of_DK: (doc read-line)

6:49 clojurebot: Reads the next line from stream that is the current value of *in* .; arglists ([])

6:50 Lau_of_DK: I cant say for sure

6:50 orero: I can't remember for sure, but I think some weeks ago read-line worked for me, so unless I'm confused....

6:51 Raynes: orero: If you are using Stu's version of Clojure included with the sample code, read-line is broken.

6:51 I had that same problem a week ago.

6:52 orero: Raynes, is it something new or ongoing?

6:52 I got the latest trunk.

6:52 Raynes: I don't know. I know it's broken, that's all I know. I mentioned it but no one answered so I just reverted back to the release version.

6:53 Maybe someone should bring this to Rich's attention?

6:53 orero: Raynes, in release it works?

6:53 Raynes: Yes.

6:53 Perfectly.

6:54 orero: Raynes, ok thanks. now that I know it's not me, I'll look into it. I thought it was just me doing something really stupid.

6:54 Raynes: No problem.

6:55 orero: Lau_of_DK: didn't you write ClojureQL?

6:55 Lau_of_DK: I did, together with Kotarak

6:56 orero: Lau_of_DK: I've just started looking into it. looks great. does it work with sqlite?

6:56 leafw: anybody can recall the webpage of the nice lib for pretty-printing clojure exceptions?

6:56 Lau_of_DK: orero: Up until now, we've ensured that everything worked with MySql, Postgresql and SQLite, without the user doing anything specific to make that happend, although from this point forward, I think we'll focus mostly on MySql, Post and Derby

6:57 The code however, will be very easy to modify, so if you want to do something specific for SQLite, you can do it and just send me the patch

6:58 orero: Lau_of_DK: ok. too bad you won't include sqlite. it's a sweet db.

6:59 Lau_of_DK: Its a toy primarily, derby takes the same principle a step further and has backing from the apache-foundation, so I think its a good move

6:59 Raynes: ,(list [2 3 4])

6:59 clojurebot: ([2 3 4])

6:59 Lau_of_DK: Im not saying though, that we wont have support for SQLite - You can do almost everything in SQLite as it is, Im just saying extending from here will come mostly through patches from good folk like yourself

6:59 Raynes: ,(set '(1 2 3))

6:59 clojurebot: #{1 2 3}

7:00 Raynes: Oh thats neat.

7:01 orero: Lau_of_DK: I haven't tried Derby yet. I've been using sqlite for quite some time because it was so simple and easy and was good for my needs.

7:02 Raynes: (doc str)

7:02 clojurebot: With no args, returns the empty string. With one arg x, returns x.toString(). (str nil) returns the empty string. With more than one arg, returns the concatenation of the str values of the args.; arglists ([] [x] [x & ys])

7:02 Lau_of_DK: orero: And Derby is basically the same, simple, easy and local. Its just more extended in terms of features, and as I recall its being developed upon quite heavily by Apache F.

7:02 Raynes: ,(str #{\n \o})

7:02 clojurebot: "#{\\n \\o}"

7:03 Raynes: ,(apply (str #{\n \o}))

7:03 clojurebot: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn

7:03 Raynes: (doc apply)

7:03 clojurebot: Applies fn f to the argument list formed by prepending args to argseq.; arglists ([f args* argseq])

7:03 orero: Lau_of_DK: I'll go take a look at it now. does clojureql works with it in the current version?

7:03 Lau_of_DK: Raynes: Could you please install Emacs and use the local repl? :)

7:03 orero: Yes, both SQLite and Derby

7:03 and Mysql and Postgresql, and in principle Oracle, though I havent tested

7:03 orero: Lau_of_DK: great

7:04 Raynes: I have the REPL in netbeans open, I'm sorry, didn't realize using Clojurebot was not allowed in here ;).

7:04 Lau_of_DK: If you didnt know you didnt know :)

7:05 Raynes: Someone should put up a Clojurebot in a dedicated channel.

7:06 Lau_of_DK: Raynes: Why? I have IRC in the right side buffer, and a Repl in the left side buffer... No need

7:06 Raynes: Then why have Clojurebot here?

7:06 Lau_of_DK: He's good for letting us keep up with the svn log, and for clearing up point in discussions

7:06 Raynes: Scratch that, all my suggestions have been disregarded so far, this one shall be no different. Forget it.

7:07 Lau_of_DK: Like, when you discuss for the 10.th time wether apply is lazy or not

7:07 (doc apply)

7:07 clojurebot: Applies fn f to the argument list formed by prepending args to argseq.; arglists ([f args* argseq])

7:07 Lau_of_DK: Oh Raynes, did I hurt your feelings? I didnt mean to

7:07 And if its any comfort, I think all my suggestions have been disregarded as well :)

7:08 Raynes: Somebody should at the very least write a list of rules for this channel.

7:08 And no, you didn't hurt my feelings.

7:13 Lau_of_DK: You can write a list of rules if you want :)

7:13 I dont really see the point though

7:14 Raynes: I do. So people would know the rules before breaking the invisible ones.

7:14 Lau_of_DK: When I ask you to cool it with clojurebot, thats not a rule, its just me asking you nicely

7:15 Raynes: It should be a rule, spamming with bots is one of the reasons why people make dedicated channels for bots, while still keeping them in the main channel.

7:16 People who want to use the bots extensively are diverted to the bot's channel.

7:16 But it doesn't really matter. This isn't my channel, and that isn't my bot :p

7:17 Also, I'm sorry if I come off too strong sometimes, when it sounds like I'm trying to be mean I'm really not.

7:18 Lau_of_DK: No I didnt take it that way at all

7:23 angol: thanks leafw

7:23 leafw: you guys sound like you have nothing else to do :)

7:24 Lau_of_DK: leafw: Thats not true - I have lots of interactive Compojure development to do - but I cant get it working!!

7:25 Raynes: leafw: I should be reading. But I can't seem to force myself to do it. I'm on teh sequences chapter.

7:26 leafw: Raynes: on Stuart's book? I loved it. I thought I knew clojure, but I learned quite a few things on every page corner.

7:26 Raynes: Yup.

7:27 It's the first book I haven't just pirated in over a year.

7:27 Well worth the money.

7:27 leafw: I couldn't sent my last reviews, the deadline was the 6th ... oh well, it stands quite nice as it is.

7:38 Lau_of_DK: In compojure, if I want a table with width: 100%, how do I output that?

7:43 I get no love

7:45 orero: we love you Lau. we just don't know. ;-)

7:48 Lau_of_DK: phew - that makes it all better :)

7:54 Man...

7:55 After some 5 hours I finally get interactive compojure development working...

7:55 Raynes: Success.

7:55 Lau_of_DK: Turns out clojure.jar and clojure-contrib.jar have to be the same revision due to some change in "includes" something...

8:02 (html [:table {:width "100%"} [:tr [:td "Hi there"]]])

8:02 And thats how its done

8:03 Man, I thought compojure was hard, but once I got Emacs involved, it became a kids game

8:03 (sponsored by the Gnu foundation)

9:25 tashafa: question...

9:26 any1 knows whats the easiest way to get a functions arguments as a seq (without using [& rest])?

9:35 Chousuke: What do you mean? :/

9:36 tkadlubo: tashafa: And what's wrong with [& rest]?

9:36 Chousuke: you mean have the args separate as well as in a seq?

9:36 map destructuring probably.

9:36 though I can *never* remember how that works...

9:38 blbrown: hope this come out right. Can I reference a function that hasn't been defined yet...in another namespace. E.g. if I am in the same namespace. (ns a1 (def abc)) ...where abc is defined in a2. (ns a2 (defn abc []) ... a2 is implemented after a1 is

9:38 I tried and I get this error. aused by: java.lang.Exception: Name conflict, can't def *styled-text* because namespace: octane.toolkit.octane_main_window refers to:#'octane.toolkit.public_objects/*styled-text*

9:41 Chousuke, see what I am saying?

9:42 tashafa: tkadlubo: I want to make sure the function can only recieve a certain number of arguments

9:43 Chousuke: blbrown: octane_main_window :uses public_objects, right?

9:44 blbrown: also: use hyphens in your namespace names instead of underscores. stylistic convention :)

9:44 blbrown: Chousuke yea, it is a cyclic dependcy thing I am trying to bypass

9:44 Chousuke: hmm

9:44 can't you use require instead?

9:44 blbrown: Chousuke, yea, I normally try to avoid underscores of the filenames because I work with older operating systems

9:44 Chousuke: and namespace-qualify the names.

9:45 blbrown: let me try that

9:46 I am not keeping all lisp code conventions. The lisp gods will just have to be mad at me

9:46 Chousuke: as long as you stay away from camelcase

9:47 blbrown: hehe

9:59 pilkarn: (not (empty? playlist)) == playlist ?

10:02 Chousuke: pilkarn: nah.

10:02 pilkarn: you playlist could be [], which is empty, but still "true"

10:02 pilkarn: ah maybe thats why i had used that not empty?

10:03 Chousuke: might be..

10:03 if your playlist were a seq, though, then it being empty would mean it's nil

10:04 so you could test for (if (seq playlist)) where seq ensures it's a sequence

10:17 aperotte: In trying to write a class for clojure, I ran up against a Java issue. If anyone has any insight, please help :). I have an Object[] array that I want to contain arrays of different types (could be primitive or objects). How do I access the elements of the nested array. It seems that the usual [][] notation doesn't deal well with this.

10:20 Chousuke: hm /:

10:20 it should work just fine in Java

10:21 aperotte: I get a compile error that says array required, but java.lang.Object found

10:21 I'll run a few more tests to make sure that's actually the problem.

10:36 Lau_of_DK: Hi all

10:38 aperotte: Hi Lau_of_DK

10:39 pilkarn: deos Java allow arrays of arrays with different types?

10:39 hihi lau

10:40 aperotte: Pilkarn: I can create it, by first creating an Object[]

10:40 then filling it with arrays of various types

10:41 I just can't get access to the elements once it's been filled (at least not in a convenient way)

10:43 pilkarn: ah ofc using object as type

10:44 post the code?

10:44 clojurebot: paste?

10:44 clojurebot: lisppaste8, url

10:44 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

10:44 cp2: aperotte arrays are objects in java so you should have no problem storing them in an Object[], however when you access you will need to cast

10:45 aperotte: ahh ... that's what I was afraid of

10:46 I wanted the code to be ignorant of the type of array inside ...

10:47 lisppaste8: aperotte pasted "heterogeneous arrays" at http://paste.lisp.org/display/75516

10:47 cp2: oh

10:47 i see what you mean

10:48 uhmm

10:48 Lau_of_DK: clojurebot: seen technomancy?

10:48 clojurebot: technomancy was last seen quiting IRC, 2304 minutes ago

10:48 cp2: i suppose you could do ((Object[]) Outer[0])[0]

10:48 although it might cry from trying to cast a primitive array to an object array

10:49 aperotte: exactly

10:49 it's important to me to be able to have primitive arrays

10:50 cp2: well, java has autoboxing for primitive types, so using arrays of Integer and such should work

10:50 but then again i dont know what you are trying to use it for

10:51 aperotte: sorry, I'm trying to write an n-dimensional array class

10:51 so it's important to be able to have unboxed primitive arrays

10:51 cp2: ah, i see

10:54 aperotte: hmm ... maybe it will work if I use one of the "collections" instead of the outer array

10:56 lisppaste8: sd pasted "compiling arraytets" at http://paste.lisp.org/display/75518

10:56 pilkarn: im no Java expert(dont know it very well) but ^^ compile,s isnt that how you need to do?

10:57 hmm o that prints 1

10:57 oh it should

10:57 aperotte: I think the problem is that the 1 it prints is a boxed 1 instead of a primitive one

10:58 pilkarn: but if you want an array of arrays you have do declare object[][] not object[] ?

10:58 or isnt that necessary

10:58 or i guess ut shouldnt be since object means of any right?

10:59 cp2: aperotte: try System.out.println(Outer[0][0].getClass().getName());

10:59 to see if its boxed

11:00 acutally, that might print out java.lang.Integer either way

11:00 pilkarn: dude it is when you index it

11:01 tashafa: let me phrase this differently...

11:01 pilkarn: i think you cant do [i][i] unless it is statically proved to be an array

11:02 blbrown: when you do :import with namespace, can you qualify the java import

11:02 E.g. (java.awt [Color :as AWTColor])

11:02 tashafa: is there a way to get the arguments of a current function (preferbly in a seq)?

11:03 blbrown: tashafa, have you looked at 'doc' not entirely what you want, but you might be able to look at the source for 'doc'

11:06 gnuvince_: electricity--

11:07 aperotte: pilkarn: I think you're right, I'll have to try another approach.

11:07 cp2: it prints java.lang.Integer, but says the variable cannot be dereferenced if it's a primitive

11:07 which seems to make sense

11:08 blbrown: clojure + jfreechart + swt = the awesome

11:08 tashafa: hmm this is not about documentation although i've looked there

11:10 I have a function that takes 2 arguments, I want to be able to get thes 2 arguments in a seq without expicilty using (defn function [val1 val2] (let [values [val1 val2] ...

11:10 surely theres a better way to do this...

11:11 :edit explicity using the let keyword

11:12 :edit expicitly

11:12 cant type today

11:13 explicitly*

11:13 gnuvince_: ,((fn [[x1 x2 :as xs]] [x1 x2 xs]) 3 4)

11:13 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--1576$fn

11:13 gnuvince_: ,((fn [[x1 x2 :as xs]] [x1 x2 xs]) [3 4])

11:13 clojurebot: [3 4 [3 4]]

11:14 tashafa: thanks!

11:14 gnuvince_: ,((fn [& [x1 x2 :as xs]] [x1 x2 xs]) 3 4)

11:14 clojurebot: [3 4 (3 4)]

11:14 gnuvince_: ,((fn [& [x1 x2 :as xs]] [x1 x2 xs]) 3 4 5)

11:14 clojurebot: [3 4 (3 4 5)]

11:18 tashafa: gnuvince_: hmm... but how would you ensure that fn only allowed for 2 arguments (i.e. throws illegalargument excpetion when fn arguements != 2)

11:19 thanks again

11:19 ,((fn [[x1 x2 :as xs]] [x1 x2 xs]) [3 4 5])

11:19 clojurebot: [3 4 [3 4 5]]

11:25 gnuvince_: tashafa: that's what I'm trying to figure out.

11:26 I'm unsure that you can do that.

11:28 tashafa: ah...its cool, your solution is close enough. I'm going to have to implement some kind of check somewhere else in the code. thanks!

11:31 gnuvince_: tashafa: I think it's more trouble than just having [x1 x2] personally

12:09 pilkarn: doesnt compile show any errors when it fails?

12:16 gnuvince_: Anyone know what the deal is with that wubbie person on the mailing lists?

12:21 pilkarn: whats it he synatx for requrie for not renaming?

12:21 (:require (progs.mp3player [utils :as utils]))

12:21 (:require (progs.mp3player.utils)) doesnt work and not (:require (progs.mp3player [utils]))

12:21 blbrown: gnuvince, there is a mailing list, hehe? you talking about the clojure/google group or a mailing list

12:26 gnuvince_: blbrown: The google group.

12:54 pilkarn: (:require (progs.mp3player.utils)) doesnt work and not (:require (progs.mp3player [utils]))

12:54 (:require (progs.mp3player [utils :as utils]))

12:54 how do you require normally without renaming?

12:56 Chousuke: (:require progs.mp3player.utils) or (:require progs.mp3player utils) iirc

12:56 oops, missing a set of parens from the latter :/

13:13 slashus2: Say I have a ref to a list of agents, what is the best way to alter the list of agents to add another agent?

13:13 durka42: in a transaction, you can use conj

13:14 slashus2: Okay, thank you.

13:14 durka42: adding to a list sounds like it might be a job for commute, although if order matters you would need alter

13:16 slashus2: I am trying to do something similar to the ant colony simulation that Rich Hickey showed in the concurrency presentation. I want to be able to add and destroy organisms (agents) on demand.

13:16 Using a ref to a list or vector of agents may not be the best way.

13:23 (dosync (alter a-few-refs conj ref)) just as an example, does not work.

13:23 a-few-refs is a vector of refs right now.

13:23 The error is that a PersistentVector cannot be cast to a Ref

13:25 ayrnieu: ,(let [(ref afr (list (ref 0) (ref 1) (ref 2)))] (dosync (alter afr conj (ref -1))) (map #(inc @%) @afr))

13:25 clojurebot: java.lang.IllegalArgumentException: let requires an even number of forms in binding vector

13:25 ayrnieu: ,(let [afr (ref (list (ref 0) (ref 1) (ref 2)))] (dosync (alter afr conj (ref -1))) (map #(inc @%) @afr))

13:25 clojurebot: (0 1 2 3)

13:25 ayrnieu: WFM.

13:26 slashus2: Okay, I figured it out, thank you.

13:27 One thing I didn't really take away from the talk, was the difference between send and send-off

13:28 ayrnieu: send uses a fixed-size thread pool, send-off uses an exandable pool.

13:29 agents are emphermeral: they only represent a thread when they're running in a function that someone has sent to them.

13:31 slashus2: In practice, I can keep using send-off to increase the amount of agents?

13:31 ayrnieu: the number of concurrently active agents, you mean.

13:32 Chouser: you can keep using send-off on more agents to increase the number of threads running

13:32 ayrnieu: creating an agent is just (agent 0) -- this doesn't task a thread pool.

13:32 Chouser: though as the agents complete, they free up threads such that further send-offs can reuse them

13:33 slashus2: When using send, I would not be able to keeping using send?

13:33 ayrnieu: so if you really wanted, you could create a hundred threads by firing off agents that just sleep for a few seconds.

13:34 the only difference between send and send-off is that send will not create a new thread if one is not available. The agent just won't run until one becomes available.

13:35 (also, the pool is fixed in size. Maybe you can increase it to some application-sensible size through Java.)

13:35 slashus2: OOOh so I can keep using send, but no more threads will be created than the amount that I first used send with?

13:35 ayrnieu: send's pool is determined by the number of processors (cores?) you have.

13:35 slashus2: Oh that is really neat.

13:36 Send-off just creates as many threads as agents that you send it, but send uses the number of threads equal to the amount of cores that you have?

13:37 ayrnieu: so, send-off creates a new thread if one isn't available.

13:37 s/so/no/.

13:37 it's still a thread *pool*, it still tries to reuse them.

13:38 slashus2: One isn't available includes when a thread is sleeping?

13:38 ayrnieu: and send's pool is not equal to the amount of cores that you have, it is determined by that amount. I think it's Processors+1.

13:40 I assume that sleeping threads are considered unavailable; I don't know if they are.

13:43 slashus2: In the ant colony simulation, when using send-off, it creates 49 threads for ants, because there are 49 agents. Those agents run until the program closes. So in that case, when using send-off on another agent, it would increase to 50 threads?

13:44 The reason I ask this, is because it doesn't seem to be working.

13:46 I am trying to do this mid simulation. I "modify" the list of ant agents by adding a new agent. I then send off that agent to behave(an agent function), but the ant does not seem to be behaving.

13:47 ayrnieu: what do you mean, those agents run until the program closes? You mean that you call send-off once for each agent and never have to do this again because the agent is still in that function?

13:48 slashus2: (dorun (map #(send-off % behave) ants)) <-- this is called once where the beginning population of ants is created.

13:49 Scenario: I create another agent and use send-off to the behave function.

13:50 If I deref the agent, it seems to be moving. It must be a problem with the animation. So the problem isn't with my understanding of the agent system.

13:50 ayrnieu: so behave contains something like (send-off *agent* ...) , to loop?

13:51 slashus2: yes

13:52 The original simulation is working. The other ants are behaving, and apparently so are these new ants.

13:52 The animation system isn't picking up on the new ants.

13:52 ayrnieu: maybe your animator hang on to its original deref of your agent list?

13:53 also, why don't you drop the list and just add-watcher an animator agent?

13:54 slashus2: I will look into that.

14:01 Okay, this doesn't make sense. The ant is being drawn on the screen as a little line, when dereferencing the agent that represents that ant, it seems to be changing position, but the ant is not moving in the animation.

14:06 Chousuke: slashus2: does the redraw function know about your ant? or was drawing it part of behave? :/

14:08 slashus2: The redraw function does draw the little ant.

14:09 Chousuke: The code I am working with is http://clojure.googlegroups.com/web/ants.clj

14:09 I am just experimenting to learn.

14:09 pilkarn: do you mark impure functions with ! ? I find it helpful for debugging

14:21 slashus2: Chousuke: The only difference is at the bottom I am doing (def ants-ref (ref ants)) so that I am able to alter the list of ant agents.

14:21 Chousuke: ah, it does not work like that!

14:22 slashus2: As soon as I do (dosync (alter ants-ref conj (create-ant [20 20] (rand-int 8))))

14:22 It paints the ant on the screen.

14:22 Chousuke: slashus2: you can't alter the ants list like that; the *only* thing you can alter is what the ref points to

14:22 you can't actually mutate anything

14:22 slashus2: Chousuke: the ants-ref points to a list of agents.

14:22 Chousuke: so the original ants list never changes

14:22 slashus2: It does indeed change the ants list

14:23 Try it. While the program is running do the transaction I just did within the live repl.

14:23 IF you look at ants, the new agent is added.

14:24 On the animation, the new ant will be painted.

14:24 Chousuke: if you do (def ants [...]), then you *can't* change the list that ants is.

14:24 slashus2: ...

14:24 Chousuke: you're seeing something else.

14:24 slashus2: How is the new ant painted onto the animation then?

14:26 Chousuke: create-ant adds it into the world

14:26 but that's not the ants list :)

14:26 slashus2: oh..

14:28 How would you do what I am wanting to do.

14:28 ?

14:28 It is hard to wrap my programming style around immutability.

14:29 Chousuke: you'll need to call (send-off behave your-new-ant) before it'll start moving I think

14:29 with your-new-ant being whatever the create-ant returns

14:30 slashus2: So I don't really need to add it to ants.

14:30 Chousuke: that's right

14:30 slashus2: *head explodes*

14:30 Chousuke: there's no way you could do it, really :)

14:30 the ant list is just a helper datastructure for the (dorun (map #(send-off % behave) ants))

14:31 hm, and that made me realise I had swapped the arguments to send-off :P

14:31 the ant of course comes first :)

14:31 slashus2: yey, it worked.

14:31 question is now... how will I kill that ant?

14:32 Just make the thread stop running under a certain condition?

14:32 durka42: set a flag somewhere and have the ants check it before recursing

14:32 Chousuke: ants.clj does not seem to allow killing individual ants.

14:32 slashus2: right

14:32 durka42: hmm, you could set it in the doomed ant's metadata

14:33 Chousuke: or just its state

14:33 it's a map, isn't it?

14:33 slashus2: set it in the ant agent data?

14:33 :dead

14:33 Chousuke: when there's the (if running ...) check before it (when-not (:mustdie @*agent*))

14:34 silkarn: why does compile silently fail?

14:34 Chousuke: then you can kill an ant by doing (send-off ant assoc :mustdie true)

14:34 because it won't send behave to itself again

14:35 slashus2: Chousuke: Why must I send-off again? Won't the thread stop once I don't call (send-off *agent* #'behave) again?

14:35 Chousuke: you send that assoc from outside

14:35 ie. from the repl

14:36 you just need to add to behave a check for it.

14:36 slashus2: That meta-data can also be set from within the agent as well.

14:36 agent function I mean.

14:36 Chousuke: which agent function? :)

14:36 slashus2: behave

14:36 Chousuke: how could you set that data from there?

14:37 it runs automatically.

14:37 you'd have to have a timeout or something

14:37 AWizzArd: clojurebot: max people

14:37 clojurebot: max people is 149

14:37 Chousuke: it's possible, but I thought you wanted to kill them manually :)

14:37 slashus2: can you not alter agents from within behave?

14:38 Chousuke: slashus2: you can only send-off new actions

14:38 the return value of an action becomes the ant's new state

14:38 slashus2: To alter agents you have to use send-off?

14:38 Chousuke: or send, but yes

14:39 slashus2: So it happens within a transaction; sort of like (alter)?

14:39 Chousuke: slashus2: you can of course do (send-off *agent* assoc :mustdie true) from inside behave, but why would you do that? :)

14:39 slashus2: nah; sends are just queued

14:40 slashus2: Chousuke: If you send off on an agent that already exists, it executes the action on it?

14:40 Chousuke: yeah, after all previously queued actions or running actions have finished

14:41 silkarn: I have a problem, if I def something that is passed to a function that def defs the symbol of the passed thing not the thing it self right?

14:41 Chousuke: silkarn: behave runs "forever" because it sends off itself to the agent that received the behave action.

14:42 er, slashus2

14:42 silkarn: so I have to sue refs if i want mutability inside clojure?

14:42 Chousuke: you have refs, agents and atoms

14:43 let's assume you have an ant running in the behave send-off loop

14:43 gnuvince_: I just saw Rich's post about first/more/rest. What do you guys think of keeping first and rest as is and having the function "tail" return possibly-empty-collection-of-the-remaining-elements?

14:44 slashus2: Chousuke: When I use send-off, does the function behave take the deref of the agent as an argument? behave takes [loc], which seems to be the deref of the agent?

14:45 Chousuke: yes.

14:45 now, you modify the behave function so that it has this: (when-not (:must-die @*agent*) (send-off *agent* #'behave))

14:46 then you can at any time kill an ant you have a reference to by doing (send-off myant assoc :must-die true)

14:46 slashus2: That is why I was a little confused when you did (send-off *agent* assoc :mustdie true). How do you know that the deref of agent isn't going to be used as an argument in that case?

14:46 Chousuke: that will cause myant's state to change so that (:must-die @myant) will return true

14:46 and the behave loop will end

14:47 slashus2: I understand that, but the seemingly inconsistent behavior confuses me.

14:47 Chousuke: slashus2: no, it's not inconsistent

14:47 slashus2: the first argument of assoc will still be the deref of the agent: a map

14:47 but that's what we want.

14:48 slashus2: The deref of agent will be something like [10 20]

14:48 Chousuke: ,(assoc {:food 1} :mustdie true)

14:48 clojurebot: {:mustdie true, :food 1}

14:48 Chousuke: hmm

14:48 well that's a problem :(

14:48 I assumed it was a map

14:48 slashus2: It isn't a map.

14:48 It is a vector

14:49 with [x y]

14:49 silkarn: for an mp3player, what makes more sense, refs, agents or atoms?

14:49 Chousuke: slashus2: that makes the case more problematic

14:50 slashus2: since now you can only kill ants by their location

14:50 and I think that might have race conditions :/

14:50 or hm

14:50 not really

14:50 durka42: silkarn: what sort of state are you storing?

14:51 silkarn: durka42: state of the mp3player, i need some gloabl state to keep track of the current player-thread, playlsit etc

14:52 durka42: i would say probably refs, but it depends

14:52 silkarn: i used a lot of defs first but it is ugly so I am refectoring

14:52 durka42: because you do need synchronization

14:52 if you use refs any modifications must be done in transactions

14:52 Chousuke: silkarn: I don't think it's very easy to kill individual ants in ants.clj without significant changes.

14:53 silkarn: if behave took a map it'd be easy, but since it's a vector...

14:53 durka42: Chousuke: watch that tab completion

14:53 Chousuke: gah

14:53 slashus2: :P

14:53 silkarn: you're confusing!

14:54 slashus2: I could modify the behave function to take another argument, a map, and change the create-ant function to create an agent with another argument, a map.

14:54 Do that difficult?

14:54 Not*

14:55 Of course, the (send-off my-ant assoc :dienow true) won't work because the deref of my-ant will have 2 arguments.

14:56 Unless I added {:x 20 :y 20 :dienow false} as the only argument in the agent?

14:57 That would work.

14:57 ayrnieu: rather than have a :dienow , you could (send-off my-ant #(do % nil))

14:59 slashus2: That would expand to (do [20 20] nil) ?

14:59 Causing the ant to lose its sense of location, but still leaving a dead body on the screen.

15:00 ayrnieu: sure. The point is to throw away the single required argument, and to return nil.

15:00 you could also (fn [_] nil)

15:05 pilkarn: so im elss confusing now

15:25 slashus2: In an agent function, is the current agent modified to whatever the agent function returns?

15:25 Chouser: yes

15:25 slashus2: yey I get it.

15:25 Chouser: :-)

15:27 rhickey: surprisingly, people are favoring optimal names on the more/rest/next question: http://groups.google.com/group/clojure/browse_frm/thread/88d9fdb5bcad36a

15:28 maybe they don't have much code to port?

15:28 ;)

15:29 pilkarn: what happens when compile runs? it does static analysis and doesnt say what happens?

15:29 it just silently fails it seems

15:29 MarkVolkmann: Mental block here ... Why would I want to use commute instead of alter to change the value of a Ref? What's the benefit of reapplying the update functions invoked by commute when the transaction commits?

15:30 gnuvince_: commute should be done for operations where order doesn't matter

15:30 rhickey: MarkVolkmann: let's say every transaction needs to update a jobs-completed counter when it's done...

15:31 gnuvince_: if you have two threads that need to add 1 to a counter, it doesn't matter if thread1 does it before thread2, the counter will be 2 afterwards.

15:31 rhickey: if you use alter the jobs will have to serialize

15:31 when they don't actually care what the resulting counter value is

15:33 MarkVolkmann: Ah ... "jobs will have to serialize". I haven't run across that before.

15:34 rhickey: MarkVolkmann: but that's strictly an optimization - if you are unsure use alter

15:34 gnuvince_: serialize in the sense "run one after another"

15:34 MarkVolkmann: What is it that causes a transaction to retry? Is it that a transaction attempts to change the value of a Ref that has been changed by another transaction since the current transaction started?

15:35 Bracki: Is anybody using gorilla for Vim?

15:36 cp2: just a minor question -- whats the "eta" on full laziness being in the main branch?

15:36 MarkVolkmann: I couldn't get Gorilla installed properly and gave up for now. I using VimClojure instead. I think Meikel is making improvements to Gorilla that will make it easier to install soon.

15:36 rhickey: MarkVolkman: yes

15:36 pilkarn: what happens when compile runs? it does static analysis and doesnt say what happens?

15:36 it seems to compile fine but then when i run it ha sno main

15:36 mattrepl: rhickey: that's the good part about having a community of CL expatriates and early adopters in general, a dislike of legacy for its own sake

15:38 gnuvince_: I agree that the time to get things right is not in 2-3 years when a lot more people depend on Clojure.

15:38 hircus: hi all

15:39 has there been any recent Clojure/SLIME regression? I had a working set-up on Linux, but on OS X, I could get a basic slime+clojure repl working but there's no tab-completion of forms

15:39 ayrnieu: mattrepl - bitter but superficial comments about CL do not make an expatriot.

15:39 hircus: e.g. (defn foo TAB

15:39 Chouser: hm, someone want to digg or reddit my blog post before it becomes obsolete? ;-)

15:41 gnuvince_: hircus: do you have the "normal" SLIME REPL with user> or do you have the inferior-lisp's user=> prompt?

15:41 hircus: gnuinferior lisp

15:41 mattrepl: ayrnieu: or more general, not all that dislike aspects of CL and use Clojure are expatriots

15:41 ayrnieu: hircus - does ESC-Tab complete it?

15:41 * durka42 reddits Chouser's post

15:41 hircus: gnuvince_: inferior lisp.

15:42 ayrnieu: "No tags table loaded; try M-x visit-tags-table

15:42 ayrnieu: mattrepl - in which case, their legacy aversion is meaningless.

15:42 gnuvince_: hircus: something changed in slime recently with regards to the repl. In your .emacs, you need: (require 'slime) (slime-setup) (require 'slime-repl) (slime-repl-init)

15:42 mattrepl: masochistic?

15:42 hircus: my SLIME knowledge is limited to getting it to work with SBCL and Clojure

15:42 aha. let me just try that

15:42 durka42: hmm, it was already in /r/lisp, but not /r/clojure

15:42 gnuvince_: (make sure that slime/contrib is in your load path)

15:43 hircus: *doh* I think I did something like that on my Linux machine a few days ago. something about it not loading the full repl by default anymore?

15:43 gnuvince_: Yeah

15:43 lisppaste8: gnuvince pasted "slime config" at http://paste.lisp.org/display/75533

15:43 gnuvince_: This is my configuration

15:44 ayrnieu: I have (slime-setup '(slime-fancy slime-asdf)) , and needed the slime-fancy to get the cool stuff.

15:44 hircus: gnuvince_, ayrnieu got it fixed now. thanks.

15:44 gnuvince_: hircus: happy to help

15:44 ayrnieu: what's in slime-fancy?

15:44 * hircus seconds gnuvince_'s question

15:45 ayrnieu: gnuvince - slime-repl , for one.

15:45 gnuvince_: ah

15:45 nice

15:45 hircus: does slime-asdf does anything for Clojure, or is it more for when using Common Lisp?

15:45 ayrnieu: hircus - it's for CL.

15:46 hircus: ah ok

15:46 thanks, you two

15:50 gnuvince_: ayrnieu: does slime-interrupt work for you?

15:53 ayrnieu: gnuvince - I haven't set clojure up with slime.

15:58 Bracki: Ah I've made Gorilla work for me. The problem was to explicitly set maplocalleader. I had assumed it would be the same setting as localleader.

16:01 gnuvince_: ayrnieu: ok

16:10 durka42: Bracki: a fellow gorilla user!

16:26 Bracki: Hm I seem to miss something. How do I import/refer/use clojure contrib?

16:26 durka42: you use particular libraries from it

16:26 AWizzArd: Bracki: you don't import it, but you require it

16:26 durka42: (use 'clojure.contrib.math)

16:27 AWizzArd: Bracki: (require '[clojure.contrib.duck-streams :as ds])

16:28 (line-seq (ds/reader "https://www.microsoft.com/&quot;))

16:34 blbrown: did clojure get some kind of award from a software magazine. I thought I read that somewhere

16:35 Bracki: Does this channel have a pastebin?

16:36 blbrown: Bracki http://paste.lisp.org/new/lisp I am sure lisp paste would work fine

16:36 durka42: ~paste

16:36 clojurebot: lisppaste8, url

16:36 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

16:36 durka42: blbrown: your link will announce in #lisp

16:37 lisppaste8: bracki pasted "untitled" at http://paste.lisp.org/display/75539

16:37 Bracki: So what's going on wrong there. I'm trying to use contrib.test_is

16:38 durka42: test-is, not test_is

16:38 hmm, it works when i do (use 'clojure.contrib.test-is)

16:39 Bracki: hm, same problem.

16:39 you just copy/pasted into the repl?

16:40 durka42: (require '[clojure.contrib [test-is :as test-is]])

16:40 then test-is/is

16:40 or use works

16:44 pilkarn: (defn fac [n] (reduce #(* %1 %2) (range 1 (inc n)))) , does that build the list lazily or is it first created O(n) then reduced over O(n) ?

16:44 durka42: reduce should be lazy

16:45 Bracki: durka42: that works.

16:45 durka42: and i think range is too

16:45 rhickey: durka42: range is lazy, reduce is always eager - it reduces its args to a single result

16:45 Bracki: what does "works" do?

16:45 durka42: i meant, or use works

16:45 ,use

16:45 clojurebot: #<core$use__4964 clojure.core$use__4964@5084c6>

16:46 durka42: oh, right, of course

16:47 Bracki: ah.

16:50 pilkarn: id i have (fun btn f) where f is a function that takes several args and fun is a function. if i dont want f to be evaluated directly but later when btn is prsed, then i wrap the whole f call in # ? (fun btn #(f x y z)) ?

16:58 Chousuke: pilkarn: f is not called if you just pass it as an argument

16:58 pilkarn: the notation #(f 1 2 3) is just a literal function that calls f with the arguments 1, 2 and 3

16:59 #(f) is equivalent to f

16:59 or well

16:59 actually, nto

16:59 only if f takes no arguments :)

17:05 Bracki: How do I split a list in two lists?

17:07 hiredman: ,(doc split-with)

17:07 clojurebot: "([pred coll]); Returns a vector of [(take-while pred coll) (drop-while pred coll)]"

17:07 ayrnieu: that depends on what relationship you want the two lists to have to the list.

17:08 Bracki: in half, split a list of integers in the "middle".

17:09 blbrown: Chouser, were you telling me about the O'Reilly algorithms books? I got it, don't know how I should approach it

17:10 ayrnieu: ,(split-at 2 [1 2 3 4 5])

17:10 clojurebot: [(1 2) (3 4 5)]

17:11 blbrown: ,(split-at "," ["klsdklfjslkdjflksjdlf, kljsldfjslkdjflksd"])

17:11 clojurebot: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number

17:11 blbrown: ,(split-at '," ["klsdklfjslkdjflksjdlf, kljsldfjslkdjflksd"])

17:12 clojurebot: Eval-in-box threw an exception:EOF while reading string

17:12 blbrown: ,(split-at ',' ["klsdklfjslkdjflksjdlf, kljsldfjslkdjflksd"])

17:12 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$split-at

17:12 ayrnieu: ,(doc split-at0

17:12 pilkarn: hmm cant clojrue import mutually? ie ns/file X imports function from Y and Y imports a function from X ? I use declare somehow?

17:12 clojurebot: Eval-in-box threw an exception:EOF while reading

17:12 ayrnieu: ,(doc split-at)

17:12 clojurebot: "([n coll]); Returns a vector of [(take n coll) (drop n coll)]"

17:14 ayrnieu: ,(map str (split-with #(= % \,) "klsdklfjslkdjflksjdlf, kljsldfjslkdjflksd"))

17:14 clojurebot: ("" "(\\k \\l \\s \\d \\k \\l \\f \\j \\s \\l \\k \\d \\j \\f \\l \\k \\s \\j \\d \\l \\f \\, \\space \\k \\l \\j \\s \\l \\d \\f \\j \\s \\l \\k \\d \\j \\f \\l \\k \\s \\d)")

17:14 hiredman: blbrown: there are several things wrong with what you were trying

17:14 ayrnieu: that's actually better than ("clojure.core$take_while__3672$fn__3674@c4bf9ef" "clojure.core$drop_while__3696$fn__3702@c4bf9ef") , a buggy return from my build.

17:14 hiredman: a charater in clojure is preceded by a \

17:14 blbrown: hiredman, I was just messing around

17:14 pilkarn: hmm cant clojrue import mutually? ie ns/file X imports function from Y and Y imports a function from X ? I use declare somehow?

17:14 ayrnieu: pilkarn - no.

17:15 hiredman: \,

17:15 not ','

17:15 Bracki: So how do I get the length of a list?

17:15 blbrown: it is count

17:15 I think most people are used to 'len' or 'length'

17:15 ,(count [1 2 3])

17:15 clojurebot: 3

17:16 pilkarn: ayrnieu: no what?

17:16 ayrnieu: pilkarn - the answer to your questions are "no".

17:16 pilkarn: len would ahve been better but whatever

17:16 and count could then have been (count 1 [1 2 3 1]) -> 2

17:17 ayrnieu: and there is no solution to that?

17:18 blbrown: ,(def length count)

17:18 clojurebot: DENIED

17:18 hiredman: ,(split-with #(= % \,) "klsdklfjslkdjflksjdl, kljsldfjslkdjflksd")

17:18 clojurebot: [nil (\k \l \s \d \k \l \f \j \s \l \k \d \j \f \l \k \s \j \d \l \, \space \k \l \j \s \l \d \f \j \s \l \k \d \j \f \l \k \s \d)]

17:18 blbrown: pilkarn, that is what I do...shrug

17:18 Bracki: ,(doc /)

17:18 clojurebot: "([x] [x y] [x y & more]); If no denominators are supplied, returns 1/numerator, else returns numerator divided by all of the denominators."

17:18 ayrnieu: pilkarn - sure. You could not do that. You could separate these functions out into their own namespace. You could put the mutually-dependent modules in the same namespace. You could look into clojure's guts and propose a declaration. You could patch the namespace after load instead of doing it through 'use'.

17:19 Bracki: Can somebody explain that to me? I want division without remainder, no floats or anything.

17:19 hiredman: ,(int \,)

17:19 clojurebot: 44

17:19 hiredman: ,(split-with #(= (int %) 44) "klsdklfjslkdjflksjdl, kljsldfjslkdjflksd")

17:19 clojurebot: [nil (\k \l \s \d \k \l \f \j \s \l \k \d \j \f \l \k \s \j \d \l \, \space \k \l \j \s \l \d \f \j \s \l \k \d \j \f \l \k \s \d)]

17:19 ayrnieu: ,(unchecked-divide 7 3)

17:19 clojurebot: 2

17:21 pilkarn: how much work would a mp3-decoder be?

17:21 Chousuke: in clojure? :/

17:21 hiredman: pilkarn: just use a java mp3lib

17:22 ,(split-with #(not= (int %) 44) "klsdklfjslkdjflksjdl, kljsldfjslkdjflksd")

17:22 clojurebot: [(\k \l \s \d \k \l \f \j \s \l \k \d \j \f \l \k \s \j \d \l) (\, \space \k \l \j \s \l \d \f \j \s \l \k \d \j \f \l \k \s \d)]

17:22 * hiredman dies

17:23 hiredman: ,(map (partial apply str) (split-with #(not= (int %) 44) "klsdklfjslkdjflksjdl, kljsldfjslkdjflksd"))

17:23 clojurebot: ("klsdklfjslkdjflksjdl" ", kljsldfjslkdjflksd")

17:23 Bracki: what yields index of item in list?

17:24 hiredman: lists are not index

17:24 ayrnieu: ,(.indexOf "hello" "l")

17:24 clojurebot: 2

17:25 hiredman: indexed

17:25 ayrnieu: (.indexOf [1 2 3 4 5] 4)

17:25 hiredman: if you want an indexed data structure use a vector

17:26 Bracki: Ok, what I actually wanted to do is solve some of these to get me going with clojure. http://codekata.pragprog.com/2007/01/kata_two_karate.html

17:26 ayrnieu: ,(.indexOf '(a b c d e) 'c)

17:26 clojurebot: 2

17:27 hiredman: Bracki: hit up project euler and start working through it with clojure

17:28 ayrnieu: of course, but it has to walk the list

17:28 wait

17:28 actually for vectors it would too

17:28 nm

17:29 Bracki: Alright, thats exactly what I was looking for.

17:31 But same problem. What's modulo in clojure?

17:32 hiredman: ,(doc mod)

17:32 clojurebot: "([num div]); modulus of num and div."

17:32 Bracki: Does that come from contrib?

17:32 Cause it's not listed on the api page.

17:32 ayrnieu: ,`mod

17:32 clojurebot: clojure.core/mod

17:33 ayrnieu: ,[(mod -1 3) (rem -1 3)]

17:33 clojurebot: [2 -1]

17:33 lenst: ,(meta #'mod)

17:33 clojurebot: {:ns #<Namespace clojure.core>, :name mod, :file "core.clj", :line 1864, :arglists ([num div]), :doc "modulus of num and div."}

17:33 Bracki: http://clojure.org/api#mod -> no result.

17:36 hiredman: and?

17:36 ayrnieu: ,(.contains (keys (ns-publics 'clojure.core)) 'mod)

17:37 clojurebot: true

17:37 Bracki: That means that my version of clojure doesn't have it as well, cos i'm usisng the latest "official" relase.

17:37 hiredman: Bracki: type mod into the repl

17:37 Bracki: Gorilla=> (.contains (keys (ns-publics 'clojure.core)) 'mod)

17:37 false

17:38 hiredman: what release are you using?

17:38 Bracki: Just wrote that, the latest from google code, 2008/12/17.

17:39 hiredman: no kidding

17:39 *shrug*

17:40 ayrnieu: ,(map :name (filter #(and (:doc %) (.contains (:doc %) "mod")) (map meta (vals (ns-publics 'clojure.core)))))

17:40 clojurebot: (derive with-precision ensure require underive mod)

17:40 hiredman: ~def mod

17:41 ayrnieu: probably goatse.

17:41 Bracki: Thx. See here http://code.google.com/p/clojure/source/browse/branches/20081217/src/clj/clojure/core.clj no mod

17:42 hiredman: actually it is the definition of mod

17:42 Bracki: yeah, we established that you have no mod

17:43 Chouser: Bracki: but 'rem' is close

17:43 hiredman: but there is the def of mod, you can copy and paste it

17:43 Chouser: ,(rem 7 5)

17:43 clojurebot: 2

17:43 ayrnieu: ,(map #(.getName %) (all-ns))

17:43 clojurebot: (clojure.set hiredman.sandbox hiredman.clojurebot.seenx hiredman.clojurebot.dice hiredman.clojurebot.sb org.danlarkin.json.decoder user hiredman.clojurebot.google clojure.main org.danlarkin.json clojure.core hiredman.clojurebot.translate org.danlarkin.json.encoder clojure.zip sandbox hiredman.clojurebot hiredman.clojurebot.forget hiredman.utilities hiredman.clojurebot.core clojure.xml hiredman.clojurebot.svn hiredman.pque

17:49 pilkarn: man my mp3player is around 250-300 lines of code, written in clojure completely but a lot of java-wrapping. doe sit sound reasonable? just making a simple player was basically no code at all but making laylists, stop next play etc and makign sure evrything works added so much code

17:50 hiredman: ~translate to sp the plains in spain in the rain

17:50 huh

17:50 Bracki: Regarding the project euler thingy, how do I filter a list twice, or rather combine the result of two filter passes to a new list?

17:51 pilkarn: yes an mp3-decoder in Clojure. I already am using mlayer and it is ok but lacks some features. im mostly interesting un learning basic signal processing, and it seems like a fun project that would teach me a lot.

17:51 ayrnieu: Bracki, that depends on what relationship you want the combined list to have to the two lists.

17:52 ,(filter #(zero? (mod % 3)) (filter #(zero? (mod % 13)) (range 200)))

17:52 clojurebot: (0 39 78 117 156 195)

17:53 ayrnieu: ,(filter #(and (zero? (mod % 3) (mod % 21))) (range 400))

17:53 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$fn

17:53 Bracki: Yeah but I want to OR the filters not AND them.

17:53 Chousuke: just use or then

17:53 ayrnieu: ,(filter #(and (zero? (mod % 3)) (zero? (mod % 21))) (range 400))

17:53 clojurebot: (0 21 42 63 84 105 126 147 168 189 210 231 252 273 294 315 336 357 378 399)

17:54 Chousuke: you can't separate the lists that way though

17:56 pilkarn: yes an mp3-decoder in Clojure. I already am using mlayer and it is ok but lacks some features. im mostly interesting un learning basic signal processing, and it seems like a fun project that would teach me a lot.

17:56 how can you compose filter and filter?

17:56 ayrnieu: ,(meta (var compose))

17:56 clojurebot: java.lang.Exception: Unable to resolve var: compose in this context

17:57 blbrown: If I define this structure. Is this an PersisentArrayMap or StructMap. I thought it would be a 'struct' map: { :tag :af, :attrs {:timestamp "Feb 14 06:02:17 2009", :id 1 }

17:57 { :tag :af, :attrs {:timestamp "Feb 14 06:02:17 2009", :id 1 } }

17:57 pilkarn: , (def ff (comp filter filter))

17:57 clojurebot: DENIED

17:57 ayrnieu: ,(doc comp) ;; bleh, I won't replace the doc with "DON'T USE THIS YOU EVIL ESCAPEE FROM HASKELL"

17:57 clojurebot: "([& fs]); Takes a set of functions and returns a fn that is the composition of those fns. The returned fn takes a variable number of args, applies the rightmost of fns to the args, the next fn (right-to-left) to the result, etc."

17:57 pilkarn: (ff #(< % 15) #(> % 10) (range 20))

17:58 , (let [ff (comp filter filter)] (ff #(< % 15) #(> % 10) (range 20)))

17:58 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$filter

17:58 hiredman: composing filter like that will not work

17:58 filter takes more than one argument

17:58 but (like all functions) only returns one

17:59 pilkarn: so you can only compsoe functions with arity 1?

17:59 so compose is good in haskell because all fucntions are currried?

17:59 but not in clojure?

17:59 ayrnieu: why do you ask "you can only?" like that? comp is just a clojure function.

17:59 hiredman: yes

17:59 Chousuke: (filter #(or (> 10 %) (< 2 %)) [1 2 3 4 5 12 70 100])

17:59 ,(filter #(or (> 10 %) (< 2 %)) [1 2 3 4 5 12 70 100])

17:59 clojurebot: (1 2 3 4 5 12 70 100)

18:00 Chousuke: hm

18:00 well that wasn't very useful :(

18:00 ,(filter #(or (< 10 %) (> 2 %)) [1 2 3 4 5 12 70 100])

18:00 clojurebot: (1 12 70 100)

18:00 Bracki: How do I unpack a list?

18:00 pilkarn: can i get the arity of a function at runtime?

18:00 ayrnieu: Bracki - that depends on what you mean why 'unpack'.

18:00 hiredman: if you want to do a lot of composing you have to uncurry functions by hand

18:01 Chousuke: pilkarn: :arglists in metadata

18:01 hiredman: Bracki: unpack?

18:01 Chousuke: ,(:arglists ^#'filter)

18:01 clojurebot: ([pred coll])

18:01 Bracki: the sum of the list by passing a list to: (+ '(1 2 3))

18:01 hiredman: Chousuke: that only works are functions stored in vars

18:01 ayrnieu: ,(:arglists (meta (fn [_] 1)))

18:01 clojurebot: nil

18:01 hiredman: Bracki: apply

18:01 Chousuke: true

18:01 pilkarn: and that metadata is gened automatically?

18:02 Chousuke: pilkarn: it exists for defn'd functions

18:02 hiredman: pilkarn: there is no way to get arity information from an arbitrary function

18:03 pilkarn: why does reduce give arity 2? (reduce + coll) ok but (reduce #(+ %1 %2 3) 0 coll) -> arity 3

18:03 ayrnieu: ,(doc reduce)

18:03 hiredman: uh

18:03 clojurebot: "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val is supplied, returns the r

18:03 hiredman: ,(:arglists ^#'reduce)

18:03 clojurebot: ([f coll] [f val coll])

18:04 hiredman: ^- two arg lists

18:07 ayrnieu: If you want to produce code as fantastic and worthless as the Haskell community has trained itself to do with that language's horrifically maldesiged^W^Wfeatures, then you'll have to do a bit of work to make this possible. And Clojure still won't have the piles of syntax sugar to give the result a veneer of acceptability.

18:07 hiredman: *cough*

18:08 pilkarn: how can I do (convert-to-vector java-LinkedList) ?

18:08 hiredman: (doc vec)

18:08 clojurebot: Creates a new vector containing the contents of coll.; arglists ([coll])

18:08 hiredman: coll in the docs means Collection

18:09 ,(doc instanceof?)

18:09 clojurebot: java.lang.Exception: Unable to resolve var: instanceof? in this context

18:09 hiredman: ,(doc instanceof)

18:09 clojurebot: java.lang.Exception: Unable to resolve var: instanceof in this context

18:09 ayrnieu: but if this is a Java linked list and not a clojure PersistentList, you can get an iterator from it and then use iterator-seq

18:10 ,(map :name (filter #(and (:doc %) (.contains (:doc %) "instance")) (map meta (vals (ns-publics 'clojure.core)))))

18:10 clojurebot: (re-pattern instance? init-proxy re-matcher read .. seque memfn accessor class? construct-proxy get-proxy-class struct-map proxy-mappings update-proxy proxy struct gen-class make-array)

18:11 hiredman: ,(instance? (java.util.LinkedList.) java.util.Collection)

18:11 clojurebot: java.lang.ClassCastException: java.util.LinkedList cannot be cast to java.lang.Class

18:11 durka42: ,(find-doc "instance")

18:11 clojurebot: ------------------------- clojure.main/repl ([& options]) Generic, reusable, read-eval-print loop. Reads from *in* and writes to *out*. *in* must either be an instance of LineNumberingPushbackReader or duplicate its behavior of both supporting .unread and collapsing CR, LF, and CRLF into a single \newline. Options are sequential keyword-value pairs. Available options and their defaults: - :init, function o

18:11 durka42: oh, i forgot that prints out the doc and not just the names

18:11 hiredman: ,(vec (java.util.LinkedList.))

18:11 clojurebot: []

18:12 hiredman: ,(vec (java.util.LinkedList. 1))

18:12 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.util.Collection

18:12 hiredman: ,(vec (java.util.LinkedList. [1 2 3 4]))

18:12 clojurebot: [1 2 3 4]

18:12 hiredman: yay java.util.Collection!

18:14 cp2: can somebody tell me the equivalent of say, int.class ?

18:14 hiredman: ,(java.util.Collections/shuffle (java.util.LinkedList. [1 2 3 4]))

18:14 clojurebot: nil

18:14 hiredman: ugh

18:14 cp2: actually, nevermind

18:14 ayrnieu: ,[(class 1) Integer/TYPE]

18:14 clojurebot: [java.lang.Integer int]

18:14 cp2: i just realised that what i asked isnt relevant to my problem

18:15 * hiredman forgot about shuffle's nsaty state chaning behaviour

18:15 cp2: well, it is, but in a different way

18:17 hiredman: 1d2

18:17 clojurebot: 2

18:17 pilkarn: (LinkedList. (make-array Integer (count [1 2 3]))) -> java.lang.ClassCastException: [Ljava.lang.Integer; cannot be cast to java.util.Collection (NO_SOURCE_FILE:0)

18:17 , why?

18:17 clojurebot: java.lang.Exception: Unable to resolve symbol: why? in this context

18:17 hiredman: ,(doc make-array)

18:17 clojurebot: "([type len] [type dim & more-dims]); Creates and returns an array of instances of the specified class of the specified dimension(s). Note that a class object is required. Class objects can be obtained by using their imported or fully-qualified name. Class objects for the primitive types can be obtained using, e.g., Integer/TYPE."

18:17 pilkarn: ayrnieu: why is haskell code so worthless? i find it extremely elegant, clojure inspired rhickey a lot I think.

18:18 hiredman: pilkarn: a java array is not a Collection

18:18 durka42: ,(use 'clojure.contrib.lazy-seqs) (random-permutation [1 2 3 4])

18:18 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib/lazy_seqs__init.class or clojure/contrib/lazy_seqs.clj on classpath:

18:20 hiredman: clojure's datastructures are Collections, so they can be passed to LinkedList directly

18:20 ,(java.util.LinkedList. [1 2 3 4])

18:20 clojurebot: #<LinkedList [1, 2, 3, 4]>

18:22 pilkarn: clojurebot: contrib?

18:22 clojurebot: contrib is http://code.google.com/p/clojure-contrib/

18:22 pilkarn: i want to shuffle a vector

18:23 hiredman: ,(doto (java.util.LinkedList. [1 2 3 4]) java.util.Collections/shuffle)

18:23 clojurebot: #<LinkedList [1, 3, 2, 4]>

18:24 hiredman: ,(vec (doto (java.util.LinkedList. (range 10)) java.util.Collections/shuffle))

18:24 clojurebot: [4 5 3 9 8 1 2 0 6 7]

18:24 hiredman: ,(vec (doto (java.util.LinkedList. (range 10)) java.util.Collections/shuffle))

18:24 clojurebot: [3 9 0 7 2 4 6 8 1 5]

18:25 Chousuke: ,(java.util.Collections/shuffle [1 2 3])

18:25 clojurebot: java.lang.UnsupportedOperationException

18:25 Chousuke: hee

18:29 Bracki: In the REPL how do I reuse the last returned value?

18:30 durka42: *1

18:30 *2, *3

18:30 pilkarn: thanks

18:31 ayrnieu: you still didnt answer whats so bad about haskell?

18:31 and roughly how much code is an mp3decoder? anyone know? 500 loc, 3000?

18:33 Chousuke: pilkarn: that's a useless question

18:33 pilkarn: it depends too much on the language, the features wanted, skill and even just coding style.

18:33 pilkarn: yes but there is a bound anyhow

18:33 Chousuke: anyway, I don

18:34 I don't think Clojure is suitable for an mp3 decoder

18:34 If I were to write one I'm quite sure I'd use C

18:35 zakwilson: I've done some simple image processing in Clojure. I think an MP3 decoder is feasable.

18:35 hiredman: poor stuart

18:36 durka42: "When faced with this, apply the following method: try the simplest possible thing, and if it doesn't satisfy you, try the next simplest thing."

18:36 i like it

18:38 hiredman: pilkarn: I suggest you go write a mp3 decoder then you will have an empiracally arrived at number for the loc needed to implement a mp3 decoder

18:39 no need for guessing games

18:39 pilkarn: no i just asked, perhas soemone had done one and then they could say my C mp3 decoder was 2000loc or my java decoder was 1000loc and then id have a slight idea

18:40 hiredman: mp3 decoding is not a piece of code people write much these days, it is a librarythey consume

18:41 it is 2009, I would hope we can call mp3 decoding a "solved problem"

18:44 pilkarn: sure but one might be interested in learning about signal processing

18:44 and unfortuneately jlaye sucks even though it is a "solved problem"

18:47 hiredman: if you are intrested in learning about signal processing, why not just write the thing?

19:16 pilkarn: if i start a new process do all refs need to be passed to that then while if i use a new thread those threads share the refs?

19:20 Chouser: pilkarn: threads all share the same memory, so all the same globals are available whether they are refs, vars, file handles, buffers, whatever.

19:21 to communicate with a different process you'll need to use some kind of IPC mechanism -- sockets, "shared memory" objects, environment variables, etc.

19:30 blbrown: I think RIch is too smart to write the documentation

19:31 ...meaning, I can't understand what he is saying

19:33 durka42: where?

19:34 AWizzArd: btw, did the idea (def [x y z] [10 :hello {:a 1, :b 2}]) already die or is there a chance that we can get this? :)

19:35 blbrown: durka42, http://clojure.org/runtime_polymorphism

19:38 AWizzArd: ,(doc future)

19:38 clojurebot: "([& body]); Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block."

19:39 AWizzArd: ,(time @(future))

19:39 clojurebot: "Elapsed time: 1.058 msecs"

19:40 MarkVolkmann: Is there a function that detects whether a symbol is defined?

19:41 I want to base an action on that. If I don't check, I get an exception that says "Unable to resolve symbol".

19:41 technomancy: MarkVolkmann: find-var?

19:42 MarkVolkmann: That must be in a contrib library.

19:42 technomancy: nope; it's in clojure.core

19:42 MarkVolkmann: Ah ... I thought it had a question mark on the end.

19:42 technomancy: oh; heh

19:42 AWizzArd: MarkVolkmann: resolve

19:45 pilkarn: what i the alternative to polling?

19:45 technomancy: is it possible to make custom data types that are callable like functions the way maps and vectors are?

19:45 I'd like to be able to do something like ((date 2008 2 28) :month) => 2

19:46 but I suspect that might need to dip into Java

19:46 pilkarn: if date creates a hashmap it is guess

19:46 technomancy: I'd like it to be a new data type, but I can do that if there's no other way

19:46 pilkarn: put data in a namespace

19:47 hiredman: clojurebot: multimethods?

19:47 clojurebot: multimethods seperate the 20% from the 80%

19:48 technomancy: hiredman: often times the intent behind your clojurebot invocations are not always clear. are you trying to say that I could implement call-able data types with multimethods?

19:50 hiredman: technomancy: ah, no, I was reacting to blbrown, 15 minutes ago

19:50 pilkarn: lol

19:50 MarkVolkmann: Is there an idiom for insuring that some code in a .clj file is only run the first time that file is loaded?

19:51 hiredman: (doc defonce)

19:51 clojurebot: defs name to have the root value of the expr iff the named var has no root value, else expr is unevaluated; arglists ([name expr])

19:51 pilkarn: , (do (defn make-date [y m d] {:year y :month m :day d}) ((make-date 2008 12 02) :month))

19:51 clojurebot: DENIED

19:51 pilkarn: denyn youself biatch

19:51 , deny youself biatch

19:51 clojurebot: java.lang.Exception: Unable to resolve symbol: deny in this context

19:52 MarkVolkmann: Won't defonce just define something once? I want to execute a chunk on code just once. In particular, I want to start a thread only the first time this source file is loaded.

19:52 technomancy: MarkVolkmann: runonce is defined in lancet, might be helpful.

19:52 * technomancy needs to take off; later folks

19:53 hiredman: MarkVolkmann: according to the docstring, the expr is not evaled if a root binding already exists

19:53 Chouser: (defonce mythread (Thread. #(...))) should do it.

19:53 yeah, like hiredman said.

19:53 MarkVolkmann: Thanks!

19:53 hiredman: (defonce q (do some stuff here))

19:56 xoox: What is the proper way to filter on the children of a node that has been selected by filtering? "(xml-> (xml1->" is giving me heap errors.

19:56 lisppaste8: sd pasted "date namespace" at http://paste.lisp.org/display/75559

19:58 pilkarn: ^technomancy: ^^ but perhaps you know that approach already, just giving an exmaple of how I would do. namespaces + hashmaps + multimethods does most/all things I need from objectorientation

19:58 oh he left

19:59 the more i program in clojure the more objectorientation just feels like obfuscation. it complicates my code rather than simplifie sit.

20:05 hiredman: ~translate to de the plains in spain in the rain

20:05 clojurebot: die Ebenen in Spanien im Regen

20:05 hiredman: hmmm

20:12 blbrown: german>?

20:13 Chouser: xoox: can you paste an example that demonstrates the problem?

20:14 xoox: Chouser: Yes, give me two minutes.

20:18 lisppaste8: xoox pasted "xml-zip filtering" at http://paste.lisp.org/display/75560

20:20 xoox: Chouser: ^

20:23 blbrown: http://img253.imageshack.us/img253/8665/screenshot3sk9.png more on my clojure app, monitor garbage collection statistics

20:26 Chouser: xoox: fetch-dom ?

20:27 xoox: Chouser: Sorry, it is essentially (xml-zip (xml/parse url)). I will update the paste.

20:27 lisppaste8: xoox annotated #75560 with "fetch-dom" at http://paste.lisp.org/display/75560#1

20:28 pilkarn: ~translate to de scheisskopf

20:28 clojurebot: scheisskopf

20:28 pilkarn: ~translate to de Ich bin geil

20:28 clojurebot: Ich bin geil

20:28 blbrown: ~translate nein

20:28 pilkarn: ~translate to de I am awesome

20:28 clojurebot: Ich bin genial

20:28 hiredman: ~translate from de scheisskopf

20:28 Chouser: xoox: sorry, gotta go for a minute. I'll be back soon.

20:28 pilkarn: ~translate to eng Ich bin geil

20:28 blbrown: ~translate to eng dogs

20:28 hiredman: ~translate from de scheisskopf

20:28 clojurebot: scheiss kopf

20:29 xoox: Chouser: I'll be around for about an hour an a half. Thanks in advance for any pointers.

20:29 pilkarn: ~translate do de hired man

20:29 blbrown: hiredman, are you do some kind of REST request to babelfish or something

20:29 hiredman: blbrown: google translate

20:29 blbrown: ah

20:29 hiredman: man

20:30 translate needs a lot of polish, it throws a lot of exceptions

20:30 xoox: ~translate to de Mehr licht.

20:30 clojurebot: Mehr Licht.

20:30 xoox: ~translate from de Mehr licht.

20:30 clojurebot: More light.

20:30 blbrown: ~translate from de Nein

20:30 clojurebot: No

20:31 blbrown: ~translate to de beer

20:31 clojurebot: Bier

20:31 blbrown: ~translate to de I like cats

20:31 clojurebot: Ich mag Katzen

20:31 blbrown: ~translate to de I like Java

20:31 clojurebot: Ich mag Java

20:31 blbrown: ~translate to de I like clojure

20:31 clojurebot: Ich mag clojure

20:32 xoox: ~translate from de Alles Gescheite ist schon gedacht worden. Man muss nur versuchen, es noch einmal zu denken.

20:32 clojurebot: Everything is quite intelligent thought. You just have to try once again to think.

20:33 blbrown: xoox, really needs a text to speech wav output. Then we can hear what is printed. I'm just saying, if you want feature complete hehe

20:40 Chouser: xoox: I think it's just returning a really large object. Printing it at my repl just spews tons of text.

20:41 but if I do (def matches (xml-> (xml1-> ...))), that works ok, though of course its lazy

20:42 But then I can say (node (last matches)) and get a sane result rather quickly.

20:47 xoox: Chouser: Okay thanks. I guess I was just being misled and assuming an error caused by trying to print the object was a problem with the code.

20:49 Chouser: you're quite welcome. I'm very much aware that the use of neither clojure.zip nor zip-filter is particularly objvious, and there's essentially no documentation on the concepts behind either.

20:49 I keep meaning to write some kind of tutorial or something, but I haven't gotten around to it yet.

20:51 xoox: Chouser: By the way, is that the "correct" way to search only one branch of the tree? Find the element and then filter on its descendants?

20:52 Chouser: Off the top of my head, that's the only way I can think of.

20:53 AWizzArd: btw, did the idea (def [x y z] [10 :hello {:a 1, :b 2}]) already die or is there a chance that we can get this? :)

20:53 Chouser: each iteration of each filter step only has access to the one loc -- its starting point.

20:54 In order to examine the whole set of matching locs in order to do something like pick the first one, then you have to step outside the xml-> expression. I think.

20:54 though if there's only one branch that matches up to that point there's no harm at all in putting the remaining filter expressions in the same xml->

20:55 AWizzArd: I don't think anyone ever approached Rich with that idea.

20:57 AWizzArd: I thought you did.

20:57 some months ago

20:58 anyway... n8 n8

21:58 MarkVolkmann: I assumed that conj always added to the end of vectors, but it seems I was wrong.

21:58 Chouser: ?

21:58 danlarkin: bzzzt

21:58 MarkVolkmann: What's the best way to create a new vector with an item added to the end of an existing one.

21:58 Are you saying conj always does that?

21:58 danlarkin: conh

21:58 conj, sorry

21:59 Chouser: conj on a vector adds to the right-hand side

21:59 conj on a list adds to the left

21:59 MarkVolkmann: Hmm, I'll recheck my code to see why I thought it wasn't doing that.

21:59 ayrnieu: (map #(conj % 1) [[-1 1] (2 3)])

21:59 ,(map #(conj % 1) [[-1 1] (2 3)])

21:59 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

22:00 ayrnieu: oh, it swallowed the quote. Stupid apple keyboard.

22:01 MarkVolkmann: It's some weird multithreading timing issue.

22:02 hiredman: lets see some example code

22:02 MarkVolkmann: I'll gladly paste it if you want, but I don't want to burden everyone. I think I can describe the situation.

22:03 I'm making two calls to a function in succession.

22:03 The function starts a transaction and adds the string argument to a vector that is the value of an atom.

22:03 They sometimes get added in the reverse order of my calls.

22:04 hiredman: lets see some code

22:04 MarkVolkmann: The combination of dosync and swap! may be adding some uncertainty about the order in which the strings get conj'ed to the vector.

22:04 Does that sound plausible?

22:04 I'll paste the code.

22:05 hiredman: lisppaste8: url?

22:05 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

22:05 Chouser: if you care about the order, you should not use 'swap!' in a transaction

22:06 lisppaste8: mvolkmann pasted "logger.clj" at http://paste.lisp.org/display/75563

22:07 mvolkmann annotated #75563 with "client code" at http://paste.lisp.org/display/75563#1

22:07 MarkVolkmann: So the first paste is logger.clj which provides a log function.

22:07 The purpose is to allow multithreaded code to do printlns that won't get intermingled.

22:08 Chouser: besides order, a 'swap!' in a transaction could be retried -- you could get the same thing added multiple times.

22:08 MarkVolkmann: For example, I don't want one thread to log "The sky is blue", another to log "The grass is green" and see the output "The sky The is grass is blue green"

22:09 The client code just calls log with any number of arguments which are concatenated to form a message.

22:09 hiredman: swap! should not be in a transaction

22:09 MarkVolkmann: Oh, I thought it had to be in a transaction.

22:10 Chouser: no

22:10 hiredman: I think in this case you would be better off with a ref anyway

22:10 Chouser: but I think you need a transaction, in order to avoid a race condition with the empty check, etc.

22:10 MarkVolkmann: I started with that, but changed to an atom since I'm only coordinating change to a single value.

22:10 Chouser: ...which means a ref

22:11 MarkVolkmann: Oh, right! I knew that, but forgot.

22:11 Okay, I'll rework it to use a ref.

22:11 Thanks for the advice!

22:18 gnuvince_: Hello

22:18 Chouser: gnuvince_: hi

22:19 gnuvince_: How's it going, Chouser?

22:20 Chouser: pretty well, thanks. and you?

22:21 gnuvince_: Not bad at all. My project is going forth nicely.

22:24 ~seen ayrnieu

22:24 clojurebot: ayrnieu was last seen in #clojure, 23 minutes ago saying: oh, it swallowed the quote. Stupid apple keyboard.

22:25 ayrnieu: ?

22:36 gnuvince_: ayrnieu: I had a problem with slime-fancy, I fixed it by selectively enabling the contrib modules I wanted.

22:36 ayrnieu: oh well.

22:38 gnuvince_: But it was in the REPL, and I recall you saying you didn't use it with Clojure.

Logging service provided by n01se.net