#clojure log - Jan 31 2010

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

0:04 * hiredman used to go by kdawg, ten years ago, on another net

0:08 pdk: you could fuse them and be a hireddawg

0:09 abrooks: dawgedman

0:09 hiredman: :P

0:09 I bring it up because I jost noticed kdawg_

1:44 technomancy: only one feature left before Leiningen 1.1.0

1:44 wute

3:56 noidi: how can I create a double[][] in Clojure?

4:00 _ato: ,(make-array Double/TYPE 10 10)

4:00 clojurebot: #<double[][] [[D@df090d>

4:00 noidi: thanks!

4:48 fholm: dmiller2718: you the guy who's working on clojure-clr ?

5:15 dr_df0: hi everyone

5:19 is anybody here?

5:19 are annotations supported now in clojure 1.1.0

5:19 I would like to use jboss netty library, but it requires annotations

5:25 _ato: no, they're not supported

5:27 dr_df0: do you know any other high performance socket server library for clojure?

5:27 socket-server from contrib is not suitable

5:27 since it creates thread for every connection

5:28 _ato: I'd just use NIO directly

5:29 I haven't heard of a clojure wrapper for it

5:29 there's a bunch of java NIO "frameworks" listed here: http://technfun.wordpress.com/2008/04/21/critique-of-java-nio-frameworks/

5:30 but they sound like overkill ;-)

5:30 dr_df0: +ato: thx

5:59 AWizzArd: Moin sys

8:02 noidi: is there something like assoc-in for conj?

8:02 I need to do this: {:foo [1 2 3]} --> {:foo [1 2 3 4]}

8:03 right now I'm tempted to make the value of :foo a ref just to make updating easier, but I know there must be a better way :)

8:04 Chousuke: noidi: updatein

8:05 with a dash :P

8:05 (doc update-in)

8:05 clojurebot: "([m [k & ks] f & args]); 'Updates' a value in a nested associative structure, where ks is a sequence of keys and f is a function that will take the old value and any supplied args and return the new value, and returns a new nested structure. If any levels do not exist, hash-maps will be created."

8:06 noidi: thanks!

8:06 that's exactly what I was looking for

9:02 AWizzArd: rhickey: is there a better/more performant way to do (= ::MyDefType (type obj))?

9:03 rhickey: AWizzArd: not really - why are you doing that?

9:05 AWizzArd: It is for my Clojure DB system. It can automatically create indexes during insertion, and for deftyped things it groups them by their type.

9:05 rhickey: ok, but why would it reference a type tag explicitly like that?

9:07 AWizzArd: Cause this can be the criteria for being taken into an index. The user can specify the criteria when to index something.

9:07 And all objects one inserts that pass this test go into a specific index.

9:08 (insert *db* obj) <-- this adds obj to all indexes for which obj pasess the index-predicate

9:09 I just wanted to make sure that using = and type is the right thing.

9:09 rhickey: it will work

9:09 AWizzArd: good

9:09 thanks

10:20 the-kenny: somnium: Does congomongo support mongo's modifiers? ($push $inc etc)

10:28 rrc7cz: has anyone implemented platform/plugin capabilities before?

11:22 satous: (doc assoc-in)

11:22 clojurebot: "([m [k & ks] v]); Associates a value in a nested associative structure, where ks is a sequence of keys and v is the new value and returns a new nested structure. If any levels do not exist, hash-maps will be created."

11:22 satous: (source assoc-in)

11:26 avarus: hi

13:54 AWizzArd: when I have a (deftype Foo [a b c]) and then (def x (Foo 10 20 30)), what name does have bar then? (bar x) ==> (:a :b :c)?

13:56 rhickey: AWizzArd: if you want map stuff, specify IPersistentMap and then you'll get support for (keys x)

13:56 otherwise you have normal Java reflection of fields

13:56 AWizzArd: Ah sure, easy enough. I could have answered this myself. Thanks.

14:10 Though it could be nice if Clojure offered its own reflection tools. Maybe this will be easier with clj-in-clj.

14:19 avarus: what's a simple template library for clojure in your opinion?

14:20 AWizzArd: avarus: template as in "html"?

14:20 avarus: yep

14:20 AWizzArd: did you look at Compojure?

14:21 avarus: oh, yes, I am just looking at it :)

14:21 AWizzArd: good choice

14:21 avarus: ok :)

14:22 I just set it up and it was very easy but I just tried the hello world for now :)

14:22 AWizzArd: This route makes sense.

14:29 avarus: the documentation is limited I think

