# #clojure log - Jul 19 2010

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

0:01 technomancy: slyrus: just use uniquify

0:01 hang on

0:02 slyrus: (require 'uniquify) (setq uniquify-buffer-name-style 'forward)

0:02 anyway, you symlink the whole directory into the checkouts dir

0:03 oh yeah; what he said

0:11 nathanmarz: , (binding [+ - - +] (+ 1 2 3))

0:11 clojurebot: -4

0:11 nathanmarz: oddly, i get "2" when i run it in my repl

0:14 IRCMaster: why does (class set!) throw an exception: Unable to resolve symbol: set! in this context

0:15 rhudson: it's a special form

0:16 IRCMaster: I was originally trying to (map !set ...) in order to set a bunch of instance fields at once

0:17 is there an easier way, than one at a time?

0:17 rhudson: You'll need to map #(set! %1 %2)

0:31 IRCMaster: hi, one more question.. what is the #(...) form called, as given a few lines back by rhudson? I'm trying to look up documentation but don't know what to search on

0:36 brehaut: IRCMaster: http://clojure.org/reader look at Dispatch, its a reader macro for an anonymous function literal

0:38 IRCMaster: excellent, thanks!

0:49 slyrus: how can I get things printed like slime does at the repl (i.e. with line breaks and nice indentation, instead of all one line)?

0:53 technomancy: slyrus: (use 'clojure.pprint) (pprint (range 99))

0:53 or clojure.contrib.pprint for older clojures

0:54 slyrus: oh, that's nice!

0:55 * slyrus now needs a 30-inch monitor, turned 90deg :)

0:56 technomancy: portrait orientation rules

0:57 * slyrus thinks the slime repl should use pprint by default

1:25 slyrus: if anyone wants to hack on a library for representing undirected graphs (and maybe digraphs soon), shortcut can be found here: http://github.com/slyrus/shortcut

1:43 replaca: slyrus: pprint is still not that fast, so sometimes one regrets it when one uses it at the repl :-)

1:44 but I should make some instructions for doing it - it's not too hard.

1:46 TakeV: (doc format)

1:46 clojurebot: "([fmt & args]); Formats a string using java.lang.String.format, see java.util.Formatter for format string syntax"

3:03 raek: whoa! checkout dependencies in the new Leingingen sounds awesome!

3:05 TimMc: What's this now?

3:06 raek: if one of you projects that you are working on depends on another that you work on too

3:06 you can now make the dependent project use the project directory of the other one directly

3:07 no need to build jar files, copy to the dependent project, lein deps, lein swank

3:07 the checkouts/ directory contains symlinks to the other projects

3:08 leiningen then adds the classpaths of all those projects into the current one

3:09 TimMc: Hmmm...

3:09 Reminds me of svn externals, which sounded like a great idea but turned out to be a load of trouble.

3:09 tomoj: that does sound nice

3:10 pain to have to startup a new swank server to fix a bug in some other project, then another new swank server to verify the fix works in the original project

3:11 TimMc: Specifically, when you have a couple version branches of project A that depend on different versions of project B, it's a mess.

3:17 slyrus: raek: yes, this was one of the big things that I was afraid I was going to miss from using CL/asdf

3:18 in fact I couldn't really see the point of leiningen without this sort of thing :)

3:18 Licenser_: I've a problem compiling some clojure code :( use works but not compile it says something like Runtime

