#clojure log - Apr 07 2011

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

0:22 Havvy: Given the following as the classpath:

0:23 (#<URL file:/C:/clojure/lein/havvy-irc/src/> #<URL file:/C:/clojure/lein/havvy-irc/test/> #<URL file:/C:/clojure/lein/havvy-irc/classes/> #<URL file:/C:/clojure/lein/havvy-irc/lib/clojure-1.2.1.jar> #<URL file:/C:/clojure/lein/havvy-irc/lib/clojure-contrib-1.2.0.jar> #<URL file:/C:/clojure/lein/havvy-irc/lib/irclj-0.4.1-20110104.084027-1.jar> #<URL file:/C:/clojure/lein/havvy-irc/lib/dev/swank-clojure-1.2.1.jar> #<URL

0:23 file:/C:/clojure/lein/plugins/swank-clojure-1.3.0.jar>)

0:23 I can't get (use 'irclj) to work.

0:24 tomoj: I would hope irclj isn't a sing-

0:24 ..single-segment namespace

0:24 Derander: I have some java object. I'm not really sure what class it is. Is there a way to find out easily?

0:25 tomoj: it appears it's irclj.core

0:25 which, again, interestingly, appears nowhere in the readme

0:26 Havvy: tomoj: Ah, thanks. That got me out of quite a jam.

0:26 tomoj: Derander: surely you know about ##(class "foo") ?

0:26 sexpbot: ⟹ java.lang.String

0:26 Derander: tomoj: surely I don't :-(

0:26 tomoj: also interesting are ancestors and supers

0:27 though I can never remember the difference

0:27 Derander: beats me

0:28 tomoj: clojure.contrib.repl-utils/show can alse be very helpful

0:29 Derander: tomoj: I will look it up.

