#clojure log - May 26 2010

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

1:01 bmason: man I'm glad I read this channel... reduce *is* the bomb

2:59 bartj: er, is there anyone here who knows russian?

3:12 unfo-: i heard google does

3:13 technomancy: unfo-: heyo

3:15 bartj: unfo: apparently google's translate engine is having problem translating a russian page to english - "http://www.yell.ru/all/2000002-%252000125-%251000083/en/146/small"

3:15 I know this is terribly off topic to the channel but...I wanted to know what language this phrase "bezopasnost' dorozhnogo dvizheniya - oborudovanie" from the above page is in

3:17 bmason: http://encyclopedia.farlex.com/Komitet+Gosudarstvennoy+Bezopasnost

3:17 perhaps it is a name?

3:19 waterless_cloud: might be ukranian

3:21 bartj: I think it is a business category, because it says so on this page - "http://www.yell.ru/EASY%20PARKING/all/en/7003483/643/entry" but weirdly google translate is not able to find the translation for - "bezopasnost' dorozhnogo dvizheniya - oborudovanie"

3:22 waterless_cloud: phrase does not work either from "Ukranian to English" on Google Translate for the phrase - "bezopasnost' dorozhnogo dvizheniya - oborudovanie"

3:28 waterless_cloud: GIBDD Gosudarstvennaya Inspectsiya Bezopasnosti Dorozhnogo Dvizheniya (Russian: Federal Road Safety Service)

3:29 bartj: waterless_cloud: I don't understand

3:30 waterless_cloud: and reference here

3:30 http://en.russia.edu.ru/tips/sec/1331/

3:30 seems to be traffic cops

3:39 vu3rdd: technomancy: would you like to include a maven po.xml in the leiningen repo for other folks who are doing similar things as me?

3:40 technomancy: vu3rdd: no, the pom is an generated artifact of project.clj

3:40 generated artifacts generally don't belong in source control; they should just be re-created on-demand

3:41 vu3rdd: technomancy: yes, but building leiningen itself without using lein is a problem in that case, right? And the generated pom does not build a useful jar

3:41 technomancy: oh, what's missing in the generated pom?

3:41 I haven't actually tried it in this case

3:42 vu3rdd: it creates an empty jar

3:42 npoektop: hi! is there a function like doseq which collects results?

3:42 vu3rdd: I had to use the maven-clojure-plugin to compile leiningen.core (or anything which needs to be aot compiled)

3:42 also add resources for the source files to be included

3:43 technomancy: hmm... I'd rather fix the pom task so it generated a useful pom.

3:43 somnium: npoektop: for

3:44 vu3rdd: technomancy: Yes, I thought about that too. pom task definitely needs some care.

3:45 npoektop: somnium, thanks!

3:45 technomancy: vu3rdd: I don't use it myself, so I'm reliant on contributions from others to get it well-polished.

3:45 vu3rdd: technomancy: ok

3:45 technomancy: I understand the hint

3:46 technomancy: from you or others. =)

3:46 IDE-users, etc.

3:46 vu3rdd: technomancy: sure, I will look at it.

3:47 technomancy: vu3rdd: have you thought about waiting for the stable 1.2 release to perform the packaging? it shouldn't be too far off now.

3:47 vu3rdd: technomancy: I don't use IDE myself though. But most java projects use mvn and hence it is quite well supported in GNU/Linux world

3:47 technomancy: vu3rdd: oh, I just meant that in the past the pom task has mostly been used for IDE interop

3:47 vu3rdd: technomancy: I was thinking of packaging 1.1.0. Also debian does not have maven-ant-tasks, so I will have to package that too..

3:49 technomancy: java packaging has been a pain. I have never faced so many issues in plain old C world.

3:49 technomancy: yes, it's tricky to do systemwide java packages. most of the java ecosystem assumes it's installed on a per-user basis

3:49 vu3rdd: technomancy: do you plan to add some verbosity/logging support in lein so that during debugging it cabe turned on?

3:50 technomancy: vu3rdd: it's crossed my mind, but it's not a high priority right now.

3:50 vu3rdd: technomancy: debian solves it quite nicely. The systemwide jars you install becomes your local maven repo

3:50 technomancy: ok

3:51 technomancy: hmm... I have often had issues with systemwide debs for things like hudson and solr that have turned me towards using tarballs.

3:51 actually no, hudson worked decently, but solr was totally broken last time I checked

3:52 vu3rdd: technomancy: perhaps true. I think it is still evolving. But debian has got some good basic infrastructure for maven in place.

3:52 technomancy: did you say you were planning on packaging the latest lein with clojure 1.1.0? because I don't think that will work; there are some things in lein right now that rely on clojure 1.2-snapshot

3:52 vu3rdd: No, I mean packaging lein-1.1.0

3:53 technomancy: oh, I see. that would probably be better, though I think 1.2 will not be too far away if you want to wait.

3:53 vu3rdd: technomancy: yes, that is what I thought after talking to you yesterday

3:53 technomancy: lein 1.1.0 has a bug in the repl task (due to a bug in clojure) that makes it use the wrong version of clojure for the project repl

3:54 but lein 1.2.0 has a bug in the repl task due to a bug in ant that makes it break on some platforms.

3:54 very annoying!

3:54 vu3rdd: oh.. ok

3:54 ordnungswidrig: vu3rdd: check if the bug in ant isn't fixed by debian

3:55 vu3rdd: ordnungswidrig: maven-ant0tasks is not yet in debian

3:55 technomancy: ordnungswidrig: the ant developers have no plans to fix the bug. =(

3:55 ordnungswidrig: vu3rdd: oh, debian and maven the long story

3:56 technomancy: maybe the debian maintainers have

3:56 I tried packaging maven for debian 3 years ago. *horrible*

3:56 vu3rdd: ordnungswidrig: I will check. ant version on debian is 1.8.0. I use unstable tree

3:57 ordnungswidrig: The current situation is quite ok. Java is sort of a first class citizen in the debian world now

3:57 ordnungswidrig: vu3rdd: can maven be build from source now? IIRC maven needs some heavy "external" bootstrapping

3:58 vu3rdd: even upstream maven used to need some existing maven jars to build itself

3:58 vu3rdd: ordnungswidrig: http://wiki.debian.org/Java/Maven2

3:58 ordnungswidrig: lots of pain

3:59 technomancy: ordnungswidrig: I'd be thrilled... but it's unlikely.

4:01 ordnungswidrig: now i'm sure it was a good decision to drop this task

4:01 vu3rdd: technomancy: clojure/clojure-contrib 1.1.0 is already in unstable/testing

4:01 technomancy: oh, cool

4:06 vu3rdd: packaging maven-ant-tasks is going to be a bit tough because they build a shaded (uder)jar

4:06 s/uder/uber

4:06 I don't think debian "allow" that

4:10 ordnungswidrig: vu3rdd: you mean shading=

4:10 vu3rdd: ordnungswidrig: yes

4:11 ordnungswidrig: vu3rdd: shading does not make sense in a distribution environment as there is only one version of each dependency available anyway

4:12 vu3rdd: but it makes sense for a build tool, where you want to avoid the version blues

4:12 vu3rdd: ordnungswidrig: yes. It is like going back to those old days of static libraries

4:12 ordnungswidrig: vu3rdd: you've heard of nixos linux?

4:13 vu3rdd: ordnungswidrig: no

4:14 ordnungswidrig: vu3rdd: they do package management like a hybrid of git and gentoo :-) Symlinking until your inodes smoke. Every package can have it's one "view" to other packages and versions.

4:14 vu3rdd: ordnungswidrig: oh.. ok. I will look at it

4:28 bozhidar: ll

4:28 ops, sorry - I thought I was in the terminal buffer ;-)

5:25 rava: greetings

5:25 cgrand: hi

5:25 Lajla: rava, bow before me.

5:25 I am the second best programmer in the world.

5:25 * rava bows

5:26 Lajla: Rise, my friend.

5:26 * rava *rises*

5:26 rava: great and merciful 2nd best

5:27 dost thow know compojure? for yonder #compojure is fairly dead this eve

5:28 Lajla: rava, I actually barely know clojure.

5:28 rava: heh

5:28 Lajla: I'm just a Scheme programmer infiltrating here.

5:28 rava: ew, scheme

5:28 Lajla: Still deciding if I want to learn Clojure or not.

5:28 rava, why?

5:28 rava: just prefer common lisp

5:28 no real or objective reason

5:29 Lajla: rava, well, there must be a subjective one?

5:30 rava: asdf for one

5:32 dislike lexical scope only

5:33 couple other odds and ends

5:33 those are what came to mine

5:34 i've not even looked at scheme in 2 + years though

5:37 LauJensen: haha <Lajla> I'm just a Scheme programmer infiltrating here.

5:37 <rava> ew, scheme

5:37

5:39 Lajla: There are some times yes when it would be easier if a variable could be given dynamic scope too.

5:39 But still, you shall be executed for your bad taste, just like Oscar Wilde and Alan Turing.

5:45 Chousuke: scheme has fluid-let, doesn't it?

5:49 naeu: could someone clarify a clearly flawed understanding of basic computing that's currently in my head. Why does (byte 2r11111111) produce -1 (or raise an exception in 1.2 snapshot). Doesn't a bit consist of 8 bits, and are they not all allowed to be 1?

5:50 Chousuke: a byte consists of 8 bits

5:50 but a number in base-2 can be as large as you want

5:51 2r... is not notation for bitfields, but numbers in base 2

5:51 though hm

5:51 ,2r11111111

5:51 clojurebot: 255

5:52 Chousuke: ,(byte 2r11111111)

5:52 clojurebot: java.lang.IllegalArgumentException: Value out of range for byte: 255

5:52 cgrand: bytes in java are signed

5:52 Chousuke: ah, right.

5:52 yeah

5:53 naeu: ok, so the max is 127 for byte consisting of 7 bits?

5:53 cgrand: -128 to 127

5:54 naeu: ah ok, so the range is the same (255) just the integer which generates a given list of bits is offset by -128

5:56 cgrand: not really offset: 0 is still 0, not -128

6:00 unsigned byte 0..127 = signed byte 0..127; unsigned byte 128..255 = signed byte -128..-1

6:01 hoeck: naeu: http://en.wikipedia.org/wiki/Two%27s_complement

6:03 ,(bit-and 0xff (byte -1)) ;; to get the unsigned value of a byte

6:03 clojurebot: 255

6:09 patrkris: What's the easiest way to run a project set up with leiningen? Using Eric Lavigne's leiningen-run? Seems to get me strange output - [null] prepended to every line i output.

6:14 naeu: hoeck: thanks

6:14 so what's the simplest way of creating a byte represented by the string 11111111

6:15 cgrand: ,(Byte/parseByte "11111111" 2)

6:15 clojurebot: java.lang.NumberFormatException: Value out of range. Value:"11111111" Radix:2

6:17 hoeck: ,(.byteValue (Integer/parseInt "11111111" 2))

6:17 clojurebot: -1

6:17 cgrand: thx

6:18 naeu: thanks

6:19 also whilst I'm in a questioning mood, is there a nice way to iterate over a sequence with for side effects, but with the iteration yielding an index?

6:19 essentially i'd like a side-effect focussed equivalent of map-indexed

6:20 hoeck: dorun + map-indexed ?

6:23 naeu: hoeck: nice, thanks so much

6:52 Lajla: Chousuke, 'Scheme' doesn't, that is R5RS doesn't.

6:52 But it's easy to add it.

6:52 The Scheme standard itself is extremely minimal, things like when, let*, fluid-let* are all just extensions written in Scheme

6:55 bartj: can anyone give a use-case for map-indexed - so that I could write some code using it?