14:29 AWizzArd: It is not optimal yet. The best thing is to start with the hello world and try to extend it a bit.

14:30 Then the Google Group has code examples. There is a Wikibook with more examples.

14:31 And a bit documentation you can find here: http://compojure.org/

14:31 avarus: ya, I'm there :)

14:32 the group seems to be full of info :)

14:32 the google group

14:32 AWizzArd: Compojure learning goes likes this: read the examples, modify them, play around with them, get an impression what you want to do, try to do it, begin asking questions in the GG.

14:32 avarus: :)

14:33 AWizzArd: after a few iterations Compojure will make very much sense. It is indeed pretty simple.

14:33 avarus: fine

14:37 cool, contrib has something for json :)

14:38 qbg: When I'm use `lein repl`, I can require my project, but when I using `lein swank`, I can't. What am I doing wrong?

14:41 AWizzArd: hi cg

14:56 * avarus is having fun :D

15:08 robwolfe: qbg: "M-x swank-clojure-project" is probably what you need

15:09 qbg: I tried that and that also didn't work

15:09 robwolfe: do you have ":dev-dependencies [[leiningen/lein-swank "1.1.0"]])" in your project.clj?

15:09 qbg: Yes

15:11 Raynes: robwolfe: You don't need lein-swank in order to use swank-clojure-project.

15:12 robwolfe: Raynes: from swank-clojure.el "Note that you must have swank-clojure.jar in the lib/ directory"

15:12 Raynes: swank-clojure.jar isn't lein-swank.

15:13 robwolfe: Raynes: right, but I thought that lein-swank depends on it

15:14 dnolen: qbg: you probably need to compile lein-swank yourself. that's what I had to do to get it to work

15:14 I believe that lein-swank in it's current release doesn't properly add the src to the classpath

15:14 in the lein-swank directory

15:14 lein uberjar

15:15 then replace the lein-swank jar in the lib folder of your leiningen repo (I 90% sure you need to be using lein from source for any of this to work)

15:22 qbg: I built it and replaced the old one. Now it doesn't complain about the ^ reader macro, but I still can't require my project

15:24 robwolfe: qbg: slime starts ok, but you can not require your project?

15:24 qbg: Yes

15:25 It is just a classpath problem

15:25 robwolfe: what's the namespace of yoour project and how do you try to load it?

15:25 qbg: Currently it is called paradigmm (yes, a dumb name)

15:26 I currently call (require 'paradigmm) from the REPL to load it

15:26 This works just fine using lein repl

15:26 robwolfe: under "src" directory "paradigm.clj" with "(ns paradigm)"?

15:26 qbg: (add-classpath also works for loading it, but is non-ideal for other reasons)

15:26 Yes

15:27 The project directory was created with lein new

15:27 robwolfe: in "lib" do you see lein-swank-1.1.0.jar ?

15:29 qbg: yes

15:29 robwolfe: hmm... it works for me just fine

15:30 hiredman: don't use single segment namespaces

15:30 foo.bar

15:31 qbg: Yeah, I need to come up with a better namespace name anyways

15:32 Most of the code is under paradigmm.<something> currently though

15:32 Hmm... If I remove lein-swank from leiningen's lib directory and the project's directory, and then run lein deps in the project directory, lein swank doesn't work, even though the lein-swank jar is copied to the project's lib directory

15:34 robwolfe: qbg: what error do you see?

15:34 qbg: "swank is not a task. Use "help" to list all tasks."

15:35 robwolfe: so you don't have lein-swank in project.clj dev-depdencies

15:35 qbg: But in my project.clj: ":dev-dependencies [[leiningen/lein-swank "1.1.0"]]"

15:36 robwolfe: try "DEBUG=1 lein swank" and see if there is "lein-swank.jar"

15:38 qbg: There is no lein-swank in the output, nor my project.

15:38 robwolfe: qbg: I hope you don't run "lein" script from Leinigen sources?

15:39 I mean I hope you copied this script to your "~/bin" for example

15:40 qbg: Grr...

15:40 Running lein-stable works; I have the lein script from the leiningen checkout symlinked to my ~/bin directory

15:40 robwolfe: wrong! :)

15:43 qbg: Hmm, the readme for leiningen says under Hacking: "When that finishes, symlink bin/lein from your checkout to your path. This will make "lein" run from your checkout while "lein-stable" uses the jar self-installed in ~/.m2."

15:43 This seems misleading then...

15:44 robwolfe: it's for hacking on Leiningen

