#clojure log - Jul 17 2011

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

0:25 Blackfoot: can i update a hierarchy used in defmulti after the defmulti call?

0:28 oh i see :hierarchy can be a ref. nm

0:45 amalloy: Blackfoot: see ##(doc derive). if you want to *remove* links in the hierarchy tree, that's probably not a good idea

0:45 lazybot: ⇒ "([tag parent] [h tag parent]); Establishes a parent/child relationship between parent and tag. Parent must be a namespace-qualified symbol or keyword and child can be either a namespace-qualified symbol or keyword or a class. h must be a hierarchy obtained from mak... http://gist.github.com/1087197

0:49 Blackfoot: amalloy: no, wanted to add them. my confusion stemmed from the fact isa? doesn't work recursively through lists

0:49 but it does through vectors, so i'm all good

0:49 amalloy: yeah, i was surprised to learn that vectors have that feature. it's handy

5:25 Pupeno: I followed the instruction on getting started with Emacs with Clojure. I installed Emacs 23.3.1 and the packages. When I run clojure-jack-in it says Starting swank server... and gets stuck there. Any ideas how to find out what's going on? what's the problem? some logs?

5:27 bsteuber: Pupeno: if you don't see error-messages in *slime-events* or *messages*, I'd assume you missed to install the slime-repl elpa package

5:28 Pupeno: bsteuber: no buffer was open at all... I just did M-x package-install and choose clojure-mode

5:29 OK... there were some buffers but not shown.

5:29 Process swank exited abnormally with code 1

5:29 That's not a task. Use "lein help" to list all tasks.

5:32 lein repl works on the console.

5:32 amalloy: Pupeno: lein --version

5:33 Pupeno: Leiningen 1.6.0 on Java 1.6.0_26 Java HotSpot(TM) 64-Bit Server VM

5:33 amalloy: i suspect you have a version from before technomancy added jack-in to clojure-mode

5:33 hm

5:33 well, i don't use lein, but i'm pretty sure that version has support

5:34 Vinzent: Pupeno, do you have swank in your :dev-deps?

5:34 Pupeno: Vinzent: I don't know what that means, so probably not.

5:35 Vinzent: Pupeno, add [swank-clojure "1.3.1"] to your :dev-dependencies in project.clj

5:39 Pupeno: Where should that project.clj file be?

5:41 Vinzent: Pupeno, in the root of the project dir. lein new will create it for you.

5:41 Pupeno: I don't have a project yet, I just wanted to play around... do I have to create a project for slime to work with cljure?

5:42 Vinzent: Yes.

5:43 lein new, then edit project.clj and add necessary dependencies, then lein deps, then jack-in from emacs

5:44 Pupeno: Vinzent: how do I tell emacs where the project is?

5:45 Vinzent: Pupeno, just open some file from that project, and run jack-in from that file

5:46 (or you can run lein swank manually, then slime-connect from emacs)

5:47 Pupeno: I got this error now in the swank buffer: https://gist.github.com/1087404

5:50 Vinzent: I think it's something wrong with your project.clj. Take a look at sample.project.clj in the leiningen repo on github.

5:51 Pupeno: Vinzent: it was created by lein: https://gist.github.com/1087410

5:52 Vinzent: Pupeno, but where the :dev-deps part? http://paste.lisp.org/display/123312 here is a sample

5:53 Pupeno: Vinzent: sorry, that was the generated one.

5:54 And I did it wrong.... let's try again.

5:56 Same thing.

5:56 Process swank exited abnormally with code 1

5:56 That's not a task. Use "lein help" to list all tasks.

5:57 Hold on.

5:57 Vinzent: have you ran lein deps?

5:59 Pupeno: Nope

6:01 Seems to be working now... :)

6:01 At least *swank* is getting thousands of expressions.

6:01 SLIME!

6:01 Thanks Vinzent!

6:04 Vinzent: no problem :)

6:09 tufflax: This http://pastebin.com/D0kXBcYv takes forever to run. Running (map sk (range 1e6)) takes several minutes. What can I do to speed it up?

6:12 Pupeno: Now I can get started preparing the conference showing how awesome Lisp is.

6:12 tufflax: ...with a doall around the map call of course :p

6:18 Vinzent: tufflax, btw, in emacs the major part of time usually takes printing results to the buffer. Use (time ...) to know actual running time and *print-length* to avoid printing the whole sequence

6:21 about the code itself, sorry I can't advice you anything new: try to use primitive types, maybe unchecked arithmetic operations

6:28 tufflax: ok, i'll try. thanks

6:28 Pupeno: Yay, now it also works in Aquamacs.

6:38 minou: Im new to clojure and lisp, i want to make a square 2 dimension vector which is gonna be a maze, i want to fill it in a loop with ones or zeroes, can anyone help me to do this? i have trouibles with modifying vector since its not easy to do mutations to state

6:40 Vinzent: minou, vectors are immutable; if you are really need state, you should read about atoms and refs.

6:41 First, write a function that returns new vector filed with ones or zeroes

6:41 minou: i have one which returns a new vector filled with nils

6:41 a new matrix

6:42 its a matrix i mean 2-dimension vector

6:42 then i try to fill it through recursion and mantaining the matrix as accumulator variable, but i stuck because i cant do the recursion dont know why

6:43 it says Can only recur from tail position

6:43 but i think i do it only in tail positions

6:44 is it possible to do it with a while loop or a loop rebinding each time the matrix?

6:45 Vinzent: Compiler doesn't lie; you have call to recur in the non-tail position if it tells you so :) Maybe you understand tail position wrong?

6:45 Maybe it's possible, but it will be a bad piece of code

