#clojure log - Dec 03 2009

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

0:13 qed: Is there anything out there to simplify using Swing? using clojure, of course

0:13 git://github.com/ztellman/penumbra.git

0:13 thats cool either way

0:14 cgordon: I'm trying to call this bit of Java: IndexWriter.MaxFieldLength.UNLIMITED, but I can't figure out how to do it. I've tried "(.. IndexWriter MaxFieldLength UNLIMITED)" and (. IndexWriter.MaxFieldLength UNLIMITED)". What am I missing?

0:14 qed: cgordon: what's the exception?

0:15 cgordon: well, in the second case, I get: error: java.lang.ClassNotFoundException: IndexWriter.MaxFieldLength (Gutenberg.clj:13)

0:15 in the first I get: error: java.lang.NoSuchFieldException: MaxFieldLength

0:15 arbscht_: IndexWriter$MaxFieldLength refers to the nested class

0:15 qed: I'm not too good with the Java interop yet, but IndexWriter and MaxFieldLength should be separate I think

0:16 cgordon: arbscht_: that did it, thanks!

0:16 arbscht_: np

0:16 qed: ah-ha, i havent seen anything like that yet cgordon

0:17 cgordon: ah, my bad, it's in the docs: If the first operand is a symbol that resolves to a class name, the access is considered to be to a static member of the named class. Note that nested classes are named EnclosingClass$NestedClass, per the JVM spec. Otherwise it is presumed to be an instance member and the first argument is evaluated to produce the target object.

0:17 I just missed it

0:17 qed: http://github.com/travis/lein-cuke

0:17 arbscht_: :)

0:24 technomancy: danlarkin: lol @ "we aren't that serious"

0:25 "honestly! the other day someone told a joke in stand-up, and everyone was cool with it."

0:25 danlarkin: srsly

0:28 defn: http://github.com/travis/lein-cuke

0:28 ^@technomancy

0:42 JAS415: anyone ever use Runtime.exec to compile LFE code from within clojure?

0:42 it almost works but seems to block for some reason

0:46 chouser: Lisp Flavored Erlang?

0:46 JAS415: yup

0:47 I've got the command line command working from my shell, but it doesn't seem to do anything from the lisp interpreter

0:47 and i'm just printing the command to the interpreter and copying it to the shell at the moment

0:48 technomancy: defn: interesting

0:49 I'm not one for english-like programming, but different strokes for different folks I guess.

0:54 _ato: I don't get it, what's the point? Oh is the idea so that people who can't code can read the tests?

0:55 technomancy: I think so. for customer-centric acceptance-testing.

0:55 I don't really have much interaction with customers.

0:55 JAS415: yeah that's what i thought, 'looks like tech support'

1:00 defn: technomancy: I've never used cucumber to be honest

1:00 but I thought it was neat he was using leiningen

1:00 cp2: man, i feel like a born-again christian

1:00 clojure is so awesome

1:00 after doing a bunch of stuff in c++.. damn i forgot how nice it is

1:00 replaca: technomancy: did you want someone to apply the patch for contrib issue 29?

1:02 technomancy: replaca: I'm not using 1.0 anymore, so I don't have any personal attachment to that issue

1:03 but it'd be nice just for the sake of having fewer perfectly good tickets sitting around waiting to be applied.

1:03 replaca: ok, I'll slam it in

1:04 technomancy: speaking of which, it's quite a shame that stuartsierra can no longer fix bugs in his own library now that test-is has been promoted. =(

1:04 replaca: I'm in the midst of writing a new ticket that I'll actually have to think about, so it'd be nice to make an easy one go away :-)

1:04 yeah, interesting

1:05 I think our dev process is still shaking down

1:05 which is ok

1:10 technomancy: replaca: I'm about to push out leiningen 1.0 (probably tomorrow) and then start to sit down and think through the doc plugin

1:10 looking forward to how that shakes out

1:15 replaca: technomancy: cool. I'm beginning to think about that too

1:16 technomancy: so ping me when you're starting to think and we can compare notes

1:16 technomancy: aye

1:17 replaca: there's a *lot* of hair on fire in the current version of autodoc

1:38 defn: if you guys were to design an extended documentation site for clojure, how would you lay it out?

1:38 id like to start working on examples for all of the existing docs

1:38 similar to how the ruby API core docs work

1:39 cgordon: how does Ruby lay out it's documentation?

1:39 defn: i think it should be a community effort, a wiki maybe?

1:39 cgordon: I'm only really familiar with the way Perl and Java do documentation

1:40 Seems like you'd want most of the documentation to come from the source files, which tends to leave out wikis (except as manuals and examples)

1:40 The "doc string" seems to actively discourage that though

1:40 defn: array.assoc(obj) → an_array or nil; Searches through an array whose elements are also arrays comparing obj with the http://ruby-doc.org/core/classes/Array.html#M002164 element of http://ruby-doc.org/core/classes/Array.html#M002173 contained array using obj.==. Returns the http://ruby-doc.org/core/classes/Array.html#M002164 contained array that matches (that is, the http://ruby-doc.org/core/classes/Array.html#M002164 associated array), or nil if no match is fou

1:40 also http://ruby-doc.org/core/classes/Array.html#M002208.; s1 = [ "colors", "red", "blue", "green" ]...example follows...

1:41 did you get all of that?

1:41 cgordon: yes

1:41 is there any sort of standard markup (or markdown) used in doc strings for Clojure?

1:41 defn: i dont believe so

1:42 id like to work on better documentation, i see a lot of things where (doc x) returns something like ([s key])

1:42 cgordon: I'm with you; I'd be happy to spend time documenting the core libraries, but I'm not sure where to do it, or how

1:42 it would, at least, be a great way to learn more about them

1:42 defn: in this case it means struct, but in other cases it means string

1:42 cgordon: yes, I haven't found the documentation to be very helpful when learning a function

1:42 although they are fine for quick reference

1:43 I keep a copy of core.clj open in Emacs at all times as "documentation" :)

1:43 defn: cgordon: i think it should just be a wiki where the "talk" page is a comments place, kind of a blog in that sense, where there can be discussion about the example, and it can be improved

1:43 timothypratley: http://en.wikibooks.org/wiki/Clojure_Programming#API_Examples <- I started this a long time ago and various others have added to it

1:43 defn: you can "watch" doc pages so you can edit them and fix them when it's appropriate

1:43 timothypratley: what I'd really like to do is put them into actual example meta-data on functions

1:43 and have them be tests that get run

1:44 and able to be looked up with (doc)

1:44 defn: timothypratley: it's a good reference, but i think it could be done better, as a single effort to create examples for the API docs

1:44 timothypratley: or (example ...)

1:44 Yup totally agree

1:44 that's what I'm saying :)

1:44 defn: hehe :)

1:44 timothypratley: It needs to be done as code

1:44 that can be run, and attached to the actual functions, and part of autodoc generation

1:44 I can imagine cases where you want it in autodoc and not

1:44 defn: yeah totally, i started on the a's, and i just got to B, i dont know a lot about agents and refs and such yet, im just providing basic examples where i know how

1:45 im doing it in org-mode in emacs and then exporting to HTML

1:45 but i think it should be a wiki

1:45 nospaces: have something that addresses problems such as "java.io.FileNotFoundException: Could not locate compojure/http/servlet__init.class or compojure/http/servlet.clj on classpath: "

1:45 and things like "java.io.FileNotFoundException: Could not locate compojure/http/servlet__init.class or compojure/http/servlet.clj on classpath: "

1:46 hiredman: you should put compojure on the classpath

1:47 defn: :)

1:47 timothypratley: would you want to work on something?

1:47 timothypratley: defn: yup

1:47 defn: timothypratley: I have getclojure.org and .com -- thought those might be a good place for API docs

1:48 what i have in mind is a site which looks like a nice way to browse API docs first and foremost

1:49 and then hidden away is the way to log in

1:49 not hidden so much-- more like, not intruding on every other link on any given page

1:50 hiya twbray

1:50 i enjoyed your post

1:50 twbray: defn: Thanks. But read the comments, and you'll see that I'm a clueless fucktard :)

1:51 defn: heh

1:51 It's just the internet

1:51 it's good to have stances and opinions

1:51 otherwise everyone just clones the same ole

1:52 twbray: Oh, I'm not upset. The reactions establish that at least people are thinking. Blog as long as I have and your skin is 3 feet thick.

1:53 hiredman: it's amazing how fast comments on anything mentioning lisp deteriorates

1:54 there must be something like godwin's law that covers it

1:54 * twbray snickers

1:55 twbray: Amused at the commenters saying "If you only used an editor that s-exp balancing and hopping You'd Get It".

1:55 timothypratley: lol

1:55 * twbray has been using Emacs since (gasp!) 1986

1:56 hiredman: I was 2

1:56 _ato: that's before I was born!

1:57 cgordon: wow, now I feel old, and I didn't start using Emacs until 1990

1:57 * twbray *is* old, but only feels that way when hung over

1:59 nospaces: that classpath thing will be a barrier to the newbies who come into clojure without java - so, some notes on that would be good.

2:00 hiredman: ~google java classpath

2:00 clojurebot: First, out of 295000 results is:

2:00 Setting the class path

2:00 http://java.sun.com/j2se/1.3/docs/tooldocs/win32/classpath.html

2:03 nospaces: can't it be set automatically via ant or something?

2:04 i'm on a mac - and have to go through stuff like this - http://www.ibm.com/developerworks/java/library/j-classpath-unix/?ca=dgr-lnxw06clspth-Unix-MacX

2:04 headius: jruby allows you to add to classpath at runtime

2:05 cgordon: I've been using "swank-clojure-project" with Emacs, and that works like a charm

2:05 headius: I'm still amazed other langs have not done that

2:05 timothypratley: defn: while I think your idea of a public wiki has merit, I'm thinking to be most useful you need to enforce 4 things: 1) A function/var that the example relates to. 2) The code. 3) The result. 4) any additional comments. So the data needs to be stored in some sort of format that allows programmatic access to that [maybe I'm just complicating things]

2:05 hiredman: nospaces: seriously?

2:05 headius: in fact, JRuby allows you to simply "require 'something.jar'" and its classes will be available to you

2:05 _ato: I think we just need to figure out the right combination of classloader magic to make add-classpath work reliably

2:05 hiredman: that is your sob story?

2:05 defn: timothypratley: with org-mode that actually is working quite well

2:06 hiredman: you are calling the steps clearly laid out in that article pain?

2:06 _ato: I noticed the ant classloader has some stuff about forcing files in higher classloaders into lower-level ones

2:06 replaca: didn't someone start writing examples for functions on the clojure wikibook (that seems to have died)?

2:06 timothypratley: defn: oh, cool! how can I help?

2:06 defn: timothypratley: do you use org-mode?

2:06 emacs?

2:07 nospaces: yeah - try installing everything from scratch on a clean machine and see what things are required - great docs are written up from tabula rasa configs

2:07 defn: timothypratley: either way ping me your email, im still brainstorming, i might just build something to do what we need, there are wikis out there, just need to combine one with what we need

2:07 nospaces: that way hidden assumptions are off

2:07 timothypratley: defn: I use vim mainly but this is a good chance for me to learn :)

2:07 _ato: defn: why not just use a git repo instead of a wiki? then you can put org-mode docs or code or whatever in it?

2:07 hiredman: nospaces: what assumptions?

2:08 defn: _ato: yeah that works, i mean, there'd be a repo regardless i suppose

2:08 but im thinking more about presentation, and how people will edit it in the long term

2:09 i think a wiki inspires more activity than a repo might

2:09 nospaces: classpath settings, git, et al

2:09 defn: i think we'd have fewer authors with a repo, i guess is my main concern

2:10 hiredman: nospaces: the classpath stuff is part and parcel of the jvm, if you wish to work with it, then it behooves you to know of it and how it works

2:10 sun has docs

2:10 _ato: defn: hmm, I guess. I suppose I was assuming that most Clojure uses would be used to using git anyway

2:10 defn: yeah i suppose they could be

2:10 hiredman: if a project is hosted in git, is it unreasonable to expect people to know git to use it?

2:11 defn: you can get clojure through macports though...

2:11 tomoj: I was thinking of a web app

2:11 nospaces: hiredman - understood - just saying that there will be folks who come in contact with clojure with no java experience - and they'll do searches like http://www.google.com/search?q=Could+not+locate+compojure/server/jetty__init.class and there will be no hits

2:11 defn: hiredman, if you can remove a bit more of the pain for a n00b, you have another user

2:11 tomoj: with the functions/macros to be documented autogenerated and then people can hang (running?) examples off of them and vote the examples up/down

2:11 then top examples get shown in the main view and the power users can go in and look at the rest

2:12 hiredman: nospaces: and they will come to irc and the mailing list and we will rectify what is wrong

2:12 JAS415: i found compojure to be a pretty easy setup considering

2:12 defn: i dont know about the voting, i think most people are pretty amicable here, id probably just leave it open, whoever wants to edit can edit, there can be discussion and maybe it'll change, no worries

2:12 hiredman: compojure actually has an ant target to download all it's deps, including clojure

2:12 tomoj: yeah I hadn't thought of just using a wiki -- too simple :P

2:12 _ato: nospaces: What do you think it is that other languages do differently?

2:13 defn: tomoj: it sort of is a webapp, with a wiki behind it

2:13 hiredman: if I recall, compojure even has a run script that will launch compojure with all the deps on the classpath

2:13 defn: that is correct

2:13 tomoj: how does it know what handler to use?

2:14 hiredman: nospaces: so, was there anything else?

2:14 nospaces: _ato : rails have been handling the deprecations pretty well - you see a lot of people running around with older books - but the deprecation blogs help them get on board and still power through - but things which are setup wise - should be complete - rather leaving new folks stuck and needing to get support - if they can hello world in 15 minutes - then that's great.

2:14 not everyone runs on super fast broadband - or the latest computers

2:15 but as always, it's a darwinian process at the end of the day :D

2:16 _ato: yeah, partly it's just that Clojure and Clojure libs are very young, so the way to do things changes a lot

2:16 we're trying to solve the dependency problem with Leiningen

2:17 timothypratley: _ato: I salute you

2:17 nospaces: I guess a place that can store the error messages and become the number 1 search link would help a lot - stuff like this should get some hits somewhere - http://www.google.com/search?q=ava.lang.ClassNotFoundException:+org.mortbay.jetty.Server+(NO_SOURCE_FILE:0)

2:18 hiredman: nospaces: that is the exact same error as with compojure

2:18 nospaces: yeah, i know - noobs are going to keep banging at the same wall :)

2:18 in different ways

2:18 _ato: yeah, for searches it's just a matter of popularity and time. The only reason other languages are better there is there's more people blogging about them

2:19 nospaces: since it's claimed to be fast and powerful - then they'll just face the wall from all angles

2:19 hiredman: I don't care about your hypothetical "noob"

2:20 nospaces: that's where i think clojure with the lisp AI background may come in handy - to generate auto blogs -

2:20 today's noob - tomorrow's contributor

2:20 hiredman: have you looked at the tutorial linked from the compojure github page?

2:21 nospaces: this one? http://groups.google.com/group/compojure/browse_thread/thread/3c507da23540da6e

2:21 hiredman: or the other 3 or 4 under it

2:22 do you have any problems besides the not having setup your classpath?

2:23 nospaces: was great up to classpath :)

2:23 the other issue is that git should have a 404 error message

2:23 _ato: nospaces: http://incanter-blog.org/2009/11/20/leiningen-clojars/

2:24 nospaces: "The remote end hung up unexpectedly" is way too cryptic

2:24 but that's another story

2:24 hiredman:

2:24 _ato: wait.. that's not the one I was thinking of

2:24 http://incanter-blog.org/2009/11/29/incanter-webapp/

2:24 ^ the webapp one

2:25 nospaces: thanks _ato

2:25 _ato: and just leave out the incanter bits

2:25 ;-)

2:26 yeah.. git is pretty obscure there. It says that even if it can't resolve an IP

2:26 nospaces: i guess as the community grows, stuff like this will float up on stackoverflow

2:27 hiredman: :|

2:27 nospaces: so that would take care of all the pesky noobs :)

2:27 plus they have a nice badge incentive

2:27 hiredman: stackoverflow often seems like the blind leading the blind, it would be great if people could just read documentation

2:28 or even source code for that matter

2:28 nospaces: the tutorial has nothing on classpath though - heh.

2:29 hiredman: nospaces: clojurebot googled you up a link to sun's classpath docs

2:29 read them

2:29 I think those docs may assume windows

2:30 _ato: nospaces: in the incanter one Leiningen is handling the classpath for you

2:31 nospaces: ok - thanks guys