3:19 Exception: ClassNotFoundExceptopn bla.bla.bla.core$loading__5166_auto____1253 3:19 has anyone encountered something like that? 3:26 slyrus: hmm... I'm not familiar with the proper clojure terminology, but it seems that protocols aren't "exported", i.e., I need to do (shortcut.graph.Graph. #{} {}) instead of (Graph. #{} {}) even though I'm using the ns and I can call non-fully-qualified functions. 3:38 Licenser_: problem solved, updateing to clojure 1.2b1 helped :) 3:55 tomoj: slyrus: they're not functions anymore 3:55 slyrus: tomoj: not sure what you mean 3:56 tomoj: used to be when you did defrecord/deftype Graph, you'd get a constructor function named Graph, but no longer 3:56 they're java classes so you have to import them like other java classes 3:57 slyrus: oh, I think I get it 3:57 hrm... I'll have to figure out how to do this cleanly in the morning then. 3:59 tomoj: (ns ... (:require [shortcut.graph :as graph]) (:import shortcut.graph.Graph)) 4:23 esj: happy monday y'all 4:23 raek: I think it's pretty common to make one's own constructor functions 4:23 that way, one can have default values for fields, etc 4:24 but I guess that all this depends on whether the use of records is an implementation detail of the lib or not 4:28 esj: raek: that's certainly how I've done it. 5:35 yason: Is the "core.clj" name just a leiningen convention or something dictated by Clojure? 5:35 mikem: yason: it's a leiningen thing afaik 5:37 yason: mikem: just a convention or can't be changed? 5:39 TimMc: I think leiningen just sets it up as a default. 5:39 mikem: yason: you can change it, i think it's just the default directory layout leining creates 5:39 TimMc: In your project.clj you can specify whatever main file you want. 5:39 s/file/class/? 5:39 sexpbot: TimMc: Format is sed [-<user name>] s/<regexp>/<replacement>/ Try$help sed

5:39 yason: ok, thanks for the information

7:33 bortreb: is there some way to change the print function the repl uses to my own generic version?

8:09 nm -- I found that I can just do (defmethod print-method <my-class> ..)

8:13 lpetit: ericthorsen: hi, you there ?

8:36 erichthorsen: nevermind, I've transformed what started like a man-to-man brainstorming into a (hopefully) community brainstorming in the ml

9:45 xcthulhu: I've been looking at ADTs in clojure and I have two questions: (1) Are ADTs still in proof of concept phase, or can they be used in production code? (2) The mathematically, there are two ways to define ADTs - inductively and coinductively. Coinductive ADTs are lazy data structures - do ADTs for clojure make this distinguish between whether they've been defined inductively or coinductively?

9:46 erm /distinguish/distinction/

9:47 opqdonut: algebraic data types

9:48 Licenser_: opqdonut: you mean native variables and litterals?

9:50 opqdonut: no

9:50 he means stuff like "data Tree = Node Tree Tree | Leaf"

9:51 like what clojure.contrib.types offers

9:52 xcthulhu: Licenser Algebraic Data Types

9:52 cemerick: Very rarely used. The deftype collision is unfortunate.

9:53 xcthulhu: cemerick, It's a the way of life in ML, Haskell, Isabelle/HOL, and Coq

9:53 less so in Coq I suppose

9:54 opqdonut: i guess he meant the clojure library is rarely used

9:54 Licenser_: oh okay then I've no clue, I'm sorry xcthulhu

9:55 xcthulhu: Licenser, NP it's a bit of a silly question.

9:58 Outside of the ivory tower you don't see people programming with ADTs all that often, so I don't think support for them should be a priority for clojure

10:00 Hodapp: and you do NOT want to get into an ivory tower war with a Lisp... you will most certainly lose.

10:00 xcthulhu: Hodapp, What do you mean?

10:01 cemerick: xcthulhu: yes, I only meant that c.c.types is rarely used

10:01 (at least in the various clojure libs I've seen, anyway)

10:02 People writing data structures in clojure should be using core's deftype. Anything defined otherwise is not going to have the performance one would typically expect in that domain.

10:03 Now, if someone were to macro on top of core's deftype with stuff to support ADT-like constructs, that could get interesting.

10:48 AWizzArd: rhickey: currently the Clojure compiler uses a comfortable naming scheme to produce its output files (.class). Will you gurantee that this naming scheme will survive also in future?

10:49 I ask because I use this for Ant jar tasks. I compile the whole utils/ folder, but only include those in the .jar that the end customer is supposed to get.

10:49 Currently I can easily work with * wildcards, and it's working nicely.

10:53 slyrus: ah, thanks tomoj. so I need to do that with records (and protocols)?

11:20 rhickey: AWizzArd: no guarantee there

11:29 cemerick: interesting that "clojure prepend vector" is the #1 suggested query when I type "clojure" into my FF search field

11:30 TeXnomancy: cemerick: I think those are personalized depending on your search history. For me "clojure API", "clojureclr", and "clojure cond" are the top suggestions.

11:31 cemerick: TeXnomancy: I scrolled past all my personalized (I think they're just history) queries to the "Suggested Queries" *shrug*

11:31 TeXnomancy: ah. interesting.

11:31 cemerick: seems glitchy, as that's above "clojure editor" "clojure web programming" and "clojure emacs" though.

11:33 Not a horrible question though -- I can't think of any easier way than (vec (concat [5] some-other-vector))

11:34 rhickey: yikes

11:35 cemerick: ut-oh ;-)

11:35 rhickey: (into avec another-vec), but the real answer is - "why do you feel you need to do that?"

11:35 cemerick: rhickey: is there some obvious core fn that I've been neglecting all this time

11:36 TeXnomancy: everyone neglects into

11:36 cemerick: rhickey: roughly the same as using vec, no?

11:38 I've had to prepend (or, in general, insert) into a vector before, though it's rare.

11:39 lpetit: TeXnomancy == technomancy ??

11:40 rhickey: people need to remain vigilant about not advising others as to how best use the wrong data structure. Yes, every now and then for a one off, but imagine if someone goes and puts that inside a loop...

11:40 cemerick: into much faster than vec + concat

11:41 TeXnomancy: lpetit: yeah, it's my fallback nick. better than techno~1...

11:41 rhickey: TeXnomancy: I thought you were an imposter

11:42 TeXnomancy: rhickey: in a way I am--in truth I am not any good at typesetting at all.

11:42 rhickey: heh

11:42 cemerick: rhickey: the latter ends up being necessary for those odd insert requirements.

11:42 lpetit: rhickey: he may be. It depends whether you've been convinced by his answer, or not !

11:43 rhickey: cemerick: just wait for chouser's finger trees

11:43 TeXnomancy: so concat is slower because it has to list-ize the whole thing, then go back and vectorize it, while into can use transients, I suppose.

11:43 lpetit: rhickey, cemerick: will chouser's finger trees be delivered before or after cinc and ClojureScript ? :-p

11:58 * lpetit discovers with horror that anytime he is in GWT debug mode for too long with FF, his FF chatzilla client is disconnected from #clojure and that he may have lost messages ...

11:59 * lpetit , by "in GWT debug mode", means "in suspended mode"

12:00 cemerick: lpetit: I think cinc will end up being a continuous effort. Each additional host will probably prompt incremental cinc-related changes, etc.

12:01 lpetit: cemerick: yep. the first one being probably the CLR, rather than javascript, I guess

12:02 cemerick: That's up to rhickey and the different implementors, but I suspect the work needed to simplify things for js is far less than for the CLR (simply because so many clojure features are out of scope for js).

12:05 AWizzArd: rhickey: a standard that defines the file names the compiler produces would be useful. And the current granularity is currently very nice.

12:10 lpetit: no reaction to my post on the ml concerning user assistance and IDEs: of interested to nobody (except me !) ? or should I leave more time for people to answer ?

12:16 cemerick: lpetit: I hadn't noticed the thread, but we're deep into the summer doldrums. Attention is down across the board. :-)

12:17 lpetit: cemerick: oh :)