6:46 minou: yeah, surely i dont understand what it means....

6:47 but its a common piece of code, where can i see something similar?

6:47 i will google it

6:48 Vinzent: Sorry, I can't give you good links about it, but I have definitely seen some blog posts about it

7:34 tufflax: minou http://pastebin.com/UniJ1k6q

7:34 oh, he left

7:44 bsteuber: weird, I'm using Thread/setDefaultUncaughtExceptionHandler but when I do (Thread. #(/ 1 0)) it won't get called

8:02 Pupeno: In Slime RELP, how do I get the previous line?

8:02 bsteuber: Pupeno: M-p

8:05 Pupeno: Is there a name to call things that could me macros or functions? For example, "In a Lisp form, the first item is the .... and the rest are the arguments". What would ... be?

8:07 bsteuber: maybe verb

8:07 Vinzent: or command?

8:08 bsteuber: command sound so imperative to me ^^

8:09 frou100: You know the socket repl that "lein repl" starts, is there a way for the client on the other end of the socket to get exception messages? Presumably they are stderr and not being sent.

8:09 tufflax: Pupeno operator maybe

8:10 Vinzent: well, then "function" imo would be just fine (to not to overload listener with the details)

8:12 bsteuber: Pupeno: for what do you need it anyways?

8:51 Pupeno: bsteuber: to use the proper term when speaking.

9:05 ns is the proper way to create namespaces, and in-ns to switch to them when necessary, is that correct?

9:35 bsteuber: forfeit liest sich schöner ^^

9:36 sorry, wrong tab :)

10:01 raek: Pupeno: yes

10:01 Pupeno: Does this short macro make sense: https://gist.github.com/1087614

10:02 * Pupeno is preparing a short talk about Lisp and macros but haven't used them in years...

10:02 Pupeno: It feels good to code in Clojure again :)

10:02 raek: (ns refers all vars in clojure.core unless you say otherwise, so if you want to exclude something in clojure.core, using ns instead of in-ns won't work)

10:03 Pupeno: raek: ok. thanks. :)

10:04 raek: Pupeno: the prints will happen at the times described in their texts, so yes

10:05 Pupeno: raek: thanks :)

10:15 So, ` is the same as ' except that it lets you escape things with ~, right?

10:15 gfrlog: Pupeno: it also namespace-qualifies things

10:15 ,['first `first]

10:15 clojurebot: [first clojure.core/first]

10:15 Pupeno: Yeah, I seen that... thanks.

10:15 Is the comma for clojurebot ?

10:16 gfrlog: Pupeno: yes

10:16 Pupeno: ok.

10:16 mudge: what does it mean for a var to be defined with ^{dynamic true} ?

