#clojure log - Oct 28 2009

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

0:00 somnium: Licenser: heyyy

0:00 hiredman: rewriting syntax-quote-reader so it actually works is the only implentation let, after that I just need to clean my reader up, and figure out a nice way to include it in the build process

0:00 Licenser: I forked you :P muhahah

0:00 somnium: Licenser: almost got 0.1 ready

0:00 already?

0:00 its about to change a lot, for the better

0:00 Licenser: yea wanted to try it ^^

0:00 somnium: got a working little ClojureDBObject java class that does all that tree walking work

0:01 cleaning up the core so its actually readable now, dropping coerce.clj entirely

0:01 hiredman: http://rubyrags.com/products/10

0:01 Licenser: nice

0:01 somnium: I found a few things I needed and figured it's a good chance to try out github :P

0:01 somnium: its funny, after a night's sleep that java didn't look so bad

0:02 Licenser: What did you do before sleeping finish up a bottle vodka alone?

0:02 somnium: I'm considering doing an immutable proxy, itll be interesting to benchmark and see how much overhead using a ref involves

0:03 Licenser: heh yup that would be interesting

0:04 somnium: Licenser: a corner, a stuffed animal, and a bottle of vodka

0:04 Licenser: ah okay that explains a lot

0:05 somnium: also switch to 1.0 core and contrib, and I'll put the needed mongodb-drivers in the jar

0:05 hopefully itll be more plug and play

0:05 its never good when something can blow up on build

0:06 Licenser: true

0:06 somnium: Licenser: did you manage to do anything with it in any case?

0:06 Licenser: yes it is working quite well, biggest problem I had was that object-to-map did ont work on recursive objects

0:06 somnium: yeah, its tricky

0:07 Licenser: well that one I fixed :P

0:07 somnium: there are some things to do with encodings, but its broken right now and presumably the dev's are sleeping

0:07 cool

0:07 with a walker?

0:07 its hard to find non-recursive solutions to nesting problems

0:07 thats what the little java class helps with

0:07 Licenser: somnium: actually I borke it again ... narf

0:08 well I just recursively called the function

0:08 somnium: and keywords for keys again

0:08 Licenser: Oh you removed keywards as keys again?

0:08 somnium: I did before because it was broken

0:08 now they're back

0:09 the proxy class is a hashmap, you can bang on them in java

0:09 Licenser: heh Okay then I had the string version which brakes my code :P that is why I'm so confused

0:09 somnium: default is to convert stuff to clojure, but if you want to optimize something its right there

0:09 hmm, I would push but only fetch is working now, if youll be around for an hour it might be ready to try out

0:10 Licenser: I'll be

0:14 somnium: what do you think about a defschema macro? I don't think the keys on most leaf nodes won't vary too much, and that way the deserializer knows what to do with each key

0:15 qed: chouser: are you around?

0:15 chouser: im wondering if you could explain some stuff about your problem 59 on proj. euler

0:15 Licenser: defschema? I've a older version I think

0:16 this one still uses defcoercion

0:16 somnium: yeah, its orthogonal

0:17 http://paste.lisp.org/display/89409 <- sneak preview, more readable?

0:17 Licenser: so there isn't any defschema in the version I forked

0:17 somnium: yeah, I haven't added it yet

0:18 but I think most of the low level problems are almost done, so can start adding more ORMy features

0:18 Licenser: one thing, you should decide if you call it col or coll ;)

0:18 that was one of the things I changed :P

0:18 somnium: ah, in the arguments?

0:19 Licenser: yap the functions are called *-coll the arguments are called col

0:19 I found that kind of confusing in the beginning, since I wasn't sure if you refer to different things that start with col* there

0:19 somnium: I don't like using coll in arguments cause that's name clojure uses for collections

0:20 and collection is too many keystrokes

0:20 maybe Ill change it to 'c'

0:20 Licenser: then name the functions -col too ;)

0:20 somnium: ok

0:20 Licenser: oh and I changed every argument that was named map to m

0:20 somnium: look at the paste

0:20 Licenser: when you call an argument map, it hides the map function in the rest of the body :P

0:20 somnium: that function is what coerce.clj was

0:21 Licenser: oh wow

0:21 somnium: and it even does more :)

0:21 Licenser: toClojureKeywordArrayMap is sneaky

0:21 somnium: the keywords are kind of a hack, mongodb has no default way to recognize them

0:22 if I can get the encoding bug sorted tomorrow it might be possible

0:22 Licenser: I know they use string keys

0:22 somnium: mongodb supports custom binary types

0:22 the java driver doesn't support it, but eliot said it would be trivial to add

0:22 Licenser: yes but storing keywords in a custom binary, isn't it easyer to store them in strings

0:22 somnium: it is if a fast little java class does it for you

0:23 Licenser: Bah java classes

0:23 somnium: it'll be possible to create custom binary types for any arbitray class

0:23 Raynes: Bah, Java.

0:23 somnium: and that means defschema could gen-class a struct map, all kinds of cool and efficient automagic become possible

0:25 Licenser: =) yea I was wondering if you could use a structmap to represent the data since most of the time you've at least a subset of keys that are always there

0:26 somnium: yeah, and if you have embedded document slot the deserializer just has to know, know reflection, no tree walking

0:26 qed: damn you euler!

0:26 oiler = euler

0:26 coincidence

0:26 somnium: er, no reflection

0:26 Licenser: nice

0:35 I really see forward to the next version :P

0:37 somnium: I'm glad your helping test it, I want to make a good impression of mongo + clojure when I start encouraging people to try it :)

0:38 maybe you could write a mongo-compojure todo example :D

0:39 Licenser: somnium: I will once I get it working ;)

0:40 and I'll wait till you have it half way beta

0:40 somnium: yeah, I'm actually planning to use it for a prototype due next week

0:41 so I really want to get something worthy of 0.1 finished tonight

0:41 Licenser: heh

0:41 see and it's not much sense to write a how to when you change everything away under my ass while I write it .P

0:41 somnium: true

0:41 the readme I did was mostly an exercise in learn markdown :)

0:42 Licenser: ^^

0:43 mongo is a lot easyer then SQL once you get the things actually working o.O

0:44 somnium: yeah, the only place it falls down is if you need complex transactions

0:44 Licenser: true but at least I don't need them

0:44 somnium: though to be honest I can't recall the last time I needed them for a web app

0:44 Licenser: exactly :P

0:45 somnium: er, that should be never

0:45 Licenser: also I'm pretty sure you could wrap them in a clojure transaction and bunch commit

0:45 somnium: trouble is its all side effecty

0:45 the dbobjects, server messaging

0:45 no way the stm can help with that

0:46 mongo has to support it server-side

0:46 Licenser: true

0:46 somnium: hrm, does it support transactions at all?

0:49 Licenser: no mongo is non transactional

0:49 somnium: theres an 'update-if-current' command

0:51 if x = y, set x to z, else fail

0:51 that can lock an entire document

0:51 good enough for me :)

0:51 Licenser: heh

0:52 hrm

0:53 adityo: Good morning all

0:53 :)

0:54 Licenser: morning adityo

0:54 somnium: but I see your point mongodb destroys the nice concurrency of clojure, at least makes it not so easy :(

0:54 not that one needs it for a web app :P

1:00 somnium: who knows, mongo is developing rapidly, the dev team is awesome

1:00 every time I ask how to do something they say if its a bug we'll fix it, if not we'll try to add it

1:00 er, ask for something not supported (in the java driver anyway)

1:01 and within 10 minutes there's a fresh push to github

1:01 Licenser: yap

1:01 they seem cool

1:01 I was in the channel to ask a few questions and the peopel really helped me

1:01 my experience is that for underdog projects it's easyer to get help the more prominent a project is the less friendly are the people

1:02 try to ask a VB questions - no chance :P

1:02 somnium: heh

1:02 Licenser: seriousely, even the ruby community got gess friendly the more prominent the language became - at least it is my impression

1:03 For Solaris people try to help you for most linux distributions you get just told RTFM

1:03 somnium: Ive seen people be pretty rude in the ruby channels

1:04 Licenser: yes but it hasn#t beent that way some time ago (like in the area of years), at least I haven't seen it there

1:04 hrm I've a seriouse problem

1:04 somnium: ?

1:04 Licenser: update kills my db entry

1:05 somnium: thats no good

1:05 Licenser: if I don't pass all arguments to update it just removes the others o.O that is very odd

1:05 somnium: I would say paste the before and after, but its all getting rewritten

1:05 Licenser: ah, look at the code then, its meant to be used with all three arguments

1:05 the shorter versions should carry warnings

1:06 they're convenient if they do exactly what you want (or that was the intention)

1:06 Licenser: hmm but it's a mongo thing

1:06 somnium: really?

1:06 Licenser: yes it's scarry

1:07 somnium: something like {:match :this} (merge old-map {:change :this}) should work?

1:07 Licenser: not for bulk updates

1:07 somnium: ah, I haven't tried those

1:07 doing javascript?

1:08 Licenser: yes I tried it from the console now

1:08 to see if it is a problem with mongo, or with something between my app and mongo

1:08 since it happens on the DB it seems that it is a problem with mongo :P

1:09 ah I've to use $set

1:09 sneaky

1:10 somnium: there's a thread on the mailing list saying its not supported until 1.1.3

1:10 Licenser: I have 1.1.3

1:10 so I really would expect update to update not replace

1:11 ow

1:11 somnium: well, as long as its just surprising and not broken

1:14 Licenser: it tells me: when using $ modifiers, apply has to be false

1:15 seems like a problem in your driver :P *hides*

1:16 hrm not good

1:17 odd

1:17 somnium: hmm

1:18 what command exactly?

1:18 I took out the '> shortcuts for now

1:18 Licenser: update but diggind deeper it seems to come from java

1:18 nah I sed $set in the update statment

1:18 java.lang.IllegalArgumentException: when using $ modifiers, apply has to be false

1:18 that is what it says

1:19 somnium: { :x { "$set" : "this" } } ?

1:20 hmm, I know the java-driver better than I know how to use mongo at this point :(

1:20 Licenser: {$set: {:x "this"}}

1:20 this one

1:20 {"$set" {:x "this"}}

1:20 rather that

1:21 somnium: I think it should be {:x {"$set" ... } } no?

1:21 youre right

1:21 Licenser: works on the console like this: > db.map.update({x: 5, y: 5}, {$set: {"owner.id": 42}})

1:22 so this apply thing has to do with the java driver, which I've no clue off

1:22 somnium: ah I know

1:22 there's a flag on update

1:22 check the source, update sends true true at the end

1:22 usually you want apply, it adds _ns and _id if they're missing

1:22 Licenser: there are two flags, one says upsert the other multi

1:23 somnium: on the java call

1:23 Licenser: I know was the first thing I looked at but the API says those two are upsert and multi nothing with apply

1:23 somnium: I know I saw it somewhere

1:24 maybe BasicDBObject? or DBCollection?

1:24 Licenser: it is a function of the Collection

1:25 there is a apply function in the collection but I don#t see it called anywhere

1:25 somnium: will definitely need more granular control of cursors and collections in the api

1:26 is there a setter? setDoApply or something?

1:26 Licenser: nope only 3 methonds, apply, apply and doapply

1:27 somnium: hmm, I'm out of my depth

1:27 Licenser: me too sadly

1:31 somnium: Licenser: you can go low level for the time being, until the Mongo devs wake up

1:31 Licenser: somnium: hm?

1:32 oi a new one: No matching method found: updateMulti for class com.mongodb.DBApiLayer$MyCollection

1:32 while that is in the API documentation o.O

1:32 somnium: yeah the API Docs aren't totally reliable

1:32 there's a missing fetch with skip, limit options too

1:32 forgot to ask about that

1:32 it'll help if youre asking questions about the java driver too :)

1:32 Licenser: ah wait no it's in the wrong doc

1:32 *g*

1:33 somnium: DB has an eval method

1:33 you can send javascript, though I'm not quite sure how it works

1:33 hopefully anything broken in the driver can get through there when things like this happen

1:34 Licenser: ah sneaky

1:39 oh fork

1:39 of cause the DB does not know eval :P

1:40 somnium: the db object in *mongo-config* is actually a DBTCP, you might have to get a hold of a lower level class

1:41 just read the javadoc!

1:41 * hides *

1:42 Licenser: somnium: sadly DBTCP isn't documented :P

1:42 somnium: the DB class is, that's where eval lives

1:42 Licenser: actually it si

1:43 somnium: I was creating the DB object through Mongo which return a DBTCP object

1:43 but you can also go through the DB class? no idea, there's way too many classes in that damn package

1:43 Licenser: but it should have eval

1:43 somnium: yes there are

1:43 and I hate javadoc :P

1:43 it's the same problem as with every inline documentation

1:43 somnium: if the design is good and the package structure is good, they can be very useful

1:43 not the case here

1:44 Licenser: when you see the code of the function a half line doc might be helpful, if you don't it is often not

1:44 somnium: really, should ByteEncoder and BasicDBObject live in the same package?

1:44 Licenser: heh

1:45 sadly eval isn't documentaed at all

1:45 somnium: yeah, it sucks, no idea what the Object argument is supposed to be

1:46 Licenser: *nods* I skpped it since I found ... means 0 or more :P now I'll just pass #^Object nil

1:47 somnium: cool

1:47 Licenser: does not really work either

1:48 somnium: hmm

1:48 doseq update till the devs wake up?

1:48 Licenser: and netbeans seem to ahve a very odd idea about reloading

1:49 somnium: if youre feeling adventurous you could look at Message... classes

1:49 Licenser: heh

1:49 soon I can go and grab breakfast :P

1:50 user=> (mongo-eval! "db.map.update({x: 5, y: 5}, {$set: {'owner.name': 'Test Owner'}})")

1:50 #<BasicDBObject { "retval" : null , "ok" : 1.0 , "_ns" : "$cmd"}>

1:50 wooh!

1:50 somnium: awesome

1:50 could you paste mongo-eval! ?

1:50 Licenser: that works

1:50 sure

1:50 somnium: I'll definitely add that as a backdoor

1:50 it'll always need to be there :)

1:51 sweet

1:51 Licenser: wooh now I contributed :P

1:52 somnium: ! :)

1:52 huh, so it did work on DBTCP after all

1:52 Licenser: yap just you need a nil in there

1:55 okay this is so horribly going to break ...

1:55 somnium: ?

1:56 Licenser: the hacked together eval stuff :P

1:56 somnium: contrib.json might help

1:57 Licenser: I used the mongo one

1:57 somnium: I'm hoping to get a hook into the JSON writer too

1:58 or, actually there's one now, but it's broken

1:58 Licenser: heh

1:58 okay I will use contrib.json

1:58 somnium: it speaks native clojure at least

2:00 kanak: Which is better (more idiomatic/faster/etc): doing something like (reduce * [1 2 3]) or (apply * [1 2 3]) ?

2:00 somnium: kanak: reduce

2:01 kanak: thanks. is it because it signals the intention more clearly?

2:01 Licenser: apply is better

2:01 at least I find it

2:01 somnium: they do different things

2:01 it would be easier to say with something other than *

2:02 Licenser: yes but for this case it's faster to do (* 1 2 3) then (* (* 1 2) 3)

2:02 somnium: kanak: apply = unpack this list, reduce means create a single value from this collection

2:02 kind of

2:03 ,(time (apply + (take 10000 (iterate inc 1))))

2:03 clojurebot: 50005000

2:03 "Elapsed time: 56.728 msecs"

2:03 Licenser: woha yea!

2:03 somnium: ,(time (reduce + (take 10000 (iterate inc 1))))

2:03 clojurebot: 50005000

2:03 "Elapsed time: 28.939 msecs"

2:03 somnium: see its faster :)

2:04 kanak: cool :)

2:04 Licenser: okay now I'm impressed AND confused

2:04 kanak: is reduce a left-fold or a right-fold?

2:04 Licenser: hmm but I think that is because the list is unpacked the first time

2:05 hrm how again could I force a lazy seq to unlasy?

2:05 kanak: it'd be interesting if we could compare the space usage of the reduce vs apply.

2:06 Licenser: reduce will have less space usage

2:06 because it only needs 2 elements from the list

2:06 and if your list isn't static but a lazy seq they will be GC'ed at some point

2:07 kanak: Licenser: by 2 elements, you mean the "answer so far" and the the first element from the list. right?

2:07 somnium: yeah, reduce is a shortcut for loop

2:07 unless you need mutual recursion

2:08 ^^ doall and dorun, depending on what you want it to return

2:08 Licenser: kanak: yap

2:09 somnium: I wanted to have the expendet list in the end :P