12:30 cemerick: now that you've noticed the thread, I'm counting on you to feed it :-)

12:45 defn: Anyone read this book? http://tinyurl.com/2bhnc8p (Language Implementation Patterns: Create your own DSL and general programming languages)

12:53 bigwavejake: i'm new to clojure and incanter. i get an error when trying to evaluate the following: (ns myproj (:use [incanter core stats]))

12:53 I get: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol

12:54 what am i doing wrong?

12:55 Nikelandjelo: Try (:use [incanter.core.stats])

12:56 bigwavejake: Nikelandjelo: with no ns around it?

12:56 Nikelandjelo: bigwavejake: with ns, do you work in repl or write separate file?

12:57 bigwavejake: Could not locate incanter/core/stats__init.class or ...

12:57 repl

12:57 Nikelandjelo: Did you include incanter in classpath?

12:58 bigwavejake: yep. i added the incanter dep in the project.clj, lein deps, lein repl

12:59 maravillas: it's not incanter.core.stats - he's trying to use incanter.core as well as incanter.stats

12:59 bigwavejake: maravillas: right

13:00 maravillas: that said, i'm not sure what the issue is

13:02 zkim: bigwavejake: try lein clean && lein deps

13:03 bigwavejake: then lein repl

13:03 bigwavejake: whoops, i have to learn to read

13:04 bigwavejake: zkim: no go

13:04 zkim: same error: '...Don't know how to create ISeq from: ...'

13:05 Nikelandjelo: bigwavejake: Does (:use [incanter.core]) (to use only core) work?

13:13 zkim: wonder if that worked

13:14 whenever i get those iseq error messages due to a ns change it's usually a badly formatted use / require / import

13:15 bigwavejake: sorry... i had a phone call

13:15 Nikelandjelo: didn't work

13:15 same error

13:15 zkim: bigwavejake: try (use 'incanter.core)

13:15 bigwavejake: zkim: no good

13:16 zkim: bigwavejake: same error?

13:16 bigwavejake: java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.

13:16 lang.Symbol

13:16 zkim: hrm, maybe i've got the syntax wrong, hold on, got a project with incanter here somewhere

13:17 yeah, that's the right syntax

13:17 Nikelandjelo: biwavejake: what about (use 'clojure.contrib.seq-utils) ?

13:17 bigwavejake: Can you use any lib? :)

13:17 bigwavejake: Nikelandjelo: that worked

13:17 zkim: weird

13:17 bigwavejake: yeah!

13:18 super weird!

13:18 zkim: can you pastebin your project.clj?

13:18 bigwavejake: sure

13:20 zkim: one sec

13:20 bigwavejake: sure, take your time

13:23 zkim: got it, seems like a problem with clojure 1.1.0, try this project.clj: http://pastebin.com/BXVeHWWV

13:26 bigwavejake: forgot to mention, do a lein clean && lein deps too

13:26 bigwavejake: that's it

13:26 nice!

13:26 zkim: cool

13:26 bigwavejake: so, the rule to getting clojure projects working is to live on the bleeding edge?

13:27 zkim: haha

13:27 bigwavejake: anyways, thanks for all your help

13:27 zkim: donno, maybe there's something in the incanter notes about incompatability

13:27 yeah np

13:43 chouser: huh. 3rd printing of Programming Clojure. Not too shabby.

13:45 cemerick: I'm surprised that there's a notion of "printings" anymore at all, really. Figured the whole industry would be JIT, or damn close at this point.

13:46 chouser: I was notified by an email that suggests there may be changes to the content as well. Perhaps "printing" is more of a minor version number or something now.

13:48 cemerick: Semantic versioning of books is around the corner. Programming Clojure e1p3 just released. :-P

14:43 hugod: is it possible to annotate a deftype constructor?

14:51 slyrus: speaking of deftype... so can I use deftype to extend a clojure.lang.IPersistentVector instead of an IPersistentMap?

14:53 cemerick: slyrus: yes

14:53 slyrus: have an example of how to do so lying around?

14:54 cemerick: slyrus: look at gvec.clj in clojure itself

14:55 slyrus: thanks cemerick

14:57 aria_42: speaking of deftype/defrecord, can you serialize them such that you can eval them back into memory from disk?

14:58 cemerick: aria_42: defrecord is java.io.Serializable, so there's that. Neither deftype or defrecord have readable printed representations yet.

15:12 slyrus: I (think) I want a vector that supports a couple operations (that I'll define) and clojure.lang.IObj. If I use defrecord, the type will be a map. If I use deftype, I can make it a vector, but I lose the built-in IObj support, right?

15:14 cemerick: slyrus: You could just proxy PersistentVector.

15:15 See, what we need are some flavour of mixins!

15:15 chouser: or write functions that operate on a vector. what operations do you want to add?

15:15 * cemerick runs away before rhickey fires off some napalm ;-)

15:16 chouser: cemerick: we need, and I assume we will get, mixins that are currently provided by the various base clojure collection base classes.

15:18 cemerick: chouser: For deftype usage? I'm all for it. I remember some ill words on mixins here a while back though.

15:18 slyrus: chouser: not sure I need any, tbh. I current have some operations that are provided by my record, but maybe these can just go away and be replaced by sequence operations.

15:19 oh, no, I still want a couple "convenience" operations so that even though this is a sequence (vector), it can still implement my NodeSet protocol.

15:20 I'm thinking of replacing the Edge record in http://github.com/slyrus/shortcut/blob/master/src/shortcut/graph.clj with something built on top a 2-element vector.

15:20 chouser: slyrus: perhaps you could just extend your protocol to PersitentVector

15:21 cemerick: I'm sure everyone else did mixins wrong ;-), but extend with a merged map is essentially a sort of mixin, the sort that clojure collections will need to be implemented in clojure without duplicated code.

15:21 slyrus: chouser: hate to be dense, but I'm not exactly sure what you mean. Do you mean have my Edge record implement methods from IPersistentVector?

15:24 cemerick: chouser: See, I thought you were talking about impls being mixed into inline deftype/record definitions. Protocols/extend are a superset of mixins as far as I've ever seen them embodied before.

15:25 chouser: slyrus: I don't know exactly what you're doing, but if you want something that behaves just like a vector, but with a few more functions on it, one option is to have the object actually be a regular vector, and provide functions (perhaps protocol methods) that operate on them.

15:25 slyrus: yeah, that sounds great. how do I do that? :)