0:29 .. after I figure out how to dump the html content of this dom element :-(

0:30 tomoj: repl-utils/show may be very helpful in doing just that

0:30 it will list all the instance methods with return and parameter types

0:30 if javadocs are handy, of course they will be more enlightening

0:36 flea__: ,(doc var)

0:36 clojurebot: It's greek to me.

0:36 flea__: ,(doc defvar)

0:36 clojurebot: Huh?

0:44 ataggart: ,(doc def)

0:44 clojurebot: DENIED

0:45 ataggart: $(doc var)

0:54 Havvy: Perchance, is there a function that tells you all possible values you can insert into (use) [and maybe variants]?

1:06 tomoj: (doc +)

1:06 clojurebot: "([] [x] [x y] [x y & more]); Returns the sum of nums. (+) returns 0."

1:06 tomoj: heh

1:06 carllerche: I'm trying to grasp macros, but I'm having a hard time getting this to work: https://gist.github.com/cf3f20d4524d78d79311 (setting a variable in the macro to use in the sexp passed in. Is this possible?

1:07 tomoj: carllerche: do you have a really good reason to do that? :/

1:07 brehaut: Havvy: http://clojure.org/libs (doc require) (doc use) (doc ns)

1:07 Derander: fuck I hate html parsing in java

1:07 fucking trivial in ruby

1:07 tomoj: istr recommending enlive

1:07 but you already had some sort of DOM thingy

1:07 brehaut: i second tomoj's suggestion

1:08 Derander: I'm trying to run html through htmlcleaner and then do a rudimentary readability algorithm on it

1:08 not sure if enlive is suitable for that

1:08 (honestly not familiar with enlive.)

1:08 carllerche: tomoj: dunno, learn macros?

1:09 brehaut: Derander: enlive is a layer ontop of tag soup; you can use it for generating and scraping

1:09 tomoj: carllerche: macros like that are called "unhygienic"

1:09 brehaut: Derander: have you seen https://github.com/swannodette/enlive-tutorial ?

1:09 tomoj: in general one should prefer hygiene

1:09 Derander: brehaut: yeah.

1:09 tomoj: but perhaps learning to be unhygienic is instructive

1:10 Derander: brehaut: I have not put the mental effort in to learn it

1:10 tomoj: carllerche: the dirty trick is to replace x with ~'x

1:11 carllerche: tomoj: ah... so, clojure's macros are hygenic?

1:11 tomoj: &`x

1:11 sexpbot: ⟹ clojure.core/x

1:11 tomoj: &`~'x

1:11 sexpbot: ⟹ x

1:11 carllerche: i googled the hygenic bit but haven't found a clear answer... thanks for the tips, i'll play around in the repl more

1:11 tomoj: clojure's macro stuff encourages hygiene more than some other lisps

1:11 Derander: brehaut: do you know off the top of your head if there is an easy way to dump the content -- including html tags -- of a certain node?

1:13 tomoj: wait, what? clojure.core/x?

1:14 &`frobniz

1:14 sexpbot: ⟹ clojure.core/frobniz

1:14 brehaut: Derander: you'd use html/select (where html is enlives html lib) to select a node, and then i forget how to get the nodes to text but its easy

1:14 Derander: brehaut: experimenting

1:14 tomoj: I think you'd just emit it?

1:15 brehaut: tomoj: i think so?

1:15 tomoj: emit is private i think

1:15 emit* is perhaps the one to use

1:16 tomoj: odd

1:16 brehaut: thats what template uses

1:16 tomoj: agreed

1:20 Derander: you might want to esperiment with sniptest if you are mucking about in the repl btw

1:20 tomoj: I noticed today another oddness, that despite enlive's working in general perfectly well with non-namespaced xml, deftemplate and friends hardcode html-resource, and the list of self-closing-tags is html specific

1:20 Derander: brehaut: googlign

1:20 brehaut: Derander: https://github.com/cgrand/enlive/blob/master/src/net/cgrand/enlive_html.clj

1:20 right at the bottom

1:22 Derander: makes sense

2:17 symuyn: Hello, I just have a quick question: what's the best way to get [0 1 2 3 4 5 6 7 8 9 10 11 12 13] -> ((0 3 9 12) (1 4 7 10 13) (2 5 8 11))?

2:20 raek: ,(apply map list (partition 3 (range 14))) ; one way to do it

2:20 clojurebot: ((0 3 6 9) (1 4 7 10) (2 5 8 11))

2:21 symuyn: Thanks!

2:22 raek: hrm, the 12 and 13 is lost, though

2:22 ,(partition 3 (range 14))

2:22 clojurebot: ((0 1 2) (3 4 5) (6 7 8) (9 10 11))

2:22 raek: ,(partition-all 3 (range 14))

2:22 clojurebot: ((0 1 2) (3 4 5) (6 7 8) (9 10 11) (12 13))

2:23 raek: map stops when one of the seqs are out of elements

2:24 ,(let [coll (range 14)] (for [i (range 3)] (drop i (take-nth 3 coll))))

2:24 clojurebot: ((0 3 6 9 12) (3 6 9 12) (6 9 12))

2:25 raek: ,(let [coll (range 14)] (for [i (range 3)] (take-nth 3 (drop i coll)))) ; ahem...

2:25 clojurebot: ((0 3 6 9 12) (1 4 7 10 13) (2 5 8 11))

3:40 TobiasRaeder: morning

3:40 ejackson: morning

3:52 symuyn: raek: Hey, I had to disconnect suddenly. I see the problem too; is there a way to prevent 12 and 13 from being lost by map?

3:52 Like, is there a function f like map: (f list [1 2 3] [1 2 3] [1 2]) -> ((1 1 1) (2 2 2) (3 3))?

3:53 Or to repeat the general question, what's the best way to get [0 1 2 3 4 5 6 7 8 9 10 11 12 13] -> ((0 3 9 12) (1 4 7 10 13) (2 5 8 11))? (->> % (partition 3) (apply map list)) omits the last element.

4:01 __name__: symuyn: https://gist.github.com/806541

4:03 Derander: symuyn: (let [coll (range 14)] (for [i (range 3)] (take-nth 3 (drop i coll)))) is what he came up with

4:03 but that is ((0 3 6 9 12) (1 4 7 10 13) (2 5 8 11))

4:03 __name__: symuyn: what i posted is the map function you wanted.

4:03 Derander: if the initial 6 matters to you

4:04 symuyn: Wonderful, thank you.

4:04 __name__: symuyn: if you use concat as the fun and nil as the placeholder, it will do what you stated above.

4:09 Ehm, not concat.

4:09 (fn [x] (filter #(not (nil? %)) x))

4:09 symuyn: list?

4:09 Ah

4:09 Anyways, I have to go; thanks again

4:10 __name__: did it work?

5:11 thorwil: so i have (for [k (keys mymap)] k), but how do i include a [v (vals mymap)] in there?

5:12 * thorwil tried varying parens and orders to no avail

5:19 thorwil: nm, (for [k (keys mymap) v (vals mymap)] [k v])

6:15 clgv: how about (seq mymap) ?

6:15 thorwil: you already get key value pairs when you try to use a map as seq, e.g. with map

6:17 thorwil: I dont know if you have the assertion that the first key in keys belongs to the first val in vals - you dont have that problem if simply use the map as seq

6:18 thorwil: clgv: actually i'm trying to build a let-map, binding all values in a map to the names of their keys

6:18 but now i gotta run, bbl

6:19 clgv: thats already integrated with let and destructuring

6:20 thorwil: see http://clojure.org/special_forms#Special%20Forms--%28let%20[bindings*%20]%20exprs*%29

6:21 you want either the :keys form or the :strs form

7:04 thorwil: clgv: i looked at that very page before and still don't understand how i would do it without ever listing any key

7:05 clgv: thorwil: can you limit yourself to either use strings, keywords or symbols as keys? then I could give you an example

7:06 thorwil: clgv: keywords

7:07 clgv: or wait, I explain: if you use that destructuring the values in the vector are the names of the symbols you can use within the let and they will be converted to the keywords so that the values can be bound to the symbols

7:08 &(let [mymap {:a 1 :b 2 :c 3 :d 4}] (let [{:keys [a b c d]} mymap] [a b c d]))

7:08 sexpbot: ⟹ [1 2 3 4]

7:09 clgv: you know the key you want to use in advance?

7:09 you probably have to if you want to write code that makes sense within the let

7:11 thorwil: i quickly arrived at (let [{:keys [a b c d]} mymap] [a b c d]), but i would like to get rid of the explicit [a b c d]

7:12 clgv: why?

7:12 clojurebot: why not?

7:12 clgv: stupid clojurebot!

7:13 thorwil: as i will use all the keys. even if it should not be a good idea, it will grow my understanding of this destructuring busines ;)

7:15 clgv: but you need to know the name of a local to use it

7:17 thorwil: yes. i know the keys, anyway. of course implicit binding would make the code harder to read

7:18 clgv: thanks for your input

7:18 time to power off and hit the road, summer is upon us! :D

7:20 clgv: thorwil: you could write the macro as follows

7:20 (defmacro let-map [m & body] `(let [{:keys ~(vec (map #(symbol (name %)) (keys m)))} ~m] (do ~@body) ) )

7:21 but it will only work if the map is accessible at macro expansion time

7:22 you can call it like: (let-map {:a 1 :b 2 :c 3} [a b c])

8:04 naeu: Someone just sent me some compiled classes that I'd like to be able to call from Clojure

8:04 Is it enough to just place them on the classpath?

8:05 They don't appear to be explicitly namespaced, so I don't know how to actually access them

8:16 clgv: It is enough to have them in the classpath. but for usage of use or refer they need a namespace

8:17 on a lower level you can also use "load" to load the files via their names

8:17 s/names/paths/

8:17 sexpbot: <clgv> on a lower level you can also use "load" to load the files via their paths

8:25 fmw: does anyone have experience sending cookies with the Apache HttpComponents client? I wrote some code that is supposed to include cookies (http://paste.pocoo.org/show/367163/), but it doesn't arrive at the server.

8:26 the HttpClient seems like the typical over engineered Java bloat to me. I've been smashing my head against the wall on this for a while now.

8:30 naeu: clgv: thanks - I needed to 'import' them

8:30 that's the step I was missing

8:30 :-)

8:31 clgv: naeu: you mean "load"?

8:31 naeu: clgv: I used (import 'MyClass)

8:32 clgv: naeu: ah java classes^^ I thought of compiled clojure first ;)

8:32 naeu: clgv: oh, sorry for being ambiguous

8:51 clgv: $source partial

8:51 sexpbot: partial is http://is.gd/zZxzDD

8:56 clgv: $findfn {:a 1 :b 2 :c 6 :d 7} {:a :b} {:a 1 :b 2}

8:56 sexpbot: []

8:56 clgv: :(

8:57 mec: $findfn {:a 1 :b 2 :c 6 :d 7} [:a :b] {:a 1 :b 2}

8:57 sexpbot: [clojure.core/select-keys]

8:58 clgv: args. thanks mec

8:59 $findfn {:a 1 :b 2 :c 6 :d 7} #{:a :b} {:a 1 :b 2}

8:59 sexpbot: [clojure.core/select-keys]

8:59 clgv: ah well, I see the error ;)

9:00 &(select-keys {:a 1 :b 2 :c 6 :d 7} [:d :c])

9:00 sexpbot: ⟹ {:c 6, :d 7}

9:01 clgv: hm damn. I need them sorted like in the list

9:02 mec: ?

9:03 clgv: I want to have [7 6] as output when given {:a 1 :b 2 :c 6 :d 7} and [:d :c]

9:03 mec: ok let me see

9:04 clgv: $findfn {:a 1 :b 2 :c 6 :d 7} [:d :c] [7 6]

9:04 sexpbot: [clojure.core/map clojure.core/replace clojure.core/keep]

9:04 mec: ya map would work

9:04 clgv: lol yeah. strangely obvious...

9:05 mec: indeed, i was about to try reducing into an array-map

9:07 clgv: hmm replace seems to be most fitting with respect to semantic

9:09 mec: im partial to keep

9:11 clgv: I can tell you what the whole thing does

9:11 (let [param-values (replace param-map param-keyword-list)] (if (empty? param-values) func (apply partial func param-values) ) )

9:12 I have a parameter map that contains keywords and values and a specification that knows the order of the parameters in the function signature of "func"

9:13 and I want to create a partial from that. so replace makes pretty much sense ;)

9:29 mec: you could do (if-let [param-values (seq (replace param-map param-keyword-list))] (apply partial func param-values) func) since apply calls seq on it anyway

9:44 avysk: $findfn [:a :b :c :d] [1 3] [:b :d]

9:44 sexpbot: [clojure.core/map clojure.core/replace clojure.core/keep]

12:02 amalloy: avysk: that one always makes me squint. seems like magic

12:04 carllerche: i have a blog post about intentional bad macro hygiene if you're interested: hubpages.com/hub/Unhygenic-anaphoric-Clojure-macros-for-fun-and-profit

12:04 carllerche: amalloy: I'll look over it, thanks

12:31 Saturnation: Could someone help me understand the structure of the function defined at the end of page 85 in "Joy of Clojure"?

12:33 dnolen: Saturnation: what are you confused by exactly?

12:36 Saturnation: Well, what the params to the function?

12:36 * Saturnation is new and slightly confused at the moment

12:37 Saturnation: I read the first 4 chapters yesterday and they are only starting to gel today...

12:38 ah, think it just made sense

12:38 I takes three parameters?

12:38 s/I/It

12:38 sexpbot: <Saturnation> It takes three parameters?

12:40 amalloy: Saturnation: i think my version of JoC isn't up to date. what function are you talking about?

12:41 dnolen: Saturnation: functions support multiple arities in Clojure.

12:42 Saturnation: that function can take 2 *or* 3 arguments.

12:43 devn: So I need to sort a map, but not by alphabetical order -- i want to define the ordering of fields so I can do something like (sort-with-keys {:my 1 :out 8 :of 3 :order 88 :map 0} [:of :order :out :my :map])

12:44 which returns {:of 3 :order 88 :out 8 :my 1 :map 0}

12:45 dnolen: join /racket

12:45 oops

12:45 devn: :)

12:47 amalloy: devn: clgv was just doing this a while ago in here

12:47 fliebel: dnolen: Logos ruined my Clojure writing. I keep using ==. By the way, how is disequality going?

12:47 Raynes: There is nothing worse in the universe than having to write a technical book in Libre/OpenOffice.

12:47 There can't be. There just can't.

12:48 fliebel: Raynes: Then why attempt it?

12:48 Raynes: fliebel: Because my publisher makes me.

12:49 amalloy: but you really want a *map* as the output? in that case i'd start with writing a comparator-from-seq-of-literals function

12:49 fliebel: Raynes: Isn't there a Textile/LaTeX/Markdown to ODT converter somewhere?

12:49 Raynes: fliebel: Not one that will adhere to their overly complex stylesheet.

12:49 amalloy: then use (sorted-map-by (comparator-from-seq-of-literals [:order :of :what :i :want]) {actual map})

12:49 Raynes: I could roll my own, but I'm probably better off just doing it this way.

12:51 amalloy: (defn comparator-from [literals] (fn [a b] (- (.indexOf literals a) (.indexOf literals b)))), maybe

12:51 dnolen: fliebel: heh, disequality is done. Though after some thought I don't really think it helps much with Sudoku. That really needs a constraint solver.

12:52 fliebel: so new plan is to do a serious clean up what I have, and then tackle the pile of papers I have on implementing efficient constraint solvers.

12:52 fliebel: dnolen: Okay. What about a sieve of erastmus? :D

12:52 dnolen: fliebel: haven't looked at.

12:54 fliebel: dnolen: It'll be wonderful, doing some recursion up to n, negating all multiples of n. Did I say multiplication? Shit… Well, projection maybe. Is there a way to do (cond-e (range))?

12:55 dnolen: fliebel: I've been brainstorming things like (cond-e (range ...)).

12:56 tomoj: &(->> ["foo" 1 "bar" 2] (map #(if %1 (keyword %2) %2) (cycle [true false])) (apply hash-map))

12:56 sexpbot: ⟹ {:foo 1, :bar 2}

12:56 tomoj: prettier way?

12:57 dnolen: fliebel: would be useful to use Logos easily again collections in general. Lots of thinking to do there tho.

12:58 fliebel: dnolen: Yea, that'd be great for using it with real data.

12:59 dnolen: fliebel: I don't have much of a problem with projection personally. Any useful Prolog program uses it to get anything done w/ numbers. Prolog programs that involve arithmetic generally can't run backwards.

12:59 amalloy: tomoj: are you trying to generate a sorted map with that?

12:59 or something else

13:00 tomoj: a hash map

13:00 fliebel: I see...

13:01 amalloy: oh i see. you're asking for a prettier way, not proposing a prettier solution to someone else's question

13:01 tomoj: ah, right, sorry

13:02 amalloy: &(into {} (for [[k v] (partition 2 ["foo" 1 "bar" 2])] [(keyword k) v]))?

13:02 sexpbot: ⟹ {:foo 1, :bar 2}

13:02 tomoj: much easier to understand

13:03 dnolen: fliebel: nqueens in Logos is pretty darn short, https://github.com/swannodette/bratko-logos/blob/master/src/bratko_logos/nqueens.clj. It's only twice as slow as most of the solutions I've seen in idiomatic Clojure written with list comprehensions.

13:03 tomoj: I feel like there should be a pointfree way to say "apply f to the first element of the seq, leave it unchanged otherwise" and similar

13:03 fliebel: dnolen: neat!

13:03 tomoj: ..without zippers

13:04 I guess zippers are exactly the machinery you would end up having to build if you tried, anyway

13:06 Saturnation: amalloy, neighbors function on page 85, Listing 5.1

13:07 amalloy: Saturnation: wow, things got moved a lot since i last updated

13:08 Saturnation: dnolen, I don't see the arity there and I don't see the three parameters now either :)

13:08 amalloy: it's on page 123 of my book :P

13:08 * Saturnation is looking at the dead tree version

13:08 amalloy: Saturnation: (defn neighbors ([param1 param2] (definition with 2 params)) ([param1 param2 param3] (definition with 3 params)))

13:08 yeah, i have that at home, but you caught me at work :P

13:09 Saturnation: ah, OK, now I see it (hope it sticks)

13:09 ah, so the version with two parameters calls the version with three parameters with basic deltas, yes?

13:09 dnolen: Saturnation: yes.

13:10 Saturnation: literal deltas, perhaps is a better term

13:10 thanks, got it! :)

13:10 amalloy: Saturnation: that's a very common pattern. define the two-arg version of your function to add one param and then call the three-arg version

13:10 Saturnation: I can't see that looking at the API for defn

13:10 makes sense

13:10 amalloy: &(doc defn)

13:10 sexpbot: ⟹ "Macro ([name doc-string? attr-map? [params*] body] [name doc-string? attr-map? ([params*] body) + attr-map?]); Same as (def name (fn [params* ] exprs*)) or (def name (fn ([params* ] exprs*)+)) with any doc-string or attrs added to the var metadata"

13:11 Saturnation: where in that definition is arities?

13:11 amalloy: [params*] body is one version. ([params*] body)+ is what you want

13:11 + being the repetition operator

13:12 * Saturnation gets ebnf

13:12 Saturnation: thanks

13:12 me fooled by the fact there was a space between the closing paren and the +

13:13 amalloy: Saturnation: yes, i noticed that in the docstring too. i don't think it's intentional

13:13 Saturnation: Don't know what I assumed it was, but not that

13:13 amalloy: if you read the "same as" section you see basically the same thing but without a space

13:13 Saturnation: I see it in the same as, but I didn't look closely at that

13:13 :)

13:13 amalloy: and who could blame you

13:13 &(doc fn)

13:13 sexpbot: ⟹ "Special Form: Please see http://clojure.org/special_forms#fn"

13:14 Saturnation: thanks for the help

13:14 * Saturnation goes back to hitting the book

13:20 scottj: http://jaderholm.com/paste/kup.html (clojure slice) http://coffeekup.org/ (coffeescript)

13:20 mec: clojure needs better special form doc support at the repl

13:21 cemerick: The repl is such a sad spot to read docs in general.

13:22 * cemerick apologizes for the non sequitur

13:22 cemerick: It's sort of sad how little documentation has progressed over the decades.

13:23 Still just lists of functions / namespaces / packages / whatever

13:24 technomancy: ns-level docstrings are a step in the right direction

13:24 it's a shame clj-130 makes them less practical

13:25 cemerick: huh, I'd never noticed that, actually

13:25 ns and function metadata is a good dataset, but the REPL is a bad UI for it

13:26 Saturnation: filter works the opposite of what I expected

13:26 cemerick: Saturnation: see remove

13:26 fliebel: Saturnation: Then use remove

13:26 hiredman: cemerick: in what way?

13:27 Saturnation: just threw me a curve, happy to use it :)

13:27 cemerick: hiredman: in any of a 100 ways. Far easier to just produce a solution than describe it.

13:27 hiredman: the ability to read and lookup docs and write little snippets code in the same place is great

13:27 cemerick: I doubt it

13:28 cemerick: hiredman: we'll see :-)

13:29 hiredman: cemerick: given that we generally seem to be at odds on this kind of thing, I feel confident prejudging

13:29 scottj: mec: maybe you can elaborate what you mean

13:30 cemerick: hiredman: as long as I can be confident of your disapproval of a concept, then I feel good about it's broader acceptance

13:30 mec: Well rather than just saying "go to this website" it could give a short description and usage too

13:30 cemerick: :-D ;-)

13:31 fliebel: I agree with mec, sometimes I don't even have internet.

13:31 hiredman: it just seems like the repl is great, what should be done is make it better, not do other things that won't be half as good unless they include a repl

13:31 cemerick: I mostly agree.

13:32 There are things that pure text interactions don't allow for though.

13:32 hiredman: repl's don't have to be pure text

13:32 cemerick: True, true.

13:32 hiredman: look at factors

13:32 cemerick: Yeah, I'm working on corollary functionality for ccw, actually.

13:32 mec: or mathematicas

13:32 cemerick: But that's orthogonal to my documentation-related stuff.

13:33 at least at the start, anyway

13:33 * fliebel wonders where ejackson is, and if he got a quote yet.

13:33 hiredman: http://www.thelastcitadel.com/images/Screenshot-Repl.png

13:34 technomancy: hiredman: proportional width? really?

13:34 ಠ_ಠ

13:34 cemerick: hiredman: that REPL is your own creation, I assume?

13:35 * cemerick used to use verdana 9-point all the time

13:35 hiredman: technomancy: *shurg* the swing default I expect

13:35 cemerick: That was back in my jedit days. ~2002, maybe

13:35 mec: ,(let [do 5] (do (println do) (+ do do)))

13:35 clojurebot: 5

13:35 10

13:35 hiredman: cemerick: given the wild code and lack of tests I think that is a safe assumption

13:36 mec: i knew it, special forms are magic

13:36 cemerick: hiredman: just checking :-)