2:09 I want to see if reduce is faster because it's faster or because the test case is a lazy seq

2:10 somnium: well, I don't know what the byte code did, but the test apply was like make a list with (* and those 10000 numbers)

2:10 actual limit is capped at 18 or so

2:10 kanak: Is this correct: since reduce, take and iterate are working lazily, when reduce needs the next element, it asks take, which asks iterate. So at each point we only have one element (i.e. the whole list is never in memory at any time)?

2:11 somnium: you have the answer so far and the next item in each iteration

2:11 until no more items

2:12 kanak: what about the previous items (i.e. items whose values have already been used)? They're simply discarded, and will be GCd right?

2:13 somnium: yeah, the current item only every exists as a local variable in the last stack frame

2:13 the previous version of the list too

2:13 so it handles memory well

2:13 Licenser: kanak: since noone knows what the GC does it can't be guaranteed

2:14 kanak: I see. thank you both :)

2:14 somnium: for small operations like that its probably on the stack

2:14 Licenser: but the list will never flood your memory

2:15 somnium: just dont do this

2:15 ,(iterate inc 1)

2:15 clojurebot: Eval-in-box threw an exception:java.lang.OutOfMemoryError: Java heap space

2:15 Licenser: :P

2:15 kanak: heh. that's evil

2:15 Licenser: I think the problem is the print

2:15 ,(def x (iterate inc 1))

2:15 clojurebot: DENIED

2:15 somnium: yeah, poor little guy tried to print the answer

2:15 Licenser: narf

2:16 ,(second x (iterate inc 1))

2:16 clojurebot: java.lang.Exception: Unable to resolve symbol: x in this context

2:16 Licenser: ,(second (iterate inc 1))

2:16 clojurebot: 2

2:16 Licenser: there we go

2:16 didn't took much time to calculate all numbers :P

2:17 somnium: ,(nth (iterate inc 7) 4242)

2:17 clojurebot: 4249

2:17 Licenser: hmm somnium the eval works fine, my project is running so far

2:17 somnium: Licenser: good to hear it

2:17 hmm

2:17 Licenser: hmm hmm

2:17 do you wonder what I wonder?