15:26 chouser: what sort of operation do you want?

15:26 slyrus: the protocol methods part that is...

15:26 chouser: oh

15:27 slyrus: ok, let's take a trivial example. I have [:a :b]. I want (get-the-other-value <the thing that is/has the [:a :b] vector> :a) to return :b.

15:29 naively, I would think that I would want a MySillyVectorOperations protocol with get-the-other-value and then some sort of defprotocol/deftype magic that allows me to write methods for MySillyVectorOperations.

15:29 My understanding is that's the way it works if I'm extending a map, which is awesome

15:29 I want the some sort of thing for a vector and am under the impression that this can be done with deftype, but I don't understand the details.

15:30 chouser: (defprotocol Pair (left [n]) (right [n])) (defn get-the-other-value [p x] (if (= (left p) x) (right p) (left p)))

15:30 something like that?

15:30 slyrus: yes

15:31 chouser: (extend-type clojure.lang.PersistentVector Pair (left [v] (first v)) (right [v] (second v)))

15:31 (get-the-other-value [:a :b] :a) ;=> :b

15:32 slyrus: wow, this is neat

15:32 only I'm not quite sure what the extend-type there just did

15:32 chouser: that sound you hear is the expression problem going up in smoke.

15:33 cemerick: heh

15:33 chouser: slyrus: extend-type is telling the 'left' and 'right' functions what to do when confronted with a plain old clojure vector.

15:34 cemerick: oh, how I wish case evaluated static field dispatch constants

15:34 chouser: cemerick: yeah, I've run into that as well.

15:34 Java enums are essentially the same, aren't they?

15:34 slyrus: "A macro that expands into an extend call." isn't too helpful :)

15:34 clojurebot: amespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it

15:35 slyrus: chouser: what does the third argument (Pair) do in that extend-type example?

15:35 both get-the-other-value and [:a :b] don't know anything about Pair, right?

15:35 chouser: slyrus: that's indicating *which* 'left' and 'right' functions I'm about to implement.

15:36 cemerick: chouser: I'm not sure what case does with a Classname/field dispatch. And yes, enums are static fields.

15:36 slyrus: so now I can call left and right on all vectors?

15:36 chouser: slyrus: get-the-other-value is built specifically on top of the Pair functions 'left' and 'right'. You could hint the args as [^Pair p, x]

15:36 slyrus: yes

15:37 slyrus: fascinating...

15:37 cemerick: I'd like to make case insensitive to hash collisions as well, so I've got a pile of case hacking to do. :-)

15:37 chouser: it's all the power of monkey patching without that itchy-teeth feeling

15:41 slyrus: oh, neat: (extend-type clojure.lang.APersistentMap Pair (left [v] (:left v)) (right [v] (:right v)))

15:41 (get-the-other-value {:left :a :right :b} :a)

15:41 chouser: :-)

15:42 slyrus: Ok, thanks for the mind-expanding explanation!

15:42 chouser: switch to (extend-protocol Pair ...) and you can do both in a single top-level expression.

15:43 slyrus: you're welcome. This is what I hope to do for everyone that comes to my talk at Strange Loop.

15:43 still looking for the killer example...

15:43 ecyrb: In a deftype I tried to create a field with ^{:tag int :unsynchronized-mutable true}, and I got the message "Must assign primitive to primitive mutable"

15:44 Is a primitive mutable a boxed primitive wrapper (i.e. java.lang.Integer)?

15:45 chouser: that's some dark magic you're playing with there...

15:46 ecyrb: I am having trouble reading my spellbook

15:47 chouser: ecyrb: can you paste a small example that generates the error?

15:47 ecyrb: I suspect what I'm trying to do is not *currently* supported, but the "primitive mutable" term makes me unsure.

15:49 chouser: the field you created is the primitive mutable

15:50 a boxed Integer is not a primitive. It's telling you that the value you pass to set! needs to be a primitive, not a boxed Integer.

15:51 ah

15:52 just needed to fix my set!

15:52 thanks

15:52 chouser: 'mod' will always returned a boxed number

15:52 ok

15:52 but those :unsynchronized-mutable's are really scary.

15:52 ecyrb: yeah, I don't know yet when I need a type-hint / cast

