#clojure log - Dec 05 2011

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

1:02 rads: also why do fully qualified keywords always give the user namespace in clojurescript?

1:20 sunng: it looks a strange behavior when using `case`:

1:20 ,(let [c (int 1)] (case c (int 1) "matches"))

1:20 clojurebot: "matches"

1:21 sunng: ,(let [c (short 1)] (case c (short 1) "matches"))

1:21 clojurebot: "matches"

1:21 sunng: ,*clojure-version*

1:21 clojurebot: {:major 1, :minor 3, :incremental 0, :qualifier nil}

1:21 sunng: wow, I think it's a bug in clojure 1.2 and fixed in 1.3

3:12 amalloy: sunng: the test-expressions in case clauses have to be compile-time constants; i believe 1.3 made it possible for more things to be regarded as constants. but in general, ##(case 1 (2 1) "either 2 or 1") is how lists are supposed to be used in a case expression

3:12 lazybot: ⇒ "either 2 or 1"

3:16 sunng: amalloy: I just find that in clojure 1.2 (case (int 1) (int 1) "ok") could return "ok" but (case (short 1) (short 1) "ok") failed. The inconsistency just confuses me a lot.

3:16 amalloy: &(hash (short 1))

3:16 lazybot: ⇒ 1

5:11 ambrosebs: I want to convert (fn. [[a :- type1] [b :- type2]] ...) to (fn [a b] ..) , with (meta a) = {::type type1}

5:11 any suggestions as to how to go about this?

5:11 also the more general case of the multi-arity syntax

5:12 I would use assoc but it doesn't work with lists

5:15 nvm, forgot about map :)

5:30 siancu: morning

6:01 triyo: I have a list of maps that I wish to merge; merge as in structural merge. Example [{:cons_data {:day {:cost {:total {} :data {}}}}} {:cons_data {:day {:volume {:total {} :data {}}}}}]. In this case, I'd expect the :cost {} and :volume nodes to be merged in to a single list. However, what happens is that the second map's :volume becomes a member but :cost node doesn't appear at all in the merged map.

6:01 *single list = I mean into the merged map

6:05 Hm, it seems that merge with is what I'm after.

6:06 *merge-with

6:10 Chousuke: triyo: if you need recursive mergeing then you can write a function that uses merge-with to merge the map using itself as the merge function :P

6:11 triyo: hehe, talking about eating your own dog food

6:11 :_)

6:11 Chousuke: Just don't forget the base case

6:12 triyo: Hehe, yip wont forget. thx

6:13 There is something I remember in contrib right the does deeper merge?

6:14 yip, deep-merge-with

6:15 raek: triyo: if the structure is small enough, it might be easy to just use destructuring: (let [[{{{cost :cost} :day} :cons_data} {{{volume :volume} :day} :cons_data}] m] {:cons_data {:day {:cost cost, :volume volume}}})

6:16 where m is your pair of maps

6:18 triyo: Its not necessary a pair of maps. Its nondetermanistic

6:21 raek: are there any other keys at the same level of :cons_data and :day?

6:26 triyo: yip, there will be other timespans: week, month, etc.

6:27 deep-merge-with seems to work as it does recursive merge.... Only thing I'm thinking about is what should by function look like...

6:32 No clashing occurs on my end except for the start_date and end_date that are under :day. However those date are the same in the maps so something simple as (fn [l r] l) will do

8:08 TimMc: Raynes: No plans, just following the examples in the blog post.

9:38 xian: Hi. I'm using some Java code in a Clojure/leiningen project. The Java code requires an external jar which is (of course) not on the leiningen classpath. Since it is not obvious how to alter the classpath of a leiningen project I am looking for another way to make my Java code accessible from Clojure (putting the jar in my_project/resources didn't help).

9:43 Basically, I'm looking for a way to add a local jar as dependency for the leiningen project.

9:44 raek: xian: first, have you checked if this "external jar" is in the maven repo?