10:16 gfrlog: &['first `first]

10:16 lazybot: ⇒ [first clojure.core/first]

10:16 gfrlog: mudge: in clojure 1.3 that metadata is required to use the var with (binding ...)

10:16 pre-1.3 all vars are dynamic

10:17 mudge: gfrlog: thanks, I search google a lot for an explanation of this and I didn't fine it, do you have a source on the web?

10:17 gfrlog: hmm

10:19 a few brief mentions when I google for "clojure 1.3 ^:dynamic vars"

10:19 I don't think I've looked for it. I first heard about it when Rich talked about it at the conference last year.

10:21 mudge: gfrlog: ah thanks

10:22 gfrlog: thanks, which event? do you know if there is a video of the talk?

10:24 gfrlog: mudge: the first Clojure Conj. Rich gave two talks, and it should be the one that was not about hammocks.

10:24 mudge: gfrlog: ah, thanks

10:24 gfrlog: mudge: I've not seen it online, but it certainly should be. I'm googling now.

10:27 mudge: gfrlog: yea, I'm looking for it too

10:27 gfrlog: I've had no more luck this time then on previous tries. It's a shame too, because I've wanted to relisten to the part about vars. He explains why the change is a performance benefit, and I've forgotten the details of that.

11:03 mudge: jf

11:09 gfrlog: clojureql doesn't provide a way to lazily consume a large result-set without holding it in memory, does it?

11:13 for that matter maybe clojure.contrib.sql/with-query-results doesn't provide that either :/

11:23 * gfrlog is starting to feel like he doesn't understand what constitutes "retaining the head" of a lazy seq

11:27 Vinzent: I thought it's just a reference to the sequence, isn't it?

11:28 gfrlog: yeah. I think I've moved on past that and now the most logical explanation seems to be that my DB is spitting data back faster than clojure can reduce it. But that too seems implausible. :/

11:29 I do a SELECT * from a 12,000,000 record table and expect to be able to reduce the results without memory filling up

11:31 Vinzent: hm, maybe query result itself isnt't lazy at all?

11:31 gfrlog: as best I can tell both libraries do it lazily

11:31 c.c.sql defers to clojure.core/resultset-seq, which is certainly lazy

11:34 amac: o/

11:35 Vinzent: but maybe data from db are coming in one big chunk, and then it is just wrapped in a lazyseq? (I really don't know, just thoughts)

11:35 gfrlog: sure, that's theoretically possible. But I would think all the java.sql stuff would be lazy by default...

11:36 unless for some odd reason there's db-server-side config that needs to take place

11:42 okay, now I've confirmed that my code isn't even running -- the driver must be eating up the result and not returning.

11:45 the internets say the only way to make the mysql-jdbc driver lazy is with special arguments to Connection#createStatement. So looks like I'm dipping into java :/

11:49 Vinzent: hm, isn't it a candidate for clojureql issues list, what do you think? It'd perfect clojure libs\wrappers made things as lazily as it possible, especially with stuff like databases

11:49 gfrlog: Vinzent: I think clojureql uses c.c.sql, and the issue is at the c.c.sql level

11:50 this line would need some extra arguments: https://github.com/clojure/clojure-contrib/blob/6a0483d9e216ca00fc648a4b3673996b76a2785a/src/main/clojure/clojure/contrib/sql/internal.clj#L190

11:50 Vinzent: ah, ok

12:53 lnostdal-laptop: i really don't understand why 1.3 has gone about this split thing with regards to clojure-contrib in the way it did

12:54 gfrlog: lnostdal-laptop: I don't think that exactly coincides with 1.3...

12:55 lnostdal-laptop: oh

13:08 mudge: does anyone have any idea when clojure.contrib 1.3 stable release will be out?

13:08 dnolen_: mudge: there will be no such thing.

13:09 mudge: dnolen: I understand that clojure.contrib will be broken up into multiple libraries

13:09 dnolen: but I don't when to start using them

13:09 gfrlog: right away?

13:10 mudge: gfrlog: they are stable now?

13:10 lnostdal-laptop: they are not stable, and not even remotely complete

13:10 afaict

13:10 Vinzent: some of them are ready to use with clojure 1.2

13:11 mudge: should i look at each individual library to determine its status?

13:11 Vinzent: yeah, i think so

13:11 gfrlog: some of the libraries seem to have not been copied at all

13:11 I think combinatorics was that way last time I checked

13:15 lnostdal-laptop: it's quite messy .. "they" should have let the Big Blob be as is; or make it both 1.2 and 1.3 compatible really .. then split it only when 1.3 was out and ready i think ... *shrug*

13:16 related issue; what replaces print-doc now?

13:17 mudge: the good thing about clojure.contrib is it brings everything together nicely -- so you easily know where to look for functionality outside clojure.core

13:17 or outside clojure.jar

13:17 lnostdal-laptop: i guess one could have that even when things are split up; a sort of meta-package

13:18 mudge: lnostdal-laptop: yea sounds good, so one could have the big jar with everything, or be able to break it up if one wanted to

13:18 lnostdal-laptop: yup

13:23 mudge: hey, does anyone understand how the unifycle works? http://fogus.me/fun/unifycle/

13:23 dnolen_: mudge: yes

13:24 mudge: but unifycle is now https://github.com/clojure/core.unify, or you can use https://github.com/clojure/core.logic

13:25 mudge: dnolen_: thanks, i don't understand the example, so trying to figure it out

13:26 gfrlog: mudge: do you know how unification works?

13:26 dnolen_: mudge: core.unify is stand alone unification library, core.logic is more efficient and brings a logic engine.

13:26 mudge: gfrlog: not really

13:27 tomoj: does it work with arbitrary lists? doesn't need to be infix?

13:27 dnolen_: mudge: unification takes two terms and attempts to make them equal.

13:27 tomoj: right, so it doesn't care what's an operator or what's data?

13:28 mudge: how can something make terms equal? they are equal or they are not

13:28 gfrlog: mudge: the terms can have variables

13:29 dnolen_: tomoj: unification will work w/ whatever data structures the implementation supports.

13:29 gfrlog: I expect he was asking about unifycle specifically

13:29 mudge: the symbols starting with ? in the example are variables

13:30 mudge: gfrlog: yes

13:30 gfrlog: comparing the values in the two structures may imply a value for a particular variable, e.g. in the example ?x has to be 5

13:30 dnolen_: mudge: (unify '(?x 1) '(2 ?y)), unification will succeed with ?x bound to 2 and ?y bound to 1. (unify '(?x 1) '(2 2)) will fail.

13:31 mudge: dnolen_: yes, i see

13:31 gfrlog: (unify '(?x ?x) (3 4)) will also fail

13:31 mudge: by failing, does that mean it couldn't unify them?

13:31 gfrlog: correct

13:32 notice in the example that not all variables have to be bound in the result

13:33 mudge: gfrlog: yes, and are variables bound to functions too? or not? in (?x *) is ?x bound to * ?

13:34 gfrlog: I don't think there's a concept of function. It's just working with literals -- lists, symbols, numbers, etc

13:34 mudge: gfrlog, okay then (?x *) means that ?x is bound to the * symbol

13:35 gfrlog: mudge: no, it's a two-element list, with a variable and a symbol

13:36 mudge: gfrlog: so are variables only bound to numbers then? (?x *) is different then (?x 5) ?

13:36 gfrlog: (?x *) and (?x 5) cannot be unified, because * is different from 5

13:36 a variable could be bound to a list as well

13:36 mudge: gfrlog: thanks

13:37 gfrlog: (?a ?b ?c) could unify with ((1 2) 3 ?z)

13:37 mudge: gfrlog: i see, thanks

13:37 gfrlog: yep

13:38 mudge: gfrlog: would this unify: (?a ?b ?c) and (* + /)

13:38 gfrlog: yes. The result would be (* + /)

13:38 mudge: gfrlog: cool, thanks

13:39 gfrlog: I should qualify this by saying I've never tried unifycle, I'm just going off of what I think I know about unification

13:39 mudge: gfrlog: so then the unifer just reduces two equal lists into the simplest form?

13:39 gfrlog: okay

13:40 gfrlog: mudge: well, the main thing it does is look at the varibles and see if there is any way the two lists can be shown to be equal by binding the variables one way or another

13:40 I suppose we're using the word "equal" in a kind of loose sense

13:40 mudge: gfrlog: yes, thanks

13:40 gfrlog: maybe a better way to say it is that unification tries to find the least-specific structure that matches both of the inputs

13:41 where specificity refers to how much of the structure is a variable

13:41 mudge: gfrlog: yes, thanks

13:42 gfrlog: so when unifying (?a 2 ?x) and (3 ?b ?y), you get something like (3 2 ?x), where the last one is left as a variable because it can be

13:43 mudge: gfrlog: yes, with your help understanding this, i now understand the example give at http://blog.fogus.me/2010/09/27/unifycle-a-unification-library-for-clojure/

13:44 gfrlog: yes, i see that it tries to get rid of every variable if it can

13:44 gfrlog: mudge: good. The complicated part is when a variable occurs more than once within an expression

13:45 that constrains the unifyer to match the same thing in both instances

13:45 mudge: gfrlog: that is interesting

13:45 gfrlog: the primary context I've encountered unification in is natural language processing

13:45 mudge: gfrlog: was it helpful?

13:46 gfrlog: it would be interesting to see cases where a unifier would be useful

13:46 gfrlog: mudge: to the folks doing it, I'm sure :) I was just taking a class

13:46 dnolen_: gfrlog: mudge: unification is central to logic programming of all kinds.

13:47 mudge: gfrlog: now I have taken a class in unification, so thanks

13:47 kephale: mmm… unification is one of the more sophisticated logic-based pattern matching techniques

13:47 gfrlog: mudge: in NLP, the sort of structures handled were features of works, like tense, person, number, etc.

13:47 the unification would happen when a rule of the language said that two words had to "agree" to some extent

13:47 dnolen_: https://gist.github.com/1083967

13:48 ^ unification allows this tiny bit of code to type check, type reconstruct, and even produce the terms that satisfy the types.

13:49 mudge: dnolen_: interesting

13:50 I guess it is useful enough to go into clojure.core

13:51 dnolen_: mudge: you can build knowledge bases, http://stackoverflow.com/questions/6713424/how-do-i-express-this-logic/6719627#6719627

13:51 kephale: can anyone point me to the place in the clojure source where binding expressions are evaluated for things like {:keys […]}, (:syms […]}

13:52 gfrlog: kephale: open the clojure.core source and grep for :syms? :)

13:53 kephale: one occurence: https://github.com/clojure/clojure/blob/f86db9cc68773dd3e4a166c1ff7b81e4a98aa602/src/clj/clojure/core.clj#L3403

13:55 kephale: gfrlog: aha, thanks. I've been using {:keys […]} a lot, so I figured I should know how that code works.

13:55 gfrlog: kephale: looks complicated to me :)

13:56 kephale: you know it's equivalent to {foo :foo, bar :bar, ...}, right?

13:58 kephale: gfrlog: yes, but I could probably take advantage of that a bit better and generate a map like that instead

13:58 lnostdal-laptop: ..and another thing with 1.3; why doesn't it assume *these-things* are dynamic after printing a warning? .. it defaults to the non-safe option

13:59 gfrlog: lnostdal-laptop: it defaults to the new behavior

13:59 lnostdal-laptop: it'd be pretty weird if it changed its behavior based on the structure of your symbol

13:59 lnostdal-laptop: it should default to the new behavior, but not when the *'s are used .. it should warn (as it does) then, and do the safest thing ...

13:59 based on history; not really

14:00 gfrlog: clojure 1.2 doesn't change its behavior based on the structure of your symbol

14:00 it's just a naming convention

14:00 lnostdal-laptop: i know this

14:00 there everything was the same

14:00 that's not the issue ofc.

14:00 using non-dynamic variables is an optimization

14:01 mudge: why is core.unify in the list of 1.3 Contrib projects when it is part or going to be part of clojure.core ?

14:01 https://github.com/clojure/core.unify

14:01 lnostdal-laptop: i mean using them by default . .one that potentially breaks things and it certainly breaks things *like-these* more than once

14:01 gfrlog: lnostdal-laptop: in 1.2, all vars are assumed to be dynamic. in 1.3, all vars are assumed to be not dynamic.

14:01 lnostdal-laptop: yes, i know this, gfrlog ..

14:02 gfrlog: lnostdal-laptop: I think it might have been better called 2.0, because of all the breaking changes

14:02 lnostdal-laptop: but it warns based on naming style in 1.3 .. and it should also fall on the safe side after printing that warning

14:02 gfrlog: but I _don't_ think it should start examining your code for naming conventions and changing its behavior based on them

14:02 mudge: the list of Contrib projects is here: http://dev.clojure.org/display/design/Contrib+Projects

14:02 and core.unify is listed there for some reason

14:03 kephale: gfrlog: (fn keys-map [m] (zipmap (keys m) (map keyword (keys m))))

14:03 gfrlog: kephale: yes?

14:04 kephale: just noting what I ended up with

14:04 lnostdal-laptop: (..the reason it should fall on the safe side of things is that this would lead to waaay less breakage..)

14:05 gfrlog: lnostdal-laptop: why doesn't the warning take care of that?

14:06 lnostdal-laptop: what you're proposing is a much more complicated change

14:06 chrissbx: Is there a "=" that returns false for separately allocated objects with the same contents? (pointer equality comparison)

14:06 Chousuke: identical?

14:07 chrissbx: Thanks

14:07 gfrlog: &(identical? (hash-map 4 5) (hash-map 4 5))

14:07 lazybot: ⇒ false

14:07 chrissbx: Is there a "=" that only works for numbers, i.e. complains if the arguments are not numbers?

14:08 gfrlog: probably not. You could write your own with a precondition.

14:08 Chousuke: hm

14:08 isn't that ==

14:08 ,(doc ==)

14:08 clojurebot: "([x] [x y] [x y & more]); Returns non-nil if nums all have the same value, otherwise false"

14:08 gfrlog: ,(== () ())

14:08 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentList$EmptyList cannot be cast to java.lang.Number

14:08 gfrlog: I learn more if I assume I know the answers to all the questions and then get corrected.

14:09 chrissbx: Perfect, thanks.

14:09 gfrlog: Chousuke: does == do anything that = doesn't?

14:10 chrissbx: Well it asserts the types.

14:10 Useful for error checking.

14:10 gfrlog: :| That hardly seems like a reason to include a separate function in core

14:10 what if I want a version of assoc that only accepts maps?

14:11 chrissbx: Equality predicates are especially sensitive to the type issue, since they silently return false in buggy cases.

14:11 gfrlog: hmm

14:12 it still only solves one instance of the problem

14:12 what if I want an == for keywords?

14:13 chrissbx: Agreed.

14:13 Other lisps still prominently provide number comparison, though.

14:13 Maybe because math is especially likely to break?

14:13 Whatever. I'm happy for the ==.

14:14 dnolen_: ,(= 1 1.0)

14:14 clojurebot: true

14:14 gfrlog: dnolen_: I even tried it with a ratio

14:14 dnolen_: this behavior is changed in 1.3.0

14:14 (= 1 1.0) is now false

14:14 (== 1 1.0) is now true

14:14 gfrlog: oh geez

14:14 chrissbx: heh:)