2:19 somnium: (nth (iterate #(+ 7 %) 0) 4242)

2:19 ,(nth (iterate #(+ 7 %) 0) 4242)

2:19 clojurebot: 29694

2:19 somnium: he counts pretty fast

2:19 Licenser: if you catch a hold of the mongodb dev people, could you ask them about the update thing? I'll not be around for the day since I've to head to wokr in 30 min

2:19 hiredman: ~clojurebot

2:19 clojurebot: clojurebot is amazing

2:19 hiredman: ~clojurebot

2:19 clojurebot: clojurebot is not a benchmarking platform

2:19 somnium: sure

2:19 lol

2:19 Licenser: somnium: comon it are only 4242 numbers

2:20 even ruby does it instantly

2:21 ~hiredman

2:21 somnium: could you paste what was broken? I'm not sure I know quite what to ask

2:21 clojurebot: hiredman is slightly retarded

2:21 Licenser: :P

2:21 hiredman: clojurebot: watch it

2:21 clojurebot: Huh?

2:22 hiredman: clojurebot: you heard me

2:22 clojurebot: hiredman: I'm just giving you a second chance

2:22 somnium: ~botsnack

2:22 clojurebot: thanks; that was delicious. (nom nom nom)

2:22 hiredman: clojurebot: why I outta!

2:22 clojurebot: why not?

2:23 somnium: hiredman: shouldn't (nom nom nom) come before he says delicious?

2:23 Licenser: and with

2:23 *

2:23 not (

2:23 actions are classically indicated with * IRC isn't lisp

2:23 ~somnium

2:23 clojurebot: No entiendo

2:24 hiredman: the nom nom thing is just another factiod, someone told it that was the proper response to "botsnack"

2:24 clojurebot: seen somnium

2:24 clojurebot: somnium was last seen in #clojure, 1 minutes ago saying: hiredman: shouldn't (nom nom nom) come before he says delicious?

2:25 Licenser: clojurebot: do you want cookies?

2:25 clojurebot: Gabh mo leithscéal?

2:25 Licenser: who set the bit to spanish o.o

2:25 somnium: hiredman: well I suppose that's true

2:25 hiredman: ~google Gabh mo leithscéal

2:25 clojurebot: First, out of 2180 results is:

2:25 Urban Dictionary: gabh mo leithscéal

2:25 http://www.urbandictionary.com/define.php?term=gabh%20mo%20leithsc%C3%A9al

2:25 somnium: ~php

2:25 clojurebot: Gabh mo leithscéal?

2:26 somnium: he really should have something to say about that

2:26 ~microsoft

2:26 clojurebot: No entiendo

2:26 somnium: ~java

2:26 clojurebot:

2:28 somnium: ~scheme

2:28 clojurebot: Excuse me?

2:30 hiredman: clojurebot: programmer is <reply>"There has to be something a little wrong with you for you to be a really good programmer." -- L Peter Deutsch

2:30 clojurebot: Roger.

2:30 somnium: ~self loathing

2:30 clojurebot: Titim gan éirí ort.

2:30 somnium: ~google Titim gan éirí ort.

2:30 clojurebot: First, out of 850 results is:

2:30 Irish phrases in the Gaelic language - Irish sayings

2:30 http://www.ireland-information.com/irishphrases.htm

2:32 adityo: ~lisp

2:32 clojurebot: Lisp isn't a language, it's a building material.

2:32 adityo: ~perl

2:32 clojurebot: Excuse me?

2:32 Licenser: i notice that there is a time X in every IRC channel where peopel start to play with the bot. I bet they have kind of cute kittens sitting on the PC's as IRC bots, it's the only explenation for the enormouse interest and affection they can raise in people

2:35 hiredman: I'd love to get clojure going on a pleo or an aibo

2:35 somnium: aibo was discontinued :(

2:36 hiredman: was the pleo for a bit, and now it's back

2:36 somnium: a lot of soldiers grow very attached to their bomb disarming robots

2:36 is it? good

2:36 hiredman: maybe even a little netbook+rc car

2:36 Licenser: no don't send the robot! I will go, we can't let him get hurt!

2:37 somnium: they've run into exposed areas to save them

2:37 Licenser: o.O

2:37 somnium: the designers apparently try to make them as unlikeable as possible

2:38 Licenser: wow that is crazy

2:38 hiredman: what is pleo?

2:39 somnium: ~google pleo

2:39 clojurebot: First, out of 1100000 results is:

2:39 PleoWorld: The Home of Pleo, the Robotic Baby Dinosaur from Innvo Labs

2:39 http://www.pleoworld.com/

2:39 arsatiki: it'd b cool to equip a pleo with a bluetooth receiver

2:40 so it could start following people who have their phones with them

2:41 somnium: ~gumstix

2:41 clojurebot: Pardon?

2:44 Licenser: haha that thing looks funny

2:45 but no shipping to germany, narf

2:57 okay peopel I need to go to work, take care and don't brake tne interwebs

2:58 somnium: cheers

2:58 kanak: is it more idiomatic to use memfn or to use an anonymous function?

2:58 somnium: (doc memfn)

2:58 clojurebot: "([name & args]); Expands into code that creates a fn that expects to be passed an object and any args and calls the named instance method on the object passing the args. Use when you want to treat a Java method as a first-class fn."

3:01 kanak: The programming clojure book claims that anonymous fns should be preferred to memfn, which sounds a little odd. (pg 87)

3:02 hiredman: #() fn literals are used far more often than memfn

3:02 memfn was created before #() existed, if I recall

3:03 kanak: I see.

3:03 hiredman: do you know of any projects with idiomatic clojure that is suitable for someone who is "intermediate" in clojure?

3:04 somnium: kanak: IMO the source code in contrib excellent for learning clojure idioms

3:05 kanak: core for that matter

3:05 kanak: somnium: any libraries in particular?

3:05 somnium: there's so many, the ones I use? :)

3:05 try using contrib.repl-utils/show on the functions you already know

3:05 kanak: sorry. i meant are there any particular ones you're thinking of

3:06 somnium: er, source, not show

3:07 core is best for 'idioms' probably

3:07 very generic operations

3:07 contrib is all specialized

3:07 hiredman: core.clj is very readable

3:09 kanak: thank you both for your help. :)

3:10 hiredman: http://delicious.com/clojurebot/pastbin+rhickey

3:10 http://delicious.com/clojurebot/pastbin+chouser

3:11 somnium: wow, hes already got a working prototype for defclass?

3:11 or is that a 'syntax prototype' ?

3:12 hiredman: http://delicious.com/clojurebot/pastbin+technomancy

3:12 somnium: I think it works, I haven't checked

3:12 somnium: I have to say, its exciting to watch a project develop with such speed

3:19 hamza: hey guys, URLConnection getHeaderFields returns an UnmodifiableMap how can i turn this in to a clojure map? (hash-map fields) returns illeagelArgumentException?

3:22 hiredman: hamza: (into {} fields) ?

3:25 hamza: thx that worked..

3:26 but some now some vals are wrapped in UnmodifiableRandomAccessList do i have to iterate all and build it my self?

3:31 hiredman: yes

3:32 G0SUB: what is the best way to manage settings for dev/production envs in a clojure app?

3:40 hiredman: well, you have a reader, so you can make a dev.clj and a production.clj

3:43 G0SUB: hiredman: how do I make sure one of the files is loaded automatically? (I am in Emacs/SLIME)

3:45 hiredman: (cond (.exists (File. "dev.clj")) (read (reader "dev.clj")) ...production.. ..testing...)

3:45 dev.clj has a map in it, so that is in a function that returns a map containg your settings

3:48 you could use a properties file if you want to be java about it

3:49 http://java.sun.com/javase/6/docs/api/java/util/Properties.html

4:06 G0SUB: hiredman: so, for production env, I will have to delete the dev.clj file?

4:07 Fossi: hi

4:14 hiredman: G0SUB: sure

4:14 w

4:14 huh, this ain't vim

4:18 G0SUB: hiredman: the thing is, I was to keep both the files, but would want to selectively load one depending on one system property

4:27 felzix: How do I find the intersection of two lists?

4:27 The function "intersection" doesn't appear to actually exist in the 1.0 release.

4:27 adityo: felzix: might be useful if you convert them in to hash-sets

4:28 how will i merge a list of maps ({} {} {}) into a {}

4:28 felzix: hmm

4:28 what version did intersection get introduced?

4:29 nvm, I see

4:30 adityo: ,(doc clojure.set/intersection)

4:30 clojurebot: "([s1] [s1 s2] [s1 s2 & sets]); Return a set that is the intersection of the input sets"

4:30 hiredman: ,(reduce into {} '({:a 1} {:b 2} {:c 3}))

4:30 clojurebot: {:a 1, :b 2, :c 3}

4:30 felzix: It keeps telling me that it can't resolve the symbol "intersection"

4:31 the same is true of other set functions

4:31 adityo: cool thanks hiredman :)

4:31 hiredman: felzix: are you using the clojure.set namespace?

4:31 adityo: felzix do a use or require

4:31 felzix: oh, I have to explicitly add it? I thought it came along with everything else

4:31 that works! thanks!

4:31 hiredman: it's included in the clojure jar

4:32 but you have to require or use it or load it like every other namespace

5:49 felzix: This function's return value isn't getting printed: (defn get-pos [tags]

5:49 (filter #(= (first %) \+)

5:49 tags))

5:49 any idea why?

5:50 Chousuke: printed where? in the repl?

5:51 also, what is "tags"

5:51 felzix: I'm running a script containing (println (get-pos rest))

5:51 it's a vector of strings

5:53 Chousuke: ,(println (filter (comp (partial = \+) first) ["+100" "100" "+50"]))

5:53 clojurebot: (+100 +50)

5:54 Chousuke: that would look a lot better in haskell :/

5:54 felzix: lol

5:55 oh. actually, it doesn't print anything after that call, even constant strings

5:55 so something else is amiss ;_;

5:56 Chousuke: weird.

5:56 maybe *out* is bound to something weird?

5:56 felzix: nah, printing works immediately before that call

5:56 Chousuke: huh

5:57 felzix: I get weird problems like this in clojure a lot. I suspect I'm misusing laziness somehow.

5:57 Chousuke: try using (doall (filter ...))

5:57 felzix: I tried that

5:57 Chousuke: though laziness really shouldn't affect this.

5:57 println will force the seq anyway

5:59 felzix: try adding (flush) after then printlns :/

5:59 the*

6:01 felzix: awesome!

6:02 it works. thank you!

6:03 so now at least I know the real problem is elsewhere

6:42 yuras: when I need to read X characters from BufferedReader. I see the way to do it by loop-ing: reading into characters array available bytes amount then converting to string, recur-ing until i have read X characters. maybe is there a better way? can I seq BufferedReader somehow?

6:43 Im sorry for my bad English.

6:52 looks like i can utilize slurp* from duck-streams

7:06 Fossi: we have the odd case that it seems that compojure is rendering faster if we put the "html-dsl" into a vector instead of leaving it in layz seqs

7:07 from what i have thought it should be slower because the list is traversed twice instead of only once during the render

7:07 somebody got a clue why that could be?

7:11 spuz: Hello, why is pos? called pos? What is that an abbreviation of?

7:12 Also, why is (seq col) preferred over (not (empty? x))?

7:15 liebke: spuz: pos? is an abbreviation for positive?

7:15 spuz: ah ok :)

7:30 Chousuke: spuz: for the latter... seq is shorter :)

7:31 spuz: Chousuke: but not so readable :p

7:31 Chousuke: spuz: it's only not readable if you know nothing about clojure :)

7:31 spuz: or you don't know about seq

7:32 Chousuke: well, everyone should :P

7:32 anyway, that usage of seq is idiomatic, so all clojure programmers are expected to understand it :)

7:32 spuz: Yeah, it's fair enough if it's a commonly used idiom

7:33 Chousuke: kind of like if (!someptr) ... in C

7:34 spuz: well that's C... :)

7:34 Chousuke: the idiom is still good

7:37 spuz: I find it interesting that sometimes Clojure appears to advocate making code easy to understand with its functional style, but other times seems to forgo readability for concision or elegance

7:38 I guess it comes down to what different people understand when looking at a piece of code

7:39 for some people, the less code, the easier it is to understand. For someone with no background knowledge it's the complete opposite

7:39 cgrand: spuz: plus the truth value of seq means more than the truth value of empty?. With empty? you wouldn't be able to write (if-let [[x & xs] (seq coll)] ...) because there's nothing more to extract from "true this coll is empty".

7:40 spuz: (I'm going to have to look up if-let in order to understand that)

7:43 cgrand: I don't understand why you would want to do something like that.

7:43 what are you trying to do?

7:44 cgrand: usually when you check if a collectin is empty or not, the next thing you are going to do is to process it

7:44 and if-let allow you to destructure the collection when it isn't empty

7:45 gerry_: hello

7:46 i'm doing clojure socket read/writer test, don't konw why it not work

7:46 i have attached reader and writer to one remote socket

7:47 spuz: cgrand I see, so that destructuring is an alternative to empty? first and rest ?

7:47 gerry_: first try readLine from socket it worked, but when i write to it, it always return nil to me

7:48 (def socket (Socket. "igs.joyjoy.net" 6969))

7:49 cgrand: spuz: yes this if-let could be rewritten (if (empty? coll) (do something) (let [x (first coll) xs (rest coll)] do domething else)))

7:49 or, using destructuring, (if (empty? coll) (do something) (let [[x & xs] coll] do domething else)))

7:49 gerry_: (def ins (reader (.getInputStream socket)) (def ous (writer (.getOutputStream socket))

7:50 that's it

7:50 (.readLine ins) work (.println ous "oops") not work

7:50 spuz: cgrand: that's nice :)

7:50 gerry_: i have tested it with telnet, it worked on both read and write

7:51 what's wrong?

7:51 telnet igs.joyjoy.net 6969 works

7:52 cgrand: spuz: another point of view of this argument is that there are more non-empty collections than empty collections, and, in clojure, there are more trues than falses (anything that isn't false or nil). So it feels righter to map the frequent cases (non-empty colls and trues) together. Hence it allows to return something more meaningful than simply "true".

7:52 shmichael: Hi everyone. Is there any way to determine in code if a given symbol is a macro?

7:53 gerry_: i can get one login: prompt from ins readLine

7:53 cgrand: (meta #'if-let)

7:53 ,(meta #'if-let)

7:53 clojurebot: {:macro true, :ns #<Namespace clojure.core>, :name if-let, :file "clojure/core.clj", :line 1166, :arglists ([bindings then] [bindings then else & oldform]), :doc "bindings => binding-form test\n\n If test is true, evaluates then with binding-form bound to the value of test, if not, yields else"}

7:53 cgrand: shmichael: see :macro true in the meta

7:53 shmichael: cgrand: awesome, thank you

7:54 cgrand: ,(-> #'when meta :macro)

7:54 clojurebot: true

7:54 cgrand: ,(-> #'map meta :macro)

7:54 clojurebot: nil

7:54 shmichael: cgrand: yes, that is exactly what I need

7:54 gerry_: hmm

8:01 does telnet directly output string to socket?

8:23 shmichael: ,(-> #'when let :macro)

8:23 clojurebot: java.lang.IllegalArgumentException: let requires a vector for its binding

8:24 gerry_: when-let?

8:26 shmichael: I am trying to test if symbols are macros

8:26 But this test fails for let

8:29 avital-: ,(meta let)

8:29 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/let

8:30 gerry_: ,(meta (var let))

8:30 clojurebot: {:macro true, :ns #<Namespace clojure.core>, :name let, :file "clojure/core.clj", :line 2851, :arglists ([bindings & body]), :doc "Evaluates the exprs in a lexical context in which the symbols in\n the binding-forms are bound to their respective init-exprs or parts\n therein."}

8:31 chouser: ,(-> #'let meta :macro)

8:31 clojurebot: true

8:31 chouser: looks right

8:31 gerry_: ,(-> #'let meta)

8:31 clojurebot: {:macro true, :ns #<Namespace clojure.core>, :name let, :file "clojure/core.clj", :line 2851, :arglists ([bindings & body]), :doc "Evaluates the exprs in a lexical context in which the symbols in\n the binding-forms are bound to their respective init-exprs or parts\n therein."}

8:33 avital-: ,(-> {:a {:b 3}} :a :b)

8:33 clojurebot: 3

8:33 avital-: nice

8:34 gerry_: ,(def socket (Socket. "igs.joyjoy.net" 6969))

8:34 clojurebot: DENIED

8:34 shmichael: gerry_: thanks

8:35 ,(-> let meta :macro)

8:35 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/let

8:35 shmichael: ,(-> (var let) meta :macro)

8:35 clojurebot: true

8:36 gerry_: #'let = (var let)

8:36 AWizzArd: chouser: I find you also are one :)

8:38 chouser: AWizzArd: but you're *named* like one. I can't compete with that.

8:41 AWizzArd: True. Although I have a double z (while I am aware there should be only one).

8:44 yuras: how to convert "1234" -> 1234?

8:44 AWizzArd: ,(Integer/parseInt "1234")

8:44 clojurebot: 1234

8:44 yuras: only java way, no built-in fun?

8:45 notallama: well, you could also use the reader.

8:45 yuras: ah ok

8:45 AWizzArd: yuras: this is not the Java way, it is the JVM way.

8:45 rhickey: ,(read-string "1234")

8:45 clojurebot: 1234

8:46 rhickey: but

8:46 AWizzArd: This would also work for very big numbers. But it does not document the code so well.

8:47 rhickey: ,(read-string "foo1234")

8:47 clojurebot: foo1234

8:47 rhickey: ,(Integer/parseInt "foo1234")

8:47 clojurebot: java.lang.NumberFormatException: For input string: "foo1234"

8:47 yuras: no questions. thanks

8:47 AWizzArd: ,(BigInteger. "999999999999999999999999999999999999999999999") ; also works for possibly huge numbers

8:47 clojurebot: 999999999999999999999999999999999999999999999

8:48 AWizzArd: and this is 5x faster than read-string

8:49 yuras: ,(BigInteger. "foo123")

8:49 clojurebot: java.lang.NumberFormatException: For input string: "foo123"

8:50 eevar2: ,(read-string "99999999999999999999999999999999999999999999999999999")

8:50 clojurebot: 99999999999999999999999999999999999999999999999999999

8:50 rhickey: ,(bigint "1234123732198712398732178123987")

8:50 clojurebot: 1234123732198712398732178123987

8:50 AWizzArd: ,(BigInteger. "abc123" 16)

8:50 clojurebot: 11256099

8:51 AWizzArd: ,(BigInteger. "lfvegohplhcowhgpvlw0923857pn3w9207p" 36)

8:51 clojurebot: 1760061993066943724720314159425702321837801663530174101

8:51 AWizzArd: :)

8:52 arsatiki: you just never know when you're gonna need something in base 19 :)

8:54 gerry_: bigint not recognize other than 10base,right?

8:55 AWizzArd: ,30rRIGHT

8:55 clojurebot: 22370939

8:56 djork: wow nice

8:58 gerry_: what's 30rRIGHT?

8:58 notallama: base 30

8:58 arsatiki: the number RIGHT in base 30

8:58 gerry_: oh

9:00 ,16rabcd

9:00 clojurebot: 43981

9:04 gerry_: ,(-> 1 (+) (-) (*) (/))

9:04 clojurebot: -1

9:05 gerry_: ,(into {} [:a 1 :b 2])

9:05 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: Keyword

9:06 AWizzArd: ,(into {} [[:a 1], [:b 2]])

9:06 clojurebot: {:a 1, :b 2}

9:07 notallama: ,(apply hash-map [:a 1 :b 2])

9:07 clojurebot: {:a 1, :b 2}

9:07 gerry_: nice

9:08 i donot figure out "into"

9:09 (into {} '(:a 1 :b 2))

9:09 chouser: (into a b) is essentially (reduce conj a b)

9:10 gerry_: ,(conj {} '(:a 1))

9:10 clojurebot: java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.util.Map$Entry

9:10 notallama: ,(seq {:a 1, :b 2})

9:10 clojurebot: ([:a 1] [:b 2])

9:10 notallama: map elements are pairs. that's your trouble.

9:11 gerry_: ok

9:12 ,(conj {} [:a 1])

9:12 clojurebot: {:a 1}

9:13 gerry_: thx

9:16 rhickey: so, in looking at defclass/deftype extensibility, I see 3 options: a) none, b) add extension fields explicitly (api tbd) assoc throws if key not present, c) implicit extension via assoc of not present key

9:17 my current feeling is that references (get/assoc) t fields not present should throw, just like fields access to fields not present throws, or vector index out of bounds

9:17 chouser: picking too high a letter has worse consequences than picking too low a letter

9:19 gerry_: chouser: you mean a?

9:19 rhickey: yes, although these would just be defaults, could opt out or for something else

9:19 I wonder how often field extensibility will be used, and in what ways

9:20 I've decided you'll always get metadata support

9:20 chouser: gerry_: I mean if (a) is implemented, it would be easy to move to (b) or (c) later. If (c) is deployed, moving to (a) or (b) will be a breaking change.

9:20 gerry_: oic

9:21 chouser: I think (a) is pretty reasonable -- let people get used to these new constructs and see if there's much demand for expando and what those use cases look like.

9:21 rhickey: even with a), there's still a question of throw on get of non-field

9:23 chouser: I can imagine the assumption-checking of a throw on a bad get being helpful, esp. if there's no expando support at all.

9:24 rhickey: aargh, is a mismatch with vector:

9:24 chouser: once fields can be added on the fly the throw on a bad get seems like it might get annoying.

9:24 rhickey: ,(get [0] 1)

9:24 clojurebot: nil

9:24 rhickey: ,([0] 1)

9:24 clojurebot: java.lang.IndexOutOfBoundsException

9:24 rhickey: chouser: really, you think the dynamic fields make a difference?

9:25 in my view, these structures are not like collections, so it's semantically less 'lookup' than 'access'

9:26 gerry_: i vote for expando support

9:26 chouser: I think so -- if a particular type has a fixed set of fields, looking up something other than one of those is a programming error frequently detectable (in theory) at compile time, so a throw at runtime seems to fit.

9:27 But if one objects of that type can have different fields from each other (b or c) then you're going to want to start asking if an object has field :foo or not, and (:foo obj) is the most common way to test for that -- would be annoying if it threw

9:28 * chouser can't remember enough python syntax to figure out what it does here.

9:29 gerry_: i think if expend field, the type of object should change also,old object should be discard

9:29 rhickey: people have asked for a throwing getx already, could just be a general function

9:30 gerry_: that's a whole different thing - you could just pour it into a map then

9:30 expando is about retaining the type

9:31 but you can't dissoc a base field and retain the type

9:32 if get threw then you could use (get x k not-found) for speculative reads

9:32 chouser: these are real types, right? With a set of interfaces implemented. Having that change when you do an assoc or dissoc would be unfortunate.

9:33 (x k nil)

9:33 gerry_: then i agree with chouser :)

9:33 chouser: (:k x nil) ... either way isn't too bad I suppose.

9:33 rhickey: chouser: defclass is a fixed type, deftype is an anonymous type, but with a stable type tag

9:34 I think if the not-found version doesn't throw, then you are set

9:35 since you'll have to know what you want if it's not there anyway

9:35 if we go with b), need an api for add-field/key

9:36 chouser: yeah, I could live with (x k nil). seems like a idiom change, but not a onerous one.

9:37 rhickey: I think the vast majority of code manipulating these things will be using known fields

9:37 chouser: what's the benefit of (b) over (c)?

9:37 rhickey: same - protection against accident. people that don't want expando, but are getting it by default, really don't want accidental expansion

9:38 cemerick: where might I look at the menu?

9:38 rhickey: rhickey: so, in looking at defclass/deftype extensibility, I see 3 options: a) none, b) add extension fields explicitly (api tbd) assoc throws if key not present, c) implicit extension via assoc of not present key

9:39 menu^^

9:39 chouser: but if it's easy to turn off the default expando support, you have protection right there. is it worth a new api for people who want to keep expando support but want protection from it?

9:40 rhickey: also - should (get x k) throw if k not present on a defclass/deftype thingy (new word for thingy desired)

9:40 chouser: "should (get x k) throw if k not present on a clabango"

9:41 cemerick: probably not IMO, although that makes nil values tricky

9:41 rhickey: chouser: if (get x not-present-k) throws then b) seems symmetrical

9:41 cemerick: and I'd prefer C, FWIW

9:41 chouser: to be clear, if (get x bad-k) throws for one of these instances, would it also throw for regular maps?

9:41 gerry_: C

9:42 rhickey: the whole point of these things is to replace classes/structs/ADTs etc

9:43 chouser: the existing apis are collection oriented, not structure oriented, this is coming from the other end - small fixed things

9:43 dynamic typing still means typing, i.e. some runtime check for correct use

9:44 its correct to add and lookup arbitrary things in a collection, not so for enumerated structs

9:44 chouser: that sounds like (a)

9:45 rhickey: (deftype Foo [a b c]) (let [f (Foo 1 2 3)] (:d f)) is just a plain mistake

9:45 cemerick: I strongly disagree. Without C, miscellaneous or orthogonal data will drift into meta, which is often not desirable semantically.

9:45 or structs will grow a near-universal "properties" slot.

9:45 chouser: for (b) we'd need a new assoc, so a new conj would also be desirable and therefore a new into

9:46 rhickey: cemerick: that doesn't demand c), b) would work ass well

9:46 as well

9:46 cemerick: rhickey: does B buy anything w.r.t. perf, or is it just a "protective" policy

9:46 ?

9:47 rhickey: chouser: I'm not sure. At some point where you will be using assoc not for 'setting' an existing key but for establishing a new one, well, I think you are doing that more explicitly with these things than with collections. assoc for setting existing key wtill works fine

9:48 there's definitely an analogy to the associativity of vectors, where you can't get a new index by merely associng into space, you need to conj

9:48 cemerick: dunno

9:49 i.e. assoc on vectors only works for existing 'keys'

9:49 user=> (assoc [0] 0 1)

9:49 [1]

9:49 user=> (assoc [0] 4 1)

9:49 java.lang.IndexOutOfBoundsException (NO_SOURCE_FILE:0)

9:49 chouser: but at least 'into' still works on vectors. sounds like B would allow into to work only for pre-defined keys, not for expando? feels weird.

9:50 rhickey: chouser: conj could be the way to expand

9:50 cemerick: unless there's a specific benefit that warrants the mental overhead of managing whatever API comes with B, it doesn't seem worth it.

9:51 rhickey: cemerick: the benefit is that these things work like classes, not collections, since that will be their overwhelmingly primary useage

9:51 chouser: heh. cemerick and I are on the same side unless B gets rules out.

9:52 so (conj o [:new-key x]) might work but (assoc o :new-key x) might throw?

9:52 rhickey: I think you have to ask - why use these things rather than, say, just maps?

9:53 chouser: yes, same as vectors

9:53 chouser: hmph.

9:53 cemerick: rhickey: Because you have a set of standard, defined slots, and then a set of optional slots that are context-dependent, for example.

9:54 and, having better-than-map perf for those standard slots is a huge benefit

9:54 rhickey: one reason is to be able to implement interfaces, but you could do that with proxy, the other is that you weren't even using maps and couldn't, you were writing Java, There, you got compile-time enforcement of - can't access non-field 'd'

9:55 now you are going to move that code and not even get runtime enforcement of same

9:57 chouser: allowing (conj o [:new-key x]) hardly seems like enforcement

9:58 rhickey: chouser: it teases out the difference between set-existing and expansion, assoc sometimes does both (only for arbitrarily indexable things), conj always expands

9:58 set-existing is super important for straight data structures

9:59 cemerick: Hum. Programming with map-like things is Good. Getting field-like perf on pre-defined map slots is even better. Having to jump through hoops to expand the map-like thing is bad.

10:00 chouser: (into o {:all 'new :keys 'here}) is hardly jumping through hoops though

10:00 cemerick: the hoops here being having to ask "do I have a map or a deftype-thing?" any time one wants to push a value into an object.

10:00 rhickey: cemerick: conj is sitting right there

10:00 cemerick: chouser: on every assoc you might want to do?

10:01 chouser: but if you actually mean to set a particular pre-defined key, knowing that (assoc o :good-key x) will catch typos might be helpful

10:01 rhickey: cemerick: I grant that moving exisitng map-based code onto b) is a problem

10:02 chouser: and it's so much less ugly than (set! (.good_key o) x)

10:02 cemerick: I know, but I still don't see the point of setting up the obstacle course. assoc works over *here*, but not over *there*, etc.

10:02 typos? Surely a useful piece of functionality isn't going to get lopped off to "prevent typos". :-/

10:02 rhickey: could be that the stricter put could get a new name

10:04 cemerick: the typo becomes an undetectable error, these are dynamic 'types' not bags of stuff

10:04 we already have bags of stuff

10:04 and they are great

10:05 * chouser busily changes . to -> and vice-versa in various pieces of copy/pasted C++ code...

10:05 cemerick: indeed. I'm just saying that the opportunity appears to be available to have a 1 + 1 = 3 situation.

10:05 rhickey: but they are substantially less definite than what people expect from types

10:06 cemerick: I'm not sure b) isn't 3

10:06 these semantics are already in place (i.e. assoc might fail on invalid index, conj adds)

10:07 and these types might want to distinguish

10:07 cemerick: It's probably a 2.3 or something. Catching typos or trying to maintain the integrity of a type, etc., seem pretty hand-wavey to me as reasons not to ensure that all map-like things share as many semantics as possible.

10:07 rhickey: as possible

10:09 cemerick: Right -- vectors aren't sparse, so associng count + N simply can't succeed. maps and deftype-things don't have that hard restriction, tho.

10:09 ttmrichter: I'm going through the "Programming Clojure" book and hit a weird snag. The code that renames keys in maps doesn't seem to exist anymore. Using it gives me errors and trying (doc rename) also gives me an exception. What has the function name been changed to since the book's writing?

10:09 rhickey: cemerick: they do when backed by a non-expando class

10:10 or a bean, say

10:10 cemerick: rhickey: well, that's something that the programmer decided upon (or had decided for them, based on other decisions about framework usage, etc).

10:11 djork: ttmrichter: are you sure rename is not defined somewhere else in the book?

10:12 chouser: ttmrichter: page 118 just under "Functions on Sets" sneaks in a (use 'clojure.set) that you need to call.

10:12 tmountain: is there a builtin way to print to stderr? right now I'm using a macro to wrap a *out* to *err* binding.

10:13 rhickey: cemerick: didn't you argue against dissoc for structs?

10:13 ttmrichter: chouser: I seem to be reading a different book than you. Page 118 isn't functions on sets for me.

10:13 chouser: ttmrichter: hmph.

10:14 djork: ,(defn rename [map key new-key] (let [value (map key)] (assoc (dissoc map key) new-key value))) (rename {:foo :bar} :foo :blah)

10:14 clojurebot: DENIED

10:14 djork: wut

10:14 ttmrichter: chouser: I know whereabouts to look though, I think. I'm scanning quickly.

10:14 djork: ,1 2

10:14 clojurebot: 1

10:14 cemerick: rhickey: indeed, because removing a defined slot is a violation of an established type contract in a way that an addition of an arbitrary, undefined slot isn't.

10:14 Clearly IMO, of course. :-)

10:14 chouser: ttmrichter: well, just try (use 'clojure.set) and then see if the examples you're trying to run work.

10:15 ttmrichter: chouser: 138 for me. It seems I have 20 extra pages somewhere. :D

10:15 chouser: djork: that's clojure.set/rename-keys which is not quite the same as clojure.set/rename

10:15 ttmrichter: chouser: Thanks for the pointer. That would have driven me nuts for a while!

10:15 djork: k

10:15 chouser: ttmrichter: weird. I heard there was a second printing -- I wonder if that's what you have?

10:15 djork: just farting around, don't mind me

10:16 ttmrichter: chouser: I have no idea, honestly. I've got the PDF here. The hardcopy is (literally) on the slow boat to China.

10:16 chouser: ttmrichter: heh. ok.

10:17 ttmrichter: Is this generally true for the data structure-specific functions: a (use 'foo) clause is needed for them?

10:18 chouser: ttmrichter: no, clojure.set is the only one with its own lib

10:18 ttmrichter: and it's mostly about relational sets-of-maps, not just plain sets of values.

10:18 rhickey: in the end this is less about assoc than it is about get. If a defthing is non-expando (this will still be possible), then assoc on non-field will have to fail. get of non-key should fail as well, stronger (dynamic) type checking all around. Introduce expansion, then the question is should get move to more relaxed as does assoc? Or is there just an a/b/c knob?

10:19 ttmrichter: chouser: Yes, i'm gathering that looking at the examples. It's kind of cool to see the primitives of a relational-like database being made before my eyes here. Good book.

10:19 rhickey: in most expando systems, get on missing fails, set on missing creates

10:20 cemerick: rhickey: fails with error, you mean, or just nil?

10:20 rhickey: error

10:21 a completely different way of looking at this is that deflcass defines classes with ordinary fields. You can access them with .field. Saying .missing is a throwing error

10:22 cemerick: huh. In all three languages I've used that had 'expando', get misses return nil (js, python, and clojure)

10:22 rhickey: but defclass requires AOT, and you want more flexibility, so you move to deftype and :field

10:22 cemerick: I don't think there's any conflict in saying .missing is an error, but (get foo :missing) returns nil.

10:23 rhickey: null or missing/undefined

10:23 ?

10:24 cemerick: well, python only has None

10:25 I'm pretty sure js returns its nil

10:25 yeah, js returns null from document["blah"]

10:26 chouser: js has too many nulls

10:26 cemerick: I think it has an Undefined as well, but I'm not clear on where it's used.

10:27 chouser: x["missing"] actually returns undefined

10:29 cemerick: hrm, maybe firebug is screwing with me

10:30 chouser: are you sure? Object()["foo"] == null here

10:30 djork: anybody here using LWJGL with Clojure?

10:30 chouser: firebug's console shows undefined as nothing at all

10:30 cemerick: undefined == null :-(

10:31 cemerick: but undefined !== null

10:31 djork: in JS you can just do undefined = x

10:31 cemerick: huh. OK...well, Object()["foo"] == null as a single expression returns true *shrug*

10:31 djork: undefined is not a keyword

10:31 undefined just happens to be undefined most of the time

10:32 chouser: cemerick: Object()["foo" ] === null returns false

10:32 cemerick: Object()["foo" ] === undefined returns true

10:34 cemerick: hahhaha

10:34 chouser: djork: I did not know that. ...so horrible.

10:35 djork: Object().x == undefined; // true

10:35 undefined = "haha"; Object().x == undefined; // false

10:36 rhickey: um, I think it's obvious we don't want to mimic js :)

10:37 djork: indeed :)

10:37 I like my languages to inspire confidence.

10:37 JavaScript is fine, but man does it make me paranoid.

10:38 speaking of JS, if you haven't already seen it do check out Safari's recent JS console... it's pretty much the nicest I've seen anywhere

10:38 completion and automatic pretty-print of objects

10:39 fogus31415926535: Oh I don't know... there may be a market for a "Clojure: The Good Parts" book. ;)

10:40 djork: just print /api

10:40 done

10:42 chouser: but python might be interesting to look at -- they've moved some extendable-objects to faster-objects I think, I just can't remember the details.

10:43 rhickey: >>> x = "foo"

10:43 >>> x.foo

10:43 Traceback (most recent call last):

10:43 File "<stdin>", line 1, in <module>

10:43 AttributeError: 'str' object has no attribute 'foo'

10:44 chouser: >>> object().x = 5 AttributeError: 'object' object has no attribute 'x'

10:45 vy: Is there a `prog1' equivalent in Clojure?

10:46 chouser: >>> class Foo(object): pass

10:46 >>> Foo().x = 5 # no error

10:47 >>> foo=Foo(); foo.x = 5; foo.x # returns 5

10:47 rhickey: >>> class Foo(object): pass

10:47 ...

10:47 >>> Foo().x

10:47 Traceback (most recent call last):

10:47 File "<stdin>", line 1, in <module>

10:47 AttributeError: 'Foo' object has no attribute 'x'

10:48 chouser: so an error to get non-existant, but setting is ok after which getting is ok

10:49 rhickey: that's what I meant before: "rhickey: in most expando systems, get on missing fails, set on missing creates"

10:49 chouser: >>> class Foo(object): __slots__ = ["a", "b"]

10:50 >>> Foo().x = 5 # AttributeError: 'Foo' object has no attribute 'x'

10:50 so you can turn off python's expando for a particular class.

10:51 rhickey: but every time I've built an exception into something I've regretted it, since you can always build a throwing thing on a non-throwing, but not the other way round without ugliness, so I'd be ok with a getx which you could build on (get x k notfound)

10:51 assoc will have to fail for non-expando

10:51 fogus31415926535: In Python get on missing doesn't always fail if there is some magic in __getattr__ to handle

10:51 cgrand: vy: "do"

10:53 vy: cgrand: I think you're confusing it with `progn'.

10:53 rhickey: vy: no prog1

10:53 chouser: vy: (let [x foo] ... x)

10:55 cgrand: vy: sorry, I read too quickly

10:55 * cgrand goes back to work

10:55 rhickey: more controversy - keywords only for defthing keys, even expando?

10:55 chouser: oh, wow.

10:57 rhickey: might not be necessary for expando, but definitely for base fields

10:57 chouser: right. any name restrictions on the base fields?

10:57 - converted to _ ?

10:57 rhickey: chouser: I'm not doing any munging right now, but should be subject to standard munging

10:58 ,(clojure.lang.Compiler/munge "foo-bar*baz")

10:58 clojurebot: "foo_bar_STAR_baz"

10:58 chouser: Isn't a) just terribly tempting?

10:59 rhickey: chouser: yeah - I'd so be done right now :)

10:59 lisppaste8: fogus pasted "__getattr__" at http://paste.lisp.org/display/89435

11:02 rhickey: so Im shooting for (deftype/class Name [fields] [interfaces] & methods), where interfaces and methods optional

11:03 still need a good way to say no thanks to specific auto-interfaces, thinking about #^{:disable [IThis IThat]} [interfaces], but would require a dummy [] if you weren't specifying any

11:04 cemerick: just to refresh my memory -- are assoc, conj, et al. protocols in the new regime?

11:04 rhickey: cemerick: will be

11:04 kanak: can someone help me understand what this means: "Vars - isolated changes within threads." Are these the same threads as Java Threads or something different?

11:05 rhickey: but will be based on interfaces, meaning implementing the interface gets you into the protocol

11:05 kanak: same

11:05 cemerick: In that case, adding Associative onto deftype implemented using option A should be pretty straightforward.

11:06 kanak: so if i have two threads and one of the vars changes the value, the other thread won't see it. right?

11:06 *one of the threads changes the value of a var

11:07 rhickey: cemerick: really - where would the extension map live?

11:07 protocols can't add/require more data slots

11:08 cemerick: no, there'd have to be a macro for it

11:08 rhickey: cemerick: these things are just macros now anyway (deftype/defclass), and not large ones

11:08 so creating similar things will be easy

11:09 but I'd like to get two good defaults in place

11:10 which is driving an interface for dynamic types that will provide sufficient reflection/access to writing similar things won't even require something as involved as defclass/deftype

11:10 so writing

11:14 opinions - keywords only for defthing keys?

11:16 cemerick: yeah, that seems perfectly reasonable.

11:16 fogus31415926535: here here

11:17 chouser: that's consistent with them being for small relatively-fixed things rather than large collections.

11:19 fogus31415926535: sorry if i missed this, but what would ::x vs. :x mean in the body of a defthing?

11:20 maacl: Can anyone give me a hint on how to convert any of the Clojure quicksorts on Rosetta Code http://rosettacode.org/wiki/Quicksort#Clojure to use recur or make them lazy?

11:20 chouser: maacl: generally to avoid stack-consuming recursion you have to rework the code to use an explicit accumulator.

11:21 rhickey: fogus31415926535: vs what?

11:21 fogus31415926535: ::x is a namespace-qualified keyword

11:21 ,::x

11:21 clojurebot: :sandbox/x

11:25 maacl: chouser: but that is a bit hard for a sort that relies on splitting a sequence recursively

11:25 or am I missing somthing

11:25 chouser: I think "a bit hard" is accurate. :-)

11:26 maacl: chouser: ok, any hints on the direction to take - other than an accumulator

11:28 fogus31415926535: understood. perhaps i'm behind the curve. if the defthing key keywords be on access and definition, then how does one specify something like self.x in the body of an associated method?

11:28 AWizzArd: Do all agents share the same thread pool?

11:30 maacl: chouser: is the Scheme version http://rosettacode.org/wiki/Quicksort#Scheme anything to emulate?

11:36 chouser: maacl: hm, I guess I can't read scheme well enough to know for sure, but it looks promising

11:36 maacl: chouser: at least there is no direct recursion

11:37 stuartsierra: How could sort be lazy?

11:37 chouser: is (let loop ...) defining a function?

11:41 fogus31415926535: let loop defines a named loop... kinda like a recur point but can be called from anywhere -- not just tail

11:42 chouser: ok, so that ought to translate pretty directly if not necessarily idiomatically.

11:43 nope, scratch that -- that scheme version uses the stack too

11:44 (let q ... (append (q ...) (q ...)))

11:47 duncanm: dum de dum

11:48 rhickey: there's nothing inherently wrong with using the stack, tree-based things do it all the time, as long as depth not prohibitive

11:48 duncanm: how does SORTED-KEY know how to sort the elements?

11:48 chouser: yes, but that was maacl's question. there are stack-consuming Clojure examples on that site, but none that don't.

11:49 rhickey: sorry, missed that

11:50 falkor: Hi, can anyone explain what is wrong with this: (let [x '.toUpperCase] (println (x "a"))) ?

11:50 I just want to be able to decide, in runtime, which Java method to call...

11:50 duncanm: falkor: write a macro

11:51 maacl: chouser: and they blow up sorting 1000 ints, which makes them not very useful

11:51 AWizzArd: It could be helpful during development to have a optionally a configurable message being printed when doing a (in-ns ...).

11:52 chouser: maacl: the sort function works really well if all you want is "useful" :-)

11:52 AWizzArd: ,(let [x #(.toUpperCase %)] (println (x "a"))

11:52 clojurebot: EOF while reading

11:52 stuartsierra: AWizzArd: the ns macro has a :verbose flag

11:52 maacl: chouser: :-) it's just and exercise

11:53 chouser: yeah

11:53 AWizzArd: falkor: (let [x #(.toUpperCase %)] (println (x "a")))

11:53 ,(let [x #(.toUpperCase %)] (println (x "a")))

11:53 clojurebot: A

11:53 duncanm: AWizzArd: i think he wants to be able to change the ".toUpperCase" method call based on some input, for that, you'd be a macro, right?

11:53 AWizzArd: If you want to forward native jvm methods wrap them into a #()

11:54 duncanm: you'd need to write a macro

11:54 i can't type today

11:54 AWizzArd: Tho I would like to be a macro from time to time.

11:54 stuartsierra: thx

11:54 falkor: duncanm , correct!

11:54 duncanm: rhickey: i see that there's a proposal for SORTED-KEY-BY, is that to be incorporated soon?

11:55 rhickey: duncanm: what proposal?

11:55 duncanm: http://www.assembla.com/spaces/clojure/tickets/79

11:56 AWizzArd: falkor: how will you make this descision? Do you know the set of methods that you potentially want to call during coding time?

11:56 duncanm: oh, the last diff was only submitted on the 20th, so i guess it's not fully baked yet

11:58 rhickey: duncanm: yes

11:59 yuras: when I execute clojure script passing its name to java .. clojure.main, can it :use some of my sources without compiling to classes? is there any rules about that?

12:01 AWizzArd: stuartsierra: do you have a minimal example that shows how to use the :verbose flag in (ns ...)?

12:02 stuartsierra: (ns hello :verbose)

12:02 hiredman: yuras: yes

12:04 yuras: clj sources should be in class to be visible for the "script"?

12:04 in the classpath*

12:05 AWizzArd: stuartsierra: maybe this is a recent addition? For me this throws an "IllegalArgumentException: Don't know how to create ISeq from: Keyword"

12:05 stuartsierra: maybe it was (use ...), not (ns...)

12:06 AWizzArd: Interesting would be if I could configure a message that gets printed when I (in-ns into-my-namespace).

12:06 printing a to-do list, or anything that i want to remember, something like that

12:07 stuartsierra: Try putting a watcher on *ns*

12:07 Don't know if that will work, but it would be interesting to try.

12:08 chouser: maacl: the ones on the wiki work fine for *random* collections up to at least 10000 -- but it pivots on the first item so (range ...) is worst-case

12:13 yuras: looks like path to sources should be in the classpath. adding "." solved my problem :)

12:31 lisppaste8: chouser pasted "tail-recursive qsort" at http://paste.lisp.org/display/89442

12:32 chouser: I'm sure that can be cleaned up

12:33 It seems that it could be made lazy which would allow you to get the first of the sorted list in O(n) time, which is somewhat interesting.

12:43 jasapp: somnium: you around?

12:48 drewr: gzip-file http://gist.github.com/220607

12:48 I'm trying to figure out why this fails for large files

12:49 it doesn't fail technically, but it doesn't successfully gzip

13:00 hiredman: hah!

13:01 my reader no longer has dependencies on LispReader and it builds clojure and runs all the clojure tests with no errors or failures

13:02 tmountain: drewr: could it have anything to do with fixing your buffer size at 8192?

13:03 drewr: tmountain: I suppose so, though I don't see how to read() and write() without it

13:05 Chousuke: hiredman: neat.

13:05 drewr: tmountain: if I reduce my test file to under 8k it works

13:05 so I'm not using that buffer correctly

13:07 Chousuke: hiredman: I still get that completely weird error :/

13:09 I think it might have something to do with my syntax-quote macro

13:09 but, hm

13:11 I guess I could test. :)

13:12 yuras: what great software written using clojure can I examine and learn from?

13:12 Anniepoo: Clojure! 8cD

13:12 lpetit: yuras: clojure :)

13:13 Chousuke: Clojure is 80% java though :P

13:13 ~github

13:13 clojurebot: http://github.com/richhickey/clojure/tree/master

13:13 chouser: not for long

13:13 yuras: clojure itself does not account, but its great dont argue :)

13:13 ambient: yeah, clojure is definitely the best software to learn clojure :)

13:13 at least for me

13:14 Chousuke: oh, only 74%

13:14 Anniepoo: actually, if you want to look at good Clojure, I'd suggest many of the clojure-contrib libs

13:14 ambient: reading through the sources

13:14 Chousuke: http://github.com/richhickey/clojure/graphs/languages

13:14 lpetit: yuras: though you will learn more for "programming in the small" than "programming in the large". Though this may not be totally correct, since "programming in the small" with higher order functions is an open door to "programming in the large" :-)

13:14 Anniepoo: they're often more accessible and feel more like application programming

13:16 Anybody know if they've put enclojure on a netbeans plugin server somewhere?

13:16 lpetit: yuras: probably (though I did not look at it myself), Stuart Sierra altLaw project

13:16 drewr: tmountain: I wasn't capturing the length that read() returns

13:16 updated gist

13:16 Anniepoo: (as in, I'm lazy and don't want to compile it, I just want to use it)

13:17 tmountain: drewr: does it work now?

13:17 drewr: tmountain: yep

13:17 yuras: but i need to learn some more general patterns, like making servers and building infrastructure, designing resusable server is a bit hard for me using lisp-1 language. atm im building json rpc server and looking for idea what is the best way to "pass" exported functions to the server. for example python uses dispatch function for simple XMLRPC server. any directions to the book are welcome :)

13:17 drewr: though I don't care for the duplicate read()

13:19 yuras: i feel like my bad english does not allow me to explain what i need :)

13:19 Chousuke: hmmh.

13:20 hiredman: you want to do dispatch?

13:20 yuras: basically i has problem building simple and easy interface for json rpc server

13:20 hiredman: there are many ways to do that, the simplest is just a map of whatever to functions

13:20 Anniepoo: you might look at webjure

13:21 hiredman: ,(-> "addition" {"addition" +} (apply [1 2]))

13:21 clojurebot: 3

13:21 yuras: yeah, but what if programmer will need more than just simple map from names to function. then should i provide ability to use dispatch, right?

13:22 hiredman: depends

13:22 Chousuke: hiredman: you should use a bit more whitespace in your reader :P

13:22 hiredman: :P

13:22 now is the hard part

13:22 Chousuke: hiredman: for example, between all the functions in the huge letfn

13:22 yuras: any other ways to do it? just hit me with them, i will dig further myself

13:22 hiredman: clean it up

13:23 Chousuke: hey, I put some comas at the end of the function bodies, that's whitespace!

13:23 multimethods

13:24 yuras: so interface in that case would be passing name of multimethod to the server, right?

13:24 hiredman: you could just use vars, but that throws things a little wider open then you usually want to allow

13:24 yuras: no, the server would be a multimethod, basically

13:25 the multimethod's dispatch function would get whatever input and decide which method in the multimethod to dispatch to

13:25 :/

13:25 Anniepoo: If I shadow a binding in a let, how securely is the old value 'not available'?

13:25 Because I'm making a remote agent system, outsider passes me clojure code, I execute it in a sandbox

13:26 hiredman: depends on the binding type of the old name => value

13:26 if it is another let I don't think there is anything you can do

13:26 qed: Is there a way to create a function that can act on what is mapped to it in a hash map?

13:26 hiredman: Anniepoo: not secure at all for actual security purposes

13:26 qed: like (defn a [x] (do something to x where x is the value that a is mapped to in a hash map))

13:26 (a 1)

13:27 hiredman: sure

13:27 qed: how do you do that?

13:27 hiredman: a function is a object

13:27 you can use it as a key in a hashmap

13:27 qed: hiredman: right i know this, but can i make the symbol a use the value in that hashmap as its input

13:28 Anniepoo: like (let [a (random) b #(somefun a) a nil] .... in here ...)

13:28 hiredman: um

13:28 Anniepoo: I want to provide access to b but not the raw a

13:28 qed: i should have fixed my above code

13:29 (defn a [x] (do something to x))

13:29 {a 1}

13:29 where 1 is the input to a

13:29 Anniepoo: (I'll hold for qed's discussion, this'll get confusing)

13:29 hiredman: no

13:29 qed: so there's no "placeholder" like there is in an anonymous function

13:29 that can reference the value that a key is mapped to

13:30 hiredman: qed: I really have trouble understanding what you are trying to ask

13:30 qed: heh me too

13:30 the above code pretty much sums it up: (defn a [x] (do something to the value that a is the key for))

13:30 {a 1}

13:31 hiredman: qed: no

13:31 qed: okay, thanks

13:31 Anniepoo: ok, back to me.

13:31 it'd be cool to have a canned 'sandbox'

13:32 hiredman: ~sandbox

13:32 clojurebot: sandbox is http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html

13:32 Chousuke: ~def with-meta

13:32 lisppaste8: Chouser annotated #89442 "lazy tail-recursive qsort" at http://paste.lisp.org/display/89442#1

13:32 hiredman: clojurebot has a sandbox.clj based on that site

13:33 Anniepoo: ah, lovely

13:33 chouser: clojurebot: tell maacl about http://paste.lisp.org/display/89442#1 when he gets back

13:33 qed: hiredman: pardon me for poking, but, do you know why that's not possible?

13:33 it seems like it could be if you worked some magic

13:33 Anniepoo: yah, I'm thinking it's a great way to do IPC if you're clojure on both ends (or even if you're not),

13:33 hiredman: qed: map literals are tied to specific map types

13:34 Anniepoo: in that case I think it would be better to write a mini clojure interpreter

13:34 Kjellski: Hi there, good evening!

13:34 hiredman: much easier to restrict

13:34 qed: hiredman: how does that preclude me from referencing some potential value that a key may refer to?

13:35 djork: howdy Kjellski

13:35 hiredman: qed: function application is not part of maps

13:35 qed: you could build a map that would work though, no?

13:36 hiredman: like I said, you don't make much sense, so I might be misinterpreting what you want

13:36 Kjellski: djork : howdy!

13:36 hiredman: sure, I don't see why though

13:36 qed: hiredman: i just want a way of referencing the value of my "self", where self is a key

13:36 hiredman: ,(-> {:a 1} (update-in [:a] inc))

13:36 clojurebot: {:a 2}

13:37 hiredman: qed: self of what?

13:37 qed: okay, so i have this function, and i know that this function will be the key in a hashmap later on

13:37 hiredman: ok, is it a def'ed function?

13:37 qed: defn

13:38 yes

13:38 hiredman: then just use it's name as the key

13:38 qed: right, but now that it is the key

13:38 is there a way of knowing what it is mapped to, once it's mapped

13:38 Anniepoo: hiredman: well, I was thinking inside the sandbox should be applet restrictions + ability to do whatever I say

13:38 hiredman: ,(-> + {+ 3} (* 2))

13:38 clojurebot: 6

13:38 Kjellski: djork: I´ve solved that problem for a small enough problem size, but as I´ve recognized, my try to a solution was a bit dumb... I think the approach I took was not that neat, just because it would be pretty hard to hold 1,000,000,000,000 integers in a vec... ^^

13:38 hiredman: qed: yes, it's called looking up the value in the map

13:38 drewr: newgen lisp machine? http://research.sun.com/projects/dashboard.php?id=185

13:38 hiredman: ,(get {:a 1} :a)

13:38 clojurebot: 1

13:39 qed: hiredman: no, i want a function {a}, to take as its input, the value it is mapped to

13:39 hiredman: sun has a research metacircular vm

13:39 djork: Kjellski: hmm, yeah you could get away with some shortcuts like using a map

13:39 if you just wanted to keep count

13:39 hiredman: qed: then apply the function to the value it is mapped to

13:40 qed: like (defn a [value-of-a] (some way of referencing a future value-of-a))

13:40 hiredman: drewr: yeah, project guest vm uses the metacircular jvm

13:40 Chousuke: hmm, okay, so the problem is not with my syntax-quote

13:40 Kjellski: djork: a map over what? If my Problemsize is big enough, it´s just stupid to represent bacteria via integers isn´t it?

13:41 hiredman: qed: it's not a value of a

13:41 it's a value a maps to in some map

13:42 qed: hiredman: right, is there some way of referencing the value 'a' maps to, in some future map

13:42 hiredman: Chousuke: I started to rewrite my syntaxquote, but it was such a big undertaking instead I just stepped through my broken verion until it worked

13:42 djork: Kjellski: I mean a map data structure {}

13:43 hiredman: ~google clojure reference types

13:43 clojurebot: First, out of 3810 results is:

13:43 Clojure - atoms

13:43 http://clojure.org/atoms

13:44 qed: like (defn a [future-mapping] #(+ % 1))

13:44 {a 1} => 2

13:44 where % is the future-mapping

13:44 i dont know, i might be talking crazy talk

13:45 Kjellski: djork : I thing I misunderstood you. What I meant was, if I represent a bac by an int, that would be stupid, just because whatever data structure I use, that would blow the memory. So I have to find a way to do the calculus on one single int or something...

13:46 qed: i guess what im trying to determine in the most basic sense, is if i can talk about a value i map to, without being mapped to anything yet -- with the understanding that when i do map to something, i will use it as my input

13:46 djork: Kjellski: I mean a map like { 1 count-for-ones 2 count-for-twos }

13:47 Kjellski: djork : there we go... now I got it.

13:51 A general question. I want to prepare a presentation about Clojure for a seminar at university, what do you think needs to get in there? (max. 30min)

13:53 chouser: Kjellski: don't try to cover everything. I think clojure has 4 or 5 killer features. Pick one or maybe two that you think your audience will "get" -- cover those deeply enough for them to get it. only mention the others.

13:54 persistent collections, seq library, reference types, macros+java interop

13:54 Kjellski: chouser : That´s what I thought. But which should I pick from e.g. http://clojure.org/features for students that at maximum discovered functional programming in there free time...

13:54 chouser : Okay. That´s a good start.

13:55 chouser: hm, I forgot multimethods and the REPL. :-)

13:55 I'd probably go with either the collections and seq library or maybe macros and interop.

13:56 qed: chouser: maybe im crazy here, but it seems possible: Can I define some function (defn a [input]...), and somehow reference what a will map to in some future hash map?

13:56 chouser: qed: I've been seeing your questions and I don't think I understand yet.

13:56 Kjellski: chouser : I wanted to definitely stunn them with the example from Stuarts book, where he shows the apache.common.indexOfAny in clojure...

13:57 qed: so by doing something like {a 1}, a can take 1 as its input, simply by virtue of it being mapped to it

13:57 without any other business

13:57 chouser: a literal {} will not call a function.

13:58 ({} :x) will call a method of hash-map, but there's no way to hook your own code in there

13:58 qed: chouser: ahh, that makes more sense

13:59 thank you :)

13:59 chouser: qed: it does? well ... good, I guess.

14:00 qed: i was just watching rich's screencast about data structures, and when he showed that you can add symbols like (defn a) to a hash map {a 1}, I wondered if there was some way of talking about what a maps to at some future scenario where it is in a hash map

14:00 hiredman: if maps are immutable, any future map is not the present map

14:00 qed: like some placeholder variable or something, that would describe the connection between a and its value

14:01 hiredman: there are promises and delays and futures and etc etc etc

14:01 chouser: qed: I seriously can't wrap my head around what you're saying. Maybe if we work on some terms a bit...

14:01 (defn a) doesn't create a symbol

14:02 (defn a [x y] (+ x y)) creates a fn and stores it in a Var named by the symbol a

14:03 if you then eval {a 1}, that's the same as eval'ing {(fn [x y] (+ x y)) 1}

14:03 that is, you get a hash-map with a single key (a function) and a single value (1)

14:03 now ... what do you want to do?

14:05 qed: manipulate the single value (1) with that single key (a function) -- the question is whether or not there is some way of writing a function that will understand how to "talk to" a value it is mapped to

14:05 kanak: What is the time complexity of doing a last on a sorted-map? (I'm trying to see if a sorted-map with "priority" as key could be a decent implementation for a heap)

14:05 qed: without it being mapped to something in the first place

14:05 hiredman:

14:05 kanak: n

14:06 qed: am i just talking crazy talk here?

14:06 kanak: hiredman: thanks. So what data structure would be the best if i need priority-queue type operations ?

14:06 qed: (defn a [var] [let var be the value this function is mapped to])

14:06 hiredman: fingertree

14:06 tomoj: "the value this function is mapped to"?

14:07 qed: {a 1}, the function is mapped to 1

14:07 chouser: kanak: you might look at subseq

14:07 tomoj: in (defn a ...), a is not a map

14:08 qed: tomoj: right, im talking about a future scenario where it is mapped to something, can you discuss the behavior of the function in a future context inside of that function?

14:08 tomoj: you're saying you want the function to behave differently depending on what the function is mapped to in some map elsewhere?

14:09 rstehwien: got notification that "Clojure in Action" book early access program is open http://bit.ly/aNJnj . Whoho! another clojure book

14:09 chouser: qed: (defn apply-map [f m] (f (m f))) (apply-map inc {inc 1}) ==> 2

14:09 qed: tomoj: not really, im saying more like: if this function is found in a map, it will behave like this, if it is found in a vector, it will behave like this

14:09 kanak: chouser: Could you explain that a little more?

14:09 chouser: qed: is that roughly what you're looking for?

14:10 tomoj: qed: what if it's in a map and a vector? and which map or vector?

14:10 the function doesn't know where you've put it, if that's what you mean

14:10 rstehwien: that link doesn't say anything about clojure for me :(

14:10 qed: tomoj: that's pretty much where i was going with this

14:10 tomoj: why in the world would you want to do that?

14:11 that would destroy everything that is good about clojure

14:11 and make me cry

14:11 qed: haha, im just thinking -- im not saying its useful or a good idea or anything

14:11 tomoj: oh, ok

14:11 qed: i was just wondering if there is anyway to define a function that understands what it is mapped to

14:11 chouser: qed: did you see what I posted?

14:11 qed: before it is mapped to something

14:12 tomoj: no, it could be mapped to any number of things in any number of different maps

14:12 rstehwien: tomoj: http://www.manning.com/rathore/ is the clojure book. odd that my email had that link but the repost our discount link didn't

14:12 qed: chouser: yeah, im thinking on it for a second, not sure if thats what i was thinking or not

14:12 tomoj: a function is just a value and you can put it anywhere

14:12 values don't know where you've put them

14:12 rstehwien: thanks

14:13 if you're passing the map into the function, then sure, it can just look itself up. guess I still don't understand what you really mean

14:14 Kjellski: Where can I get the latest build of clojure? is it github or google code?

14:14 qed: tomoj: how does it look itself up?

14:14 chouser: kanak: actually, nevermind subseq. calling first on a sorted map or set should be O(log n)

14:15 tomoj: qed: (defn a [the-map] (the-map a))

14:15 chouser: kanak: then removing that item should also be O(log n), I think, as should adding items.

14:16 kanak: so that's not too bad O(log n) for add and remove.

14:16 kanak: finger trees if we had them should give you O(1) insert and O(log n) remove. Or vice-versa, I suppose, as you see fit.

14:17 qed: tomoj: chouser: thanks for the patience, maybe ill figure out a better way to explain and try again later

14:17 ciao

14:18 kanak: chouser: hmm. does that mean that a finger tree would give me even better performance than a binomial heap?

14:18 tomoj: functions that return themselves are weird

14:24 chouser: kanak: sorry, don't know about binomial heaps

14:25 kanak: chouser: thank you for your help. Is your implementation of finger-tree "ready" to be used?

14:25 chouser: but performance is about more than just big-O, there are also the constant factors which are as yet still hounding my finger trees.

14:25 kanak: not really. no docs, for example.

14:26 kanak: hmm might be fun to play with it anyway :)

14:27 chouser: for some value of "fun", sure. :-) The core is feature complete, and it's got some tests that show how it can be used.

14:27 The API needs some improvement and it currently requires the 'new' branch of clojure to work at all.

14:29 kanak: chouser, are there any new data structures that might get added to the core? or will newer data structures (if any) get added to contrib (if at all)

14:30 chouser: kanak: I don't know. rhickey has said things that lead me to believe it's possible finger trees might make it in to core. I haven't heard even that about any others.

14:32 kanak: are there other persistent structures you'd like to see?

14:33 kanak: chouser: something that would allow efficient heap implementation would be nice to have. But i guess that could be had with a good finger tree.

14:35 Okasaki's book has implementations for Binomial and leftist heaps, which might be fun to implement in clojure.

14:39 chouser: hm. (:foo non-collection) just returns nil

14:39 In this case I would have really appreciated an exception.

14:40 tomoj: that happened to me too :(

14:41 chouser: in this case I had a reference type and was forgetting to deref it

14:46 rhickey: aargh - contrib has deftype?

14:46 chouser: heh

14:46 * rhickey about to push defclass/deftype

14:46 chouser: where?

14:47 rhickey: clojure.contrib.types

14:47 chouser: types

14:48 huh, I've never looked at that one. I guess I knew vaguely it was there.

14:48 "Algebraic types" anyway.

14:50 push to master?

14:50 rhickey: chouser: no way, up to new

14:50 chouser: :-) ok

14:55 rhickey: ok - have fun, feedback needed: http://github.com/richhickey/clojure/commit/5f090a0925f3dcbd3fa8b7104cd59b6d4c087413

14:55 cemerick: is clojure.contrib.types getting a hasty refactoring?

14:55 rhickey: cemerick: not bey me

14:55 by me

14:56 so new branch incompatible with compiling contrib at present

14:56 cemerick: hrm, I guess c-c should have a new branch too

14:56 chouser: nah

14:57 rhickey: cemerick: I have been building contrib and running its tests all along with new branch, this name conflict first problem

14:57 Chousuke: hmm, I think I have got the unreading behaviour working now in my reader.

14:57 chouser: just exclude deftype from contrib types for now

14:57 Chousuke: state is evil :(

14:57 rhickey: probably just need an :exclude in contrib.types

14:58 chouser: github knows how to color letfn

14:58 rhickey: I'm sure the defthing docs need a lot of work, as questions come in I'll clarify them

14:59 chouser: heh. create-defclass* bears striking similarities in structure with make-digit

15:01 http://tinyurl.com/ylx4j3k/finger_tree.clj#LID83

15:02 that is, new-new like thing generate by macro.

15:14 rhickey: chouser: yeah, inevitably

15:17 bradford: I'm having a hell of a time building something nice for remote repl over ssh.

15:17 (defn read-command-output [in buffer-size time-out poll-interval]

15:17 (let [buffer (make-array Byte/TYPE buffer-size)

15:17 bos (java.io.ByteArrayOutputStream.)

15:17 exit-status 0

15:17 end-time (+ (System/currentTimeMillis) time-out)]

15:17 (while (< (System/currentTimeMillis) end-time)

15:17 (while (> (.available in) 0)

15:17 (let [next-block (.read in buffer 0 buffer-size)]

15:17 (if (< count 0) break

15:17 (do

15:17 (.write bos buffer 0 count)

15:17 (if (.isClosed channel)

15:17 technomancy: ,lisppaste

15:17 clojurebot: java.lang.Exception: Unable to resolve symbol: lisppaste in this context

15:17 bradford: (do (println (str "exit-status: " (.getExitStatus channel)))

15:18 break))

15:18 technomancy: ~lisppaste

15:18 clojurebot: I don't understand.

15:18 bradford: (Thread/sleep poll-interval))))))

15:18 (.toString bos)))

15:18 technomancy: bradford: lisppaste.org dude

15:18 bradford: trying to figure out how to port some nasty jsch code to clojrue and deal with the breaks in these nested while loops

15:18 danlarkin: this is an inappropriate amount of pasting

15:18 bradford: technobancy: i know...let me finally set it up :-)

15:18 G0SUB: ,lisppaste8

15:18 clojurebot: java.lang.Exception: Unable to resolve symbol: lisppaste8 in this context

15:18 bradford: yea - my bad :-)