15:45 for other projects just use lein-stable

15:47 qbg: The Emacs Integration page on github seems to implies that you need to be hacking on leiningen to use it

15:49 robwolfe: you just need "lein" script and "leiningen-standalone.jar" and that's it

15:49 and "clojure" of course ;)

15:50 qbg: The documentation seems misleading then

15:50 But now it works, so I'm happy

15:50 Now to subject myself to the pain of Swing...

15:55 avarus: good night

16:04 {aaron}: hi, i had a question about clojure...what, if anything, does clojure do about non-pure functions? do these matter, or affect assumptions clojure makes? e.g. if i want to, say, list files in a directory...that is a non-pure function... do i need to tell clojure that somehow?

16:04 thearthur: I'm trying to start a vpn(n2n) process through java.Runtime.exec and when the process starts in java the ioctl fails with "device or resource busy" when it starts form the shell it works??

16:05 hiredman: {aaron}: nope

16:05 thearthur: how does a process start by runtime.exec differ from a normal process

16:05 {aaron}: hiredman: so clojure doesn't cache results of functions, etc.?

16:06 hiredman: {aaron}: unless you use memoize

16:06 {aaron}: how about requirements for no side-effects in transactions?

16:06 hiredman: {aaron}: that is a practical requirement

16:06 {aaron}: that's my responsibility to ensure right?

16:06 hiredman: yes

16:06 {aaron}: ok

16:07 hiredman: you can use the io! macro

16:07 ,(doc io!)

16:07 clojurebot: "([& body]); If an io! block occurs in a transaction, throws an IllegalStateException, else runs body in an implicit do. If the first expression in body is a literal string, will use that as the exception message."

16:07 hiredman: but io! doesn't seem to be used much

16:07 {aaron}: i see

16:07 well, i guess it depends on whether the side effects are significant

16:08 i guess it's not really an "effect"

16:08 if i'm logging the time in a transaction, then i can't ensure the time is always going to be the same each try

16:08 hiredman: definitely not

16:09 I think one possibility is to use an agent

16:09 sends to agents inside a transaction don't happen until the transaction completes

16:10 I believe the docs for agents also specify side-effect free functions, but it is common to ignore that

16:10 ,(doc agent)

16:10 clojurebot: "([state] [state & options]); Creates and returns an agent with an initial value of state and zero or more options (in any order): :meta metadata-map :validator validate-fn If metadata-map is supplied, it will be come the metadata on the agent. validate-fn must be nil or a side-effect-free fn of one argument, which will be passed the intended new state on any state change. If the new state is unacceptable, the validate-fn

16:10 hiredman: hmm

16:10 ,(doc send)

16:10 clojurebot: "([a f & args]); Dispatch an action to an agent. Returns the agent immediately. Subsequently, in a thread from a thread pool, the state of the agent will be set to the value of: (apply action-fn state-of-agent args)"

16:10 hiredman: I guess it doesn't specify that

16:13 {aaron}: i like the idea of be assured that functions can be side-effect free...but if there is no way to distinguish in the language...how do i know that mr. library author hasn't just implemented all of his library with the standard Java libraries and doesn't make guarantees about side-effects?

16:13 hiredman: you don't

16:14 rsynnott: in general, trusting that the library author is infallible is probably a bit over-optimistic :)

16:14 {aaron}: so then does programming functionally gain me anything? i'm only as pure as the code i rely on

16:14 hiredman: clojure emphasizes functional style with immutable values, but does not enforce it

16:14 {aaron}: hmm

16:15 ok. in other languages i guess they enforce declaring side effects or something?

16:15 rsynnott: {aaron}: well, if the library author SAYS their functions are side-effect fre, you can trust them or not

16:15 hiredman: {aaron}: well, I am pretty sure the only one that does is haskell

16:15 {aaron}: i see

16:15 rsynnott: just as when a glibc author says that function X won't segfault, you can trust them or not

16:15 {aaron}: right ;)

16:16 Chousuke: {aaron}: if the library author claims a function is pure, and it turns out not to be, file a bug :P

16:17 {aaron}: ok, another question - does clojure itself, separate from Java libraries, have the notion of side-effects...or does it just rely on the JVM for all IO?

16:17 Chousuke: hiredman: doesn't haskell have UnsafePerformIO or something that allows you to override the type system? :/

16:17 hiredman: Chousuke: no idea

16:17 Chousuke: I guess that's just an extension

16:18 hiredman: {aaron}: "just" is prejudicial, clojure is deigned to be integrated with the jvm