15:52 slyrus: (edges q7 1) ==> ([385 1] [1 35]...) is much nicer than (#:shortcut.graph.Edge{:node1 3, :node2 4} ...)

15:53 the only thing more satisfying than writing records is deleting them when they're no longer needed!

15:53 chouser: heh

15:54 eshira: I'm working on a memozied prime finder (for a project euler problem: find the sum of the primes below 2 million): http://gist.github.com/480723

15:54 it is too slow for primes bigger than about 20,000. any ideas why?

15:55 ecyrb: chouser: Are they scary for any reason other than unsynchronized method calls?

15:55 slyrus: oh, only thing is now I can't just rely on the type of the object to know what kind of behavior to implement. hmm...

15:56 chouser: ecyrb: and uncontrolled mutables. Very non-clojury except at the innermost levels of the most performance-demanding code. application-level code should definitely not be using them.

15:56 slyrus: the example is that I used to have an Edge record for undirected edges and an Arc edge for directed edges. Now if those both go away and are replaced by vectors, I have to keep track of whether the edge is directed or undirected. metadata?

15:57 ecyrb: chouser: Alright, cool. Thanks for the help, and I'm looking forward to the rest of the book.

15:57 chouser: slyrus: ah, that is one wrinkle. protocols only dispatch on the actual java type, so if you need different implementations, you'll need different objects -- at least one defrecord again.

15:58 ecyrb: great, thanks!

15:59 slyrus: chouser: then I'm back to my original question. can I defrecord a vector instead of a map?

15:59 chouser: slyrus: no, not in any way I can think of.

15:59 slyrus: it's not so much different implementations, but that certain operations should only be allowed on certain objects.

16:00 ok, thanks. perhaps there's a need a defvector analog to defrecord.

16:00 chouser: hm. I rather doubt that'll happen.

16:01 The only thing you really need from vectors is IObj?

16:01 slyrus: yeah, I think so

16:03 chouser: which is just get/set of metadata

16:04 slyrus: ok

16:04 chouser: so add a 'meta' to your field list -- then implementing IObj should be just 3 lines in each of your defrecords

16:05 slyrus: great

16:05 forgive me if i've asked this already, but is there a more idiomatic way of doing: (remove #(= % 3) [1 2 3 4 5])

16:06 herdrick: I'm not sure if it's ok to promote my own (Clojure) blog post here

16:06 Is it?

16:08 raek: why not?

16:09 herdrick: Well, refactoring some Clojure

16:09 to get rid of hashtables

16:09 chouser: ,(remove #{3} [1 2 3 4 5])

16:09 clojurebot: (1 2 4 5)

16:10 herdrick: that is, instead of returning a hashtable from a function

16:10 just call that function every time you need a value that would have been in said hashtable

16:11 just put the key from the hashtable that you would have gotten on the end of your argument list

16:11 slyrus: chouser: again, nice!

16:11 herdrick: Here it is: http://news.ycombinator.com/item?id=1529918

16:13 slyrus: chouser: when you implementing IObjc should be 3 lines in defrecords, you mean deftypes, right?

16:13 herdrick: It's a technique not specific to Clojure

16:14 slyrus: s/you/you say/

16:14 sexpbot: chouser: when you say implementing IObjc should be 3 lines in defrecords, you say mean deftypes, right?

16:14 herdrick: btw is there a name for that technique? i've never run across it anywhere.

16:14 chouser: slyrus: sorry, yes.

16:14 slyrus: ok, just checking

16:16 chouser: herdrick: nice. it's a sort of laziness

16:17 herdrick: chouser: yeah

16:17 chouser: same kinds of benefits and tradeoffs as clojure's caching lazy seqs compared to cons-cell lists.

16:25 herdrick: chouser: really?

16:25 I wouldn't have said that

16:26 but then I've not ran into much in the way of tradeoffs with lazy seqs

16:26 except the difficulty in finding bugs

16:26 that's really similar

16:26 chouser: heh

16:27 herdrick: and there's something similar in feel there

16:27 where a lazy seq sets up a function call chain but doesn't use it immediately for all values

16:28 same thing with this - you call down the function chain to get your value when needed, instead of batching it all up into a hashtable

16:28 so it's a lazy hashtable, yeah

16:29 chouser: also interacting with dynamic or "real world" environment -- when you're less sure when the code is going to be called or the results cached, you have to be more careful about impure functions.

16:30 slyrus: chouser: I take it back, yes, I want IObj functionality, which is small, but I also want the thing to be a vector! which I don't think I can do with deftype. (in 3 lines anyway)

16:31 chouser: you want to be able to conj on the end?

16:32 slyrus: hmm... no, I guess not.

16:33 chouser: you want nth to work? or what?

16:33 slyrus: yeah, that sort of thing.

16:33 perhaps I'm not thinking this through clearly enough

16:34 chouser: I suppose you could implement a subset of PersistentCollection, or may just java.util.Collection. It generally requires about one line per method.

16:35 slyrus: ok

16:48 raek: how does future-cancel work? must the thread block or something to be canceled, or can it be stopped anyway?

16:49 also, if the future, say, does a blocking read from a socket, will any data be lost if the future is canceled?

16:51 slyrus: ooh, this gets me out of wanting protocols and records of the same name. I can define the protocols as I want and then just extend-type the underlying representation. neat!

16:56 herdrick: chouser: yes, very much so. I was thinking that sometimes the way to go would be to just make a new memoization wrapper of a function to 'clear the cache' for example at the beginning of a web page context

16:56 so with a new call to that page, you get a new cache

16:57 sometimes handy, i think

17:04 executors process a queue of futures, so if the future hasn't been run yet it can be cancelled

17:05 raek: but if it is running?

17:05 I'm investigating methods of aborting a blocking read

17:07 but maybe there isn't any good way

17:07 mattrepl: use a timeout on the blocking read

17:11 raek: (defn source-seq [source] (lazy-seq (let [item (take! source end-of-stream)] (if-not (= item end-of-stream) (cons item (source-seq source))))))

17:11 rsh: are there any good part of speech tagging libraries for clojure?

17:11 raek: I'm doing a library to make IO more functional

17:11 arohner: rsh: there's a clojure wrapper around openNLP

17:14 * raek contemplates some more

17:16 chouser: raek: future-cancel will cancel a blocking read

17:25 timcharper: lein swank fails for me

17:26 Exception in thread "main" java.lang.Exception: Unmatched delimiter: ) (basic.clj:185)

17:26 using [swank-clojure "1.2.1"]

17:27 raek: when I do a .readLine on a BufferedReader connected to a socket in a future and cancel it, one line gets dropped

17:28 technomancy: timcharper: probably an outdated version of clojure-test-mode

17:28 timcharper: that's the general solution to that problem

17:28 however this is occurring when firing up from the console

17:28 not from within emacs

17:30 At any rate, at clojure-test-mode 1.4 in emacs. I upgrade it a while ago to fix this problem. Now that we've upgraded a project to clojure 1.2, I'm getting it again :(

17:30 slyrus: ,(sort-by #(:level (val %)) {"foo" {:level 1}, "bar" {:level 4}, "ape" {:level 3}})

17:30 clojurebot: (["foo" {:level 1}] ["ape" {:level 3}] ["bar" {:level 4}])

17:30 lpetit: if I were to implement the function I described in the ml (the one which takes a list of namespaces, finds out all the transitive namespaces which depend upon these namespaces, and then calls reload in the right order for each of these namespaces),

17:30 what do you think could be a good name for it ?

17:30 Optionnally, would you use this function ?

17:31 timcharper: hmmm

17:31 lpetit: chouser: nope, it's the exact inverse.

17:31 chouser: it reloads all ns which "depend" on the ns I pass to the function, thus ensuring that all ns which have functions using macros of my ns are accurate (compiled towards the last version of the namespace)

17:31 etc.

17:32 chouser: oh, I see.

17:32 arohner: lpetit: though the inverse would be nice to have as well

17:32 lpetit: chouser: that's a feature I want for ccw, but I guess it could be used outside ccw as well, so I intend to write it in an independent place

17:33 chouser: lpetit: I love that that's your approach. Someday someone's going to steal all your code and put it in a pure-clojure editor.

17:34 lpetit: chouser: if I haven't written the pure clojure editor in pure JDK swing before him :-p

17:34 timcharper: technomancy: do you know how to get the "52 more" to sho ?

17:34 show ?

17:34 chouser: :-)

17:34 technomancy: lpetit: search the mailing list; Steve Gilardi was working on an overhaul for require that basically implemented what you're looking for.

17:34 timcharper: (at the end of my pastie)...

17:35 somnium: lpetit: will you accept random requests for features from emacs?

17:35 technomancy: timcharper: dunno; sorry. clj-stacktrace is nice for that.

17:35 * somnium wonders if we can trick him into rewriting emacs in clojure

17:35 lpetit: technomancy: oh! Now that you're talking about it, I remember the thread, but I didn't remember this feature was on the list. Thanks !

17:36 somnium: yes, if you're ready accept random reponses ! :)

17:36 somnium: :-)

17:36 crowbar7: I think it's time I write a clojure asterisk lib.

17:36 lpetit: somnium: seriously, yes.

17:37 ~counterclockwise

17:37 clojurebot: Counterclockwise aka ccw at http://code.google.com/p/counterclockwise/

17:37 neotyk: is there a way to see if promise was delivered yet? (delivered? prom)

17:37 lpetit: somnium: ^^^^ the issue tracker accepts feature requests

17:37 somnium: what do you have in mind ?

17:38 ,(doc delivered?)

17:38 clojurebot: No entiendo

17:39 lpetit: neotyk: no

17:40 TimMc: lpetit: Is there a plan to integrate lein into CCW?

17:41 lpetit: TimMc: yes

17:42 TimMc: Yay!

17:42 With all the jars nesting happily together in ./lib?

17:43 lpetit: TimMc: there's even a first demonstration of the use of ccw with lein in Stephan Mühlstrasser's ccw repository. He used it to enable a "File > new > Example > LabRepl project" feature. And while adding lab repl support, he wrote the first parts of integration lein with ccw

17:43 timcharper: technomancy: I'm trying to trace my way through and see where the problem lies. The only clue is swank.clj, line 11. When I fire up lein repl and type (require 'swank.core)... it seems to hang with no output. Any ideas on how to proceed ?