7:09 anyone?

7:27 mikem: looking at clojure.core source, I see something like this: (fn defn (&form &env name & fdecl] ...) -- what does the leading & in &form and &env mean?

7:32 reZo: ohai

7:33 bartj: mikem: my guess - that they are optional arguments

7:34 mikem: bartj: hm I thought optional arguments are suffixed with a *

7:36 bartj: mikem: the general convention is to use *earmuffs* for things intended for rebinding. Reference: http://www.assembla.com/wiki/show/clojure/Clojure_Library_Coding_Standards

7:43 hoeck: mikem: those are some macro-only?, compiletime? args while expanding the macro, &env resolves to the current lexical environment, &form to the current form

7:44 patrkris: how do I get the Class<T> of Integer? Tried Integer/TYPE, but that is apparently not it.

7:45 hoeck: mikem: sorry, those are arguments the macro-expansion function takes when called

7:45 ,Interger

7:45 clojurebot: java.lang.Exception: Unable to resolve symbol: Interger in this context

7:45 hoeck: ,Integer

7:45 clojurebot: java.lang.Integer

7:46 patrkris: hoeck: just like that? cool :)

7:48 hoeck: yeah, Integer/TYPE returns the primitive type int

7:49 bartj: what is the use of #^ while defining function

8:11 _na_ka_na_: hi, is there any built in fn to convert an ns into file system path ?

8:12 currently I'm have to do -

8:12 ,(.replaceAll "a.b.c" "\\." (str java.io.File/separator java.io.File/separator))

8:12 clojurebot: "a//b//c"

8:12 _na_ka_na_: File/separator is two times coz of windows

8:19 mikem: hoeck: ah great, thanks for that clarification

8:20 hoeck: mikem: to see what they contain, you can use a dummy macro like this: (defmacro foo [] (println &env &form))

8:21 mikem: and expand in a let: (let [x 10] (foo))

8:38 mikem: also in clojure.core source, I see the ^ symbol used to denote metadata as well as type hints (ie: http://github.com/richhickey/clojure/blob/master/src/clj/clojure/core.clj#L124) -- is the ^ context aware?

8:40 i guess it must be

8:40 chouser: no

8:41 type hints *are* metadata

8:41 mikem: a lightbulb just went on over my head :P of course!

8:41 chouser: "^FooType foo" is just short for "^{:tag FooType} foo"

8:42 mikem: thanks :)

8:48 _na_ka_na_: hey can anyone solve my regex mystery, I'm not so proficient in Java,