16:19 {aaron}: well, i'm trying to determine whether programming "only" in clojure guarantees pure functions...or whether there are intrinsically non-pure functions in clojure

16:19 Chousuke: there are.

16:19 {aaron}: (because then anything that imported stuff outside of clojure could automatically be labelled "dirty/sideeffects"

16:19 ok.

16:19 chouser: prn

16:20 builtin function that prints to stdout -- a side-effect.

16:20 Chousuke: but the host is such an integral part of the language that it doesn't make sense to consider Clojure without one :)

16:20 * {aaron} nods

16:20 _ato: {aaron}: one of the main philosophies of Clojure is that pure-functional code, while having nice properties, is not always sufficient in a practical language. It allows side-effects but provides mechanisms (refs, atoms, agents etc) for making them safer.

16:20 Chousuke: it doesn't have to be the JVM though, but I guess that will always be the "main" Clojure host

16:21 {aaron}: ok. i assume the culture is such that when something *has* to have side effects, clojure authors typically make this pretty clear

16:22 Chousuke: hmm, well, you can use ! in naming :)

16:22 haphazardly mixing functional things and size effects just leads to bad code so it's implicitly discouraged :P

16:24 {aaron}: i see, that's what i was looking for

16:24 _ato: yep, usually it's either fairly clear from the context (eg you're doing IO or talking to a SQL database or something) or the ! naming convention is used.

16:25 {aaron}: cool

16:25 Chousuke: I think clojure actively tries to support a functional programming style rather than discourage any other style.

16:26 but a natural consequence is that imperative programming in clojure tends to feel out-of-place :/

16:26 qbg: When using lein swank, the system classloader doesn't have the project on the classpath, so where can I find a classloader that does?

16:27 Chousuke: hmm, wasn't there some function to get Clojure's classloader? :/

16:28 _ato: (clojure.lang.RT/baseLoader) IIRC

16:32 qbg: Yep, that works

17:30 technomancy: just tagged a Leiningen 1.1.0 release candidate: http://github.com/technomancy/leiningen/blob/master/NEWS

17:31 would love to get some more eyes on it before the release

17:31 qed: technomancy: grabbing it right now

17:31 thanks! :)

18:29 AWizzArd: rhickey: Is there a principle possibility to make insertion into sorted-sets (or maps) faster? Something like "transient sorted-sets" into which I insert elements guaranteed in the correct order?

18:30 ,(let [x (range 300000)] (count x) (time (count (apply sorted-set-by < x))))

18:30 clojurebot: 300000

18:30 "Elapsed time: 7320.944 msecs"

18:30 AWizzArd: ,(let [x (range 300000)] (count x) (time (count (apply vector x))))

18:30 clojurebot: 300000

18:30 "Elapsed time: 92.089 msecs"

18:33 chouser: ,(let [x (range 300000)] (count x) (time (count (into [] x))))

18:34 ,(let [x (range 300000)] (count x) (time (count (into [] x))))

18:34 clojurebot: 300000

18:34 "Elapsed time: 163.705 msecs"

18:34 chouser: ,(let [x (range 300000)] (count x) (time (count (into [] x))))

18:34 clojurebot: 300000

18:34 "Elapsed time: 132.526 msecs"

18:35 chouser: ,(let [x (range 300000)] (count x) (time (count (vec x))))

18:35 clojurebot: 300000

18:35 "Elapsed time: 86.965 msecs"

18:35 AWizzArd: also interesting

18:35 vec and vector use transients under the hood i guess

18:35 hiredman: I doubt it

18:36 I imagine they use to-array under the hood

18:46 mecolin: hello

18:46 chouser: hi

18:47 mecolin: i have these two snippets http://pastie.org/803512

18:47 how can i make the second snippet to evaluate in the first one ?

18:49 Raynes: There are a couple of pastebins that do Clojure highlighting specifically, including gist.github.com, paste.pocoo.org, ideone.com (also evaluates your code for you), and I think snipt.org does as well.

18:49 Not that it matters all that much. Just sayin'. :)

18:49 chouser: what's read-file? but perhaps that doesn't matter -- you were hoping for the locals 'meta' and 'content' to be available to the code you're eval'ing?

18:49 mecolin: Raynes: thanks ;)

18:50 chouser: I'd like to start off with snippet 2 to evalute in place of (eval tempalte)

18:51 chouser: have you tried 'load-file'?

18:52 mecolin: chouser: next, I'd like decorate it with content and meta data