17:43 lpetit: TimMc: it's planned, not totally done yet :-)

17:43 TimMc: but I guess so.

17:43 TimMc: :-D

17:44 somnium: lpetit: maybe org-mode and a shell-emulator?

17:44 lpetit: somnium: you'll first have to explain me (no RTFM please) what those are !

17:44 timcharper: http://pastie.org/1051105

17:45 Raynes: org-mode is a TODO list format on crack.

17:45 lpetit: somnium: really, I don't know these modes. So maybe you were joking ?

17:45 lpetit: somnium: answers collision. Is org-mode what is demonstrated by Lau ?

17:46 somnium: collision again :p

17:46 somnium: Eclipse already has a TODO list manager solution. It's heavy, it does everything you want, and I know nobody which uses it :)

17:47 somnium: lpetit: shell-emulator is just bash in emacs

17:47 lpetit: the only time Ive used eclipse was to try ccw :)

17:47 lpetit: somnium: I don't see any interest in shell-emulator. Maybe I'm missing something

17:48 dpritchett: Can anyone help me figure out this simple function? defmapcatop split [sentence] (seq (.split sentence "\\s+")))

17:49 TimMc: I think you're missing some parens at the front there.

17:49 dpritchett: I'm specifically confused by the .split part at the end... it doesn't seem to return anything (side effects from a native Java function I guess?) and the "\\s+" appears to be a regex but the ones i see in my books are more like #"\s+"