15:18 G0SUB: lisppaste8

15:19 technomancy: I have a problem with completion on a clojure buffer. can you help?

15:19 bradford: http://paste.lisp.org/display/89458

15:20 G0SUB: technomancy: completion on a clojure buffer does not work at all. it used to work on the repl, but that too broke somehow recently. (i made no changes to emacs files)

15:20 bradford: there is the lisppaste- i usually use gists, but whatever

15:20 technomancy: G0SUB: unfortunately at the present moment I only have time to complain about IRC usage and not actually be helpful; catch me later in the day?

15:21 G0SUB: technomancy: sure.

15:21 bradford: can peeps have a look at this ssh exec horror:

15:21 http://paste.lisp.org/display/89458

15:22 danlarkin: bradford: did you not catch george's socket-repl presentation at the SF clojure meetup a few weeks ago? :(

15:22 bradford: nope, please forward me the goodness

15:23 is the stuff in clojure.contrib?

15:24 dysinger: y

15:24 danlarkin: bradford: hunting it down..

15:25 bradford: dysinger: clojure.contrib.server-socket?

15:25 dysinger: y

15:31 bradford: reading server-socket.clj ...

15:39 Licenser: aloa

15:42 ysmolsky: how to test particular symbol, if it is a function?

15:43 danlarkin: ysmolsky: there's ifn? and fn?