13:36 amalloy: &(let [if 10 do 20] (if do (do if)))

13:36 sexpbot: ⟹ 10

13:36 cemerick: So yeah, images and such in a REPL will work. Maybe HTML+js+css in an embedded webkit container too, but that could get really unwieldy.

13:36 amalloy: mec: that one always looks funnier to me

13:37 hiredman: cemerick: but it would open the door to maginalia in the repl

13:37 mec: amalloy: nice one

13:37 cemerick: hiredman: true; for my part, I've never quite grokked the utility of such presentations though.

13:38 hiredman: but failing that, possibly marginalia could generate a documentation datastructure that could be used for other presentation mediums

13:39 since it does work like extracting comments (not just docstrings)

13:39 scottj: I have this function http://jaderholm.com/paste/show-help.html that I like for displaying docs, you just C-c C-h anywhere in the form and it tooltips the doc for the function like http://jaderholm.com/tmp/show-help.png

14:21 amalloy: scottj: C-c C-d C-d already does something pretty similar to that

14:22 technomancy: scottj: you think that could go into durendal?

14:38 carllerche: if using emacs & swank, is it possible to jump to where the symbol currently under the cursor is defined? M-. doesn't seem to work (neither does slime-edit-definition)

14:38 jfields: isn't there a built in fn to swap keys and vals in a map?

14:38 technomancy: carllerche: M-. should work as long as the file is compiled already

14:39 carllerche: technomancy: i just compiled the file (C-c C-k) then try it and get (definition not found)... but emacs is highlighting the definition right above it.