17:51 Yes TimMc I did miss the leading paren when I copied this out of a blog post. I'm actually working on project Euler problem 11 and I turned to a wiki for help on converting this big string into a series of lists of 20 ints using (partition 20 (map #(Integer. %) (.split nums "\\s+")). I'm only confused by the .split and the regex I guess

17:51 lpetit: ,(.split "ab cd" "\\s+")

17:51 clojurebot: #<String[] [Ljava.lang.String;@d1102f>

17:51 lpetit: ,(seq (.split "ab cd" "\\s+"))

17:51 clojurebot: ("ab" "cd")

17:52 lpetit: dpritchett: of course you're wrong, and .split returns something, because if not you would not want to pass it to seq, and also because Strings in java are guaranteed immutable since java inception

17:53 dpritchett: #"\s+" is not "a regex", it's a regex pattern, precisely:

17:53 ,(type #"\s+")

17:53 clojurebot: java.util.regex.Pattern

17:55 lpetit: a java.util.regex.Pattern instance. dot calls in clojure are for java interop. You thus have to conform to the java object's API. java.lang.String has a split function, and you used the version which takes a pattern encoded in a String. Nothing wrong with this. It's just less readable.

17:55 somnium: ,(seq (.split "foo\\bar\\baz" "\\\\"))

17:55 clojurebot: ("foo" "bar" "baz")

17:55 lpetit: dpritchett: you could although do that:

17:55 ,(seq (.split "foo bar baz) (.pattern #"\s+"))

17:55 clojurebot: Unsupported character: \s+

17:55 lpetit: argh

17:57 ,(seq (.split "foo bar baz") (.pattern #"\s+"))

17:57 clojurebot: java.lang.IllegalArgumentException: No matching field found: split for class java.lang.String

17:57 lpetit: re-gargl

17:57 ,(seq (.split "foo bar baz" (.pattern #"\s+"))

17:57 lpetit: re-re-gargl (must go to bed, now)

17:57 ,(seq (.split "foo bar baz" (.pattern #"\s+")))

17:57 clojurebot: ("foo" "bar" "baz")

17:57 lpetit: ah !

17:58 finally !

17:59 * lpetit wishes nobody will ever look at the code he does over midnight (that is almost all of current ccw's code :-/ )

17:59 dpritchett: thanks lp

17:59 I better understand the java interop part

17:59 Still not quite sure why the code I copied uses "\\s+" instead of "\s+"

18:00 timcharper: OK... so (require 'swank.swank) makes my repl hang...

18:00 somnium: ,"\s+"

18:00 clojurebot: Unsupported escape character: \s

18:00 dpritchett: Ok I'm with you now somnium

18:01 I'm passing "\s+" to java but unless I escape the backslash Clojure eats it instead of passing it along like any other character

18:01 timcharper: (require 'leiningen.swank) causes an error: java.io.FileNotFoundException: Could not locate leiningen/compile__init.class or leiningen/compile.clj on classpath: (swank.clj:1)

18:01 dpritchett: so "\\s+" is interpreted as a "\s+" by .split

18:01 timcharper: I'm really struggling to try and diagnose this..

18:03 lpetit: dpritchett: not quite. You're passing the source code literal string composed of characters slash, letter s, sign plus to the clojure reader. The clojure reader reads clojure Strings with the same algorithm as the java compiler reads literal java Strings. And "\s+" is not a valid clojure/java string.

18:04 timcharper: technomancy: any clues... please? :) I am trying to understand how lein works so I can figure this out.

18:04 dpritchett: Tim what are you trying to do?

18:04 timcharper: why can't I issue 'lein repl' and then invoke (use 'leiningen.compile)?

18:04 technomancy: timcharper: there's a bug in the repl task that sometimes makes it look like it's hanging when it's not... try entering a few more lines (http://github.com/technomancy/leiningen/issues#issue/71)

18:04 timcharper: I'm trying to get to the bottom of why lein swank no longer works for me after a clojure upgrade

18:05 technomancy: ahh... that solves it

18:05 technomancy: =\

18:06 timcharper: able to dig deeper...

18:09 dpritchett: Thanks again lpetit. I admit I know even less about Java than I do about Clojure so this has helped me.

18:09 timcharper: technomancy: unfortunately, clj-stacktrace was no additional help, though the output was prettier :) still making progress though with the fake repl-hang workaround

18:09 knowledge

18:10 lpetit: dpritchett: np, it was done with this intent in mind ! :)

18:13 timcharper: technomancy: found it !!

18:13 tell me if this little line doesn't reveal the issue to you:

18:15 how much damage did I just do ?

18:15 technomancy: heh that'd do it

18:16 I was hoping for a fix to the repl problem =(

18:16 timcharper: I have a fix: use emacs

18:16 ok... not much of a fix if emacs/clojure aren't playing well with eachother

18:17 lpetit: technomancy: I didn't manage to find the thread created by Steve Gilardi, related to requiring dependants. Could you give it a try ?

18:17 timcharper: actually... nevermind... maybe not... erase the last two message by me

18:18 lpetit: technomancy: nevermind, found in my personal archives :

18:18 :)

18:21 timcharper: For future people who stumble on this: If, when you invoke lein swank, using lein 1.2.0, and adding [swank-clojure "1.2.1"] to your project.clj, you get this error message:

18:21 Exception in thread "main" java.lang.Exception: Unmatched delimiter: ) (basic.clj:185)

18:21 It could be because another dependency of yours is bringing in an older version of swank. Like orolo is doing currently, for example: http://github.com/stuarthalloway/orolo/blob/660e8260/project.clj#L8

18:22 technomancy: timcharper: it could be an older version of any lib; that exception is caused by using ^ as meta, which has been deprecated for a while.

18:23 timcharper: hmm... so this is more like a "not compatible with clojure 1.2" issue

18:23 Raynes: technomancy: I updated clojure-http-client to use the new betas and threw you a pull request.

18:24 lpetit: technomancy: re-read the thread you mentioned. I can't see where the feature I was mentioning ^^^ is covered

19:46 eshira: how would i init a vector of bools of a certain size?

19:47 technomancy: ,(into [] (repeat 10 false))

19:47 clojurebot: [false false false false false false false false false false]

19:48 chouser: ,(into (vector-of :boolean) (repeat 10 false))

19:48 clojurebot: [false false false false false false false false false false]

19:48 technomancy: well hello mister fancy-pants. =)

19:48 chouser: or what technomancy said, depending on what you want.

19:48 :-)

19:48 eshira: is vector-of suppose to be a builtin?

19:49 timcharper: I can verify that I have indeed hear chouser has pants that are mighty fancy

19:49 ^hear^heard

21:26 TakeV: Does Clojure have anything like Rails, yet?

21:27 dnolen_: TakeV: conjurehttp://github.com/macourtney/Conjure

21:27 never tried it myself, but it does seem pretty heavily developed

21:27 TakeV: Awesome, thank you.

21:53 rhudson: Given (defprotocol P (f [p])), (defrecord R [a] P (f [_] (- a))), (def r (R. 2)), it seems I can use the calls (f r) or (.f r). Is there any semantic or performance difference between the two?

22:02 ok, if I move to a different namepace, (.f user/r) works & (f user/r) doesn't ("unable to resolve symbol: f")

22:12 So (defprotocol P (f [p])) interns P and f in the current namespace

22:14 slyrus: how can I make a method preferred: Multiple methods in multimethod 'code-dispatch' match dispatch value: class chemiclj.core.Bond -> interface clojure.lang.IPersistentMap and interface clojure.lang.IPersistentVector, and neither is preferred

22:17 rhudson: ,(doc prefer-method)

22:17 clojurebot: "([multifn dispatch-val-x dispatch-val-y]); Causes the multimethod to prefer matches of dispatch-val-x over dispatch-val-y when there is a conflict"

22:17 slyrus: i see. thanks rhudson.

22:19 rhudson: Your dispatch value is Bond? or IpersistentVecor or IPersistentMap?

22:21 slyrus: Bond. (defrecord Bond ... clojure.lang.IPersistent Vector length ...)

22:21 but, you know, that's probably not so smart anyway.

22:21 just because I _can_ do something, doesn't necessarily mean I _should_.

22:32 sproust: helo clojurians ; I have a question about leiningen.

22:34 I want to embed swank-clojure into my code; how do I get leiningen to pull it from its own checkout (outside my project)? How am I supposed to specify the path to it?

22:38 tomoj: is there a reason you need to pull it from its own checkout? living on the edge? hacking on swank-clojure?

22:40 there is a new feature in 1.2.0 which can do what I think you're asking, but there's really no reason to do it unless you are hacking on swank-clojure

22:41 in the normal case you'd just add swank-clojure to your project's deps

22:42 dnolen_: rhudson: f is preferred over .f if using protocols. For one I think .f probably needs a typehint to work without reflection. f does not. there is no performance difference that I've seen.

22:43 rhudson: I mean f and type-hinted .f seem equally fast. f is of course much prettier, no uglying up your arglists with type hints.

22:44 slyrus: is there a *print-circle* equivalent for the pretty printer?

22:45 oh, there is.

22:45 rhudson: dnolen_: Then how do I make sure f is defined in a different namespace?

22:45 slyrus: too bad it's not implemented yet :(

22:45 dnolen_: rhudson: like any other function, :use :require

22:47 sproust: tomoj: i'd have to tell it where to find it.

22:47 tomoj; adding it to my project's deps is what i'm trying to do

22:48 tomoj: sproust: :dependencies [[swank-clojure "1.2.1"]]

22:49 sproust: thx tomoj

22:49 i shouldn't have updated leiningen, looks broken, well something's broken with it not being able to locate find-namespaces from contrib.

22:50 tomoj: do you have contrib in your :dependencies?

22:51 sproust: yep.

22:51 tomoj: maybe the version you're depending on doesn't have find-namespaces?

22:52 sproust: 1.2.0-beta1, i doubt that's it

22:52 tomoj: agreed

22:53 I doubt it's leiningen's fault though

Logging service provided by n01se.net