18:52 chouser: with 'load-file' i cannot achieve it, can i ?

18:52 chouser: correct, you cannot.

18:52 nor with eval the way you're going about it.

18:53 mecolin: can you give some clue how should i proceed ?

18:53 s/give/give me

18:53 chouser: I think you'd have to read in the file and wrap it in (let [...] ...), then eval that let form.

18:53 ,(eval (read-string "(+ 10 foo)"))

18:53 clojurebot: DENIED

18:54 chouser: bah. anyway, that fails because foo is undefined

18:54 mecolin: ok

18:54 chouser: but this fails the same way: (let [foo 5] (eval (read-string "(+ 10 foo)")))

18:55 this returns 15: (eval `(let [~'foo 5] ~(read-string "(+ 10 foo)")))

18:55 mecolin: chouser: thanks !

18:55 chouser: hm. you might have other problems though if the file you're reading in is doing 'ns' or 'in-ns'

18:56 mecolin: in fact, i'm doing it in the 2nd snippet

18:58 chouser: yes you are. trouble.

19:06 mecolin: chouser: if i defined a function in 2nd snippet (let's say: defn template), is there a way to switch different layouts in 1st snippet using :use but within render-template ?

20:09 qed: eeneeeeasd

20:14 ag90: Hi. Does the Class/StaticField form work for static enums?

20:16 I'm trying to access java.awt.TrayIcon.MessageType but it complains about not being able to find the class. I have improted (java.awt TrayIcon) but none of the following work:

20:16 TrayIcon/MessageType/INFO

20:16 TrayIcon.MessageType/INFO

20:18 arbscht: java.awt.TrayIcon$MessageType/INFO

20:18 ag90: Oh great that works.

20:18 Thanks

20:40 konr: Guys, why is this false?

20:40 ,(= "44" (reverse "44"))

20:40 clojurebot: false

20:40 hiredman: ,(reverse "44")

20:40 clojurebot: (\4 \4)

20:41 hiredman: ,(= "44" '(\4 \4))

20:41 clojurebot: false

20:41 hiredman: good?

20:41 konr: yes! thanks!

20:43 the correct would be, then

20:43 ,(= "44" (reduce str (reverse "44")))

20:43 clojurebot: true

20:43 hiredman: apply str, not reduce

20:43 konr: Why?

20:43 clojurebot: why not?

20:43 hiredman: clojurebot: deep

20:43 clojurebot: It's greek to me.

20:44 hiredman: str uses a StringBuilder internally for multiple args (the apply case), the reduce case produces more intermediate garbage

20:49 ts00000: anyone here with some clojureql clue?

21:38 jcromartie: would it make any reasonable sense to use a set with vectors as keys for two-dimensional data?

21:39 sorry, hash-map, not set

21:40 ,{[0,1] :foo [1,1] :bar}

21:40 clojurebot: {[0 1] :foo, [1 1] :bar}

21:40 jcromartie: it seems pretty natural

21:40 and it's sparse

22:16 chouser: jcromartie: sure, why not.

22:16 maybe a sorted-map, depending on how you intend to use it

23:23 mquander: i'd like to have a function that either takes a number n, a number n and a list of strings xs, and if i pass it a number n and a single string x, i'd like to treat that string as a list of one string

23:23 is there a nice way to do this?

23:24 oh nevermind

23:24 i figured out how to do it using apply

23:34 technomancy: given a var that's bound to a function and a list of arguments to apply, is there anyway to tell if the arity is correct by looking at the :arglists metadata?

23:34 I mean a built-in function?

23:35 hiredman: ,(:arglists (meta #'+))

23:35 clojurebot: ([] [x] [x y] [x y & more])

23:35 technomancy: I guess it wouldn't be terribly hard to just figure it out with reduce

23:35 hiredman: ,(map count (:arglists (meta #'+)))

23:35 clojurebot: (0 1 2 4)

23:35 hiredman: or something

23:36 technomancy: trickier to do with varargs though, which is why I'd like something built-in

23:37 hiredman: ,(map #(if (.contains % '&) :vararg (count %)) (:arglists (meta #'+)))

23:37 clojurebot: (0 1 2 :vararg)

23:52 abrooks: I'm pretty sure that there's a way to type-hint a defn with its metadata but I'm failing to emit the right words into Google to find it.

23:52 Oh, I want to type hint the type on the RETURN Value.

23:54 Hm. I should looking core.clj...

23:55 Ah... {:tag "[Ljava.lang.Object;"}

Logging service provided by n01se.net