14:15 gfrlog: can we please pull a Torvalds and call it 2.0? there's still time.

14:15 chrissbx: Maybe that was the reason :)

14:15 gfrlog: this is embarrassing

14:15 it's not just poking at the big-ints anymore

14:16 dnolen_: gfrlog: these changes have been sitting around for like 8 months, plenty of time to get used to it.

14:16 threads galore on the ML and here on rationale

14:16 gfrlog: dnolen_: for those who are paying attention maybe

14:16 just because there's a reason to break things doesn't mean you shouldn't indicate it in your numbering

14:17 dnolen_: gfrlog: if you think 2.0 and 1.3.0 distinction is significant. bikeshedding non-sense IMO.

14:19 gfrlog: dnolen_: so why do we have dotted version numbers at all? why not just increment an integer whenever something changes?

14:20 dnolen_: gfrlog: there's discussion on the ML about this as well, I don't have much more to say about it.

14:20 gfrlog: dnolen_: okay I'll go look. thanks.

14:20 lnostdal-laptop: it sure does have breaking changes

14:21 dnolen_: lnostdal-laptop: so did the other releases.

14:21 lnostdal-laptop: i guess 1.2.0 --> 1.2.1 didn't, then

14:22 gfrlog: dnolen_: in arithmetic?

14:25 chrissbx: What's the standard way to open a file for input (or output), to get at the stream.