14:41 technomancy: man... I was a lot bigger fan of multimethods when they let you change the dispatch function =(

14:42 carllerche: do clojure.core fns work?

14:42 amalloy: technomancy: seriously, the defonce behavior there doesn't make me happy

14:44 (defmacro defmulti-for-realz [name & args] `(do (ns-unmap *ns* '~name) (defmulti ~name ~@args))) maybe?

14:44 technomancy: (def name nil) is actually enough

14:45 but srsly

14:45 scottj: technomancy: sure

14:45 carllerche: technomancy: clojure.core functions? like (and ...) ? they work in the open repl i have

14:46 scottj: amalloy: yes C-c C-d C-d has a few weaknesses you're probably aware of though, including that it's not a tooltip it opens a new window, and that it can't be run from anywhere in the form

14:53 technomancy: carllerche: yeah, you should be able to M-. on for in your clojure-mode buffer too

14:55 carllerche: technomancy: ah... i can M-. to a clojure.core function

14:55 just not to one in my current buffer (even though I thought I compiled it, i can try again)

14:56 technomancy: it isn't available in the current namespace. could be it hasn't been compiled, or it could be slime is confused about which is the current namespace.

14:56 carllerche: is there a way to tell (right now i'm trying to navigate around aleph)

14:56 scottj: carllerche: windows? you've run C-c C-k on current namespace?

14:57 carllerche: scottj: i have (and it did the fortifying message)

14:57 technomancy: it looks like it is confused about the current namespace

14:58 this is the file that I am in: https://github.com/ztellman/aleph/blob/master/src/aleph/netty.clj

14:58 tomoj: you may need the one-character tweak for new style ns metadata

14:59 scottj: probably that skip-wiki that's confusing it

14:59 technomancy: carllerche: yup, ^{:skip-wiki true} is throwing off slime's namespace detection heuristic

14:59 carllerche: tomoj: I'm just learning clojure :P not sure what the new style ns is

14:59 tomoj: in clojure-mode.el, in clojure-find-package, there should be a question mark after the #

15:00 technomancy: tomoj: nice.

15:00 tomoj: if that's missing, you add it, then C-M-x, maybe it will work

15:01 technomancy: tomoj: actually still no dice; only fixes it if the name is on the same line

15:01 that regex is terrifying

15:02 side note, that's the first useful non-docstring namespace-level metadata I've even seen

15:02 carllerche: should I just try to pull clojure-mode off of a git repo instead of elpa?

15:02 scottj: yeah makes me want to learn emacslisp package rx

15:02 technomancy: carllerche: no, I don't have a fix for it yet; sorry

15:02 ugly workaround is to just delete the :skip-wiki true bit for now

15:02 tomoj: huh.. I haven't run into the problem since I added that question mark. guess I just got lucky

15:02 carllerche: yeah... that's fine, i'll just browse aleph anymore :P

15:03 tomoj: carllerche: btw, in the issues for ztellman/potemkin on github you will find a patch that makes M-. skip the import-fns

15:03 always bugged me

15:03 scottj: carllerche: easiest would just be use imenu

15:04 carllerche: imenu? for what? (not super familiar w/ emacs yet either)

15:04 tomoj: technomancy: huh, seems to work for me

15:04 scottj: carllerche: for M-. in current buffer

15:05 tomoj: except when point is on the line with the name

15:05 scottj: carllerche: M-x imenu RET when on the function name ou want to go to

15:05 tomoj: or right after the metadata

15:33 redinger: carllerche: You hopping aboard the Clojure bandwagon finally? :)

15:34 carllerche: i'm dabbling :P

15:34 redinger: You looking at it for SproutCore? I briefly played with that for fun

15:35 carllerche: building some server components on top of netty

15:47 devn: <-not a huge fan of sproutcore

16:06 wires: hi, i want to install a plugin in leiningen which is on a sonatype repository; lein plugin install doesn't seem to search this repository. I specified the repository in project.clj:

16:06 :repositories {"sonatype" "http://oss.sonatype.org/content/repositories/releases"}

16:06 yet running lein plugin install org.cloudhoist/pallet-lein "0.4.1" failes because leinigen cannot find some dependency...

16:07 any thoughts..?

16:07 amalloy: wires: i wouldn't expect lein plugin to look inside any project's clj

16:08 dnolen: deftype/record/protocols kinda remind me of SML modules a bit.

16:08 wires: amalloy: so I'm not too suprised either, but how can I specify some other repositories to search besides the standard four

16:09 (clojure

16:09 clojure (http://build.clojure.org/releases),

16:09 clojars (http://clojars.org/repo/),

16:09 clojure-snapshots (http://build.clojure.org/snapshots),

16:09 central (http://repo1.maven.org/maven2)

16:09 dnolen: http://en.wikipedia.org/wiki/Standard_ML#Module_system

16:09 amalloy: eh. i use cake, which has a global project.clj as well as per-project ones

16:09 i'm sure lein has a way to do it

16:15 wires: amalloy: couldn't find anything on the google regarding that (add repository)

16:17 but thanks :)

16:45 thorwil: why o why do i get a status 200, despite using ring's redirect

16:46 brehaut: thorwil: paste up you handler somewhere?

16:47 thorwil: brehaut: currently the handler's only content is (rsp/redirect "/admin")

16:48 brehaut: thorwil: are you running an internal jetty?

16:48 thorwil: with [ring.util.response :as rsp]

16:49 brehaut: i guess, using appengine-magic

16:49 brehaut: im not familiar with the specifics of appengine-magic, but how are you specifying the handler to it?

16:51 thorwil: brehaut: routing via moustache, i just confirmed that the handler is definitively triggered

16:53 brehaut: thorwil: can you paste this all somewhere? id rather not keep making wild stabs in the dark

16:55 thorwil: of course, was just working on that

16:55 http://paste.pocoo.org/show/367472/

16:57 brehaut: thorwil: quick question: does the problem exists across restarts of your whole server?

16:57 thorwil: brehaut: yes

16:57 brehaut: (i dont know how the AEM stuff works but with the basic jetty adapter you can just keep reloading in the repl)

16:58 thorwil: is this your first moustache app?

16:58 thorwil: the paste i actually wanted to make, with the ns: http://paste.pocoo.org/show/367476/

16:58 brehaut: my first clojure app, even

16:59 brehaut: thorwil: ok sure. try changing delete-queue-article to (defn d-q-a [req slug] (rsp/redirect "/admin")) and the RHS of your inner app to (delegate d-q-a slug)

17:01 thorwil: unfortunately, that will have to wait for tomorrow :/

17:01 brehaut: thank you!

17:01 brehaut: thorwil: no problem

17:02 * thorwil should have looked at clock earlier

17:25 devn: redinger: you around?

17:36 maacl: If I define metadata for a field in a record like this: (defrecord Thing [#^{:foo "bar"} name]) how do I then read the metadata?

17:39 amalloy: maacl: i doubt it's possible

17:39 maacl: amalloy: ok, odd that it is possible to define it then

17:39 amalloy: maacl: it only seems that way

17:40 you're just putting metadata on the symbol "name", which defrecord probably doesn't do anything with; it just compiles into a basic java class with a field called "name"

17:40 maacl: amalloy: ok

17:40 amalloy: defn does you the favor of pulling metadata from the symbol and attaching it to the var

17:40 maacl: amalloy: shouldn't it be possible?

17:41 amalloy: everything "should" be possible

17:41 but the point of defrecord is to have basic, performant, host-level classes. how would that benefit from meta?

17:43 choffstein: hey all, quick question: can i define a function within a function that uses the values I have defined in the let statement above?

17:43 amalloy: yes

17:43 choffstein: I could just define an anonymous function, I suppose -- but I mean using the defn special form

17:43 scottj: what ns changing/creating form uses keywords for the name of the namespace? like (ns :foo)

17:44 amalloy: choffstein: you *can* do that, but having a function that contains "defn" at all is usually wrong

17:44 maacl: amalloy: well, my idea was to attach validator functions and "type" information so I could derive html fields (textbox, text etc) directly from the record class

17:44 choffstein: amalloy: okay. is it better to just do it a named anonymous function in my let statement?

17:45 amalloy: maacl: so don't use records. just use a plain old hashmap

17:45 maacl: amalloy: metadata look like an elegant approach to this

17:45 amalloy: choffstein: starting to get too vague/abstract. coedz plz

17:45 choffstein: amalloy: okay. i'll write up a quick gist

17:46 maacl: amalloy: sure, but then you loose the benefits you just outlined

17:47 choffstein: amalloy: https://gist.github.com/908804

17:47 but f would do more complex stuff...

17:47 amalloy: maacl: if you're doing any inspection on the fields, you were never getting those benefits anyway. you only get them if you know the fields at compile time

17:48 choffstein: that is a zillion times better than using a defn

17:48 choffstein: but basically relies on the two values in the let above which are big pieces of data. I know since it is immutable, it could just be pass by value -- but it feels weird since the function is only used inside the outer function.

17:48 amalloy: okay

17:48 amalloy: and a very common/powerful pattern

17:49 Let Over Lambda is a whole book about the exciting things you can do with this ability: you have a let sitting "over" a lambda (or clojure's equivalent, fn)

17:49 choffstein: Hmmm, I might have to pick that up

17:50 maacl: amalloy: What would be the diffference btw asking for a field and it's associated metadata?

17:50 amalloy: choffstein: you could even return a reference to f, letting other people take advantage of the a and b after they've gone out of scope

17:50 choffstein: amalloy: oh, that is very cool.

17:51 amalloy: or if complex-method-n really take no args, you could compute them at the top-most scope

17:51 (let [a (complex-whatever)] (defn process [x] (use x and a)))

17:53 &(let [make-adder (fn [a] (fn [x] (+ a x))), adder-5 (make-adder 5)] (adder-5 10))

17:53 sexpbot: ⟹ 15

17:53 amalloy: is kinda the classic example of this sort of thing

17:53 choffstein: ^

17:54 choffstein: oh, very cool

17:54 ohhh, yeah, i've seen that before

17:54 when I took my class on functional programming 4 years ago in college :D

17:56 tomoj: lucky they had one

17:57 amalloy: choffstein: in one of the early chapters LoL points out that you can easily build OO sorts of "objects" by stacking up with lambda::let::lamda

17:58 choffstein: sounds like this is a book i'm gonna have to pick up

17:58 amalloy: if you do, send me a copy

17:58 i only read the free chapters

17:58 choffstein: tomoj: Yeah -- it was in SML/NJ. Definitely hard to wrap my mind around at first.

17:58 amalloy: haha, well, you probably deserve it for how much you help me :D

17:59 amalloy: http://letoverlambda.com/

17:59 tomoj: is that the one that's like "lisp is the best language ever and this is the best book ever?"

17:59 ayup

17:59 amalloy: tomoj: are there lisp books that aren't like that?

17:59 Raynes: Mine!

18:00 Oh, you mean Common Lisp, don't you?

18:00 * Raynes grumbles

18:00 amalloy: i guess On Lisp doesn't claim to be the best book ever. it does definitely claim lisp is the best language

18:00 in fact i don't, mr whiny-pants

18:00 On Lisp has several chapters where he delves into scheme instead because common lisp would make the concepts ugly

18:01 tomoj: amalloy: sure, but..

18:02 I remember laughing almost hysterically after reading that intro

18:02 companion_cube: the first paragraph on the site is amazing

18:02 i like that this book title says "LOL" in whole letters

18:03 tomoj: perhaps just because of the "your humble author," at the bottom

18:04 which I hope was a joke

18:11 Borkdude: I am trying out some compojure and want to send a hebrew unicode character to the client

18:11 but it gets displayed as a question mark. does anyone know where things could go wrong?

18:11 amalloy: Borkdude: character encoding

18:13 Borkdude: for example, I have this:

18:14 (defroutes handler (GET "/" [] "\u05D2"))

18:14 Raynes: I managed to screw try-clojure.org up in the most hilarious of ways -- it now links to a Ruby on Rails getting started page.

18:14 Borkdude: amalloy: do you know if there is something which fixes this problem?

18:15 I can display the letter just fine with my GWT-application

18:15 but that is probably because it is all client side

18:15 amalloy: Borkdude: i don't do much web programming. i'd say make sure you set your character encoding to match whatever java is sending

18:15 tomoj: is there a header for that or just the meta tag?

18:16 amalloy: tomoj: header

18:16 tomoj: oh, in the content-type header

18:16 ?

18:16 amalloy: i think so

18:16 scottj: technomancy: what do you think? https://github.com/scottjad/clojure-mode/commit/ab9e3f175024a5d5f355c9a2359b2bcbb989964f

18:17 brehaut: tomoj: the meta tag is the http-equiv for the header of same

18:17 amalloy: tomoj: <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

18:17 is just a workaround for setting the header called Content-Type when you don't have access to modify the actual server

18:17 technomancy: scottj: nom!

18:17 scottj: looks great; thanks

18:17 maybe put the test in a separate file?

18:17 do you have commit on my repo?

18:17 brehaut: the metatag has a sideeffect of causing processing of the whole html doc to restart to reinterpret with the new content type so make sure its as early as possible

18:18 scottj: technomancy: maybe just on swank-clojure

18:18 technomancy: scottj: you do now; feel free to give it a push

18:18 scottj: technomancy: I think someone wouldn't see the tests if it were elsewhere

18:19 technomancy: btw in case you didn't notice this fixes the dude earlier's problem

18:19 but also supports 1.3 style ^:foo and stacking those

18:19 technomancy: scottj: yeah... don't worry about the tests then

18:19 woot

18:19 clojure-mode-test.el would just get confused with clojure-test-mode.el

18:20 scottj: there are a couple cases of metadata that don't work, they're the ones with :fail in the tests

18:20 I remember hearing regexes can't ensure matching parens, that's why I didn't look into those failing cases

18:20 I don't know if that's true

18:21 tomoj: I wonder if that's specific to regex or all regular languages

18:22 technomancy: IIRC it's that regexes can't be used for handling general nesting of arbitrary depth

18:22 Borkdude: amalloy: like this? https://gist.github.com/908901

18:23 tomoj: guess it's not just regexes http://en.wikipedia.org/wiki/Pumping_lemma_for_regular_languages

18:23 Borkdude: amalloy: I just edited an example program from here http://mmcgrana.github.com/2010/07/develop-deploy-clojure-web-applications.html

18:24 amalloy: but I want to do some hebrew stuff with it

18:26 amalloy: Borkdude: augh. you're writing a webserver. don't put http-equiv in your document when you have the option of passing an *actual* http header

18:27 Borkdude: also, find out what character encoding java is actually sending. it might be utf-8, but i don't know

18:28 Borkdude: does compojure really want the doctype inside of the html tag?

18:30 Borkdude: amalloy: view source, then I see this: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html ...

18:30 amalloy: so that looks correct I guess

18:32 tomoj: the "html" there is just the hiccup macro

18:33 that it looks like it's supposed to be the html tag is misleading

18:39 amalloy: fun

18:52 _Vi: How to force Leiningen to offline mode (like "mvn -o")?

18:53 "lein deps -o" fails (behaves just like "lein deps")

18:55 technomancy: _Vi: in general it shouldn't be necessary. what's the problem you're trying to solve?

18:57 _Vi: technomancy, Try "lein uberjar" on project created by "lein new" without downloading megabytes of jars first (I prefer to build clojure of the required version from source and then install it by 'mvp install-file' or whatever)

18:57 s/mvp/mvn/

18:57 sexpbot: <_Vi> technomancy, Try "lein uberjar" on project created by "lein new" without downloading megabytes of jars first (I prefer to build clojure of the required version from source and then install it by 'mvn install-file' or whatever)

19:00 _Vi: And I want Leiningen/maven to try-and-fail downloading that file and output "Try downloading the file manually from the project website. Then, install it using the command" message with correct command.

19:02 technomancy: there's not really any way Leiningen could support doing that well

19:02 _Vi: technomancy, Is Leiningen based on Maven?

19:03 technomancy: unless maybe you put your own marker in the version string when you do mvn install so it doesn't try to use any of the official Clojure builds maybe

19:03 pdk: if lein can't find it in its repositories then it doesn't know it exists

19:03 technomancy: it is

19:03 pdk: so it can't make assumptions about where it is and how it's installed :p

19:03 technomancy: what I'm saying is the equivalent of "mvn -o" wouldn't really solve the problem you're describing

19:04 _Vi: (applied workaround by temporary "iptables -I OUTPUT -m state --state NEW -j REJECT")

19:04 technomancy: you could also use :omit-default-repositories true in project.clj

19:05 miltondsilva: Hi, I think I saw some clojure benchmarks on a azul machine, but now I can't find them, does some one have a link or were I just dreaming?

19:05 amalloy: _Vi: that sounds as sophisticated as ripping the ethernet cable out of your machine. why not just do that?

19:05 _Vi: technomancy, Workaround succeed. The result is "mvn install:install-file -DgroupId=org.clojure -DartifactId=clojure -Dversion=1.2.1 -Dpackaging=jar -Dfile=/path/to/file". How do to is properly?

19:06 amalloy, Don't want to lose connections/SSH session/this chat.

19:06 tomoj: why would you rather it error out so you can go compile from source instead of just downloading it?

19:07 amalloy: so you don't want an offline version of leiningen at all. you want it to print out "here's the command to install a jar"?

19:07 Borkdude: amalloy: I now have this :headers {"Content-Type" "text/html" "charset" "utf-8"}

19:07 amalloy: charset is not a header; it is a part of the content-type header

19:07 Borkdude: amalloy: but in chrome I see these headers: Content-Type:text/html; charset=iso-8859-1 Date:Thu, 07 Apr 2011 23:01:52 GMT Server:Jetty(6.1.14) charset:utf-8

19:08 amalloy: ah that explains it

19:08 tomoj: it already does print out "here's the command to install a jar", doesn't it?

19:08 amalloy: {"Content-Type" "text/html;charset=utf-8"} or something

19:08 _Vi: tomoj, Yes, because of my internet connection is rarely cheap and stable.

19:09 Borkdude: amalloy: it works! tnx

19:09 _Vi: Question 2: Why leiningen just copies libraries from $HOME/.m2 to libs/ when it can sym/hardlink them? Unnecessary duplication.

19:09 amalloy: _Vi: echo echo "mvn install:install-file -DgroupId=org.clojure -DartifactId=clojure -Dversion=1.2.1 -Dpackaging=jar -Dfile=/path/to/file" > ~/how-to-install-a-jar.sh

19:10 ./how-to-install-a-jar.sh

19:10 now, you never need lein in offline mode again

19:10 _Vi: What if I don't exactly know the groudId, artifactId and don't remember is it "mvn install-file" or "mvp install:file"? Why Maven itself has "-o" option then?

19:11 amalloy: _Vi: that's why i just told you to write it to a file

19:11 then you won't forget

19:12 _Vi: amalloy, For example, can I ask Leiningen to output equivalent "mvn" command? (so that I can modify it and execute)

19:13 scottj: technomancy: _Vi no, lein doesn't use the mvn command

19:14 amalloy: the things that you want are fundamentally weird and undesirable. it's hard to make recommendations for "how to use lein without using lein"

19:14 scottj: _Vi: symlink issue has been discussed on mailing list

19:14 amalloy: if your connection is slow, then fetching the source will be no faster than fetching a jar. both will be cached in ~/.m2

19:14 so the difference is, if you fetch source you have to compile

19:15 _Vi: scottj, And what the conclusion is? (and what about hardlinks?)

19:15 amalloy, If I have clojure's Git repository I can build any version.

19:16 scottj: _Vi: I don't remember, you can check the archive

19:23 technomancy: _Vi: you can have jars symlinked into lib/; future versions will construct the classpath straight out of ~/.m2

19:24 they are copied for historical reasons, because the calculating the classpath needed to be as simple as possible

19:24 _Vi: technomancy, (after reading maillist) May be it should be the option? E.g. by default it will construct the classpath, but run "lein lib" and it build "lib" directory.

19:25 technomancy: _Vi: yes, that will probably happen in 2.0

19:25 hiredman: clojurebot: scopes?

19:25 clojurebot: Huh?

19:25 hiredman: clojurebot: scope?

19:25 clojurebot: scope is at http://paste.lisp.org/display/73838

19:26 _Vi: technomancy, OK. /* may be add maven's options like -o, -fn, -D, -s as well? */

19:28 technomancy: -D is handled in Leiningen by making tasks functions that take arguments instead of needing fancy syntax for arguments. I don't know what -fn or -s are

19:29 _Vi: -fn is "fail never" mode. Like "make -B -i". Like "build as much of the project as you can, ignoring errors".

19:29 -s is to specify other Maven settings file.

19:30 technomancy: you can specify an alternate settings file by setting the LEIN_HOME environment variable

19:31 I can't think of a justifiable use case for fail-never

19:31 _Vi: In general, should Maven and Leiningen command-line interface be somewhat compatible?

19:32 technomancy: (not that there isn't a use case; I would just need to be presented with one before considering it)

19:32 _Vi: not at all.

19:33 the only overlap between the two is the mechanism by which they fetch and cache dependencies internally

19:33 and I guess deploying to remote repos now

19:33 _Vi: technomancy, Large project that fails to build (and builds very long time when succeeds). You start "mvn -fn", it builds most of the project, you go for a walk. When you return, it finished the build, you restart without "-fn", fix error, "mvn" again, fix error etc. Don't need to wait loads and loads of time between fixing errors.

19:34 technomancy, OK, I thought Leiningen just prepares things to run Maven.

19:34 technomancy: leiningen builds typically don't have multiple compilation phases

19:35 it should already DTRT if deps fail. I guess if AOT fails maybe it would be nice to be able to fall back to stale class files? I'm not sure. but it would be very different from the way maven does it.

19:35 most "builds" don't even involve AOT compilation

19:51 amalloy: technomancy: Make include make -i, which i found useful for similar reasons: "if a command fails, give up on its dependent subtree, but keep doing as much useful work as you can"

19:52 i haven't found any reason to want it in clojure yet

19:53 _Vi: Question 3 (not about lein): Writing Swing application. I want program to exit when the window is closed, but not when I running it from REPL. What is the best practice for this?

19:54 Is there something like (when (not *running-from-repl*) (System/exit 0))?

19:55 technomancy: ,(bound? #'*1) ; might be one way to check if you're repling it up

19:55 clojurebot: false

19:55 amalloy: haha ewwww

19:56 _Vi: see also ##(doc when-not)

19:56 sexpbot: ⟹ "Macro ([test & body]); Evaluates test. If logical false, evaluates body in an implicit do."

20:13 TimMc: _Vi: DISPOSE_ON_CLOSE

20:13 amalloy, technomancy: You people are disgusting. :-P

20:14 amalloy: wut?

20:14 TimMc: that doesn't solve his problem at all

20:15 iirc, java doesn't stop the process just because there are no non-disposed windows

20:15 TimMc: _Vi: Does your main thread exit after launching your swing app?

20:16 _Vi: TimMc, Yes, it just uses SwingUtils/invokeLater.

20:17 TimMc: _Vi: https://github.com/timmc/CS4300-HW3/blob/master/src/timmcHW3/gui.clj#L194

20:18 As long as you don't have any other threads, Swing will exit the JVM when all windows have been closed and disposed of.

20:19 amalloy: TimMc: ah, i guess that changed in 1.4, apparently

20:19 TimMc: ah

20:19 _Vi: Also: I start 1. "lein repl", 2. "(-main)", 3. Window shows, 4. I close the window, 5. I change the source file, 6. "(-main)" again, 7. The same (non-reloaded) window appears. How to make it like with :reload-all?

20:20 TimMc: amalloy: I went from developing AWT in 1.2 to not using Swing (until recently) in 1.6.

20:20 livingston: is there a good example of calling some clojure code from java anywhere? (there seems to be some competing options on the web) I have a library I would like to expose to some java programmers.

20:20 TimMc: _Vi: (use 'foo.core :reload-all) as step 5.5 doesn't work?

20:23 _Vi: TimMc, OK, considering it as simple enough because of namespace name is already here (before "=>") thing.

20:24 s/\) thing/ thing)/

20:24 sexpbot: <_Vi> TimMc, OK, considering it as simple enough because of namespace name is already here (before "=>" thing).

20:25 amalloy: livingston: don't call clojure code from java. instead, use clojure to gen-class a real java class

20:25 hiredman: amalloy: stop that

20:25 amalloy: i mean, it's *possible* to call clojure from java, but it's a lot more painful

20:25 hiredman: you can call clojure from java just fine

20:25 TimMc: Terminology difference?

20:25 amalloy: or do what hiredman says. whatever

20:26 hiredman: ((IFn)RT.var("clojure.core", "println").deref()).invoke("Hello World");

20:26 livingston: amalloy: I've seen that option, but if I don't have an actual class I want to expose, just some functions, it seems a bit heavy handed...

20:26 hiredman: casting could be off, not sure

20:26 ^-

20:27 amalloy: hiredman: casting looks right to me

20:27 TimMc: livingston: gen-class should be fine

20:27 livingston: hiredman: that was the kind of example I was looking for, I saw something like that, but wasn't sure it was still preferred.

20:27 hiredman: it is

20:27 livingston: that seems a little messy to get a java coder to want to do though

20:28 hiredman: it is clojure transliterated into java (except clojure does some caching around var derefing)

20:28 TimMc: hiredman: That's really preferred over a gen-class? Ew.

20:28 amalloy: livingston: with genclass you can get something more like: new ClojurePrintlnWorker().print("Hello World")

20:29 hiredman: livingston: you can also use definterface + defrecord (or deftype)

20:29 TimMc: Throw a factory in there somewhere, it's not idiomatic enough yet.

20:29 hiredman: gen-class is digusting

20:29 amalloy: *murders TimMc*

20:29 livingston: TimMc: lol

20:29 hiredman: it has no useful place except interacting with java code you have no control over

20:29 _Vi: (when-not (bound? #'*1) (System/exit 0)) fails. It exits even if I run from "lein repl".

20:29 amalloy: hiredman: that sounds exactly like his situation

20:30 TimMc: hiredman: Which is what libraries do all the time.

20:30 livingston: I actually do have defrecords that will be returned

20:30 hiredman: amalloy: it doesn't at all

20:30 amalloy: "there are some java programmers who i wish would use my clojure code but they don't know/like clojure"

20:30 hiredman: if he wants to call java from clojure obviously he has control over the java

20:30 amalloy: hiredman: "I have a library I would like to expose to some java programmers."

20:31 hiredman: so you can use definterface to generate and interface, deftype or defrecord to implement it, and the java programmer will just new up your type and call your methods and it will all work

20:31 no gen-class

20:31 livingston: I have a lab full of java coders (and a lot of existing java code) that will benefit from some of my stuff - I'm just trying to get it to them as conveniently as possible.

20:32 amalloy: livingston: definterface/defrecord does sound like a good approach

20:32 once you get past the dogmatic shouting about gen-class

20:32 livingston: hiredman: I have protocols too, so that should get me the interfaces right..

20:33 hiredman: livingston: for java interop definterface is nicer

20:33 lets you specify types etc so you can avoid casting

20:33 https://gist.github.com/909068

20:33 is what it kind of ends up looking like

20:33 livingston: I just also had some helper functions that instanciated one of the records and was hoping to expose that too, in addition to the objects.

20:33 oh cool

20:34 hiredman: definterface has some quirks

20:34 type hinting seems to be sort of broken, unless you do the string thing like I did there

20:34 (on 1.3 alpha something or other)

20:35 I would recommend defrecord unless you know that you need deftype

20:35 livingston: oh that's weird, I'm still on 1.2 (this is all still there too? or I need to upgrade?)

20:36 hiredman: ,definterface

20:36 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/definterface

20:36 livingston: I have been using protocols and defrecord so far, it works good in the clojure world, but to go to the java world you're suggesting definterface

20:36 hiredman: ,*clojure-version*

20:36 clojurebot: {:major 1, :minor 2, :incremental 0, :qualifier ""}

20:36 hiredman: yes

20:36 because if you use definterface at the java boundry you don't need to do all this casting

20:39 _Vi: How to check if we are running from "lein repl" if "(bound? #'*1)" fails?

20:40 livingston: how does definterface compete/compliment protocols? I just switch over entirely or use them both

20:41 protocols say "defprotocol will automatically generate a corresponding interface, with the same name as the protocol, i.e. given a protocol my.ns/Protocol, an interface my.ns.Protocol. The interface will have methods corresponding to the protocol functions, and the protocol will automatically work with instances of the interface."

20:41 oooh right but the type hints, duh

20:41 hiredman: right

20:41 protocol interface methods all have Object signatures if I recall

20:42 livingston: although all clj function effectively do under the hood, this is really only an issue for the return type right? re: calling from java

20:43 hiredman: deftype+definterface get you very close to bare vm, minimal reliance on clojure runtime

20:43 livingston: depends

20:44 my main annoyance is macros that get expanded out of the code still end up having their vars referenced in the class file

20:44 (with deftype+definterface)

20:45 livingston: I can't find the documentation on definterface

20:46 hiredman: ,(doc definterface)

20:46 clojurebot: "([name & sigs]); "

20:46 hiredman: heh

20:46 like defprotocol, but with type hints

20:46 livingston: it's remarkably absent on the web too

20:46 ok

20:46 hiredman: right, not an often used feature

20:47 I fear most people do horrible things like use gen-class or worse

20:47 technomancy: hiredman: how's that compiler patch coming? =)

20:49 hiredman: technomancy: I have it patched on a local branch, but the compiler is significantly altered there so I can just take it from there

20:49 and I wasn't sure that I actually got the go ahead

20:50 livingston: so I use the interface just like the protocol it seems and I still get to avoid dispatch etc. that's good. I can use it with defrecord just like I am right? (if I just change my defprotocols to definterface and add type hints I'm 90% there right?)

20:50 hiredman: yes

20:50 livingston: hiredman: cool - thanks.

20:51 hiredman: actually, it maybe better to switch to deftype in some places, I kind of recall defrecord's being a drag to create in java, but deftypes get a no-arg constructor

20:51 I don't entirely recall though

20:51 may be

20:54 technomancy: I've have to remember how to find clojure's jira too

20:54 livingston: oh huh. ok. I went with records because I was using some extra map fields too

20:55 technomancy: hiredman: yeah... good luck with that. =)

20:57 jweiss_: does it make much difference in performance ( or size of compiled classes, etc) to have code produced by a macro, versus factoring that code out into its own function and having the macro call it?

20:58 seems kinda wasteful to have my macro that's called so many times, expand into a fair bit of code when i could just put it in a function... but then all the callers would have to know about that function as well, which is why i haven't done it.

20:58 tomoj: call it once? no. otherwise? seems impossible to answer in general

20:58 jweiss_: tomoj: let's say it's called in thousands of other places

20:58 tomoj: bah

20:59 jweiss_: let me be more specific, does the size of the generated classes shrink if i factor it into its own fn?

20:59 livingston: jweiss_: if you are using macros to optimize compiled code size, you might be doing it wrong...

20:59 tomoj: I think any optimization advice from me will be premature

20:59 jweiss_: livingston: my purpose isn't to optimize, i'm just wondering if the way i did it was inefficient in some way.

20:59 hiredman: jweiss_: macros do make the generated byte code larger

20:59 tomoj: does the size of generated classes matter for some other reason besides disk space?

20:59 load time or something?

21:00 jweiss_: compile time does matter a bit

21:00 hiredman: tomoj: they have to exist in ram

21:00 jweiss_: and ram too

21:00 tomoj: ah

21:01 livingston: in general for clean maintainable code you want functions, when you need to add to the language, require that something be called before or after a block etc. use a macro then

21:02 jweiss_: livingston: these macros are just sugar mostly, to allow my callers to write more succinctly

21:02 livingston: macros are powerful tools, but often over used

21:02 jweiss_: there's no doubt i need a macro (unless i want my callers writing repetitive stuff)

21:03 livingston: depending on what it is, they were going to write it anyway, it just gets compiled away (lots of the core "functions" are actually macros) there's no harm in them

21:03 tomoj: I feel like I don't really understand well the problem of visibility there

21:04 jweiss_: tomoj, if my macro is the only thing 'used' from the namespace, and it calls another fn in its namespace, my callers need to 'use' it too.

21:04 tomoj: the functions need to be public, at least, but the callers will never need to require or use some namespace to use a macro, right?

21:04 (..besides the one the macro is defined in)

21:04 ah

21:04 jweiss_: hm, i thougt they did

21:04 tomoj: I was actually asking

21:05 it would surprise me if they did, though

21:05 unless the macro is written badly

21:05 jweiss_: hm, well that may be the case :)

21:05 tomoj: syntax quoting's full qualification seems like it would get rid of that problem

21:05 jweiss_: i tried once to factor out the lengthy code into a fn, and that's the problem i hit

21:05 i think i'll give it another go, seems worth it from the responses i've gotten here.

21:06 tomoj: yeah, i thought it would have worked but it didn't. i didn't investigate fully, so i'll do that now :)

21:09 tomoj: huh

21:09 that you can defmacro something that syntax-quotes a symbol that doesn't resolve is interesting

21:10 in that case the macro-definer may clearly rely on callers to at least require the namespace

21:10 wait.. that can't be right. I'm confused and giving up now.

21:12 hiredman: the symbols will be fully qualified, so they will resolve correctly as long as the namespace with the var they point to has been loaded

21:12 but there is nothing to guarantee that

21:12 livingston: tomoj: you can quote anything your want in a macro - all macros are are ways of manipulating the s-expressions (or whatever clj calls lists etc.) that are the sequences of symbols etc that are then handed off to the compiler -- it's then the compilers job to sort out what's there or not

21:12 hiredman: presumably the namespace you got the macro from makes sure supporting code is loaded

21:12 tomoj: my confusion is that the process of fully qualifying a symbol is namespace-dependent

21:13 ..right?

21:13 hiredman: at compile time

21:13 tomoj: so how come there's no error at compile time?

21:13 hiredman: but load + runtime can take place on a different jvm

21:13 without the needed namespaces loaded

21:13 tomoj: oh, I think I see

21:14 yeah, (defmacro foo [] `baz) in user complains about user/baz when you try to use it in some other namespace

21:18 livingston: on java interop: so I can easily pass a clojure map/hash back to java caller of my function, but now they are going to have casting nightmares working with it aren't they?

21:21 tomoj: what are they dreaming of casting to?

21:21 ataggart: livingston: only if they work with it as something other than a java.util.Map.

21:21 livingston: I more meant the values in it

21:22 ataggart: ,(.get {1 2} 1)

21:22 clojurebot: 2

21:23 livingston: I just mean that on the java end the type signature is going to be Object on the keys/vals etc. and they'll have to know to cast accordingly

21:26 ataggart: how are you getting the map from clojure?

21:26 into javaland

21:27 hiredman: how do you tag files in jira?

21:28 livingston: oh good point - with a call off an interface - I could probably put a type signature on the interface...

21:28 tomoj: a definterface interface?

21:28 livingston: ... except the values in the hash could be a couple of different things so, yeah, they'll just have to deal with it I guess.

21:28 tomoj: yes

21:28 tomoj: you can't fill in generic types there, can you?

21:28 (or whatever they say in javaland)

21:29 livingston: yeah I could.

21:30 tomoj: oh? what's the syntax?

21:31 livingston: the key is symbols, the value unfortunately will be symbols, strings, or numbers ... so there's no avoiding that for them they'll just have to get it out into an Object variable and deal from there

21:31 hiredman: what do you mean tag? point to one somewhere else? or upload one? (that's under the "more actions" menu at least on our install)

21:33 hiredman: livingston: dunno, http://clojure.org/patches says 'tag'

21:33 I kind of recall figuring out how to do that in assembla

21:36 livingston: hiredman: oh. there are labels for issues (that I think work like "tags"), maybe after you upload the file you can put labels/tags on it too?

22:08 trptcolin: is it accurate to say that if there are multiple protocol implementations for a given record/type, the impl in the last ns to be loaded in that process/classloader wins? regardless of the current ns's ns dependencies?

22:09 that's what i'm observing, but i'd thought the faux-monkey-patching capabilities were supposed to be namespace-limited, so i think i'm misunderstanding one end or the other

22:12 Havvy: "lib names inside prefix lists must not contain periods" when I put "[:use '[irclj.core]]" in an (ns). If I do (use 'irclj.core) it works. What am I doing wrong?

22:12 pdk: the ' shouldn't be needed in the (ns) case

22:13 it's all being quoted in there already

22:13 Havvy: Oh. :/

22:24 trptcolin: :) of course the answer is in Joy of Clojure

22:26 Havvy: All I've got right now is Stuart Holloway's book. ;)

22:26 trptcolin: Havvy: sorry, i meant the answer to my question

22:26 Raynes: Havvy: Check out sexpbot and his irc.clj for an more decent example of Ircljiness.

22:26 $whatis sexpbot

22:26 sexpbot: sexpbot is not clojurebot

22:27 tomoj: Havvy: also, vectors there are odd

22:27 kephale00: $whatis clojurebot

22:27 sexpbot: clojurebot does not exist in my database.

22:27 Raynes: $whatis source

22:27 sexpbot: source is http://github.com/cognitivedissonance/sexpbot

22:27 tomoj: for some values of "wrong" that is wrong

22:27 Raynes: Havvy: Furthermore, if you have any problems or queries, #sexpbot would is our little channel.

22:27 tomoj: it'll work, but it's nonstandard

22:27 Havvy: I don't see a case where vectors would not work there.

22:28 Raynes: Minus the 'would'. Long day. <3

22:28 tomoj: specifically for (:use ...) vs [:use ...], vectors deeper inside are common

22:28 but vectors right there... I think this is the first time I've ever seen them

22:29 Havvy: I've seen code that has vectors for all of them not written by me.

22:30 brehaut: Havvy: vectors are weird there because in a list, the first term has 'precedence' (inaccurate term) over the rest of the list, while ina vector all terms are equal

22:30 trptcolin: Havvy: sure, that may be, but it's fairly rare in clojure code

22:30 Havvy: Raynes: With irclj, whenever I start it, I get a NullPointerException, but it continues running.

22:30 tomoj: well, if it works and you like it, go ahead :)

