2009-10-28
| 00:00 | somnium | Licenser: heyyy |
| 00: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 |
| 00:00 | Licenser | I forked you :P muhahah |
| 00:00 | somnium | Licenser: almost got 0.1 ready |
| 00:00 | somnium | already? |
| 00:00 | somnium | its about to change a lot, for the better |
| 00:00 | Licenser | yea wanted to try it ^^ |
| 00:00 | somnium | got a working little ClojureDBObject java class that does all that tree walking work |
| 00:01 | somnium | cleaning up the core so its actually readable now, dropping coerce.clj entirely |
| 00:01 | hiredman | http://rubyrags.com/products/10 |
| 00:01 | Licenser | nice |
| 00:01 | Licenser | somnium: I found a few things I needed and figured it's a good chance to try out github :P |
| 00:01 | somnium | its funny, after a night's sleep that java didn't look so bad |
| 00:02 | Licenser | What did you do before sleeping finish up a bottle vodka alone? |
| 00:02 | somnium | I'm considering doing an immutable proxy, itll be interesting to benchmark and see how much overhead using a ref involves |
| 00:03 | Licenser | heh yup that would be interesting |
| 00:04 | somnium | Licenser: a corner, a stuffed animal, and a bottle of vodka |
| 00:04 | Licenser | ah okay that explains a lot |
| 00:05 | somnium | also switch to 1.0 core and contrib, and I'll put the needed mongodb-drivers in the jar |
| 00:05 | somnium | hopefully itll be more plug and play |
| 00:05 | somnium | its never good when something can blow up on build |
| 00:06 | Licenser | true |
| 00:06 | somnium | Licenser: did you manage to do anything with it in any case? |
| 00:06 | Licenser | yes it is working quite well, biggest problem I had was that object-to-map did ont work on recursive objects |
| 00:06 | somnium | yeah, its tricky |
| 00:07 | Licenser | well that one I fixed :P |
| 00:07 | somnium | there are some things to do with encodings, but its broken right now and presumably the dev's are sleeping |
| 00:07 | somnium | cool |
| 00:07 | somnium | with a walker? |
| 00:07 | somnium | its hard to find non-recursive solutions to nesting problems |
| 00:07 | somnium | thats what the little java class helps with |
| 00:07 | Licenser | somnium: actually I borke it again ... narf |
| 00:08 | Licenser | well I just recursively called the function |
| 00:08 | somnium | and keywords for keys again |
| 00:08 | Licenser | Oh you removed keywards as keys again? |
| 00:08 | somnium | I did before because it was broken |
| 00:08 | somnium | now they're back |
| 00:09 | somnium | the proxy class is a hashmap, you can bang on them in java |
| 00:09 | Licenser | heh Okay then I had the string version which brakes my code :P that is why I'm so confused |
| 00:09 | somnium | default is to convert stuff to clojure, but if you want to optimize something its right there |
| 00:09 | somnium | hmm, I would push but only fetch is working now, if youll be around for an hour it might be ready to try out |
| 00:10 | Licenser | I'll be |
| 00: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 |
| 00:15 | qed | chouser: are you around? |
| 00:15 | qed | chouser: im wondering if you could explain some stuff about your problem 59 on proj. euler |
| 00:15 | Licenser | defschema? I've a older version I think |
| 00:16 | Licenser | this one still uses defcoercion |
| 00:16 | somnium | yeah, its orthogonal |
| 00:17 | somnium | http://paste.lisp.org/display/89409 <- sneak preview, more readable? |
| 00:17 | Licenser | so there isn't any defschema in the version I forked |
| 00:17 | somnium | yeah, I haven't added it yet |
| 00:18 | somnium | but I think most of the low level problems are almost done, so can start adding more ORMy features |
| 00:18 | Licenser | one thing, you should decide if you call it col or coll ;) |
| 00:18 | Licenser | that was one of the things I changed :P |
| 00:18 | somnium | ah, in the arguments? |
| 00:19 | Licenser | yap the functions are called *-coll the arguments are called col |
| 00:19 | Licenser | 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 |
| 00:19 | somnium | I don't like using coll in arguments cause that's name clojure uses for collections |
| 00:20 | somnium | and collection is too many keystrokes |
| 00:20 | somnium | maybe Ill change it to 'c' |
| 00:20 | Licenser | then name the functions -col too ;) |
| 00:20 | somnium | ok |
| 00:20 | Licenser | oh and I changed every argument that was named map to m |
| 00:20 | somnium | look at the paste |
| 00:20 | Licenser | when you call an argument map, it hides the map function in the rest of the body :P |
| 00:20 | somnium | that function is what coerce.clj was |
| 00:21 | Licenser | oh wow |
| 00:21 | somnium | and it even does more :) |
| 00:21 | Licenser | toClojureKeywordArrayMap is sneaky |
| 00:21 | somnium | the keywords are kind of a hack, mongodb has no default way to recognize them |
| 00:22 | somnium | if I can get the encoding bug sorted tomorrow it might be possible |
| 00:22 | Licenser | I know they use string keys |
| 00:22 | somnium | mongodb supports custom binary types |
| 00:22 | somnium | the java driver doesn't support it, but eliot said it would be trivial to add |
| 00:22 | Licenser | yes but storing keywords in a custom binary, isn't it easyer to store them in strings |
| 00:22 | somnium | it is if a fast little java class does it for you |
| 00:23 | Licenser | Bah java classes |
| 00:23 | somnium | it'll be possible to create custom binary types for any arbitray class |
| 00:23 | Raynes | Bah, Java. |
| 00:23 | somnium | and that means defschema could gen-class a struct map, all kinds of cool and efficient automagic become possible |
| 00: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 |
| 00:26 | somnium | yeah, and if you have embedded document slot the deserializer just has to know, know reflection, no tree walking |
| 00:26 | qed | damn you euler! |
| 00:26 | qed | oiler = euler |
| 00:26 | qed | coincidence |
| 00:26 | somnium | er, no reflection |
| 00:26 | Licenser | nice |
| 00:35 | Licenser | I really see forward to the next version :P |
| 00: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 :) |
| 00:38 | somnium | maybe you could write a mongo-compojure todo example :D |
| 00:39 | Licenser | somnium: I will once I get it working ;) |
| 00:40 | Licenser | and I'll wait till you have it half way beta |
| 00:40 | somnium | yeah, I'm actually planning to use it for a prototype due next week |
| 00:41 | somnium | so I really want to get something worthy of 0.1 finished tonight |
| 00:41 | Licenser | heh |
| 00:41 | Licenser | 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 |
| 00:41 | somnium | true |
| 00:41 | somnium | the readme I did was mostly an exercise in learn markdown :) |
| 00:42 | Licenser | ^^ |
| 00:43 | Licenser | mongo is a lot easyer then SQL once you get the things actually working o.O |
| 00:44 | somnium | yeah, the only place it falls down is if you need complex transactions |
| 00:44 | Licenser | true but at least I don't need them |
| 00:44 | somnium | though to be honest I can't recall the last time I needed them for a web app |
| 00:44 | Licenser | exactly :P |
| 00:45 | somnium | er, that should be never |
| 00:45 | Licenser | also I'm pretty sure you could wrap them in a clojure transaction and bunch commit |
| 00:45 | somnium | trouble is its all side effecty |
| 00:45 | somnium | the dbobjects, server messaging |
| 00:45 | somnium | no way the stm can help with that |
| 00:46 | somnium | mongo has to support it server-side |
| 00:46 | Licenser | true |
| 00:46 | somnium | hrm, does it support transactions at all? |
| 00:49 | Licenser | no mongo is non transactional |
| 00:49 | somnium | theres an 'update-if-current' command |
| 00:51 | somnium | if x = y, set x to z, else fail |
| 00:51 | somnium | that can lock an entire document |
| 00:51 | somnium | good enough for me :) |
| 00:51 | Licenser | heh |
| 00:52 | Licenser | hrm |
| 00:53 | adityo | Good morning all |
| 00:53 | adityo | :) |
| 00:54 | Licenser | morning adityo |
| 00:54 | Licenser | somnium: but I see your point mongodb destroys the nice concurrency of clojure, at least makes it not so easy :( |
| 00:54 | Licenser | not that one needs it for a web app :P |
| 01:00 | somnium | who knows, mongo is developing rapidly, the dev team is awesome |
| 01:00 | somnium | 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 |
| 01:00 | somnium | er, ask for something not supported (in the java driver anyway) |
| 01:01 | somnium | and within 10 minutes there's a fresh push to github |
| 01:01 | Licenser | yap |
| 01:01 | Licenser | they seem cool |
| 01:01 | Licenser | I was in the channel to ask a few questions and the peopel really helped me |
| 01:01 | Licenser | 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 |
| 01:02 | Licenser | try to ask a VB questions - no chance :P |
| 01:02 | somnium | heh |
| 01:02 | Licenser | seriousely, even the ruby community got gess friendly the more prominent the language became - at least it is my impression |
| 01:03 | Licenser | For Solaris people try to help you for most linux distributions you get just told RTFM |
| 01:03 | somnium | Ive seen people be pretty rude in the ruby channels |
| 01: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 |
| 01:04 | Licenser | hrm I've a seriouse problem |
| 01:04 | somnium | ? |
| 01:04 | Licenser | update kills my db entry |
| 01:05 | somnium | thats no good |
| 01:05 | Licenser | if I don't pass all arguments to update it just removes the others o.O that is very odd |
| 01:05 | somnium | I would say paste the before and after, but its all getting rewritten |
| 01:05 | somnium | Licenser: ah, look at the code then, its meant to be used with all three arguments |
| 01:05 | somnium | the shorter versions should carry warnings |
| 01:06 | somnium | they're convenient if they do exactly what you want (or that was the intention) |
| 01:06 | Licenser | hmm but it's a mongo thing |
| 01:06 | somnium | really? |
| 01:06 | Licenser | yes it's scarry |
| 01:07 | somnium | something like {:match :this} (merge old-map {:change :this}) should work? |
| 01:07 | Licenser | not for bulk updates |
| 01:07 | somnium | ah, I haven't tried those |
| 01:07 | somnium | doing javascript? |
| 01:08 | Licenser | yes I tried it from the console now |
| 01:08 | Licenser | to see if it is a problem with mongo, or with something between my app and mongo |
| 01:08 | Licenser | since it happens on the DB it seems that it is a problem with mongo :P |
| 01:09 | Licenser | ah I've to use $set |
| 01:09 | Licenser | sneaky |
| 01:10 | somnium | there's a thread on the mailing list saying its not supported until 1.1.3 |
| 01:10 | Licenser | I have 1.1.3 |
| 01:10 | Licenser | so I really would expect update to update not replace |
| 01:11 | Licenser | ow |
| 01:11 | somnium | well, as long as its just surprising and not broken |
| 01:14 | Licenser | it tells me: when using $ modifiers, apply has to be false |
| 01:15 | Licenser | seems like a problem in your driver :P *hides* |
| 01:16 | Licenser | hrm not good |
| 01:17 | Licenser | odd |
| 01:17 | somnium | hmm |
| 01:18 | somnium | what command exactly? |
| 01:18 | somnium | I took out the '> shortcuts for now |
| 01:18 | Licenser | update but diggind deeper it seems to come from java |
| 01:18 | Licenser | nah I sed $set in the update statment |
| 01:18 | Licenser | java.lang.IllegalArgumentException: when using $ modifiers, apply has to be false |
| 01:18 | Licenser | that is what it says |
| 01:19 | somnium | { :x { "$set" : "this" } } ? |
| 01:20 | somnium | hmm, I know the java-driver better than I know how to use mongo at this point :( |
| 01:20 | Licenser | {$set: {:x "this"}} |
| 01:20 | Licenser | this one |
| 01:20 | Licenser | {"$set" {:x "this"}} |
| 01:20 | Licenser | rather that |
| 01:21 | somnium | I think it should be {:x {"$set" ... } } no? |
| 01:21 | somnium | youre right |
| 01:21 | Licenser | works on the console like this: > db.map.update({x: 5, y: 5}, {$set: {"owner.id": 42}}) |
| 01:22 | Licenser | so this apply thing has to do with the java driver, which I've no clue off |
| 01:22 | somnium | ah I know |
| 01:22 | somnium | there's a flag on update |
| 01:22 | somnium | check the source, update sends true true at the end |
| 01:22 | somnium | usually you want apply, it adds _ns and _id if they're missing |
| 01:22 | Licenser | there are two flags, one says upsert the other multi |
| 01:23 | somnium | on the java call |
| 01:23 | Licenser | I know was the first thing I looked at but the API says those two are upsert and multi nothing with apply |
| 01:23 | somnium | I know I saw it somewhere |
| 01:24 | somnium | maybe BasicDBObject? or DBCollection? |
| 01:24 | Licenser | it is a function of the Collection |
| 01:25 | Licenser | there is a apply function in the collection but I don#t see it called anywhere |
| 01:25 | somnium | will definitely need more granular control of cursors and collections in the api |
| 01:26 | somnium | is there a setter? setDoApply or something? |
| 01:26 | Licenser | nope only 3 methonds, apply, apply and doapply |
| 01:27 | somnium | hmm, I'm out of my depth |
| 01:27 | Licenser | me too sadly |
| 01:31 | somnium | Licenser: you can go low level for the time being, until the Mongo devs wake up |
| 01:31 | Licenser | somnium: hm? |
| 01:32 | Licenser | oi a new one: No matching method found: updateMulti for class com.mongodb.DBApiLayer$MyCollection |
| 01:32 | Licenser | while that is in the API documentation o.O |
| 01:32 | somnium | yeah the API Docs aren't totally reliable |
| 01:32 | somnium | there's a missing fetch with skip, limit options too |
| 01:32 | somnium | forgot to ask about that |
| 01:32 | somnium | it'll help if youre asking questions about the java driver too :) |
| 01:32 | Licenser | ah wait no it's in the wrong doc |
| 01:32 | Licenser | *g* |
| 01:33 | somnium | DB has an eval method |
| 01:33 | somnium | you can send javascript, though I'm not quite sure how it works |
| 01:33 | somnium | hopefully anything broken in the driver can get through there when things like this happen |
| 01:34 | Licenser | ah sneaky |
| 01:39 | Licenser | oh fork |
| 01:39 | Licenser | of cause the DB does not know eval :P |
| 01:40 | somnium | the db object in *mongo-config* is actually a DBTCP, you might have to get a hold of a lower level class |
| 01:41 | somnium | just read the javadoc! |
| 01:41 | somnium | * hides * |
| 01:42 | Licenser | somnium: sadly DBTCP isn't documented :P |
| 01:42 | somnium | the DB class is, that's where eval lives |
| 01:42 | Licenser | actually it si |
| 01:43 | somnium | I was creating the DB object through Mongo which return a DBTCP object |
| 01:43 | somnium | but you can also go through the DB class? no idea, there's way too many classes in that damn package |
| 01:43 | Licenser | but it should have eval |
| 01:43 | Licenser | somnium: yes there are |
| 01:43 | Licenser | and I hate javadoc :P |
| 01:43 | Licenser | it's the same problem as with every inline documentation |
| 01:43 | somnium | if the design is good and the package structure is good, they can be very useful |
| 01:43 | somnium | not the case here |
| 01: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 |
| 01:44 | somnium | really, should ByteEncoder and BasicDBObject live in the same package? |
| 01:44 | Licenser | heh |
| 01:45 | Licenser | sadly eval isn't documentaed at all |
| 01:45 | somnium | yeah, it sucks, no idea what the Object argument is supposed to be |
| 01:46 | Licenser | *nods* I skpped it since I found ... means 0 or more :P now I'll just pass #^Object nil |
| 01:47 | somnium | cool |
| 01:47 | Licenser | does not really work either |
| 01:48 | somnium | hmm |
| 01:48 | somnium | doseq update till the devs wake up? |
| 01:48 | Licenser | and netbeans seem to ahve a very odd idea about reloading |
| 01:49 | somnium | if youre feeling adventurous you could look at Message... classes |
| 01:49 | Licenser | heh |
| 01:49 | Licenser | soon I can go and grab breakfast :P |
| 01:50 | Licenser | user=> (mongo-eval! "db.map.update({x: 5, y: 5}, {$set: {'owner.name': 'Test Owner'}})") |
| 01:50 | Licenser | #<BasicDBObject { "retval" : null , "ok" : 1.0 , "_ns" : "$cmd"}> |
| 01:50 | Licenser | wooh! |
| 01:50 | somnium | awesome |
| 01:50 | somnium | could you paste mongo-eval! ? |
| 01:50 | Licenser | that works |
| 01:50 | Licenser | sure |
| 01:50 | somnium | I'll definitely add that as a backdoor |
| 01:50 | somnium | it'll always need to be there :) |
| 01:51 | somnium | sweet |
| 01:51 | Licenser | wooh now I contributed :P |
| 01:52 | somnium | ! :) |
| 01:52 | somnium | huh, so it did work on DBTCP after all |
| 01:52 | Licenser | yap just you need a nil in there |
| 01:55 | Licenser | okay this is so horribly going to break ... |
| 01:55 | somnium | ? |
| 01:56 | Licenser | the hacked together eval stuff :P |
| 01:56 | somnium | contrib.json might help |
| 01:57 | Licenser | I used the mongo one |
| 01:57 | somnium | I'm hoping to get a hook into the JSON writer too |
| 01:58 | somnium | or, actually there's one now, but it's broken |
| 01:58 | Licenser | heh |
| 01:58 | Licenser | okay I will use contrib.json |
| 01:58 | somnium | it speaks native clojure at least |
| 02:00 | kanak | Which is better (more idiomatic/faster/etc): doing something like (reduce * [1 2 3]) or (apply * [1 2 3]) ? |
| 02:00 | somnium | kanak: reduce |
| 02:01 | kanak | thanks. is it because it signals the intention more clearly? |
| 02:01 | Licenser | apply is better |
| 02:01 | Licenser | at least I find it |
| 02:01 | somnium | they do different things |
| 02:01 | somnium | it would be easier to say with something other than * |
| 02:02 | Licenser | yes but for this case it's faster to do (* 1 2 3) then (* (* 1 2) 3) |
| 02:02 | somnium | kanak: apply = unpack this list, reduce means create a single value from this collection |
| 02:02 | somnium | kind of |
| 02:03 | somnium | ,(time (apply + (take 10000 (iterate inc 1)))) |
| 02:03 | clojurebot | 50005000 |
| 02:03 | clojurebot | "Elapsed time: 56.728 msecs" |
| 02:03 | Licenser | woha yea! |
| 02:03 | somnium | ,(time (reduce + (take 10000 (iterate inc 1)))) |
| 02:03 | clojurebot | 50005000 |
| 02:03 | clojurebot | "Elapsed time: 28.939 msecs" |
| 02:03 | somnium | see its faster :) |
| 02:04 | kanak | cool :) |
| 02:04 | Licenser | okay now I'm impressed AND confused |
| 02:04 | kanak | is reduce a left-fold or a right-fold? |
| 02:04 | Licenser | hmm but I think that is because the list is unpacked the first time |
| 02:05 | Licenser | hrm how again could I force a lazy seq to unlasy? |
| 02:05 | kanak | it'd be interesting if we could compare the space usage of the reduce vs apply. |
| 02:06 | Licenser | reduce will have less space usage |
| 02:06 | Licenser | because it only needs 2 elements from the list |
| 02:06 | Licenser | and if your list isn't static but a lazy seq they will be GC'ed at some point |
| 02:07 | kanak | Licenser: by 2 elements, you mean the "answer so far" and the the first element from the list. right? |
| 02:07 | somnium | yeah, reduce is a shortcut for loop |
| 02:07 | somnium | unless you need mutual recursion |
| 02:08 | somnium | ^^ doall and dorun, depending on what you want it to return |
| 02:08 | Licenser | kanak: yap |
| 02:09 | Licenser | somnium: I wanted to have the expendet list in the end :P |
| 02:09 | Licenser | I want to see if reduce is faster because it's faster or because the test case is a lazy seq |
| 02: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) |
| 02:10 | somnium | actual limit is capped at 18 or so |
| 02: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)? |
| 02:11 | somnium | you have the answer so far and the next item in each iteration |
| 02:11 | somnium | until no more items |
| 02: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? |
| 02:13 | somnium | yeah, the current item only every exists as a local variable in the last stack frame |
| 02:13 | somnium | the previous version of the list too |
| 02:13 | somnium | so it handles memory well |
| 02:13 | Licenser | kanak: since noone knows what the GC does it can't be guaranteed |
| 02:14 | kanak | I see. thank you both :) |
| 02:14 | somnium | for small operations like that its probably on the stack |
| 02:14 | Licenser | but the list will never flood your memory |
| 02:15 | somnium | just dont do this |
| 02:15 | somnium | ,(iterate inc 1) |
| 02:15 | clojurebot | Eval-in-box threw an exception:java.lang.OutOfMemoryError: Java heap space |
| 02:15 | Licenser | :P |
| 02:15 | kanak | heh. that's evil |
| 02:15 | Licenser | I think the problem is the print |
| 02:15 | Licenser | ,(def x (iterate inc 1)) |
| 02:15 | clojurebot | DENIED |
| 02:15 | somnium | yeah, poor little guy tried to print the answer |
| 02:15 | Licenser | narf |
| 02:16 | Licenser | ,(second x (iterate inc 1)) |
| 02:16 | clojurebot | java.lang.Exception: Unable to resolve symbol: x in this context |
| 02:16 | Licenser | ,(second (iterate inc 1)) |
| 02:16 | clojurebot | 2 |
| 02:16 | Licenser | there we go |
| 02:16 | Licenser | didn't took much time to calculate all numbers :P |
| 02:17 | somnium | ,(nth (iterate inc 7) 4242) |
| 02:17 | clojurebot | 4249 |
| 02:17 | Licenser | hmm somnium the eval works fine, my project is running so far |
| 02:17 | somnium | Licenser: good to hear it |
| 02:17 | somnium | hmm |
| 02:17 | Licenser | hmm hmm |
| 02:17 | Licenser | do you wonder what I wonder? |
| 02:19 | somnium | (nth (iterate #(+ 7 %) 0) 4242) |
| 02:19 | somnium | ,(nth (iterate #(+ 7 %) 0) 4242) |
| 02:19 | clojurebot | 29694 |
| 02:19 | somnium | he counts pretty fast |
| 02: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 |
| 02:19 | hiredman | ~clojurebot |
| 02:19 | clojurebot | clojurebot is amazing |
| 02:19 | hiredman | ~clojurebot |
| 02:19 | clojurebot | clojurebot is not a benchmarking platform |
| 02:19 | somnium | sure |
| 02:19 | somnium | lol |
| 02:19 | Licenser | somnium: comon it are only 4242 numbers |
| 02:20 | Licenser | even ruby does it instantly |
| 02:21 | Licenser | ~hiredman |
| 02:21 | somnium | could you paste what was broken? I'm not sure I know quite what to ask |
| 02:21 | clojurebot | hiredman is slightly retarded |
| 02:21 | Licenser | :P |
| 02:21 | hiredman | clojurebot: watch it |
| 02:21 | clojurebot | Huh? |
| 02:22 | hiredman | clojurebot: you heard me |
| 02:22 | clojurebot | hiredman: I'm just giving you a second chance |
| 02:22 | somnium | ~botsnack |
| 02:22 | clojurebot | thanks; that was delicious. (nom nom nom) |
| 02:22 | hiredman | clojurebot: why I outta! |
| 02:22 | clojurebot | why not? |
| 02:23 | somnium | hiredman: shouldn't (nom nom nom) come before he says delicious? |
| 02:23 | Licenser | and with |
| 02:23 | Licenser | * |
| 02:23 | Licenser | not ( |
| 02:23 | Licenser | actions are classically indicated with * IRC isn't lisp |
| 02:23 | Licenser | ~somnium |
| 02:23 | clojurebot | No entiendo |
| 02:24 | hiredman | the nom nom thing is just another factiod, someone told it that was the proper response to "botsnack" |
| 02:24 | hiredman | clojurebot: seen somnium |
| 02:24 | clojurebot | somnium was last seen in #clojure, 1 minutes ago saying: hiredman: shouldn't (nom nom nom) come before he says delicious? |
| 02:25 | Licenser | clojurebot: do you want cookies? |
| 02:25 | clojurebot | Gabh mo leithscéal? |
| 02:25 | Licenser | who set the bit to spanish o.o |
| 02:25 | somnium | hiredman: well I suppose that's true |
| 02:25 | hiredman | ~google Gabh mo leithscéal |
| 02:25 | clojurebot | First, out of 2180 results is: |
| 02:25 | clojurebot | Urban Dictionary: gabh mo leithscéal |
| 02:25 | clojurebot | http://www.urbandictionary.com/define.php?term=gabh%20mo%20leithsc%C3%A9al |
| 02:25 | somnium | ~php |
| 02:25 | clojurebot | Gabh mo leithscéal? |
| 02:26 | somnium | he really should have something to say about that |
| 02:26 | somnium | ~microsoft |
| 02:26 | clojurebot | No entiendo |
| 02:26 | somnium | ~java |
| 02:26 | clojurebot | ☕ |
| 02:28 | somnium | ~scheme |
| 02:28 | clojurebot | Excuse me? |
| 02: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 |
| 02:30 | clojurebot | Roger. |
| 02:30 | somnium | ~self loathing |
| 02:30 | clojurebot | Titim gan éirí ort. |
| 02:30 | somnium | ~google Titim gan éirí ort. |
| 02:30 | clojurebot | First, out of 850 results is: |
| 02:30 | clojurebot | Irish phrases in the Gaelic language - Irish sayings |
| 02:30 | clojurebot | http://www.ireland-information.com/irishphrases.htm |
| 02:32 | adityo | ~lisp |
| 02:32 | clojurebot | Lisp isn't a language, it's a building material. |
| 02:32 | adityo | ~perl |
| 02:32 | clojurebot | Excuse me? |
| 02: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 |
| 02:35 | hiredman | I'd love to get clojure going on a pleo or an aibo |
| 02:35 | somnium | aibo was discontinued :( |
| 02:36 | hiredman | was the pleo for a bit, and now it's back |
| 02:36 | somnium | a lot of soldiers grow very attached to their bomb disarming robots |
| 02:36 | somnium | is it? good |
| 02:36 | hiredman | maybe even a little netbook+rc car |
| 02:36 | Licenser | no don't send the robot! I will go, we can't let him get hurt! |
| 02:37 | somnium | they've run into exposed areas to save them |
| 02:37 | Licenser | o.O |
| 02:37 | somnium | the designers apparently try to make them as unlikeable as possible |
| 02:38 | Licenser | wow that is crazy |
| 02:38 | Licenser | hiredman: what is pleo? |
| 02:39 | somnium | ~google pleo |
| 02:39 | clojurebot | First, out of 1100000 results is: |
| 02:39 | clojurebot | PleoWorld: The Home of Pleo, the Robotic Baby Dinosaur from Innvo Labs |
| 02:39 | clojurebot | http://www.pleoworld.com/ |
| 02:39 | arsatiki | it'd b cool to equip a pleo with a bluetooth receiver |
| 02:40 | arsatiki | so it could start following people who have their phones with them |
| 02:41 | somnium | ~gumstix |
| 02:41 | clojurebot | Pardon? |
| 02:44 | Licenser | haha that thing looks funny |
| 02:45 | Licenser | but no shipping to germany, narf |
| 02:57 | Licenser | okay peopel I need to go to work, take care and don't brake tne interwebs |
| 02:58 | somnium | cheers |
| 02:58 | kanak | is it more idiomatic to use memfn or to use an anonymous function? |
| 02:58 | somnium | (doc memfn) |
| 02: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." |
| 03:01 | kanak | The programming clojure book claims that anonymous fns should be preferred to memfn, which sounds a little odd. (pg 87) |
| 03:02 | hiredman | #() fn literals are used far more often than memfn |
| 03:02 | hiredman | memfn was created before #() existed, if I recall |
| 03:03 | kanak | I see. |
| 03:03 | kanak | hiredman: do you know of any projects with idiomatic clojure that is suitable for someone who is "intermediate" in clojure? |
| 03:04 | somnium | kanak: IMO the source code in contrib excellent for learning clojure idioms |
| 03:05 | somnium | kanak: core for that matter |
| 03:05 | kanak | somnium: any libraries in particular? |
| 03:05 | somnium | there's so many, the ones I use? :) |
| 03:05 | somnium | try using contrib.repl-utils/show on the functions you already know |
| 03:05 | kanak | sorry. i meant are there any particular ones you're thinking of |
| 03:06 | somnium | er, source, not show |
| 03:07 | somnium | core is best for 'idioms' probably |
| 03:07 | somnium | very generic operations |
| 03:07 | somnium | contrib is all specialized |
| 03:07 | hiredman | core.clj is very readable |
| 03:09 | kanak | thank you both for your help. :) |
| 03:10 | hiredman | http://delicious.com/clojurebot/pastbin+rhickey |
| 03:10 | hiredman | http://delicious.com/clojurebot/pastbin+chouser |
| 03:11 | somnium | wow, hes already got a working prototype for defclass? |
| 03:11 | somnium | or is that a 'syntax prototype' ? |
| 03:12 | hiredman | http://delicious.com/clojurebot/pastbin+technomancy |
| 03:12 | hiredman | somnium: I think it works, I haven't checked |
| 03:12 | somnium | I have to say, its exciting to watch a project develop with such speed |
| 03:19 | hamza | hey guys, URLConnection getHeaderFields returns an UnmodifiableMap how can i turn this in to a clojure map? (hash-map fields) returns illeagelArgumentException? |
| 03:22 | hiredman | hamza: (into {} fields) ? |
| 03:25 | hamza | thx that worked.. |
| 03:26 | hamza | but some now some vals are wrapped in UnmodifiableRandomAccessList do i have to iterate all and build it my self? |
| 03:31 | hiredman | yes |
| 03:32 | G0SUB | what is the best way to manage settings for dev/production envs in a clojure app? |
| 03:40 | hiredman | well, you have a reader, so you can make a dev.clj and a production.clj |
| 03:43 | G0SUB | hiredman: how do I make sure one of the files is loaded automatically? (I am in Emacs/SLIME) |
| 03:45 | hiredman | (cond (.exists (File. "dev.clj")) (read (reader "dev.clj")) ...production.. ..testing...) |
| 03:45 | hiredman | dev.clj has a map in it, so that is in a function that returns a map containg your settings |
| 03:48 | hiredman | you could use a properties file if you want to be java about it |
| 03:49 | hiredman | http://java.sun.com/javase/6/docs/api/java/util/Properties.html |
| 04:06 | G0SUB | hiredman: so, for production env, I will have to delete the dev.clj file? |
| 04:07 | Fossi | hi |
| 04:14 | hiredman | G0SUB: sure |
| 04:14 | hiredman | w |
| 04:14 | hiredman | huh, this ain't vim |
| 04: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 |
| 04:27 | felzix | How do I find the intersection of two lists? |
| 04:27 | felzix | The function "intersection" doesn't appear to actually exist in the 1.0 release. |
| 04:27 | adityo | felzix: might be useful if you convert them in to hash-sets |
| 04:28 | adityo | how will i merge a list of maps ({} {} {}) into a {} |
| 04:28 | felzix | hmm |
| 04:28 | felzix | what version did intersection get introduced? |
| 04:29 | felzix | nvm, I see |
| 04:30 | adityo | ,(doc clojure.set/intersection) |
| 04:30 | clojurebot | "([s1] [s1 s2] [s1 s2 & sets]); Return a set that is the intersection of the input sets" |
| 04:30 | hiredman | ,(reduce into {} '({:a 1} {:b 2} {:c 3})) |
| 04:30 | clojurebot | {:a 1, :b 2, :c 3} |
| 04:30 | felzix | It keeps telling me that it can't resolve the symbol "intersection" |
| 04:31 | felzix | the same is true of other set functions |
| 04:31 | adityo | cool thanks hiredman :) |
| 04:31 | hiredman | felzix: are you using the clojure.set namespace? |
| 04:31 | adityo | felzix do a use or require |
| 04:31 | felzix | oh, I have to explicitly add it? I thought it came along with everything else |
| 04:31 | felzix | that works! thanks! |
| 04:31 | hiredman | it's included in the clojure jar |
| 04:32 | hiredman | but you have to require or use it or load it like every other namespace |
| 05:49 | felzix | This function's return value isn't getting printed: (defn get-pos [tags] |
| 05:49 | felzix | (filter #(= (first %) \+) |
| 05:49 | felzix | tags)) |
| 05:49 | felzix | any idea why? |
| 05:50 | Chousuke | printed where? in the repl? |
| 05:51 | Chousuke | also, what is "tags" |
| 05:51 | felzix | I'm running a script containing (println (get-pos rest)) |
| 05:51 | felzix | it's a vector of strings |
| 05:53 | Chousuke | ,(println (filter (comp (partial = \+) first) ["+100" "100" "+50"])) |
| 05:53 | clojurebot | (+100 +50) |
| 05:54 | Chousuke | that would look a lot better in haskell :/ |
| 05:54 | felzix | lol |
| 05:55 | felzix | oh. actually, it doesn't print anything after that call, even constant strings |
| 05:55 | felzix | so something else is amiss ;_; |
| 05:56 | Chousuke | weird. |
| 05:56 | Chousuke | maybe *out* is bound to something weird? |
| 05:56 | felzix | nah, printing works immediately before that call |
| 05:56 | Chousuke | huh |
| 05:57 | felzix | I get weird problems like this in clojure a lot. I suspect I'm misusing laziness somehow. |
| 05:57 | Chousuke | try using (doall (filter ...)) |
| 05:57 | felzix | I tried that |
| 05:57 | Chousuke | though laziness really shouldn't affect this. |
| 05:57 | Chousuke | println will force the seq anyway |
| 05:59 | Chousuke | felzix: try adding (flush) after then printlns :/ |
| 05:59 | Chousuke | the* |
| 06:01 | felzix | awesome! |
| 06:02 | felzix | it works. thank you! |
| 06:03 | felzix | so now at least I know the real problem is elsewhere |
| 06: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? |
| 06:43 | yuras | Im sorry for my bad English. |
| 06:52 | yuras | looks like i can utilize slurp* from duck-streams |
| 07: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 |
| 07:07 | Fossi | from what i have thought it should be slower because the list is traversed twice instead of only once during the render |
| 07:07 | Fossi | somebody got a clue why that could be? |
| 07:11 | spuz | Hello, why is pos? called pos? What is that an abbreviation of? |
| 07:12 | spuz | Also, why is (seq col) preferred over (not (empty? x))? |
| 07:15 | liebke | spuz: pos? is an abbreviation for positive? |
| 07:15 | spuz | ah ok :) |
| 07:30 | Chousuke | spuz: for the latter... seq is shorter :) |
| 07:31 | spuz | Chousuke: but not so readable :p |
| 07:31 | Chousuke | spuz: it's only not readable if you know nothing about clojure :) |
| 07:31 | spuz | or you don't know about seq |
| 07:32 | Chousuke | well, everyone should :P |
| 07:32 | Chousuke | anyway, that usage of seq is idiomatic, so all clojure programmers are expected to understand it :) |
| 07:32 | spuz | Yeah, it's fair enough if it's a commonly used idiom |
| 07:33 | Chousuke | kind of like if (!someptr) ... in C |
| 07:34 | spuz | well that's C... :) |
| 07:34 | Chousuke | the idiom is still good |
| 07: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 |
| 07:38 | spuz | I guess it comes down to what different people understand when looking at a piece of code |
| 07:39 | spuz | for some people, the less code, the easier it is to understand. For someone with no background knowledge it's the complete opposite |
| 07: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". |
| 07:40 | spuz | (I'm going to have to look up if-let in order to understand that) |
| 07:43 | spuz | cgrand: I don't understand why you would want to do something like that. |
| 07:43 | spuz | what are you trying to do? |
| 07: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 |
| 07:44 | cgrand | and if-let allow you to destructure the collection when it isn't empty |
| 07:45 | gerry_ | hello |
| 07:46 | gerry_ | i'm doing clojure socket read/writer test, don't konw why it not work |
| 07:46 | gerry_ | i have attached reader and writer to one remote socket |
| 07:47 | spuz | cgrand I see, so that destructuring is an alternative to empty? first and rest ? |
| 07:47 | gerry_ | first try readLine from socket it worked, but when i write to it, it always return nil to me |
| 07:48 | gerry_ | (def socket (Socket. "igs.joyjoy.net" 6969)) |
| 07: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))) |
| 07:49 | cgrand | or, using destructuring, (if (empty? coll) (do something) (let [[x & xs] coll] do domething else))) |
| 07:49 | gerry_ | (def ins (reader (.getInputStream socket)) (def ous (writer (.getOutputStream socket)) |
| 07:50 | gerry_ | that's it |
| 07:50 | gerry_ | (.readLine ins) work (.println ous "oops") not work |
| 07:50 | spuz | cgrand: that's nice :) |
| 07:50 | gerry_ | i have tested it with telnet, it worked on both read and write |
| 07:51 | gerry_ | what's wrong? |
| 07:51 | gerry_ | telnet igs.joyjoy.net 6969 works |
| 07: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". |
| 07:52 | shmichael | Hi everyone. Is there any way to determine in code if a given symbol is a macro? |
| 07:53 | gerry_ | i can get one login: prompt from ins readLine |
| 07:53 | cgrand | (meta #'if-let) |
| 07:53 | cgrand | ,(meta #'if-let) |
| 07: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"} |
| 07:53 | cgrand | shmichael: see :macro true in the meta |
| 07:53 | shmichael | cgrand: awesome, thank you |
| 07:54 | cgrand | ,(-> #'when meta :macro) |
| 07:54 | clojurebot | true |
| 07:54 | cgrand | ,(-> #'map meta :macro) |
| 07:54 | clojurebot | nil |
| 07:54 | shmichael | cgrand: yes, that is exactly what I need |
| 07:54 | gerry_ | hmm |
| 08:01 | gerry_ | does telnet directly output string to socket? |
| 08:23 | shmichael | ,(-> #'when let :macro) |
| 08:23 | clojurebot | java.lang.IllegalArgumentException: let requires a vector for its binding |
| 08:24 | gerry_ | when-let? |
| 08:26 | shmichael | I am trying to test if symbols are macros |
| 08:26 | shmichael | But this test fails for let |
| 08:29 | avital- | ,(meta let) |
| 08:29 | clojurebot | java.lang.Exception: Can't take value of a macro: #'clojure.core/let |
| 08:30 | gerry_ | ,(meta (var let)) |
| 08: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."} |
| 08:31 | chouser | ,(-> #'let meta :macro) |
| 08:31 | clojurebot | true |
| 08:31 | chouser | looks right |
| 08:31 | gerry_ | ,(-> #'let meta) |
| 08: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."} |
| 08:33 | avital- | ,(-> {:a {:b 3}} :a :b) |
| 08:33 | clojurebot | 3 |
| 08:33 | avital- | nice |
| 08:34 | gerry_ | ,(def socket (Socket. "igs.joyjoy.net" 6969)) |
| 08:34 | clojurebot | DENIED |
| 08:34 | shmichael | gerry_: thanks |
| 08:35 | shmichael | ,(-> let meta :macro) |
| 08:35 | clojurebot | java.lang.Exception: Can't take value of a macro: #'clojure.core/let |
| 08:35 | shmichael | ,(-> (var let) meta :macro) |
| 08:35 | clojurebot | true |
| 08:36 | gerry_ | #'let = (var let) |
| 08:36 | AWizzArd | chouser: I find you also are one :) |
| 08:38 | chouser | AWizzArd: but you're *named* like one. I can't compete with that. |
| 08:41 | AWizzArd | True. Although I have a double z (while I am aware there should be only one). |
| 08:44 | yuras | how to convert "1234" -> 1234? |
| 08:44 | AWizzArd | ,(Integer/parseInt "1234") |
| 08:44 | clojurebot | 1234 |
| 08:44 | yuras | only java way, no built-in fun? |
| 08:45 | notallama | well, you could also use the reader. |
| 08:45 | yuras | ah ok |
| 08:45 | AWizzArd | yuras: this is not the Java way, it is the JVM way. |
| 08:45 | rhickey | ,(read-string "1234") |
| 08:45 | clojurebot | 1234 |
| 08:46 | rhickey | but |
| 08:46 | AWizzArd | This would also work for very big numbers. But it does not document the code so well. |
| 08:47 | rhickey | ,(read-string "foo1234") |
| 08:47 | clojurebot | foo1234 |
| 08:47 | rhickey | ,(Integer/parseInt "foo1234") |
| 08:47 | clojurebot | java.lang.NumberFormatException: For input string: "foo1234" |
| 08:47 | yuras | no questions. thanks |
| 08:47 | AWizzArd | ,(BigInteger. "999999999999999999999999999999999999999999999") ; also works for possibly huge numbers |
| 08:47 | clojurebot | 999999999999999999999999999999999999999999999 |
| 08:48 | AWizzArd | and this is 5x faster than read-string |
| 08:49 | yuras | ,(BigInteger. "foo123") |
| 08:49 | clojurebot | java.lang.NumberFormatException: For input string: "foo123" |
| 08:50 | eevar2 | ,(read-string "99999999999999999999999999999999999999999999999999999") |
| 08:50 | clojurebot | 99999999999999999999999999999999999999999999999999999 |
| 08:50 | rhickey | ,(bigint "1234123732198712398732178123987") |
| 08:50 | clojurebot | 1234123732198712398732178123987 |
| 08:50 | AWizzArd | ,(BigInteger. "abc123" 16) |
| 08:50 | clojurebot | 11256099 |
| 08:51 | AWizzArd | ,(BigInteger. "lfvegohplhcowhgpvlw0923857pn3w9207p" 36) |
| 08:51 | clojurebot | 1760061993066943724720314159425702321837801663530174101 |
| 08:51 | AWizzArd | :) |
| 08:52 | arsatiki | you just never know when you're gonna need something in base 19 :) |
| 08:54 | gerry_ | bigint not recognize other than 10base,right? |
| 08:55 | AWizzArd | ,30rRIGHT |
| 08:55 | clojurebot | 22370939 |
| 08:56 | djork | wow nice |
| 08:58 | gerry_ | what's 30rRIGHT? |
| 08:58 | notallama | base 30 |
| 08:58 | arsatiki | the number RIGHT in base 30 |
| 08:58 | gerry_ | oh |
| 09:00 | gerry_ | ,16rabcd |
| 09:00 | clojurebot | 43981 |
| 09:04 | gerry_ | ,(-> 1 (+) (-) (*) (/)) |
| 09:04 | clojurebot | -1 |
| 09:05 | gerry_ | ,(into {} [:a 1 :b 2]) |
| 09:05 | clojurebot | java.lang.IllegalArgumentException: Don't know how to create ISeq from: Keyword |
| 09:06 | AWizzArd | ,(into {} [[:a 1], [:b 2]]) |
| 09:06 | clojurebot | {:a 1, :b 2} |
| 09:07 | notallama | ,(apply hash-map [:a 1 :b 2]) |
| 09:07 | clojurebot | {:a 1, :b 2} |
| 09:07 | gerry_ | nice |
| 09:08 | gerry_ | i donot figure out "into" |
| 09:09 | gerry_ | (into {} '(:a 1 :b 2)) |
| 09:09 | chouser | (into a b) is essentially (reduce conj a b) |
| 09:10 | gerry_ | ,(conj {} '(:a 1)) |
| 09:10 | clojurebot | java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.util.Map$Entry |
| 09:10 | notallama | ,(seq {:a 1, :b 2}) |
| 09:10 | clojurebot | ([:a 1] [:b 2]) |
| 09:10 | notallama | map elements are pairs. that's your trouble. |
| 09:11 | gerry_ | ok |
| 09:12 | gerry_ | ,(conj {} [:a 1]) |
| 09:12 | clojurebot | {:a 1} |
| 09:13 | gerry_ | thx |
| 09: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 |
| 09:17 | rhickey | 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 |
| 09:17 | chouser | picking too high a letter has worse consequences than picking too low a letter |
| 09:19 | gerry_ | chouser: you mean a? |
| 09:19 | rhickey | yes, although these would just be defaults, could opt out or for something else |
| 09:19 | rhickey | I wonder how often field extensibility will be used, and in what ways |
| 09:20 | rhickey | I've decided you'll always get metadata support |
| 09: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. |
| 09:20 | gerry_ | oic |
| 09: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. |
| 09:21 | rhickey | even with a), there's still a question of throw on get of non-field |
| 09: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. |
| 09:24 | rhickey | aargh, is a mismatch with vector: |
| 09:24 | chouser | once fields can be added on the fly the throw on a bad get seems like it might get annoying. |
| 09:24 | rhickey | ,(get [0] 1) |
| 09:24 | clojurebot | nil |
| 09:24 | rhickey | ,([0] 1) |
| 09:24 | clojurebot | java.lang.IndexOutOfBoundsException |
| 09:24 | rhickey | chouser: really, you think the dynamic fields make a difference? |
| 09:25 | rhickey | in my view, these structures are not like collections, so it's semantically less 'lookup' than 'access' |
| 09:26 | gerry_ | i vote for expando support |
| 09: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. |
| 09:27 | chouser | 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 |
| 09:29 | gerry_ | i think if expend field, the type of object should change also,old object should be discard |
| 09:29 | rhickey | people have asked for a throwing getx already, could just be a general function |
| 09:30 | rhickey | gerry_: that's a whole different thing - you could just pour it into a map then |
| 09:30 | rhickey | expando is about retaining the type |
| 09:31 | rhickey | but you can't dissoc a base field and retain the type |
| 09:32 | rhickey | if get threw then you could use (get x k not-found) for speculative reads |
| 09: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. |
| 09:33 | chouser | (x k nil) |
| 09:33 | gerry_ | then i agree with chouser :) |
| 09:33 | chouser | (:k x nil) ... either way isn't too bad I suppose. |
| 09:33 | rhickey | chouser: defclass is a fixed type, deftype is an anonymous type, but with a stable type tag |
| 09:34 | rhickey | I think if the not-found version doesn't throw, then you are set |
| 09:35 | rhickey | since you'll have to know what you want if it's not there anyway |
| 09:35 | rhickey | if we go with b), need an api for add-field/key |
| 09:36 | chouser | yeah, I could live with (x k nil). seems like a idiom change, but not a onerous one. |
| 09:37 | rhickey | I think the vast majority of code manipulating these things will be using known fields |
| 09:37 | chouser | what's the benefit of (b) over (c)? |
| 09:37 | rhickey | same - protection against accident. people that don't want expando, but are getting it by default, really don't want accidental expansion |
| 09:38 | cemerick | where might I look at the menu? |
| 09: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 |
| 09:39 | rhickey | menu^^ |
| 09: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? |
| 09:40 | rhickey | also - should (get x k) throw if k not present on a defclass/deftype thingy (new word for thingy desired) |
| 09:40 | chouser | "should (get x k) throw if k not present on a clabango" |
| 09:41 | cemerick | probably not IMO, although that makes nil values tricky |
| 09:41 | rhickey | chouser: if (get x not-present-k) throws then b) seems symmetrical |
| 09:41 | cemerick | and I'd prefer C, FWIW |
| 09:41 | chouser | to be clear, if (get x bad-k) throws for one of these instances, would it also throw for regular maps? |
| 09:41 | gerry_ | C |
| 09:42 | rhickey | the whole point of these things is to replace classes/structs/ADTs etc |
| 09:43 | rhickey | chouser: the existing apis are collection oriented, not structure oriented, this is coming from the other end - small fixed things |
| 09:43 | rhickey | dynamic typing still means typing, i.e. some runtime check for correct use |
| 09:44 | rhickey | its correct to add and lookup arbitrary things in a collection, not so for enumerated structs |
| 09:44 | chouser | that sounds like (a) |
| 09:45 | rhickey | (deftype Foo [a b c]) (let [f (Foo 1 2 3)] (:d f)) is just a plain mistake |
| 09:45 | cemerick | I strongly disagree. Without C, miscellaneous or orthogonal data will drift into meta, which is often not desirable semantically. |
| 09:45 | cemerick | or structs will grow a near-universal "properties" slot. |
| 09:45 | chouser | for (b) we'd need a new assoc, so a new conj would also be desirable and therefore a new into |
| 09:46 | rhickey | cemerick: that doesn't demand c), b) would work ass well |
| 09:46 | rhickey | as well |
| 09:46 | cemerick | rhickey: does B buy anything w.r.t. perf, or is it just a "protective" policy |
| 09:46 | cemerick | ? |
| 09: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 |
| 09:48 | rhickey | 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 |
| 09:48 | rhickey | cemerick: dunno |
| 09:49 | rhickey | i.e. assoc on vectors only works for existing 'keys' |
| 09:49 | rhickey | user=> (assoc [0] 0 1) |
| 09:49 | rhickey | [1] |
| 09:49 | rhickey | user=> (assoc [0] 4 1) |
| 09:49 | rhickey | java.lang.IndexOutOfBoundsException (NO_SOURCE_FILE:0) |
| 09: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. |
| 09:50 | rhickey | chouser: conj could be the way to expand |
| 09: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. |
| 09:51 | rhickey | cemerick: the benefit is that these things work like classes, not collections, since that will be their overwhelmingly primary useage |
| 09:51 | chouser | heh. cemerick and I are on the same side unless B gets rules out. |
| 09:52 | chouser | so (conj o [:new-key x]) might work but (assoc o :new-key x) might throw? |
| 09:52 | rhickey | I think you have to ask - why use these things rather than, say, just maps? |
| 09:53 | rhickey | chouser: yes, same as vectors |
| 09:53 | chouser | hmph. |
| 09: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. |
| 09:54 | cemerick | and, having better-than-map perf for those standard slots is a huge benefit |
| 09: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' |
| 09:55 | rhickey | now you are going to move that code and not even get runtime enforcement of same |
| 09:57 | chouser | allowing (conj o [:new-key x]) hardly seems like enforcement |
| 09: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 |
| 09:58 | rhickey | set-existing is super important for straight data structures |
| 09: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 | cemerick | 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 | rhickey | cemerick: the typo becomes an undetectable error, these are dynamic 'types' not bags of stuff |
| 10:04 | rhickey | we already have bags of stuff |
| 10:04 | rhickey | and they are great |
| 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 | rhickey | cemerick: I'm not sure b) isn't 3 |
| 10:06 | rhickey | these semantics are already in place (i.e. assoc might fail on invalid index, conj adds) |
| 10:07 | rhickey | 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 | rhickey | 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 | cemerick | 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 | chouser | 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 | rhickey | 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 | rhickey | ? |
| 10:24 | cemerick | well, python only has None |
| 10:25 | cemerick | I'm pretty sure js returns its nil |
| 10:25 | cemerick | 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 | cemerick | 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 | chouser | cemerick: undefined == null :-( |
| 10:31 | chouser | 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 | djork | undefined just happens to be undefined most of the time |
| 10:32 | chouser | cemerick: Object()["foo" ] === null returns false |
| 10:32 | chouser | 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 | djork | 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 | djork | I like my languages to inspire confidence. |
| 10:37 | djork | JavaScript is fine, but man does it make me paranoid. |
| 10:38 | djork | 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 | djork | 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 | djork | 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 | rhickey | >>> x.foo |
| 10:43 | rhickey | Traceback (most recent call last): |
| 10:43 | rhickey | File "<stdin>", line 1, in <module> |
| 10:43 | rhickey | 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 | chouser | >>> Foo().x = 5 # no error |
| 10:47 | chouser | >>> foo=Foo(); foo.x = 5; foo.x # returns 5 |
| 10:47 | rhickey | >>> class Foo(object): pass |
| 10:47 | rhickey | ... |
| 10:47 | rhickey | >>> Foo().x |
| 10:47 | rhickey | Traceback (most recent call last): |
| 10:47 | rhickey | File "<stdin>", line 1, in <module> |
| 10:47 | rhickey | 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 | chouser | >>> Foo().x = 5 # AttributeError: 'Foo' object has no attribute 'x' |
| 10:50 | chouser | 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 | rhickey | 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 | 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 | chouser | - converted to _ ? |
| 10:57 | rhickey | chouser: I'm not doing any munging right now, but should be subject to standard munging |
| 10:58 | rhickey | ,(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 | rhickey | 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 | rhickey | 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 | kanak | *one of the threads changes the value of a var |
| 11:07 | rhickey | cemerick: really - where would the extension map live? |
| 11:07 | rhickey | 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 | rhickey | so creating similar things will be easy |
| 11:09 | rhickey | but I'd like to get two good defaults in place |
| 11:10 | rhickey | 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 | rhickey | so writing |
| 11:14 | rhickey | 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 | rhickey | fogus31415926535: ::x is a namespace-qualified keyword |
| 11:21 | rhickey | ,::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 | maacl | 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 | chouser | nope, scratch that -- that scheme version uses the stack too |
| 11:44 | chouser | (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 | falkor | 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 | AWizzArd | ,(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 | duncanm | i can't type today |
| 11:54 | AWizzArd | Tho I would like to be a macro from time to time. |
| 11:54 | AWizzArd | 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 | yuras | 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 | AWizzArd | 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 | stuartsierra | 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 | chouser | 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 | drewr | I'm trying to figure out why this fails for large files |
| 12:49 | drewr | it doesn't fail technically, but it doesn't successfully gzip |
| 13:00 | hiredman | hah! |
| 13:01 | hiredman | 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 | drewr | so I'm not using that buffer correctly |
| 13:07 | Chousuke | hiredman: I still get that completely weird error :/ |
| 13:09 | Chousuke | I think it might have something to do with my syntax-quote macro |
| 13:09 | Chousuke | but, hm |
| 13:11 | Chousuke | 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 | Chousuke | ~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 | ambient | 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 | Anniepoo | 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 | drewr | 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 | hiredman | 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 | hiredman | Chousuke: hey, I put some comas at the end of the function bodies, that's whitespace! |
| 13:23 | hiredman | 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 | hiredman | yuras: no, the server would be a multimethod, basically |
| 13:25 | hiredman | the multimethod's dispatch function would get whatever input and decide which method in the multimethod to dispatch to |
| 13:25 | hiredman | :/ |
| 13:25 | Anniepoo | If I shadow a binding in a let, how securely is the old value 'not available'? |
| 13:25 | Anniepoo | 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 | hiredman | 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 | qed | (a 1) |
| 13:27 | hiredman | sure |
| 13:27 | qed | how do you do that? |
| 13:27 | hiredman | a function is a object |
| 13:27 | hiredman | 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 | qed | (defn a [x] (do something to x)) |
| 13:29 | qed | {a 1} |
| 13:29 | qed | 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 | qed | 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 | qed | the above code pretty much sums it up: (defn a [x] (do something to the value that a is the key for)) |
| 13:30 | qed | {a 1} |
| 13:31 | hiredman | qed: no |
| 13:31 | qed | okay, thanks |
| 13:31 | Anniepoo | ok, back to me. |
| 13:31 | Anniepoo | 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 | qed | 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 | hiredman | 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 | qed | 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 | qed | 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 | djork | 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 | hiredman | 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 | clojurebot | Clojure - atoms |
| 13:43 | clojurebot | http://clojure.org/atoms |
| 13:44 | qed | like (defn a [future-mapping] #(+ % 1)) |
| 13:44 | qed | {a 1} => 2 |
| 13:44 | qed | where % is the future-mapping |
| 13:44 | qed | 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 | Kjellski | 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 | chouser | 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 | Kjellski | chouser : Okay. That´s a good start. |
| 13:55 | chouser | hm, I forgot multimethods and the REPL. :-) |
| 13:55 | chouser | 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 | qed | without any other business |
| 13:57 | chouser | a literal {} will not call a function. |
| 13:58 | chouser | ({} :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 | qed | 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 | chouser | (defn a) doesn't create a symbol |
| 14:02 | chouser | (defn a [x y] (+ x y)) creates a fn and stores it in a Var named by the symbol a |
| 14:03 | chouser | if you then eval {a 1}, that's the same as eval'ing {(fn [x y] (+ x y)) 1} |
| 14:03 | chouser | that is, you get a hash-map with a single key (a function) and a single value (1) |
| 14:03 | chouser | 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 | hiredman | 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 | tomoj | the function doesn't know where you've put it, if that's what you mean |
| 14:10 | tomoj | 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 | tomoj | that would destroy everything that is good about clojure |
| 14:11 | tomoj | 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 | tomoj | values don't know where you've put them |
| 14:12 | tomoj | rstehwien: thanks |
| 14:13 | tomoj | 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 | chouser | kanak: so that's not too bad O(log n) for add and remove. |
| 14:16 | chouser | 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 | qed | 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 | chouser | 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 | chouser | 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 | chouser | 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 | kanak | 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 | chouser | 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 | chouser | where? |
| 14:47 | rhickey | clojure.contrib.types |
| 14:47 | chouser | types |
| 14:48 | chouser | huh, I've never looked at that one. I guess I knew vaguely it was there. |
| 14:48 | chouser | "Algebraic types" anyway. |
| 14:50 | chouser | 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 | rhickey | by me |
| 14:56 | rhickey | 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 | chouser | http://tinyurl.com/ylx4j3k/finger_tree.clj#LID83 |
| 15:02 | chouser | 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 | bradford | (defn read-command-output [in buffer-size time-out poll-interval] |
| 15:17 | bradford | (let [buffer (make-array Byte/TYPE buffer-size) |
| 15:17 | bradford | bos (java.io.ByteArrayOutputStream.) |
| 15:17 | bradford | exit-status 0 |
| 15:17 | bradford | end-time (+ (System/currentTimeMillis) time-out)] |
| 15:17 | bradford | (while (< (System/currentTimeMillis) end-time) |
| 15:17 | bradford | (while (> (.available in) 0) |
| 15:17 | bradford | (let [next-block (.read in buffer 0 buffer-size)] |
| 15:17 | bradford | (if (< count 0) break |
| 15:17 | bradford | (do |
| 15:17 | bradford | (.write bos buffer 0 count) |
| 15:17 | bradford | (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 | bradford | break)) |
| 15:18 | technomancy | ~lisppaste |
| 15:18 | clojurebot | I don't understand. |
| 15:18 | bradford | (Thread/sleep poll-interval)))))) |
| 15:18 | bradford | (.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 | G0SUB | 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 | bradford | 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 | bradford | 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 | AWizzArd | 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 | AWizzArd | while with defclass one can even implement things like Clojures maps and vectors. |
| 15:50 | AWizzArd | 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 | rhickey | defclass |
| 15:53 | rhickey | (.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 | rhickey | 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 | rhickey | 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 | duncanm | (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 | AWizzArd | 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 | rhickey | 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 | hiredman | 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 | chouser | 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 | hiredman | and the java task to call Compile should fork |
| 16:17 | hiredman | 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 | arohner | 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 | chouser | 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 | arohner | 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 | hiredman | so it builds clojure once with LispReader, uses clojure to build my reader, then deletes clojure and rebuilds it using my reader |
| 16:35 | hiredman | 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 | hiredman | 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 | djork | yes |
| 17:10 | Kjellski | noone? |
| 17:11 | hiredman | so far I have yet to embed code in of my latex documents |
| 17:11 | hiredman | 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 | hiredman | 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 | Licenser | 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 | Licenser | (loop [f1 f2] ... (recur f2 f1)) |
| 17:25 | tomoj | ok, that's better than toggling |
| 17:25 | tomoj | but I meant without loop, really |
| 17:25 | tomoj | 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 | hiredman | huh |
| 17:26 | arohner | tomoj: (source iterate) |
| 17:26 | arohner | make your version of iterate take two functions |
| 17:27 | arohner | swap f1 and f2 in the recursive call |
| 17:27 | tomoj | arohner: yeah, that's a good way too |
| 17:27 | tomoj | 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 | arohner | 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 | Licenser | 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 | arohner | then reduce it |
| 17:29 | arohner | 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 | djork | a hex string that is |
| 17:34 | tomoj | well |
| 17:34 | tomoj | 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 | tomoj | hiredman: yes but it's signed |
| 17:37 | hiredman | well |
| 17:37 | hiredman | 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 | tomoj | 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 | djork | 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 | djork | 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 | AWizzArd | (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 | djork | ,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 | AWizzArd | ,#(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 | djork | (Integer/toHexString 0) |
| 17:47 | djork | ,(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 | djork | working fine |
| 17:50 | djork | just need to pad my zeroes |
| 17:52 | AWizzArd | format |
| 17:53 | AWizzArd | btw, I think format can also do toHexString for you |
| 17:54 | djork | http://gist.github.com/220900 |
| 17:55 | djork | format would be better I think |
| 17:56 | AWizzArd | djork: yes, good example code, this is how it works |
| 17:56 | AWizzArd | only thing that I personally would change is "SHA-1" ==> "SHA-512" :-) |
| 17:58 | AWizzArd | so, how can one give fill chars to format? |
| 17:58 | AWizzArd | ,(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 | djork | http://gist.github.com/220900 |
| 18:00 | djork | ,(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 | wooby | 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 | wooby | thank you |
| 18:04 | AWizzArd | no, those are chars |
| 18:04 | AWizzArd | 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 | hiredman | ,(-> 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 | wooby | ->>? |
| 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 | wooby | i see |
| 18:17 | wooby | so (map read-string (map str (str 123))) is equivalent |
| 18:17 | wooby | ,(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 | div- | besides "being possible" |
| 18:20 | div- | 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 | arohner | 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 | arohner | foo().bar().baz() |
| 18:24 | arohner | 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 | tomoj | 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 | hiredman | ,(->> ["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 | hiredman | 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 | div- | 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 | hiredman | ,(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 | hiredman | 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 | somnium | 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 | tomoj | 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 | somnium | 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 | tomoj | I guess if you want to go through the trouble to write a parser it would be pretty cool |
| 18:58 | tomoj | macros are awesome because you don't :) |
| 18:58 | tomoj | (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 | somnium | 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 | tomoj | 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 | hiredman | 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 | tomoj | (but just ignores it?) |
| 19:04 | hiredman | sure |
| 19:04 | hiredman | 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 | hiredman | 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 | somnium | 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 | somnium | who doesn't know what its doing |
| 19:08 | tomoj | and very hard to indent properly, I'd think |
| 19:09 | tomoj | 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 | somnium | true, a heredoc would solve that though |
| 19:10 | tomoj | yeah |
| 19:10 | tomoj | how often are you wanting to parse literal yaml in your source files? |
| 19:10 | tomoj | seems a very strange thing to do |
| 19:11 | hiredman | word |
| 19:11 | hiredman | 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 | hiredman | 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 | somnium | ... |
| 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 | Chousuke | which is a good things |
| 19:17 | Chousuke | -s |
| 19:17 | hiredman | alot of that could be collapsed into conds I guess |
| 19:18 | hiredman | 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 | Chousuke | 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 | hiredman | 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 | tomoj | 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 | somnium | 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 | tomoj | 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 | tomoj | 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 | scottj | emacs = slime in this case |
| 19:36 | scottj | and newlines = newlines in strings in values of my map |
| 19:38 | tomoj | scottj: windows? |
| 19:39 | tomoj | ^M is what the carriage return looks like, right? |
| 19:41 | scottj | tomoj: yeah windows |
| 19:42 | scottj | 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 | technomancy | chouser: what would you think of a patch to add this? |
| 20:05 | rlb | technomancy: looks like it to me |
| 20:05 | rlb | (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 | miltonsilva | http://paste.lisp.org/display/89475 |
| 20:31 | savanni | Quick question... |
| 20:32 | savanni | 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: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 | rhickey_ | well, they could all be changed to either qualify use or refer-clojure with exclude |
| 20:49 | rhickey_ | deftype seems like too good a name to give up |
| 20:49 | rhickey_ | 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 | rhickey_ | 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 | cemerick | 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 | rhickey_ | 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 | cemerick | :-) |
| 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 | rhickey_ | we'll see if Konrad et al get riled up or not :) |
| 21:03 | rhickey_ | 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 | rhickey_ | throwing |
| 21:05 | cemerick | yuck |
| 21:05 | cemerick | throwing assoc on what, structs? |
| 21:05 | rhickey_ | yeah |
| 21:06 | rhickey_ | 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 | rhickey_ | very many maps are never expanded |
| 21:06 | cemerick | eh. That's what testing is for. |
| 21:07 | cemerick | 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 | rhickey_ | 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 | rhickey_ | chouser: no, real immutability like all the other stuff |
| 21:10 | chouser | oh oh, right. sorry. |
| 21:11 | chouser | 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 | rhickey_ | #:org.clojure/Foo{:a 1 :b 2} |
| 21:14 | rhickey_ | 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 | rhickey_ | 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 | rhickey_ | subsequent to construction, you have labeled access |
| 21:26 | st3fan | is there a string->number ? |
| 21:26 | st3fan | 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 | tomoj | 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 | st3fan | so i doubt there will be 'lisp injection' errors :-) |
| 21:29 | chouser | probably good enough. |
| 21:30 | chouser | ,(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 | st3fan | 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: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 | st3fan | 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 | hiredman | (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 | hiredman | 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 | hiredman | 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 | st3fan | 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 | somnium | have you used clojure-project or swank-clojure-project in slime? |
| 22:05 | somnium | 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 | somnium | 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 | ambient | automatically adding project root, from whence the source file is ran from, to the classpath would be nice |
| 22:12 | ambient | 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 | somnium | 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 | st3fan | 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: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 | cemerick | 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 | djork | and you want to share it |
| 23:00 | djork | 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 | djork | so you set your salt on a server, for instance |
| 23:05 | djork | and you can store large data structures in other places |
| 23:06 | djork | 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 | wooby | 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 | tomoj | 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 | djork | 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 | tomoj | in this case that doesn't matter |
| 23:11 | djork | it's better to change up the salt |
| 23:12 | djork | but it isn't super critical |
| 23:12 | djork | in a password situation you want a different salt because it means a rainbow table is ineffective against any other password |
| 23:13 | djork | 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 | tomoj | 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 |