14:26 gfrlog: chrissbx: check in clojure.java.io

14:28 chrissbx: Thanks

14:29 raek: chrissbx: clojure.java.io/{input,output}-stream for binary (byte based) files and clojure.java.io/{reader,writer} for text (character based) files

14:37 chrissbx: I'm getting "java.io.BufferedReader cannot be cast to java.io.PushbackReader" when using reader with read

14:43 raek: yeah, you have to wrap the result of reader with (PushbackReader. )

14:43 chrissbx: Aha.

14:43 raek: there isn't any function for that in clojure.java.io unfortunately

14:44 chrissbx: Weird, it seems to me that reading s-expressions from a file would be one of the most standard things a Lisp system would do.

14:45 I'm finding myself not only implementing a read-all, but also binding java to get the offered functions from two clojure libraries to work together.

14:45 VT_Entity: there's no easier way?

14:46 chrissbx: Why is '`a evaluated to (quote user/a) and not to (quasiquote a)? Is quasiquote expanded by the reader, or is quasiquote still evaluated at macro expasion time but does quote not prevent macros from being evaluated?

14:48 VT_Entity: I think quasiquote means hold off until the macro is invoked.

14:49 so, you can still shuffle around the code as data until you invoke the macro.

14:49 I could be wrong though, still new at this.

14:54 raek: chrissbx: it is expanded by the reader

14:55 chrissbx: In other lisps, (quote expr) means that expr is treated as a literal constant, i.e. unmodified. So I was expecting the result of (quote (quasiquote a)) to be (quasiquote a) as it is in Scheme.

14:56 Now I guess Clojure "mangles" the symbols in the reader (to add the namespace to them), whenever it sees quasiquote.

14:57 gfrlog: how do I run the tests in a clojure/maven project like clojure.java.jdbc?

14:57 `mvn test` doesn't seem to find anything to do

14:57 VT_Entity: I think you need to explicitly invoke auto gensym, no?

14:58 raek: ,(read-string "`foo")

14:58 clojurebot: (quote sandbox/foo)

15:14 gfrlog: forking project, changing, compiling with maven, uploading to clojars: very hard.

15:23 I guess it's more the fact that I was doing two libs at the same time

15:23 and don't know how to use clojure/maven

15:25 amalloy: chrissbx: reading files into s-expressions is pretty easy with slurp + read-string

15:28 chrissbx: amalloy: I need all expressions, so I wrote a read-all, but that expects a stream as an argument

15:28 read-string only reads 1 expr

15:29 Also, why slurp the whole file into memory when reading expressions lazily from a stream would do.

15:30 But if you meant to say that read-string and slurp are the reasons that the rest is totally incomplete, then I see the point.

15:32 gfrlog: so after an hour of furious patching I finally got clojure.java.jdbc + clojureql to read lazy result sets from mysql

15:33 chrissbx: gfrlog: interesting; when I last looked at the mysql protocol (or was it just libmysql?) about 5 years ago, it didn't support lazy reading of result sets.