9:44 (seach engine: http://jarvana.com/)

9:45 in case the java code is your own and small, you might want to include it in your clojure project (leiningen can build java code too)

9:47 the last resort is to put the jar file in the lib/ directory and add :disable-deps-clean false to the project.clj file. there is usually a better way than this to solve the problem, though

9:49 if the java code is it's own project, you should really make an artifact for it so that you can use it the usual way (add it as a dependency)

10:11 xian: raek: My dependency is the tools.jar from the JDK distribution (which I need for some JDI interaction).

10:17 So it's not in the maven repo.

10:18 TimMc: xian: You can add it as an extra classpath element in your project.clj.

10:19 raek: looks like that .jar is usually declared with a special systemPath option in maven (which I don't think Leiningen supports)

10:20 TimMc: xian: https://github.com/technomancy/leiningen/blob/1.x/sample.project.clj

10:21 :extra-classpath-dirs

10:21 raek: so in this case maybe :extra-classpath-dirs ["path/to/tools.jar"] is the best you can do

10:22 this path depends on which OS you have, so this will be messy when/if you try to work on this project on another computer

10:22 TimMc: clojurebot: sample project |is| https://github.com/technomancy/leiningen/blob/1.x/sample.project.clj

10:22 clojurebot: You don't have to tell me twice.

10:34 lemoq: hi folksk

10:35 got a question: how do i add the content of a seq to an exception? something like (throw (Exception. "elements in seq: " theseq)), where it lists all elements in theseq??

10:35 lazybot: lemoq: What are you, crazy? Of course not!

10:38 joegallo: ,(doc prn-str)

10:38 clojurebot: "([& xs]); prn to a string, returning it"

10:38 erujolc: is there an issue with documentation being out of date: http://clojure.org/vars (a tutorial that is probably high traffic for beginners) that wont work with clojure 1.3 due to not being declare dynamic

10:38 joegallo: so, for instance, you might do something like (appy prn-str the-seq)

10:40 erujolc: specifically the part about (binding [x 2 y3] (+ x y))?

10:40 s/y3/y 3/

10:42 Raynes: &(str "Exception and stuff: " (prn-str [1 2 3]))

10:42 lazybot: ⇒ "Exception and stuff: [1 2 3]\n"

10:43 Raynes: &(str "Exception and stuff: " (apply prn-str [1 2 3]))

10:43 lazybot: ⇒ "Exception and stuff: 1 2 3\n"

10:43 erujolc: joegallo, i mean that the example wont work

10:43 you need to declare the vars with (def ^:dynamic x 1)

10:43 Raynes: lemoq: Pick your poison.

10:43 erujolc: for example

10:44 lemoq: Raynes, joegallo, thanks, prn-str perfectly does the job

10:46 joegallo: erujolc: right, that's what i was asking -- was that the problematic part of the example?

10:46 and your answer is yes

10:47 erujolc: but theres more...http://ideone.com/EAthN

10:48 future is in another thread so I expected the out to be 42nill not 44nil

10:50 xian: raek, TimMc: Thanks, that works nicely. I don't worry too much about different OSes..

10:51 ckirkendall`: erujolc: the future was created under a given binding thus inheriting its thread locals for those bindings.

10:52 erujolc: Its my understanding the bindings apply to all child threads created inside the binding.

10:57 erujolc: ckirkendall`, that would make sense but cant see this documented anywhere

10:57 ckirkendall`: erujolc: I am trying to validate but I believe bindings use InheritableThreadLocal

11:16 eurjolc: It doesn't using the built in InheritableThreadLocal but it does seem to implement a custom form of inheritance by passing a copy of the parent bindings into binding frame.

11:19 erujolc: thanks for the clarification, it does seem to make sense when I think about it a bit longer

11:24 Raynes: I feel so powerful to be able to release marginalia to clojars.

11:24 michael_campbell: Good deal with Manning's "deal of the day" today.

11:25 cemerick: Raynes: when did that happen?

11:26 squeaky wheel effect? ;-)

11:26 Raynes: cemerick: Fogus and I had a night of passion at the conj.

11:26 * devn throws up

11:26 Raynes: Or, he just got tired of me whining at him to release new snapshots.

11:26 cemerick: Between him and the no starch guys, you really get around!

11:26 michael_campbell: man, I'm not sure if I'm happy or sad that I just ate, and read that

11:27 Raynes: cemerick: It took me 30 minutes to tone that tweet down enough to make it even remotely acceptable.

11:27 You should have seen the first draft.

11:27 cemerick: Raynes: so, we'll have indexes in marg output soon?

11:27 Raynes: Indexes?

11:29 cemerick: Indexes like outlines? Like on http://jedahu.github.com/story/

11:29 cemerick: yeah; indexes, outlines, whatever

11:30 Raynes: I hope so. I made an issue about it and story, but no responses so far. I'm not sure where one would fit in marg output. If fogus is really attached to the docco format, I bet we're screwed.

11:31 Story is pretty great though. I think it is an excellent compromise between the marginalia-style literate programming and the API-docish stuff that autodoc brings to the table.

11:31 cemerick: That's closer to what I really want.

11:31 esp. an index that is fixed to the top, just like the ToC in story.

11:31 Raynes: Me too.

11:32 The one on the left?

11:32 cemerick: yeah

11:32 Raynes: Yeah, that's pretty awesome.

11:32 It's the index on the right that I like the most.

11:33 It isn't intrusive but is very useful if you need to scan through the API.

11:33 cemerick: make the index a selection panel for larger projects, and it's money

11:33 Raynes: I'm just not sure it could ever work with the side-by-side layout.

11:34 cemerick: how do you mean?

11:34 Raynes: http://raynes.github.com/ororo/ given the side-by-side layout, where would such an outline fit?

11:34 cemerick: oh

11:35 I'm not attached to that. :-P

11:35 Raynes: Nor am I.

11:35 cemerick: I'll probably just start using story.

11:35 Raynes: Yeah, I'm not really seeing anything wrong with story at this point.

11:35 cemerick: I'd tinkered with marginalia, but it wasn't useful enough for stuff I wrote.

11:36 Raynes: I mean, it doesn't rip docstrings, but in what universe would that be useful for a non-side-by-side layout?

11:36 cemerick: i.e. reference material

11:36 Raynes: cemerick: I'll write a Leiningen plugin for it in a little while.

11:40 cemerick: Raynes: Perhaps the outline could go under the TOC?

11:40 Raynes: cemerick: What really got me thinking was when I did that tentacles blog post and Laurent Petit was completely baffled as to why I had marginalia docs and no autodoc. He pointed out that it wasn't very useful for looking at the API.

11:41 cemerick: That would be excellent, I think.

11:41 cemerick: It's certainly seems opinionated towards the literate programming thing, which I confess I've not really grokked.

11:41 Raynes: The the side-by-side will work fine.

11:41 Raynes: I've been doing a form of half-assed literate programming that I really like.

11:41 See my irclj docs for an example.

11:42 http://flatland.org/irclj

11:42 cemerick: half-assed is the path to salvation.

11:42 Raynes: I don't think I could ever buy into full-assed literate programming.

11:44 cemerick: ah, "accordion" is what I was trying to think of… http://jqueryui.com/demos/accordion/

11:44 s/selection panels/accordion

11:44 Raynes: Foldable!

11:44 That would be great and would fit in marginalia fine, wouldn't it?

11:45 Only see what you want to see.

11:45 I love you so much, Chas.

11:45 cemerick: There are tradeoffs.

11:45 chad_: Raynes: your comment on full-assed literate programming reminds me of the strange southern french colloquillism "Avoir le cul bordé de nouilles"

11:45 cemerick: for smaller libs, seeing everything is far preferable and superior

11:46 For libs that have larger namespaces, you need something like an accordion with a scrollable list of vars.

11:46 Raynes: It seems like a nice compromise.

11:46 cemerick: …or other namespaces just roll below the frame.

11:47 Both story and marg are javascript-heavy, so a decision could easily be made at load-time as to which is most appropriate.

11:47 Raynes: Okay, let me know when you've finished implementing all of that.

11:47 cemerick: What, I'm not ordering off a menu or something? :-P

11:47 Raynes: ;p

11:52 cemerick: Hah. Story is one big ol' story.clj file.

11:53 pdk: story.clj has a story all its own to tell

11:53 cemerick: 700 lines isn't *too* bad

11:54 pdk: yeah that's about the length of your average java hello world

11:54 cemerick: mmm, test-free yumminess

11:54 Raynes: cemerick: To be fair, marginalia's tests weren't passing the last I checked.

11:54 cemerick: it's a bummer that both have markdown bolted in

11:55 Raynes: Surely it wouldn't be difficult to have pluggable parsing backends?

11:55 "Dear Marg: Piss off, I like asciidoc."

11:56 cemerick: no, probably not

11:56 "Quick and dirty dsl for inline css rules, similar to hiccup." Run away, run away! :-P

11:57 Raynes: Heh

11:57 I'm a fan of hiccup, but not sure how I feel about inline CSS.

11:58 cemerick: it's wanting for some enlive and gaka.

11:59 Raynes: Gaka still depends on 1.2.0-master-SNAPSHOT.

11:59 cemerick: This is unfortunately true.

12:14 mccraig: cemerick: dyu know what's happening with clojure.core.strint (it's in the core.incubator git repo, but not in the core.incubator 0.1.0 jar on mvnrepository) ?

12:14 cemerick: it's in 0.1.1-SNAPSHOT

12:15 I think abedra is the lead on incubator, so it's up to him to push a release. You can mail the list about it if you like.

12:16 mccraig: thx

12:40 TimMc: Should I bring up the results of ##(list? (list* 1 ())) on the ML?

12:40 lazybot: ⇒ false

12:41 technomancy: list? is the worst function in clojure.core, hands down

12:42 zakwilson: I have never had any desire to call list? that I can recall.

12:42 TimMc: technomancy: The whole confusion between lists and seqs bothers me.

12:43 technomancy: lists and seqs is one thing; distinguishing between list and cons is dumb

12:43 hiredman: cons in clojure is for seqs

12:44 technomancy: if you care whether something is counted, there's a function for that called counted?

12:44 TimMc: Well, I like to think there is an abstraction barrier there.

12:45 seqs are a type of coll, `seq` takes you from any coll to a seq, `into` and company take you to various colls.

12:45 But list* returns a seq, not a list.

12:46 technomancy: The use case was someone writing a DSL or whatever the other day. They wanted to distinguish between [] and ().

12:46 technomancy: TimMc: yeah, that's where I learned to avoid list? too, inside a macro

12:47 TimMc: &(map list? ['foo (quote foo)])

12:47 lazybot: ⇒ (false false)

12:48 TimMc: Hrm, what was the example?

12:49 Chousuke: TimMc: code doesn't actually have to be a list so the more robust way is to check for the vector and assume it's a list otherwise :P

12:50 technomancy: could be a map

12:50 Chousuke: or check for seq? or something I guess

12:51 technomancy: anyway, fixing it is a breaking change since the docs state "Returns true if x implements IPersistentList", so IMO it should just be deprecated

12:51 if you really want it, you can type out the whole (instance? clojure.lang.IPersistentList x) call; it's only one more token

12:57 so goooood: http://www.qwantz.com/index.php?comic=2096

12:59 zakwilson: Is there a test for whether something is a lazy seq or a non-lazy collection?

13:01 Raynes: cemerick: Do you actually plan to do anything about the marginalia stuff we were talking about earlier? Just asking because, if not, I'm going to post the logs on my existing issue as food for thought for people who might actually do something at some point (we're probably both too lazy).

13:03 Plus, if I did it... well, we all remember what Try Clojure looked like before LauJensen and apgwoz.

13:04 cemerick: Raynes: It's in my todo. But, if I could predict when stuff from there would get done, civilization might collapse.

13:05 Raynes: cemerick: Well, it's on there. That's all that matters.

13:08 scgilardi: Chousuke: seq? has worked well so far for me as a test for "form" in macro expansions: clojure code rendered in text as "(operator operand1, operand2, ...)" appears always to be lists or conses in the code-as-data seen by macros.

13:09 drewr: is `lein run` not supposed to work with lein 1.6.2?

13:09 I keep getting an exception regarding PersistentList <-> String

13:09 technomancy: =(

13:10 Raynes: cemerick: I've got world domination and porn stardom on my TODO list. I'd love to see yours.

13:10 technomancy: drewr: it worked with 1.6.1?

13:10 cemerick: Raynes: stop stealing my TODOs

13:10 drewr: technomancy: no. I updated my 1.x branch because of it too, which is why I'm at 1.6.2

13:10 Raynes: Oh man, I'm so sorry.

13:11 technomancy: drewr: paste the invocation and/or relevant bits of project.clj?

13:11 cemerick: zakwilson: (instance? clojure.lang.LazySeq x)

13:12 TimMc: zakwilson: counted? may be more appropriate.

13:12 drewr: technomancy: is it supposed to be (defproject... :main 'foo.bar)?

13:12 maybe I'm missing some syntax in there

13:12 technomancy: drewr: no need to quote

13:13 drewr: that's a common mistake though; maybe open an issue about getting a better error message?

13:13 gtrak`: why is there no advantage to lists being able to be transient?

13:14 drewr: technomancy: or just silently accept a symbol

13:14 hiredman: technomancy: or check for a seq that starts with quote

13:14 bartj: folks, is anyone aware of scraping libraries in Clojure ?

13:15 technomancy: if it were just that place, I'd totally pull a postel's, but I need it to be consistent with every other place namespaces are accepted as symbols.

13:15 drewr: pedantry will get you nowhere technomancy

13:17 Raynes: technomancy: Is your init.el file up anywhere?

13:18 technomancy: Raynes: sure: https://github.com/technomancy/dotfiles

13:18 Raynes: technomancy: I keep wanting to show everyone my ERC configuration now.

13:19 technomancy: my own init.el is comprised only of things that aren't generally useful though; I outsource as much of that stuff as I can to the starter kit

13:19 Raynes: technomancy: https://gist.github.com/1434060 I wrote most of that code all by myself. :>

13:19 drewr: technomancy: https://github.com/technomancy/leiningen/issues/347

13:19 * Raynes is proud.

13:20 technomancy: Raynes: setq accepts an arbitrary number of symbol/value pairs; you can collapse them into a single call. also read up on eval-after-load.

13:20 drewr: cool; that'll help me remember it for 1.6.3

13:22 drewr: ack

13:32 cemerick: TimMc: ##(counted? (range 5))

13:32 lazybot: ⇒ false

13:39 rickmode: When calling a java method which takes a Integer parameter, I'm having to construct an Integer. Evidently the int primitive returned by the int function is boxed by a Long. Am I missing something?

13:41 nickmbailey: yes that changed in 1.3

13:41 ints are boxed to longs automatically

13:41 you have to use Integer for interop

13:43 http://dev.clojure.org/display/doc/Documentation+for+1.3+Numerics

13:44 boxing shouldn't occur during the interop call though so something like (.javaMethod Object (int 43)) should work

13:44 TimMc: cemerick: What about it? range is a lazy (chunked) seq.

13:46 rickmode: nickmbailey: thanks

13:48 well.. the method signature is an Integer, so it has to box somehow. The error when I call with (Foo/bar (int 1)) is java.lang.Long cannot be case to java.lang.Integer. Calling with (Foo/bar (Integer. 1)) works

13:48 Signature is something like "public static void bar(Integer i)"

13:49 obviously this was built before auto-boxing :(

13:49 pjstadig: (int 1) will create a Long in a boxing context

13:50 you have to use (Integer. 1) to get a Integer

13:50 (int 1) is a primitive int cast, which will cause Clojure to box according to it's own boxing rules

13:51 TimMc: rickmode: Probably wants to allow null.

13:51 technomancy: So... how would *you* define "list"?

13:52 (the Clojure concept, not the fn)

13:53 technomancy: TimMc: #(.startsWith (pr-str %) "(")) obviously

13:53 TimMc: >_<

13:53 technomancy: just kidding, that returns true for clojure.lang.PersistentQueue.

13:54 TimMc: I'd just add (or (instance? clojure.lang.Cons x) ...)

13:55 TimMc: technomancy: Would you say that the result of cons is also a seq?

13:56 Or that "seq" and "list" are usage patterns, not discoverable from isolated values?

13:57 nickmbailey: rickmode: that sounds like a bug to me. according to the doc: "It is possible to convert a boxed number into a JVM primitive using one of the following coercion functions: byte, char, int, long, float or double. Be aware, however, that unless the value is an immediate argument to a Java interop call or a Clojure function hinted to match, it is likely to be immediately auto-converted back to a boxed type."

13:57 technomancy: the result of cons is a list, so it must be a seq

13:58 nickmbailey: so either the doc is wrong or (Foo/bar (int 1)) should work

13:58 technomancy: lists are special because they are their own seq

13:58 hiredman: technomancy: no, the result of cons is a seq

13:58 it is not a list

13:59 technomancy: hiredman: it's not an instance of clojure.lang.PersistentList, but thinking in terms of classes is not helpful.

13:59 hiredman: cons is only for adding items to the front of seqs

14:04 TimMc: hiredman: In case you didn't see context: (list? (list* 1 ())) => false

14:04 technomancy: yeah, I understand that's how it works under the current implementation of the list? predicate; I just think it's a dumb predicate.

14:05 it's not a helpful distinction to make

14:05 TimMc: I think *something* is wrong here, but I'm not sure what!

14:05 I'd just like a consistent abstraction.

14:09 I'm fine with seq? and list? both returning true for the same object.

14:12 hiredman: technomancy: have you looked at the implementation of the cons function?

14:12 technomancy: you mean in RT.java?

14:13 hiredman: technomancy: sure

14:13 * technomancy looks

14:14 TimMc: Presumably you are highlighting the return type?

14:16 technomancy: ok, what I'm saying is that a list is a thing with a head and a tail; a linked list. a clojure.lang.PersistentList is something more specific.

14:16 hiredman: technomancy: it is defined as being "add this thing to head of a seq"

14:17 TimMc: technomancy: seqs and lists *do* have basically the same API, don't they.

14:17 technomancy: if you want to talk about whether something is a clojure.lang.PersistentList, you should be specific. if someone just says "I have a list", it's reasonable to think they aren't specifically talking about a clojure.lang.PersistentList but a linked list.

14:18 pjstadig: i've always found this part of clojure muddied IMO

14:21 TimMc: It definitely increases the cognitive load.

14:21 hiredman: technomancy: coll? only deals ipcolls and I believe the rest of the predicates are restrictied similarly

14:22 should list? return true for array lists?

14:22 TimMc: Should lists and seqs even be different things?

14:24 technomancy: I'm not convinced there should be a list? predicate, but the only two times I've heard of people wanting it, it was to determine if its argument was a piece of code in parens.

14:25 dnolen: technomancy: there are only a few data structure that guarantee that the rest will be identical? across operations

14:25 cons and list

14:25 this is useful

14:25 an seq doesn't make any such promise because the seq may come from a data structure that doesn't support it.

14:26 Chousuke: seqs cache the generated values though

14:26 dnolen: Chousuke: that not the property I'm talking about

14:26 identical?, not =

14:27 Chousuke: well, I'm not sure why the rest portion couldn't be identical

14:27 dnolen: Chousuke: it could of course.

14:27 TimMc: &(let [x [1 2 3]] (identical? (rest x) (rest x)))

14:27 lazybot: ⇒ false

14:27 technomancy: not sure how that's useful; IMO the only time identical? is called for is in explanatory texts =)

14:27 TimMc: happens to not be

14:27 dnolen: technomancy: just because you haven't used it doesn't mean it's not. core.logic benefits from the guarantee.

14:27 Chousuke: TimMc: that example is wrong

14:28 TimMc: you're calling rest on two different seqs

14:28 technomancy: isn't the whole point of egal to not have to think in terms of identical?

14:28 Chousuke: on the same vector.

14:28 amalloy: &(let [x [1 2 3], s (seq x)] (identical? (rest s) (rest s)))

14:28 lazybot: ⇒ false

14:28 dnolen: technomancy: performance, you don't want to traverse to determine equality - you know what you're doing.

14:28 TimMc: Chousuke: Oops, you're right. The point dnolen was making was more subtle than I thought.

14:29 technomancy: dnolen: ok, but I'd argue if you care about that level of perf you're well into breaking-through-abstractions territory and you're probably also concerned about the difference between array-map and hash-map, etc.

14:29 Chousuke: &(let [x [1 2 3], s (seq x)] (identical? (next s) (next s)))

14:29 lazybot: ⇒ false

14:29 technomancy: you can write your own predicates

14:31 dnolen: technomancy: there's seems to be a bit functional literature out there that leverages the identical? guarantee offered by cons / list.

14:31 so it's worth preserving in Clojure IMO.

14:40 technomancy: yeah, definitely makes sense to preserve that guarantee. not sure how that plays into what defines a list though.

14:41 hiredman: (defn cons [x y] (reify clojure.lang.ISeq (first [_] x) (next [_] y)))

15:20 patchwork: hey all, where did dissoc-in go in 1.3?

15:20 can't find any docs on it

15:20 they all say it is in clojure.contrib.core

15:21 even better, how could I discover this? Is there a handy migration list for 1.3?

15:23 cemerick: patchwork: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

15:31 TimMc: patchwork: I think dissoc-in was removed in favor of using update-in with dissoc.

15:32 patchwork: TimMc: that is what I needed to know, thank you!

16:00 flazz: i'm using clojure.tools.logger and my messages all contain sun.reflect.NativeMethodAccessorImpl as the namespace, how do i change this?

16:14 TimMc: flazz: The answer probably depends on which logger you are using.

16:14 flazz: jul

16:21 TimMc: ?

16:21 Is that j.u.logging or something?

16:23 amalloy: seventh month of the year

16:32 hm. this makes sense but kinda makes me sad: if your function foo returns a function f as (comp g h), and f is later called and blows up, foo doesn't show up in the stacktrace at all. does anyone have advice for figuring this out? in this case i knew foo was the culprit but if i didn't i'm not sure how i would track down which instance of comp was causing the problem

16:34 hiredman: amalloy: I dunno how you could change that in an acceptable way

16:35 the functions a generated at compile time and their class names reflect lexical scope, but you want the stacktrace to reflect dynamic scope, which is not known and compile time

16:36 maybe if comp was inline-able, but that is not a general solution

16:37 amalloy: yeah, i don't really see a viable solution either

16:38 you couldn't get it into the java stacktraces, but maybe you could put metadata on the returned function somehow, to get some crude diagnostics? even that seems pretty challenging

16:39 hiredman: the best solution to errors is always: know what you are doing and don't make errors

16:41 technomancy: I find that internally-named fns are pretty handy for debugging

16:41 (fn does-a-thing [x] [...])

16:41 flazz: TimMc: yep java.utls.logging, sorry

16:43 hiredman: technomancy: but if you create the fn with comp you don't have that

16:43 technomancy: hiredman: yeah, I don't think there's a good point-free answer for that

16:45 TimMc: flazz: If that's anything like log4j, you'll put some sort of properties file into the classpath with the configuration details you need.

16:45 amalloy: Solution: Make comp a macro. :-P

16:46 (scratch that, it doesn't make enough sense to be funny)

16:46 amalloy: right, i wound up changing it to #(g (h %)) so that i could confirm it was inside foo

16:47 TimMc: amalloy: The generated classname includes foo?

16:47 amalloy: of course. foo$fn__2349 or something

16:48 &((fn foo [] #(inc 1)))

16:48 lazybot: ⇒ #<sandbox12996$eval16802$foo__16803$fn__16804 sandbox12996$eval16802$foo__16803$fn__16804@e3313a>

16:54 TimMc: That is suprisingly useful and obvious.

16:56 technomancy: weavejester: heya

16:57 weavejester: technomancy: Hey there

16:58 technomancy: how goes the hacking on ragtime?

16:58 did that ordering trick work out?

16:58 weavejester: Perfect :)

16:58 technomancy: sweet

16:59 weavejester: I also changed the functions from 0-arg to 1-arg.

16:59 technomancy: thinking of trying out on clojars

16:59 weavejester: With the one argument being the database.

16:59 jcromartie: good call

17:00 weavejester: So (migrate db [foo]) will run ((:up foo) db)

17:00 technomancy: looks like it still needs an adapter for sql; maybe that could just be yoinked from migratus?

17:00 weavejester: Yeah, I'm working on a ragtime.sql. I haven't got very far though, so grabbing one from migratus is probably a good idea.

17:01 technomancy: curious: are you using this for work?

17:01 weavejester: I was also looking into maybe grabbing the one from Lobos, as I'm using that librart anyway.

17:01 technomancy: https://github.com/weavejester/ragtime/graphs/punch_card <= guessing not =)

17:01 weavejester: No, currently work is a Ruby shop

17:01 No Clojure there yet.

17:01 technomancy: bummer

17:02 weavejester: Yeah, but on the other hand, it gives me a window into what's happening in Rails webdev

17:02 My current plan is to make the database connection map a record

17:03 So then I can add the "Migratable" protocol to it that allows me to store migrations.

17:03 I'm not 100% sure about it, but it's the best solution I've come up with so far...

17:03 technomancy: hmm... I just refactored c.j.jdbc so that you can pass a database URL string instead of the connection map

17:04 I guess you could extend it to string and URL and parse it there

17:04 weavejester: technomancy: I was thinking about writing a library for that :)

17:04 technomancy: that's your catch-phrase, innit?

17:04 weavejester: Haha! I'm a fan of many small libraries

17:05 Apparently the empirical evidence suggests bugs are closely related to the number of lines of code.

17:05 So less code = less bugs on average

17:05 technomancy: yeah, as long as the abstractions are rock-solid

17:05 weavejester: Yeah.

17:05 technomancy: because the other side of the coin is that more libraries means more integration points

17:06 but in general I agree

17:06 weavejester: So I need the "Migratable" protocol so that I can store migrations without mandating a specific type of database.

17:06 I mean, that makes sense, right?

17:06 technomancy: yeah, I think so.

17:07 weavejester: So (migrate db migration-list)

17:07 technomancy: it would be nice if you could pass the exact same config to ragtime and c.j.jdbc, but that might just be unrealistic

17:07 weavejester: Or (migrate-ns db & namespaces)

17:07 technomancy: nice

17:07 weavejester: Originally I was going to have it execute migrations like ((:up migration))

17:07 But now I've changed it to ((:up migration) db)

17:08 Because it seems like a good idea to pass the database connection info through the migrate function

17:08 Essentially saying "migrate this database with these migrations"

17:09 I guess I could just use a wrapper.

17:09 technomancy: I think taking an arg makes sense

17:09 weavejester: (migrate #SqlDatabase{:url "..."} ...)

17:09 technomancy: but we'll probably have to flesh out a few adapters to really get a feel for what works

17:09 weavejester: Yeah

17:10 Or maybe: (migrate-ns (sql-database db-url) 'my.app.migrations)

17:12 One of these days I'll run out of libraries to build, and then I'll actually be able to make an application

17:13 technomancy: do you want a hand with the sql adapter?

17:14 weavejester: technomancy: Sure

17:14 I rarely turn away a helping hand :)

17:15 technomancy: check your /msgs

18:08 accel: is there a godo book / chapter of a book / tutorial on Swing + Clojure?

18:09 What is a godo book / chapter of a book / tutorial on Swing + Clojure? (I don't want a yes/no answer, I want a reference :-) ).

18:20 Raynes: Tutorials on swing + Clojure are fairly lacking, though I'll be covering it in my book. That doesn't help you much now.

18:23 Wild_Cat: Raynes: when is said book supposed to come out?

18:23 Raynes: I wish I knew.

18:23 Wild_Cat: (also, I get the feeling that it'd be pretty interesting to model the UI as an agent)

18:24 Raynes: I'll be covering Seesaw in the book.

18:24 http://github.com/daveray/seesaw

18:28 gtrak`: Wild_Cat, why agent over atom?

18:28 or ref, I guess

18:28 Wild_Cat: gtrak`: because I'm envisioning every event as a message it could/should send to other agents (the actual program logic)

18:29 also, because I'm a Clojure noob and it's likely my understanding of its concurrency and synchronization primitives is sketchy.

18:30 gtrak`: hmm, well the downside of an agent is when you actually want stuff to happen synchronously

18:30 I guess if the queue is small, it's no big deal

18:31 Wild_Cat: yeah, there's the potential issue of the UI lagging way behind the user's commands

18:31 which tends to happen when you accept too many of those, usually as a side effect of event handlers returning immediately

18:32 gtrak`: there's really no downside of a single rendering thread, is there?

18:33 but I know that in swing it's easy to do the wrong thing, maybe seesaw makes that better?

18:34 Wild_Cat: as long as rendering is fast or easy to break down in steps that are and return quickly, no downside. The problems start creeping in when rendering is neither fast nor broken down in small steps.

18:34 gtrak`: Wild_Cat, I've done programming in adobe flex, you only have a single thread there, and event queues, it's pretty flexible though unless you have long-running work and need to interleave it between frame-renderings

18:34 Wild_Cat: at which point your UI hangs while your logic is processed, a very common issue in Swing programs

18:34 amalloy: swing tells you not to interact with gui elements in anything but the event dispatch thread

18:34 Wild_Cat: gtrak`: yeah, it's pretty much exactly that problem ;)

18:34 (to be fair, you get it in most UI toolkits)

18:36 gtrak`: the data-binding was super-nice though, basically any time a property changes, an event bubbles up and updates everything that it needs to update

18:36 Wild_Cat: ah, nice.

18:36 gtrak`: like this: <mx:Binding source="source.text" destination="destination.text" />

18:36 or <mx:TextInput id="destination" text="{source.text}" />

18:37 Wild_Cat: that's another thing Swing sorely lacks: a declarative UI representation format.

18:38 ...or anything that makes working with a WYSIWYG UI designer something other than a massive kludge that autogenerates megabytes of horrible Java code

19:16 accel: Raynes: perhaps I am asking the wrong question.

19:16 What are the currently well used methods for doing GUI in Clojure?

19:17 To me, the important bits are: I need to code in Clojure. I need to have a GUI.

19:17 Swing is replacable.

19:18 Also, did anyone ever port the GUI that common lisp systems had to clojure?

19:18 cemerick: Swing and SWT are the only games in town, really.

19:19 plus using an embedded webkit view via SWT and using a web UI on the desktop :-P

19:19 There was a tasty Clojure swing wrapper that just came out that looked very promising…

19:20 accel: IIRC, common lisp had a very interesting GUI toolkit: clim, I thin it was called.

19:20 Is there no port of it to clojure?

19:22 cemerick: Surely not.

19:22 TimMc: cemerick: Yeah, the next time I can get away with it, I'm writing a web GUI.

19:22 accel: TimMc: why?

19:22 cemerick: If clim is your benchmark, then the framework doesn't matter that much, it's the construction of the API you care about.

19:22 accel: Why is Web GUI easier than Java GUI?

19:23 cemerick: Declarative layout is nifty.

19:23 accel: cemerick: sure; I care more about the API than "framework"

19:23 TimMc: accel: It's not that it's easier (although it often is), it's that you can meet more of the user's interface expectations.

19:24 Cross-platform GUIs are often awkward for the user.

19:24 They look wrong and feel wrong on *every* platform.

19:24 accel: lol

19:24 I believe this is called *fairness*

19:24 TimMc: haha

19:24 Something declarative that got compiled to each platform's widgets would *rock*.

19:25 duck1123: but they look wrong in different ways depending on the OS

19:25 TimMc: you mean, HTML?

19:25 cemerick: accel: try https://github.com/stathissideris/clarity or https://github.com/daveray/seesaw

19:26 accel: ce

19:26 cemerick: going to try clarity just because I like the name better

19:27 TimMc: duck1123: Just about.

19:27 zerokarmaleft: technomancy: does emacs-starter-kit override settings in init.el for cc-mode somewhere?

19:27 TimMc: It could totally be done.

19:27 accel: what if, we took HTML

19:27 then we made it scriptable

19:27 with a scripting language

19:27 TimMc: heh

19:27 technomancy: zerokarmaleft: version 1 or 2?

19:27 accel: the scripting langauge would be cross platform, like Java

19:27 duck1123: hold the phone

19:28 accel: but it would be for Scripting purposes

19:28 zerokarmaleft: technomancy: 2

19:28 technomancy: zerokarmaleft: 2 doesn't add any bindings outside the starter-kit-bindings module, but I don't know if it overrides anything in cc-mode because I've never used it.

19:29 accel: Sadly, I think the approach I want to take

19:29 is to suffer and deal with Swing directly so I can build my own abstractions.

19:29 What is the most hardcore way to learn Swing?

19:30 duck1123: accel: flagelate yourself for every bug

19:30 accel: No no, I don't want a Darwin award.

19:30 I'm looking for the K&R equivalent, i.e.

19:30 "The Swing GUI Library"

19:30 [2nd edition]

19:32 zerokarmaleft: technomancy: ok...i hadn't installed bindings yet anyway

19:35 maybe cc-mode has changed in 24, i'll check that

19:53 seancorfield: boy, i've had one of those days where i just love clojure!

19:54 we have a custom search engine that returns a block of results with metadata on each call and now, thru clojure, i have a single search call that returns three lazy sequences that call the search engine as needed to get results as we page thru results!

19:58 Raynes: seancorfield: I'm going to be doing something similar for paging in tentacles.

20:06 yayitswei: how would I group items in a list based on a cumulative function? e.g. split when sum is greater than 10: (9 1 2 5 1 8) -> ((9 1) (2 5 1) (8))

20:09 duck1123: yayitswei: IIRC there's a reductions fn in combinatorics that returns each stage of a reduction, that might get you started

20:11 yayitswei: ah quite useful, ty

20:12 duck1123: not quite sure how you'll make it work, but it should help

20:13 brehaut: ,#((map vector % (reductions + 0 %)) [1 2 5 3 4])

20:13 clojurebot: #<sandbox$eval28$fn__29 sandbox$eval28$fn__29@25dd02>

20:13 brehaut: crap

20:13 ,(#(map vector % (reductions + 0 %)) [1 2 5 3 4])

20:13 clojurebot: ([1 0] [2 1] [5 3] [3 8] [4 11])

20:14 brehaut: nah thats ugly

20:22 amalloy: this feels like something i wrote recently, but i can't remember what it actually was

20:24 yayitswei: here's what i have so far: (reductions #(if (<= (+ %1 %2) 10) (+ %1 %2) %2) '(9 1 2 5 1 8))

20:26 brehaut: oh. its not a foreclojure question is it?

20:27 Raynes: amalloy has returned?!?

20:27 yayitswei: nope, at least not afaik

20:28 amalloy: nah, i though wrote it as a response to something on the google group. but i can't find it

20:28 my basic premise was "it seems like you should be able to do this with reductions and split-with or something, but it was easier to just write with lazy-seq directly"

20:30 rickmode: I'm doing a remote debugging via swank-clojure, but when I tried (swank.core/break) I get IllegalStateException: Attempting to call unbound fn: #'swank.core.connection/*current-connection*

20:32 I did a C-c c on my (ns ..) line that added :require swank.core and on the fn that has (swank.core/break). And oddly, if I require swank.core.connection, I can see *current-connection* in my remote REPL.

20:33 drivera: .exit

20:35 amalloy: yayitswei: https://github.com/flatland/useful/blob/develop/src/useful/seq.clj#L191 is maybe a little relevant/useful?

20:40 yayitswei: thanks amalloy, i'm finishing up my split-with version and i'll take a look in a sec

20:44 amalloy: VICTORY. it was http://groups.google.com/group/clojure/browse_thread/thread/fc08587280d2244e/c266706ed52c8d2?q=#0c266706ed52c8d2 - someone wanted to group a bunch of strings such that each partition had a maximum size <= N

20:58 ihodes: anyone hiring Clojure devs about to graduate from school? :)

21:21 yayitswei: nice.. thanks amalloy

21:53 brweber2: how do I make my protocol extend Map?

21:54 brehaut: (doc extend-protocol)

21:55 clojurebot: "([p & specs]); Useful when you want to provide several implementations of the same protocol all at once. Takes a single protocol and the implementation of that protocol for one or more types. Expands into calls to extend-type: (extend-protocol Protocol AType (foo [x] ...) (bar [x y] ...) BType (foo [x] ...) (bar [x y] ...) AClass (foo [x] ...) (bar [x y] ...) nil (foo [x] ...) (bar [x y] ...)) expands into: (do (clojure.c

21:55 brehaut: ,(supers (class {}))

21:55 clojurebot: #{clojure.lang.IPersistentCollection clojure.lang.IPersistentMap clojure.lang.Counted clojure.lang.IMeta clojure.lang.AFn ...}

21:56 brehaut: brweber2: clojure.lang.IPersistentMap is the interface you want to implement the protocol for. you can either do it in the protocol definition, or with extend-protocol.

21:56 brweber2: brehaut: thanks

21:56 brehaut: brweber2: i am under the impression that if you define it in the protocol definition, then it will be a bit faster than if its done later

21:57 brweber2: brehaut: perfect. I forgot about supers for checking the hierarchy

22:05 amalloy: brehaut: you can't include any implementation in the definition of a protocol; you're probably thinking about inlining protocol implementations when defining a type, but your advice doesn't make sense in that context: you don't control the creation of the IPersistentMap class so there's nowhere to inline

22:05 brehaut: amalloy: aha yes of course i am

22:22 tmciver: Anyone using CDT from a repl? I tried following http://georgejahad.com/clojure/cdt.html but when I (use 'com.georgejahad.cdt) I get they FileNotFoundException.

22:33 seancorfield: tmciver: i think the namespaces have changed recently?

22:33 i got this working: http://georgejahad.com/clojure/swank-cdt.html

22:35 tmciver: seancorfield: I was just looking at that. I wanted to see if I could get *pure* CDT working w/o swank. I guess I'll just move on to swank-cdt.

22:42 jcrossley3: why was clojure.java.io/delete-file-recursively removed from 1.3?

22:49 erujolc: using the clojure 1.3 repl (clj) from a terminal emulator in linux it doesnt behave very natively e.g. if i type (def x 1) <Enter> and then on the next line the up arrow instead of showing last command shows the escape of up arrow

22:49 amalloy: $google rlwrap

22:49 lazybot: [rlwrap - utopia.knoware.nl] http://utopia.knoware.nl/~hlub/rlwrap/

22:49 amalloy: erujolc: ^

22:50 Raynes: Leiningen handles that for you.

22:50 amalloy: though really, don't use clj at all; install lein and it will make a repl with readline

22:50 Raynes: That.

22:51 https://github.com/technomancy/leiningen

22:51 erujolc: thanks

22:51 lein repl works perfectly

22:52 Raynes: 'clj' is not an official Clojure thing. It's just a script that your package manager probably installed to start up a REPL. You still have to deal with handling the classpath once you've began a project and start having dependencies. Leiningen does that too.

22:52 erujolc: thanks. yes i believe clj was installed via pacman (archlinux)

23:02 OT: techie podcasts worth subscribing to?

23:08 devn: What's the channel for chicken scheme?

23:15 Raynes: devn: Wild guess, but I'd assume it to be #bawwwwwwwwk.

Logging service provided by n01se.net