#clojure log - Apr 22 2009

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

0:04 brennanc: is there anything like find-doc but that has just the function names. It's really hard to read it when it outputs 20 pages

0:09 Jedi_Stannis: brennanc: not that I know of, shouldn't be too hard to write one

1:27 joha1: I'd like to use a syntax quote which doesn't try to resolve symbols. Is there any easy way of achieving this?

1:30 hiredman: uh, quote?

1:30 ,'(a b @(c d))

1:30 clojurebot: (a b (clojure.core/deref (c d)))

1:30 hiredman: or not

1:31 why do you want syntax quote?

1:33 joha1: building a function that generates code from a template, and I want to insert some values deep inside the vector. Perhaps there is a better way

1:35 hiredman: zippers

1:36 joha1: what i'm looking for is something like `(xxx (yyy ~zzz))) -> (xxx (yyy 3)), but without symbol resolution (assuming zzz = 3)

1:36 zippers, eh? I'll see what I can find

1:36 hiredman: clojure.zip

1:37 ,(require '[clojure.zip :as zip])

1:37 clojurebot: nil

1:37 hiredman: ,(zip/zip-vec '[a b c])

1:37 clojurebot: java.lang.Exception: No such var: zip/zip-vec

1:37 joha1: yes of course, that should work. I looked into zip just a few hours ago. thanks for the hint

1:37 hiredman: ,(-> '[a b c] zip/vec-zip zip/root)

1:37 clojurebot: java.lang.Exception: No such var: zip/vec-zip

1:38 hiredman: bah

1:39 ,(ns-interns (find-ns 'zip))

1:39 clojurebot: java.lang.NullPointerException

1:40 hiredman: ,(find-ns 'zip)

1:40 clojurebot: nil

1:40 hiredman: ,(ns-interns (find-ns 'clojure.zip))

1:40 clojurebot: {lefts #'clojure.zip/lefts, down #'clojure.zip/down, insert-left #'clojure.zip/insert-left, up #'clojure.zip/up, next #'clojure.zip/next, path #'clojure.zip/path, children #'clojure.zip/children, vector-zip #'clojure.zip/vector-zip, append-child #'clojure.zip/append-child, zipper #'clojure.zip/zipper, branch? #'clojure.zip/branch?, end? #'clojure.zip/end?, leftmost #'clojure.zip/leftmost, edit #'clojure.zip/edit, replace

1:40 hiredman: ,(-> '[a b c] zip/vector-zip zip/root)

1:40 clojurebot: [a b c]

1:40 hiredman: ,(-> '[a b c] zip/vector-zip zip/left zip/left zip/root)

1:40 clojurebot: java.lang.NullPointerException

1:41 hiredman: ,(-> '[a b c] zip/vector-zip zip/down zip/right zip/right (zip/replace 'z) zip/root)

1:41 clojurebot: [a b z]

2:06 hiredman: hmmm

2:06 that is three commits of autodocs for rev 687

2:08 replaca: yeah, cause I'm doing more work on the robot than people are doing work on contrib

2:08 and google's lame-ass wiki doesn't have an offline preview tool

2:09 I can do some stuff editing in the text box and hitting preview, but only so much

2:09 hiredman: I see

2:09 replaca: if you want too see the current product, go to http://code.google.com/p/clojure-contrib/wiki/OverviewOfContrib

2:10 but it still has a long way to go

2:10 Cark: wah nice stuff you're doing there

2:11 hiredman: nice

2:11 replaca: thx

2:11 dealing with the google wiki is kind of a bear

2:11 all sorts of limitations I wouldn't have in HTML :-(

2:15 Cark: ah funny, so many functions in there i implemented on my own

2:15 replaca: the problem has been that contrib is so opaque! I'm trying to fix that

2:16 noidi: that's great!

2:16 the fixing, not the opaqueness ;)

2:16 replaca: :-)

2:16 noidi: grepping the sources gets old fast

2:18 replaca: know whatchya mean

2:26 cp2: bah, i lost my uptime

6:49 emacsen: hey pjb3

8:50 kadaver: what are hashmaps internally? red-black-trees?

8:52 cemerick: kadaver: they're hash array mapped tries

8:52 the sorted hash maps are red-black trees, I think.

9:12 rhickey_: cemerick: right, sorted sets/maps are rb trees

9:22 cemerick: I haven't had a good brainfuck in a while, but implementing conses, lists, and map/reduce in terms of constraint propagation certainly qualifies...

10:49 postit: hi. i need a litte advice on which order to read some books

10:50 ["On Lisp","Practical Common Lisp","The Clojure book"]

10:51 Chouser: if you've already decided to learn Clojure, I think I'd start with the Clojure book

10:51 postit: i know the basics of lisp and functional programming

10:51 Chouser: I've never read PCL, so someone that has may have a different opinion

10:51 gnuvince: PCL is nothing really special and it's really tailored for Common Lisp

10:51 postit: do you know, does the clojure book just deal with syntax compared to other lisps?

10:52 gnuvince: I'd start with the Clojure book as well and if you need to, On Lisp.

10:52 postit: there's more to the Clojure book than just explanation of the syntax.

10:53 postit: ive decided on clojure, but i wanted to get a good understanding of the "lispy" way to design things too

10:53 arohner: postit: I would look at SICP then as well

10:53 gnuvince: postit: learn Clojure and read code by others

10:53 You'll pick it up.

10:54 arohner: but yeah, gnuvince is right. The clojure way of doing things is not exactly the same as CL or Scheme

10:54 Chouser: The Clojure Book is aims at both Lispers and Java'ers, so it explains how and why to do idiomatic Clojure

10:54 postit: i was wondering that to. if i could learn enough clojure from the "clojure book" to port other stuff as i read

10:55 Raynes: The Clojure book teaches Clojure very well. I learned out of it.

10:55 Chouser: yes, I think if you grok the clojure book material, "on lisp" will then still be useful and interesting.

10:55 postit: great, thanks guys!

11:04 dliebke: postit: the author of Programming Clojure, Stuart Halloway, also wrote some articles on porting examples from PCL to Clojure. http://blog.thinkrelevance.com/2008/9/16/pcl-clojure

11:04 rapido: ,(count [1 2 3])

11:04 clojurebot: 3

11:05 rapido: ~confluently persistent

11:05 clojurebot: It's greek to me.

11:18 postit: is emacs/slime the preferred dev environment (at least if you use emacs)

11:21 djpowell: it is pretty good. i just use emacs + clojure-mode + the built-in M-x inferior-lisp

11:22 clojuredev seems quite nice tho - i like the rainbow paren highlighting - anyway of doing that in emacs?

11:22 clojure-dev for eclipse i mean

11:25 arohner: postit: if you're already an emacs user, then yes it's the best environment

11:25 I use emacs + slime, though inferior lisp works pretty well

11:26 what does rainbow paren highlighting do?

11:27 Chousuke: different colour for each paren pair.

11:27 arohner: on my emacs, if you put your cursor on a paren, bracket or brace, it highlights the matching one

11:27 but only when the cursor is on a paren

11:27 and it highlights in a different color when there is no match

11:28 djpowell: the rainbow paren thing in clojure-dev just syntax colors parens different colors depending on the nesting level - not only when the cursor is near them

11:31 Chousuke: anyway, it's pointless to ask if emacs can do something. you need to ask "where's the plugin?"

11:33 Chouser: and then, "why does it only work with xemacs"?

11:33 arohner: emacswiki.org has a section on paren modes: http://www.emacswiki.org/emacs/CategoryParentheses

12:42 gnuvince: Can anyone answer a Java question?

12:43 danlarkin: waste of a question :)

12:43 gnuvince: Well, whatever

12:43 I compiled a bunch of Java files.

12:43 That worked

12:44 when I do: java ClassName, I get an error telling my that package/ClassName is a "wrong name"

12:45 Exact message: $ java BinRepParser

12:45 Exception in thread "main" java.lang.NoClassDefFoundError: BinRepParser (wrong name: hu/belicza/andras/bwhf/control/BinRepParser)

12:50 hiredman: gnuvince: what package is the class in?

12:51 gnuvince: hu.belicza.andras.bwhf.control

12:51 hiredman: you need to include the package

12:51 java hu.belicza.andras.bwhf.control.BinRepParser

12:51 gnuvince: ah<

12:52 thanks

12:52 brianh2: gnuvince: yeah. look @ this http://www.jarticles.com/package/package_eng.html

13:03 replaca: For those using emacs and slime, I strongly recommend paredit: http://mumble.net/~campbell/emacs/paredit.html, it's made for a huge leap in my programming happiness

13:03 (actually this is true even if you're not using slime)


13:14 * gnuvince smacks himself in the face

13:17 Lau_of_DK: Evening gents

13:21 technomancy: paredit is amazing.

13:22 it makes me hate editing non-lisp code.

13:23 gnuvince: technomancy: it's neat, but I could not get used to it.

13:23 I'd need to spend more time using it

13:29 technomancy: gnuvince: only in the long run

13:29 stuhood: gnuvince: it waits longer to optimize, and can use more memory on optimizations

13:29 danlarkin: -server will use hotspot

13:29 gnuvince: technomancy: the largest bottleneck (20%) was FileInputStream.read; removing -server fixed the problem.

13:30 p_l: JVM 1.7 is supposed to always use the same optimization model as -server

13:31 technomancy: gnuvince: are you talking about my extract-jar function?

13:33 gnuvince: technomancy: no, my Starcraft parser.

13:34 technomancy: gnuvince: that was really weird, because I almost sent an email to the mailing list last night asking why a function that used FileInputStream.read was slow.

13:34 I thought you were reading my mind.

13:34 dnolen: gnuvince is your project a one time run thing?

13:34 gnuvince: technomancy: I thought that I was nearly 20x slower than Java; turns out my Java was faulty and I wasn't analyzing any file. The number is now ~2.5-3x slower. And when I profiled both programs, -server was about twice as slow as -client

13:34 technomancy: nice

13:35 gnuvince: dnolen: currently, yes; give a bunch of files on the command line and it parses them.

13:36 dnolen: gnuvince: client speeds up startup time, server does really aggressive on the fly optimization. for long running processes server is usually better from what I understand.

13:36 technomancy: anyway, FileInputStream.read takes an array of bytes, but it won't accept a (make-array Byte 1000); it needs a (make-array Byte/TYPE 1000), but I have no idea what the difference is; I just copied it blindly. =)

13:37 gnuvince: technomancy: reference type vs value type. The first is a Byte[], the second a byte[] and apparently Java treats them differently.

13:38 technomancy: static typing saves the day again

13:39 who knows what horrors would occur if I sent it bytes when it wanted Bytes.

13:39 or vice versa

13:39 gnuvince: That's more of a "let's have primitives and objects" problem.

13:39 danlarkin: technomancy: this has nothing to do with static typing

13:39 it's strong typing vs weak typing, which is orthogonal to static vs dynamic

13:43 technomancy: oh, bytes are primitive, right.

13:46 Chousuke: having the primitive types is a nasty JVM wart, but I guess there at least used to be a reason to have them :/

13:46 gnuvince: I figure performance

13:47 Although it seems like the kind of thing the compiler should take care of.

13:48 Cark: well it really makes sense ti have a buffer made of real contiguous bytes

13:48 rather than byte objects or whatever

13:49 danlarkin: right, well it's an array of data structures rather than an array of pointers to classes with overhead etc

13:50 I agree it's a wart, but I /suppose/ I can see the rationale for having it

13:51 Cark: .net has the same thing m

13:51 more or less

13:51 so i guess that's pretty much the way to go

13:56 gnuvince: instance? seems like a pretty quick operation, am I right?

13:56 dnolen: what kind of machine does clojurebot run on?

14:00 Cark: clojurebot has been on strike these days

14:00 clojurebot: are you there ?

14:00 clojurebot: Huh?

14:02 cemerick: gnuvince: as quick as Class.isInstance :-)

14:03 gnuvince: cemerick: that's what I wanted to know, that seems to be pretty fast, right?

14:03 cemerick: for the job, it's all there is...

14:04 the speed of instance? is never going to be your bottleneck, if that's your question

14:04 gnuvince: cemerick: think again :)

14:04 rank self accum count trace method 1 37.54% 37.54% 3532 300290 java.lang.Class.isInstance 2 20.12% 57.66% 1893 300285 java.lang.Class.isInstance

14:04 3 17.94% 75.60% 1688 300292 java.lang.Class.isInstance

14:04 4 2.44% 78.04% 230 300308 java.io.FileInputStream.readBytes

14:04 well, the output didn't come out too nicely :-/

14:05 cemerick: can you paste the code that produces that mix?

14:05 gnuvince: http://bitbucket.org/gnuvince/clj-starcraft/src

14:05 check starcraft/replay/parse.clj

14:07 cemerick: where's the source of the instance? calls?

14:07 Cark: did you set the *wern-on-reflection* variable ?

14:07 warn

14:08 gnuvince: Cark: yes, there's none.

14:08 cemerick: most likely the call to vector? in read-field

14:11 cemerick: what's the overall runtime of the code that you profiled? I'm thinking if the overall runtime was very short, then instance? calls would likely still be reflective, and they could easily be a significant amount of runtime compared to a small disk read.

14:12 Cark: and the file must be in the cache too, so even faster to read

14:14 gnuvince: cemerick: ~110 seconds.

14:14 cemerick: it processed over a thousand files in that time frame.

14:16 Cark: what's the troughput ? how many megabytes in this time frame ?

14:17 gnuvince: Not a lot

14:17 151 MB

14:18 Each file is about 150 KB

14:18 Cark: i remember seeing somewhere a way to read several buffers in one go

14:18 an array of buffers with different types

14:19 gnuvince: Cark: my hands are tied by the Java lib I use.

14:19 I don't do the IO

14:19 I take the file

14:19 pass it off to a Java method

14:19 grab the ByteBuffer it returned

14:19 and work with that.

14:24 replaca: I will attest to isInstance? being a bottleneck, it's also the slowest thing in the pretty printer (although I do do it a lot).

14:24 Cark: ah too bad ...because with a FileChannel you have this method : read(ByteBuffer[] dsts)

14:24 gnuvince: replaca: I do a lot of vector? calls too.

14:24 Cark: you could then prepare wrapped buffers on top of that for each record type

14:25 for each field type i mean

14:25 gnuvince: I was thinking of changing my API slightly, but it seems that a comparaison of length or using try/catch are the same speed.

14:25 Cark: does your library do memory mapped files ?

14:26 gnuvince: Cark: not that I know of.

14:26 as far as I can tell (not really a Java programmer), the guy just opens a FileInputStream, reads, and returns a ByteBuffer.

14:26 Cark: anyways that's not your problem ...you need to do less at run time

14:27 gnuvince: yeah

14:27 I define a field in a record like this:

14:27 replaca: gnuvince: obviously the pretty printer needs to think about types a lot, cause it's making dynamic decisions based on type. BUt it does more work than it needs to. I'll need to deal with that when I revisit dispatch.

14:28 gnuvince: [:name 1 Byte] or [:name2 [1 Byte] Integer]. The vector? calls is to read the [1 Byte] and use the value as the number of Integers to read.

14:30 ,(let [xs (repeat 1000000 [[1] [2 3]])] (time (doseq [x xs] (if (= (count x) 1) 1 2))))

14:30 clojurebot: "Elapsed time: 3834.042 msecs"

14:30 gnuvince: ,(let [xs (repeat 1000000 [1 [2 3]])] (time (doseq [x xs] (if (vector? x) 2 1))))

14:30 clojurebot: "Elapsed time: 2458.336 msecs"

14:30 Cark: I would prepare that parsing before hand

14:31 you know build a lambda

14:31 there you're "parsing" the field spec during the actual processing

14:32 gnuvince: So turn these into lambdas instead of structs? http://bitbucket.org/gnuvince/clj-starcraft/src/tip/src/starcraft/replay/actions.clj

14:33 Cark: that's nice and clean as it is

14:33 but you could process this "DSL" before hand into lambdas to make it quicker to parse

14:36 gnuvince: To make sure I'm following, something like (compile-record [:name 1 Byte] [:name2 [1 Byte] Integer]) and that would return a fn that takes a ByteBuffer as its input?

14:37 Cark: right

14:38 gnuvince: Should that be a macro or a function?

14:38 cipher: hey gnuvince what are you writing there--quick description

14:39 gnuvince: cipher: it's a library that reads a Starcraft replay file and returns information about the game (players, races, map, etc.) as well as all the actions done by the players. Players use those kinds of programs to analyse their games.

14:40 cipher: neat.

14:49 gnuvince: Cark: do you think compile-field should be a function or a macro? I'd prefer a function, but I'm not sure if I can do it...

14:50 cipher: gnuvince: did you see my PM?

14:50 gnuvince: Oh, yes.

14:50 Thanks

14:51 cipher: Ok.

14:52 gnuvince: Did you guys to bnetd?

14:52 cipher: we have some involvement

14:52 had*

14:53 gnuvince: OK

14:53 Shame Vivendi pulled the plug on that project :(

14:53 technomancy: if I can't delete a file, should I raise an instance of Exception, or is there a more specific class I should use?

14:53 gnuvince: technomancy: IOException?

14:54 technomancy: gnuvince: thanks; that sounds better

14:55 what do you think: does a delete-file-recursively function belong in contrib?

14:56 http://p.hagelb.org/delete-file-recursively.html

15:03 gnuvince: Java doesn't already have a method for that?

15:03 technomancy: gnuvince: yeah, I was surprised, but I couldn't find one.

15:03 maybe they just hid it really well?

15:05 gnuvince: Python's shutil.rmtree ftw!

15:05 technomancy: FileUtils.rm_rcf

15:05 *rm_rf

15:05 Chouser: that's the kind of thing apache commons provides

15:05 leafw: technomancy, gnuvince: no, java does not have a recursive file deletion command. I guess it meant too much potential for damage.

15:06 technomancy: Chouser: yeah, but needing a 3rd-party dependency for something that basic is unfortunate.

15:06 leafw: at least it has File.mkdirs()

15:06 Chouser: technomancy: yeah

15:06 technomancy: this functionality is pretty important for unit testing

15:06 since you need to clean up after yourself

15:13 posted it to the mailing list

15:13 can create an issue/patch

15:13 cemerick: contrib *is* a 3rd party dependency (or dependencies). Much more pleasant API than 99% of the stuff out there, but it's a dependency nonetheless.

15:15 technomancy: every project I've worked with uses contrib already

15:15 so it's not an additional dependency for most

15:15 and it's not exactly 3rd-party

15:16 Chousuke: Chouser: what's the plan with your clojure-compiler? I see you haven't worked on it in a while

15:17 cemerick: my real point is that I think it'd be bad if stuff as generic (and as redundant w.r.t. existing libraries) as common IO operations starts leaking into contrib

15:20 Chouser: Chousuke: I've got a new job and a lot less time to work on Clojure stuff

15:20 so the plans the same, the pace is just way down

15:26 Chousuke: the code you have right now looks quite scary.

15:26 Chouser: hm. yeah, it's not gotten to the "clean up" phase yet. ;-)

15:43 jayfields: how can I return the first item from a collection that matches a predicate?

15:43 other than (first (filter pred coll))

15:43 kotarak: (seq-utils/find-first pred coll)

15:43 jayfields: cool. thanks.

15:44 I take it that's in contrib?

15:44 kotarak: Yup.

15:45 cemerick: Chouser: hey, congrats! Is it hush-hush, or do we get to leer at your new employer's wares?

15:45 Chouser: http://sentryds.com/

15:59 drewr: Chouser: Congrats!

16:00 Are you relocating to FL or working from IL/IN/wherever you are now?

16:01 Chouser: telecommuting full time now. We'll see how that goes. :-)

16:02 drewr: It's definitely bittersweet.

16:03 I love it today because it's 65 and I'm on my porch.

16:03 Chouser: ah, nice

16:09 triddell: functions are supposed to return early, right? I have a function that checks user security against authorized access roles. How should I return true after the first authorized match from a for list comphrehension?

16:10 are not supposed to return early that is

16:10 hiredman: (first (for ...))

16:11 arohner: triddell: for returns a lazy list that is realized as necessary

16:12 first "blocks" until the first element is returned from the lazy list

16:12 technomancy: cemerick: I don't follow.

16:12 what's wrong with that?

16:13 hiredman: ~literal [3] clojure

16:13 clojurebot: a very attractive hammer with a nice heft to it

16:13 hiredman: ^- now using fnparse

16:14 cemerick: technomancy: there's a lot of java libraries that do a lot of things. Reimplementing capabilities (especially inherently-stateful stuff like IO) in clojure is counterproductive overall, IMO. Not having to do that sort of thing is why having fantastic java interop is a Good Thing.

16:14 AWizzArd: ~ max people

16:14 clojurebot: max people is 164

16:15 triddell: arohner & hiredman: thanks

16:15 cemerick: been that way for a long time now

16:15 maybe clojurebot should track the date that the last max was reached

16:16 technomancy: cemerick: everyone's just going to re-implement it on their own anyway

16:16 AWizzArd: Well, it first was 164. Then Clojurebot forgot that number. After a few days it maxed out freshly on 162. But then I resetted it to 164 again. This is now a while ago.

16:16 technomancy: contrib is useful *because* it provides common I/O operations

16:17 AWizzArd: Until that max number of users there was a funny correlation between the numbers of the GG and the number of users in here. That correlation was: for each 10 new users in the GG we got one more user here.

16:17 cemerick: technomancy: really? At what point is pulling in well-tested libraries worthwhile, then?

16:17 technomancy: cemerick: rm -rf ain't exactly rocket science

16:17 AWizzArd: For some reason then the number of users here settled at +/- 125, while the GG got more users.

16:17 technomancy: you'd pull in 3rd-party libs for tricky things like joda for date parsing

16:18 cemerick: I'm sure someone will reimplement date parsing in clojure, too. I'm just wondering where the line gets drawn.

16:19 technomancy: cemerick: I did. but I realized it's a bad idea because it's impossible to get right.

16:19 so it didn't go in contrib.

16:19 but this is very, very different.

16:22 cemerick: To each his own, I guess. Reinventing any otherwise well-tested wheel without getting a significant return on that work just seems like a waste to me. *shrug*

16:23 technomancy: everybody who writes tests for code that writes to disk needs to delete whole directories. having to pull in an apache dependency to do this is... sad.

16:23 cemerick: not really -- we use ant to clean such temp spaces up.

16:24 technomancy: it's fewer lines of code to just implement the function than actual lines of XML necessary to express the dependency on apache commons io.

16:24 what about people who want to run tests from the REPL or from slime?

16:26 cemerick: that largely doesn't make sense to me either :-)

16:27 technomancy: if you have to launch a new instance every time you want to run the tests, it totally kills your rhythm since you've got to wait a few seconds for the JVM to boot.

16:28 which is OK for integration tests, but totally unacceptable for unit tests where you need instant feedback

16:29 see http://p.hagelb.org/06-clojure-test-mode.ogv

16:30 cemerick: like I said, to each his own. IMO, the REPL is phenomenal for interactive development, but any results from tests run in it aren't to be trusted -- too much opportunity for environment pollution that can skew them one way or another.

16:31 technomancy: yeah, it can't be your only method of testing; that's for sure.

16:31 but to avoid testing with it is to give up a valuable tool.

16:33 cemerick: I don't avoid it...but then, I can't think of a single REPL-friendly test we have that uses any temp files.

16:37 technomancy: maybe that's because you don't have an rm -rf that works from the repl. =)

16:37 cemerick: heh

16:38 nah, we just don't generate files *shrug*

16:38 if we did, I'd probably have to know my way around a shell way better than I do

16:39 * technomancy is a fan of self-contained tests

16:41 cemerick: everything we do is in-memory. GC cleans up after us :-)

16:42 technomancy: that's awesome if you can get away with it. =)

16:42 cemerick: I know :-D

16:58 emacsen: Can someone explain why I get an error that v doesn't resolve in the context: http://paste.lisp.org/display/79032

16:58 (that's not the final code, but it's the simplest version I have right now)

16:59 cemerick: emacsen: each arity must be wrapped in parens....

16:59 emacsen: cemerick, ah :)

17:00 cemerick: emacsen: http://paste.lisp.org/display/79032

17:00 kotarak: emacsen: and the (if (empty? ..) true) ( ... looks ominous. The if is basically useless.

17:00 emacsen: kotarak, the first one? you're probably right

17:01 otherwise, well you need it to return true sometime right?

17:01 cemerick, thx

17:01 kotarak: And (cond ... :else false) can also be left out. cond will return nil of no clause matched, so it will count as false.

17:02 emacsen: This also isn't the final code. It's going to do more than this, and will be lazy, but this is my first shot

17:02 kotarak, for this version, true. Later versions, no, but you're right in what you see

17:02 (because nil won't print as false in print I believe

17:05 hiredman: ~ticker JAVA

17:05 clojurebot: JAVA; -0.06

17:12 durka42: ~ticker ORCL

17:12 clojurebot: ORCL; -0.18

17:13 danlarkin: ~ticker CHINA

17:13 clojurebot: CHINA; +0.07

17:13 danlarkin: tada!

17:14 durka42: china?

17:14 p_l: ?

17:15 kotarak: ~ticker CON.F

17:15 clojurebot: java.io.IOException: Server returned HTTP response code: 400 for URL: http://www.google.com/finance/info?q=CON.F

17:15 durka42: CDC Corporation

17:15 (Public, NASDAQ:CHINA)

19:19 cads: hey, how do I use a namespace like clojure.set ? Neither (use clojure.set) or (use clojure/set) seem to work.

19:22 technomancy: (use 'clojure.set)

19:22 Raynes: use 'clojure.set

19:22 technomancy: You win this time. :(

19:22 technomancy: or even better put (:use [clojure.set]) in your ns directive

19:26 lisppaste8: Rayne pasted "imports and uses in namespace example for cads" at http://paste.lisp.org/display/79041

19:28 cads: why do we quote it?

19:28 wow, thanks for the example rayne

19:29 Raynes: cads: No problem.

19:29 technomancy: cads: because clojure.set is not bound to a value

19:29 Raynes: Quoting it keeps Clojure from trying to evaluate it.

19:29 technomancy: try just entering clojure.set into a repl; it doesn't mean anything

19:29 Raynes: ^ what he said.

19:29 cads: ah

19:30 technomancy: it's a symbol that is used to look up a namespace

19:30 which is different from a var that's used to look up a value

19:30 cads: I thought it would just pass the symbol in that case, but I remember the eval rules now

19:30 technomancy: cads: if use were a macro, it could do that

19:31 but use is a function

19:31 ns is a macro, which is why the evaluation rules are different there

19:37 cgrand: technomancy: hi! just noticed (while grepping irc logs) that you talked to cgrand-rec 2 days ago. cgrand-rec isn't me, it's a disconnected irssi logging the channel

19:37 technomancy: cgrand: ah; good to know. =)

19:38 I forgot what I said though.

19:38 cgrand: that you were trying the new enlive

19:39 technomancy: oh, I was "use"ing enlive and was wondering if it might be better not to export any vars that conflicted with clojure core.

19:39 unlink: What's the idiom for function definitions visible only inside another function?

19:39 technomancy: I've since decided to stick with "use :only" unless I have a reason not to

19:39 unlink: define them in let bindings

19:40 lisppaste8: technomancy pasted "let-binding a function for internal use; see target-file" at http://paste.lisp.org/display/79044

19:40 technomancy: unlink: ^^

19:41 unlink: boom

19:41 stuhood: you overwhelmed lisp.org with your awesome code, and it is throwing 500's...

19:41 technomancy: amazing

19:42 if you want something done right, you have to do it yourself: http://p.hagelb.org/extract-jar.html

19:42 dreish: Or http://gist.github.com/

19:42 technomancy: witness the power of Static Files

19:42 does gist do clojure highlighting?

19:42 dreish: Yes.

19:42 stuhood: yea

19:42 technomancy: cool

19:43 but I prefer static files. =)

19:43 dreish: They do Genshi highlighting.

19:43 stuhood: speaking of which, has anyone tried to get Clojure highlighting for Trac?

19:44 dreish: Maybe Genshi's not so obscure. (I'd never heard of it.) But anyway they cover something like 80 languages.

19:44 cgrand: technomancy: it bothers me to clash with clojure.core (eg CSS :not is 'but), I should rename 'complement back to 'complement-state (or 'negate or something else) and find another name for 'empty

19:45 technomancy: cgrand: clashing in private defns is not as big of a deal

19:45 unlink: So def always (re)binds in the global namespace, regardless of the scope?

19:46 technomancy: yeah. you shouldn't use it at outside toplevel scope unless you have a really good reason to do it though.

19:46 unlink: I guess I'm just used to scheme's scoping

19:46 which is different

19:47 technomancy: in fact, you shouldn't do it after your application has loaded at all

19:47 cgrand: technomancy: I want to keep them (complement and empty) public

19:47 technomancy: or at least be aware that you're stepping outside the Golden Path

19:47 unlink: right

19:48 I think (def a [x] (def b [x] (+ x 1)) (b x)) is nicer syntax than (def a [x] (let [b (fn [x] (+ x 1))] (b x))) though

19:48 s/\<def\>/&n

19:49 chessguy: so i'm thinking about an interesting little project, but i'd really need a freaking good REPL to play with it. anybody got any good suggestions? is SLIME as good as it gets?

19:49 dreish: letfn would be handy.

19:49 technomancy: chessguy: slime is rockin'

19:49 unlink: see: factorial with recur

19:49 technomancy: be sure you use M-x clojure-install to set it up though.

19:50 chessguy: hmm. i don't remember if that's how i installed it or not

19:50 how would i tell?

19:50 technomancy: chessguy: if you used it, you should have a call to clojure-slime-config somewhere in your personal .emacs setup.

19:51 chessguy: doesn't look like it

19:51 just (slime-setup)

19:51 technomancy: if you've already got it working you should be ok

19:51 chessguy: and slime-setup '(slime-repl)

19:51 technomancy: I was just thinking if you were going to install from scratch

19:51 unlink: Am I writing this idiomatically? http://gist.github.com/100173

19:52 dreish: unlink: Maybe (letfn [inner [n m] ...] (inner n 1)) ?

19:52 unlink: Oh, there exists a letfn?

19:52 dreish: Since January, yes.

19:52 chessguy: i don't get it, when i M-x slime, it says something about connecting to a server? what is it connecting to

19:52 unlink: oh

19:52 hot

19:53 technomancy: chessguy: a clojure instance is started that "serves" the Emacs instance over slime

19:53 there's a socket connection between the two

19:53 chessguy: oh, a JVM environment?

19:54 Raynes: technomancy: Stop being smarter than me. It's not nice. :|

19:54 technomancy: heh

19:54 chessguy: yeah, it's launched as a subprocess.

19:54 chessguy: cool

19:54 dreish: unlink: Or just ((fn inner [n m] ...) n 1), but the double open parens can cause crossed eyes.

19:56 chessguy: does slime store the result of the last evaluation anywhere that you can get at it?

19:56 e.g., for haskell, in ghci, if i do > 2 + 3, followed by > it == 5, i'd get true

19:56 technomancy: chessguy: probably, but I couldn't tell you off the top of my head. the slime manual is really good though.

19:56 chessguy: oh ok, i'll take a look

19:57 thanks

20:15 dysinger: why does this work (straight java)

20:15 sonian.archive.aws=> (String/format "%s ran %d miles today" (to-array ["Stu" 8]))

20:16 "Stu ran 8 miles today"

20:16 sonian.archive.aws=>

20:16 and this one doesn't

20:16 sonian.archive.aws=> (format "%s ran %d miles today" ["Stu" 8])

20:16 java.util.MissingFormatArgumentException: Format specifier 'd' (NO_SOURCE_FILE:0)

20:16 sonian.archive.aws=>

20:16 dreish: Remove the []

20:16 dysinger: I know that works

20:17 I am saying the internal code for (format converts to a java array and passes it to java like the 1st call

20:17 dreish: The & turns the remaining args into a sequence.

20:18 dysinger: ~(format "%s ran %d miles today" (seq ["Stu" 8]))

20:18 clojurebot: format is http://github.com/tomfaulhaber/cl-format/tree/master

20:18 dysinger: oops

20:18 hiredman: dysinger: it works that way because [] does not make an array

20:18 dysinger: ,(format "%s ran %d miles today" (seq ["Stu" 8]))

20:18 clojurebot: java.util.MissingFormatArgumentException: Format specifier 'd'

20:19 dreish: dysinger: Why would you expect that to work?

20:19 hiredman: [] makes a persistent vector, which java's format doesn't know anything about

20:19 dreish: args now contains (("Stu" 8)) -- a seq with only one thing in it.

20:19 dysinger: right

20:19 dreish: That thing happens to be another seq, but it needs _two_ things.

20:19 Not _one_ seq.

20:20 dysinger: so the only way to format with a seq / vector / set is to use apply

20:20 dreish: Sure, or you could do String/format yourself I guess.

20:21 dysinger: y

20:21 dreish: If you do it a lot, maybe write a formatseq?

20:21 dysinger: true

20:21 dreish: I'd probably apply. It seems cleaner somehow.

20:21 dysinger: y it works fine

20:21 just curious

20:22 the & args turning into a seq explains the magic

20:22 dreish: k

20:23 dysinger: sorry for the bone-headed questions - I've been seriously programming clojure for 3 weeks.

20:23 :)

20:23 dreish: np

20:24 For some reason I thought you'd been around for months, actually.

20:24 dysinger: I learn quick - but sometimes ask dumb questions

20:24 and I did Java for 10 years and some lisp already :)

20:25 am totally loving it though

20:25 I rewrote some java today and shrank it 10:1

20:25 dreish: It is nice.

20:27 Raynes: dysinger: Good evening.

20:27 dreish: Whenever I have to make a change to the existing Java part of my pet project, it's painful to have to deal with that language.

20:27 dysinger: heya Raynes

20:38 chessguy: hmm, i don't get how to use slime presentations to copy the previous results to the prompt

20:42 gnuvince_: Sometimes I hate dynamic typing...

20:50 chessguy: i'm reading http://common-lisp.net/project/slime/doc/html/Presentations.html and it says "Using standard Emacs commands, the presentation can be copied to a new input in the REPL", but it doesn't say WHAT standard Emacs commands

20:53 technomancy: chessguy_: M-p

20:53 slashus2: try them all

20:54 chessguy: M-p takes me to the last one that matches what i've typed so far

20:55 technomancy: C-h m will show you what bindings are active for the current mode

20:59 chessguy: none of those seem to do what i want

21:03 *sigh*

21:16 unlink: How do I pattern match based on whether the argument to a function was a vector or a scalar?

21:16 durka42: you could do something with multimethods

21:17 or you could just put an if statement at the top of the function

21:17 dreish: Destructuring isn't the same as pattern matching, in that it can't really do what you're asking for.

21:18 unlink: oh

21:18 hiredman: well

21:18 it can

21:18 unlink: That was basically the #1 use case of pattern matching for me

21:19 hiredman: (defmulti f vector?)

21:19 (defmethod f true [arg] do vector stuff)

21:19 (defmethod f false [arg] do scalar stuff)

21:19 dreish: hiredman: That's a multimethod, as durka42 suggested.

21:20 unlink: e.g. fun g(a, b, c) = case a of [] => (round c) = 1 | 1::xs => not (null xs) | _ => b

21:22 dreish: I'm surprised no one has written a defpattern macro for contrib yet.

21:23 unlink: Obviously (fn ([[a b & c]] ...) ([_] ...)) doesn't work.

21:28 Jedi_Stannis: what are you trying to do?

21:31 technomancy: chessguy: it might be a clojure repl feature rather than a slime feature

21:50 chessguy: Jedi_Stannis, a simple example: if i've done user> (+ 2 3)

21:50 and gotten back 5

21:51 i want to be able to do user> (+ 5

21:51 and then hit some combo

21:51 to put the 5 from the previous evaluation into what i'm currently typing

21:51 Jedi_Stannis: *1

21:51 ?

21:52 ,(doc *1)

21:52 clojurebot: "; bound in a repl thread to the most recent value printed"

21:52 chessguy: oh cool!

21:52 Jedi_Stannis: ,(doc *2)

21:52 clojurebot: "; bound in a repl thread to the second most recent value printed"

21:53 Jedi_Stannis: ,(doc *3)

21:53 clojurebot: "; bound in a repl thread to the third most recent value printed"

21:53 chessguy: ,(doc *42)

21:53 clojurebot: java.lang.Exception: Unable to resolve var: *42 in this context

21:53 Jedi_Stannis: lol

21:53 only 1 - 3

21:53 chessguy: just checking :)

21:53 ,(doc *4)

21:53 clojurebot: java.lang.Exception: Unable to resolve var: *4 in this context

21:53 chessguy: boo

21:53 ok, better than nothing

21:53 thanks!

21:54 Jedi_Stannis: no problem

22:00 cipher: can someone explain how to use the -> form

22:01 unlink: I guess one simple example of what I'm trying to do would be a basic implementation of map, where it accepts two parameters, a function and a list. I would like to pattern match on whether the list is empty or not; in the former case, map returns (); in the latter case, it retuns (cons (f x) (map f xs))

22:01 Jedi_Stannis: ,(macroexpand '(-> 1 (+ 2) (* 3))

22:01 clojurebot: EOF while reading

22:01 Jedi_Stannis: ,(macroexpand '(-> 1 (+ 2) (* 3)))

22:01 clojurebot: (* (clojure.core/-> 1 (+ 2)) 3)

22:02 Jedi_Stannis: bleh, doesn't expand all the way:( * (+ 1 2) 3)

22:03 unlink: you can't really pattern match in clojure like you can in haskell or other functional languages.... need to write a conditional or write some sort of pattern matching macro

22:03 unlink: oh.

22:04 Good excuse to learn reader macros, I suppose.

22:04 Jedi_Stannis: cipher: so if you want an imperative style, you can start with your data structure and list the functions you want applied to it

22:04 unlink: umm, clojure also doesn't have reader macros

22:05 ,(-> {} (assoc :a 1) (assoc :b 2) (assoc :c 3))

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

22:05 Cark: hey how is it imperative to start with data structures ?

22:05 unlink: I guess regular macros might be powerful enough?

22:05 Jedi_Stannis: yeah, it just will change the way you write it

22:09 cipher: so I can almost think of it like doto?

22:09 unlink: Thanks, Jedi_Stannis.

22:12 Jedi_Stannis: cipher: similar to doto, except instead of it applying methods to an object for side effects, it passes the result from one function call to the next, building up the result

22:13 cipher: got it. alright thanks.

22:13 Jedi_Stannis: cark: its not really imperative, just lets you write things in the order they happen, instead of reverse order by having to nest all the calls

22:15 your welcome

22:17 emacsen: I've just learned the comparison operators < and > don't work on strings

22:17 Is there a deep reason for this?

22:17 Cark: i'll take the bait : what do you expect from the < operator on strings ?

22:17 Chouser: I think performance of numeric operations are generally cited.

22:18 Cark: byte by byte comparison ? character wise comparison ? what collating order then ?

22:18 emacsen: Chouser, right but shouldn't < be defmulti-ed

22:18 durka42: emacsen: exactly. that would be slow(er)

22:18 emacsen: okay, so is there a generic function for this?

22:18 gnuvince_: Cark: by the way, thanks for the suggestion of "compiling" my records this afternoon. I'm doing some rough tests here, but performance went from 115 seconds on my home PC for 1000+ files to ~90

22:19 lambda++

22:19 Cark: that's not as good as i imagined gnuvince ='(

22:19 gnuvince_: Cark: well it is the first time I've done something like this, so I may have not been as efficient as I could.

22:19 emacsen: in other languages you can compare numbers, or dates, or strings and they use some inferior operator overloading. Is there a function I can use generically?

22:19 gnuvince_: Cark: I'll push the code in a little while if you want to see the code.

22:20 Cark: gnuvince : i'd love to

22:20 emacsen : to me it does not make sense to use the same operator for strings and for numbers

22:21 is some kenji symbol smaller or bigger than the letter B ?

22:21 unlink: Is there a shorthand for (let [x (cond ...)] (if (nil? x) (...) x))

22:21 Or maybe something more robust which lets me return nil from cond and still not evaluate the second (...)

22:22 emacsen: Cark, Maybe. But then I guess I have to figure out the right function

22:22 and I won't know that ahead of time

22:22 Cark: emacsen : you have the full java stack at your fingertips

22:22 and pretty good docs too =)

22:22 emacsen: Cark, that's like saying "You have as much mud as you want to build the house of your dreams!"

22:23 durka42: :)

22:23 Cark: maybe but that's efficient mud you dobn't need to recreate !

22:23 durka42: unlink: if-let maybe?

22:24 unlink: I guess like cond-else in scheme

22:25 Cark: ,you want some kind of when-not-let ?

22:25 clojurebot: java.lang.Exception: Unable to resolve symbol: you in this context

22:28 unlink: After some googling it appears that (cond) excepts :else in place of a condition.

22:29 gnuvince_: Cark: http://bitbucket.org/gnuvince/clj-starcraft/src/tip/src/starcraft/replay/parse.clj#cl-41

22:29 emacsen: okay, one last very dumb question. Why, if we have namespaces, can't I reuse names from the core?

22:29 Cark: gnuvince : checking it now

22:29 emacsen: eg I can't use "val" in my functions as an argument because it's already used in the core

22:30 Chouser: emacsen: you can, but you have to explicitly exclude those core names from being referred into your new namespace

22:30 Cark: emacsen : you can but you have to specifically import core

22:30 hiredman: ,((fn [val] val) 1)

22:30 clojurebot: 1

22:30 emacsen: Wow both those options suck ;)

22:31 Cark: that's the same option =P

22:31 emacsen: Then it sucks twice as hard ;)

22:31 unlink: How is recur not 100% equivalent to using the name of the function in a tail position recursive call?

22:31 Cark: that's CLish

22:32 unlink: emacsen: I agree, the semantics are very surprising.

22:32 hiredman: unlink: cond does not take :else, :else is just convient because it evals to not nil (true) all the time so if it is reached it's clause will run

22:32 unlink: hiredman: oh, of course.

22:32 Cark: gnuvince : you still have the lookup in read-field

22:32 hiredman: ,(cond (= 1 0) :foo 1 :bar)

22:32 clojurebot: :bar

22:32 emacsen: unlink, well it's just I have been writing code lately and finding out quickly that I need to change a lot variable names because they're already in the core

22:33 "val" has always been my default single value argument name

22:33 unlink: emacsen: I ran into the gotcha a few times today as well.

22:33 emacsen: and "seq" seemed like a good name for an argument which was a sequence passed in :)

22:33 unlink: I think the idiom is "coll" for that.

22:33 emacsen: fair nuff

22:33 gnuvince_: Cark: the lookup to select the getting function?

22:33 Cark: right

22:34 unlink: Ok, I guess except for the use of recur with loop.

22:34 Cark: gnuvince : you could have a make-read-field function, then in compile record you prepare that function, and just use it in the returned lambda

22:35 i usually name these lamba compiling functions like this : make-frobnicator-fn

22:35 as this is not really compiling

22:35 gnuvince_: ok

22:36 Cark: so that's one less lookup for you right there ...though i beleive this should not make a huge difference

22:36 gnuvince_: As for a make-read-field function, won't I need to lookup the type anyway to select the right one?

22:37 Cark: well the type is already given in the field-specs right ?

22:37 gnuvince_: Yes

22:37 Cark: mhh let me make a paste with some untested code

22:37 lisppaste8: url?

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

22:40 cark pasted "untitled" at http://paste.lisp.org/display/79053

22:40 Cark: that's only to give the idea

22:40 and is actually completely wrong =/

22:41 you want to prepare a list of functions

22:41 gnuvince_: I'll give it a whirl

22:41 Cark: very wrong i put it in the returned lambda =P

22:41 cipher: ,(make-array (. Byte TYPE) [1 2 3])

22:41 clojurebot: java.lang.ClassCastException: clojure.lang.LazilyPersistentVector cannot be cast to java.lang.Character

22:41 Cark: let me anotate again

22:42 cipher: What's the right way to do that?

22:43 Chouser: ,(into-array Byte/TYPE (map byte [1 2 3]))

22:43 clojurebot: #<byte[] [B@1eab16b>

22:44 lisppaste8: cark annotated #79053 "untitled" at http://paste.lisp.org/display/79053#1

22:44 Cark: that's more like it

22:45 lisppaste8: cark annotated #79053 "untitled" at http://paste.lisp.org/display/79053#2

22:46 Cark: gnih

22:46 gnuvince_: All right

22:46 I'll test it out tomorrow at work when I need to pretend like I'm working

22:47 Cark: disregard the last one, i need to edit in emacs instead of firefox =P

22:47 unlink: Am I missing some clojure programming construct which allows me to avoid writing a cond like this? http://gist.github.com/100253

22:47 gnuvince_: hehe ;)

22:48 ,(map even? [1 2 3 4 5 6])

22:48 clojurebot: (false true false true false true)

22:48 gnuvince_: ,(mapgilter even? [1 2 3 4 5 6])

22:48 clojurebot: java.lang.Exception: Unable to resolve symbol: mapgilter in this context

22:48 gnuvince_: ,(filter even? [1 2 3 4 5 6])

22:48 clojurebot: (2 4 6)

22:49 unlink: Ok, yes, I know it is a bit contrived.

22:49 gnuvince_: unlink: the seq functions are prefered.

22:50 unlink: But the point of the function is not to return the even elements in the list, but rather the elements in even positions.

22:50 lisppaste8: cark annotated #79053 "untitled" at http://paste.lisp.org/display/79053#3

22:50 Cark: gnuvince : notice on how the vector? call is now out of the loop

22:51 err though the first bracnh of the size if is wrong, you get the idea

22:52 gnuvince_: Yeah

22:52 I've bookmarked the page

22:52 Cark: pretty hard to give a solution without rewriting a whole bunch of it

22:52 gnuvince_: One thing I've had to do to get more performance is to close over data instead of using vars.

22:52 unlink: In Haskell, you would do: evens [] = []; evens x = []; evens (x:y:xs) = y:evens xs

22:52 Cark: well, the var there is only called once

22:53 not inside the loop

22:53 gnuvince_: Won't it be called every time I call make-read-field-fn?

22:54 Cark: yes, but you could do this a single time at compile time

22:54 or once a file

22:54 gnuvince_: unlink: you want only the even indexed elements?

22:54 Cark: once for every field in every record type

22:54 unlink: gnuvince: Yes.

22:54 gnuvince: starting at 1

22:55 gnuvince_: ,(take-nth 2 [1 2 3 4 5 6])

22:55 clojurebot: (1 3 5)

22:55 gnuvince_: This starts at zero however.

22:55 ,(take-nth 2 (cons nil [1 2 3 4 5 6]))

22:55 clojurebot: (nil 2 4 6)

22:55 gnuvince_: meh

22:55 * gnuvince_ is dumb tonight

22:56 unlink: I'm actually looking for a way to mimic the Haskell construction.

22:56 gnuvince_: Cark: is there any good literature on using lambdas like that to optimize code and "compile" code?

22:56 unlink: Clojure doesn't have pattern matching, so you're pretty much out of luck there.

22:57 Go with the length

22:57 unlink: So (cond (nil? ...)) is the right construction?

22:57 Cark: i don't know, i learned this reading the source code of cl-pcre (the common lisp regex compiler made by edi weitz which is faster than perl)

22:57 unlink: @gnuvince_

22:58 gnuvince_: Cark: ok.

22:59 Cark: gnuvince : too bad you don't have some test files in there, i would give it a go =)

22:59 lisppaste8: gnuvince pasted "evens" at http://paste.lisp.org/display/79054

22:59 gnuvince_: Cark: I have a script to get a bunch of them

23:00 lisppaste8: gnuvince pasted "Download Starcraft replay files" at http://paste.lisp.org/display/79055

23:00 unlink: gnuvince_: That doesn't lazily iterate the list, though.

23:01 s/list/collection

23:01 gnuvince_: Cark: this is screen scrapping, so hopefully they didn't change their entire site.

23:01 unlink: it's not too hard to change that

23:01 Cark: is this python ?

23:02 unlink: gnuvince_: you mean and still not check whether car and cadr are nil?

23:04 gnuvince_: Cark: yes.

23:04 Cark: i think i'll just download a couple files manually =P

23:06 gnuvince_: Cark: wait

23:06 I'll put up an archive on a webserver

23:07 lisppaste8: gnuvince annotated #79054 "lazy evens" at http://paste.lisp.org/display/79054#1

23:07 unlink: ok, thanks, I have to run

23:10 gnuvince_: Cark http://www.studio-cdd.com/replays.tar.gz

23:10 about 1050 files

23:10 Cark: quite a big file =)

23:11 gnuvince_: yeah

23:21 replaca: good evening, clojurians

23:21 Cark: hello replaca

23:51 are you still there gnuvince ?

23:54 replaca: this is the time of night when tumbleweeds begin to roll through #clojure

23:55 Cark: hehe

Logging service provided by n01se.net