15:33 amalloy: gfrlog: "I learn more if I assume I know the answers to all the questions and then get corrected." so true

15:33 gfrlog: amalloy: :)

15:34 chrissbx: apparently it supports it if you pass particular arguments to [prepare|create]Statement, and then do this hacky thing with fetchSize

15:34 chrissbx: Ok, will have to look at it some time. Thanks for the hints.

15:34 gfrlog: amalloy: it registers in my brain as embarrassment, which subconciously motivates me to remember

15:34 ...or suppress

16:00 StayInSkool: hi #clojure! what are good examples of (simpler for starters) open-source clojure (and compojure) apps to learn from?

16:01 so far I've found either really basic or rather complex examples

16:01 amalloy: StayInSkool: https://github.com/dbyrne/4clojure ?

16:03 StayInSkool: amalloy: hmm, that sounds like a good starting place. thanks!

16:04 amalloy: StayInSkool: and feel free to bug us (okay, mostly just me these days) in #4clojure if you need some hints

16:06 StayInSkool: thanks :D

16:10 seancorfield: clojure.java.jdbc 0.0.4 on maven central - fixes reflection warnings, fixes transaction handling on Error thrown, code cleanup

16:11 gfrlog: sounds like you had some problems with c.j.j?

16:11 i use it with mysql all the time - anything i can do to help?

16:11 or was it more around clojureql (which i don't use i'm afraid)?

16:14 gfrlog: seancorfield: it was regarding reading a ResultSet lazily

16:15 apparently the mysql driver only does it if you add some arguments to (.prepareStatement ...)

16:15 seancorfield: so I did this kind of thing: https://github.com/USCSoftware/java.jdbc/commit/7f9d45d2e88b82a4d28b706b4ebe8696827348ef

16:15 seancorfield: ah, i'm working on exposing machinery to allow users to operate on the PreparedStatement before it is executed

16:16 gfrlog: seancorfield: that might do the trick, I haven't looked at the methods on PreparedStatement to see if the configuration can be done _to_ it as well

16:17 seancorfield: yeah, it may need just exposing as a way to pass in a function that creates the PreparedStatement appropriately

16:17 whoever design the Java API for the JDBC stuff should be taken out and shot - it's horrible to work with!

16:18 lucian: seancorfield: why not use clojureql?

16:19 gfrlog: i patched clojureql as well; it creates its statements on its own

16:19 seancorfield: lucian: i maintain clojure.java.jdbc

16:19 lucian: oh

16:19 seancorfield: yeah, clojureql is kinda standalone

16:20 i tried it but didn't really like the approach

16:20 lucian: i see

16:20 seancorfield: at world singles we have some pretty gnarly joins and stuff and it was not very intuitive to read the clojureql forms for those

16:21 also, since i'm introducing clojure to an existing project and the team all know SQL, using c.j.j was a much easier transition for them

16:25 gfrlog: seancorfield: a simple first-try could be to allow (with-query-results) to take a PreparedStatement as well as a vector

16:25 lucian: right

16:32 seancorfield: that means the calling code has to do the uglies with the connection to create the PreparedStatement - i think i'd rather pass a map of parameters that the code uses to figure out the right call of .prepareStatement on the connection...

16:34 amalloy: seancorfield: isn't the point here that the client wants to do something complicated? better to let them do it, when they want control

16:35 seancorfield: yeah, it's a matter of making a clean interface for the most common needs

16:35 i haven't decided quite what's best yet

16:37 passing a map of {:type :forward-only :concur :read-only :fetch-size Integer/MIN_VALUE} seems like a nicer approach than making the user deal with the java directly, yes?

16:40 amalloy: seancorfield: that sounds fine, i'm sure. i don't really know what's going on here in general, but it seems to me like you should also give them a way to pass you an actual object they built, in case there's some feature you don't expose

16:41 seancorfield: yes, probably that too

17:28 ihodes: (def π (Math/PI))

17:28 ,(def π (Math/PI))

17:28 clojurebot: DENIED

17:30 amalloy: &(let [π (Math/PI)] (* 2 π))

17:30 lazybot: ⇒ 6.283185307179586

17:52 chrissbx: Hm. I'm looking for a way to reformat Clojure code (wrapping and indentation); clojure.pprint has been suggested to me, but how am I supposed to make it indent it right?

17:52 Isn't there something that would just do it out of the box?

17:53 I've already written a Clojure printer in my Scheme-to-Clojure converter, if I'll have to figure out all rules to make the Clojure code wrapped and indented right myself anyway,

17:53 I can just as well add this to my printer.

17:55 * technomancy resorted to emacs to indent clojure code