8:48 ,(let [m (.matcher #"(.+)\.([^\.]+)" "a.b.c")] (.matches m))

8:48 clojurebot: true

8:49 _na_ka_na_: ,(let [m (.matcher #"(.+)\.([^\.]+)" "a.b.c")] (.groupCount m))

8:49 clojurebot: 2

8:49 _na_ka_na_: ,(let [m (.matcher #"(.+)\.([^\.]+)" "a.b.c")] (.group m 0))

8:49 clojurebot: java.lang.IllegalStateException: No match found

8:49 _na_ka_na_: Please tell me why the above fails?

8:50 rhickey: chouser: want to discuss recur?

8:50 chouser: rhickey: sure

8:50 _na_ka_na_: nvm got it

8:50 ,(let [m (.matcher #"(.+)\.([^\.]+)" "a.b.c")] (if (.matches m) (.group m 0)))

8:50 clojurebot: "a.b.c"

8:50 chouser: _na_ka_na_: clojure has re- functions that make these things easier.

8:51 rhickey: first and foremost, recur is about no stack usage - goto

8:51 with loop, the target is labelled by loop

8:52 chouser: yep, I'm with you so far

8:52 rhickey: with fns, the target is the same fn, with the same arglist. The 'this' is the fn, and implicit

8:52 you can't goto another method in the same this, or to another this

8:53 chouser: hmmm

8:53 rhickey: to do so would be a proper method call with stack overhead

8:55 chouser: because the fn is a java method and you can't change the value of 'this' within it.

8:56 rhickey: because you can't recur out of a method

8:57 naming this is what's broken as it is really not an argument supplied in the normal way

8:57 chouser: when you recur to a fn, locals are actually re-assigned, right?

8:58 rhickey: but doing so is useful and preferred

8:58 chouser: yes

8:58 chouser: and the JVM won't let you reassign 'this' even if you wanted to.

8:58 rhickey: but technically, rebound

8:59 chouser: 'this' is not an argument, nor a local in Java

8:59 chouser: right

8:59 no way to refer to it in the bytecode such that it could be rebound

8:59 rhickey: there's nothing to rebind

9:01 placing this in the arglist just makes it appear like something it's not

9:01 but we've done that

9:02 but that shouldn't swap our thinking around

9:02 this is not an argument

9:02 chouser: no, it's more of a debate.

9:02 sorry, j/k

9:02 rhickey: aargh

9:02 chouser: ok, I'm with you

9:03 rhickey: one way out is top forbid recur to method head in deftype/record method bodies, force using loop

9:03 but that seems like a loss

9:04 chouser: My concern was cheifly if it might actually be a argument on some hosts, or be able to act like one, that the behavior of the JVM here would lock us out of capabilities these other hosts might provide.

9:04 rhickey: doing so would make it obvious, because people that tried to loop-rebind this would find they couldn't then use it without using '.'

9:05 chouser: *sigh* I don't follow.

9:06 rhickey: if recur to head was forbidden in deftype/record method bodies, you'd be forced to say (foo [this x] (loop [x x] ... (recur new-x)))

9:07 chouser: yes, I see that.

9:07 rhickey: but if you wanted to recur with this ... (loop [this this x x] ... (recur new-this new-x))

9:07 but why would you do that if you didn't want to use this?

9:08 and if you did want to use this, you'd find yourself needing to use '.'

9:08 chouser: ah, instead of plain names to refer to your own fields, for example.

9:08 rhickey: and thus I hope understand why this isn't a bindable recur target, you must call another method to use it

9:09 yes, or explicit field ref

9:11 so, the this 'arg' is truly special, and it is surprising only recur exposes that

9:12 chouser: ok, it that last point that finally makes it click for me

9:12 rhickey: I think the choice of propagating the specialness to recur is least appeal atm

9:13 so either we call out this arg, and thus why it can't be in recur, or disallow recur to deftype/record method head

9:13 chouser: in the method bodies x means (.x this), but if you could rebind 'this' those would mean different things. or something. just broken.

9:13 rhickey: we have the former right now

9:14 djpowell: I'm no fan of throwing the kitchen sink into clojure, but I would have liked to see some version of clojure.contrib.repl-utils/show brought across with clojure.repl - it was very handy to have, especially if you are used to using an IDE to remember all your method names.

9:20 chouser: djpowell: I'm with you on that.

9:21 rhickey: I think the current behavior of recur is good, now that I understand why.

9:22 rhickey: so, what do people prefer - recur not pass this, or disallowed?

9:22 chouser: oh good!

9:22 chouser: disallowed doesn't seem any better

9:23 _na_ka_na_: rhickey: can you explain with an example how the first option would work?

9:23 rhickey: chouser: it would be better only in calling out methods as not first class fns, the heads of the latter being ok recur targets

9:24 chouser: yeah, and a more informative error message, etc.

9:24 rhickey: _na_ka_na_: (foo [this x] ... (recur new-x))

9:24 _na_ka_na_: rhickey: and inside the method body we can use (.a this) (.b this) as usual right?

9:24 chouser: But the "what" is clearly documented as it is, and you can always use 'loop' to get explicit and clear behavior

9:25 rhickey: _na_ka_na_: inside you can just use a and b

9:25 chouser: as you said, you could even do (loop [this this] ...) if you want, but then the meaning of plain field symbols goes all wonky

9:25 rhickey: chouser: right, recur would not be inconsistent in any way

9:26 _na_ka_na_: great I think, then the first option sounds good

9:26 but would require some calling out, as you said

9:27 chouser: some day the error case for recur could notice an attempt to use 'this' and give a more helpful error, but that's a nicety that's a whole different level of concern than I was trying to bring up.

9:27 rhickey: chouser: if you do (loop [this this] ...) I don't see any problem with plain fields. Do you think people will expect them to move to the new this?

9:28 chouser: no, they won't, or at least it'll be immediately obvious why they don't.

9:28 _na_ka_na_: I think people with lesser Java experience would, no?

9:28 chouser: no, I really don't think so.

9:29 (defrecord C [a] (foo [this] (prn a) (loop [this this] (prn a) (when a (recur other-c))))

9:30 I think it would seem magical and unexpected for the a's inside the loop to get new values on recur

9:31 rhickey: yeah, and the lack of use of this in the body a sure sign of something wrong

9:31 SinDoc: Any ideas as to making ADTs in Clojure?

9:31 rhickey: SinDoc: deftype

9:32 chouser: really, the only answer I needed for my original concern was "what about plain symbols referring to fields?"

9:32 I wasn't considering those.

9:32 With them in the picture, my argument (er, debate) falls apart.

9:32 SinDoc: rhickey: Thanks, I'm on it.

9:34 _na_ka_na_: chouser: Can you explain what the intended behavior is in the above example .. when you recur with other-c ?

9:35 rhickey: chouser: still, that's more of the symptom than the root cause

9:35 chouser: _na_ka_na_: my point is that the intended behavior is a bit non-sensical

9:36 _na_ka_na_: My thinking is if at all people do that (i.e. loop [this this]) they'd expect it to change?

9:36 rhickey: (foo this [x] ... (recur new-x))

9:37 chouser: _na_ka_na_: Maybe it should use (.a this) inside the loop instead of just a

9:37 rhickey: yeah, that thought occured to me.

9:37 or maybe :as this up at the top. ;-)

9:37 rhickey: is more akin to fn, but a break from the protocol sigs

9:37 chouser: heh

9:38 no, it's better than :as at top by a lot

9:38 the alignment with self-naming fns is strong

9:38 _na_ka_na_: noobish question, but why is it at all necessary to keep a 'this' arg ?

9:39 is it can never change, is there even any point ?

9:39 s/is/if

9:39 chouser: you need to be able to refer to it

9:39 rhickey: _na_ka_na_: for method self-calls and to pass your this to others

9:39 chouser: so you can pass it as an arg to other functions, that sort of thing.

9:40 _na_ka_na_: hmm, got it!

9:43 what if, this were made a special symbol inside a method call? I mean, (defrecord C [a] (foo [x] (.. x, a, this all available..)))

9:44 just like in Java

9:45 chouser: _na_ka_na_: These options have all been discussed. :-) Previously you could name the 'this' for the whole defrecord by saying ":as this"

9:46 one problem with that is that your protocol was (defprotocol P (foo [this x])) ...a different number of args

9:46 _na_ka_na_: chouser: oh, I'm late then, nvm

9:47 chouser: I don't know if that's the main reason rhickey changed it or if there was something else more compelling.

9:48 _na_ka_na_: hmm, but can be solved by saying this is special

9:48 just checked, in Java you get invalid VariableDeclaratorId

9:48 void f(int this){}

9:50 Licenser_: hmm anyone using enclojure?

10:01 cemerick: Licenser_: yes

10:10 Licenser_: cemerick: did you ever have the problem that you can't create new projects?

10:11 * fogus_ wonders if the project name ends in "jure" :p

10:11 cemerick: Licenser_: I've never created a clojure-specific project in netbeans/enclojure. Just a regular java project with clojure dependencies is just fine.

10:12 (i.e. either a netbeans-specific project, which you can configure through the UI, or a maven project, from which netbeans will pull all configuration / dependency info)

10:13 Licenser_: *nods* okay too sad

10:27 cemerick: Licenser_: why sad?

10:30 somnium: I'm a bit disappointed that (ahem) 'Fantom' has made it to the available plugins list ahead of Clojure

10:31 cemerick: somnium: this is in netbeans?

10:32 oh, yup, there it is

10:40 chouser: ugh, I hate discovering I've been building on an incorrect assumption

10:40 bozhidar: most people do :-)

10:41 Hodapp: well, some people will argue for hours in the hopes that the assumption will prove correct or that people will start to believe it is

10:48 chouser: turns out this thing is an identity not a value.

10:49 speaking of which, it's interesting that clojure's all about the split between identity and value, and it has functions 'identity' and 'val'.

10:52 lpetit: rhickey: reminder for you to add clojure.com ref in #clojure 's topic :)

10:55 drewr: quick macro question

10:55 how can I get `((foo) (bar) (baz)) to expand to (foo) (bar) (baz)?

10:56 lpetit: drewr: you can't

10:56 bozhidar: clojure.com?

10:56 clojurebot: clojure is not groovy

10:56 drewr: the normal idiom is `(do ~@(....)), but the wrapping do won't work in this case

10:56 somnium: clojurebot: mechanic?

10:56 clojurebot: No entiendo

10:56 lpetit: drewr: but you can have `(do (defn (...)) (def ...)) at the top level

10:57 chouser: drewr: a macro returns a single thing, it can't return 3 things

10:57 lpetit: drewr: if the macro is called from top level, the do will be read as if each of its child were emitted in sequence

11:00 drewr: ok

11:01 I should be able to expand it in a parent macro

11:01 just wanted to make sure I wasn't missing an obvious hack

11:07 cgrand: ,(-> (range 33) vec transient pop! count )

11:07 clojurebot: java.lang.IllegalAccessError: Transient used after persistent! call

11:08 cgrand: ,(-> (range 42) vec transient pop! count )

11:08 clojurebot: 41

11:09 Plouj: (doc source)

11:09 clojurebot: "clojure.contrib.repl-utils/source;[[n]]; Prints the source code for the given symbol, if it can find it. This requires that the symbol resolve to a Var defined in a namespace for which the .clj is in the classpath. Example: (source filter)"

11:09 Plouj: (source doc)

11:09 for some reason my slime-repl doesn't find source

11:10 ,(source doc)

11:10 clojurebot: java.lang.Exception: Unable to resolve symbol: source in this context

11:10 bozhidar: have you required it?

11:10 Plouj: yeah

11:10 bozhidar: only required or used?

11:11 Plouj: humm

11:11 actually it seems that (clojure.contrib.repl-utils/source doc) works

11:11 (clojure.contrib.repl-utils/source doc)

11:11 ,(clojure.contrib.repl-utils/source doc)

11:11 clojurebot: java.lang.ClassNotFoundException: clojure.contrib.repl-utils

11:11 Plouj: weird, I used to get that ClassNotFoundException too

11:13 bozhidar: I do a

11:13 (use 'clojure.contrib.repl-utils)

11:13 and (source source) for example works just fine for me

11:14 clojure 1.1

11:14 Plouj: humm, that works for me too, now

11:16 bozhidar: when you do an import you have use the full namespace before the symbol unsless you used :as

11:18 stuarthalloway: anybody here write clojure code that uses Strings?

11:19 if so, take a look at https://www.assembla.com/spaces/clojure/tickets/359-promote-contrib-string and tell me what's right/wrong about this plan

11:24 fogus_: I might find better names for chop and chomp

11:29 stuarthalloway: fogus_: well do it then! :-)

11:30 those names are common to the scripting languages, but if you've better ones I am all ears

11:30 maybe EndOfStringCleanupFactoryCreator.getInstance.create.removeStuff(options)

11:31 fogus_: I suspected that they were.

11:31 I suppose if they are ubiquitous then I'm the weird one here

11:31 stuarthalloway: still, if you have any other names at all I would like to hear them

11:31 candera: There are only two hard problems in computer science: naming things, cache invalidation, and off-by-one errors.

11:31 eikke: does clojure have a 'zip' equivalent?

11:32 somnium: I think code like: (-> *nomnom* chomp slurp chop chop spit) is rather elegant

11:32 cgrand: eikke: (map vector coll1 coll2 ...)

11:32 fogus_: Is options a concrete realization of IDoWeirdStuffToStringsKeySet?

11:32 eikke: cgrand: ah, makes sense...thanks!

11:33 dnolen: stuarthalloway: why promote chomp if String.trim() is "similar and faster" ? I'm curious as to why that's not just called trim and have it call String.trim

11:33 stuarthalloway: if their semantics are identical then chomp will get dumped

11:34 fogus_: dnolen: chomp works on the end only

11:35 bozhidar: btw should upper-case and lower-case actually be uppercase & lowercase?

11:35 * stuarthalloway uses fogus_ as a javadoc replacement

11:35 dnolen: fogus_: ah

11:35 stuarthalloway: bozhidar: don't think so

11:35 * fogus_ awaiting Javadoc commands

11:35 stuarthalloway: the Java versions camel case at the 'c'

11:35 bozhidar: according to the dictionary upper case and uppercase are both valid

11:36 and I think that for a function name the single word should be favoured

11:36 stuarthalloway: so we are being "consistent" with Java, in some odd sense

11:36 bozhidar: I assumed so

11:36 arohner: does congomongo support sending JS to the server?

11:36 bozhidar: I'd prefered names like upcase/downcase - they sound more groovy ;-)

11:37 stuarthalloway: so nobody is going to say "you forgot my favorite string function"?

11:37 somnium: arohner: there's a method, db.eval on one of the db classes.

11:37 bozhidar: other than that I think the library's got what is generally needed

11:37 arohner: somnium: and when querying?

11:37 bozhidar: sometimes there are separated ltrim/rtrim methods though

11:37 somnium: arohner: I found its quite easy to crash a mongod with it though

11:38 arohner: somnium: oh, fun. Thanks for the warning

11:38 stuarthalloway: bozhidar: those exist in contrib, but are not (yet) on the list for promotion,

11:38 somnium: arohner: I think there's a $js or $eval key

11:39 stuarthalloway: in other news: we are going to start doing sublibrary builds for contrib

11:39 bozhidar: stuarthalloway: where are you promoting this string functions to?

11:40 stuarthalloway: to address the problems people have expressed around unnecessarily coarse dependencies + churn in contrib

11:40 bozhidar: clojure.string in clojure.jar

11:40 bozhidar: great

11:40 stuarthalloway: the sublibrary thing seems like boring detail work for someone (hoping to sucker sierra into it :-) )

11:40 fogus_: I got nothing for renames, the best I could do was remove-last for chop... chomp is so narrow in focus that any other name would be just as opaque

11:41 bozhidar: btw I think I read in your book that your opinion was that stuff like String manipulation don't need clojure wrappers

11:41 stuarthalloway: ... but the sublibraries should be an easy win for library users ... or am I missing some danger here?

11:42 bozhidar: string manipulation doesn't need clojure wrappers, but the community seems to like them, *and* some of the ones in contrib have usability or performance problems

11:42 so if they are going to be there, they might as well be right

11:43 bozhidar: sure

11:43 I'd probably prefer them myself if there are part of clojure.jar

11:44 since I generally avoid using stuff from contrib, fearing the extent to which they were tested

11:44 somnium: is (upper-case "foo") => (.toUpperCase "foo") ?

11:45 bozhidar: yes

11:48 fogus_: Oh I see now. chop and chomp are Perlism.

11:49 bozhidar: fogus_: and Rubism as well

11:50 somnium: I wonder if haskell is the only language with a function called 'intercalate' in its std-library

11:52 fogus_: If we change chomp to rstrip, then we can add an additional lstrip, and then add ltrim and rtrim. too much? :p

11:53 stuarthalloway: fogus_: not seeing them used much in code to date...

11:54 fogus_: Fair enough. It might still be useful to rename chomp to rstrip

12:01 bozhidar: I think chomp will do fine

12:01 and there is no problem to have a couple of sinonyms for some function I guess

12:02 this was one of the things I liked a lot about Ruby

12:02 chouser: I very very much dislike that about Ruby

12:02 bozhidar: for me in Clojure a bad name choice was the count function

12:02 yacin: i want to add jpcap to a lein project i'm working on. but it isn't in a mvn repo and it requires a C-Java JNI library to be compiled

12:02 bozhidar: I remember when I first needed it

12:02 yacin: how should i go about packaging it?

12:02 bozhidar: trying (size ..)

12:02 (length ...)

12:03 without consulting the docs I'd never have figured out that I needed count...

12:04 chouser: I dislike the many leftovers from Perl and the end for end statements

12:04 fogus_: rstrip is much more descriptive and does not require that you have experience in some esoteric language. ;)

12:04 bozhidar: but I don't think that the freedom of choice that Ruby's authors have given developers is that bad

12:05 though it might be confusing indeed if you're not familiar with the language

12:05 fogus_: Perl is far from esoteric - after all it's far more popular than Clojure

12:06 from a JAPH's point of view probably Clojure is just as esoteric ;-)

12:06 fogus_: plus rstrip leaves the door open for lstrip... what does chomp provide? lchomp? champ?

12:06 somnium: has anyone ported Acme::Buffy to clojure?

12:06 fogus_: bozhidar: Just kidding

12:07 bozhidar: fogus_: just kidding back ;-)

12:08 I used to do a lot of programming in perl some 5-6 years ago, but know I'm having hard time remembering even the basics

12:08 it was a fun ride while it lasted, though :-)

12:09 now*

12:10 fogus_: Finally, rstrip works better in an overall StrippingProtocol (not what you think).

12:10 * fogus_ has officially spent too much time thinking about chomp

12:10 rhickey: fogus_: rstrip is just about newlines?

12:10 bozhidar: you should think more about strippers ;-)

12:10 fogus_: rhickey: yes

12:11 rhickey: fogus_: and lstrip is also?

12:11 fogus_: yes

12:11 rhickey: is that a real use case - leading newlines?

12:11 bozhidar: rhickey: fogus_ is not correct

12:12 fogus_: :(

12:12 bozhidar: rstrip/rstrip should generally strip every whitespace character

12:12 cgrand: rhickey or stuarthalloway: did you see https://www.assembla.com/spaces/clojure/tickets/358 ?

12:12 bozhidar: including newlines

12:13 fogus_: bozhidar: I thought that was trim/ltrim/rtrim's job?

12:13 stuarthalloway: cgrand: just claimed it

12:13 bozhidar: fogus_: true

12:13 stuarthalloway: thanks!

12:13 bozhidar: that's why chomp is not exactly rstrip

12:14 since at least in Perl it removed only the trailing newline

12:14 if any

12:14 replaca: rhickey, stuarthalloway: are we going to do something about the mismatch between with-in-reader and line-seq? This messes up a nice file reading idiom.

12:14 cgrand: stuarthalloway: ok, thanks

12:14 rhickey: replaca: which mismatch?

12:14 bozhidar: in most languages - strip == trim

12:15 replaca: with-in-reader returns a PushbackReader and line-seq wants a BufferedReader (I think that's right)

12:16 rhickey: yeah, that's it

12:17 rhickey: replaca: what's the fix?

12:19 replaca: rhickey: dunno, I'm not sure I'm the one who knows all the issues (understanding what kind of readers we want where). Maybe with-input-reader should open a buffered reader (but I think other funcs want pushback readers) or maybe line-seq should be more relaxed about what kind of reader it takes.

12:19 stuarthalloway: build on top of a language with good IO abstractions? :-)

12:19 fogus_: bozhidar: Not in contrib.string, which is where I tried to constrain my focus. To me chomp and chop are meaningless names, but I do not have a heavy shell text processing background. strip and trim are descriptive and represent names that I might actually look for.

12:19 replaca: rhickey: all I know is that they don't play well together :)

12:20 rhickey: I'm happy to start a discussion on the list and try to surface all the issues and drive it to resolution if you'd like

12:21 bozhidar: fogus_: I tought we were have a more general discussion, about the naming -> what should it do. Sorry about that

12:21 rhickey: replaca: that would be great, thanks

12:21 replaca: rhickey: k, I'll do it later on today

12:22 bozhidar: were having*

12:22 I hate my typing...

12:22 patrkris: why is [null]

12:22 ... prepended to all output from leiningen?

12:25 stuarthalloway: patrkris: level 1 answer: it's an ant thing

12:25 patrkris: stuarthalloway: ah... any way to get around it?

12:25 stuarthalloway: maybe -- years since I forgot ant

12:25 patrkris: :)

12:26 stuarthalloway: if there is a way, it probably would require some small change to lein to expose it

12:31 Chousuke: I think it actually has something to do with the logging facilities

12:32 angerman: it's not possible to have a tree-shaker for clojure, right?

12:36 arohner: angerman: I don't think it's possible to do purely in clojure. it'd have to understand the host language as well

12:37 angerman: arohner: well I guess cleanly designed and separable librarys would make it not such much a problem :D

12:38 and otherwise I guess it could get really trick to figure out what is dynamically loaded ...

12:40 mefesto: is there an existing function that will provide a lazy-seq of chars for a Reader?

12:44 arohner: mefesto: what are you trying to do?

12:44 ,(seq "foo")

12:44 clojurebot: (\f \o \o)

12:44 arohner: somnium: are you interested in a patch to congomongo that allows you to send arbitrary JS to the server?

12:45 mefesto: arohner: parsing some file and i need to be aware of newlines depending on if im in quotes or not

12:45 Licenser_: Writing clojure in windows is a sad experience :(

12:45 mefesto: so line-seq wouldn't work since a quote could be open on line 1 and closed on line 5

12:45 arohner: mefesto: oh, a java stream Reader, not a clojure compiler reader

12:45 candera: Licenser_: agree. It's the ghetto.

12:45 mefesto: arohner: yeah, sorry for the confusion.

12:46 Licenser_: I tried emacs, ccw and enclojure all make me cry :/

12:46 Why can't my boss give me a MacBook :P

12:46 Chousuke: mefesto: (repeatedly #(.read thereader)) should work

12:47 candera: I settled on emacs, and I like it well enough, but it's definitely got more friction than on other platforms. But VirtualBox and Ubuntu are both free, so often I just go virtual.

12:48 mefesto: Chousuke: i went this route since i wanted them to be chars, overkill?: https://gist.github.com/6d7c8a2c9bcd748b22fb

12:49 ,(char -1)

12:49 clojurebot: java.lang.IllegalArgumentException: Value out of range for char: -1

12:49 Licenser_: candera: I use emacs on my mac but I don't like to do all the jar management by hand it makes me unhappy :P and I can't use maven/lein/whatever else

12:49 Quiesce: Licenser_: Yeah? What would you use on this hypothetical gift MacBook?

12:49 Chousuke: mefesto: that's essentially what my suggestion does

12:49 Licenser_: Quiesce: AquaEmacs :P and a usefull internet connection hopefully

12:49 Chousuke: mefesto: except it doesn't check for EOF, it includes in in the stream

12:51 angerman: yea, Aquamacs is pretty nice. ...

12:51 except when you run into C-; making the meta switch :D

12:51 somnium: arohner: sure

12:53 drewr: isn't there a flatten-1 somewhere that only flattens a sequence one list deep?

12:54 ie: (flatten-1 '(1 2 (3 (4 5)))) -> (1 2 3 (4 5))

12:54 or is it called something else?

12:54 chouser: apply concat

12:54 drewr: hm

12:54 chouser: hm, or maybe not in that case.

12:55 ,(mapcat #(if (coll? %) % [%]) '(1 2 (3 (4 5))))

12:55 clojurebot: (1 2 3 (4 5))

12:55 chouser: dunno if there's a flatten-1 somewhere or not

12:56 drewr: my contrived example isn't quite right

12:57 '((1 2) (3 4) ((5 6) (7 8))) -> ((1 2) (3 4) (5 6) (7 8)) is more like what I need

12:57 my macro needs to end up with a list of single sexps

12:58 chouser: I assume it's not always just the last one that's grouped an extra level?

12:58 drewr: right

12:59 chouser: ,(mapcat (fn [[x :as a]] (if (coll? x) a [a])) '((1 2) (3 4) ((5 6) (7 8))))

12:59 clojurebot: ((1 2) (3 4) (5 6) (7 8))

13:00 drewr: ah, thanks, I think that works

13:01 KirinDave: I finally got around to reading "Multiple Dispatch in Practice"

13:02 Man, it's really interesting how there seems to be this consistent but small desire for multiple dispatch

13:03 drewr: what's strange is that my solution worked if I called it as (foo '((...) (...))), but idn't when called as (foo (map bar '(....))); bar being what transformed the original forms into the nested forms

13:04 ...which shouldn't have changed the behavior of the flatten

13:04 but oh well

13:04 zakwilson: Given enough time, almost every project needs multiple dispatch or some sort of ugly hack to simulate it.

13:05 KirinDave: zakwilson: I was just surprised at how consistent that demand is

13:05 And it's not for like 7 way dispatch, the majority is 2 term dispatch

13:07 rhickey: KirinDave: and you can do clean, extensible 2-way dispatch using double dispatch and protocols, which don't have the problems of using interfaces for the same task

13:08 KirinDave: rhickey: When you say double dispatch you mean?

13:08 rhickey: KirinDave: dispatching on 2 terms via 2 single-dispatches

13:08 KirinDave: Ah

13:09 So yeah, bouncing back and forth a la visitor?

13:09 rhickey: normally that's a problem using interfaces, leading to the dreaded visitor

13:09 but protocols are not type intrusive, so it's clean and open

13:09 KirinDave: rhickey: I must confess, from a strictly aesthetic perspective I don't like that solution.

13:09 protocols DO make it easier.

13:10 And the 2 dispatch system is more amenable to trace tree optimizations.

13:10 Still, it just sticks in my teeth. :)

13:10 rhickey: not just easier, substantively different in that it is open, double dispatch with interfaces can't be

13:11 KirinDave: I understand and agree. :)

13:11 I just like reading code where the double dispatch is clear

13:11 So md methods seem like a better notation to me. It's very clear what's happening.

13:27 Oh McCarthy

13:27 srry

14:18 islon: is there a way to set the number of agent threads used by send-off?

14:18 chouser: no, it grows as needed.

14:21 islon: hmmm... strange... I used send-off to run a bat (java.lang.Process) that blocks forever, the second send-off I called (another different bat) never started

14:21 chouser: to the same agent?

14:22 islon: yes... ok I got it...

14:28 cemerick: sending to one's own threadpool/executionservice is on my 1.3 list

14:28 send-to, perhaps

14:30 rhickey: cemerick: send-to vs (agent ... :on-pool pool) ?

14:31 I don't think consumers want/need to know about the pool

14:31 chouser: that would influence only send-off not send?

14:31 rhickey: chouser: both

14:32 chouser: huh

14:32 cemerick: rhickey: that's why my first thought was send-to

14:32 send and send-off are thin abstractions for what pool to use

14:33 chouser: it's not uncommon for me to use send and send-off on the same agent because it's the action that controls that decision.

14:33 cemerick: right

14:33 islon: the :on-pool is implemented?

14:33 cemerick: no

14:33 chouser: seems weird to remove that option in order be able to use your own pool.

14:33 rhickey: If you are choosing its pool you must know how you are going to use it

14:33 cemerick: the usage can be mixed, though

14:34 fogus_: I try not to think about pools

14:34 rhickey: cemerick: so choose a pool that works for both, certainly we could only have send-off

14:35 but providing a pool at every send-to is a catastrophe from an app modularity standpoint

14:35 cemerick: yeah, I can see that

14:36 rhickey: really, looking back I'd rather have had only send and force you to choose a pool at agent construction

14:36 cemerick: In that case, the intended semantics of send and send-off would get blurry IMO. Blocking vs. non-blocking, ok, but again, you really do end up needing to know the specific characteristics of the corresponding pools.

14:36 right, yes

14:37 rhickey: cemerick: if you always use blocking-is-ok there is only one semantic

14:37 even if it doesn't ever block

14:38 chouser: I think that'd be fine with me.

14:38 rhickey: so send == send-off, supply a pool to get a compute-only agent

14:38 deprecate send-off

14:38 chouser: sure

14:39 islon: what about (binding [*agent-pool* my-pool] (do stuff...))

14:39 chouser: binding-only args are baaad.

14:39 especially in such close proximity to theads

14:40 (binding [*agent-pool* my-pool] (send foo #(do ... (send foo ...)))) ; sends to two different pools!

14:40 islon: right

14:43 remleduff: Do you think dynamic bound variables have been net positive to clojure? They seem to be where most of my head-banging problems have come from

14:44 Once you're used to them, it's less of an issue, but seems that (map some-fn-that-depends-on-dynamic-vars ...) is something everyone has tripped on at least once

14:44 cemerick: rhickey: sounds good to me

14:45 chouser: remleduff: I do wonder. My current take is that they're useful, but at the top of the list for ways to accidentally produce unintended behavior.

14:45 hiredman: binding is the doom of the world

14:45 (unless you use it to emulate multiple returns)

14:45 chouser: heh

14:46 remleduff: I think that would be the top check I'd like to see in a clj-lint project ;)

14:49 technomancy: hiredman: botsmack

15:13 bartj: anyone from an information extraction background and using clojure here?

15:14 * angerman thinks facebook uses PHP :D

15:20 cemerick: bartj: hi :-)

15:20 very broad concept there

15:59 remleduff: Is there a difference between butlast and drop-last?

16:00 chouser: hardly. drop-last is lazy

16:01 remleduff: Is there a difference between chomp and butlast/drop-last?

16:02 Oh, chomp checks if it's a newline

16:02 chouser: and returns a string, presumably. butlast and drop-last return seqs

16:02 oh, I see where you're ogin

16:02 goin

16:02 going

16:03 clojure.string/butlast instead of chop or less

16:03 remleduff: Probably slightly too big of a semantic difference

16:04 chouser: I think it's the same as chop -- drops one thing regardless of what it is

16:04 chomp/rtrim/rstrip are something else

16:06 remleduff: Oh yes, I meant chop ;)

16:09 fogus_: Is butlast defined by its drop-iness or its seq-iness, or are they inseparable?

16:09 tomoj: huh?

16:10 chouser: butlast should continue to return a seq, as it does now

16:10 ,(butlast "abc")

16:10 clojurebot: (\a \b)

16:11 chouser: but (clojure.string/butlast "ab") could certainly return "ab"

16:11 fogus_: That's kinda confusing no?

16:11 chouser: isn't that what clojure.string is all about?

16:12 fogus_: confusion?

16:12 chouser: right!

16:12 fogus_: :p

16:12 chouser: wait, no.

16:12 reusing names fron clojure.core, but applied to strings

16:12 fogus_: Well, that I'm not sure.

16:13 chouser: like replace, and ... others I can't think of.

16:13 tomoj: what does anyone think of the idea of having a single set of functions/macros paralleling map, filter, for, etc but which return the same type as their args, use transients or whatever speedups are available, and are implemented with protocols?

16:14 or is the seq abstraction too important to optionally abandon? hmm

16:14 remleduff: I really like the way protocols let you provide a default implementation and then specialize where appropriate, so I hope something like that happens

16:15 chouser: tomoj: I think there have been a couple efforts in that direction

16:15 tomoj: excellent

16:15 chouser: clojure.contrib.generic or something, and I think sean devlin has done something else.

16:15 * chouser is all about vague hand-waving today

16:18 tomoj: wonder what good names would be for those functions/macros

16:18 fogus_: That kinda leads into my whole reason for jumping on the string functions. I would like to see a different categories of protocols: 1) some that do something to X and return seqs and 2) some that do something to X and return things of type X 3) ???

16:19 chouser: hm... I wonder if it's the wrong approach.

16:19 tomoj: you would like to see #3 but don't know what it would be?

16:19 fogus_: not sure. It's not really formulated in my brain yet

16:20 remleduff: Why do you need functions that return a seq, as long as everything knows how to produce a seq when needed?

16:20 chouser: A chain of seq-processing fns on a vector with vec around them all is almost certainly going to be more efficient than producing a vector at each step

16:20 tomoj: even with transients?

16:20 hadn't considered that possibility

16:20 chouser: transients would still be eager

16:20 tomoj: ah, hmm

16:21 fogus_: darn... gotta go

16:21 chouser: lazy seqs, esp with the cell stuff that rhickey has mentioned, may be as fast as a hand written loop that processes each item fully before proceeding to the next.

16:21 tomoj: I guess the use case I am thinking of is doing a small chain near the inner loop and not wanting to do hashmap->seq->hashmap or whatever

16:21 chouser: such that intermediate objects not even be created.

16:21 tomoj: nice

16:22 chouser: even 1.1 has chunked seqs that can beat some naive hand-written loops.

16:22 so perhaps something that conveniently wraps the whole chain for you...

16:23 (same-type->> my-vector (map ...) (filter ...) (partition ...) ...)

16:23 tomoj: when we're working with seqables qua data not qua seqs, I wonder if this would still be faster

16:23 e.g. transforming a bunch of small maps with filter or something in the inner loop

16:24 if the seqables are small I guess it won't matter a whole lot anyway

16:24 hsjunnesson: So, hm..

16:24 tomoj: or maybe it would matter more? gah, I'm just confused now

16:24 chouser: heh

16:24 hsjunnesson: Okay, so I asked this in #leiningen but no one there replied. I figured people here might have a bead on this.

16:25 I uploaded a few jars to clojars and it took a few tries before I "got it", so now I need to delete a couple of jars.

16:25 tomoj: as the seqable grows, the O(n) conversion overhead (like (into {} ...)) becomes less visible, I guess

16:26 chouser: hsjunnesson: I wouldn't actually be surprised if there were no way to delete jars from clojars

16:26 hsjunnesson: That's kind of what I'm afraid of.

16:26 chouser: hsjunnesson: you might send email to the maintainer

16:26 hsjunnesson: I'll have to do that, thanks.

16:29 tomoj: I wonder if clojure is a good choice for a first language to teach to non-programmers

16:30 technomancy: hsjunnesson: yeah, you have to get _ato to do it for you =(

16:30 chouser: tomoj: I wonder that too. The biggest worry I have is the Java interop -- so good for getting things done, but such a bag of complexity for someone who doesn't already know OOP

16:32 tomoj: ah, hmm, hadn't even thought about java interop :(

16:32 learning only enough java to get by at the same time you learn clojure sounds terrible

16:33 SynrG: i know oop, but mostly via ruby. i'm only learning enough java to do clojure :/

16:34 chouser: if you could find enough fun and interesting exercizes that didn't require much (or any?) java calls, it might be perfect.

16:34 and now you could learn OOP via records and protocols before confronting all of Java's complexity

16:35 SynrG: mind you, i've read some java texts ... i've just never actually used it for anythign real

16:35 so i don't have what i'd consider a working knowledge

16:36 chouser: I'd especially love to see if a new programmer has any trouble at all with immutable collections, locals, and even HOF -- things that those of us who started in BASIC/Pascal/C/etc. have had to struggle through.

16:37 mefesto: i think my first reaction to someone that has only programmed in clojure would be, "you spoiled brat!" ;)

16:37 chouser: heh

16:38 I would show them for(i=0; i<foo.length; i++) { if(skip(i)) { i++ } } ... and watch them panic

16:43 _na_ka_na_: Hi

16:43 Ok, I come from the family of imperitive languages so macros and I are not really friends till now. I have a few basic qs reg. macros.

16:43 My understanding is macros (only?) live to make code shorter and sweeter by spitting out mechanical code for you.

16:43 For example if I'm repeatedly printing diff of two numbers, (println (- x y)),

16:44 I can (defmacro print-mah-diff [x y] `(println (- ~x ~y))) ; and (print-mah-diff x y)

16:44 But I've also seen macros such as (defmacro print-mah-diff [x y] (println (- x y))) (eg: gen-class)

16:44 chouser: that is one use-case, yes

16:44 _na_ka_na_: What would be the purpose of such macros? Wouldn't a fn work too?

16:45 mefesto: _na_ka_na_: i think the general rule is that if you can do it with just a function... then you don't need macros

16:45 _na_ka_na_: macros let you manipulate the forms before they are evaluated which can be very powerful

16:46 _na_ka_na_: think manipulating an AST

16:46 chouser: gen-class is a macro just so you don't have to quote things a bunch. It's a thin wrapper around generate-class which is a function

16:47 remleduff: _na_ka_na_: Your example calculates the substraction at compile time... it might be used for optimization of an expensive constant

16:48 Borkdude: When is a array-map going to turn into a hash-map when conj-ing elements to it?

16:48 _na_ka_na_: chouser: Didn't quite get that, gen-class couldn't be a fn ?

16:49 chouser: gen-class could be a function, but you give it a lot of symbol names for functions and classes that don't exist yet

16:49 _na_ka_na_: Hmm got it

16:49 chouser: if those were evaluated before being passed to a function, you'd get errors. So instead you'd have to quote all of them.

16:50 if generate-class weren't private, you could just call (generate-class '{:name ... :methods ...}) ...it would work fine.

16:50 remleduff: _na_ka_na_: macros are also for selective evaluation. You couldn't implement a short-circuiting "or" function as a function.

16:50 chouser: so that's another use-case for macros -- to simplify the interface to a function

16:51 _na_ka_na_: remleduff: we could quote the stuff to be ored?

16:51 chouser: what macros *are* is a hook into the compilation process. What they're *for* is anything you can dream up that needs to hook into the compilation process.

16:52 _na_ka_na_: not quite, because then you'd have to 'eval' those quoted things, which isn't quite the same

16:52 _na_ka_na_: Ok so I'm noting all of these points down, and will ponder over them next few days :P

16:53 chouser: without macros, 'or' could be a function that takes a bunch of no-arg functions.

16:53 (or-fn #(foo) #(bar) #(baz)) instead of (or (foo) (bar) (baz))

16:53 _na_ka_na_: chouser: how not same? I mean evaling the quoted things.

16:54 chouser: but that would still be more work at runtime than what 'or' does now. So that's another use-case -- performance improvements by doing some work at compile time that would otherwise have to be done at runtime.

16:54 not the same because eval doesn't have access to the local environment where it's called.

16:55 eg. this doesn't work: (let [a 1] (eval '(prn a)))

16:55 _na_ka_na_: Hmmm

16:55 Borkdude: _na_ka_na_: are you perhaps that guy who asked a Scala call-by-name/Clojure macro question on Twitter? :)

16:56 _na_ka_na_: One curious q : so how is (x || y) implemented in imperative langs w/o macros?

16:56 chouser: _na_ka_na_: direct compiler support, usually. you can't write your own.

16:56 _na_ka_na_: Borkdude: Nope

16:57 chouser: _na_ka_na_: some langauges have explicit support for delayed arg evaluation (scala), otherer are always lazy (haskell)

16:57 _na_ka_na_: Haven't touched Scala (yet)

16:57 Hmm, that sounds interesting

16:57 Borkdude: chouser: he (the guy on Twitter) said he could do most macro's with Scala call by name... I wonder how far he would get, don't know Scala though

16:58 chouser: Borkdude: not far at all

16:59 humphrej: Hi

16:59 here's an add-watch puzzler http://clojure.pastebin.com/N4TauWpV

16:59 _na_ka_na_: So how does the compilation work? Does the reader first macroexpand all macros and then compile stuff?

17:00 humphrej: should a call to await cause a watcher-fn to update?

17:00 _na_ka_na_: What if there are nested macro calls like or, .. when is the next time macroexpand is called?

17:00 chouser: humphrej: old value is the same as the new value -- you can ignore if you want.

17:01 mefesto: _na_ka_na_: i believe macro expand continues until all macros are fully expanded

17:01 chouser: _na_ka_na_: each top-level form goes through several stages before the next top-level form is touched.

17:01 1. read (text to nested data structures)

17:02 2. macroexpand of the outermost form, repeatedly until it is a special operator

17:03 3. analysis of that outermost special operator. depending on the op all kinds of special things may be done. frequently steps 2 and 3 are done recursively for one or more args to this outer special form

17:03 humphrej: chouser: yes but I'm thinking the equality test could be expensive if the agent state is large

17:04 chouser: 4. walk the tree that results from the analysis, emitting bytecode

17:04 5. (optionally) save bytecode to .class files

17:04 6. load and run bytecode.

17:05 1 is "read time", 2-5 are "compile time" and 6 is "runtime"

17:05 _na_ka_na_: thanks! chouser take makes a lot of things clear, are these details somewhere on the clojure.org page?

17:06 Borkdude: Am I right that an array-map of 8 kv's turns into a hash-map when conjed a new kv pair?

17:06 _na_ka_na_: one doubt: macroexpand won't expand inner level forms .. like for or .. right? they are expanded only at runtime?

17:06 chouser: note that step 2 involves calling functions provided by the user -- so what is "compile time" for the current top-level form is "runtime" for the macros being expanded.

17:06 _na_ka_na_: no, those inner levels are expanded as parts of the recursion at step 3

17:07 Borkdude: Wait, 9.

17:07 _na_ka_na_: Hmm so after step 3. macros no longer exist

17:07 Borkdude: ,(type (conj (array-map 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8) [9 9]))

17:07 clojurebot: clojure.lang.PersistentHashMap

17:08 chouser: Borkdude: yeah, but you shouldn't rely on that.

17:08 _na_ka_na_: essentially, yes!

17:08 Borkdude: chouser: it could differ per OS or smth?

17:08 _na_ka_na_: lol that smiley looks nice in a data structure

17:08 chouser: Borkdude: per version of clojure

17:09 Borkdude: chouser: aha

17:16 _na_ka_na_: I was trying to do something like ... (defmacro m1 [x y] (println (+ x y)))

17:16 (defmacro m2 [x y] (do (m1 x y) (println (- x y))))

17:16 and it was not compiling .. I couldn't understand .. but now I do :)

17:16 chouser: well! good.

17:17 _na_ka_na_: Is it idiomatic to do something like .. (defmacro m2 [x y] (do (macroexpand `(m1 ~x ~y)) (println (- x y))))

17:17 chouser: I don't think so. I have used macroexpand in a macro for the very first time last week, and it seems *very* specialized.

17:18 _na_ka_na_: Didn't quite follow the very specialized part

17:18 chouser: the reason your m2 doesn't compile is because you're passing the symbols x and y to m1, which then tries to add them.

17:18 _na_ka_na_: yup

17:19 chouser: you might want: (defmacro m2 [x y] `(do (m1 ~x ~y) (println (- ~x ~y))))

17:20 Chousuke: except that will evaluate x and y twice

17:20 _na_ka_na_: ya for that one can use let

17:20 chouser: using eval, macroexpand, or anything with side-effects in a macro definition is pretty suspect.

17:21 actually, to a certain extent using defmacro is a bit suspect. :-P

17:21 remleduff: Hmm, doesn't any macro that expands to def have side effects?

17:21 Chousuke: remleduff: no

17:21 remleduff: the code they expand to has side-effects, not the macro

17:22 remleduff: ah, makes sense

17:22 Chousuke: it is possible to use the whole language in a macro. It's just not generally done. But I think for example using reflection to generate bindings for an API could be a good application of more complicated macrology.

17:23 chouser: Chousuke: yes

17:23 but you ought to be able to justify at each step why you're doing it in a macro instead of a function.

17:24 Chousuke: Doesn't penumbra do something like that btw?

17:25 IIRC reflects the jogl stuff and generates clojure functions/macros... Or maybe I'm confusing it with something else.

17:25 chouser: of course once you're in that deep you might want to do like clj-native and just call into the ASM lib directly.

17:27 bozhidar: I was wondering what is the idiomatic way in Clojure to cache a function return values

17:28 chouser: memoize

17:28 bozhidar: in a trivial example say we want to cache factorials between invocations

17:29 chouser: so I should basically just wrap my existing function with memoize and that's all?

17:30 chouser: for trivial cases, that's it.

17:30 _na_ka_na_: bozhidar: even shorter is defn-memo (c.c.def)

17:34 goodmike_mh: Hey, I'm the numbskull who asked on the Google group about how Agents are lock-free...

17:34 Are either of the authors of Agent.java online, and would you be willing to humor me?

17:35 chouser: Pretty sure Agent.java is all rhickey.

17:35 but others may be able to help

17:36 goodmike_mh: git blame tells a different tale, chouser. :-)

17:36 chouser: hmph.

17:36 Borkdude: chouser: why is it that a conjed array-map sometimes returns a hash-map?

17:36 goodmike_mh: But I'll take any help i can get

17:36 bozhidar: chouser, _na_ka_na_ : thanks

17:36 chouser: Borkdude: because array-maps are only efficient when they're small.

17:36 goodmike_mh: I can tell it's all about the agent's queue

17:37 The queue can only be updated (e.g. given a new value) in an atomic compareAndSet

17:38 Then the actions in the queue are executed

17:38 Borkdude: chouser: so 9 (varying over Clojure versions) is kind of the flipping point of efficiency?

17:38 chouser: Borkdude: that's the conclusion currently implemented, yes.

17:39 Borkdude: chouser: still you can use array-maps bigger if you want, because of ?

17:40 chouser: goodmike_mh: almost. if enqueue takes the queue size from 0 to 1, it starts a chain of executions

17:41 goodmike_mh: chouser: Yeah, I saw that! I was a little confused by why there's an explicit action.execute in case the queue was empty before the compareAndSet

17:41 chouser: goodmike_mh: after each action is done, it's popped off the queue (CAS again), and if there is another action to be done it is executed

17:41 so each action on an agent triggers the execution of the next action on the agent

17:42 goodmike_mh: chouser: I assume there is a case in which the queue was non-empty at the end of Agent#enqueue. I'm not sure what happens then.

17:43 chouser: goodmike_mh: nothing happens then. it relies on the fact that whatever action is currently in the executor will trigger the next when it's done.

17:43 goodmike_mh: chouser: Whoa. OK. I think I see that.

17:44 chouser: so it's the atomic updating of the queue that keeps actions from overlapping. It looks like it makes the agent's actions execute in serial order. Is that right?

17:45 chouser: agent's actions execute in serial order, yes.

17:46 goodmike_mh: chouser: Thanks. I really appreciate being able to ask someone who wrote the code.

17:46 chouser: Even if he doesn't remember doing it. :-)

17:46 chouser: the actions are kept from overlapping by the CAS on the queue and the use of that to make sure that only one place (either enqueue or the current action) triggers the next action.

17:47 I didn't write it! I tweaked the error handling a bit.

17:48 goodmike_mh: chouser: The CAS on the queue is really sweet.

17:48 chouser: yeah, that was definitely not me

17:48 goodmike_mh: chouser: Regardless, thanks for the explanation.

17:48 chouser: you're welcome

17:50 _na_ka_na_: what does point 5. clojure.org/agents - "If during the function execution any other dispatches are made (directly or indirectly), they will be held until after the state of the Agent has been changed." mean?

17:53 tomoj: _na_ka_na_: if you send or send-off during the action you send(-off) to an agent, those will not happen until after the current agent is finished

17:53 I don't know the vocabulary to explain it better :(

17:55 _na_ka_na_: Hmm got that tomoj, I wanted to understand why that is so?

17:55 tomoj: oh, hmm

17:55 well, it's useful :)

17:56 not sure if there is a better reason... can agent actions be retried?

17:58 _na_ka_na_: don't think agent actions are ever re-tried .. but one explanation might be that the other agent to which there is a dispatch might want to see the updated state? doesn't sound like a good reason tho.

17:59 goodmike_mh: _na_ka_na_: I *think* the reason for holding the dispatch is to prevent contention. The conversation chouser and I just had was about how agents serialize the actions that update their state. So they have to happen one after the other.

18:01 _na_ka_na_: It's fairly common for the fn sent to an agent to include a send of the same fn to the agent, with the understanding that "this will happen later"

18:01 tomoj: like ants.clj

18:01 goodmike_mh: yep

18:02 _na_ka_na_: goodmike_mh: you mean an agent in its action fn sends an action to itself again?

18:02 kasperlanger: I think it's to make actions on agents atomic (the A in ACID)

18:02 goodmike_mh: _na_ka_na_: exactly. the fn contains a line like (send *agent* foo)

18:03 *agent* being the Var holding a reference to the current agent.

18:03 arkahn: covered in http://blip.tv/file/812787 with relevant bits at 71:43, specifically 72:50

18:03 goodmike_mh: _na_ka_na_: Are you suggesting a case in which the function sends a function to a different agent?

18:04 _na_ka_na_: hmm ok that might be an explanation then, but I can't immediately see why an agent would send to itself again

18:04 goodmike_mh: yes, it can be a common scenario no?

18:05 arkahn: _na_ka_na_: example code at the bottom of ants.clj http://tinyurl.com/322p5kf

18:06 goodmike_mh: _na_ka_na_: I'm not sure I would do that. :-) I prefer to coordinate state outside the current agent by opening a transaction (dosync) and updating refs. Let the coordinated state stay in refs.

18:06 tomoj: an agent action can send send itself to its agent again to set up a sort of infinite loop

18:06 and the action can do some check for whether to send again or not in order to terminate

18:06 arkahn: _na_ka_na: a function sends off to itself after checking for whether it should continue running and executing a sleep so it doesn't sit and spin too fast

18:07 tomoj: so it's a way to do the run loops you see in java threading stuff with agents

18:07 _na_ka_na_: goodmike_mh: not all situations would require coordination, for eg: agent a got a message, it just wants to tell agent b that it got a msg, doesn't care when agent b gets that msg

18:08 arkahn: it's my understanding that agents only provide for coordination so state change (i.e. the function in send or send-off) can happen safely

18:09 you're also guaranteed on order (it's fifo)

18:10 you can read an agent at any time but aren't guaranteed you'll see the latest changes

18:10 goodmike_mh: _na_ka_na_: Hmmm. An agent is primarily a way of encapsulating some state and controlling its updating. You have to provide behavior. They're not like objects in other languages with their own behavior. So I'm not sure that message-passing is the right approach here.

18:11 _na_ka_na_: In Clojure >= 1.1 promises are used to pass values between threads. Agent B might block on a promise until agent A sets it. You'd want to send-off the fn to B that blocks.

18:13 Just a thought. Please, no one go out and architect their systems based on my semi-informed comments.

18:15 arkahn: Ever since I learned about functions self-sending, I've wondered if it's currently common/idiomatic. I guess it's safe to say that Rich thought it was back in the day, whenever ants.clj was written.

18:16 it seems like a working contortion of the original intent for agents, but maybe I just don't know enough ; )

18:18 nDuff: I've got a loop/recur where I'm getting "recur arg for primitive local: remaining must be matching primitive"; however, to me, the types look like they should match. Is there a way to determine what the expected vs actual types are?

18:18 _na_ka_na_: goodmike_mh: what would be a good way to implement the following scenario: agent A, agent B are doing independent work.. A reaches a state when it wants to inform B about it, but B might be busy, so it doesn't want to be synchronous

18:20 kasperlanger: I didn't quite follow the atomicity part you mentioned

18:21 kasperlanger: If the function you send to an agent has no side effect except possibly mutating the agent and sending of stuff to other agents you know the whole thing will either happen completely or not at all

18:21 That's a really nice property to have

18:24 arkahn: nDuff: could you use 'class' to verify type?

18:25 _na_ka_na_: kasperlanger: but isn't is possible that after the agent state is mutated, action is sent to another agent which fails ?!

18:25 i mean the act of sending fails, not the action of other agent

18:25 nDuff: arkahn, ...explicitly wrapping the argument in question with (int ...) resolved the issue; I'm presuming the other value was being boxed to an Integer, perhaps?

18:26 kasperlanger: Yes the action on the second agent may fail

18:26 The atomicity property only holds on a single send not the whole chain of sends

18:27 oh

18:27 arkahn: nDuff: not sure without seeing the code

18:27 _na_ka_na_: didn't quite get, but how does point 5. ensure that? or if point 5. wasn't there how can the whole action not be atomic?

18:28 kasperlanger: I don't think sending fails since it's all local stuff but I'm speculating now :)

18:28 SinDoc: I'm using Clojure 1.2.0-master and have trouble with deftype

18:29 (deftype point [x y])

18:29 arkahn: kasperlanger: I don't think sending ever fails - but the assumption of state may have changed so you can determine at the time the function executes whether you'd like the function to complete

18:30 kasperlanger: ... trying to remember what that precondition check is called ...

18:31 nDuff: arkahn, http://gist.github.com/415170; the comments at the end of the file point where the issue occurs

18:32 herdrick: question: lein new project_name gives you a project.clj with dependencies that are out of date, I think. org.clojure/clojure "1.1.0

18:32 oops

18:32 nDuff: (this is some of my first clojure code, by the way, so I'm fully expecting -- and would welcome -- any critique / comments re obvious failings re practices / style failings)

18:33 herdrick: ok, so the default org.clojure/clojure version according to lein new is 1.1.0

18:33 isn't that obsolete?

18:34 ah, I see that's the newest version in Clojars

18:34 remleduff: 1.2 isn't out just yet

18:36 _na_ka_na_: chouser: the eval behavior of clojure struck me, coz eval in Perl happens in lexical scope, what implications do the two behaviors have ?

18:37 herdrick: okremleduff: ok, thanks

18:41 islon: "lein help" gives me Exception in thread "main" java.lang.RuntimeException: java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.Named (help.clj:5)

18:42 SinDoc: I pasted a simple deftype interaction; http://paste.lisp.org/display/100539

18:44 The syntax is probably not correct but this is what I understand from (doc doctype)

18:44 *deftype

18:44 tomoj: don't use new

18:44 but your example still doesn't work for me after fixing that

18:45 but e.g. this works: (deftype Point [x y]) (def pt (Point. 1 2)) (.x pt)

18:45 remleduff: deftype defines no functionality, you want defrecord

18:45 tomoj: also, (defrecord Point [x y]) (def pt (Point. 1 2)) (:x pt)

18:45 yeah

18:46 islon: how do I start swank with my lein project? i tried "lein swank" but it gives me "swank is not a task. Use "help" to list all tasks."

18:46 remleduff: islon: Do you have lein-swank in your dev-dependencies, and have you run lein deps?

18:46 skeeterbug: islon, i had that problem, upgrading lein worked for me

18:46 Raynes: islon: You need to add swank-clojure to your project.clj file.

18:46 SinDoc: i thought fields were keywords

18:46 Raynes: remleduff: lein-swank is obsolete.

18:46 remleduff: lein swank is bundled with the new swank-clojure.

18:46 remleduff: oh, I should upgrade :)

18:47 tomoj: http://github.com/technomancy/swank-clojure explains

18:47 Raynes: [swank-clojure "1.2.1"]

18:47 islon: thanks, is there a way to lein self upgrade? like "lein upgrade"?

18:47 Raynes: Put that in your dev-dependencies

18:47 lein update, I believe.

18:47 skeeterbug: yeah, lein update, but i think older versions didn't have that command

18:47 Raynes: No, it's lein upgrade

18:47 tomoj: SinDoc: not on a raw deftype, apparently. for defrecord, yeah

18:48 islon: wow, works =)

18:49 remleduff: SinDoc: deftypes are not maps, so they have no default functionality for keyword lookup. There was an earlier version of deftype that defined some map functionality magically for you if you implemented IPersistentMap or something like that, but Rich wisely split it up into deftype with nothing magic and defrecord which is always map-like.

18:50 SinDoc: Yeah, i saw that defrecord implements IPersisistentMap

18:51 Are there recent examples of deftype?

18:51 http://paste.lisp.org/display/90329

18:52 I found this but doesn't work given the recent changes

18:54 _na_ka_na_: Hey guys I'm writing 2 macros .. first is straightforward .. (defmacro m1 [x] (println "m1 got" x)) ..

18:54 tomoj: SinDoc: https://gist.github.com/ad9cad85dc72c41dd52b

18:54 that seems to work

18:54 _na_ka_na_: but in the second, i want to simulate something like :

18:54 (defmacro m2 [y] (macroexpand `(m1 ~y)) (println "m2 got" y))

18:55 only w/o the macroexpand part ..

18:55 how can it be done ?

18:56 SinDoc: tomoj: You're a grace; thanks

18:56 it uses defrecord though

18:56 tomoj: _na_ka_na_: have you tried macroexpanding?

18:56 SinDoc: yes, because that's what you should use to do that example nowadays

18:57 deftype has similar syntax but no automatic :real :imaginary access

18:57 _na_ka_na_: tomoj: didn't get what you meant ?

18:57 tomoj: _na_ka_na_: I mean, for example, have you tried (macroexpand-1 '(m1 3)) ?

18:57 _na_ka_na_: yes

18:58 tomoj: so you noticed, then, that it expands to nil?

18:58 _na_ka_na_: yup

18:58 tomoj: so why would you want to expand nil and stick that in m2?

18:58 anyway.. (defmacro m2 [y] `(do (m1 ~y) (println "m2 got" ~y))) maybe?

18:58 SinDoc: tomoj: I'm looking for a way to write ADTs and currently I was hoping to write an abstraction that does memory management so I should export thinks like cons, car, cdr, etc.

18:59 _na_ka_na_: no but the above definition of m2 work s ... it calls m1

18:59 i mean the macroexpand one

18:59 tomoj: yes, the one I just pasted calls m1 as well

18:59 arkahn: nDuff: it has to do with code in clojure/src/jvm/clojure/lang/Compiler.java near "public static class RecurExpr implements Expr". I'm not understanding it all yet, other than it looks like it's thrown off by the method call you make to #^java.nio.ByteBuffer .remaining which returns a java int. So far, it looks to me like the implementation recur doesn't like mixing boxed and unboxed primitives. Maybe immediately box the return value with Integer

18:59 right away? All subsequent clojure manipulations would then treat it like a clojure Number ... maybe

18:59 tomoj: it expands like (m2 5) -> (do (user/m1 5) (clojure.core/println "m2 got" 5))

19:00 SinDoc: dunno how to help you, good luck

19:01 SinDoc: tomoj: thanks for the help

19:01 nDuff: arkahn, ...hmm. Would you suggest testing this against a newer upstream (this is 1.1) and filing a ticket if the behavior is unchanged?

19:02 _na_ka_na_: tomoj: but I want both macros to run at compile time, the one you pasted runs at run time

19:02 I mean macroexpand m2 should return null

19:03 tomoj: I see

19:03 arkahn: nDuff: I really don't know. What was the design goal for recur? To be able to mix clojure and java primitives? You could always file a ticket and find out. Unfortunately, I've probably been using clojure for as long or less than you have, so I'm not the best person to ask ; )

19:03 _na_ka_na_: thats how (defmacro m2 [y] (macroexpand `(m1 ~y)) (println "m2 got" y)) will work

19:03 tomoj: yeah

19:03 weird

19:03 arkahn: nDuff: fwiw (which isn't much, considering my noob-ness) I like your code

19:04 nDuff: arkahn, heh -- thanks (both for taking the time to look into the issue, and providing at least some kind of feedback that I wasn't making _really_ obvious errors)

19:05 arkahn: nDuff: np! It's always nice to get a sanity check ... I just hope what I dug up was sane

19:05 tomoj: _na_ka_na_: I think you might be stuck with the macroexpand, then, not sure

19:06 _na_ka_na_: just curious, what's the point?

19:06 _na_ka_na_: tomoj: I'm trying to write a macro wrapper over gen-class

19:08 tomoj: and you can't wrap gen-class with a normal-style macro? never would have thought otherwise, interesting

19:08 I thought you were struggling with macros, but you know them better than I :D

19:11 _na_ka_na_: tomoj: Not sure about that, but I've been struggling alright! This is like my 2nd macro which I've had to write .. I'm done with the macroexpand solution .. but chouser above said that one shouldn't use macroexpand inside a macro

19:14 What's the easiest way to run arbitrary shell commands from Clojure, example I want to, cd into a directory, and kick off a process from there ..

19:25 found c.c.shell

19:28 ,(sh :cmd "echo Hello Thr" :return-map true)

19:28 clojurebot: java.lang.Exception: Unable to resolve symbol: sh in this context

19:28 _na_ka_na_: (sh :cmd "echo Hello Thr" :return-map true) throws an exception for me .. java.lang.IllegalArgumentException: No matching method found: exec for class java.lang.Runtime

19:31 chouser: _na_ka_na_: try (sh "echo" "Hello" "There" :return-map true)

19:32 _na_ka_na_: oh I thought you forgot to mention the :cmd key in the docs .. after looking at the source

19:32 wasn't sure how to pass the cmd

19:33 chouser: yeah, the docs could use some help there

19:35 ihodes: anyone in here familiar with Enlive

19:35 ?

19:36 i've been getting "java.lang.NullPointerException ", pointing to a line where i defsnippet, is the issue.

19:38 _na_ka_na_: chouser: maybe you could put your example above in the docs .. and this for Win XP works for me.. (sh "cmd.exe" "/c" "echo" "Hello" "There" :return-map true)

20:05 ihodes: anyone here yet? i'm really interested in learning enlive, but i'm having a small problem i'm sure someone's seen before

20:14 islon: is clojure.contrib.json the best way to read json in clojure?

20:14 ihodes: as far as i know, it's the only way. and if it's in contrib, chances are it does what it's supposed to to, well.

20:19 * technomancy would not make those kinds of assumptions about contrib

20:20 ihodes: fair enough. technomancy, would you be able to answer a quick question re enlive for me?

20:20 i've been getting "java.lang.NullPointerException ", pointing to a line where i defsnippet, is the issue.

20:20 islon: well, json parsing is not that difficult

20:20 danlarkin: ihodes: no!

20:20 he's busy helping me

20:21 technomancy: I've only used enlive once... I was pretty confused the whole time.

20:21 ihodes: ah, ok haha. for some reason i'd thought you'd somehow been involved. wrooong person. know someone who might be able to help? frustrating little problem

20:22 technomancy: cgrand is the author; there's also dnolen who's written some docs for it

20:22 neither is around now =

20:22 =\

20:22 nor lau

20:22 ihodes: noticed that. siiigh. it looks so nice, but mystery error is a pain.

20:22 yeah lau did what i'm trying to do with it ahah, though i didn't know until last night

20:25 hugod: ihodes: I think a NPE at that line means that the path to the template is not being found

20:26 ihodes: unfortunately, it's an absolute path right now, so I don'tt hink that's it.

20:28 though now i've changed the selector for the snippet and get this: java.lang.ArrayIndexOutOfBoundsException: 1 ---- on the same line

20:31 http://pastie.org/979148 is the snippet that is being hated on. there's definitely a file there. i require enlive in as html.

20:44 herdrick: say, can anyone tell me why this: (ns user (:use [incanter.core :only (abs)])) gives me "java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol"

20:44 while this: (ns user (:use [clojure.set :only (union)]))

20:44 works fine ?

20:45 substituting various things for clojure.set works fine too

20:45 like clojure.contrib.combinatorics

20:45 or whatever

20:45 (assuming you replace union with something in one of those packages

20:45 )

20:46 tomoj: is that the exact code which caused the error?

20:47 herdrick: yep

20:48 tomoj: can you try both and pastie the repl session?

20:48 herdrick: sure

20:48 brb

20:48 tomoj: I'm just boggled

20:50 herdrick: http://pastie.org/979167

20:50 this is a fresh install of swank-clojure

20:50 and the first time i'm using lein

20:50 tomoj: no idea why that could happen

20:51 herdrick: so probably something wrong with what i'm doing there

20:51 tomoj: does (use '[incanter.core :only (abs)]) also give the error?

20:51 herdrick: yep, identical error

20:51 tomoj: and, does the error come with a stacktrace? I wonder where the error is happening?

20:51 maybe it's inside incanter? that's the only explanation I can think of..

20:52 your syntax looks perfect to me

20:52 herdrick: whereas (use '[incanter.coreBAD :only (abs)]) gives what you'd expect: "Could not locate incanter/coreBAD__init.class or incanter/coreBAD.clj on classpath: ... "

20:52 brb

20:52 hugod: ihodes: the braces around the snippet selector argument look wrong to me

20:53 tomoj: herdrick: what versions of incanter and clojure are you depending on?

20:54 herdrick: here's the stacktrace and it's cause: http://pastie.org/979169

20:54 incanter 1.2.3

20:54 clojure 1.1.0

20:57 tomoj: hmm

20:57 herdrick: uh oh -

20:57 looks like incanter's project.clj file wants clojure 1.2.0

20:57 tomoj: I think incanter 1.2.3 requires clojure 1.2.0

20:57 yeah

20:57 herdrick: roger

20:58 tomoj: that's the only way this error makes sense to me, anyway

20:58 herdrick: ok, thanks, that's probably it

20:59 i was following this blog post from November: http://data-sorcery.org/2009/11/20/leiningen-clojars/

20:59 which is like 14 clojure dog years ago

20:59 my bad ;)

20:59 tomoj: hehe

21:01 Drakeson: Is there a facility to work with paths (like file system paths)?

21:01 replaca: Drakeson: I use java.io.File

21:03 Drakeson: replaca: maybe I miss something. How do you do (path :home "foo/bar") using java.io.File ?

21:04 is there something easier than (str (System.getProperty "user.home") "/" "foo/bar") ?

21:11 replaca: Drakeson: More corrrect would be (File. (System.getProperty "user.home) (File. "foo") "bar)

21:11 I think - I'm not buried in that java space

21:12 easy to imagine a path func that did (path :home "foo" "bar")

21:16 herdrick: tomoj: ok, that worked

21:16 thanks!

21:18 By the way, since Clojure 1.2 isn't in lein-space, I just went with the older version of Incanter that is OK with Clojure 1.1

21:19 but now I've got a bunch of Incanter 1.2.3 jars in my /lib dir of my lein-created project

21:19 those shouldn't be a problem, right?

21:19 ihodes: hugod: i tried removing them: no luck. it's also a selector from david nolen's tutorial :\

21:19 herdrick: unless i were to use swank-clojure-project (the avoidance of which was the point of this whole switch to lein)

21:23 bhenry: herdrick lein clean && lein deps

21:23 herdrick: bhenry: ok. but is it important?

21:23 bhenry: yes

21:24 herdrick: will swank or anything else pick up those extra jars in lib?

21:25 Drakeson: herdrick: What are you trying to do?

21:25 herdrick: Drakeson: just curious about the issue

21:26 my problem was solved above

21:27 Drakeson: oh sorry

21:28 bhenry: herdrick: everything in lib/ is on your class path. so if you (use 'some-project) you won't know which one you'll get (that's if it doesn't error, i'm not sure what would happen, but I know it's important). someone speak up if i'm misdirecting herdrick.

21:29 tomoj: herdrick: what do you mean 1.2.3 isn't in lein-space?

21:29 herdrick: bhenry: i was thinking lein would manage that, and generate a custom classpath using only the jars of the deps and their deps, recursively, etc

21:29 tomoj: no, you need to remove duplicate jars

21:29 bhenry is correct

21:30 herdrick: No, Clojure 1.2 isn't in lein-space

21:30 tomoj: oh, hmm

21:30 you mean that you can't get it with lein?

21:30 herdrick: well, *i* couldn't in a couple of tries

21:30 tomoj: you can: [clojure "1.2.0-master-SNAPSHOT"] and [clojure-contrib "1.2.0-SNAPSHOT] or something like that

21:30 herdrick: i'm new to lein tho

21:30 tomoj: bhenry: ok, thanks for the info on lein and classpaths

21:31 tomoj: also would need to use 1.2.3-SNAPSHOT for incanter

21:31 ihodes: anyone here an enlive expert yet? ;) still having a fun little NullPointerException http://pastie.org/979148

21:31 herdrick: trying that

21:31 tomoj: but using an old version and 1.1.0 is not too bad either

21:31 ihodes: what's {[:.cg-post]} supposed to be?

21:31 I'm surprised that doesn't cause an error

21:32 ,'{[:.cg-post]}

21:32 clojurebot: 1

21:32 tomoj: uh, what?

21:32 bhenry: herdrick, if you have a lot of dependencies in your projects, and you're updating them a lot, alias lcd to lein clean && lein deps then just use that every time. it hardly takes any additional time, since lein stores things in a local repository on your computer.

21:32 tomoj: oh, the error message is "1", haha

21:32 ihodes: it's a selector: Noel used it in his tutorial: (def *section-sel* {[:.title] [[:.content (nth-of-type 1)]]})

21:32 nolen*

21:32 http://github.com/swannodette/enlive-tutorial/

21:32 tomoj: ihodes: ok, but your {} is wrapped wrong

21:33 you've got it just around [:.cg-post]

21:33 which looks like a map with a key with no value, which is illegal

21:33 ihodes: true: i did change it to "[:.cg-post]" in the version i'm playing with now

21:33 tomoj: ah

21:33 ihodes: that was a mistake in the pastie when i was messing with stuff, i'm sorry!

21:33 herdrick: say, i've been using [org.clojure/clojure "1.1.0"] instead of [clojure "1.1.0"] does that matter?

21:33 tomoj: no problem

21:33 herdrick: bhenry: ok, thanks looks like a good tip

21:34 ihodes: tomoj: the problem remains, though, unfortunately

21:34 tomoj: herdrick: nope, clojure is just an abbreviation for org.clojure/clojure

21:34 herdrick: ok

21:34 tomoj: well, I'm betting the problem can't be determined without seeing the html, but not sure

21:34 and I am not an enlive expert, good luck

21:35 ihodes: it's a compile-time error though

21:35 tomoj: ah

21:35 ihodes: as it occurs when i'm loading the file into the repl

21:35 tomoj: that's odd, must be bad syntax then

21:36 ihodes: it looks exactly like the syntax in nolen's tutorial, i *think*. gah. ben banging my head against a wall about this for a while. it's what happens when you code in C the first half of the day, and then clojure the other half.

21:37 tomoj: you need something to bind to the keys destructuring map

21:37 (I think)

21:37 ihodes: i don't quite understand?

21:37 tomoj: I mean, [{:keys [title author pubdate post-text]} <something needs to go here>]

21:38 e.g. the tutorial has [{:keys [title data]} model]

21:38 though I can't tell where model came from

21:38 oh, maybe that's just an extra param?

21:39 yeah, I was wrong, just the {:keys ..} should work too it seems

21:39 ihodes: yeah it's just an additional arg: the {:key..} thing is just destructuring a map

21:41 java.lang.NullPointerException (render_index.clj:19) is the exception, too

21:46 tomoj: what's on line 19, the start of the defsnippet?

21:47 ihodes: yep

21:59 tomoj: ihodes: I don't think this problem is your fault

22:00 the examples from the tutorial seem to do the same thing

22:01 ihodes: that simultaneously good to hear. and awful! in his examples, it all seems to work. he is using compojure 0.3.2, which might be the cause of the problems, but it's highly unlikely as .4 doesn't change much, and nothing that enlive relies on.

22:01 tomoj: it seems like load-html-resource is being called with nil

22:01 which clojure is he using?

22:01 ihodes: the thing is, his examples work in the lein-powered environment he has on hit.

22:01 tomoj: huh, he doesn't have any clojure in his project.clj

22:01 remleduff: NPEs in enlive have always meant "couldn't find your template" for me

22:01 ihodes: i'm going to have to build up his examples (M-w, C-y) in a new project

22:02 tomoj: remleduff: yeah, but..

22:02 oh, hmm

22:02 does it try loading from the classpath?

22:02 remleduff: What do you get if you just do (html-resource "your_template.html")

22:02 hugod: ihodes: the path should be relative

22:02 tomoj: rather than taking it as an absolute file path

22:02 I see

22:02 hugod: it uses the resource loader

22:02 ihodes: ah, let me give that a go

22:02 so an absolute path *won't* work?

22:02 tomoj: so the html file needs to be in resources/ I guess, and you need to have that directory there before you start up swank

22:03 (does `lein swank` add resources/ to the classpath?)

22:03 remleduff: resources is a recommendation rather than a requirement. Current lein adds it to classpath, but there were older versions that didn't

22:03 tomoj: swannodette just sticks his html files in src along with the clj

22:04 ihodes: let me try just doing that

22:05 tomoj: you'll need to use the relative path from src/ if you put them there

22:05 e.g. "foo/bar.html" for src/foo/bar.html, I mean

22:06 ihodes: ok, so i moved the template to the same folder my render-index.clj is in (the file I've been futzing with) and change the path from absolute to clogs/template_index.html (clogs being my project's name), and it appears to now work.

22:07 well, i'm on to other exceptions on other lines anyway. which is progress.

22:07 remleduff: hehe

22:08 ihodes: so is there a nice way I can have the HTML files in other folders..? I had in my project.clj …:resources-path "html") and my html (templates) in that folder. i thought that'd work, but it didn't so I tried absolute path which also didn't. any clues as to why those things don't work?

22:09 remleduff: I'm not sure what resources-path does, but by the time lein reads your project.clj it's too late to change the classpath so I can't imagine it working. Probably just using resources would work

22:11 ihodes: resources-path should be setting the name of the resources to folder to whatever i specify–apparently it doesn't work, as I just tested and I *can* refer to my template at recoures/template.html

22:11 which is nice. odd. now I have another cryptic error.

22:13 remleduff: What's that?

22:14 ihodes: tomoj: before you scroll off the screen, thank you :) remleduff: one of these buggers: java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Character (render_index.clj:28)

22:16 solved.

22:31 thanks for the help, all. i'm running into more off errors, so i'm going to call it a night and do some set theory.

22:31 odd* errors. finals time is not a good time to try to start a new project. cheers, and thanks again.

22:36 remleduff: Why might M-x slime give me "let: Symbol's function definition is void: swank-clojure-reset-implementation"?

22:37 tomoj: something is looking for swank-clojure-reset-implementation and you don't have it

22:37 I guess you probably figured that much out :(

22:38 remleduff: I usually use lein swank to start up, was trying to start up a repl without a project this time

22:39 I'm so bad with emacs still

22:40 tomoj: remleduff: do you have swank-clojure installed from elpa?

22:53 defn: technomancy: did you change the URL for your package.el repo

23:00 remleduff: tomoj: I have swank-clojure 1.1.0 from ELPA, yes.

23:03 tomoj: remleduff: I think you need to upgrade

23:04 it looks like swank-clojure-reset-implementation is in 1.2.0 but not 1.1.0

23:06 herdrick: so you've got to keep your version of swank-clojure installed in ELPA synched with your swank-clojure jars in your lein projects?

23:06 remleduff: I thought swank-clojure was added to your project. What does swank-clojure in emacs do?

23:06 herdrick: tomoj: is that true?

23:06 tomoj: herdrick: I don't know if that's true or not

23:06 swank-clojure from elpa is no longer even required

23:07 herdrick: oh, really?

23:07 tomoj: some stuff will not work without it

23:07 presumably M-x slime for example

23:07 I don't know what problems a version mismatch might cause

23:07 herdrick: hmm

23:07 perhaps better to delete it then

23:07 tomoj: remleduff: swank-clojure in emacs is not needed if you only connect to externally started swank servers

23:08 better to ask technomancy

23:08 about version mismatches I mean

23:09 herdrick: ive got a related question: when i drop a jar (in this case, an apache commons one) into my /lib under my lein project, it is not picked up by slime/swank until and restart the swank instance

23:09 is there a better way?

23:09 remleduff: hendrick: Nope :\

23:09 technomancy: defn: haven't touched that in a while, no.

23:10 remleduff: swank-clojure in emacs isn't really needed

23:10 you just need slime + clojure-mode

23:10 remleduff: But swank-clojure is what provides M-x slime if I'm just wanting to play with one-off stuff?

23:10 herdrick: tomoj: remleduff: technomancy: ok, thanks

23:13 remleduff: Duh, have to (require 'swank-clojure) if I want to use stuff provided by it (including M-x slime)

23:13 technomancy: remleduff: yeah, that's true

23:14 tomoj: you shouldn't have to require it, I think...

23:14 but if it works, who cares

23:15 SinDoc: Can a type refer to itself?

23:16 Raynes: SinDoc: I believe so.

23:17 remleduff: technomancy: How do you usually start up swank if you're hacking on clojure itselfl?

23:17 SinDoc: Raynes: thanks, would you know how?

23:17 Raynes: SinDoc: You have to instantiate the class directly, because the factory functions aren't there yet.

23:17 technomancy: remleduff: I start a repl in swank and then edit clojure in the jar file itself

23:19 SinDoc: Raynes: if I need the name of the class in order to instantiate it then it wouldn't work since the name won't have been bound yet.

23:24 Raynes: SinDoc: http://gist.github.com/415409

23:31 remleduff: Anyone got a good way to check if a deftype has successfully implemented all the abstract methods its inherited, and not forgotten any?

23:47 SinDoc: remleduff: checking the protocols it has implemented using reflection?

23:50 Raynes: Thanks, I tried your solution; it still can't reify itself but it's fine for now

23:51 Raynes: :(

23:51 Sorry I couldn't be more helpful. <3

23:52 SinDoc: Raynes: FWIW, I found out that my initial requirement wasn't valid to begin with

Logging service provided by n01se.net