2:32 _ato: I guess the only difference is that rails generates a script ./script/server which sets up the load path to lib vendor/*

2:32 alexyk: technomancy: can lein use a loval maven repo, and download *there*, too, if needed?

2:32 local

2:32 _ato: alexyk: lein always uses your local maven repo in ~/.m2/repository

2:33 alexyk: good... does it download there, too?

2:33 _ato: yeah, it uses it like a download cache

2:33 alexyk: nice. is it using maven, in fact?

2:33 _ato: it first downloads there and then copies to your projects lib/ directory so other tools like swank-clojure can find the libs

2:34 it is indeed just using maven internally for depedency resolution (but sssh! don't tell anyone)

2:34 ;-)

2:34 alexyk: can it symlink instead of copying?

2:34 _ato: not at this stage. Are you worried about disk space with lots of projects?

2:35 alexyk: scala people said you can't emulate maven instead of maven, so SBT uses Ivy... and at that point I thought enough of java world build tools

2:35 _ato: I am worried about staleness. Maven proper will update all snapshots for you.

2:35 If I use clojure snapshot form maven, it updates every night.

2:35 a copy will go stale quick.

2:35 _ato: lein will update as well

2:36 if it doesn't it's a bug

2:36 alexyk: I didn't try, I'm just gauging :)

2:36 I'm ok with clojure-maven so far... in fact so far I'm ok with cut'n'paste, but we'll see.

2:37 I just got clojuratica working on my mac, wohoo!

2:37 replaca: technomancy: still here?

2:37 _ato: technomancy's gone to bed

2:37 replaca: wimp :-)

2:37 somnium: alexyk: btw, did the protocol-version of congo have any difference in performance?

2:37 replaca: thx

2:37 headius: what's this about vendor and script/server and maven and dependencies?

2:38 sounds like rails, but I assume it's compojure

2:39 hiredman: I imagine it was someone talking about rails

2:39 _ato: headius: maven stuff is a seperate discussion

2:39 headius: I dunno how similar they are

2:39 ahh

2:39 one of my goals I'll get to some day is getting rubygems and maven repos working together seamlessly

2:39 hiredman: it's not like there aren't a lot of rubyists in here

2:39 headius: so that you can specify dependencies on maven artifacts in gemspecs on jruby

2:39 so that's why I was curious

2:39 alexyk: somnium: ah! you here! protocol didn't do much, alas, looks like my bottleneck.

2:39 _ato: I was just saying that rails is slightly easier for newbies than compojure when it comes to classpath stuff as it provides scripts that set them up for you

2:40 headius: ahh, sure

2:40 hopefully compojure isn't following the all-maven path that lift is

2:40 maybe that's changed for lift, I dunno

2:40 alexyk: somnium: for a moment, I had PermGen errors doing mass-insert! in blocks of 10000, then increased MaxPermSpace and have a 1 GB size collection inserted in an hour

2:40 _ato: nah I don't think James Reeves likes maven

2:40 nospaces: lol - http://news.ycombinator.com/item?id=675984

2:41 _ato: I don't think he likes Leiningen either though, he's working on his own dependency tool called Capra

2:41 headius: alexyk: I'm still confused what that code would be doing that busts permgen

2:41 there's not much that goes in there other than class data

2:41 alexyk: headius: one hunch was it's partial, but I moved it outside the doseq and increased PermGen at the same time

2:42 somnium: alexyk: 1hr ... yikes

2:42 alexyk: takes a while to stuff the database, may try running old code overnight with default PermSpace to see what kills it

2:42 hiredman: alexyk: if chouser says it wasn't partial then it wasn't

2:42 headius: an hour doesn't seem very good

2:42 hiredman: put it in a profiler

2:43 headius: yeah, jack up permgen and do some heap inspection once it gets large

2:43 alexyk: somnium: ha, it's a 3 million collection with 1-8000 list members in each element

2:43 headius: I've dealt with my share of permgen issues, as you can imagine

2:43 somnium: alexyk: trying to get a simple one-connection clojure driver working atm

2:43 headius: but of course, this shouldn't be your job :)

2:43 alexyk: headius: I wonder if there's any Clojure/JRuby shootout out there :)

2:43 headius: different tools for different jobs

2:44 I know several folks using them together

2:44 nothing can really compete with what Rails does for webapps right now, and Clojure obviously does a great job of concurrent services

2:44 the two together are a pretty nice combination

2:44 alexyk: somnium: you mention a desire to auto-chunk mass-insert!, how do I know when the chunk's too big?

2:45 headius: perf-wise, we're roughly the same as clojure for most things

2:45 we have some extra overhead for a few ruby features, but we're slowly eliminating that when it's not necessary

2:45 alexyk: headius: I do pure data mining, and clojure does OK so far. I need dense fast code, that's all. :)

2:45 TheBusby: what's the easy way to increase the value of a map element by one and return the new map?

2:45 hiredman: ,(update-in {:a 1} [:a] inc)

2:45 clojurebot: {:a 2}

2:46 TheBusby: hiredman: much thanks!

2:46 alexyk: ,(update-in {:a 1} [:b] inc)

2:46 clojurebot: java.lang.NullPointerException

2:46 somnium: alexyk: its due to laziness I think, Im not sure how to guard against it

2:46 headius: I'm hoping I can get around to Duby with Clojure collections/refs/stm soon...I have taken on too many projects lately (and no, hiredman, I have not completed that work yet...)

2:47 alexyk: ,(update-in {:a 1} [:b] (comp inc #(or % 0)))

2:47 hiredman: :P

2:47 clojurebot: {:b 1, :a 1}

2:47 somnium: alexyk: another good argument for a pure clojure driver though

2:47 alexyk: -- that was hiredman's advise to my earlier question, TheBusby :)

2:48 headius: clojure and scala make me angry, because I want some of their features without all of their features

2:48 * headius smash

2:48 headius: I'm an "a la carte" language guy these days

2:48 alexyk: somnium: but how does mass-insert work? besides RTFC :)

2:48 TheBusby: alexyk: yeah I hate asking easy questions that I should be able to lookup myself...

2:48 _ato: headius: do you feel the same way about ruby?

2:49 headius: yes

2:49 alexyk: headius: I use both Clojure and Scala allright. Can have both in the same Maven project, too. :)

2:49 tomoj: alexyk: does (comp inc #(or % 0)) look better to you than #(inc (or % 0)) ?

2:49 headius: I would most definitely remove some things from ruby that confound other features or make them less efficient than they could be

2:49 but in general it fits my sensibilities most closely right now

2:50 alexyk: tomoj: hiredman etched the former in my brain first, then I got burned on an update-in writing (cong ... #(...)) without comp. I think always having #(...) outside is safer.

2:50 conj I meant

2:51 tomoj: outside? how'd you get burned?

2:51 alexyk: I suddenly like (fn ...) better than #(), I can destructure fn's args.

2:51 TheBusby: and no nesting problems...

2:51 _ato: headius: what would you remove from Clojure? S-expressions, macros, the require/use mess? Any of the concurrency primitives?

2:51 alexyk: tomoj: grow lists as map nodes. (conj #(or % []) x) fails, #(conj (or % [] x) works.

2:52 for the update-in fn.

2:52 somnium: alexyk: it passes a j.u.Map to the java driver which tries to realize the whole thing iirc

2:52 tomoj: huh

2:52 _ato: multimethods, maybe

2:52 somnium: er, List, not Map

2:52 alexyk: somnium: I tried to stuff the whole huge map with 3 mil keys as one element, and the thing cranked till I killed it.

2:53 hiredman: alexyk: you have to comp conj, just like inc

2:53 alexyk: I think you're right about pure clojure, at least for control.

2:53 hiredman: right

2:53 hiredman: (comp inc #(or % 0)) v. (inc #(or % 0))

2:54 headius: _ato: I'd remove lisp

2:54 tomoj: nooo

2:54 hiredman: :(

2:54 headius: but that's just me, I know others really like lisp as a language

2:55 alexyk: headius: then we remove rubies

2:55 headius: I'm more interested in the backend

2:55 alexyk: be my guest, if ruby's backend is what you want

2:55 I don't care

2:55 somnium: ill take sexps over instance_eval any day

2:55 _ato: alexyk: I'd use #(if % (inc %) 1) instead of comp and or.. I think it's more readable

2:56 headius: somnium: no argument there...a nicer macro capability in ruby would be welcome

2:56 but I don't use evals with strings all that often anyway

2:56 * alexyk loves ruby too

2:57 headius: I was debating some ways to represent clojure primitives in duby

2:57 alexyk: _ato: nice too

2:57 headius: maybe fields would only be initializable in constructor or maybe they'd be refs by default

2:57 it would basically be a separate dialect of duby that uses all immutables except where you tell it to use refs

2:58 and maybe syntax to do refs easily

2:58 tomoj: are you stealing clojure's persistent data structures?

2:59 somnium: headius: is duby usuable as a drop-in for .java now?

2:59 headius: it supports a (small) subset of java features

2:59 I've been slowly adding more as time permits

2:59 TheBusby: what's the clojure way, to generate a vector of 100 empty hash-maps?

2:59 _ato: headius: yeah understandable. There's a trade-off between readability and power with LISP syntax. I'm not one of the people who think LISP is as readable as syntaxes more like Ruby or Python

2:59 headius: it needs a better type model

3:00 _ato: right...I think it's possible to do a mostly-immutable ruby-like language with plain java types, clojure refs/collections/stm

3:00 duby is probably the easiest way

3:00 alexyk: TheBusby: (repeat 10 '{}) ; probably?

3:00 headius: one of a dozen projects I'd like to work on, unfortunately

3:00 alexyk: , (vec (repeat 10 '{}))

3:00 clojurebot: [{} {} {} {} {} {} {} {} {} {}]

3:01 TheBusby: thanks, I need a ruby to clojure cheat sheet...

3:01 tomoj: {} will not be a hash-map, but I don't think you care :)

3:01 (+ no need to quote an empty map)

3:01 alexyk: ok

3:02 headius: I guess the ruby would be Array.new(10) {{}}

3:02 er 100

3:02 tomoj: [{}]*100 ?

3:02 alexyk: _ato: I didn't parse your last sentence. :) Are you saying lisp is not as readable as ruby? :)

3:02 headius: tomoj: works too, but less efficient (probably not by enough to matter)

3:02 alexyk: headius: Ruby looks almost like Scala, btw

3:03 headius: alexyk: yeah, and duby blurs that line even more

3:03 somnium: especially with the new lambda

3:03 headius: def foo(args:List)

3:03 duby's parser is based on ruby 1.9, so it has the 1.9 features like literal lambda too

3:03 _ato: alexyk: yes. I think once you're used to it, you can find lisp pretty readable. But it's always going to less approachable to someone who doesn't know it

3:03 headius: haven't built clojure support into duby yet

3:04 er

3:04 closure

3:04 damn that name

3:04 alexyk: _ato: I'm getting a hang of it, in fact. Then again it's *my* dense code I wrote yesterday which I see clearly. :)

3:05 _ato: on the other hand there's some things that S-expressions give you that other syntaxes don't: simple macros and better editor integration (code navigation and manipulation hotkeys and the like)

3:05 headius: certainly true

3:05 alexyk: yeah. my textmate handles it admirably

3:05 headius: I would like duby to have some sort of macro capabilities (probably compile-time, though)

3:06 editor integration is pretty easy though...duby should have as much editor capability as Java

3:06 intellij guys already expressed an interest in adding duby support

3:06 my immediate thought was "what have I gotten myself into"

3:06 _ato: hehe

3:07 headius: I'm rather underqualified to build a consistent static-typed language

3:07 but I was underqualified to build a dynamic-typed language four years ago

3:08 anyway, I'll shut up about duby

3:08 alexyk: headius: wow, duby is like 20 months old! does it talk already? :)

3:09 * alexyk just googled it

3:09 headius: sure.... bin/duby -e "puts 'hello world!'"

3:09 _ato: hehe it's nearly as old as Clojure then

3:10 headius: yeah, though it's had a bit less effort put in :)

3:10 basically no work from last fall until late this past summer

3:10 alexyk: headius: is it just you, or other folks too?

3:11 headius: there's one other guy doing a lot of commits, and a handful of people who have done minor things

3:12 a lot of stuff works, a lot of stuff doesn't

3:13 http://github.com/headius/duby/blob/master/examples/simple_class.duby

3:13 other examples there

3:13 it's basically ruby, but not

3:14 hiredman: it's kind of a shame to see all this language work and still write the os in C

3:14 alexyk: oh boy, there's also Juby, a dynamic Duby, which was a static Ruby!

3:14 headius: duby could target other backends

3:15 alexyk: yeah, juby became surinx, and then I just decided to add dynamic types to duby

3:15 have not done that yet

3:15 so duby will be hybrid static/dynamic like fan

3:15 hiredman: without gc?

3:16 headius: hiredman: there are ways..."new" could do a normal struct allocation, and "free" could be added as a language-level primitive for clearing memory

3:16 a runtime with GC would be easier though

3:16 hiredman: sure

3:17 headius: there's a stupid broken C compiler for it as a proof of concept

3:17 hiredman: :D

3:17 headius: and of course there's a .java compiler, so if you can write a backend that outputs source, you can do anything

3:19 hiredman: http://gist.github.com/247982

3:19 Duby .class and .java output for a simple script

3:26 eevar2: headius: how strong/elaborate is Duby's type system? fairly close to Java's, or ML/Haskell/Scala-ish?

3:26 headius: it's mostly symbolic now

3:27 but the JVM backend does define a Java-like set of types

3:27 it's not as rich as scala's (yet?) but will need to evolve a bit more than what we have currently

3:27 I'm not an expert on that stuff, so I'll have to learn

3:31 TheBusby: so how do you use update-in if your key is an integer?

3:31 .(update-in {5 "five", 6 "six"} 5 "boo")

3:31 ,(update-in {5 "five", 6 "six"} 5 "boo")

3:31 clojurebot: java.lang.UnsupportedOperationException: nth not supported on this type: Integer

3:32 hiredman: TheBusby: []

3:32 have a closer look at the example I gave and the docs for update-in

3:34 TheBusby: ahh, I get it now

3:35 headius: nite folks

3:53 angerman: What are the pros/cons of a PushbackReader?

3:55 _ato: angerman: compared to what?

4:22 angerman: _ato: I want to read a larger file, linewine

4:22 linewise

4:24 _ato: angerman: okay, but are you comparing PushbackReader to a regular Reader, to a line-seq or to slurp or what?

4:24 note that PushbackReader doesn't have a readLine method

4:24 you need a BufferedReader for readLine

4:25 angerman: hmm.

4:26 I was using (read-lines) from duck-streams

4:26 so I'm basically looking for a facility that hands me a line if I request one.

4:26 as long as there are lines available.

4:27 _ato: read-line is just a lazy-seq wrapper around a BufferedReader

4:27 ~def read-lines

4:28 note that read-lines is lazy, it won't pull the whole file into memory unless you ask it to

4:28 so it's suitable for large files

4:28 angerman: _ato: ok, but how do I take one element off the sequence and let clojure forget the item?

4:28 e.g. use it as a queue and "pop"

4:29 _ato: ,(next ["line1" "line2" "line3"])

4:29 clojurebot: ("line2" "line3")

4:31 _ato: it sounds like you might be trying write your code in an imperative style rather than a functional style

4:31 angerman: _ato: I guess so :(

4:31 _ato: which you can do

4:31 just use (reader some-file) and then call (.readLine) on the reader object

4:32 but it'd be more Clojureish to restructure your program in a functional way, using map, reduce and filter

4:32 angerman: for the algorithm, I have in mind looks like the following: (open file) (process lines until #"^SV$" with process-header-fn) (process lines with process-sv-fn until eof)

4:33 _ato: ah, ok, just a sec, I'll write an example

4:33 angerman: _ato: what I have is http://gist.github.com/247236 starting at lines 38

4:35 _ato: ah

4:35 that is okay, the only problem is you're keeping a handle on the "model" binding

4:35 so it's keeping everything in memory

4:39 angerman: so I should have that out in a different function and assign the result to *model*?

4:40 I'm also curious abou the way I handle the second part of the file, I basically return the (next lines) from the (loop ... recur) and use that on the rest of the file, while I still have the model variabiable bound to the (read-lines ...

4:41 so (to mee) it looks like I have two pointer to the file

4:41 as I don't really discard the model var.

4:41 should I start it in the loops binding?

4:42 _ato: yes exactly

4:42 http://gist.github.com/248018

4:42 just move the call to read-lines into the loop's binding

4:42 and then you won't be holding onto the reference to the start of the lines seq

4:42 so the garbage collector can clean it up as it goes

4:44 the problem was you weren't really losing the head, because model was holding on to it

4:46 ah you'll run into the same problem when parsing the body

4:47 although the JVM might optimize it away

4:49 Bjering: Hello, I have a mutable->immutable transition pain. I wonder what the idiomatic way to handle possible cyclic relationsships in immutable datastructures are. Say two persons being married. As I understand there are no immutable references, is the only way to use a kinf of relational model where "the marrige" lives outside the two persons?

4:50 tomoj: that's what I've been doing

4:50 edges in a graph stored separately and outside the nodes

4:51 angerman: _ato: I'll give it a second thought

4:51 tomoj: but I need ids on everything anyway so it's not too bad

4:52 angerman: _ato: I could chain it, right? assign the results of the (loop for the header to a loop for the body) shouldn't that work?

4:52 Bjering: tomoj: Thanks, ok, and well I guess the value of the "Person" themselves could work as keys in that map of marriges, with two entries per "Marrige" and I would get constant time two-way navigation.

4:52 _ato: angerman: yes, that should work. If you split it into multiple functions it might be easier to structure it chained like that

4:52 angerman: (loop [[a b] (loop ... recur) ...)

4:53 yes, moving the inner loop recur into a fn depending on the file name

4:58 _ato: Bjering: another option is to have keys for your data, so have an entry like {:id :bob, :spouse :jane}. But I think for this sort of thing an external marriage map is nicer, as you want the marriage to be bidirectional

5:00 angerman: _ato: is loop really fast or is doseq with transient types faster? (though I don't know how to break out of doseq

5:00 tcrayford: Is there an easy way to get the last 20 items out of a vector?

5:01 _ato: angerman: doseq uses loop internally, so loop will be just as fast

5:01 tcrayford: or reverse a list for that matter

5:01 _ato: ,(take 2 (reverse [1 2 3 4 5 6]))

5:01 clojurebot: (6 5)

5:02 tcrayford: chairs

5:02 _ato: cheers? :-)

5:02 tcrayford: mm

5:02 just more fun saying chairs

5:02 angerman: _ato: so If I'm going to modify a value very often in a tight loop recur session. Using an external transient ref or atom is faster then recuring with a modified immutable?

5:04 _ato: angerman: recurring with a modified immutable should be faster than a ref or atom

5:05 note there's no reason you can't use a transient in a loop

5:06 angerman: _ato: I just thought that recuring with modified immutables would put a huge burdon on the GC

5:08 _ato: ,(loop [v (transient [])] (if (< (count v) 10) (recur (conj! v 1)) (persistent! v)))

5:08 clojurebot: [1 1 1 1 1 1 1 1 1 1]

5:09 _ato: it's exactly the same amount of work for the GC using an atom vs using a loop binding

5:10 loop and recur is basically implemented underneath using a goto and variable assignment

5:11 angerman: I thought more about (let [v transient []] (loop [r (range 100)] (conj! v (first r)) (recur (next r))) (persisten! v))

5:11 _ato: ah

5:11 angerman: ok

5:11 _ato: that won't work

5:11 your transient code should look exactly the same as non-transient, except adding ! to the end of functions

5:12 transient doesn't mean imperative

5:12 angerman: Maybe I'm messing transient up. In my initial version I used an atom

5:12 though I guess that would cause tremendous overhead for locking

5:13 or a ref, but that would need dosync too

5:13 _ato: yeah, that's what loop bindings are for

5:14 so you can "change" value of the binding on each loop by pasing in a new value to recur

5:14 so in your case there you'd use two bindings

5:14 like this:

5:15 (loop [v (transient []), r (range 100)] (recur (conj! v (first r)) (next r)))

5:15 angerman: with ref like this: (let [v (ref [])] (loop [r (range 10)] (dosync (alter conj v (first r))) (recur (next r))) @v) ;; looks messy

5:16 _ato: yeah, so you don't need the ref if you make "v" a loop binding as well

5:16 angerman: ok. I think I'm getting it slowly. So using loop recur will be quite fast and under the hood do a reassignment or a variable

5:16 _ato: yep exactly

5:17 angerman: the whole idea of taking the ref out of the loop, was to prevent sending data between loop head and the recur

5:18 _ato: right, but you're still sending it, you're just sending v to the ref before recur, and then getting it back again from the ref in the next loop iteration

5:19 Anyway you don't have to worry about passing extra things that don't always change with loop and recur -- the JVM will optimise any unnecessary assignments away

5:20 eg: (loop [x 1, y 2] (recur x (inc y)))

5:20 that'll compile to something where x never changes

5:21 cause underneath it's just a loop

5:21 I mean an imperative loop

5:21 x = 1; while(true) { x = x; y = y + 1; }

5:21 angerman: ok

5:22 _ato: I think Clojure needs some better high-level functions for doing parsing stuff though

5:23 so you don't have to resort to using loop/recur at all

5:23 angerman: _ato: probably.

5:23 for simple parsing I found fn-parse pretty nice

5:23 hiredman: ~parse

5:23 clojurebot: Gabh mo leithscéal?

5:23 hiredman: ~fnparse

5:23 clojurebot: Pardon?

5:23 hiredman: clojurebot: are you kidding me?

5:23 clojurebot: You will not become skynet

5:23 hiredman: clojurebot: parsing

5:23 clojurebot: No entiendo

5:24 angerman: ~on vacation?

5:24 clojurebot: I don't understand.

5:24 hiredman: clojurebot: google fnparse

5:24 clojurebot: First, out of 53 results is:

5:24 joshua-choi&#39;s fnparse at master - GitHub

5:24 http://github.com/joshua-choi/fnparse

5:24 _ato: ah cool, I hadn't seen fnparse

5:28 Qt takes sooooo long to compile.

5:28 * _ato is compiling Qt Jambi 4.6 so he can muck around with writing a conkeror-like browser in Clojure

5:48 angerman: if I have two collections with possible many duplicates, how would I construct a combination with unique items?

5:49 vy: angerman: merge and remove duplicates?

5:50 _ato: angerman: what sort of collections? maps?

5:50 angerman: _ato: (1 2 3 4 5 6 ...)

5:51 I'm thinking of (let [A (set collA)] (map #(conj A %) collB) collA)

5:51 vy: do you want order to be preserved?

5:51 _ato: ,(union (set [1 3 4 5]) (set [1 2 3 6]))

5:51 clojurebot: java.lang.Exception: Unable to resolve symbol: union in this context

5:51 _ato: ,(use 'clojure.set)

5:51 clojurebot: nil

5:51 _ato: ,(union (set [1 3 4 5]) (set [1 2 3 6]))

5:51 clojurebot: #{1 2 3 4 5 6}

5:52 _ato: or yeah... (into (set [1 3 4 5]) [1 2 3 6))

5:52 angerman: if I want to preserve order, I need to use sorted-set?

5:52 _ato: ,(into (set [1 3 4 5]) [1 2 3 6))

5:52 clojurebot: Unmatched delimiter: )

5:52 _ato: ,(into (set [1 3 4 5]) [1 2 3 6])

5:52 clojurebot: #{1 2 3 4 5 6}

5:52 _ato: ,(into (sorted-set [5 4 3 1]) [6 1 2 3])

5:52 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number

5:53 _ato: oh

5:53 angerman: apply

5:53 _ato: ,(into (apply sorted-set [5 4 3 1]) [6 1 2 3])

5:53 clojurebot: #{1 2 3 4 5 6}

5:53 _ato: yeah.. so that's not preserving order, it's sorting it

5:53 angerman: ok, need to do some speed comparisons

5:53 clojurebot: speed is dangerous

5:55 hiredman: ,(doc distinct)

5:55 clojurebot: "([coll]); Returns a lazy sequence of the elements of coll with duplicates removed"

5:56 djpowell: 198 people? is that the highest ever?

5:56 _ato: ah ha!

5:56 I wrote that function the other day

5:56 ha!

5:57 angerman: hmm set and sorted-set seem to have comparable perormance characteristics

5:57 _ato: ~max people

5:57 clojurebot: max people is 222

5:58 _ato: ,(distinct (concat [1 3 5 6] [1 2 2 4 6 7]))

5:58 clojurebot: (1 3 5 6 2 4 7)

5:59 angerman: well calling sort on it is giving it the same speed as the sorted-set version.

6:00 assuming both collections are sorted hmm.

6:01 _ato: oh, are your collections presorted?

6:03 if so you could do a sorted merge which could be completely lazy

6:03 and not require memory

6:10 angerman: http://gist.github.com/248074

6:11 hmm. so nowerdays I can use multiple recurs? intersting. somehow I think I remember it did not work that way

6:12 _ato: it's okay as long as they're all tail calls

6:14 tcrayford: ato, cheers for putting compojure on clojars (assuming that's you)

6:17 angerman: hm. ok my combine functions seems to be a good candidate for reduce

6:20 _ato: angerman: a lazy version: http://gist.github.com/248080

6:21 and with my crazy naming scheme :p

6:22 tcrayford: no worries :)

6:23 angerman: _ato: humilating :)

6:23 powr-toc: Has anyone got leiningen working with swank/slime?

6:24 angerman: powr-toc: yes? exactly on how it's on the website

6:24 powr-toc: angerman: which site, the lien github page?

6:24 angerman: http://wiki.github.com/technomancy/leiningen/emacs-integration

6:25 _ato: but that [[x & xs*] xs] ... I've been so stupid not to know that tick :(

6:25 powr-toc: angerman: thanks... I had that one open in a long lost browser tab :-)

6:26 angerman: is sort lazy?

6:26 _ato: sort can't be lazy

6:26 opqdonut: a correctly implemented insertion sort can be

6:27 _ato: ah well maybe it is then

6:27 angerman: hmm no. it's not. ok

6:27 _ato: hmm

6:27 ~def sort

6:27 opqdonut: taking k first elements of sort xs only finds the k smallest ones from xs

6:27 yeah it's not in clojure

6:27 but it could be

6:27 at the price of performance for sorting the whole list

6:27 _ato: ah right, yeah, I see what you mean

6:28 it'd quicly get expensive with a long list though, unless it was already almost sorted

6:29 opqdonut: mhmm

6:31 angerman: _ato: well. I was just wondering for the second def http://gist.github.com/248085

6:32 it's missing some parens and a sort :( on the last line

6:34 _ato: yeah that might be faster than the set implementation as it skips all the hashing and such

6:34 angerman: hm. the lazy version seems to be a little slower.

6:34 I wonder why

6:35 _ato: than non-lazy?

6:35 laziness has some overhead

6:35 it creates temporary objects

6:37 that's why rich introduced chunked-seqs, but chunked seqs don't help for this sort of algorithm

6:38 angerman: here are both http://gist.github.com/248087

6:48 powr-toc: Ok... when running "lein swank" and finally slime-connect from inside emacs it complains with "Versions differ: 2009-05-17 (slime) vs. nil (swank). Continue? (y or n) " continuing then yields "error in process filter: cond: No inferior lisp process" any ideas?

6:48 what version of slime do I need to install to work with leiningen?

6:58 AWizzArd: to emacs+slime users: does your (tab) autocompletion works when you put a @ in front of a var?

6:59 On my system: *lengthy-nam<tab> ==> *lengthy-name-of-var* but @*lengthy-nam<tab> ==> can't find completion

7:00 technomancy: do you happen to know something about this?

7:00 somnium: same here

7:00 powr-toc: AWizzArd: doesn't work for me either

7:01 what version of slime do I need to work with leiningen?

7:01 AWizzArd: à propos new version of slime.. does a fresh checkout work again with swank-clojure?

7:02 powr-toc: I think the version of slime I'm running is the one that was installed by clojure-mode

7:03 AWizzArd: when you start it it should print its most recent entry date of the change log

7:05 angerman: _ato: (if-let [[ x & xs ] '()] 1) => 1

7:10 where do I retain any thing here?

7:10 http://gist.github.com/248105

7:11 i've added the output just now.

7:11 it's getting slower and slower and slower ...

7:12 Chousuke: angerman: the lines reference I think

7:13 angerman: wrap the loop in a function and call it, instead :)

7:13 somnium: ,(if-let [[x & xs] (seq '())] 1 2)

7:13 clojurebot: 2

7:16 Chousuke: angerman: http://gist.github.com/248106 this should be fine, but I didn't test it

7:16 angerman: Chousuke: thanks. I'll examine it carefully

7:18 Chousuke: angerman: basically, since function arguments are only cleared at tail calls, the lines reference exists for the duration of the entire loop

7:18 angerman: but if you instead create an inner function and call it, that counts as a tail call, and the reference is cleared

7:21 aav-: anyone knows if test-is from clojure.contrib 1.0 works with clojure 1.0? i always get 'actual: java.lang.IllegalStateException: Var clojure.core/if is unbound.' exception

7:21 Chousuke: it might be clearer if you did (defn compute-metrics [[header lines]] (letfn [(worker [[ln & lns] fs exps] ...)] (worker lines nil 0)))

7:21 it ought to work

7:22 that's what the branch is for :)

7:22 cemerick: oh-my-god annotations are awful

7:23 Chousuke: aav-: you sure there aren't any stale classfiles around or something like that?

7:23 aav-: or that you really *do* have the correct versions :)

7:24 aav-: Chousuke: hope so. will check once again.

7:26 angerman: Chousuke: doesn't make a difference :(

7:27 what I so much do not understand is, why the timing for the combining goes up.

7:27 that should be near constant at least to my understanding.

7:27 as it's always doing the exactly same

7:28 Chousuke: hmm

7:29 I suppose closing over header shouldn't keep the lines ref around? :/

7:30 that would be silly.

7:30 anyway, can you show lazy-combine-sorted?

7:30 angerman: http://gist.github.com/248122

7:30 aav-: Chousuke: my clojure-contrib is built from clojure-1.0-compatible branch

7:32 Chousuke: angerman: looks like building the combination takes X+Y time, and X grows with each iteration of course.

7:33 angerman: no, X stays the same

7:33 it's 44928 items large

7:33 on each iteration

7:33 somnium: angerman: the (if (empty? ...) lines dont have any effect

7:34 angerman: somnium: yep. I know. I just saw that. They were there wen I tried to work out how to handle empty input

7:34 somnium: angerman: call seq on the input in the if-lets

7:34 ,(true? '())

7:34 clojurebot: false

7:34 * angerman is still very confused why it's taking longer and longer

7:35 _ato: because "features" is getting longer and longer

7:35 Chousuke: I can't see how features is *not* growing.

7:35 somnium: ,(if '() true)

7:35 clojurebot: true

7:35 angerman: Chousuke: when you look at the output log

7:35 Chousuke: somnium: true? tests whether foo is the boolean value true

7:35 somnium: ,(if (seq '()) true)

7:35 clojurebot: nil

7:35 _ato: oh wait

7:35 angerman: https://gist.github.com/248106/449e604d5c190c452ac4c50bdde1f81dcabe6e24

7:35 _ato: you're right

7:36 so it merges them all

7:36 angerman: I print experiment and the size of the features each iteration

7:36 somnium: Chousuke: yeah, I realized that when clojurebot replied :/

7:36 _ato: there are the same number of lines in each experiement?

7:37 angerman: right now. yes. but that's not the general case

7:37 right now it's a dense case, where each experiment (line) has the same amount of features

7:37 _ato: weird

7:37 angerman: so it's basically computing something very stupid in this edge case

7:37 _ato: I can't see why it'd be getting slower :/

7:38 angerman: _ato: me neither. it just makes no sense to me

7:38 Chousuke: I obviously need a cup of coffee.

7:38 angerman: it's like computing (x A B) with the exactly same input values 100 times in a row and it's getting slower the longer it computes it.

7:39 I could probably speed it up by putting it into a memorize block

7:39 _ato: I guess it could be a garbage collection effect, but you'd expect the performance to be spikey if it was GC instead of growing linearly line that

7:39 or well not linearly

7:40 angerman: seems more exponentially

7:40 _ato: yeah

7:41 Chousuke: the lazy-seq keeps a reference to all the xs and ys seqs? :/

7:41 that might be it.

7:43 _ato: huh? it drops them as it goes doesn't it? so once it's through the map, the shorter of xs and ys should be nil

7:43 angerman: Chousuke: but should not doall force the evaluation ?

7:44 _ato: err yeah, doall, not map

7:44 I'm getting too sleepy

7:45 Chousuke: yes it should, but somehow I'm suspicious

7:45 angerman: I'll see what happens if I just make it unlazy

7:46 that causes a sraight stackoverflow

7:47 Chousuke: use recur

7:47 :P

7:47 _ato: yeah remove lazy-seq and change the (lazy-combine-sorted ...) to recur

7:47 Chousuke: the calls in the cond are in tail position, so you can do that.

7:47 _ato: oh wait

7:47 it's not tail

7:47 yeah

7:47 angerman: what about your other version?

7:47 http://gist.github.com/248122

7:48 does it happen with that?

7:48 angerman: my other version doesn't work at all ... no idea why

7:49 crap, I've a lecture.

7:49 bbl

7:49 Chousuke: hmm

7:51 _ato: I'm stumped, perhaps the problem is actually in extract-features

7:52 Chousuke: ,(map (fn [x y] (cond (> x y) y :else x)) [1 1 3 3 4 5] [1 2 2 2 3 8])

7:52 clojurebot: (1 1 2 2 3 5)

7:52 Chousuke: isn't that sorted-combine? :P

7:53 _ato: I think it's also supposed to remove duplicates

7:53 Chousuke: it doesn't :/

7:54 _ato: I mean (combine-sorted [1 2 3] [1 2 3]) => (1 2 3)

7:54 distinct inputs and outputs

7:55 cond (= x y) (cons x (lazy-combine-sorted xs* ys*))

7:55 ^ pops from both lists

7:57 Chousuke: the map does that... what it doesn't do is not advancing both of the lists when there's a mismatch :/

7:58 _ato: ah right

7:58 ,(map (fn [x y] (cond (> x y) y :else x)) [1 2 3] [1 2 3])

7:58 clojurebot: (1 2 3)

7:59 _ato: ,(map (fn [x y] (cond (> x y) y :else x)) [1 3 5] [2 4 6])

7:59 clojurebot: (1 3 5)

7:59 Chousuke: and now I realised the whole fn is just min :P

8:01 _ato: what?

8:02 how? :/

8:02 Chousuke: I mean in the map

8:02 mikem: he means (fn [x y] (cond (> x y) y :else x)) == min

8:02 Chousuke: ,(map min [1 1 3 3 4 5] [1 2 2 2 3 8])

8:02 clojurebot: (1 1 2 2 3 5)

8:02 _ato: oh right

8:02 yeah

8:03 hehe

8:03 I thought you meant combine-sorted was just a min

8:05 cemerick: hrm, looks like PersistentVector serialization is broken again, though I'm not sure it could because of the AtomicReference<Thread> field

8:05 Chousuke: lazy-combine-sorted *does* cause the seq to grow though, unless they're identical or if the other seq is a kind of a "superseq" :/

8:05 cemerick: could be serializable, that is

8:06 Chousuke: but for some reason this leads me to think that maybe maps would be better :P

8:07 an integer key and count and you could just merge-with min

8:09 ~def merge-with

8:10 doesn't seem to use transients.

8:12 cemerick: I suppose making that field transient will make vector serialization possible again without much of an issue. Not sure if edited transient vectors would be properly serialized, though.

8:16 AWizzArd: foo takes an object and returns a sequence of "tags". Example: (map foo my-coll) ==> ((:a :b :c :d), (:d), (), (:a :d), (:e)). Is there a good bar which would accumulate those "tags"? (bar (map foo my-coll)) ==> {:a 2, :b 1, :c 1, :d 3, :e 1}? Or maybe even better: ((:d 3), (:a 2), (:b 1), (:c 1), (:e 1)).

8:16 powr-toc: whats the best way to install clojure-mode/slime right now?? I've tried to go through ELPA and supposedly have the packages installed, but I can't get them to load properly

8:19 _ato: ,(apply merge-with + (map (hash-map % 1) [:a :a :b :c :d]))

8:19 clojurebot: java.lang.Exception: Unable to resolve symbol: % in this context

8:19 _ato: ,(apply merge-with + (map #(hash-map % 1) [:a :a :b :c :d]))

8:19 clojurebot: {:a 2, :c 1, :b 1, :d 1}

8:20 _ato: actually

8:20 in seq-utils I think there's something

8:21 yeah

8:21 ,(frequencies [:a :a :b :c :d])

8:21 clojurebot: {:d 1, :c 1, :b 1, :a 2}

8:22 _ato: ,(frequencies (concat [:a] [:a :b] [] [:a :b :c]))

8:22 clojurebot: {:c 1, :b 2, :a 3}

8:22 _ato: AWizzArd: ^

8:23 AWizzArd: oh good, thx

8:32 cconstantine: Is there a clojure lib that does diffing of sequences?

8:33 ohpauleez: cconstantine: if the seqs are small you can turn them into sets and diff them

8:34 cconstantine: I'm afraid the seqs might get large

8:34 like gigibytes in size

8:34 ohpauleez: ah

8:35 you might just want to make a filter function that returns a lazy sequence of matches

8:35 chouser: cconstantine: you want full order-aware patch-producing type diff?

8:35 ohpauleez: but someone here might have a much much better idea

8:35 cconstantine: obviously if they are gigibytes in size and a pathilogical case for diffing we have problems, but lets assume they are very similar

8:35 chouser: insert/delete detection and such?

8:35 cconstantine: chouser: I would like that, but I wouldn't call that a requirement

8:36 the big idea is to diff the output of two programs line-by-line, where I convert the lines of their outputs into lazy sequences and compare them

8:37 chouser: if you don't care about insert/delete, you should be able to just (map = coll1 coll2)

8:37 cconstantine: for my use-case of this program they will have the same number of lines, but to be a generic solution inserts/delete would need to be supported

8:38 oh... right.

8:39 ohpauleez: chouser: what if he did care about insert/delete?

8:40 chouser: ohpauleez: then I'd say it's high time someone look into the diff research that's been done, maybe find some analysis of the gnu diff algorithms, and port them to Clojure seqs.

8:41 And put that in contrib.

8:41 ohpauleez: gotcha

8:41 cconstantine: hehe

8:41 ie, "that sounds damned useful, and we don't have it" :)

8:41 chouser: heh. exactly.

8:42 cconstantine: *sigh*... I have 4 hours to implement this program

8:42 chouser: I've frequently wanted access to those algorithms for things other than lines of a file. Clojure seqs should be perfect.

8:42 cconstantine: thats what I was thinking

8:43 Chousuke: can't look a gnu diff though.

8:43 it's GPL :P

8:43 chouser: A friend of mine implemented a very nice english-text differ that treats all whitespace the same (newlines as well as spaces in a line)

8:44 he did it by munging the input, running it through diff, then reassembling the results. The results are beautiful. The means ... not so much.

8:44 _ato: http://en.wikipedia.org/wiki/Diff#Algorithm

8:44 chouser: http://agriffis.n01se.net/adiff/

8:45 ohpauleez: _ato: That's what I though, a LCS modification

8:45 I wrote a program analyzer that normalized java code and tried to find plagiarized code

8:46 it was all based on LCS and Euclidean distance (effort measured operations need to transform one to the other)

8:46 cemerick: writing a proper diff for arbitrary seqs isn't really that hard. We have one that is the basis of the scorer for an approximate regex library. *shrug*

8:52 powr-toc: When you run lein swank in the terminal, does anyone else find the terminal REPL halts?

8:52 i.e. it blocks... and doesn't allow input?

8:52 (except via emacs slime-connect)

9:00 _ato: powr-toc: yeah I get the same thing

9:00 I don't use lein-swank though

9:00 I use M-x swank-clojure-project in emacs

9:01 ohpauleez: it's ok to include Apache licensed code into a EPL licensed project, correct?

9:01 being that Apache is rather similar to BSD in that regard

9:02 powr-toc: _ato: ok, might give that a try... I found that "lein repl" with a call to my (swank-server) function in my user.clj worked though... giving me both terminal and emacs access to the same repl

9:02 not sure why I like having both a terminal based repl and the emacs one

9:03 marten: powr-toc: (swank.swank/start-server "/tmp/swank.4005" :port 4005 :dont-close true)

9:03 that works for me

9:06 powr-toc: marten: yeah, that's what I have in my swank-server fn...

9:08 _ato: swank-clojure-project seems to work quite well too

9:18 alexott: hello all

9:19 i have one question about using send-off with long-running functions. If i have some long-running function, and start it with send-off, then modification of state, that this function will receive as argument, could affect other send-off functions?

9:21 for example, i call (send-off agent func), func receives agent's state, do some job (in parallel with other jobs), and return modified state. what will happen, if some another job had already changed agent's state

9:21 rhickey: alexott: you are sending mutable data as an argument, and mutating it?

9:21 alexott: i'm sending map {}

9:21 rhickey: alexott: the function sent to an agent will always see the current state at the time it is applied

9:22 not at the time it is sent

9:22 alexott: rhickey: ok, thanks

9:22 rhickey: thank you for this language ;-) I don't like Java, but I'm very happy with Clojure

9:23 rhickey: alexott: you're welcome

9:26 djork: why doesn't the with-meta reader macro attach metadata to quoted forms? (if those are the right terms... let me demonstrate)

9:26 ,(meta #^:bar '(foo))

9:26 clojurebot: nil

9:26 chouser: djork: it attaches to the (quote ...) form

9:27 ,(meta (quote #^:bar '(foo)))

9:27 clojurebot: {:tag :bar}

9:27 djork: hmm

9:27 I'm not sure I understand

9:27 chouser: '(foo) is read as (quote (foo))

9:28 #^ attaches metadata to read-time forms, not to runtime data objects

9:28 djork: ah, I see

9:28 chouser: so the seq (quote (foo)) gets the metadata in your example

9:28 clojurebot: foo is is Short, Self Contained, Correct (Compilable), Example http://sscce.org/

9:29 chouser: when compiled and evaluated, metadata on a (quote ...) form is ignored

9:29 perhaps you want to quote the whole thing:

9:29 djork: yeah

9:29 chouser: ,(meta '#^:bar (foo))

9:29 clojurebot: {:tag :bar}

9:30 djork: I might also want to be using with-meta and list instead of fiddling with quoting :)

9:30 chouser: that one ' quotes (foo) with its metadata

9:30 djork: also possible. :-)

9:30 djork: thanks

9:30 aav-: does anyone know which branch of clojure.contrib is compaible with clojure 1.0 ? 1.0-compatible fails to build

9:30 djork: interesting how quoting the #^ reader macro quotes the next form too

9:30 chouser: suffix metadata will help decrease confusion about interaction with quoting

9:31 djork: as far as the reader is concerned, #^:bar foo is a single form

9:31 djork: right

9:31 still weird to me

9:31 chouser: yes

9:31 the space there is I think the culprit

9:31 djork: good to know though

9:31 chouser: foo^:bar looks more like a single form

9:32 alexott: rhickey: and another question about agents - is it possible to control number of running threads for given agent?

9:32 chouser: and 'foo^:bar would do what you expect, as would '(foo)^:bar ... but that meaning of ^ is a ways off yet.

9:32 rhickey: but there sill never be [a data structure]^:bar

9:32 chouser: rhickey: really?

9:32 rhickey: really

9:32 chouser: why's that?

9:33 rhickey: because foo^:bar is enough of a hack on symbol reading, allowing ]^ etc would totally trash the concept of what it means to be a delimiter

9:34 and, who want's to search to the end of a long data structure to see if there's metadata?

9:34 wants

9:35 I'm completely unconvinced about suffix metadata

9:36 but I think moving from #^String foo to ^String foo will be welcome noise reduction

9:36 djork: yuck, good points

9:36 wait, so #^ is becoming ^

9:36 but ^ currenty means the opposite of #^, doesn't it?

9:37 rhickey: djork: maybe someday, first comes a period of deprecation for ^

9:37 djork: ah

9:37 somnium: is there a way to add #^Klass type-hints in a macro (when Klass is a string)?

9:37 djork: yeah, I don't mind (meta foo)

9:37 rhickey: djork: not, it isn't the opposite, and that's one of the problems

9:37 djork: I see

9:38 chouser: somnium: yes. type hints are symbols, so you just make sure the forms the macro is returning has the right tag metadata

9:38 somnium: (with-meta 'Foo {:tag (symbol "Klass")})

9:39 somnium: awesome! thanks

9:39 rhickey: we still need a plan for deprecating ^

9:40 djork: hiredman: I took inspiration from your clojurec gist and am using metadata + multimethods to really accelerate this codegen process

9:40 I'm planning on being able to define C modules in pure clojure using namespaces and macros

9:40 (c-module hello-world (:import stdio stdlib))

9:40 etc.

9:43 chouser: c-in-parens

9:49 lisppaste8: rhickey annotated #91445 "bring back :as ?" at http://paste.lisp.org/display/91445#2

9:50 rhickey: :as this-name optional, use only when you need to refer to this

9:51 chouser: hm, I had thought of a non [] marker, but :as has nice symmetry with destructuring that I hadn't thought of.

9:51 rhickey: it was in early newnew design

9:52 but I hate the floating thisnames, this anchors them

9:52 and gives a context for :other settings

9:52 ohpauleez: rhickey: I really like this idea

9:52 chouser: that's interesting terminology. I'm not confident I understand everything you mean by "floating"

9:55 rhickey: chouser: it's not a precise thing, more of afeel issue, in (deftype Foo [...] this Protocol (method [] ...)), Protocol feels like it is floating, having this floating too is too much

9:56 whereas :keyword val pairs feel anchored

9:58 reify read a little better in the original newnew: (reify [Interface] :as this (method [] ...)...)

9:58 shr3kst3r: when passing a script to clojure.main, how to i tell it to execute -main?

10:00 rhickey: but I think P1 + methods P2 + methods ... will be important for deftypes, which might get large. It is a real mess in Java when overrides don't end up bunched by interface, and they often don't, also you can search for the protocol and find the entire implementation

10:00 so reify follows, but doesn't have the same needs as it will usually be one protocol/interface

10:02 and should there be other options, the structure will remain (deftype name [fields] options* proto+methods*), (reify options* proto+methods*)

10:02 shr3kst3r: figured out my question

10:36 * angerman still doesn't get why this code takes more and more time.

10:44 angerman: at least combine-sorted works now

11:12 StartsWithK: lisppaste8: help

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

11:13 StartsWithK pasted "Generalized -> and ->> forms, no special symbols" at http://paste.lisp.org/display/91522

11:15 StartsWithK: just cooked this, there are examples at the end

11:15 what do you think?

11:24 cemerick: StartsWithK: so x is always replaced with the prior value?

11:26 chouser: I certainly like it better than using $

11:26 StartsWithK: cemerick: yes, but 'as' works ib both =>> (->>) and => (->) as espected

11:26 in*

11:26 chouser: I'm just not sure it carries it's weight

11:27 cemerick: ...the objective being threading arguments in arbitrary positions?

11:27 StartsWithK: (=>> [1 2 3] (map inc) (as [x y z] [(-> x inc inc) (-> y inc inc) (-> z inc inc)])) is valid too

11:28 cemerick: oh, I see, => defaults to -> placement =>> to ->> placement

11:28 StartsWithK: yes, just a quick placeholders

11:28 'as' is normal macro, you can create a wrapping macro for it, it still work, destructurin too

11:29 arbitrary position will never work withoud magic symbols, this is second best thing :)

11:29 rhickey: there is let

11:30 StartsWithK: but you cant do (-> [1 2] (let ...))

11:30 chouser: (let [[x y z] (map inc [1 2 3])] [(-> x inc inc) (-> y inc inc) (-> z inc inc)])

11:30 rhickey: once you put as in there the simplicity of -> and ->> is gone

11:30 so why push it?

11:30 stuartsierra: agreed

11:31 StartsWithK: rhickey: true, it was just a small experiment i just did

11:31 chouser: this is what I meant by "weight". Although there are occasions when I start with -> or ->> and realize an out-of-place arg is required and so I have to break out into 'let', in the end such complex expressions feel better as 'let' anyway.

11:31 rhickey: StartsWithK: that's fine, just my $.02

11:32 stuartsierra: chouser: I find the same thing

11:32 chouser: Huh. I haven't used doto in ages.

11:32 I guess that has mostly to do with the APIs I'm interacting with.

11:32 rhickey: I think it is important that -> and ->> convey that the entire expression is chained or piped

11:32 not woven

11:33 stuartsierra: or knotted

11:33 rhickey: heh

11:34 Raynes: rhickey: I read that as "not women"

11:34 clojurebot: women are just jealous, since lisp has nice curves. -- Chousuke

11:34 chouser: I did write and use a macro like -$> early on.

11:34 rhickey: so http://paste.lisp.org/display/91445#2 is the winner, barring some substantive objections

11:34 chouser: called mine >>_

11:35 Chousuke: if you're going to have arbitrary position pipelines you might just have the arg be explicit in every expression.

11:35 chouser: rhickey: good.

11:38 methods aren't functions, but might they support :pre/:post anyway?

11:39 fogus_: Not to beat a dead horse, but an additional benefit to -> and ->> is that they can be used programmatically to build functions/forms pretty generically. -$> and the like require some precise knowledge about the pipeline elements

11:40 rhickey: chouser: :pre and :post are interesting - I had originally planned to put them on the protocols themselves, but that is trickier with the inline implementation of protocols in deftype and reify

11:41 * angerman smashes his head against a wall. Why on earth is my code running out of memory?! I'm trying to do this line by line

11:41 chouser: oh, right, I remember that now. hm...

11:42 angerman: is c.c.duck-streams read-lines or reader specifially mean?

11:43 chouser: read-lines is a bit dangerous. I don't like tying the closing of the file to consuming the whole seq.

11:44 angerman: but if you're running out of memory, the most likely problem is that the head of the seq is being held somewhere, preventing GC from freeing it.

11:45 stuartsierra: Using lazy sequences for large file processing is very difficult.

11:47 duck-streams is written for convenience, with no consideration of memory usage.

11:50 angerman: my utilities http://gist.github.com/248319 , my code: http://gist.github.com/248320 , my sample file http://dl.dropbox.com/u/281539/upps.data.model.bz2 [60M]

11:50 stuartsierra: what's the best way to read a file linewise then?

11:50 stuartsierra: angerman: your problem is in (defn compute-metrics [[header lines]]...)

11:50 "lines" is the head of the sequence, not released until the tail call of the compute-metrics function.

11:51 angerman: yes, somewhere there it's crashing

11:51 stuartsierra: My rule of thumb is this: never bind a lazy sequence to a local variable, including function arguments.

11:51 angerman: stuartsierra: initially i thought about using (with-in-reader), hoping I could just (read-line) after another and process it. :(

11:52 neilmock: is surrounding a var definition in * idiomatic for something?

11:52 AWizzArd: Is there a .csv parser for Clojure?

11:53 angerman: stuartsierra: ok, but mapping and reducing is allowed, right?

11:53 stuartsierra: angerman: sure, that's not the problem.

11:53 chouser: neilmock: *earmuffs* suggest the var is meant to be re-bound using 'binding'

11:54 stuartsierra: neilmock: or used as a global variable/constant

11:54 angerman: stuartsierra: how would I approch my problem then, to parse the file with parse-header until it hit's the line SV and then continue to parse the rest with compute-metrics?

11:55 rhickey: stuartsierra: looking into liveness tracking is next on my todo after incorprating the latest forms of deftype and reify

11:55 angerman: somehow I need to hand over the point where parse-header left of to compute-metrics.

11:55 rhickey: unless someone else wants to do the latter

11:55 neilmock: chouser: ah, thanks!

11:55 stuartsierra: angerman: my best suggestion is to work with the java.io.Reader directly.

11:55 StartsWithK: isn't +foo+ a convention for global/constant?

11:56 stuartsierra: rhickey: great

11:56 StartsWithK: sometimes, but not used as often, lots of people use *foo* for that too

11:56 angerman: stuartsierra: so in the wide-finder thing, it only works because he's explicitly mapping and mergine the lazy-seq

11:57 stuartsierra: angerman: haven't seen that code

11:59 angerman: can I implement something like http://code.hammerpig.com/how-to-read-really-large-files-in-java.html in pure clojure?

12:00 stuartsierra: angerman: in http://technomancy.us/130#c it works because the result of line-seq is never bound to a local variable.

12:00 angerman: You can do this in Clojure, you just have to be careful.

12:00 Chousuke: angerman: that's just line-seq, isn't it?

12:01 chouser: a non-caching line-seq, perhaps.

12:01 Chousuke: well, just don't hold onto the head

12:02 angerman: hmm. alternativly I could write a function, and rebind it with a sideeffekt?

12:03 lisppaste8: stuartsierra pasted "Safe lazy sequences" at http://paste.lisp.org/display/91525

12:04 chouser: it's pretty unfortunate how subtle that is.

12:04 stuartsierra: yes

12:04 chouser: stuartsierra: but that's a nice clear, specific example. thanks.

12:04 stuartsierra: Took me ages to figure it out.

12:04 chouser: you're welcome

12:05 Chousuke: hm.

12:05 rhickey: this is one area where hotspot has definitely let me down - those local references should be plainly dead to the GC

12:05 stuartsierra: Actually, (read-lines (reader filename)) is redundant

12:07 Chousuke: so wait, why does process-lines hold on to the head? the map returns immediately, and isn't reduce a tail call? I don't quite see what's happening there

12:08 assuming that process-stuff in the latter code is supposed to be process-lines

12:08 stuartsierra: Chousuke: yes

12:08 rhickey: what's with the read-lines example though?

12:08 stuartsierra: Chousuke: I'm not sure if process-lines is actually safe; maybe "lines" gets cleared and reduce is a tail call

12:09 Chousuke: looks fine to me.

12:09 stuartsierra: rhickey: That's usually the first place people get hung up on non-GC'd lazy sequences, trying to read a large file line by line.

12:10 rhickey: stuartsierra: is the problem in read-lines or process-stuff?

12:11 stuartsierra: The problem (I think) is passing the sequence as an argument to process-stuff.

12:11 rhickey: stuartsierra: if you have a test case for that can you try it in master and new?

12:12 lisppaste8: stuartsierra annotated #91525 "Safe lazy sequences (2)" at http://paste.lisp.org/display/91525#1

12:12 stuartsierra: rhickey: sure, I'll try to come up with a test case

12:14 angerman: well. I think my code could probably be a testcase, he :)

12:15 rhickey: stuartsierra: nm, I thought you had a case of invoke holding, but your latter example is just data literal is not a tail call

12:16 from the perspective of locals clearing

12:16 stuartsierra: rhickey: right, that's why it doesn't work

12:17 rhickey: but not a problem with read-lines

12:17 stuartsierra: No, there's no problem with read-lines, it just returns a sequence. It's what people do with that sequence that's a problem.

12:18 rhickey: shiny: http://github.com/bradford/crane

12:19 stuartsierra: yeah, I've been looking at that

12:19 rhickey: stuartsierra: there was a subtle hold inside apply and restfn (Java code) which I removed in the new branch

12:20 most of the examples I see are just clear realization of a seq prior to tail call, needs liveness tracking to fix

12:20 stuartsierra: ok

12:21 chouser: ,(time (try (let [s (iterate #(java.util.Arrays/copyOf % (count %)) (int-array (range 1e5)))] [(first s) (last s)]) (catch Error e (prn e))))

12:21 clojurebot: chouser: Huh?

12:21 rhickey: so for all of you testing fans out there, I have some feedback

12:21 in working on new branch I kept controb working

12:22 several times something I did caused a contrib test to fail

12:22 angerman: in the future, will i be able do use a seq, the way i tried to use it?

12:22 rhickey: never did the test failure help me figure out how what I did affected the code that failed

12:23 chouser: did it help you discover a possible drawback to a change that you hadn't considered?

12:23 rhickey: just meaningless stuff like (not (= 42 43))

12:23 fogus_: rhickey: Uncle Bob just felt a pain in his temple

12:24 stuartsierra: rhickey: was the problem with the way the tests were defined, lack of documentation, poor naming?

12:24 rhickey: the tests themselves were nigh unreadable

12:24 and the failure message conveyed little other than - 'unexpected result'

12:24 stuartsierra: Well, what else could it convey?

12:25 chouser: ,(let [s (iterate #(java.util.Arrays/copyOf % (count %)) (int-array (range 1e7)))] [(first s) (last s)])

12:25 fogus_: To put valueable error messages would only add further obfuscation

12:25 rhickey: stuartsierra: I'm not proposing an answer, just conveying my experience

12:25 clojurebot: Execution Timed Out

12:25 chouser: ,(let [s (iterate #(java.util.Arrays/copyOf % (count %)) (int-array (range 1e5)))] [(first s) (last s)])

12:25 clojurebot: java.lang.OutOfMemoryError: Java heap space

12:26 chouser: there. that's the fastest-failing infinite lazy seq I've found yet.

12:26 smaller or larger arrays take longer to fail

12:28 rhickey: stuartsierra: the author of a test knows it should produce 42, given a full understanding of the original code, the consumer of a failed test knows 42 != 43

12:29 angerman: ok. I'll have to write that BigFile as a clojure option.

12:29 stuartsierra: rhickey: yes, I tried to help with that in "is" by printing both the unevaluated form and the evaluated result, but it's not perfect

12:29 rhickey: somewhere inside the code a semantic invariant was violated, but the test treats the semantics as a black box

12:30 I guess something like pre/post conditions would be better for me

12:30 stuartsierra: rhickey: So rather than specific results, it would be better to test semantic invaniants?

12:30 *invariants

12:31 rhickey: stuartsierra: I don't know, like I said, just conveying my experience. The tests worked in that I knew I broke something, but that was the extent of the help

12:32 bitbckt: rhickey: Seems like useful input for something like git bisect, though.

12:32 e.g. "What commit broke that?"

12:32 stuartsierra: rhickey: Better than nothing. That's been my experience with testing as well, though.

12:32 rhickey: bitbckt: but I knew that information

12:33 it's more a matter of, what about what I did matters to this failing code and why?

12:33 stuartsierra: That's a lot harder.

12:33 rhickey: given I know nothing about the failing code

12:33 stuartsierra: I think it's like error messages and stack traces - they tell you something went wrong, but don't tell you why.

12:34 angerman: (with-big-file (read-big-file "....") (next-line) ;; return next line // (rest-seq) ;; returns lazy sequence for the rest of the file)

12:34 bitbckt: stuartsierra: It's exactly like that, to me.

12:34 rhickey: stuartsierra: but there can be a useful locality there - failing tests just says - this end result is bad

12:34 angerman: does that seem like a suitable wrapper?

12:34 stuartsierra: rhickey: "useful locality" - can you explain more?

12:35 rhickey: stuartsierra: well, if there were pre and postconditions inside the implementation of the code under test, any violation would report about the inside of the codebase, not its results

12:38 stuartsierra: So you're looking to know specifically where the failure occurred?

12:39 bitbckt: The test failing is merely a flag, to me. It signals that something I didn't intend to break, broke, and I need to investigate.

12:40 The "why" comes from reasoning, not from the test.

12:40 rhickey: stuartsierra: well, with an exception for instance I get a pointer inside the code in question

12:40 stuartsierra: but often several layers removed from the actual cause of the bug

12:40 rhickey: bitbckt: that's not an answer here, I can;t reason about code I didn't write without a huge amount of work

12:40 stuartsierra: still, there's a path too

12:41 stuartsierra: yes

12:41 I think what we're getting at here is that unit tests on library code are not helpful for debugging language implementations.

12:42 rhickey: stuartsierra: I don't think that's the issue

12:43 stuartsierra: I guess I'm having trouble visualizing pre/post conditions that could provide better failure diagnosis.

12:43 rhickey: consider the difference between unit tests and pre and post conditions

12:44 a precondition says - I expect this input to be even, a unit test produces 43 instead of 42 when it isn't

12:44 the precondition is in the head of the test author, but gone at test runtime

12:45 bitbckt: That seems like a poorly-written test.

12:45 stuartsierra: But isn't that just the fault of the test author? i.e., instead of testing (is (= 42 foo)) they should test (is (even? foo))

12:45 bitbckt: The point is to avoid "a huge amount of work"

12:46 rhickey: stuartsierra: (is (even? foo)), then pass 17 - what's the point? if the test for evenness isn't in the code called

12:47 i.e. the test should verify that the precondition is validated by the runtime code

12:47 bitbckt: rhickey: Are you looking for greater coupling between the tests and the implementation? That's what it sounds like...

12:47 rhickey: you can't move a precondition into a test

12:49 stuartsierra: Ok, so you're looking for functions to do more run-time validation, then use the tests to verify that they are doing it correctly?

12:50 rhickey: stuartsierra: if the latter is even needed, given the former (or the former in a validation mode, sometimes the checks are too expensive)

12:50 asserts > tests

12:50 stuartsierra: Ok, now I get it.

12:50 bitbckt: There we go. You finally said it.

12:51 stuartsierra: I think of unit tests as guarantees of future behavior. E.g., I changed the implementation of this function to make it more efficient, but did I accidentally change the behavior as well?

12:51 rhickey: um, I think Bertrand Meyer figured this out a while ago

12:52 stuartsierra: no doubt, they do that - my scenario is different than the code author's

12:53 stuartsierra: Maybe I should learn Eiffel.

12:55 Recalling my Algorithms class, defining invariants is MUCH harder than writing unit tests. :)

12:55 rhickey: well, clojure has ;pre and :post now, so people can play with them

12:56 stuartsierra: is there a summary of those somewhere?

12:59 rhickey: http://github.com/richhickey/clojure/commit/0ac482878a1dd520cbee2faa0f5f6ab1082ffa76

13:00 stuartsierra: speaking of the documentation punchlist for 1.1 ... :)

13:00 fogus_: Seems like we're heading down the road to incorporating Datalog

13:00 rhickey: I've cleared the plate of 1.1. features other than some deprecate/doc stuff

13:00 bitbckt: fogus_: Sadly.

13:01 rhickey: bitbckt: how is that sad?

13:01 fogus_: bitbckt: You misspelled "awesome"

13:01 bitbckt: haha

13:01 lisppaste8: stuartsierra pasted "Simple laziness test cases" at http://paste.lisp.org/display/91528

13:01 rhickey: stuartsierra: do you want to marshall the dev troops around 1.1 prep?

13:02 stuartsierra: sure, what do you need?

13:02 rhickey: first step is determining what we need

13:02 some things already known - a list of changes since 1.0

13:02 stuartsierra: :)

13:03 rhickey: docs for bigger features that won't be found in doc strings (e.g. chunks, transients)

13:03 any packaging issues (we've had complaints about the .zip littering the expansion dir)

13:04 new API docs from Tom Faulhaber's process (these are underway)

13:04 maven stuff

13:04 stuartsierra: ok

13:06 rhickey: What do you think of packaging a contrib snapshot with 1.1?

13:07 rhickey: stuartsierra: definitely interesting, will require some commitment from contrib to maintain a 1.1 branch if needed

13:07 these are all good things to raise in clojure-dev

13:07 stuartsierra: ok

13:08 rhickey: a plan for release candidates

13:09 these are the only open items right now for 1.1: https://www.assembla.com/spaces/clojure/tickets?milestone_id=93750&tickets_report_id=1

13:10 stuartsierra: working on 214

13:10 alinp: hi guys

13:10 I have an issue here, that I can't build the clojure-contrib

13:11 ant -Dclojure.jar=clj.jar

13:11 [java] Caused by: java.io.FileNotFoundException: Could not locate clojure/walk__init.class or clojure/walk.clj on classpath:

13:12 this is from where I got the sources: git://github.com/richhickey/clojure-contrib.git

13:12 stuartsierra: alinp: you have the 1.0 release of Clojure and the github master release of contrib

13:12 alinp: ah

13:12 so, there is a way to use the old version of clojure-contrib ?

13:12 or a stable version or something like that

13:12 stuartsierra: alinp: yes, checkout the "clojure-1.0-compatible" branch of contrib

13:13 alinp: ok, great

13:13 thanks

13:14 rhickey: stuartsierra: I guess one pre-req for contrib release with clojure is that there be some cordoning off of the code destined to be 1.1 while new work proceeds (akin to new vs master right now in core)

13:15 stuartsierra: The biggest problem is that different contrib libraries are at different levels of release-readiness.

13:16 rhickey: you could create a 1.1 branch and trim off any libs not ready

13:17 definitely needs discussing on clojure-dev

13:17 stuartsierra: ko

13:17 ok

13:49 chouser: Mmm...

13:49 * chouser settles in to read http://projectfortress.sun.com/Projects/Community/blog/ObjectOrientedTailRecursion

13:55 cemerick: rhickey, stuartsierra: FWIW, I'd be happy to help with the maven bits, if no one else is ready/willing.

13:55 ohpauleez: nice

13:56 rhickey: chouser: it's a refinement of the argument Will Clinger made at Lisp 50 at OOPSLA last year

13:57 the Cook paper he refers to is more interesting

13:57 chouser: heh

13:58 rhickey: something I'd just been reading while working on protocols

13:59 chouser: well, the tail-call argument is so frequently trotted out by people trying to avoid learning clojure, that I feel I need to understand its best-reasoned arguments.

14:00 oh! it's just what we saw with counting in ASeq

14:01 rhickey: right, that was Clinger's example recursive OO contains in Java

14:01 Steele's point can't be understood without reading Cook's paper

14:07 chouser: well, before reading Cooks paper, it seems to me that explicit trampoline methods in the interface, while relatively messy, would resolve this particular issue.

14:08 I guess I could implement it in clojure to demonstrate that point.

14:08 rhickey: chouser: but that's just admitting the point, you need that style of recursion to work

14:09 where you put it is a separate question

14:10 anyway, Cook's paper is a great survey of a set of interesting issues, even if his point is quite subtle

14:10 tomoj: which paper is this? sorry, just got here

14:11 rhickey: tomoj: http://www.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf

14:11 tomoj: thanks

14:12 rhickey: "While Java is not a pure object-oriented language, it is pos-

14:12 sible to program in a pure object-oriented style by obeying

14:12 the following rules""

14:12 tomoj: huh, unfortunately never had a class with that guy

14:12 rhickey: Classes only as constructors A class name may only be

14:12 used after the keyword new.

14:12 scottj: Anyone know of a good serious doc that outlines "these are the things you can't do in static typing systems", "this is why they're important and where they come up in writing real software", "this is how you have to work around it", and does it for a good typing system (I hear haskell or ocaml)? I'm fine w/ if there's a dynamic bent to it.

14:12 rhickey: No primitive equality The program must not use primitive equality (==).

14:13 In particular, classes may not be used as types to declare members, method arguments or return values. Only interfaces may be used as types. Also, classes may not be used in

14:13 casts or to test with instanceof.

14:13 chouser: the comments on the blog post itself as well as elsewhere suggest that explicit trampolines would be insufficient, that the only alternative to proper TCO is an explicit closed case statement covering all possible types.

14:14 rhickey: "This is generally considered good object-oriented style.

14:14 But what if you were forced to follow this style, because

14:14 the language you were using required it?"

14:15 stuartsierra: One thing I've wondered about deftype is how to define a type in which some fields are computed rather than stored.

14:16 chouser: stuartsierra: I *think* that's an abuse of deftype. Should use a protocol for that.

14:16 rhickey: stuartsierra: they are not fields then

14:16 stuartsierra: That's what I thought.

14:17 I like the separation of methods (protocols) from fields (types).

14:17 * rhickey recommends the Cook paper

14:17 * stuartsierra is reading it now.

14:23 konr: what was the function that could generate [0 1.5 3 4.5 6 ...]?

14:24 the-kenny: ,(iterate #(+ % 1.5) 0)

14:24 Chousuke: range?

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

14:24 Chousuke: ,(range 1 5 0.5)

14:24 clojurebot: (1 1.5 2.0 2.5 3.0 3.5 4.0 4.5)

14:24 the-kenny: ... that's easier :)

14:25 konr: thanks!

14:25 Chousuke: it can even generate exact fractions

14:25 fogus_: ,(take 5 (iterate #(+ % 1.5) 0))

14:25 clojurebot: (0 1.5 3.0 4.5 6.0)

14:25 Chousuke: ,(range 1 5 3/4)

14:25 clojurebot: (1 7/4 5/2 13/4 4 19/4)

14:25 lpetit: ,(doc range)

14:25 clojurebot: "([end] [start end] [start end step]); Returns a lazy seq of nums from start (inclusive) to end (exclusive), by step, where start defaults to 0 and step to 1."

14:25 lpetit: you cannot use range to produce an infinite lazy-seq of step <> 1

14:26 Chousuke: well, yeah.

14:26 scottj: when java heap space is exhausted from a dumb mistake (evaluating a infinite sequence), does it wait for a while to gc all that garbage so there's more space on the heap or does it keep all that dumb stuff around? (when you're in the repl)

14:26 Chousuke: in that case just use iterate.

14:35 stuartsierra: So real-world modeling should be done in terms of protocols, not types? E.g., we have an Employee protocol, operating on some (hidden) type representing the data that define an employee.

14:36 rhickey: stuartsierra: yes

14:36 stuartsierra: That's what I thought.

14:36 rhickey: stuartsierra: that's really the way Clojure's abstractions were designed

14:37 stuartsierra: But everybody gets it wrong by trying to model with defstruct.

14:37 rhickey: Just had onlu interfaces to represent them, and the RT.* functions bridged the abstractions beyond the interfaces, but was a closed system

14:38 stuartsierra: defstruct isn't a model - no functions

14:38 icey: Has anyone compiled a list of Clojure best-practices? It might be nice to have a short document that says "Hey, if you're modeling, use this. If you need concurrency, here are the use-cases and why." etc.

14:38 stuartsierra: I like this: "When implementing data abstractions, there are two important dimensions of extensibility. New representational variants can be added, or new operations can be added. This observation suggests it is natural to organize the behaviors into a matrix with representations on one axis and observations/actions on the other. Then extensibility can be viewed as adding a column or row to the matrix."

14:39 rhickey: protocols + deftype deliver exactly that

14:40 stuartsierra: yes!

14:40 icey: It's still evolving, mostly on IRC and the mailing list.

14:41 rhickey: I liked: "One conclusion you could draw from this analysis is that the untyped λ-calculus was the first object-oriented language."

14:41 lpetit: rhickey: so accessing a type's field from anywhere but the type's definition or the literal code of a protocol's type implementation should be considered a code smell

14:41 ?

14:43 stuartsierra: "academics tend to be more interested in correctness than flexibility. Finally, programming language researchers tend to work with data abstractions that are more natural as ADTs."

14:43 lpetit: yes, I think so.

14:43 rhickey: lpetit: no, because in order to make a type you don't own reach a protocol, you might need to access its fields. At that point it is acting as a concrete type. Consumers must understand that this is a tight binding. Otherwise concrete types will just expose their fields via a type-specific protocol and, well, that's not much different

14:45 but limiting the set of abstractions a type can reach to the original author is a known loser - see every OO language without open classes

14:45 Haskell gets by pretty well with type classes applied to types with fully exposed structure

14:45 lpetit: rhickey: didn't I write "or the literal code of a protocol's type implementation" ? :) that is : you can access fields of the type when you're extending the protocol for that type

14:46 rhickey: aren't we saying the same thing with different words ?

14:46 rhickey: lpetit: I thought you meant the implementations of protocols in the deftype

14:47 confused by "a protocol's type implementation"

14:47 lpetit: rhickey: I said both, right in the deftype, and in extends for that type, but not anywhere else in the code (or you're starting to be coupled)

14:47 rhickey: my bad, not native english speaker, sorry

14:47 stuartsierra: So fields of a type should rarely, if ever, be accessed outside of a protocol implementation.

14:48 rhickey: had you said extends I would have seen it, so yes - ok to access type in definitions of protocols, but also in type-specific helper functions to facilitate that

14:49 replaca: OK, API doc is up at http://richhickey.github.com/clojure/. Enjoy!

14:49 rhickey: stuartsierra: I;m not so focused on the prohibition than on the positive recommendation - modeling in terms of protocols will serve you well

14:49 replaca: thanks!

14:49 lpetit: replaca: now that's something, congrats !

14:50 rhickey: also via: http://clojure.org/api

14:50 cconstantine: replaca: very nice :)

14:50 replaca: still lots more work to do

14:50 thanks, all

14:50 lpetit: rhickey: wow, so the move is official ! But what is it: the doc for 1.0, or a fresh checkout of main ?

14:50 stuartsierra: rhickey: fair enough.

14:51 replaca: next up, support for leiningen (so your project can have pretty doc too)

14:51 lpetit: fress checkout of main

14:51 *fresh

14:52 stuartsierra: replaca: patch on #217 will add docstrings for core namespaces.

14:52 lpetit: rhickey: maybe you should keep the old 1.0 page around (and easily visible) for users of official 1.0 release ?

14:52 rhickey: stuartsierra: the bigger prohibitions are - don't use new, or '.', or the protocol interface other than in a Java extension

14:52 cemerick: replaca: far be it for me to offer design advice, but perhaps allowing the TOC to be separately scrollable would be a good tweak

14:53 lpetit: replaca: it would also be great to have the version of the "library" the doc applies to displayed. Though I don't know how to do this right now ...

14:53 replaca: stuartsierra: yeah, I saw you working on it. When it's applied, it will flow through naturally

14:53 stuartsierra: cool

14:54 djork: is there a setting to get full stack traces in the REPL?

14:54 stuartsierra: djork: no, but (.printStackTrace *e) will do it

14:54 replaca: cemerick, lpetit: good ideas. lpetit: I have that info, so I'll look at where to add it

14:54 djork: thanks

14:54 rhickey: stuartsierra: also avoid instance?, isa?, extends? and satisfies?

14:54 cemerick: replaca: it's amazing how much javadoc got right :-)

14:55 rhickey: my poor multimethods are such second class citizens now ;-)

14:55 stuartsierra: javadoc is one of the best doc systems around, only thing it lacks is a link to the source of each method.

14:56 rhickey: cemerick: not really, but they serve a different purpose. Some of the things I did for protocols might apply to multimethods

14:56 replaca: cemerick: yeah, though Java SE overwhelms it

14:56 lpetit: cemerick: not if you're still doing multiple dispatch, even a very controlled one just on types (think the classic Visitor pattern)

14:56 cemerick: Maybe I should have used two or three winks ;-)

14:57 rhickey: so one problem with the new docs it that they break all internal API links in the rest of clojure.org

14:57 of course the new docs have even better anchor tag support, so should be straightforward to map everything

14:59 lpetit: but double dispatch with protocols doesn't require the intrusion as does the Visitor pattern

15:00 i.e. can be open

15:00 lpetit: rhickey: ok, thanks to the oppenness of the system, but still a lot of boilerplate, no ?

15:00 openness

15:00 replaca: http://richhickey.github.com/clojure/&lt;namespace>-api.html#<namespace>/&lt;function-name>

15:00 e.g. http://richhickey.github.com/clojure/clojure.stacktrace-api.html#clojure.stacktrace/print-throwable

15:00 rhickey: lpetit: you'll still have x*y implementations

15:01 replaca: Now that I look at it, I'm surprised that the / after the # doesn't mess things up

15:01 though it works fine for me

15:01 rhickey: replaca: yes, I saw that - nice, hopefully not subject to wikispace's problems with some characters in anchors, lemme try...

15:03 * lpetit is wondering how this would really look like to implement visitor patterns with protocols ...

15:03 lpetit: ~protocols

15:03 clojurebot: http://clojure-log.n01se.net/date/2009-10-13.html#12:02

15:03 lpetit: oh, it's been redefined

15:03 rhickey: (defprotocol Addable (add [x y]))

15:04 replaca: rhickey: easy to make some extra translation rules if we need 'em

15:04 rhickey: (defprotocol AddableToInteger (add [x i]))

15:04 replaca: rhickey: just let me know

15:05 rhickey: (extend Integer Addable :as i (add [y] (addi y i))

15:05 should have been AddableToInteger (addi...

15:06 stuartsierra: rhickey: Is arithmetic a protocol?

15:06 rhickey: that style of double dispatch is how Clojure math used to work when it had it's own numbers

15:06 stuartsierra: oh, no

15:06 lpetit: rhickey: oh, btw, I missed an information: explicit or none "this" is what you've come up finally ?

15:06 rhickey: just an example for lpetit

15:06 lpetit: :as this

15:07 lpetit: pretty much what you wanted but no dots

15:07 lpetit: http://paste.lisp.org/display/91445#2

15:08 lpetit: rhickey: yes, the double dispatch is still needed, more like in Smalltalk I guess, but still need a double dispatch where it would not have been necessary with multimethods

15:08 rhickey: thanks

15:08 rhickey: replaca: looks like it works fine - I think the problem was with their anchors, not external ones

15:09 lpetit: yes, but it will be much faster than multimethods

15:09 lpetit: rhickey: of course, manual double dispatch is the price to pay for performance ...

15:10 replaca: rhickey: great!

15:10 rhickey: lpetit: I mean specifically manual double dispatch for this case will be faster than multimethods for this case

15:10 chouser: All the links to specific api docs from clojure.org pages are now broken.

15:10 lpetit: rhickey: yes

15:11 rhickey: I like the last version with :as

15:11 rhickey: chouser: yes, I just mentioned that

15:11 lpetit: I must leave, cu

15:11 chouser: sorry, behind on the log.

15:11 rhickey: chouser: fortunately the anchors are good in the new doc, and we won't have the hiccups with special characters

15:12 chouser: ok, excellent. Just need to walk through and fix the wiki pages?

15:13 rhickey: yup

15:16 chouser: time for some vimmin'

15:17 replaca: this is one of many things that makes me happy to be producing pure html rather than dealing with wiki stuff. In the old google code version, dealing with anchors was a major headache

15:18 drewr: what am I doing wrong here? http://gist.github.com/248466

15:18 I would expect (car (Cons 1 nil)) to return 1

15:19 also, is there a better way to model this?

15:20 "Consable" is admittedly lame

15:21 ohpauleez: drewr: you most likely want rest or last, not cdr

15:21 most likely rest

15:22 drewr: clojure uses first and rest, not car and cdr

15:22 hiredman: ohpauleez: he implementing his own

15:22 drewr: ohpauleez: clojure doesn't have cons cells :-)

15:22 ohpauleez: ahh nvm, you're defining the protocol for it

15:23 right, I see that now, I didn't see the defprotocol when I took a quick look

15:23 drewr: just using a known construct for experimenting

15:23 trying to compare to haskell

15:25 rhickey: drewr: returns 1 for me here

15:26 drewr: let me update my new branch then

15:26 I'm on dd152aed9c from Monday

15:27 stuartsierra: rhickey: I've put in patches for the remaining 1.1 tickets

15:28 rhickey: stuartsierra: awesome - thanks!

15:28 stuartsierra: My patch for #217 may be sufficient #216 as well.

15:28 drewr: restarting the jvm helped

15:28 I must've polluted the user ns

15:29 would have thought everything would have been redefined though

15:30 rhickey: stuartsierra: yes

15:30 stuartsierra: Need to improve error message on #215, working on that

15:30 rhickey: heh, was just going to say...

15:32 drewr: from the previous conversation, I guess I should name my protocols Cons and List instead

15:32 and then create concrete types?

15:34 then I lose the ability to say (Cons 1 nil), which is more natural

15:35 (deftype Cons [car cdr] [ICons] ...) perhaps

15:36 stuartsierra: rhickey: ok, better patch for #215

15:39 AWizzArd: clojurebot: max people

15:39 clojurebot: max people is 239

15:39 AWizzArd: :-)

15:40 chouser: stuartsierra: should that be System.err?

15:40 rhickey: AWizzArd: amazing, as too, almost 25k messages and 3k members on the group

15:40 angerman: what does "clojure.proxy.java.io.StringWriter cannot be cast to java.io.PrintWriter" want to tell me?!

15:41 stuartsierra: chouser: I thought about it, but so many IDE's hide System.err

15:42 angerman: You're using PrintWriter-specific functions inside with-out-str ?

15:42 chouser: stuartsierra: ok

15:43 AWizzArd: rhickey: yes, it is happening, and I congratulate you to this :)

15:43 rhickey: so, how many uses of ^ have we got in clojure itself?

15:43 stuartsierra: rhickey: I removed them; it was ~2 in core.clj, a dozen or so in xml.clj, and 1 in genclass.clj

15:43 rhickey: stuartsierra: cool, thanks

15:44 stuartsierra: Plus a couple in test-clojure, which I also removed

15:45 * drewr &

15:45 angerman: stuartsierra: I'm trying to ad an extention to c.c.d-s

15:45 http://gist.github.com/248498

15:45 and then eveluate (.readLine (random-access-reader "/Users/angerman/testfile"))

15:45 don't see the link :(

15:48 stuartsierra: angerman: first of all, you should use in-ns, since you're re-opening the namespace.

15:49 hiredman: is there a replacement for ^ yet?

15:49 stuartsierra: hiredman: (meta foo)

15:49 hiredman:

15:49 angerman: stuartsierra: ok. that's what I was wondering for anyway ;) thanks for clearing that up

15:49 hiredman: I meant a replacement reader macro

15:49 stuartsierra: I don't think there is meant to be; the goal is to use ^ in place of #^

15:50 hiredman: ok

15:51 prhlava1: hello, how to I upload files to the "files" section of the clojure google group? I need to upload fixes (as the code examples are broken for clojure 1.1.0), and AFAIK only managers can upload...

15:52 konr: Has anyone tried to play an mp3 song using clojure?

15:52 angerman: stuartsierra: but apart from the ns -> in-ns issue. is there any connection to the PrintWriter issue?

15:53 stuartsierra: angerman: Why are you binding *file*?

15:53 angerman: that was an initial, though, I plan to rewrite the macro. As *file* is probably the most stupid thing i could have come up with

15:54 stuartsierra: *file* is already used by Cloure

15:54 angerman: the idea to bind it to a var is to support some additional function.

15:54 stuartsierra: yes, saw that.

15:54 but the error arises without using the macro. just from (.readLine (random-access-reader "/Users/member:angerman/testfile"))

15:55 yey. for colloquy rewriting the path :(

15:56 stuartsierra: dunno; check the return type of random-access-reader

15:56 angerman: ohh.

15:56 Maybe it comes from the File call

15:57 tmountain: can someone remind me how to test if a vector contains a given element?

15:58 angerman: wow.

15:58 the-kenny: (get vec elem nil)

15:58 (Will return nil if elem is not present)

15:59 stuartsierra: tmountain: I think you want (some #{elem} vector)

15:59 (get vec elem nil) will return nil if elem is not a valid *index* into vector.

16:00 ,(get [:a :b :c] 2)

16:00 clojurebot: :c

16:00 the-kenny: agh

16:00 sorry :/

16:00 tmountain: stuartsierra: thanks!

16:00 angerman: stuartsierra: I'm sorry to have bugged you. Baiscally (File. (str "/User/angerman/" "testfile")) was causing the error :'(

16:00 and that wasn't even clear from my sample

16:00 stuartsierra: ok

16:01 djork: now this might not be everybody's taste, but... (c (defn int main [int argc, char** argv] (printf "%i args" argc) (return 1)))

16:01 :P

16:02 the-kenny: djork: I like this idea

16:02 :D

16:02 djork: scriptjure influenced it a lot

16:02 also supports objc

16:02 chouser: djork: very cool.

16:03 djork: will be on github soon enough

16:03 chouser: djork: any code in common between what you have and scriptjure?

16:03 djork: I borrowed the "emit" and "emit-special" approach but other than that it's pretty much from scratch

16:04 chouser: as in, could there be a library that makes it easy to write new foo-in-parens for various languages of foo?

16:04 stuartsierra: chouser: String Template!

16:04 djork: not a bad idea

16:04 it was shockingly easy, actually

16:05 so doing other languages would probably only improve this code

16:05 I took the liberty of adding things like let and using terms like ref and deref for pointers

16:05 ska2342: schaf5: hi, everything fine with your Emacs setup?

16:07 angerman: ok. Problem not solved

16:07 it's the (.readLine method on the RandomAccessFile) that cases clojure.proxy.java.io.StringWriter cannot be cast to java.io.PrintWriter

16:09 hiredman: angerman: you are wrapping something in a proxied StringWriter

16:12 prhlava1: ? ok, so no-one from "normal mortals" can upload to files section of clojure google group these days?

16:13 chouser: prhlava1: I'm pretty sure anyone subscribed to the group can upload a file

16:13 stuartsierra: But I would tend to discourage file uploads to the group anyway.

16:13 chouser: prhlava1: though that's not used for submitting patches or anything

16:14 stuartsierra: Probably most of the files currently there should be deleted.

16:14 angerman: hiredman: but how did I do that? so I have a RandomAccessFile object. and .readLine (according to the api) returns a String. now, even if I put that into a let binding, and output nil, e.g. (let [line (.readLine raf)] nil) i get that exceptions. It's really puzzeling me

16:14 prhlava1: cheers, but I can only see rename & delete now. What I have is (simple) examples of Clojure usage. Where is the better/preffered place to post this?

16:14 hiredman: angerman: lets see your code

16:15 prhlava1: ? wiki ?

16:17 angerman: hierdman http://gist.github.com/248532

16:18 hiredman: angerman: and what is the exception

16:19 chouser: prhlava1: you might consider http://en.wikibooks.org/wiki/Clojure_Programming which is linked right from clojure.org

16:19 hiredman: and what does file-str do?

16:19 angerman: clojure.proxy.java.io.StringWriter cannot be cast to java.io.PrintWriter [Thrown class java.lang.ClassCastException]

16:19 (file-str "...") converts the String into a File object, it's from c.c.duck-streams

16:19 stuartsierra: prhlava1: I would suggest just posting a message to the group for feedback first.

16:19 hiredman: ~def file-str

16:20 angerman: what is the result of the call to file-str?

16:21 angerman: hiredman: http://github.com/richhickey/clojure-contrib/blob/master/src/clojure/contrib/duck_streams.clj#L86 ; result is #<File /Users/angerman/upps.data.model>

16:21 RandomAccessFile API http://java.sun.com/javase/6/docs/api/java/io/RandomAccessFile.html

16:21 prhlava1: chouser: thank you, I am going to put it there. :-)

16:22 stuartsierra: and will post to the group first :-) .

16:23 hiredman: angerman: works fine here

16:23 angerman: O_O

16:23 hiredman: must be an issue in some other piece of your code

16:24 angerman: has clojure "1.1.0-alpha-SNAPSHOT" issues?

16:24 hiredman: this is alpha

16:24 angerman: hmm... maybe I shouldn't have just copied the project spec :(

16:25 hiredman: I wouldn't worry about clojure

16:25 find the bug in your code

16:25 is it possible that the code you pastebin'ed is not the exact code you running?

16:28 ska2342: Hi. The section on Maps on http://clojure.org/data_structures says that the sorted map has slower access than the hash-map, just "log(N)". Is it right to assume log_2(N) here?

16:29 chouser: ska2342: I think that's right

16:29 probably not log_e

16:29 ska2342: na, ln would be strange for trees :-)

16:29 chouser: sorted maps and sets are currently persistent red-black trees

16:30 ska2342: ok, I'll look their access up. Thanks for the info!

16:31 angerman: hiredman: I could swear I did run exactly that code. though, restarting swank, and the slime session twice. now it works.

16:31 o_O wtf?!

16:33 lpetit: Does the -i option of clojure.main accept lib names (which it would then search from the classpath) or just resource names ? Can the resource names be relative to the classpath ?

16:33 chouser: ska2342: I see left/right fields in Node classes in the code. I think it's safe to assume base 2

16:33 lpetit: s/search/require/

16:34 chouser: lpetit: from the --help: Paths may be absolute or relative in the filesystem or relative to classpath. Classpath-relative paths have prefix of @ or @/

16:34 ska2342: learned something new in O(log(N)) according to Landau notation docs the base doesn't matter. Funny though, that we keep on writing log_32 in Clojure-documents

16:34 hiredman: angerman: must have forgot to re-def something function after you changed something

16:34 lpetit: chouser: thanks

16:35 chouser: ska2342: it's because it matters in real life

16:35 just like constants do

16:35 ska2342: the reason for not caring about the base is that they differ only in a constant factor which doesn't grow. Obvious, but my university days are long gone

16:35 lpetit: chouser: oh yes, it was on the bottom of the help, I missed that, sorry

16:36 chouser: lpetit: np. it's a somewhat unusual use of @, easy to forget.

16:37 ericthorsen: FYI, with-bindings is defined both in clojure.core and clojure.main on the new branch

16:37 lpetit: chouser: I have a doubt, right now. If I use -i with @/some/ns.clj , will 'load use either the AOT compiled version either the .clj if fresher, or always the .clj ?

16:38 ericthorsen: thanks

16:38 chouser: lpetit: I don't know. I would hope use of ".clj" means it will always use the .clj file, but I don't know that for sure.

16:40 lpetit: chouser: well, I'm not sure it will be a problem for me, but I'm correcting a bug in ccw where I'd like to be close to the behaviour of requiring a ns. The closest is to use -i with @/ , but there may still be side effects I can't think of right now ...

16:40 requiring a ns at launch time

16:40 clojurebot: a is b

16:41 chouser: lpetit: you're not willing to use -e "(require 'foo)" ?

16:41 lpetit: chouser: I want to let the end user be able to specify -e for its own options ; is it possible to have several -e in the command line ?

16:41 chouser: lpetit: I think so

16:42 it is

16:42 lpetit: chouser: great, so

16:43 chouser: you're my hero

16:43 chouser: heh

16:43 thanks, glad to be of service. :-)

16:44 buy my book: <insert link here>

16:44 * chouser wishes there were a link to insert

16:44 angerman: ~source repeatedly

16:46 lpetit: chouser: if that's not "kitch" :-) : http://www.ezilon.com/e-cards/index.php?step=makecard_step1&ec_id=524&lang=

16:46 * lpetit wonders if "kitch" has the same meaning in english as in french ...

16:46 chouser: ha! juding by that image, I would say "yes"

16:49 lpetit: ;)

16:50 chouser: but finally, no, my user is able to select a predefined set of clojure files on the classpath to "launch" at startup, but those file do not necessarily have to be namespaces, so blindly using -e will not work 100% of the cases. I'll try with @/ for the moment ...

16:53 technomancy: lpetit: I've been thinking about having a -m argument that would be the equivalent of specifying a "main" class on the java command-line, but would work whether or not you'd done AOT

16:53 I guess that's a little different from what you're looking at

16:53 nm

16:55 lpetit: technomancy: really, pointing to a "main" class in java is pointing to some static method, equivalent to a function somewhere in a namespace in clojure. Though in java the "loading" of the class is also done at the same time, due to the naming conventions

16:56 angerman: nja.... RAF is slow

16:56 jkoppel: Running clojure-update broke my working Clojure/SLIME/Aquamacs setup

16:57 Now I'm having trouble getting it working again :(

16:57 lpetit: technomancy: so, the generalized equivalent, for clojure.main, could be to pass the fully qualified function name to -m, e.g. my.ns/toto (or why no my.ns/-main), with an implicit requirement for clojure.main to try to 'require my.ns first .. ?

16:57 technomancy: but yes, it's different from what I'm after :)

16:57 technomancy: lpetit: that would be great.

16:58 ska2342: jkoppel: did you do a new checkout of Slime, maybe from CVS? Current Slime-HEAD does not work with current swank-clojure. We had a discussion in the group on this.

16:58 technomancy: unfortunately I've already got a workaround, so my incentive to implement it is reduced. =)

16:58 lpetit: :)

17:00 jkoppel: whisper ska2342 Thanks, looking at the discussion

17:00 Gah, IRC fail

17:08 ska2342: chouser: I tried to find a publishing date for your book. Is there any public information on this?

17:08 chouser: ska2342: no, but there will be Real Soon Now. Haven't quite pinned down a title yet.

17:09 ska2342: chouser: I thought you were talking about "idiomatic clojure"?

17:09 chouser: ska2342: that's been the working title, yes.

17:09 shr3kst3r: ha, lein compile seems to have hung

17:10 ska2342: chouser: really looking forward to reading it

17:10 chouser: ska2342: fantastic! I'm really looking forward to being done writing it. :-)

17:11 ska2342: chouser: how many pages down, how many to go?

17:11 chouser: approx.

17:12 chouser: fogus_: how much of this are we talking about?

17:13 ska2342: well, I expect it to fluctuate a bit. Let's put it this way: Manning likes to have about 1/3 of it done for the early online access (MEAP), and we're expecting that to happen in the next couple weeks.

17:14 ska2342: chouser: thanks. Didn't mean to be impolite

17:14 chouser: no, it's not at all impolite. Thank you very much for your interest!

17:15 Joreji: Hey guys, is there some way to call a protected (final) supermethod from within a proxy?

17:15 chouser: I'm just not sure what I know (if anything) that's not meant to be shared.

17:15 ska2342: chouser: FULL ACK

17:15 chouser: Joreji: no good way. But, if you really need to, contrib java-utils wall-hack-method

17:18 Joreji: chouser: For some reason wall-hack-method does not find the method I am looking for. I think that is because the method I'd like to invoke gets "int" as its parameter, and I can only specify "Integer" as a parameter.

17:18 angerman: ahh. now it's speedy

17:18 Joreji: Is there some way to get the type of a native int? (i.e. not the object type)

17:18 Chousuke: Joreji: Integer/TYPE represents int

17:19 Joreji: ah, thanks!

17:21 supernovamaniac: can someone help me with a code problem that im having? (I just started clojure)

17:22 lisppaste8: dakorne pasted "is line-seq really that much slower than slurp?" at http://paste.lisp.org/display/91554

17:22 Chousuke: supernovamaniac: go ahead and ask.

17:23 dakrone: add type hints for starters

17:23 supernovamaniac: http://codepad.org/2iZyLOCS when i try (fun "5") or anything else for the string it gives me java.lang.ClassCastException: clojure.lang.PersistentHashSet cannot be casted to clojure.land.IDeref (NO_SOURCE_FILE:0) error

17:23 hiredman: dakrone: lazy seqs have overhead

17:23 dakrone: Chousuke: okay, I'll turn on warn-on-reflection

17:24 Chousuke: though most likely you need it only for the "%"

17:24 supernovamaniac: (i also declared (def visitors #{}) before i defined fun

17:24 hiredman: supernovamaniac: pick a simpler function to start with

17:24 supernovamaniac: kk

17:24 hiredman: (and write it instead of copy and pasting it_

17:25 _ato: supernovamaniac: did you forget to make visitors a ref?

17:25 ska2342: supernovamaniac: should that read (def visitors (ref #{}))?

17:25 angerman: ok, here we go: BufferedRandomAccessFile c.c.duck-streams extention http://gist.github.com/248603, required BufferedRandomAccessFile.java http://gist.github.com/248605

17:27 supernovamaniac_: I did write it

17:28 hiredman: angerman: I don't believe that whatever you say was required was required

17:29 angerman: hiredman: hmm. well. it does work without the BufferdRandomAccessFile, but using the bare RAF is very slow

17:29 _ato: SNM|Away: you absolutely sure you did (def visitors (ref #{})) not (def visitors #{})? cause that error is saying you're passing a hashmap to @ instead of a ref.

17:30 angerman: here's a sample of how I intended to use it http://gist.github.com/248618

17:30 hiredman: angerman: why would it be faster?

17:31 horrible

17:31 function calls with no arguments

17:31 atoms everywhere

17:31 gbt_: b

17:31 hiredman: state state state

17:31 :(

17:31 angerman: hiredman: because when reading line-wise, the RAF calls read over and over again which hit's the filesystem, and that's slow.

17:31 hiredman: I'm very open to any suggestions

17:33 hiredman: honestly I haven't been paying that close attention, so I don't have specific suggestions

17:33 twbray: Hmm... wondering if anyone here has looked at -Xprof output.

17:33 49.5% 3 + 101 org.tbray.read_lines$proc_block__24.invoke

17:33 hiredman: the one off use of atoms is icky

17:34 the reliance on some code from a blog post somewhere is icky

17:34 twbray: I have a function org.tbray.read-lines/proc-block

17:34 SNM|Away: ...dope

17:34 twbray: Looks to me like it's saying 49% of the time was in that function.

17:35 angerman: hiredman: well, I did read the code of the BRAF. And I have no clear idea how to keep track of the current line no.

17:35 though I have to admit, I don't really need the line-no right now. So the atom and swaps could just go away.

17:36 hiredman: angerman: if you must use the atom, at least lose the bindings

17:36 (binding is also ick)

17:36 angerman: i tried hard to get it to work with what c.c.d-s was providing

17:37 hiredman: macros that shadow are ick

17:37 angerman: but ran into a OutOfMemory wall fast

17:37 hiredman: etc, etc

17:37 never used duck-streams except when looking at problems other people had using

17:37 it

17:38 angerman: hiredman: as I said earlier. I'd love to get suggestions how to turn this into a very nicely fitting clojure code. But I'm unexperienced at best, if not totally lacking any ability to improve on that alot.

17:39 hiredman: I would at least follow the example of with-open and use a binding vector instead of just binding to *file*

17:39 angerman: ~source with-open

17:39 hiredman: (with-random-access-reader [file "/Users/angerman/upps.data.model"] ...)

17:39 j3ff86: is there a "replace value at index i with value x" function?

17:39 hiredman: (next-line file)

17:40 ,(assoc [1 2 3 4] 0 :a)

17:40 clojurebot: [:a 2 3 4]

17:40 j3ff86: ah cool, thanks

17:40 hiredman: the implicit parameter passing via binding is very annoying when you try to compose code

17:40 angerman: hiredman: yes, that looks better. I'll try to turn it tune it that way

17:41 if i drop the not (really) required line-no, it would become binding less

17:41 though I'm not sure how I'd loose the shadowing in the save-recursion

17:42 err save-excursion

17:43 hiredman: thanks for the input. Very much appreciated

17:44 Qvintvs: is there a simple way to convert a string "like this" to a list of symbols '(like this) ?

17:44 chouser: ,(map symbol (.split #"\s+" "like this"))

17:44 clojurebot: (like this)

17:45 hiredman: ,(import 'java.io.ByteArrayInputStream)

17:45 clojurebot: java.io.ByteArrayInputStream

17:46 hiredman: ,(import 'java.io.InputStreamReader)

17:46 clojurebot: well?

17:46 clojurebot: java.io.InputStreamReader

17:46 No entiendo

17:46 j3ff86: haha

17:46 hiredman: ,(doc read)

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

17:46 chouser: huh. we have cycle but not rotate?

17:47 hiredman: ,(import 'java.io PushbackReader BufferedReader)

17:47 clojurebot: java.lang.ClassNotFoundException: java.io

17:47 hiredman: ,(import '(java.io PushbackReader BufferedReader))

17:47 clojurebot: java.io.BufferedReader

17:48 hiredman: ,(letfn [(io [string] (-> string .getBytes ByteArrayInputStream. InputStreamReader. BufferedReader. PushbackReader.))] (io "foo"))

17:48 clojurebot: #<PushbackReader java.io.PushbackReader@1e2b2a6>

17:48 chouser: hm. rotate's a bit messy.

17:49 hiredman: ,(letfn [(io [string] (-> string .getBytes ByteArrayInputStream. InputStreamReader. BufferedReader. PushbackReader.))] (let [x (io "like this")] (take-while identtity (repeatedly #(read x)))))

17:49 clojurebot: java.lang.Exception: Unable to resolve symbol: identtity in this context

17:49 hiredman: ,(letfn [(io [string] (-> string .getBytes ByteArrayInputStream. InputStreamReader. BufferedReader. PushbackReader.))] (let [x (io "like this")] (take-while identity (repeatedly #(read x)))))

17:49 clojurebot: java.lang.RuntimeException: java.lang.Exception: EOF while reading

17:49 hiredman: bah

17:49 chouser: (defn rotate [[x & xs :as all]] (when (seq all) (concat xs [x])))

17:50 hiredman: :(

17:51 I guess

17:52 chouser: yeah, it's not exactly beautiful

17:53 neither seqs nor vectors like to do what 'rotate' tries to do.

17:58 duncanm: sigh

17:59 technomancy: i keep on having trouble with the slime installed from ELPA

19:23 defn: (areduce (into-array [1 2 3]) k 0 +)

19:24 obviously this is wrong... how do I use areduce?

19:24 chouser: (doc areduce)

19:24 clojurebot: "([a idx ret init expr]); Reduces an expression across an array a, using an index named idx, and return value named ret, initialized to init, setting ret to the evaluation of expr at each step, returning ret."

19:25 defn: i dont understand the index,init,return

19:26 why do we need an index or a return value

19:26 and what does it mean initialized to init

19:31 twbray: Grrr: java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.IFn

19:31 ohpauleez: twbray: wrap it in an anon function

19:31 hiredman: the exception is correct

19:32 twbray: hiredman: For some definition of "correct"

19:32 hiredman: well a Boolean cannot be cast to an IFn

19:33 such clarity is enviable

19:33 ohpauleez: right, and if you need to eval it like a function, you can return an anon/lambda function

19:33 defn: ,(doc array-map)

19:33 clojurebot: "([] [& keyvals]); Constructs an array-map."

19:33 twbray: hiredman: Not obvious why such a cast is unreasonable

19:34 Chousuke: twbray: Those are annoying :/

19:34 it basically just tells you you have a type error. :P

19:34 twbray: preferred idiom from getting a java.lang.Boolean into something I can feed into an (if?

19:35 hiredman: if takes Booleans

19:35 Chousuke: you might have extra parens somewhere.

19:36 hiredman: although

19:36 ,(if (Boolean. "false") :a :b)

19:36 clojurebot: :a

19:36 ohpauleez: clojure.lang.IFn is for if's? Not Function Interfaces?

19:36 hiredman: ohpauleez: no

19:36 Chousuke: ,(boolean (Boolean. "false"))

19:36 clojurebot: false

19:36 Chousuke: mmh.

19:37 twbray: ,(let [ trailing-nl (. "foo" endsWith "o") x (if trailing-nl "yes" "no") ] (println x))

19:37 clojurebot: yes

19:38 hiredman: ,(println (if (.endsWidth "foo" "o") "yes" "no"))

19:38 clojurebot: java.lang.IllegalArgumentException: No matching method found: endsWidth for class java.lang.String

19:38 hiredman: ,(println (if (.endsWith "foo" "o") "yes" "no"))

19:38 clojurebot: yes

19:39 * twbray is straining his eyes to figure out why that (apparent) same code is blowing up. Thanks for the input.

19:39 Chousuke: are you sure you haven't wrapped the predicate in extra parens?

19:40 hiredman: ,((true))

19:40 clojurebot: java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.IFn

19:41 Chousuke: it's probably pretty easy to write (if(somebool) ....) and then be completely blind to it if you're used to C-ish syntax.

19:42 itistoday: reading the monad tutorial for clojure: http://onclojure.com/2009/03/05/a-monad-tutorial-for-clojure-programmers-part-1/

19:42 hiredman: possible an unquoted list

19:42 ,(true 1 2 3)

19:42 clojurebot: java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.IFn

19:42 itistoday: in my repl m-bind seems to do something else

19:42 in the tutorial it's defined as: (defn m-bind [value function] (function value))

19:43 has its definition changed?

19:43 hiredman: are you sure?

19:43 Chousuke: m-bind is a bit special.

19:43 hiredman: possibly

19:43 ~def m-bind

19:43 clojurebot: It's greek to me.

19:43 itistoday: user=> (m-bind 1 (fn [a] (+ a 1)))

19:43 #<user$eval__75$fn__77 user$eval__75$fn__77@508aeb74>

19:43 ,(m-bind 1 (fn [a] (+ a 1)))

19:43 clojurebot: java.lang.Exception: Unable to resolve symbol: m-bind in this context

19:43 hiredman: clojurebot doesn't seem to thing it exists

19:44 itistoday: ,(use 'clojure.contrib.monads)

19:44 clojurebot: nil

19:44 hiredman: think

19:44 itistoday: ,(m-bind 1 (fn [a] (+ a 1)))

19:44 clojurebot: #<sandbox$eval__4712$fn__4714 sandbox$eval__4712$fn__4714@1984acb>

19:44 hiredman: grrr

19:44 itistoday: see?

19:44 in the tutorial it should return 2

19:44 hiredman: I wonder my m-bind was left out of the docstring gerneration

19:44 Chousuke: ~def m-bind

19:44 clojurebot: I don't understand.

19:44 Chousuke: hm

19:44 hiredman: ,((m-bind 1 (fn [a] (+ a 1))))

19:44 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--4718$fn

19:45 Chousuke: ~def defmonadfn

19:45 symbol macro stuff :/

19:46 hiredman: ~macros

19:46 clojurebot: Holy Crap.

19:46 Chousuke: I suppose that m-bind is specific to the identity monad.

19:46 itistoday: so... how can i learn monads now?

19:46 tutorial seems out of date :-p

19:47 Chousuke: continue with the tutorial for now.

19:47 I think that m-bind definition is just a simplified example

19:48 itistoday: Chousuke: the tutorial makes it seem like m-bind is "fundamental"

19:48 if i don't know what it's doing i can't follow the tutorial

19:48 Chousuke: it is, but each monad has its own definition of m-bind

19:48 (function value) is what it is for the identity monad

19:48 some other monad will have a different definition

19:50 itistoday: ,(identity-m 1 (fn [a] (+ a 1)))

19:50 clojurebot: #<sandbox$eval__4724$fn__4726 sandbox$eval__4724$fn__4726@1e513fb>

19:50 Chousuke: you probably need some function to extract the value from the monad. :)

19:51 itistoday: Chousuke: yeah... trying to figure out what that is...

19:51 Chousuke: as far as I understand monads, m-bind defines the "composition operation" for whatever class of operations the monad represents

19:51 for functions, it's just comp

19:51 for some other monad, it's... something else :P

19:51 itistoday: are monads used a lot in clojure?

19:52 Chousuke: Well, I wrote some monadic code once for fun

19:52 but not really.

19:52 itistoday: i've been reading about them for about an hour now

19:52 still have close to zero clue how they work

19:53 Chousuke: ,((identity-m 1 (fn [a] (+ a 1)) identity)

19:53 clojurebot: EOF while reading

19:53 Chousuke: ,((identity-m 1 (fn [a] (+ a 1))) identity)

19:53 clojurebot: java.lang.ClassCastException: clojure.core$identity__4959 cannot be cast to java.lang.Number

19:53 Chousuke: hmm

19:53 ,((identity-m 1 (fn [a] (+ a 1))) 3)

19:53 clojurebot: 4

19:53 Chousuke: curious. what's the value doing.

19:53 (doc identity-m)

19:53 clojurebot: "; Monad describing plain computations. This monad does in fact nothing at all. It is useful for testing, for combination with monad transformers, and for code that is parameterized with a monad."

19:54 itistoday: is there an updated guide on clojure monads somewhere?

19:55 i like how the source in the namespace declaration links to the post i'm reading currently... yet it's outdated :-\

19:55 maybe i'll send this guy an email

19:55 Chousuke: there's another definition of m-bind at the bottom of the page.

19:55 I don't see how that's outdated.

19:56 itistoday: Chousuke: what are you referring to?

19:56 Chousuke: itistoday: the m-bind for the maybe monad.

19:57 http://intensivesystems.net/tutorials/monads_101.html maybe take a look at this instead? :P

19:58 itistoday: Chousuke: thanks, i just noticed that in the comments too

19:58 i'll try to figure out based on this and the code you linked to

19:58 Chousuke: thanks!

19:58 i've gotta run

19:58 Chousuke: I should re-read those things too

19:58 itistoday: :-)

19:59 Chousuke: I think I know the why and what of monads but I am not yet enlightened. /:

20:06 twbray: ,(let [ trailing-nl (. "foo" endsWith "o") x (if trailing-nl "" "no") ] (println x))

20:06 clojurebot:

20:07 twbray: ,(let [ trailing-nl (. "foo" endsWith "o") x (if trailing-nl "" (last ["foo", "bar"])) ] (println x))

20:07 clojurebot:

20:09 timothypratley: ,(.endsWith "foo" "o")

20:09 clojurebot: true

20:13 qed: re-matches and re-find returns ["original string" "match"]

20:13 how do i just have it return match?

20:14 Chousuke: you can use java methods or just drop the first element from the vector :)

20:14 ohpauleez: or filter

20:14 qed: filter #(rest %)

20:14 sure, i just thought there might be a better way

20:18 timothypratley: qed: http://groups.google.com/group/clojure/msg/7578ed1f513df2b8 <-- this is my take

20:19 qed: thanks tm

20:19 tim

20:27 I have a list of strings, to concat them all I?

20:27 nevermind

20:27 ohpauleez: str

20:35 twbray: Hah... that exception on Boolean was in fact a stinky Clojure 1.0 bug, perfectly reproducible. WIll report. Had this huge vector, 50k long or more, and (last huge-vector) went nuts.

20:35 (get (dec (count huge-vector)) huge-vector) works fine.

20:36 qed: (reduce str (flatten (map #(rest %) (map #(re-find #".*\s+.*\s+(.*)\Z" %) (re-split #"\n" input-string))))))

20:36 there has got to be a better way to do that

20:36 Chousuke: #(rest %) == rest

20:37 qed: even across a list of lists Chousuke ?

20:37 Chousuke: across anything.

20:37 #(rest %) is just a function that calls rest with its argument.

20:38 qed: (("a" "b") ("c" "d"))

20:38 so you'd just (map rest ...)?

20:38 Chousuke: yeah

20:38 qed: ah ok, thanks

20:38 Chousuke: in general, #(foo %) can be reduced to foo, if foo is a function

20:39 qed: oh right, because it's only when we're doing something like #(foo 1 %) that it matters

20:39 where we have additional arguments, yes?

20:39 Chousuke: it's not like it changes anything though. it just removes noise

20:39 yeah

20:39 qed: nod

20:39 Chousuke: it's an easy mistake to make, though.

20:40 qed: yeah seems like kind of a bad habit more than anything

20:40 poor style i guess

20:40 Chousuke: yeah.

20:40 qed: here's one more regex question: \W is a non-word char right?

20:40 notallama: (partial foo 1) also works for that. whichever syntax you prefer.

20:40 Chousuke: it's so often that you need a #(foo whatever) in a map and a filter so your fingers learn to type #() :P

20:40 s/and/or

20:41 qed: for some reason #"0x(.*)\W" is matching past % and ('s

20:41 Chousuke: yeah that makes sense

20:41 chouser: qed: maybe (map second ...)

20:42 notallama: (.*) is greedy, isn't it?

20:42 chouser: qed: . will match % and (, so on it goes

20:42 notallama: right. * is greedy

20:43 maybe #"0x(\w*)" or #"0x(.*?)\W"

20:43 qed: thanks chouser

20:43 chouser: np

20:45 timothypratley: qed: how come you split them by line then flatten them again later? am I missing something important this does?

20:45 qed: just sloppiness, i'll likely switch that \Z to a \n

20:45 and get rid of the split

20:46 timothypratley: oh :) also I think reduce str would have poor performance compared to just apply str?

20:46 [just a guess though]

20:47 because it would construct a whole lot of intermediate strings

20:47 clojurebot: a is t

20:48 timothypratley: I'm probably wrong about that though as I'm sure apply would have to do similar work

20:48 forget I spoke!

20:57 ohpauleez: re: reduce vs apply, I think apply is usually faster. There's a blog post or tutorial somewhere

20:59 Chousuke: timothypratley: no, you're correct. If you use apply, then str will only need one StringBuilder for the whole seq

20:59 ohpauleez: there we go

21:00 timothypratley: oh, great! :)

21:55 polypus: ,'just-testing

21:55 clojurebot: just-testing

22:08 interferon: given a sequence of key names (e.g. ["a" "b") and a seq of [[1 2] [3 4]]), is there a built-in that will give me [ {"a" 1, "b" 2}, {"a" 3, "b" 4} ] ?

22:13 chouser: ,(let [keys ["a" "b"], val-vecs [[1 2] [3 4]]] (map #(into {} (map vector keys %)) val-vecs))

22:13 clojurebot: ({"a" 1, "b" 2} {"a" 3, "b" 4})

22:30 _ato: ,(map #(zipmap ["a" "b"] %) [[1 2] [3 4]])

22:30 clojurebot: ({"b" 2, "a" 1} {"b" 4, "a" 3})

22:33 interferon: thanks!

22:36 chouser: _ato: nice!

22:40 _ato: zipmap doesn't get enough love :)

22:43 defn: I need to find a good way to do this clojure example documentation -- a wiki + comments is what I'm going for here, but it's looking more and more like I'm going to need to build the whole thing from scratch

22:44 chouser: defn: on top of google wave, right?

22:44 :-)

22:44 defn: haha, nah

22:44 i just have this vision and im looking for stuff that's already been built, but there's not really anything out there

22:45 _ato: defn: what does it need to do that a regular wiki doesn't?

22:45 defn: i think mainly im just trying to get away from all the bells and whistles

22:46 i want it to behave more like an editable blog post

22:46 maybe im getting too hung up on the details

22:46 chouser: sounds like ... google wave

22:46 defn: i just have this picture in my head

22:46 chouser: touché

22:46 hiredman: ideally you'd like to break the editable parts up per function instead of per page

22:46 defn: correct

22:46 chouser: I don't think one function per page would be too few

22:47 hiredman: you have a block with the docstring text, and when you click on the block, it turns into a textarea

22:48 _ato: don't most wikis do some sort of subpage editing? eg you can edit just part of an article in wikipedia

22:49 defn: yeah i guess i just feel like giving this more of a face, something that looks more like an API documentation site and not a wiki, is my main goal

22:50 i want to go to the site and navigate it like it's a static site for the most part, with only tiny hints of the wiki poking out

22:50 the wikis out there right now tend to be so filled up with sidebars and sub-sidebars and sub-sub-sidebars, and 1400 links per article -- it's just noise

22:52 _ato: keep it simple to start with

22:52 you can add bells and whistles later

22:52 clojurebot: You will not become skynet

22:52 defn: haha

22:52 _ato: otherwise you'll never get it done

22:53 defn: _ato: yeah, i think my main concern here is not the functionality and such, it's just building something that works properly, and a wiki is not what it is, IMO

22:53 err by functionality i mean bells and whistles

22:54 _ato: oh well, best not to listen to me anyway. I still like the idea of git repository with text files and a script to spit out HTML. But I'm weird like that. :-P

22:54 _mst: sounds like my website :)

22:55 defn: _ato: i think you're right actually

22:55 that's the way im gonna go

22:56 tomoj: unconventional uses of git make me happy

22:56 * defn cheers

22:57 ohpauleez: nice work guys

22:57 interferon: how can i get the contents of a URL?

22:58 http-agent?

22:58 the examples in its docs don't work....there's no symbol called string in the http-agent namespac e

22:58 tomoj: if it's really just a URL you want, duck-streams will work I think

22:59 e.g. (slurp* "http://www.google.com/&quot;)

22:59 defn: quite handy

23:00 tomoj: if you want to do more http stuff there's also clojure-http-client

23:01 defn: http://github.com/defn/clojure-examples

23:01 interferon: tomoj: wow, thanks

23:01 slurp* is perfect

23:02 tomoj: defn: are you going to write the code involved in clojure? or use some other static-html-generated-from-git kinda thing?

23:02 defn: html-gen'd-from-git

23:03 just make blocks delimited by some special operator get pygmentized

23:03 and handle the rest as textile or something

23:04 tomoj: gotta have some kind of basic layout thing too right?

23:04 defn: yeah, definitely

23:04 interferon: is there a clojure analogue to activerecord?

23:05 tomoj: I wonder how jekyll is coming along lately

23:05 defn: not too good IMO

23:05 I'm not a fan of jekyll

23:06 but maybe i should give it a second chance

23:06 tomoj: I always loved the idea but never liked the implementation

23:06 defn: same here

23:06 tomoj: always felt like a huge pain in the ass

23:06 defn: glad im not the only one

23:06 i kind of felt like "am i stupid or something?"

23:06 none of the "edges" are clean

23:07 i dont know where one part of jekyll ends, and the next begins

23:08 it'd be sort of cool to make the clojure-examples my user page, and just use jekyll

23:08 but like you said, sort of a pain

23:09 tomoj: hmm.. writing a replacement for jekyll in clojure sounds like fun

23:10 * defn agreed :)

23:18 tomoj: I wonder if it's worth it to use pygments in clojure through jython

23:22 technomancy: defn: srsly; you can do static HTML generation in like a hundred lines of code; never saw the use for a generalized tool like that where everyone pitches in to add their pet feature

23:32 alexyk: anybody tried incanter here? I'm drooling over it, reading the site.

23:33 R in Clojure, now that's ambition.

23:33 ohpauleez: alexyk: just started looking at it today

23:33 alexyk: apparently it got some machine learning today

23:34 with Scala Processing, these two look good now for some serious stuff

23:34 and clojuratica of course

23:35 * alexyk finds himself singing the word clojuratica at various moments throughout the day for no reason

23:35 tomoj: alexyk: I don't see the commits

23:36 the machine learning ones I mean

23:36 alexyk: tomoj: it says FlightCaster merged its ML code into it on incanter-blog

23:36 or agreed to :)

23:36 tomoj: oh I see

23:37 * alexyk marvels at clojuratica: (math (FactorInteger 12345)) => [[3 1] [5 1] [823 1]]

23:37 alexyk: tomoj: are you playing with incanter?

23:38 tomoj: nope, but I am interested in machine learning

23:38 alexyk: tomoj: me too

23:39 tomoj: dang, why didn't I take a look at incanter before

23:39 I was trying all this matrix crap with ugly java libraries

23:41 alexyk: tomoj: clojuratica feeds of fantastic Mathematica matrix routines :)

23:42 tomoj: having mathematica embedded in my couchdb view server sounds awesome

23:42 ohpauleez: cool thing about incanter is that it wraps all of parallel colt, so you get all the math/algebra stuff too

23:42 not just the stat stuff

23:44 interferon: shouldn't (use '[clojure.contrib.str-utils2 :only (split trim) :rename {:replace :string-replace}]) give me a function named string-replace?

23:45 ohpauleez: interferon: is this on the repl or in a .clj file?

23:45 interferon: that's on the repl but ultimately i want it to work in a clj file. and it doesnt work there either :)

23:46 ohpauleez: http://richhickey.github.com/clojure-contrib/str-utils2-api.html

23:48 does it also fail in the file when you use require?

23:48 tomoj: (use '[clojure.contrib.str-utils2 :only (split trim replace) :rename {replace string-replace}])

23:49 (two things: add replace to the :only list, and use symbols in the :rename map)

23:52 interferon: ah i see

23:52 i had this kludge: (def string-replace clojure.contrib.str-utils2/replace)

23:53 but adding it to :only is much cleaner

23:53 thanks

23:53 also, can i share a clojure moment?

23:53 i was building a cache to prevent pulling data from a web service after it had already been filled

23:53 using refs, dosync, etc

23:53 then i realized memoize is built in

23:53 brilliant!

23:56 _ato: although the problem with memoize is you can't clear the cache, but yeah it's great for simple cases

Logging service provided by n01se.net