17:55 chrissbx: (With the added benefit that I wouldn't be tied to using Clojure / the JVM as part of the conversion.)

17:55 Yes, sounds like I could as well go that route;

17:55 except that I don't know any emacs code that does the wrapping.

17:56 technomancy: yes, that's trickier. so far I've punted on wrapping.

17:56 _simonf: Hola - my first day using clojure. I'm having trouble seeing the clojure.contrib.math jar that I put in ~/.clojure. Running "CLOJURE_EXT=~/.clojure java -cp /usr/local/downl/clojure/clojure/clojure.jar clojure.main" does not help.

17:57 chrissbx: It seems a bit funny to me how much stuff Scheme systems got done that the Clojure community doesn't seem to have solved yet.

17:57 technomancy: chrissbx: is it really all that surprising? scheme has had many, many more decades.

17:58 chrissbx: I still find it surprising, because my impression is that there are more people using Clojure than all the Scheme systems together, but maybe that's a wrong impression.

17:59 technomancy: _simonf: you might have a better time starting at http://dev.clojure.org/display/doc/Getting+Started

17:59 chrissbx: Thing is that most Scheme systems got things like these implemented independently, each with only a tiny community.

17:59 technomancy: _simonf: any time you're invoking "java" directly you're probably making things more complicated than they need to be, and there are a lot of bad docs out there, including clojure.org

18:00 _simonf: technomancy: yeah, I already stumbled into bad docs

18:01 chrissbx: Also, of course it's funny because Hickey *could* just have made Clojure a dialect of Scheme and borrowed much code.

18:01 But then it wouldn't have been new and people wouldn't have flocked to it maybe. Dunno.

18:01 _simonf: technomancy: yeah, I already stumbled into bad docs is about IDEs, which is less interesting. My Ubuntu's clojure is old, so I figured I'll build the jars from github.

18:01 chrissbx: Anyway, back to writing code.

18:02 technomancy: clojurebot: lein tutorial?

18:02 clojurebot: lein is http://github.com/technomancy/leiningen

18:02 technomancy: _simonf: ^^ I recommend starting there.

18:03 building the jars by hand can be a bit of a rabbit trail

18:04 _simonf: technomancy: I'm not sure what you mean. I use vim, so this page tells me to use vimclojure, which is a syntax highlighter. Does not tell me anything about getting the actual language.

18:05 technomancy: _simonf: generally it's coupled with a build tool

18:06 http://lisp4fun.blogspot.com/2010/02/leiningen-and-vimclojure.html might be relevant

18:09 Scorchin: _simonf: lein gives you a simple build tool to hide away many of the issues involved with loading jars. It also simplifies a number of common tasks such as loading up your app into the repl, compiling, running tests and packaging

18:10 _simonf: trying now...

18:15 raek: _simonf: re your original problem: clojure.contrib.math is not included in clojure itself, so you need to add [org.clojure/clojure-contrib "1.2.0"] as a dependency in your project.clj and run "lein deps" to fetch it

18:15 (assuming you are using clojure 1.2.0 or 1.2.1)

18:16 _simonf: raek: yup, I just figured this out

18:16 Scorchin: raek: He wasn't using lein to begin with. He's switching to use it now though, so that should be extremely useful!

18:16 _simonf: looks like in 1.3 individual contrib libraries are split out

18:16 it's not clear how to specify them individually in project.clj

18:19 technomancy: _simonf: I don't know if math has been upgraded to 1.3 yet

18:19 if you're starting out you should use the latest stable release, not the betas

18:25 _simonf: ok, I got the compile cycle working, but this means I lost the REPL mode. I have to rebuild my jar after every edit

18:31 raek: _simonf: while developing its more common to keep a repl open and reload files when you change them instead of doing the compile cycle

18:31 _simonf: raek: ok

18:32 raek: it's simpler to develop in the repl if you think of the source files as holding the definitions of the functions you use in the repl (or in the -main function) rather than a script that is executed

18:33 _simonf: if you have a file in src/myproject/core.clj, you can load it and enter its namespace with (doto 'myproject.core require in-ns)

18:33 use (require 'myproject.core :reload) to reload it

18:33 amalloy: (which is shorthand for (require 'myproject.core) (in-ns 'myproject.core)

18:34 raek: for this to work you should also have a (ns myproject.core) at the top of the source file

18:34 lnostdal-laptop: hm, i guess using transients inside agents won't do since agents execute using any random thread from a pool?

18:34 _simonf: hm - so I have to know which files I want to reload

18:34 in the Python world, I'm mostly developing by running unittests until they pass

18:35 that seems to minimize overhead

18:35 brehaut: _simonf: (use :reload-all 'namespace)

18:36 _simonf: or you could run lazy test which watches your source files and reloads them and runs tests automatically

18:37 _simonf: or lein interactive

18:37 amalloy: lnostdal-laptop: yeah, i'm afraid so

18:37 _simonf: awesome, reload-all works. Thank you everyone!

18:38 I must say, Clojure is easier to get into than Haskell

18:38 amalloy: you'd need to allocate a future and manage it yourself

18:52 ihodes: _simonf: Haskell is awesome though--i think you need just a bit more activation enegery with Haskell than you do with clojure to get going

18:52 tufflax: Hm, why it this so slow http://pastebin.com/bVHRKaKz

18:55 is*

18:56 amalloy: tufflax: you're boxing and unboxing integers a lot

18:56 tufflax: ok, how can i avoid that

18:57 not use an int array?

18:57 amalloy: typehints in the appropriate places, except i don't know what places those are. dnolen will know

18:58 bsteuber: tufflax: which clojure version?

18:58 tufflax: 1.2.1

18:58 bsteuber: expect 1.3 to be a lot faster in these things

18:58 tufflax: ok, thats nice

19:34 haploid: can defn define sequential execution without let, dorun, etc ?

19:35 brehaut: ((fn [x] (prn "x is" x) (inc x)) 1)

19:35 ,((fn [x] (prn "x is" x) (inc x)) 1)

19:35 clojurebot: "x is" 1

19:35 2

19:35 brehaut: haploid: ^

19:36 haploid: long version: functions have an implicit do

19:36 haploid: dorun is quite different to do

19:36 haploid: ok, cool, thanks

19:40 one other thing - does anyone know off the top of the head what "simpledb.core" is? trying to understand the noir-blog source, but google is not helpful here with understanding what the dependencies are/do

19:43 brehaut: haploid: perhaps an api for amazon's simpledb ?

19:45 haploid: yeah, could be, except the main libraries for simpledb in clojure appear to be "sdb" and "rummage" - and it wouldn't make sense that the noir folks would make having an aws account mandatory to run their example app.

19:45 weird

19:46 brehaut: haploid: https://github.com/ibdknox/simpledb

19:47 haploid: its a trivial in memory db

19:47 that serializes to a file using clj forms

19:47 haploid: ah awesome, thanks.

19:47 wonder why google couldn't find it.

19:48 brehaut: presumably because amazon's simpledb is much more talked about

19:48 and google isnt friendly to precious code-ish queries (by default anyway)

19:49 s/precious/precise/

19:49 lazybot: <brehaut> and google isnt friendly to precise code-ish queries (by default anyway)

19:57 Scriptor: there's always google code search

19:59 gfrlog: seancorfield: I left before the discussion with amalloy. I support both options -- I think your idea is good because the java.sql interface is pretty limited, so it might be that there's only a small set of things somebody could do anyhow. But amalloy's idea is good in principle, and probably can't hurt.

20:00 brehaut: and in this case knowing to check ibdknox's github

20:15 StayInSkool: what's the point of doing something like (fn add-five [x] (+ x 5)) 3) ?

20:16 isn't that still an anonymous function? what's the point of add-five?

20:16 gfrlog: StayInSkool: you can recurse

20:16 StayInSkool: oooooh

20:16 like in javascript

20:16 gfrlog: StayInSkool: true true

20:17 StayInSkool: perfect, thanks!!

20:17 gfrlog: no probalo

20:17 Scriptor: ,(class (defn foo [] "foo")

20:17 clojurebot: EOF while reading

20:17 Scriptor: ,(class (defn foo [] "foo"))

20:17 clojurebot: DENIED

20:18 gfrlog: Scriptor: come on man you know it ain't gonna let you def nuthin

20:18 Scriptor: :(

20:18 gfrlog: it's a var right?

20:33 amalloy: gfrlog: yes, clojurelang.Var

20:33 gfrlog: amalloy: what was the thing I was going to say to you if you were around?

20:35 amalloy: $help mail

20:35 lazybot: amalloy: Send somebody a message. Takes a nickname and a message to send. Will alert the person with a notice.

20:35 gfrlog: amalloy: a notice? when?

20:36 amalloy: gfrlog: next time they're spotted logging in or saying something

20:36 gfrlog: so if they're already logged in then it waits till they say something?

20:36 amalloy: $mail gfrlog like so

20:36 lazybot: Message saved.

20:36 gfrlog: come on lazy bot what did he want to tell me?

20:36 oh I bet it's in some other erc window

20:36 damn you emacs

20:37 amalloy: yeah he PMs you. mails are definitely not public

20:37 * gfrlog does ctrl-x-something

20:37 amalloy: C-x b lazybot, probably

20:37 gfrlog: not seeing anything there actually

20:37 amalloy: hm

20:37 $mail amalloy test

20:37 lazybot: Message saved.

20:37 amalloy: test test

20:38 gfrlog: $mail amalloy giggle

20:38 lazybot: Message saved.

20:38 amalloy: gfrlog: well you were wrong, he PMs me just fine

20:38 errr, except i didn't get that one. puzzling

20:38 * amalloy looks at the source

20:38 gfrlog: PM here stands for Prime Minister, right?

20:39 * gfrlog knows what it stands for, he just couldn't keep himself from saying that

20:39 amalloy: oh, interesting. apparently he won't notify you of new mail more than once every five minutes

20:39 but you can still read them by sending him the message "mail"

20:39 gfrlog: ah there got it for the first time

20:40 maybe cuz I used '/msg lazybot ...'

20:40 and erc likes that

20:40 amalloy: dunno

20:40 gfrlog: I'm not going to technomancy's emacs talk, so I will never learn how all this works.

20:46 amalloy: grrrr. i love clojure, but exception-handling is often so much easier with mutable state

20:48 technomancy: amalloy: is it really mutable state you want, or just more flexible exception types?

20:49 amalloy: technomancy: i'm not sure. i suspect there'd be an easy way to do it with slingshot, but since i'm not used to having better exceptions i'm not sure what it would be

20:50 my current problem is i need to react in similar ways to a number of different conditions. i'm calling into a library which throws a "dumb" exception, and if it does i need to include part of my current environment (a loop binding) in the eventual result

20:51 which sounds like either making that binding a mutable semi-global, or catching the internal exception and then throwing something different

20:51 technomancy: nah, slingshot can include the local context as part of the exception

20:52 amalloy: so, catch the dumb exception, and then throw a smart one which will automatically have local context bundled into it?

20:52 technomancy: oh, I didn't catch (har) that a separate library was throwing

20:53 yeah, it's awkward when you have this divide between your code and dumb exception land

20:53 which I feel is part of why error-kit and c.c.condition didn't take off

20:53 amalloy: i mean, the library is clojail, which i have write access to. but either way, it wouldn't have access to the *calling* code's environment in order to include into the exception

20:54 technomancy: it sounds like chaining may be the way to go... and it sounds like that would be true in a mutable system too

20:54 amalloy: technomancy: chaining as in re-wrapping the exception?

20:55 technomancy: right

20:55 amalloy: i don't even need to throw an exception. i know how to handle the error, i just have to unify the various error cases

20:56 maybe i can just rewrite this whole function. it's pretty gross anyway

21:21 zakwilson: Something that's awesome about Clojure is that the usual programming advice of hiding the underlying implementation and exposing an unchanging API is a little different. Usually, the API and underlying implementation can just be based around Clojure data structures, and if the implementation changes those data structures still make a reasonable API.

Logging service provided by n01se.net