15:44 chouser: symbols are always functions, but that's probably not what you meant.

15:44 ysmolsky: i mean user defined ones as (defn ..)

15:44 chouser: ,('foo '{foo 5, bar 5})

15:44 clojurebot: 5

15:44 ysmolsky: seems like fn? is the answer

15:44 Licenser: somnium: I found more problems :P

15:44 chouser: ,(fn? 'foo)

15:44 clojurebot: false

15:44 chouser: ,(ifn? 'foo)

15:44 clojurebot: true

15:45 AWizzArd: rhickey: nice, thanks for the new checkin :)

15:45 chouser: ,(-> 'filter resolve deref ifn?)

15:45 clojurebot: true

15:45 chouser: ,(-> 'i-just-made-this-up resolve deref ifn?)

15:45 clojurebot: java.lang.NullPointerException

15:46 AWizzArd: ,(resolve 'filter)

15:46 clojurebot: #'clojure.core/filter

15:46 rhickey: AWizzArd: did you try it?

15:46 AWizzArd: rhickey: no, just saw the email and now looking at the diffs

15:47 chouser: ,(when-let [v (resolve 'made-this-up)] (fn? @v))

15:47 clojurebot: nil

15:47 chouser: ,(when-let [v (resolve 'resolve)] (fn? @v))

15:47 clojurebot: true

15:47 AWizzArd: But tomorrow at work I can give it a try and see if I can get my tokenization example running.

15:48 chouser: can one simply checkout the "new" branch from git and compile it like the master? Or are other steps needed?

15:48 chouser: AWizzArd: that should do it

15:49 AWizzArd: As I understand it then deftype is more for endusers like me.

15:49 while with defclass one can even implement things like Clojures maps and vectors.

15:50 or finger trees

15:51 chouser: no, I think deftype and defclass are designed with very similar syntax so you can start with deftype and if you need that extra bit of performance or named Java classes (and don't mind losing a bit of dynamism and doing the AOT setup) you can easily switch to defclass.

15:52 cemerick: is there a perf difference? I didn't realize there was one.

15:52 rhickey: cemerick: defclas will let you do (.field x)

15:52 defclass

15:53 (.field x) from outside of the method bodies

15:53 cemerick: ah. is that a field access or invoking a getter called field?

15:53 rhickey: inside the method bodies you can just use x, same perf for newnew/deftype/defclass

15:53 cemerick: field access

15:54 AWizzArd: and outside of method bodies for deftypes?

15:54 rhickey: next up for me is to add a perfect-hash based case construct to Clojure, will be used in the implementation of valAt (get)

15:55 AWizzArd: outside, both support (:field x)

15:55 duncanm: how do i get all the keys from a set of maps?

15:55 AWizzArd: ,(keys {:a 1, :b 2})

15:55 clojurebot: (:a :b)

15:55 duncanm: AWizzArd: a set

15:55 arohner: (map keys set-of-maps)

15:55 rhickey: mapcat

15:55 duncanm: ooh

15:56 (map keys #{{'a 'b} {'c 'd}}) -> ((a) (c))

15:56 AWizzArd: rhickey: some days ago someone postet a microsoft paper or so, of perfect hashes. Will you use some of that stuff?

15:56 drewr: ,(mapcat keys #{{:foo 1 :bar 2} {:baz 3 :quux 4}})

15:56 clojurebot: (:baz :quux :foo :bar)

15:56 duncanm: nice

15:57 rhickey: AWizzArd: tht paper was about 3d hashes, but other papers. The case thing will bottom out on a JVM tableswitch bytecode

15:59 ysmolsky: is there a way to handle optional arguments like "a" and "c" inside of function by keywords? (for arg1 :some a :bar c)

15:59 AWizzArd: sounds lowlevel ;-) are those hashes also needed for Clojure in Clojure?

16:00 chouser: ysmolsky: see clojure.contrib.def/defnk

16:00 rhickey: AWizzArd: it will look like cond, not low level in use, but very fast match given compile-time constant keys

16:00 AWizzArd: ysmolsky: you can manually do this in your own functions, or you can accept a map as argument

16:00 i see

16:00 cemerick: ysmolsky: or, you can use map destructuring with an :or map containing defaults

16:00 rhickey: AWizzArd: (case x :a (do-this) :b (do-that) ...)

16:01 but unlike (condp = x :a (do-this) :b (do-that) ...) it won't try every choice sequentially

16:01 AWizzArd: i am just looking at http://www.artima.com/underthehood/flowP.html as they say a bit about tableswitch

16:04 duncanm: it'd be nice if i can supply my own comparator in clojure.set/difference

16:10 chouser: AWizzArd: thanks for that link

16:13 hiredman: would anyone be interested in a reworked build.xml? specificly one that doesn't blow away and recompile everything everytime you run ant?

16:14 http://gist.github.com/220784

16:14 chouser: it used to now blow everything away, but would sometimes mess up and fail to rebuild something, resulting in weird runtime errors

16:15 used to not blow everything away

16:15 hiredman: well, hving it blow everything away when you call the compile-clojure target is annoying if you want to call that target twice

16:16 and the java task to call Compile should fork

16:17 or else, again, calling the compile-clojure task twice doesn't work

16:18 cemerick: FWIW, we just check clojure jars into our fork of the repo. Building clojure as a direct ant build dependency doesn't seem worthwhile.

16:20 hiredman: of course, but for actual developement work on clojure, it's nice to have a nicer build process

16:20 Dawgmatix: are there any tools to generate wrappers for c libraries for clojure ?

16:20 chouser: Dawgmatix: I've had success with both swig and jna

16:21 arohner: Dawgmatix: I like JNA

16:21 it's a little slower, but the convenience is nice

16:21 tomoj: autogenerated clojure wrappers for C would be weird

16:21 chouser: yeah, I'd recommend JNA if the libs are plain C

16:22 for C++ swig has worked out well.

16:22 Dawgmatix: okay arohner will look at jna

16:22 chouser: tomoj: swig comes very close to autogenerated, and yes it's a bit weird.

16:22 Dawgmatix: why is it weird ?

16:22 tomoj: it would be weird to me because I don't want my clojure to look like C

16:23 Dawgmatix: hehe :)

16:23 chouser: it's weird to me because frequently so frictionless and doesn't seem like it should be.

16:23 tomoj: and if I'm going to write a wrapper around the wrapper I might as well just use an autogenerated java wrapper and wrap that in clojure

16:23 chouser: Dawgmatix: http://github.com/Chouser/clojure-jna

16:24 Dawgmatix: so whats the alternative for wrapping things like opengl ?

16:24 chouser: there are gl libs for java

16:24 Dawgmatix: jogl ?

16:24 arohner: if the gl lib didn't exist, JNI

16:24 tomoj: chouser: ok, that's pretty cool

16:25 arohner: it's similar to writing c-ruby or c-python extensions, but an even bigger pain

16:25 because the JVM is fussier

16:25 chouser: swig makes generating JNI code relatively painless

16:32 hiredman: anyone want a clojure.jar with a slower reader, that happens to be written in clojure :P

16:34 chouser: heh

16:34 hiredman: http://gist.github.com/220805 same buid.xml as earlier but with my reader dropped in

16:35 so it builds clojure once with LispReader, uses clojure to build my reader, then deletes clojure and rebuilds it using my reader

16:35 by clojure I mean the compiled clj files

16:35 chouser: I imagine will need a build setup like that for cinc in general

16:36 hiredman: yeah

16:37 emit_: what does the M suffix mean next to an integer. like (= 3156M 3156) is true

16:37 hiredman: I am going to send an "anouncement" email about my reader to -dev once I get it working nicely in a fairly vanilla clojure tree

16:37 arohner: emit_: bignum

16:37 chouser: ,(map class [3156 3156M])

16:37 clojurebot: (java.lang.Integer java.math.BigDecimal)

16:38 hiredman: I had to make a lot of stuff public instead of class private

16:38 bits of RT and the Compiler

16:41 emit_: ok... thanks

16:41 chouser: hiredman: yeah, that's not surprising. I had to do the same for ClojureScript, though likely not exactly the same stuff

16:46 hiredman: ugh

17:04 Kjellski: Anyone already using a LaTeX-Highlight Listing for clojure?

17:05 hiredman: http://markmail.org/message/emngybncqtlcsunb <-- oh lord

17:05 technomancy: hiredman: we all have posts like that... some are just better-hidden than others =)

17:06 djork: heh heh

17:06 yes

17:10 Kjellski: noone?

17:11 hiredman: so far I have yet to embed code in of my latex documents

17:11 but am I interested, just have nothing ov value to contribute at the moment

17:12 Kjellski: Okay... so maybe I´ll just post my listings defines if you want?

17:12 hiredman: sure

17:14 I mean, if I had some way of embedding syntax hilighted clojure code in my latex documents I guess I would practically have to

17:15 chouser: heh

17:15 Kjellski: I´ll send you a minimal example when I´m done... ^^

17:16 hiredman: http://github.com/hiredman/clojurebot/blob/master/clojurebot.pdf I started on a clojurebot slidedeck

17:17 danlarkin: Kjellski: what is i you're sending at the end of each line? I can't decode it

17:17 tomoj: I wonder if there are any general output-independent highlighters

17:17 Licenser: hiredman: I don't understand the message

17:17 hiredman: message?

17:18 Licenser: the mail thingy

17:19 I am just not getting it

17:19 hiredman: oh, I sent and email to the mailing list because I couldn't find 'mod'

17:20 Licenser: ah, I had that problem too :P I gave up

17:22 Kjellski: danlarkin : huh? Sorry... might be the miranda irc client?

17:23 hiredman: I don't see anything weird at the end of Kjellski's lines

17:23 danlarkin: I see ^^ [incompatible encoding] after each one

17:24 hiredman: weird

17:24 danlarkin: no biggie

17:24 hiredman: uh, I know he did end one line with ^^

17:24 Licenser: good night people, and danlarkin set the channel encoding to UTF8 or something

17:24 tomoj: hmm.. how would you write a function which does like iterate, but alternates between applying two functions?

17:24 danlarkin: It is already set to utf-8

17:24 tomoj: (besides tail-recursion with a toggling counter or integer mod 2... wondering if there's a cool way)

17:24 technomancy: channels don't actually have encoding; it's up to the clients to agree on them =)

17:25 Licenser: tomoj: tail recusion with 2 function arguments that alter place in the call

17:25 (loop [f1 f2] ... (recur f2 f1))

17:25 tomoj: ok, that's better than toggling

17:25 but I meant without loop, really

17:25 like with seq-fu

17:25 hiredman: tomoj: not really, because iterate uses the same function over and over

17:25 Kjellski: Sorry about that... sometimes I can´t resist my smiley reflexes.

17:26 hiredman: ~def iterate

17:26 huh

17:26 arohner: tomoj: (source iterate)

17:26 make your version of iterate take two functions

17:27 swap f1 and f2 in the recursive call

17:27 tomoj: arohner: yeah, that's a good way too

17:27 I was curious if there is an "even more lazy" way

17:27 arohner: I think that's about as lazy as it gets

17:27 tomoj: as in the kind of thing the clojure book does

17:28 arohner: the original iterate is completely lazy

17:28 so is the version I suggested

17:28 tomoj: recursion -> lazy-seq -> combining builtin seq fns

17:28 Licenser: but buildin seq fns usually are recursive :P

17:28 tomoj: sure, but the recursion is hidden away and you don't have to think about it

17:29 Licenser: heh when you write a interalternate or how you call it, it would be hidden for the rest of the world too :P

17:29 anyway I', off to be,d take care everyone!

17:29 arohner: you could make an infinite-seq of the fns to call, in order

17:29 then reduce it

17:29 i.e. (reduce #() [f1 f2 f1 f2 f1...])

17:29 hiredman: well, reduce isn't lazy

17:30 arohner: ah, right

17:30 tomoj: would need reductions

17:31 arohner: I like my first way

17:31 tomoj: ,(take 10 (interleave (repeat 'f1) (repeat 'f2)))

17:31 clojurebot: (f1 f2 f1 f2 f1 f2 f1 f2 f1 f2)

17:31 tomoj: I still don't understand your "reduce #()", but, thanks

17:32 djork: how could I convert a raw byte array to a string within clojure?

17:32 a hex string that is

17:34 tomoj: well

17:34 I think signedness can screw you up

17:35 hiredman: ,(.getBytes "foo")

17:35 tomoj: if you try to use java's toHex stuff, that is

17:35 clojurebot: #<byte[] [B@db8155>

17:35 hiredman: ~jdoc String

17:36 djork: oh bit-and

17:36 tomoj: one way would be to have a map of ints to hex chars

17:36 hiredman: integer has a toHexString method

17:36 tomoj: yeah and then (bit-shift-right ) I suppose

17:36 hiredman: yes but it's signed

17:37 hiredman: well

17:37 all java primitives are signed

17:37 tomoj: so you'd have to find someway to make the byte an int that doesn't keep the sign

17:37 djork: OK so

17:37 AWizzArd: you want to convert a byte array into a hex num sequence correctly?

17:37 tomoj: ,(Integer/toHexString (.intValue (byte 130)))

17:37 clojurebot: "ffffff82"

17:38 AWizzArd: no, use bit-and

17:38 djork: ,(let [bytes (.getBytes "byte me")] (bit-and (aget bytes 0) 0xFF))

17:38 clojurebot: 98

17:38 AWizzArd: ,(bit-and -128 255)

17:38 clojurebot: 128

17:38 hiredman: ,(-> \h int Intager/toHexString)

17:38 clojurebot: java.lang.Exception: No such namespace: Intager

17:38 hiredman: ,(-> \h int Integer/toHexString)

17:38 clojurebot: "68"

17:38 AWizzArd: (map #(bit-and % 255) (range 256))

17:38 hiredman: ,(-> \hlint Integer/toHexString)

17:38 clojurebot: Unsupported character: \hlint

17:39 tomoj: AWizzArd: then what do you do with that?

17:39 I was thinking bit-and with 0xf to get one char, then shift right 4 and do it again for the second char

17:39 AWizzArd: then you can use Integer/toHexString

17:39 tomoj: no..

17:39 djork: hmm, nibble at a time?

17:39 there's no such thing AWizzArd

17:40 tomoj: oh, hmm

17:40 AWizzArd: say you do a sha-256 hash, you will get a byte[]

17:40 djork: yeah that's what I'm doing

17:40 sha

17:40 tomoj: bit-and plays nicely with signed bytes, you're right

17:40 AWizzArd: but if you want to print out that hash code then you display it a hex

17:41 (apply str (map #(Integer/toHexString (bit-and % 255)) (sha "hello moon")))

17:41 wooby: is there something like contains? for seqs?

17:42 AWizzArd: find-first

17:42 arohner: ,(doc some)

17:42 clojurebot: "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return true if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"

17:42 djork: hmm I guess Integer/toHexString exists

17:42 ,Integer/toHexString

17:42 clojurebot: java.lang.Exception: Unable to find static field: toHexString in class java.lang.Integer

17:42 arohner: wooby: that's a linear scan

17:42 djork: I'm doing it wrong™

17:42 AWizzArd: ,(apply str (map #(Integer/toHexString (bit-and % 255)) (range 150 160)))

17:42 clojurebot: "969798999a9b9c9d9e9f"

17:43 AWizzArd: djork: it is a Java method and so you can't return a function object of Integer/toHexString

17:43 ,#(Integer/toHexString %)

17:43 clojurebot: #<sandbox$eval__4362$fn__4364 sandbox$eval__4362$fn__4364@b5c292>

17:46 djork: I think I've got it

17:47 (Integer/toHexString 0)

17:47 ,(Integer/toHexString 0)

17:47 clojurebot: "0"

17:47 djork: not cool

17:47 AWizzArd: djork: please compare the output of your program with the example here: http://en.wikipedia.org/wiki/SHA_hash_functions#Examples_and_pseudocode

17:48 djork: will do

17:50 working fine

17:50 just need to pad my zeroes

17:52 AWizzArd: format

17:53 btw, I think format can also do toHexString for you

17:54 djork: http://gist.github.com/220900

17:55 format would be better I think

17:56 AWizzArd: djork: yes, good example code, this is how it works

17:56 only thing that I personally would change is "SHA-1" ==> "SHA-512" :-)

17:58 so, how can one give fill chars to format?

17:58 ,(format "%h" 255)

17:58 clojurebot: "ff"

17:58 AWizzArd: ,(format "%2h" 0)

17:58 clojurebot: " 0"

17:59 AWizzArd: Can one make it output "00"?

17:59 hiredman: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Formatter.html

18:00 djork: OK this is better

18:00 http://gist.github.com/220900

18:00 ,(format "%02x" 1)

18:00 clojurebot: "01"

18:01 djork: you know what would be cool... gist loading in clojurebot

18:01 hiredman: :/

18:01 AWizzArd: ,(format "%02x" 255)

18:01 clojurebot: "ff"

18:02 hiredman: fyi clojurebot is xmpp too: clojurebot@thelastcitadel.com

18:02 rstehwien: dawgmatrix: for opengl in java there is jogl and lwjgl . The game libs Slick (2d) and JMonkeyEngine (3d) use jogl and/or lwjgl (the default seems to be using lwjgl in the java game world)

18:03 wooby: what would be the preferred way to convert a number to a seq of its digits?

18:03 i'm doing this now: (map #(Integer/parseInt (Character/toString %)) (str n))

18:03 AWizzArd: ,(seq (str 123))

18:03 clojurebot: (\1 \2 \3)

18:03 wooby: oh duhhh

18:03 thank you

18:04 AWizzArd: no, those are chars

18:04 not digits

18:04 wooby: i see

18:04 AWizzArd: ,(map int "123")

18:04 clojurebot: (49 50 51)

18:04 AWizzArd: ah ;)

18:04 hiredman: :P

18:04 wooby: ,(map irc://irc.freenode.net/#(Integer/parseInt (Character/toString %)) (str 123))

18:04 clojurebot: java.lang.ClassNotFoundException: irc://irc.freenode.net

18:05 AWizzArd: wooby: Character/toString ==> str

18:06 wooby: ah yes

18:06 AWizzArd: ,(map #(Integer/parseInt (str %)) (str 123))

18:06 clojurebot: (1 2 3)

18:06 wooby: that's better, thanks

18:07 hiredman: (-> 123 str ((partial map str)) ((partial map read-string)))

18:07 ,(-> 123 str ((partial map str)) ((partial map read-string)))

18:07 clojurebot: (1 2 3)

18:07 wooby: fancy

18:08 hiredman: ,(->> 123 str (map str) (map read-string))

18:08 clojurebot: (1 2 3)

18:09 wooby: wow what's going on there

18:09 ->>?

18:10 hiredman: ,(doc ->>)

18:10 clojurebot: "([x form] [x form & more]); Threads the expr through the forms. Inserts x as the last item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the last item in second form, etc."

18:10 wooby: mindblowing

18:17 i see

18:17 so (map read-string (map str (str 123))) is equivalent

18:17 ,(map read-string (map str (str 123)))

18:17 clojurebot: (1 2 3)

18:18 AWizzArd: ,(use 'clojure.contrib.pprint)

18:18 clojurebot: nil

18:19 piccolino: Is there some function built-in that can take a sequence of strings, and return the string of all of them concatenated with a separator between them?

18:19 div-: what would be the benefit of ->> ?

18:19 besides "being possible"

18:20 hiredman: any opinion ? :)

18:20 arohner: div-: it reduces the nesting of function calls, and (can) make things more readable

18:20 AWizzArd: ,(apply str ["string 1" "XXX" "ABC"])

18:20 clojurebot: "string 1XXXABC"

18:21 AWizzArd: if you need a separator you can map it

18:22 piccolino: Map it?

18:22 div-: arohner: okay, but it seems like it would be sporadically used, and if so, wouldn't really make things more readable, right ?

18:22 notallama: is ->> in core?

18:22 hiredman: yeah

18:22 arohner: notallama: yes

18:22 hiredman: it's newish

18:22 arohner: ->> is easier to understand if you start with ->

18:22 which has been around for a long time

18:22 AWizzArd: ,(apply str (map #(str % "/") ["abc" "xyz"]))

18:22 clojurebot: "abc/xyz/"

18:23 notallama: threading/composition is fun stuff.

18:23 div-: ,(doc ->)

18:23 clojurebot: "([x form] [x form & more]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc."

18:23 arohner: think of a java function call

18:24 foo().bar().baz()

18:24 now let's add arguments

18:24 piccolino: Ah, but that sticks a pointless separator on the end.

18:24 arohner: foo(x).bar().baz()

18:24 tomoj: ,(apply str (interpose '/ ["foo" "bar" "baz"]))

18:24 clojurebot: "foo/bar/baz"

18:24 arohner: (-> x foo bar baz)

18:24 piccolino: Ah, there we go. Thanks.

18:24 tomoj: str-join is in str-utils I believe

18:25 piccolino: Ah, that too, nice. Thank you.

18:25 div-: hm, interesting

18:25 notallama: comp is a bit irritating because it's backwards compared to my intuition. so i made >>> as a reverse-ordered comp.

18:26 tomoj: ((>>> foo bar) x) is (bar (foo x)) ?

18:26 notallama: yeah

18:27 AWizzArd: what is >>>?

18:27 tomoj: ...

18:27 see 4 lines up

18:28 notallama: function in here: http://github.com/hclarke/pointfree-clojure just a reversed comp.

18:30 AWizzArd: notallama: yeah, a function (pipe ...) would be nice, like comp but in reverse order :)

18:31 wooby: or (apply str (interpose "/" ["foo" "bar"]))

18:32 hiredman: -> and ->> are similar to the thrush combinator

18:33 ,(->> ["foo "bar"] (interpose "/") (apply str))

18:33 clojurebot: EOF while reading string

18:34 hiredman: ,(->> ["foo" "bar"] (interpose "/") (apply str))

18:34 clojurebot: "foo/bar"

18:36 hiredman: ,(->> "bar" (conj []) (into ["foo"]) (interpose "/") (apply str))

18:36 clojurebot: "foo/bar"

18:36 notallama: i'm kindof a licencing noob. what's one that basically says "do whatever you want, but put my name somewhere"?

18:36 hiredman: hmm

18:37 MIT/X11

18:37 notallama: thanks

18:37 hiredman: ,(-> [] (conj "foo" "bar") (->> (interpose "/") (apply str)))

18:37 clojurebot: "foo/bar"

18:38 div-: haha

18:40 i suppose it takes some getting used to mentally mapping the evaluation scheme when encountering -> and ->> :}

18:41 notallama: it's a lot easier if it's formatted vertically, i find.

18:41 hiredman: ,(pl (↕map (replicate 3 (↕apply vector $ (↕map range $ 10 inc · inc · inc) call · ⌽* $ 10 · call · (⌽+ -2) map)) shuffle)))

18:41 clojurebot: ((40 100 90 70 30 10 60 20 80 50) (100 60 50 80 40 10 20 30 90 70) (80 10 20 100 60 40 90 50 30 70))

18:42 notallama: ..what?

18:42 hiredman: :)

18:43 ,(pl (λx (inc x) 1))

18:43 clojurebot: 2

18:44 somnium: ,(doc pl)

18:44 clojurebot: "([& forms]); replaces a $ b with (a b) walking right to left replaces a · b with (comp a b) left to right ⌽a with (uncurry a) left to right ↕a with (flip a) left to right"

18:45 hiredman: outdated docstring

18:45 but mostly correct

18:45 somnium: hiredman: have you been teaching clojurebot dialect?

18:45 notallama: huh, fancy

18:46 hiredman: and of course uncurry actually curries a function

18:46 notallama: well of course.

18:46 cemerick: wow, that looks painful

18:47 hiredman: done with zippers, I guess I should look into redoing it with clojure.walk now that I am aware of it

18:54 somnium: I hope some form of heredoc emerges eventually, it would be wonderful to be able write macros that can see whitespace and arbitrary characters.

18:54 I guess its not much of a priority with all the progress on cinc

18:55 tomoj: writing macros that can see whitespace and arbitrary characters sounds horrid to me

18:56 macros are already bad enough when you get to work with forms, can't imagine what they'd be like if you had to work with raw strings

18:56 notallama: you could write a macro to inline perl in your code, though.

18:56 somnium: tomoj: strings are easy to make into forms, except when you can't see all the characters :)

18:57 tomoj: it would be easy to imbed any kind of parser anywhere, like notallama said ^^

18:57 tomoj: ok, if you happen to have a perl parser lying around

18:58 I guess if you want to go through the trouble to write a parser it would be pretty cool

18:58 macros are awesome because you don't :)

18:58 (have to go through the trouble, I mean)

18:59 somnium: tomoj: not a full language parser, but some kind of yaml-like declarative syntax would be convenient for dsl designs

18:59 right now # % ^ probably others choke the reader

18:59 hiredman: you can do that if you reall want

18:59 somnium: and plain strings have their own limitations

18:59 hiredman: just use reflection to get at the two reader macro tables

19:00 somnium: hiredman: I saw something about that

19:00 tomoj: you can add reader macros?

19:00 somnium: I don't want to add reader macros so much as be able to turn off the reader on occasion

19:00 hiredman: tomoj: the reader looks up reader macros in a private array, so it is technically possible to get at the table and add your own

19:01 somnium: turn off the existing reader macros I mean

19:01 hiredman: but that would be very bad and you should not do it

19:01 tomoj: indeed

19:01 still I didn't know it was even possible

19:02 hiredman: my reade uses condp as a switch so you can't do that any more

19:02 somnium: something like (#no-reader-macros macrosym & raw-string-input)

19:03 hiredman: somnium: is basically what a reader macro's view of the world is

19:04 a reader macro is called with the pushbackreader and last chracter read as arguments

19:04 tomoj: so the reader macro sees whitespace?

19:04 (but just ignores it?)

19:04 hiredman: sure

19:04 reader macros see the reader

19:05 somnium: hmm

19:05 hiredman: http://github.com/hiredman/clojure/blob/readerII/src/jvm/clojure/lang/LispReader.java#L365

19:05 somnium: well I guess its not gonna happen then :)

19:05 hiredman: that is a reader macro

19:05 actually, it is a reader dispatch macro

19:06 somnium: a heredoc would be close enough though

19:06 hiredman: but uh, they are not that different

19:06 somnium: it wouldn't quite as seamless, but it will still make it easy to imbed yaml or whatever

19:06 tomoj: how is a heredoc any less seamless than (#no-reader-macros ...)?

19:06 hiredman: http://github.com/hiredman/clojure/blob/readerII/src/clj/clojure/reader.clj#L306 clojure version

19:06 somnium: because the user has to delimit the input

19:07 but its a very minor quibble

19:07 tomoj: I don't understand

19:07 somnium: a heredoc would be fully satisfying

19:07 tomoj: you have to delimit the input with #no-reader-macros too

19:07 somnium: instead of (yaml-parser ... ...)

19:07 tomoj: ooh, I see what you mean

19:07 somnium: (yaml-parser """ ... ... """)

19:08 tomoj: I don't like (yaml-parser ...) at all

19:08 somnium: yeah, it is disconcerting for someone reading it

19:08 who doesn't know what its doing

19:08 tomoj: and very hard to indent properly, I'd think

19:09 unless your editor crawls through and finds all these weird macros, I guess

19:09 somnium: its kind of possible now, you just cut up to the first newline, and then build a tree from whitespace

19:09 tomoj: paredit would have a fit

19:09 somnium: but strings have all kinds of escape issues

19:09 true, a heredoc would solve that though

19:10 tomoj: yeah

19:10 how often are you wanting to parse literal yaml in your source files?

19:10 seems a very strange thing to do

19:11 hiredman: word

19:11 this is clojure, we have map literals

19:12 Chousuke: hiredman: java written in clojure is less readable than Java written in Java :(

19:12 somnium: I'm building a mongodb driver right now, and wanting to define schemas and validations with something yaml-like would be very nice

19:13 hiredman: somnium: a clojure mongodb drive should use clojure map literals, not yaml

19:13 somnium: but its already possible to get very ceremony declarative code

19:13 hiredman: Chousuke: regex-reader isn't really that bad

19:14 http://github.com/hiredman/clojure/blob/readerII/src/clj/clojure/reader.clj#L225 fn-reader

19:14 somnium: hiredman: glance at the api at http://github.com/somnium/congomongo

19:15 hiredman: why?

19:15 somnium: hiredman: it does use map literals, and it could be reduced a lot more

19:15 ...

19:15 hiredman: well, then use less map literals

19:16 somnium: ok

19:16 Chousuke: hiredman: I guess it's not bad if you compare it to the surroundings :/

19:16 tomoj: looks fine to me

19:16 Chousuke: but the shape is all wrong.

19:16 tomoj: except I'd use keywords instead of strings

19:16 hiredman: shape?

19:16 Chousuke: nested ifs look awful :(

19:16 somnium: tomoj: there are some issues with the current java driver

19:16 Chousuke: yeah. it's too deep.

19:16 somnium: tomoj: but they're almost worked out

19:16 tomoj: I don't use mongodb

19:17 hiredman: yeah, well, the java code is a bunch of if(x) return w

19:17 Chousuke: yeah :/

19:17 tomoj: I just mean the map literals on your readme look OK to me and I don't see how yaml would make them better

19:17 somnium: ok

19:17 Chousuke: Clojure is horrible at stuff like that :)

19:17 which is a good things

19:17 -s

19:17 hiredman: alot of that could be collapsed into conds I guess

19:18 I did go a little wild, I think I may have 3 or 4 deep nested letfns

19:18 Chousuke: I wish I could just fix the bug in my reader

19:18 but it persists

19:18 somnium: are letfns similar to definline, or just a convenience for let [f (fn ...)]?

19:19 tomoj: somnium: what are you using for json?

19:19 hiredman: keep plugging away, over the weekend I felt like I might never get mine in shape

19:19 tomoj: somnium: the latter

19:19 somnium: tomoj: the parts of the java driver that work, and contrib.json for the rest

19:19 hiredman: letfns also make names visible to all other fns

19:19 in the letfn

19:19 Chousuke: the Compiler might be making some assumptions that are no longer true with my reader :/

19:19 somnium: the java one is almost certainly faster, but its taken some patches to make it easily modifiable at runtime

19:19 tomoj: oh I hadn't realized there was json in contrib

19:20 I had found http://github.com/danlarkin/clojure-json and was poking around in that

19:20 hiredman: Chousuke: :(

19:20 Chousuke: but I'm pretty sure I don't "overconsume" the source stream anymore.

19:20 hiredman: well the compiler is my next stop

19:20 tomoj: why do you need to modify your json stuff at runtime?

19:20 Chousuke: please don't java-translate that :P

19:20 somnium: the java driver is very java-the-language centric unfortunately, but its been a good learning experience at how to mold java to clojure's view of the world

19:20 hiredman: Chousuke: :P

19:21 somnium: tomoj: doesn't have to be done at runtime, but instead of modifying the driver source they've been adding hooks to change its behavior

19:21 tomoj: so at startup clojure teaches it to handle clojure and then its all good

19:21 Chousuke: I might actually mod my reader at some point to be restartable.

19:21 tomoj: but I mean, what needs to change about java json?

19:22 hiredman: I think the compiler might have less of a bootstrapping problem

19:22 somnium: tomoj: its java centric, it likes objects, and it likes to create objects

19:22 tomoj: ah :(

19:22 damn objects

19:22 hiredman: but, uh, I haven't looked yet

19:22 somnium: indeed

19:22 Chousuke: ie. that you can just feed stuff into it and it either gives you back items and/or a function that you can call with more input :)

19:22 tomoj: gonna work on couchdb stuff so gotta figure out what to do about json

19:24 somnium: tomoj: take a look at a comparison of mongodb and couchdb if you have time, they're different animals in interesting ways

19:27 tomoj: "proprietary binary protocol"

19:27 that just means it's not a protocol mongo shares with other software, right?

19:27 somnium: tomoj: I guess so, BSON?

19:28 tomoj: dunno, just reading http://www.mongodb.org/display/DOCS/Comparing+Mongo+DB+and+Couch+DB

19:28 somnium: its compressed JSON for all intents and purposes, so its indexable and searchable

19:31 tomoj: based on that I'm stickin with couch

19:35 scottj: I ran into the problem where I had a map in my source code that got too big so I had to put it into a separate file and I'm reading it in and then running read on it to store it in a variable, and now all my newlines appear to be doubled up, where in emacs I see the newline and a ^M character. Any ideas what step I missed?

19:36 emacs = slime in this case

19:36 and newlines = newlines in strings in values of my map

19:38 tomoj: scottj: windows?

19:39 ^M is what the carriage return looks like, right?

19:41 scottj: tomoj: yeah windows

19:42 tomoj: ok, I changed file endings to Unix on that filename and now the ^M's don't show up.

19:53 technomancy: c.c.shell-out/sh looks like it doesn't support streaming output from subprocesses; is that correct?

20:01 chouser: what would you think of a patch to add this?

20:05 rlb: technomancy: looks like it to me

20:05 (that it doesn't)

20:07 technomancy: it's pretty easy to implement, but I've had contrib patches languish for a long time, so I don't want to move forward unless I've got buy-in from committer =)

20:07 rlb: eventually it'd be nice to be able to easily build process pipes

20:31 miltonsilva: hi

20:31 http://paste.lisp.org/display/89475

20:31 savanni: Quick question...

20:32 I'm wanting to attach documentation to an entire namespace. Just a multi-paragraph explanation of what the namespace is about. How can I do that?

20:32 rhickey_: jeez, there's deftypes all over contrib

20:32 miltonsilva: I'm having a bit of trouble understanding why my code (above link) doesnt work

20:37 chouser: savanni: I think most contrib libs have namespace doc strings you could mimic.

20:40 rhickey_: I wonder if all these contrib deftypes could become new deftypes

20:40 savanni: Okay, I'll grab one of those.

20:41 rhickey_: or do I have to rename deftype?

20:42 cemerick: rhickey: how many are there?

20:43 * rhickey_ surprised no one mentioned the conflict with contrib given deftype was listed on the wiki page

20:44 rhickey_: accumulators, complex, pprint, probabilities, stream utils, types

20:45 cemerick: I'd say anyone naming anything def* is accepting the risk of being compelled to change up down the road.

20:46 rhickey_: pprint's is its own

20:48 well, they could all be changed to either qualify use or refer-clojure with exclude

20:48 * rhickey_ would like help with this

20:49 rhickey_: deftype seems like too good a name to give up

20:49 and types/deftype merely approximates what deftype does

20:49 cemerick: rhickey_: shouldn't the maintainers of those libs decide on what to do in each case?

20:50 rhickey_: cemerick: yeah, I'll ask on dev

20:54 has anyone tried deftype/defclass?

20:56 cemerick: rhickey_: I'll hopefully get to it on Friday. I'm up against it, as usual. :-(

20:57 In some profiling, about 20% of our overall app runtime is map/struct slot access, so I'm pretty enthusiastic to get something better in there. :-)

20:58 rhickey_: cemerick: deftype is better than defstruct already, at least with few fields, but I am hoping for much better with case

20:59 and of course, you can now go to defclass and get field access perf

20:59 cemerick: rhickey_: well, the three key structs in that 20% are totally fixed, so defclass is appropriate there

20:59 :-)

21:00 rhickey_: defclass supports expando too, so you can mix fixed .field access with :expansion-field access

21:00 cemerick: rhickey_: option B or C?

21:00 rhickey_: C

21:01 cemerick: :-D

21:02 rhickey_: you might have missed - I decided I always regret building in an exception, since you can build a throwing api on a non-throwing but not vice-versa, so we can define getx anytime

21:02 we'll see if Konrad et al get riled up or not :)

21:03 I feel like I heard from the dynamic camp today, and argued for the missing static camp

21:03 cemerick: I'm all for that. Let the man on the ground decide what's best.

21:04 rhickey_: well, it should be obvious where Clojure's heart lies - flexibility

21:04 cemerick: I think C is a perfect blend of both, especially as people can get all B&D with their def-closed-type-really-I-mean-it forms built on deftype.

21:05 rhickey_: people have asked for throwind get and assoc, both can be written today if needed (maybe are already in contrib :)

21:05 throwing

21:05 cemerick: yuck

21:05 throwing assoc on what, structs?

21:05 rhickey_: yeah

21:06 or anything, just key must be present

21:06 cemerick: oh, I see

21:06 rhickey_: use a factory to create and then avoid mistakes

21:06 very many maps are never expanded

21:06 cemerick: eh. That's what testing is for.

21:07 ours accrete stuff in their travels frequently, like so many snowballs. :-)

21:08 chouser: heh

21:08 rhickey_: well, I'm sure will still like the new deftype

21:08 Konrad et al

21:08 cemerick: He's on the list mostly, right?

21:08 rhickey_: now just case and protocols

21:09 cemerick: I've let it build up again... > 750 msgs

21:09 rhickey_: cemerick: yeah, he did the ADT stuff, and - deftype :)

21:09 cemerick: rhickey_: is expando implemented with a map off to the side, or are you doing some field-injection-magic?

21:09 rhickey_: a map

21:10 chouser: in a volatile field? (eventually?)

21:10 rhickey_: too expensive to recompile class on assoc

21:10 chouser: no, real immutability like all the other stuff

21:10 chouser: oh oh, right. sorry.

21:11 slipped the clutch there

21:11 rhickey_: we need some print/read support too...

21:11 cemerick: chouser: man, that's me every day in here ;-)

21:11 chouser: :-)

21:12 rhickey_: #:Foo{:a 1 :b 2} for deftypes?

21:13 #:org.clojure/Foo{:a 1 :b 2}

21:14 or adt style #:Foo[1 2]

21:15 cemerick: was this on the list before? Seems familiar...

21:20 chouser: I sure like the brevity of the latter, but it seems fragile over time.

21:21 cemerick: Yeah: what if you've got a type with 9 numeric slots (or whatever)? Not a fun debugging exercise.

21:22 rhickey_: welcome to Haskell

21:22 that's my beef with ADTs - positional, constantly have to relabel in pattern matches

21:22 cemerick: heh. You missed the discussion of ->> vs >>> vs |||| earlier.

21:23 rhickey_: OTOH, out of the box defype give you positional factory fn/ctor only

21:23 subsequent to construction, you have labeled access

21:26 st3fan: is there a string->number ?

21:26 where do i look for functions like that?

21:26 tomoj: java I guess?

21:27 chouser: ,(Integer/parseInt "5")

21:27 st3fan: oh like (Integer. "123") ?

21:27 clojurebot: 5

21:27 chouser: ,(read-string "123M") ; or the clojure way

21:27 clojurebot: 123M

21:27 chouser: take your pick.

21:28 tomoj: hmm

21:28 is read-string dangerous?

21:28 Raynes: <3 read-string

21:28 chouser: tomoj: yep, unless you turn off *read-eval*

21:28 st3fan: well the string comes from a regex that matches a number

21:28 so i doubt there will be 'lisp injection' errors :-)

21:29 chouser: probably good enough.

21:30 ,(read-string "#=(java.lang.System/exit 0)")

21:30 clojurebot: java.lang.RuntimeException: java.lang.Exception: EvalReader not allowed when *read-eval* is false.

21:35 st3fan: when i have a .clj file open in emacs with slime and clojure-mode, how do i compile the whole file?

21:35 C-c C-c only seems to compile the last form in the file

21:36 Raynes: st3fan C-c C-l, if you want to load the entire file into the REPL. If that's what you mean.

21:37 st3fan: is that a good way to do 'edit, compile, test-in-repl' ?

21:37 Raynes: It's how I do it.

21:37 * Raynes shrugs

21:38 somnium: C-c C-k recompiles it if it's already loaded

21:38 st3fan: cool

21:39 Raynes: st3fan: You can also evaluate a single sexp if you put the cursor just after the last closing paren and do C-x C-e.

21:39 st3fan: ahhh good one

21:40 somnium: it doesn't add in new vars after recompilation, have to do (use ... :reload), existing vars get instantly updated though

21:40 st3fan: right

21:41 Raynes: Incidentally, I just always use C-c C-l.

21:41 st3fan: what is the advantage over C-c C-k ?

21:42 Raynes: I'm not sure why you would use C-c C-k. Maybe somnium can help us out on this one.

21:42 st3fan: it works on the current buffer .. skips the query for the file?

21:43 is there a logging library for clojure? or some simple wrapper?

21:46 somnium: Raynes: well, with compojure for example, jetty is off spinning in another thread, you can recompile the code and it immediately responds

21:47 st3fan: yeah that is cool

21:47 somnium: though perhaps its the same with load file? I've gotten into the habit of using recompile

21:49 hiredman: st3fan: there is something in contrib

21:49 (that I really should try out)

21:59 st3fan: hmm is there a way to load a jar file from the repl? i don't want to restart emacs

22:01 hiredman: there is add-classpath

22:01 but uh, don't make a habit of using it

22:02 st3fan: i have no idea how to package clojure apps yet :-)

22:02 hiredman: *shrug*

22:02 add-classpath is not about packaging

22:02 st3fan: i know

22:02 hiredman: it's about adding a jar/directory to the classpath

22:03 st3fan: but i know my app depends on some jars

22:03 somnium: you can just put .clj files in a jar and put in the classpath when you start clojure

22:03 st3fan: right

22:04 little shell script wrapper to setup the classpath and start the app?

22:04 somnium: yeah, if you always ./lib and ./src ... you can use the same one everywhere

22:05 have you used clojure-project or swank-clojure-project in slime?

22:05 that's what they do

22:09 Raynes: somnium: clojure-project? What's this voodoo you speak of?

22:10 somnium: Raynes: eh? it comes with one of the clojure...el files

22:10 Raynes: you use ant right?

22:10 Raynes: Mhm.

22:10 somnium: I changed it to work ant if you want to try the function

22:10 Raynes: I tried M-x clojure-project - Nothing happened. :>

22:10 somnium: it was built to use maven but one xml dialect is enough for me

22:12 ambient: i find classpath annoying :/

22:12 automatically adding project root, from whence the source file is ran from, to the classpath would be nice

22:12 dont know if that is possible with JVM

22:14 st3fan: man i love how much i get done with a bunch of small functions

22:14 somnium: Raynes: http://paste.lisp.org/display/89477

22:14 st3fan: without the infrastructure that a regular java app would need

22:14 somnium: its pretty much a copy of the original but it looks for build.xml instead of a pom

22:15 and I keep stuff in ~/.clojure, so if you decide to try it change the relevent paths

22:16 Raynes: Thanks. <3

22:19 st3fan: question .. what does the & mean in (insert-records table & records) ? does it mean records is like a vararg?

22:19 like (insert-records :mytable {} {} {}) ?

22:20 hiredman: yeah

22:20 st3fan: hmm what if i have a list of maps? can i do something like python's (insert-records :mytable *listofmaps) ?

22:21 chouser: (apply insert-records :mytable listofmaps)

22:22 st3fan: ahh i remember this from practical common lisp :-)

22:23 cemerick: man, dealing with agent errors can get tricky

22:23 st3fan: cool it works :-)

22:26 chouser: cemerick: there's ticket for that

22:31 technomancy: chouser: thanks for committing my deletion patch for contrib!

22:37 chouser: technomancy: finally. :-) You're welcome. You saw my note?

22:40 technomancy: chouser: if it was a note in IRC I missed it; closed my client indiscriminately after work.

22:40 * technomancy makes a mental note to finally set up dircproxy

22:41 chouser: technomancy: no, on assembla

22:42 technomancy: oh, I see; the windows question

22:49 cemerick: It seems a little absurd that StackOverflowError is an error.

22:49 chouser: instead of?

22:51 cemerick: I consider it to be an app-level failure, especially these days and with current languages.

22:52 or, current popular idioms, I should say

22:54 technomancy: chouser: sorry; crap connection here. will try to test in a windows VM

22:54 chouser: technomancy: thanks.

22:55 technomancy: appreciate the attention to the tickets. =)

22:58 djork: so I've been playing with verifiable objects

22:59 tomoj: what are verifiable objects?

23:00 djork: let's say you have a map or a vector

23:00 and you want to share it

23:00 but you don't want someone to be able to modify it

23:03 cemerick: heh, where were you when rhickey was trying to represent the static type folk? ;-)

23:04 chouser: nobody can modify any of Clojure's maps or vectors. :-)

23:05 djork: http://gist.github.com/220900

23:05 so you set your salt on a server, for instance

23:05 and you can store large data structures in other places

23:06 I guess it's not that special but it was fun to think about

23:07 wooby: hey all, working on project euler prob 92... came up with this: http://gist.github.com/221079

23:07 for some reason that last line doesn't terminate, for any size range

23:07 djork: I was thinking about this in the context of MMO games where maybe you don't want to store every piece of data ever generated by players, or you could let players store unique items etc

23:07 wooby: any help very welcome

23:08 tomoj: djork: so that would mean a player couldn't forge an item?

23:08 pretty cool

23:09 djork: yup

23:09 tomoj: does giving out a large number of hashes using the same salt expose you?

23:10 cemerick: sha-1 isn't doing its job in that case, no?

23:11 djork: sha-1 is probably fine

23:11 the salt could be anything

23:11 tomoj: why does authlogic for example use a different salt for every user?

23:11 cemerick: right, I'm sure it is, I was just saying that if we can't depend on sha-1, then a lot of stuff is in trouble :-)

23:11 tomoj: I guess maybe that's so you can't tell that two passwords are the same

23:11 in this case that doesn't matter

23:11 djork: it's better to change up the salt

23:12 but it isn't super critical

23:12 in a password situation you want a different salt because it means a rainbow table is ineffective against any other password

23:13 so maybe a secret permutation of some part of what you're hashing would be good

23:15 tomoj: well rainbow tables etc don't matter at all in this case, right?

23:15 because they already have the object

23:52 hiredman: clojure is so cool

23:53 wooby: can't agree more

23:53 hiredman: http://gist.github.com/221130 <-- check for files added/removed on an ftp directory and message me on jabber with the differences

23:54 wooby: that's insanely awesome

Logging service provided by n01se.net