22:30 brehaut: Havvy: in other words, the meaning of a list is denoted by the first thing (eg :use) but a vector isnt

22:31 tomoj: we'd be worse off if everyone always agreed

22:31 but do expect funny looks

22:31 Raynes: Havvy: That's odd. Did you try running the example bot? Chances are, it's your code causing the NPE.

22:32 TimMc: I get vectors and lists mixed up in the require, use, and import forms all the time.

22:32 Usually it doesn't make a difference.

22:32 Raynes: Surprisingly, I don't.

22:32 livingston: I don't like how sometimes it's vectors in code and sometimes lists - it makes certain types of macros etc. on code a pain because you can't just cons stuff up you have to get the right containers back in there

22:34 brehaut: livingston: know your standard lib ##((juxt identity vec) (cons 1 [2 3]))

22:34 sexpbot: ⟹ [(1 2 3) [1 2 3]]

22:34 mec: cons always adds to left and makes a seq, conj is the one that changes

22:34 brehaut: forms generally use vectors to denote special evaluation semantics

22:36 Havvy: My code changes so far include adding a personal namespace, changing the server/channels it connects too, and adding another form to the :on-message handler...

22:36 devn: ,(conj '(1 2) 3)

22:36 clojurebot: (3 1 2)

22:36 livingston: brehaut: somethings work, say if you're just adding (cons, etc.) but if you have to muck it up more or rebuild the whole thing because say you've replaced something deep in the sexp then your traversal algorithms need to know more.

22:36 devn: ,(cons 3 '(1 2))

22:36 clojurebot: (3 1 2)

22:36 devn: ,(conj [1 2] 3)

22:36 clojurebot: [1 2 3]

22:36 devn: ,(cons 3 [1 2])

22:36 clojurebot: (3 1 2)

22:36 brehaut: livingston: then use the appropriate traversal functions; the standard lib is full of tools for processing all of its built in structures

22:37 livingston: [colloquial saying about hammers here]

22:37 devn: ,(doc juxt)

22:37 clojurebot: "([f] [f g] [f g h] [f g h & fs]); Alpha - name subject to change. Takes a set of functions and returns a fn that is the juxtaposition of those fns. The returned fn takes a variable number of args, and returns a vector containing the result of applying each fn to the args (left-to-right). ((juxt a b c) x) => [(a x) (b x) (c x)]"

22:37 livingston: don't mind me I'm a grouchy lisp hacker - and "get off my lawn"

22:43 brehaut: clojure seems to reside in an uncanny value for people from more traditional lisps

22:43 s/value/valley/

22:43 sexpbot: <brehaut> clojure seems to reside in an uncanny valley for people from more traditional lisps

22:44 livingston: brehaut: yes. there are things like the transactional memory that make it very attractive though, but others that are annoying (still way better than java though)

22:45 tomoj: wonder what the once crusty CL'ers who stick with clojure for, say, two years, think

22:45 if there are any?

22:45 gotta be at least a few

22:46 pdk: i havent really seen any posts from people making a serious cl -> clojure transition

22:46 but sure as hell plenty from cl guys dissing it from a distance

22:46 tomoj: heh

22:46 livingston: tomoj: I've been here almost 1 year, give or take. (I'm in a place that does mostly Java though, so if it's clj or java, ... if it's CL or clojure, I don't know yet, jury is still way out on that one)

22:46 tomoj: I can equally only diss CL from a distance

22:47 but it's hard for me to imagine the jury not returning immediately

22:47 pdk: there's certainly a few snap judgments immortalized in blog posts out there

22:47 tomoj: but of course I focus more on the stuff I like about clojure and don't know what I'm missing in CL

22:48 from this point of view it seems like, how can you live without a built-in set of persistent data structures?

22:48 livingston: CL has it's problems, but look at how long it's survived and the functionality it had way before anyone else - all the other stupid crippled object models etc. that came after CLOS etc.

22:48 TimMc: pdk: The phrase "immortalized in blog posts" struck my funny bone for some reason.

22:48 pdk: two things i tend to miss from cl

22:48 cl's handling of exceptions

22:49 and multiple-value-call

22:49 it's really useful to know when nil is being returned as a sentinel value vs when it's the actual return value of a data structure lookup

22:49 tomoj: both correspond to weaknesses clojure inherits from the jvm, yeah?

22:49 livingston: multiple-value-bind is huge - I miss that so much

22:49 devn: anyone know of any existing clojure parsers out in the wild?

22:49 tomoj: (where "inherit from the jvm" means "rich thinks it's too ugly to hack this into the jvm")

22:50 livingston: pdk: yeah, clj for traversing lists etc. seems ever so slightly less elegant than CL, but there's some nice things too like the sequence abstraction over maps etc. that you just don't have in CL

22:52 java question: can names have hyphens in them? i.e., if I'm calling definterface I better make my names look right if the java people want to call them

22:53 brehaut: livingston: they cant but i believe (test this!) that clojure in 1.2.1+ does the right thing to munge it to javaable

22:54 livingston: brehaut: yuch, I don't want it to look funny, rather they just match ugh

22:54 brehaut: livingston: well it is a type, so java convention is UpperCamelCase

22:54 and thats entirely appropriate for clj too

22:55 (i believe the munging is that hyphens become underscores)

22:55 livingston: that's what happens with ns names

22:55 tomoj: as a lisp1 I think camelcase should be viewed as useful, not ugly

22:56 s/as a/as clojure is a/

22:56 livingston: camel case is another thing that rubs my lisp side funny

22:56 tomoj: well, you had a lisp2, probably? not that that totally explains your rubbiness

22:57 pdk: not seein the connection here :p

22:57 i've never seen hyphens in java symbol names

22:58 brehaut: pdk that would be a direct result of the java lexer thinking - is an operator right?

22:58 pdk: this is kinda why letting people write x-y; and x - y; is bs :p

22:59 or worse yet

22:59 livingston: pdk: CL convention is count-pattern (and what I'm inclined to put in my definterface as names, but Java convention is countPattern

22:59 pdk: *x/*y;

22:59 good ol C

22:59 clojure code ive seen always used cl convention

23:00 livingston: right, but when I want them to talk to each other using defprotocol / definterface I have to be more cognizant of the border

23:01 programming in prefix notation has totally ruined me for infix. I screw that up all the time "x minus y" ok write that first, now "times z" wait why is this so negative... 5 minutes later, oh

23:04 tomoj: I've still yet to learn calc

23:05 which is, what, postfix by default? I feel like I really like RPN and that it is unexcelled but have barely used it\

23:13 technomancy: chouser: have you documented anywhere your specific reservations about the error-kit implementation?

23:25 livingston: do function names from definterface need to be called like java functions with the (.fn args) dot notation? instead of like plain clj functions that you get with defprotocol

23:26 dnolen: livingston: yes, definterface is for declaring Java interfaces.

23:27 livingston: dnolen: thanks. and arghh that's a lot more code that needs updating now, just to see if this is going to work

23:28 dnolen: livingston: did it seem to you that definterface and defprotocol were similar?

23:29 livingston: actually there seems to be no docs on definterface, and I had a lot of defprotocol code that runs well on the clj side but I want to make that available to java people as a library

23:30 hiredman suggested that the change was a good way to go as I could put type signatures on my functions then to help the java people

23:30 dnolen: livingston: defprotocol creates Java interface from what I understand.

23:30 livingston: yes

23:31 and I understand that I can use either protocols or interfaces for the "interfaces" of defrecord and deftype

23:33 I guess there's no reason I couldn't implement a protocol and an interface, but that seems redundant and like I should only need one.

23:33 dnolen: livingston: definterface to me stinks, it's only about perf and interop.

23:33 livingston: I mean rather, definterface is great for those two scenarios. Yucky otherwise.

23:34 livingston: well if I'm giving a library to some java hackers... interop is kinda called for. although that's not the only thing this library will be used for, and it will be used extensively by clojure code too

23:35 dnolen: livingston: writing a macro to declare both the protocol and the interface for interop seems like the way to go to me at least.

23:36 livingston: defprotocol gives you an interface, but I think everything's type signature is just Object everywhere

23:55 if I have a compiled java .class file is there any magic I can use to see what's in it?

Logging service provided by n01se.net