#clojure log - Dec 06 2009

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

0:01 ngoc: I think filter must be used instead of map?

0:01 Because of the condition

0:03 somnium: ngoc: (filter identity (map (fn [a b] (when test [...])) seq1 seq2))

0:13 technomancy: Leiningen 1.0 released: http://github.com/technomancy/leiningen/blob/1.0.0/NEWS

0:16 slyrus: technomancy: congrats

0:34 replaca: congrats, technomancy! Leiningen is another great step forward for Clojure

0:53 DeusExPikachu: I just gotta say, clojure has beautiful reader syntax, it feels natural

0:54 I suppose I feel that way because I'm coming from some common lisp background...

1:11 ngoc: I think Lein is feature-complete if live-repl is integrated: http://github.com/djpowell/liverepl

1:22 mtm_: technomancy: congrats on 1.0

1:26 msingh: has anyone experimented with clojure on a blackberry?

1:54 slyrus: is there a good directory of various available clojure libraries (besides clojure-contrib)?

1:54 _ato: http://clojure.org/libraries has some

1:55 slyrus: thanks!

1:55 (I suppose I should have thought of looking there...)

2:18 ataggart: anyone awake that's played around with extend-* in the new branch?

5:15 the-kenny: Is there a library for refactoring lisp-code for emacs?

6:17 fliebel: How much optimization is done while compiling Clojure?

6:34 cark: i believe not much

6:34 isn't that the work of hotspot anyways ?

6:34 work/job

6:43 fliebel: cark: I think it would save some time if computations based on static values would put only the result in the bytecode. For example (+ 1 1) could easily be represented as 2.

6:44 But the same thing might be useful for regexes, templates or other stuff.

6:44 cark: don't you think hotspot does it ? i don't know much about it but that seems quite easy

6:45 fliebel: But then it has to do it every time the file is ran, right?

6:45 cark: i think literal regexes are compiled only once

6:46 ah you're using clojure as a scripting language ?

6:46 fliebel: I'm not using Clojure at all at the moment actually...

6:46 cark: among the dynamic languages, clojure is pretty good perfomance-wise

6:47 fliebel: I figured that. :)

6:47 angerman: ~source re-seq

6:48 fliebel: I just came up with the crazy idea of hinting the compiler for static-data-funcions that might be compiled into values, like some sort of macro.

6:48 cark: heh compiler macros =P

6:49 we don't have that

6:50 fliebel: Ok, so I can let Clojure replace some code with other code by using a macro, but I can not use a macro to put the return value of the function instead.

6:50 cark: what's the use case you're investigating clojure for ?

6:51 well yes you can do that (if i understand you correctly) ... have a look at memoize

6:52 fliebel: Just a personal project, and for learning purposes. I was writing a small CSM with Python and decided that it would be fun to do it with Clojure.

6:52 cark: oh man you don't need to optimize anything for a web app =)

6:52 unless you're facebook or something

6:53 fliebel: It's not even a web app… :$ I intend to produce static html form source and template files.

6:53 cark: oh i see

6:53 well it's very possible to do this with macros

6:53 tho i think most html libraries do it with functions

6:53 in clojure i mean

6:54 there are macro based html libraries in CL

6:54 fliebel: It's just because I like to try to squeeze every possible possibility out of any language. I'm not in a need for the speed it might provide.

6:55 cark: well that's an easy project, macro based html template, good for learning

6:55 fliebel: Hmhm, but so far I failed...

6:55 cark: oh what's the problem point ?

6:56 fliebel: I want to do impossible thing… at least for a beginner like me.

6:57 angerman: technomancy: can I add jvm arguments to lein swank?

6:57 cark: if you have some specific question, i'm pretty sure you'll find help in this channel

6:57 tomoj: what is the point of generating static html with macros instead of functions?

6:57 fliebel: tomoj: fun, and possibly speed…

6:58 or at least a nicer looking template language.

6:58 tomoj: what I mean is that I think speed is irrelevant for this use case

6:58 fliebel: I agree

6:58 tomoj: at least the difference between macros and functions is irrelevant

6:58 cark: right, even using functions, you can always memoize and you can't go much faster than that

6:58 tomoj: I guess you've seen compojure's html language?

6:58 clojurebot: compojure is http://github.com/weavejester/compojure/tree/master

6:59 fliebel: no, don't think so.

6:59 tomoj: if you think of a nicer looking language, let me know :)

7:00 of course personally I'd rather use actual html and manipulate it with enlive

7:00 cark: i liked cl-who

7:01 opqdonut: hrgh, cl-who was a hack

7:01 cark: the syntax was nic

7:01 e

7:01 opqdonut: yes

7:01 but the implementation was horrible, side effects and all

7:01 tomoj: do you like compojure's html syntax?

7:01 cark: i don't like the parameters as map in compojure

7:02 tomoj: I guess vectors and maps can look pretty inscrutable

7:02 opqdonut: i understand it was because they wanted to avoid first building the whole syntax tree and then outputting html

7:02 cark: i think it's more because he wanted speed

7:02 edi is a pretty good programmer i think

7:03 tho i had to do a function based html library in cl =P

7:03 same syntax as cl-who, but functions

7:03 fliebel: Is there some sort of 'with' macro that lets me use a lot of functions that would otherwise clutter the current namespace?

7:03 tomoj: I guess sexp-based html templating is a touchy topic

7:04 fliebel: tomoj: why?

7:04 tomoj: well, maybe most everything is a touchy topic in our area

7:04 but some people love it, some people think it's totally stupid

7:04 cark: hehe i guess =)

7:04 i love sexp based html

7:04 so much easier

7:05 fliebel: tomoj: I acutally wanted to do the sexp approach…

7:05 tomoj: cark: just curious, have you looked at enlive?

7:05 (and if so, what do you think?)

7:05 cark: i glanced at it from a distance... looks like a good one

7:05 fliebel: But that leaves me with the problem of how to define so many functions properly.

7:05 tomoj: so far I have only used enlive for screen scraping but the approach for templating really appeals to me

7:06 well, not really a problem in clojure

7:06 cark: fliebel : explain better what you want

7:06 tomoj: you only need one function, html

7:06 cark: in a function scope ?

7:06 tomoj: the argument to this function can be a vector

7:07 don't have to make fake functions for the various tags, just [:tag-name contents]

7:07 though that may look ugly to you :/

7:07 fliebel: indeed

7:08 even worse, you would nee [:tag {:attr "value"} content]

7:08 *need

7:08 cark: you could do (:tag-name contents) then make the html call a macro that walks the tree... but you have to think about composition, it's definatly easier with vectors

7:09 fliebel: what do you mean?

7:09 tomoj: you want something like (html (h1 "foo") (p "bar baz")) ? or what?

7:09 cark: you could make it [:tag :attr1 "val" :attr2 "val" "content"]

7:09 fliebel: tomoj: yea, something like that I guess

7:10 cark: how would you distinguish between attributes and content?

7:10 tomoj: if html is a function that seems doomed to me

7:10 cark: fliebel : as long as you have keyword value pair, it's attributes, after that it's content

7:10 tomoj: have to make a function for each tag, which means if you want to use a tag that wasn't given to you by the authors, you're screwed :(

7:11 compojure is like (html [:h1 "foo"] [:p "bar baz"])

7:11 fliebel: how about this: make html a macro that transforms (a content) to (tag "a" content) that would leave you with one function.

7:12 tomoj: yeah, that doesn't sound too bad

7:12 except..

7:12 this transformation would need to be recursive to be useful, no?

7:12 fliebel: yea...

7:12 tomoj: and that means you can't call actual functions anywhere inside this html macro?

7:12 cark: well that's only a matter of walking the tree

7:13 you need special syntax, hum that's ugly

7:13 tomoj: whereas with compojure we can say (html [:h1 (some-func "foo")]) for example

7:13 the-kenny: Uhm.. I haven't read the whole conversation, but do I understand you right that you want to write a function to create html out of sexps?

7:13 fliebel: tomoj: good point :S

7:13 the-kenny: If so: there is already a library in contrib to do that.

7:15 fliebel: the-kenny: using vectors and :keywords?

7:15 the-kenny: fliebel: Yes

7:15 (prxml [:p {:class "greet"} [:i "Ladies & gentlemen"]])

7:15 -> ; => <p class="greet"><i>Ladies &amp; gentlemen</i></p>

7:15 fliebel: the-kenny: I was thinking about some magic with functions and macros, but it seems impossible, or at least hard.

7:16 the-kenny: fliebel: Nothing is impossible in a lisp

7:16 angerman: lol. running my code with -server -Xms512m resulted in an unbeleavable performacen boost from 1'063'192.462 msecs down to 167'054.122 msecs

7:17 fliebel: the-kenny: But it could be impossible for a beginner like me...

7:18 the-kenny: fliebel: But you can learn ;)

7:19 fliebel: I was discussing how to do it with those guys...

7:20 the-kenny: hm... sorry if I interrupted you

7:20 fliebel: A key problem with the function approach is that there might be naming clashes with built in functions.

7:21 or you would need to define a subset of tags or lose the ability to call functions in the macro

7:22 the-kenny: Why not use keywords for tags?

7:23 fliebel: Are there any secret hooks or functions that can be used to filter function calls to a specific namespace? I used the quite much in Python. When one calls a method on an object __getattr__ gets called and you can decide what is returned.

7:26 the-kenny: Ugly? Maybe as a last resort, but if possible i'd like to avoid them. Then I might just as well use the one in contrib.

7:27 the-kenny: I don't think it's ugly. It's almost perfect for this use case

7:27 tomoj: the ugliness is what, the extra :?

7:27 and I guess square brackets instead of parentheses?

7:28 the-kenny: Either you have to use a specified set of tags or something dynamic. It goes down to strings, symbols and keywords. I think keywords are the best one of these tree ;)

7:29 fliebel: mostly, yes… Of course I could use that, but I like to try out what is possible with a language.

7:29 the-kenny: tomoj: I think it would be possible to avoid the parenthesis with some magic in a macro

7:30 s/parenthesis/square brackets/

7:30 fliebel: the-kenny: how?

7:30 tomoj: well, that's the problem

7:30 if you really want paretheses instead of square brackets, seems to me you lose the ability to call functions inside your template

7:30 which makes me think that vectors are perfect :)

7:30 the-kenny: fliebel: Use a & body struct in the argument list, destructurize the tree yourself and check if the first element of every sexq is a valid function in clojure

7:31 (and then evaluate it)

7:31 tomoj: ah, but possible conflicts where the tag you want is actually a function?

7:31 the-kenny: But vectors are easier :)

7:31 tomoj: yap

7:31 fliebel: the-kenny: that is what i was thinking about, but how do I do that? is the something like 'function-exists?'?

7:32 the-kenny: tomoj: I'm talking about keywords + parenthesis. I don't think there will be conflicts

7:32 tomoj: ah yes

7:32 the-kenny: fliebel: I'm sure there is.

7:32 tomoj: that works I suppose as long as you don't use a keyword as a function

7:32 the-kenny: (Or it's simple to write one)

7:32 tomoj: and that would be a particularly daft thing to do when it looks just like a tag

7:32 the-kenny: tomoj: Heh yeah, that will break it

7:32 cark: ,(fn? seq)

7:32 clojurebot: true

7:32 the-kenny: ,(:foo {:bar 42 :foo 23})

7:33 clojurebot: 23

7:33 the-kenny: That won't be possible

7:33 cark: i think keywords as tag is cool because of the syntax coloring in emacs

7:33 tomoj: vectors are indeed easier, of course

7:33 fliebel: hmhm

7:33 the-kenny: cark: that's another argument for keywords :)

7:33 clojurebot: for is not a loop

7:33 the-kenny: bad clojurebot, bad.

7:34 fliebel: how would i transform (a) to (tag a) with a macro

7:34 ?

7:36 tomoj: maybe something like (defmacro the-macro [& body] (map #(conj % 'tag) body))

7:37 no..

7:37 need a list or something

7:37 otherwise the first (tag ...) will be called as a function

7:38 Chousuke: ,(conj '(a) 'tag)

7:38 clojurebot: (tag a)

7:38 Chousuke: like that.

7:39 thomaslee: hi all ... I want something like the "->" macro with a slight twist. e.g. (some-fn a (b) (c) (d)) would evaluate to (b a) (c a) (d a). Does anybody know if this "some-fn" exists in clojure's standard API? :)

7:39 Chousuke: doto?

7:39 ,(macroexpand '(doto a b c))

7:39 clojurebot: (let* [G__6085 a] (b G__6085) (c G__6085) G__6085)

7:40 Chousuke: hm

7:40 thomaslee: Chousuke: I think that might be close enough to what I'm after

7:40 Chousuke: usually used with mutable java stuffthough

7:40 thomaslee: well that's what I'm doing here :)

7:40 working with a URLConnection object

7:41 calling all sorts of horrible setters and stuff

7:41 Chousuke: yeah

7:41 that's what doto is for

7:41 thomaslee: thanks very much!

7:41 clojurebot: much is permittted

8:48 fliebel: can I use doto on Clojure functions?

8:49 Chousuke: sure.

8:49 it's just (doto x .method (f args))

8:49 fliebel: But how do java classes map to clojure and the other way around? I guess something with namespaces?

8:49 Chousuke: hm? :/

8:51 fliebel: Well, in Java everything is organized in packages and classes, so you can do java.package.class.method, in clojure… ?

8:51 _ato: clojure.namespace/function

8:52 Chousuke: for java static methods, you'd do java.package.class/staticMethod

8:53 fliebel: so if for example i want to call some things in user(quite pointless, yes) I'd say (doto clojure.user (function1 "bla") (function2 3))

8:53 interferon: let's say thread t1 enters an STM transaction. it starts processing and then t2 enters an STM transaction that touches the same refs that t1 touches. when they end, do both transactions retry? or does t2 retry as soon as it tries to change a ref that t1 has changed?

8:53 Chousuke: fliebel: um, no.

8:54 fliebel: doto is for calling functions or methods on its first argument.

8:54 that expression would become (do (function1 clojure.user "bla") ...) which makes no sense

8:55 fliebel: so it becomes (.getitem class argument) but getitem is no valid clojure method is it?

8:55 Chousuke: fliebel: but .getitem is a method symbol

8:55 because it has the leading .

8:56 so (doto x .foo bar) becomes (do (.foo x) (bar x) x) which is completely valid clojure code

8:56 _ato: clojure namespaces are not java classes, they behave completely differently

8:56 Chousuke: and x is not a java class, but an object

8:56 though it can be a Class object :P

8:57 fliebel: wait a moment… *grinding gears*

8:58 so doto is just a temporarily partial?

8:58 Chousuke: doto is just a macro for avoiding repetition in cases where in java you'd do:

8:58 _ato: no, doto is a macro, it just rewrites the code at compilation time

8:58 Chousuke: x.foo(); x.bar(); x.foobar();

8:58 which with doto is (doto x .foo .bar .foobar)

8:59 and doto returns x

8:59 fliebel: so it is of no particular use in clojure?

8:59 Chousuke: sure it is.

8:59 fliebel: with clojure code i mean

8:59 Chousuke: when dealing with mutable java objects, mainly

9:00 _ato: it is less useful, if you're writing functional code

9:00 but you could do something like: (doto some-agent (send foo) (send bar))

9:01 fliebel: :( I was actually looking for the opposite :D like (do-with foo bar egg) -> (do (foo bar) (foo egg))

9:02 _ato: (doseq [x [bar egg]] (foo x))

9:02 or (map foo [bar egg]) if you care about the return value

9:03 angerman: Chousuke: do I understand this right? If I want to create a javaclass with clojure that extends another class and implements something I should go with refiy?

9:03 fliebel: map has a cooler syntax in my opinion, i don't get doseq.

9:03 Chousuke: angerman: reify can't extend classes

9:03 only interfaces

9:03 _ato: angerman: you want proxy

9:03 Chousuke: (Object is an exception)

9:04 angerman: Hm. but I thought proxys performance was questionable

9:04 Chousuke: use gen-class then

9:05 fliebel: Is map recursive?

9:05 _ato: fliebel: you mean if you have nested lists? no

9:06 fliebel: ato: yea, that is what I mean… how can I do that?

9:06 _ato: ,(map inc (flatten [[1][[[2]][3]]))

9:06 clojurebot: Unmatched delimiter: )

9:06 _ato: ,(map inc (flatten [[1][[[2]][3]])))

9:06 clojurebot: Unmatched delimiter: )

9:06 _ato: ,(map inc (flatten [[1][[[2]][3]]])))

9:06 clojurebot: (2 3 4)

9:07 _ato: stupid nested vectors :p

9:07 ,flatten

9:07 clojurebot: #<seq_utils$flatten__685 clojure.contrib.seq_utils$flatten__685@1aca0d9>

9:07 _ato: not that flatten is in clojure.contrib.seq-utils not core

9:08 fliebel: ato: macports does not install contrib. :(

9:08 _ato: (for [row [[1][2][3 4]], col row] (inc col))

9:08 ,(for [row [[1][2][3 4]], col row] (inc col))

9:08 clojurebot: (2 3 4 5)

9:08 _ato: but that's not recursive, just two levels

9:09 ~def flatten

9:09 ^ you can of course just define it in your own code if you don't want to use contrib

9:10 fliebel: could I just do (map #(if (vector? %) (map this %) (inc %) [[2][3]]) or something like that?

9:10 Chousuke: guess you could

9:11 though not like that

9:11 you need (fn this [x] (if (vector? x) ...))

9:11 fliebel: hm, i see… Good place to make a macro?

9:13 _ato: don't see how a macro would help

9:13 fliebel: a recursive map macro I guess...

9:14 _ato: ,(map (fn this [x] (if (sequential? x) (map this x) (inc x))) [[2][[3]]])

9:14 clojurebot: ((3) ((4)))

9:14 _ato: it doesn't need to be a macro

9:14 map is just a function

9:15 fliebel: :( I like macros a little to much I guess, just like learning design patters :D

9:16 _ato: yes.. the first thing you should do when you think you need a macro is to ask yourself "does this really need to be a macro?" generally macros should be avoided except when they're the only way to do something

9:16 fliebel: like when?

9:17 _ato: like when trying to implement something like doto or -> or a new type of conditional

9:18 fliebel: what is ->?

9:25 angerman: ~letfn

9:25 clojurebot: Titim gan éirí ort.

9:26 _ato: ~def letfn

9:39 fliebel: wow! My first bit of code that actually has a use: http://pastebin.com/m1dc20c30 recursive map

9:40 uuhm, mace that middle map an rmap.

9:40 *make

9:41 http://pastebin.com/m21efd720

9:44 If I define a nested function, how can I recur the outer function? It would be cool to make my rmap work with TCO...

9:44 The-Kennz: fliebel: Maybe trampoline?

9:46 fliebel: the-kennz: Could be, bu it's going to take me some experimenting before I can get the above example to work.

9:51 the-kennz: I can't get it to work :(

9:56 ngoc: Hi, is there a coding style guideline for Clojure (I think there should be one)? For example, ident, function naming (is that correct that factory functions are make-xxx?), file structure, directory structure etc...

9:57 It will help a lot when there are many people in a team

9:57 fliebel: The only special thing I know about it is 2 space indent and hyphens in names instead of camelcase,

9:58 I'm not sure where I red that, I'm quite noobish.

9:59 The-Kennz: Use te indent provided by clojure-mode :)

9:59 clojurebot: clojure is not scheme

9:59 The-Kennz: s/te/the/

10:00 Most of the guidelines from common lisp can be applied to clojure code

10:01 fliebel: the-kennz: what is clojure-mode?

10:01 ngoc: indent is only one of the problem

10:01 problems

10:02 The-Kennz: For a team of average developers, it is almost impossible to force everyone to use Emacs?

10:03 The-Kennz: fliebel: Clojure indenting, highlighting etc. for emacs

10:04 fliebel: what is emacs? no, sorry, I should know that… Or at least be able to google it.

10:04 The-Kennz: fliebel: The most powerful text editor in the universe. Written in Emacs Lisp :)

10:04 Very good for writing lisp code.

10:06 fliebel: seems good enough for me...

10:06 http://aquamacs.org/

10:07 The-Kennz: Emacs + Slime is the killer-ide for clojure, common lisp and any other lisp where a swank-backend exist

10:08 ngoc: The file browser of Emacs is awful, for project that contains many files and directories, file browser is a must

10:09 The-Kennz: ngoc: There are so many extension for everything.. I'm sure that what you want exists

10:10 fliebel: slime? Clojure is not common lisp, right?

10:10 The-Kennz: fliebel: Yes, but slime works with clojure.

10:10 fliebel: cool

10:10 Chousuke: file browser? I just use tramp :/

10:11 fliebel: I'm off, bye!

10:11 * The-Kennz is using C-x C-f

10:11 Chousuke: The-Kennz: well, tramp integrates with that.

10:12 usually it just finds the file and I don't even need to know where exactly it is :P

10:12 The-Kennz: ngoc: What exactly is a "file browser" for you?

10:12 Chousuke: Yeah, "File Name Cache" does this too

10:13 I'm a bit afraid to add my whole ~/Development directory because of the bazillion .classfiles there

10:13 Chousuke: can't you exclude classfiles?

10:14 The-Kennz: Chousuke: I think so. But I haven't really tried it. I just found out it exists yesterday

10:15 ngoc: The-Kennz: I mean the left pannel in this screenshot of Eclipse: http://www.gesource.jp/weblog/archives_img/eclipse-pydev03.png

10:16 The-Kennz: ngoc: M-x speedbar

10:16 ngoc: The code hightlight of the Clojure plugin for Eclipse is good, but it does not do auto indent

10:16 The-Kennz: ngoc: Example: http://www.telecom.otago.ac.nz/tele402/files/speedbar-customise.gif

10:17 ngoc: yes, that what I mean awful, compared with the file browser of Eclipse :D

10:18 The-Kennz: ngoc: I'm sure there are plenty of customizations and extensions for it

10:26 ngoc: My company of is having problem with Perl, code of projects is a mess. I want to improve this situation. Moving to Ruby is the easiest solution. I am investigating Clojure and Scala. For myself anything is OK, but to build a team of totally average people, an easy developing environment is a must. They are comfortable with Eclipse, so I think the Clojure plugin for Eclipse is the most suitable.

10:29 I want to build a good common coding style from the start, the people are too deep in the mess culture of Perl :(

10:29 tomoj: totally average people :(

10:33 ngoc: Yes, I have to admit that we are average people, so we need an easy start

10:34 Emacs is too hard to start

10:35 angerman: Enclojure?!

10:36 ngoc: Does Enclojure have auto indenting?

10:37 angerman: Not sure. But if I was looking for a clojure support plugin and an IDE I'd check out enclojure+netbeans

10:37 though I heard that IDEA has a nice plugin too... maybe I'm wrong

10:42 ngoc: Can someone share experience of moving to Clojure from other technologies? Why did you pick Clojure instead of Scala. For example Scala has Lift web framework which seems to be comparable to Rails.

10:43 angerman: ngoc: I think it's mostly a personal matter. Either you like Scalas syntax or not. Either you want a lisp or not.

10:45 jasapp: I'm just curious, but what benefits do you see for moving to lisp if you've got "average" people?

10:45 a lisp, I should say

10:46 Chousuke: making them non-average :)

10:46 jasapp: that'll do the trick :)

10:47 ngoc: The benefits are Clojure is easier to start. But I'm not sure about the long term, I have no experience in Clojure and Scala. How about from the view point of a team in a company? Is Scala a safer choice?

10:49 Chousuke: I can't answer that question :/

10:49 I know next to nothing about scala, save that the syntax is scary

10:50 jasapp: from a cover your ass point of view, it seems like java is the safest bet

10:50 no one is going to blame you for using java if something catastrophic happens

10:50 but you're not going to be nearly as productive either

10:50 angerman: I'd say it's like this: the JVM won't break backward compartibility too much in the forseable future. Clojure works right now. So it will work as well as it does today in the forseable future

10:51 ngoc: For a Perl company, moving to Ruby is a safest choice. But after hearing all about the multicore crisis, Clojure may be a choice for a bright future.

10:51 konr: What do you use to wrap jars and the JVM in a single file? JSmooth?

10:53 esj: ngoc, for my 2c: we were a perl shop, then Ruby, and are now starting into Clojure. Each step has been a step for greater sophistication and less complexity.

10:55 ngoc: esj: Do you think we should move to Ruby first, then to Clojure some years later? How many years have you been with Ruby before moving to Clojure? Do you have any problem with Ruby? Is Ruby slow for you?

10:57 esj: ngoc: We were mostly consolidating our code base and Ruby allowed us to that very quickly and quite painlessly.

10:58 We started using Ruby 18months ago, and will continue using it, but starting new work in Clojure as soon as we can get our collective heads around it.

11:00 Our issue with Ruby are performance and growing complexity.

11:01 but we are a very small operation, so its quite easy for us to change direction. I would not say that knowing Ruby will help you learn Clojure, in fact possibly the opposite, but maybe I'm wrong.

11:02 ngoc: esj: Can Ruby 1.9 solve your performance issue? What is the complexity? Is that because class openning makes your code hard to maintain?

11:04 esj: Ruby 1.9 should help on the performance front, but Clojure promises a lot more. Complexity is concurrency.

11:05 regularfry: Noon all. Having a little syntax difficulty. How do I create a HashTable<String, Object> to pass off to a library? I get a ClassCastException if I use a hash-map.

11:08 I can't see much documentation on using java generics from Clojure, which makes me think I must be missing something obvious.

11:08 ngoc: regularfry: http://groups.google.com/group/clojure/browse_thread/thread/4b127c9374ece307/1062db714c991bc2

11:10 I think you should see the Java Interop instruction to create a Java HashTable

11:12 regularfry: ngoc: I've seen that, and don't understand.

11:12 ngoc: the google groups post doesn't explain anything, and the java-interop page doesn't involve generics.

11:13 ngoc: I think the <String, Object> is not important because "generics are only at compile time". If you can create a subclass of HashTable, then you're done

11:14 Drakeson: have you tried to provide nailMain(NGContext context) in clojure?

11:15 ngoc: Create an object of a subclass of HashTable, manipulate that object, then pass it to the Java library

11:15 regularfry: ngoc: that would make sense. I don't know enough about how generics are implemented in Java to know, though. I'll give it a shot.

11:17 ngoc: If hash-map is a subclass of HashTable, then you're done, but I'm not sure about that

11:20 scellus: btw, is it easy (or possible) to generate such a subclass in clojure?

11:41 ngoc: scellus: yes, buy this book, it's a must for learning Clojure: http://pragprog.com/titles/shcloj/programming-clojure

11:42 scellus: ngoc: i have it, have to read it :)

11:44 ngoc: Unfortunately at the moment this book is the only Clojure book, and the Clojure doc is too short without examples. So you can say this book IS the Clojure doc.

11:46 Chousuke: Mark Volkmann's Clojure article is also great.

11:48 ngoc: ah yes, sorry I forgot that wonderful summary

11:52 scellus: ngoc: yes i've actually done clojure for a few hundred lines already. java is just foreign to me. feels nice, i'll try to advertise it in our company

12:12 ngoc: scellus: the cheat sheet may be the most "must have": http://clojure.org/cheatsheet because there are too many functions in the default namespace

12:22 KirinDave: So I saw this: http://dhotson.tumblr.com/post/271733389/a-simple-chat-server-in-node-js

12:22 Makes me wonder

12:22 what's the java-world answer to node's evented IO?

12:23 ngoc: JBoss Netty and Servlet 3

12:23 micampe: or apache mina

12:23 ngoc: Netty and Mina have good doc

12:24 KirinDave: Well i found this

12:24 http://github.com/ngocdaothanh/telchat-clojure

12:24 ngoc: ... than some others

12:25 KirinDave: And it seemed like Netty was something of a pain to use with clojure because it lacks annotation support?

12:26 ngoc: yes, but you have to create only one Java class to use annotation in it, for others you can use proxy that Clojure provides

12:27 KirinDave: Well I was pondering if there was as elegant way to do this in clojure that would make a good blog post

12:27 ngoc: and the class is super short: http://github.com/ngocdaothanh/telchat-clojure/blob/master/src/main/java/telchat/net/Handler.java

12:28 KirinDave: Yes, but that approach doesn't fit in a single blog post. :)

12:29 ngoc: Is that true that on theory it is impossible to add annotation support to Clojure?

12:31 KirinDave: I wonder if the clojure-esque architecture is to have rooms as agents holding lists of sockets to write to.

12:32 Although I dunno how to do non-blocking reads in clojure.

13:27 The-Kennz: KirinDave: I'm sure the iostreams provided by the socket-classes have options to do non-blocking reading

13:28 But I think a more clojure-like approach would be better (a background thread to collect data to an agent or something like c.c.http.agent

13:33 fliebel: What is a proper way to write my own custom map function?

13:44 scellus: fliebel: be a bit more specific. what's wrong with the standard map?

13:45 fliebel: scellus: Nothing, just for learning purposes.

13:46 scellus: fliebel: look at the sources. it's a bit tricky with the laziness.

13:47 without laziness, in a typical lisp, you'd use tail recursion

13:47 fliebel: scellus: I don't need to something advanced like that. Just how to use recur to execute and return for every value.

13:48 I got this now:

13:48 (defn testmap [function body]

13:48 (function (first body))

13:48 (println function body)

13:48 (recur function (rest body))

13:48 )

13:48 But that returns nothing and gives a nullpointerexception

13:51 durka42: fliebel: you need a base case to stop the recursion

13:51 eventually (rest body) is null

13:51 and since this isn't lazy you want to be using next, not rest

13:52 The-Kennz: hm.. I think this map is missing a cons or conj

13:53 scellus: (defn mymap [f l] (loop [l l r []] (if (empty? l) r (recur (rest l) (conj r (f (first l)))))))

13:53 fliebel: durka42: But if I supply next to recur, the next iteration does not have access to the list.

13:53 durka42: fliebel: huh? you want (next body) instead of (rest body)

13:54 fliebel: what is the difference?

13:55 ,(= (rest [:a :b :c]) (next [:a :b :c]))

13:55 clojurebot: true

13:55 scellus: http://clojure.org/lazy

14:05 fliebel: Can I do optional arguments? I noticed a question mark somewhere, but I can't figure out how it works.

14:06 technomancy: fliebel: (fn [req & [opt1 opt2]])

14:07 basically you destructure on your rest param.

14:07 fliebel: how do I destructure?

14:07 technomancy: you can also use a multi-body fn where the N-1 arity body calls the N

14:08 N-arity one with the optional args filled in

14:08 fliebel: So what does this function do? (defn optional [a b? c] (println a c))

14:09 technomancy: that just means you have a local with "b?" as its name

14:09 the question mark is a valid name for a local

14:09 fliebel: ah, how stupid of me...

14:09 technomancy: err--valid in a local name

14:10 fliebel: I guess I'll go for the multi-body fn...

14:10 scellus: it goes as a local as well :)

14:10 technomancy: fliebel: that's better if you want a default value that's non-nil.

14:12 fliebel: What is the definition of the tail position? I mean in what ways I can nest and move the recur call.

14:12 KirinDave: the-kenny: I don't think they do, at least without calling to java.

14:12 the-kenny: Let me show you my plan. :)

14:13 the-kenny: https://gist.github.com/39e337dd0e8afa822dda

14:13 Can you see what I'm up to there?

14:13 micampe: I am looking at the http-agent contrib code

14:13 what are the double-colon ::keywords?

14:14 KirinDave: micampe: They're keywords in the current namespace

14:14 rhickey: ,:foo

14:14 clojurebot: :foo

14:14 rhickey: ,::foo

14:14 clojurebot: :sandbox/foo

14:14 scellus: fliebel: clojure does not have tail recursion optimization because jvm does not support it. you can do recursion however you want, but you will use the stack. with recur and trampoline you are safe, though

14:14 fliebel: Wow, that was actually something I knew!

14:14 the-kenny: KirinDave: Looks good.

14:14 micampe: I see, namespaced keywords, thanks

14:14 KirinDave: the-kenny: Yeah, simple enough

14:15 the-kenny: Just gonna doa classic thread spawn for handing the user loop itself

14:15 Although remove-user-room isn't working and I don't get why.

14:15 the-kenny: KirinDave: Looks good.

14:15 oops sorry

14:16 fliebel: scellus: I mean using recur… Where can I place that call? It should be at the tail. But is the first argument of an if form still the tail?

14:16 micampe: now I just have to figure out when I would use those.

14:16 KirinDave: I think I am gonna do a multi-part series

14:16 Are the java SSL libraries relatively easy to work with?

14:16 it'd be cool to show a pure-clojure version of this then use a java lib to add SSL.

14:16 A real one-two-punch hitfest.

14:17 scellus: fliebel: recur can be anywhere within (loop ) afaik

14:17 micampe: KirinDave: I am interested, where are you going to post this?

14:17 KirinDave: micampe: On kirindave.tumblr.com

14:17 Did you see that node.js chat server?

14:18 ngoc: How to recur if there are 2 recursion call? I can only convert the second call to recur:

14:18 * technomancy has a cunning plan: bundle elisp in swank-clojure.jar and send it to Emacs to be eval'd upon connection.

14:18 ngoc: (defn hanoi [n from to spare]

14:18 (if (> n 0)

14:18 (do

14:18 (hanoi (dec n) from spare to)

14:18 (println n ":" from "->" to)

14:18 technomancy: so commands can be added without pushing out new versions to elpa

14:18 ngoc: (recur (dec n) spare to from))))

14:18 the-kenny: ngoc: Use lisppaste for multi-line pastes

14:18 lisppaste8: url

14:18 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

14:18 micampe: KirinDave: yes, I looked at it when you linked it earlier

14:19 KirinDave: actually, my objective is using sockets, at the moment, but that would be useful

14:19 KirinDave: technomancy: Isn't that how swank normally does it?

14:19 solussd: what is the most idiomatic way to leverage the executors framework in clojure? Is there a clojure specific way to schedule periodic thread execution?

14:20 the-kenny: solussd: I think there's scheduledThreadExecutor somewhere in java.util.concurrent. I'm using the thread-pools for a project

14:20 lisppaste8: ngocdaothanh pasted "2 recurs" at http://paste.lisp.org/display/91690

14:21 KirinDave: technomancy: Any input you have would be appreciated. :)

14:21 solussd: the-kenny: yeah, I know about the scheduledExecutorService. I was wondering if there is maybe a contirb library that clojurifies it a bit. :)

14:22 technomancy: KirinDave: no, swank-clojure expects you to get swank-clojure.el loaded into Emacs on your own. but there's no reason it needs to be installed emacs-side as long as you have slime.

14:23 ngoc: the-kenny: thanks, how to recur if there are 2 recursion call? I can only convert the second call to recur: http://paste.lisp.org/display/91690

14:24 technomancy: KirinDave: re: the gist: are you using "get" on line 8 just for readability? (you know it's not required?)

14:24 the-kenny: ngoc: I'm not very familiar with recursive function in clojure

14:24 technomancy: KirinDave: also: I'm not sure what I think about the fact that write-room has both side-effects and a return value

14:24 guess I,d need more context

14:33 michaeljaaka: hi

14:33 is there any way to check if seq is lazy?

14:33 I would like to see If groups of values in a sequence coming as a result of partition is a lazy group

14:34 seqence of these groups is lazy but groups?

14:35 ngoc: Why it is said that in Clojure Java integration is smoother and more complete than in Scala?

14:35 Chousuke: is it? :P

14:36 technomancy: ngoc: I don't think I've heard that personally.

14:36 fliebel: I have heard the same stories...

14:36 technomancy: people complain about the lack of annotations

14:36 rhickey: ngoc: I can't speak for Scala, but Clojure's algorithms all work with Java data structures, and Clojure's data strucutures implement the corresponding Java interfaces

14:37 no wrappers in either direction

14:38 fliebel: I heard Scala is proud not to implement them because they say java collections are broken.

14:38 michaeljaaka: but you have to live with Java

14:38 rhickey: fliebel: fine, but that would effect 'smooth' wouldn't it?

14:39 ngoc: From the last comment: http://codemonkeyism.com/scala-vs-clojure. I also heard this somewhere else, don't remember now.

14:39 fliebel: rhickey: I guess so, but maybe they are transparently converted or something like that.

14:40 rhickey: transparent conversion implies either a wrapper or a copy

14:40 both have problems

14:42 try both - there's no reason to rely on hearsay

14:42 arohner: ivy dumps its jars in ~/.m2, right?

14:43 KirinDave: technomancy: write-room is an agent transformer.

14:43 technomancy: So its return value should be identity in that case.

14:43 technomancy: It's used only for side effects.

14:44 ngoc: arohner: no, just checked, there's ~/.ivy2 on my machine

14:44 arohner: ngoc: thanks. Though it appears ivy also dumped the files in project/lib

14:45 KirinDave: technomancy: I haven't seen any idiom or glyph to signify something is an agent transformer.

14:45 arohner: maven / ivy make it more annoying than necessary to compile against e.g. a non-standard clojure.jar

14:46 I really don't want some random library off the internet assuming I run clojure-1.0.0.jar

14:47 KirinDave: Yay, I just need to implement commands now: http://idisk.me.com/dfayram/Public/Pictures/Skitch/Terminal_%E2%80%94_telnet_%E2%80%94_Homebrew_%E2%80%94_ttys002_%E2%80%94_80%C3%9724-20091206-114608.png

14:59 technomancy: KirinDave: makes sense; nice

14:59 KirinDave: technomancy: I guess I am going to use agent-method-name to denote agent xformers.

15:00 As goofy as it seems, I may make a macro for agent definition that just lets me group agent methods and auto-generate sending for them.

15:05 ngoc: Where can I find the roadmap of Clojure?

15:07 Chousuke: ngoc: I don't think there's a roadmap but you can read about upcoming features on the assembla wiki pages.

15:07 rhickey: ngoc: https://www.assembla.com/spaces/clojure

15:08 ngoc: Thanks a lot

15:28 KirinDave: Is there a way to unbind a symbol?

15:29 rhickey: ,(doc ns-unmap)

15:29 clojurebot: "([ns sym]); Removes the mappings for the symbol from the namespace."

15:29 KirinDave: Thanks

15:48 defn: 'lo

15:56 seths: a question on pulling items from a vector at specific indexes...

15:56 does the map function seem like a reasonable approach?

15:56 example:

15:56 (map [:boat :plane :fish] [0 2])

15:56 clojurebot: map is lazy

15:56 seths: (:boat :fish)

15:57 Licenser: hmm some kind of filter?

15:58 give me a second I've an ida

16:02 scellus: ,(map (partial nth [:boat :plane :fish]) [0 2])

16:02 clojurebot: (:boat :fish)

16:04 Chousuke: ,(map [:foo :bar :zonk] [0 2])

16:04 clojurebot: (:foo :zonk)

16:05 seths: I haven't used partial function application before. It does the trick here, but what is the advantage over Chousuke's example?

16:05 KirinDave: Hum

16:06 scellus: none i guess :)

16:06 Chousuke: there's no real difference

16:06 KirinDave: technomancy: Got a sec?

16:06 seths: good to see it in action though

16:06 thanks everyone

16:06 Licenser: wow all so much easyer then my idea o.O

16:08 KirinDave: technomancy: I borrowed a bit of code from mire, specifically your response loop

16:13 defn: is it okay to call a special form a method?

16:13 err a function

16:16 hiredman: special forms are more like macros in that they have control over the evaluation of their arguments

16:16 defn: in other words, you're at a clojure REPL, you hit b[tab], all of those things you're able to use, could you give them a single name even though there are special forms and such in there?

16:16 or is it proper to differentiate

16:17 for the purposes of documentation, let's say

16:20 hiredman: that is an interesting question

16:20 lisp certainly does not differentiate

16:20 a macro call, special form, and function all look the same

16:20 but you can't use a macro or a special form as a function object

16:21 arohner: special forms are never qualified

16:21 hiredman: hmm

16:22 arohner: I would guess they're all 'forms'

16:22 defn: see that was sort of my intuition

16:23 but im not a long-time lisper so I thought I'd ask the brotherhood

16:23 * arohner is not a long-time lisper

16:23 defn: what do you mean by never qualified

16:23 I'm not familiar with that terminology

16:23 arohner: special forms don't belong to a namespace

16:24 so they're not qualified by a namespace, like foo/bar

16:24 defn: but the builtin clojure.core stuff could all be called qualified, yes?

16:24 arohner: I didn't quite understand what you were asking when I said that, though

16:24 hiredman: there is nothing stopping them from being namespace qualified

16:25 arohner: they're not vars

16:25 hiredman: so?

16:25 arohner: ,`(map [42])

16:25 clojurebot: (clojure.core/map [42])

16:25 arohner: ,`(if [42])

16:25 clojurebot: (if [42])

16:25 technomancy: KirinDave: hey

16:25 sup?

16:26 hiredman: what defines the special form fn* is a list with the symbol fn* at the front

16:27 the symbol fn* could be replaced with the symbol a qualified symbol and what would the difference be?

16:27 scellus: special forms cannot be function args, can they?

16:27 arohner: scellus: no, they can't

16:28 (foo/fn*) doesn't make sense. It says look in the namespace foo for the var name fn*, and call it. But the special forms don't belong to a namespace. You can't refer or use or require them

16:29 namespaces only hold vars. the special forms aren't vars. They're not even functions.

16:29 hiredman: arohner: foo/fn* is just a namespace qualified symbol

16:29 scellus: special forms have no values nor the fn interface, or whatever it is called in clojure

16:29 hiredman: so the compiler could just as easily use namespace qualified symbols for special forms

16:30 arohner: yes, I can imagine a language that does that. But that's not the way clojure is today

16:30 hiredman: sure

16:31 (x y z) ;is x a special form, macro, or a function?

16:32 scellus: x is just the first item in a list - if it is evaluated, x can represented any of those, right?

16:33 rhickey: scellus:no, if x is a special form or macro it is not evaluated

16:33 hiredman: ,(@#'fn [] 1)

16:33 clojurebot: (fn* ([] 1))

16:33 scellus: rhickey: i mean if the list is evaluated

16:35 hiredman: thats kind of the point

16:36 you can't know until you evaluate the form, and even then differentiating between macros and special forms can be difficult

16:36 arohner: rhickey: I understand how if x were a special form, it would not be evaluated. But if it's a macro, don't you have to evaluate the symbol to figure out that the var points at a macro (a fn with the macro metadata set)?

16:37 polypus: i'm trying to use swank-clojure-project. so i need to have clojure and clojure-contrib jars in a lib directory and must i also havea swank-clojure jar there?

16:37 technomancy: polypus: that's correct.

16:38 scellus: arohner: yes you first check if it's a special form, then evaluate, then treat arguments according to what came out as the value of the first item. or i don't actually know what clojure does, but that's what i'd do :)

16:39 KirinDave: technomancy: I just wanted to solicit advice before I posted that code. Since I did kinda steal from mire to do it. :)

16:39 polypus: where is that jar, if i installed swank via elpa?

16:39 KirinDave: technomancy: https://gist.github.com/39e337dd0e8afa822dda

16:39 rhickey: arohner: it is examined, but something short of evaluation - i.e. you couldn't put an expression that evaluated to a macro var in the first position and get a macro call

16:40 technomancy: polypus: elpa only handles elisp dependencies; for clojure/jvm dependencies a tool like leiningen or maven is more appropriate

16:40 arohner: rhickey: ah, thanks

16:40 technomancy: polypus: but if you want to handle it by hand, just do a standalone M-x slime, and the jars will get downloaded into ~/.swank-clojure for you

16:42 seths: scellus: your answer to my question was more robust.

16:42 ,(map [1 2 3] [0 2])

16:42 clojurebot: (1 3)

16:42 seths: ,(map '(1 2 3) [0 2])

16:42 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

16:42 seths: ,(map (partial nth '(1 2 3)) [0 2])

16:42 clojurebot: (1 3)

16:43 technomancy: KirinDave: if-let on line 9 could be replaced with "or" if you're into that kind of thing, but that's largely a matter of taste.

16:43 KirinDave: I'd also rename "output" to just "out"

16:44 polypus: technomancy: ok looks like swank-clojure.jar is already in that directory. i haven't got around to exploring lein yet, that's next after i 'm comfortable with emacs. thx

16:44 technomancy: polypus: cool

16:44 KirinDave: might want to declare *username* instead of def'ing it to a dummy value.

16:44 KirinDave: technomancy: Okay.

16:44 technomancy: though I guess def'ing it makes repl-time experimentation easier. it's a trade-off there.

16:45 KirinDave: Yeah, that's why i did it. :)

16:45 technomancy: since it's pretty clear that "Someone" is a dummy value.

16:45 KirinDave: I am just adding "has disconnected" messages.

16:45 scellus: seths: yes, only collections have this fn interface or whatever it is. and a list is not.

16:45 KirinDave: And then I'll have 100% parity with the node.js example, except i have rooms.

16:45 seths: I wonder why PersistentList doesn't implement IFn?

16:45 technomancy: KirinDave: sweet

16:45 seths: ah, thx

16:45 KirinDave: And if I change that if-let to an (or) I will be the same number of lines.

16:45 technomancy: heh

16:46 KirinDave: technomancy: The only thing that bugs me

16:46 Is that repeated (let [room (make-get-room! roomname)] …)

16:46 I see it three times, feels weird.

16:47 arohner: seths: my guess is that lists don't have sub-linear lookups to their values, unlike vectors and maps

16:47 solussd: can someone explain clojure.contrib.fill-queue to me? docsstring isn't doing it. :)

16:47 technomancy: KirinDave: you could inline it in line 37 since it's only used once

16:47 if it were significantly more than three times it might justify a with-room macro

16:48 KirinDave: Yeah, at 5 times I feel like I have a pattenr.

16:48 If there were even a few more commands I would write this with a macro

16:48 But I said, "No macros for this example.?

16:48 When i wsa learning lisp, long ago, every asshole seemed to insist on a macro in their introduction

16:48 and it pissed me off when I didn't understand them.

16:48 technomancy: hehe; yeah.

16:49 because people pull them in when they're not justified

16:52 seths: arohner: is it easy/possible to make vectors and maps infinitely large, like lists with (cycle 1)?

16:52 KirinDave: Okay, now to blog about it, I guess.

16:52 Ahh, no. First, github. Can't forget these things.

16:52 seths: KirinDave: what's the blog url?

16:53 KirinDave: seths: kirindave.tumblr.com

16:53 But I won't post till tonight

16:53 I've got errands of the ikea variety. :)

16:53 arohner: seths: no. vectors and maps have to be a finite size. I believe lists have to be as well. I think only seqs can be infinite

16:54 (cycle 1) creates a lazy seq whose current value is 1, and the next value is (cycle 1)

16:55 hiredman: if you find yourself repeatedly calling nth on an infinite sequence a rethink might be in order

16:55 seths: KirinDave: great, I'll lob it into Google Reader now

16:56 KirinDave: seths: Beware. I am not what you'd call a "focused subject blog" ;)

16:56 * the-kenny like tumblr

16:57 KirinDave: God even knows what I'm frontpaging up there.

16:57 seths: But while you have greader open and adding subs, xkcdexplained.tumblr.com ;)

16:58 technomancy: _ato: I just realized that you got the first version of clojars implemented in less time than many of my elpa submissions have taken to get uploaded... not looking forward to going back to elisp hacking. =\

16:58 the-kenny: KirinDave: http://the-kenny.tumblr.com/post/257607877/evolution-of-xkcd

16:58 seths: KirinDave: done -- looks neat. enjoy ikea!

16:59 KirinDave: the-kenny: Heh. I gotta say though, I don't think she realized what she was in for with xkcdexplainedexplained

16:59 As difficult as it is to make xkcdexplained funny

16:59 Jas has got it like 10x harder.

16:59 technomancy: KirinDave: can you explain some of those earlier strips with the red spiders and such?

16:59 that would really be helpful.

17:00 the-kenny: Wait... are you involved with xkcdexplained, KirinDave?

17:02 KirinDave: the-kenny: Yes. I am "Dave" from the title.

17:02 I have written about 1/3

17:02 the-kenny: Wow, awesome. Nice to meet you :)

17:04 KirinDave: the-kenny: Ian Collins is the real guy you wanna kudos to. He has kept up with it while Toby and I have slacked off.

17:04 Of course, Toby had a family emergency and I got married.. but… there are *no excuses*

17:26 polypus: ok i've got slime working now, but if i just use plain M-x slime and i slime-eval-buffer, then i can access the symbols defined in the buffer at the repl, an if i use swank-clojure-project i can't, i get symbol undefined errors. any ideas?

17:30 technomancy: polypus: is it a problem with a hook?

17:30 polypus: you mean one i've defined?

17:30 cuz i haven't defined any

17:31 technomancy: no, I mean does the error message say something about a hook not being defined

17:33 polypus: Unable to resolve symbol: server in this context

17:33 [Thrown class java.lang.Exception]

17:33 thats all i get, with a stack trace

17:33 defn: that could be the class path no?

17:33 polypus: server was just a symbol defined in the buffer

17:33 technomancy: that's a new one to me

17:33 polypus: oh, so it connects; you get that error when you eval the buffer?

17:33 defn: polypus: how'd you install swank

17:34 clojure, etc.

17:34 did you use technomancy's elpa pkg?

17:35 polypus: yeah it conects fine. i don't get the error when i eval, i get the error when i type 'server' in the repl. server is just a symbol bound with def in the biffer. i installed with elpa

17:35 buffer*

17:35 technomancy: polypus: my guess is your buffer is in one namespace but your repl is in "user" still

17:36 polypus: doh

17:36 technomancy: C-c M-p from your code buffer will let you change the repl namespace automatically

17:39 the-kenny: I have to remember this shortcut

17:39 technomancy: it's handy

17:40 I should add it to the swank-clojure readme

17:40 even though it's technically part of slime

17:40 polypus: yeah that was it. ty

17:41 i was testing with two files one with a namespace and one without and didn;t notice

17:42 * technomancy is not a fan of files that don't declare a namespace

17:42 technomancy: but they exist

17:44 MikeDev: Is a macro just like a #DEFINE in C?

17:44 hiredman: no

17:44 seths: Surrounding a symbol with * like *this* means this is a "global"? does it imply mutability?

17:45 polypus: it would be pretty cool to get slime working over http to access a running web app in emacs. is this possible yet?

17:45 technomancy: seths: not mutability per se, but it does imply that the var will be rebound to another value using binding.

17:45 MikeDev: This: http://clojure.org/macros is not helpful

17:45 technomancy: polypus: you can connect to compojure (etc) apps just fine, but it doesn't work over HTTP

17:45 you either need to be local or tunnel over SSH

17:46 polypus: yeah, i was thinking in cases where you only have http access with managed hosting or something

17:46 _ato: MikeDev: it is in the sense that it replaces code just with other code before it is compiled. It's not in that a macro can contain any Clojure code and the replacement happens with data structures not text. A lisp macro is a lot more powerful and more regular than a C macro.

17:47 technomancy: polypus: oh for like google app engine or something? maybe.

17:47 polypus: exactly

17:47 seths: MikeDev: agreed that page is not a great introduction. I refer to one of Chouser's blog posts at: http://blog.n01se.net/?p=33

17:48 Also the Programming Clojure book by Halloway has a good chapter on them

17:48 MikeDev: This is kinda for a homework assignment

17:48 fair disclojure

17:48 technomancy: polypus: no reason why it couldn't be done... are you volunteering? =)

17:48 seths: You can get an ebook of it I think

17:48 MikeDev: using Clojure for homework?

17:49 polypus: technomancy: maybe after i'm over the noob hump :)

17:49 hiredman: someone did a blog post about getting slime to connect to the appengine dev server

17:49 technomancy: polypus: unfortunately it would involve writing some elisp too.

17:49 hiredman: so you can do local developement at the repl

17:49 technomancy: oh cool

17:49 _ato: http://www.hackers-with-attitude.com/2009/08/intertactive-programming-with-clojure.html

17:49 MikeDev: seths, I am doing exercise for a possible job

17:50 hiredman:

17:50 polypus: yeah i saw that blog post. that's pretty good but only local

17:51 MikeDev: the 2nd exercise looks like I'm just supposed to write a macro that will plug in a name and value and replace it with a macro's value for it

17:51 which would seem trivial

17:51 compared to the first exercise

17:51 seths: MikeDev: best of luck! I'm hoping to land a Clojure day job in 6 months to a year or so.

17:51 technomancy: so if I recommend that swank be started from the shell and just connected to via M-x slime-connect, I'll be able to sidestep the entire elisp installation process

17:51 thoughts?

17:52 (started using leiningen or clojure-maven-plugin, etc)

17:56 seths: technomancy: is it easy to start swank on Windows?

17:57 technomancy: seths: I don't know.

17:57 someone ported the leiningen 0.5.0 launch script to powershell

17:57 but I don't think it's been updated for 1.0

17:57 clojure-maven-plugin could probably do it

17:58 seths: technomancy: I guess it doesn't matter as long as it doesn't block the shell. At work I survive Windows by using shell in Emacs

17:58 solussd: hmm.. how do you "remove" items from a fill-queue?

17:58 hiredman: powershell or just a bat file?

17:58 MikeDev: it look like macros are imperative

17:58 technomancy: hiredman: I think it was powershell. I didn't really look at it closely since he never contacted me about submitting it to leiningen proper.

17:58 MikeDev: defn count-and-print-words

17:58 hiredman: interesting

17:58 technomancy: seths: on windows I would still recommend launching it from within Emacs with M-x swank-clojure-project

17:59 at least until leiningen gets ported

17:59 MikeDev: i could use syntax colors

18:02 what is a macro's docstring and attribute map?

18:03 Chousuke: MikeDev: (defmacro foo {:metadata 'here} "docstring" [args] ...)

18:03 seths: MikeDev: strongly recommend $21 ebook for Programming Clojure: http://pragprog.com/titles/shcloj/programming-clojure

18:04 patrkris: Hey. What is the easiest way of traversing the XML data that clojure.xml/parse spews out? For instance, if I want all instances of a certain tag? By using filter/map and the like, or is there some cool/advanced functions specifically for XML?

18:05 MikeDev: zipper?

18:05 hiredman: tree-seq and filter are nice for that

18:06 patrkris: wow... and that was *really* hard finding online... I have to look better next time ;)

18:06 hiredman: (filter #(= :some-tag (:tag %)) (tree-seq map? (comp seq :content) xml))

18:06 patrkris: hiredman: thanks man

18:07 rhickey: patrkris: http://richhickey.github.com/clojure-contrib/zip-filter-api.html

18:07 patrkris: rhickey: yeah, i just stumpled upon that - I should really learn to use search engines

18:09 michaeljaaka: hi

18:09 can (map #(partition 2 (read-data (data-reader %))) inter-files) be turned into (map #(-> % data-reader read-data (partition 2)) inter-files) ?

18:10 right now I get error #<CompilerException java.lang.RuntimeException: java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer (test1.clj:0)>

18:10 hiredman: michaeljaaka: what does -> do?

18:11 MikeDev: annoys me

18:11 michaeljaaka: takes argument and applies functions passing result to the next

18:12 (defn zz[x y] (+ x y )) (-> [ [ 1 2 ] [ 2 3 ] ] first second (zz 3) ) gives 5

18:12 hiredman: michaeljaaka: and how does it do that?

18:12 specificly in the more complicated case of, for example, (-> x (a b))

18:14 michaeljaaka: well it will pass x as argument to a list

18:14 (a b)

18:14 (a b x)

18:14 hiredman: michaeljaaka: that is wrong

18:14 MikeDev: ,(a b x)

18:14 clojurebot: java.lang.Exception: Unable to resolve symbol: a in this context

18:15 hiredman: ,(macroexpand-1 '(-> x (a b)))

18:15 clojurebot: (a x b)

18:15 hiredman: ,(macroexpand-1 '(->> x (a b)))

18:15 clojurebot: (a b x)

18:15 MikeDev: ,(kill closurebo)

18:15 clojurebot: java.lang.Exception: Unable to resolve symbol: kill in this context

18:15 hiredman: MikeDev: I can arrange for clojurebot to ignore you

18:17 michaeljaaka: hmmm, well I will have to switch to clojure 1.1

18:17 I miss the ->>

18:17 polypus: looks like somebody has already messed around with the idea of slime over http in common lisp:

18:17 http://avodonosov.blogspot.com/2008/01/it-is-problematic-at-first-sight-to-use.html

18:17 hiredman: michaeljaaka: or change the argmuent order expected by partition

18:17 seths: michaeljaaka: consider using leiningen to help you switch to clojure 1.1

18:17 hiredman: ,(macroexpand-1 '(-> x ((partial partition 2))))

18:17 clojurebot: ((partial partition 2) x)

18:17 seths: I could not be happier, using it to run tests, package code, get dependencies...

18:18 michaeljaaka: ok, I will try it

18:20 hiredman: wow thanks

18:20 it helped

18:26 seths: would a code coverage tool make any sense for a Clojure codebase? Would lazy evaluation be a complication?

18:26 michaeljaaka: hiredman: btw. which style do you prefer?

18:26 nesting functions or use of ->

18:27 nesting calls actualy

18:27 MikeDev: what is the rationale for requiring that everything be a list?

18:28 Chousuke: what do you mean? :/

18:28 MikeDev: (func a b)

18:28 Chousuke: Not everything is a list in Clojure.

18:28 MikeDev: Why does that have to be in a list

18:28 Chousuke: why not?

18:28 it's a neat representation for a function call

18:28 MikeDev: why not func a b

18:29 Chousuke: but that's a list too

18:29 MikeDev: works in ML

18:29 Chousuke: just without the parens

18:29 michaeljaaka: because it is LISP

18:29 list processing language

18:29 ;)

18:29 MikeDev: ah

18:29 Chousuke: non-parenthesised syntax wouldn't be homoiconic

18:29 rhickey: http://en.wikipedia.org/wiki/Homoiconicity

18:30 MikeDev: I'm afraid to look in a public place

18:30 Chousuke: :P

18:30 michaeljaaka: it is a beauty of that lang

18:30 hiredman: michaeljaaka: I use -> a lot

18:31 michaeljaaka: I like the statment: show data structure and when going to the syntax you say: hay you already seen it

18:32 hiredman: -> seems to be more declarative

18:32 Chousuke: MikeDev: Clojure code is made of lists and vectors and such things, and the parenthesised form is just the visual representation.

18:32 michaeljaaka: you say do that that that having rule of result is an argument of the next func

18:32 with nested calls it seems to feel more imperative

18:33 so I will to use -> now

18:33 too

18:33 Chousuke: MikeDev: you could "write" lisp code in C++ without ever seeing (foo bar) by forming all lists and other data structures programmatically, but that would be rather tedious

18:34 MikeDev: I think I need to understand this: http://sardakcode.blogspot.com/2009/02/my-first-clojure-macro-inspired-by.html

18:34 Chousuke: MikeDev: I think the parenthesised syntax was chosen because it was plainly the simplest possible textual representation of a list.

18:38 MikeDev: why is the & there?

18:38 (defmacro over[coll var-name & body]

18:39 Chousuke: it's the rest arg

18:40 ,((fn [a b & c] [a b c]) 1 2 3 4 5 6)

18:40 clojurebot: [1 2 (3 4 5 6)]

18:42 MikeDev: what's the deal with the ~

18:42 Chousuke: it's unquote

18:42 hiredman: clojure.org/reader

18:42 Chousuke: a feature specific to syntax-quote, not macros

18:42 ,(let [x 5] `(x ~x))

18:42 clojurebot: (sandbox/x 5)

18:43 MikeDev: i have no idea what happened there

18:43 Chousuke: it returned a list

18:43 with a symbol and a number

18:44 ,'(x 5); kind of like this

18:44 clojurebot: (x 5)

18:44 MikeDev: so it let x=5

18:44 Chousuke: yeah

18:44 and then constructed the list

18:44 hiredman: MikeDev: I have to ask, are you sure a job where you write clojure is the best thing for you?

18:45 MikeDev: it's a starting job

18:45 not senior

18:45 Chousuke: sure it is! Once you get to know Clojure better :)

18:45 the key point to understanding macros is realising that clojure code is never text

18:46 it has a textual representation, but that's not clojure code until it has been transformed into data structures by the reader

18:46 MikeDev: besides, my halfassed qualification is knowing ML and functional programming concepts in general

18:46 ML didnt have macros AFAIK

18:47 Chousuke: Most languages that have macros are lisp-derivatives

18:48 though I guess there might be some others that have a similar macro system but are not based on s-exprs

18:48 MikeDev: Bob Harper was my teacher and he hated Java

18:48 lol

18:50 seths: I am still trying to see the difference between C macros and Lisp macros

18:50 MikeDev: so if you do `() it treats the whole thing as a string which is only escaped by ~

18:50 for variables

18:50 seths: The C preprocessor enables plenty of unhygenic evil...

18:50 MikeDev: Kinda like "Blah $MyVar" in PHP

18:51 `(Blah ~MyVar)

18:51 Chousuke: seths: C macros are just search-and-replace :P

18:51 MikeDev: it's *not* treated a string

18:52 that's the key point to understand. it's a list.

18:52 not a string.

18:53 MikeDev: then it's `(Blah ~MyVar) is like ("Blah" MyVar)

18:53 Chousuke: hm

18:54 (let [x 5, form '`(x ~x), evaled-form `(x ~x)] [form, evaled-form])

18:54 ,(let [x 5, form '`(x ~x), evaled-form `(x ~x)] [form, evaled-form])

18:54 clojurebot: [(clojure.core/seq (clojure.core/concat (clojure.core/list (quote sandbox/x)) (clojure.core/list x))) (sandbox/x 5)]

18:54 Chousuke: the ` reader magic generates code that constructs a list at runtime

18:54 it doesn't generate strings

18:54 when that code is evaluated, it forms the evaled-form you see there

18:55 (if x happens to be 5 in the environment)

18:56 it's very handy in macros, because it allows you to write "template-like" code

18:57 MikeDev: why form '`(x ~x) and not form `(x ~x)

18:58 Chousuke: but you could just as well write all macros like (defmacro foo [x] (list '+ x 6 'y))

18:58 MikeDev: to show you what `(x ~x) expands to at read-time

18:58 the ' prevents the evaluation

18:59 but, if you had a macro like foo there, and called (foo 42), it would expand to the code (+ 42 6 y) which would be evaluated in its place

19:00 again, no strings involved.

19:00 MikeDev: yeah seqences, cats and lists

19:01 Chousuke: well, symbols and numbers too.

19:01 MikeDev: oh those are functions

19:01 Chousuke: yeah

19:01 MikeDev: ok

19:01 Chousuke: clojure macros are functions of arbitrary arguments that output lists, vectors or maps... that is, clojure code.

19:02 you could technically write a Clojure macro in java.

19:02 kind of, anyway. it could be a static method that takes some parameters and returns a PersistentList

19:03 you could then eval the result

19:03 the trick with macros created with defmacro is, the function is marked special so that the clojure compiler does the evaluation for you.

19:03 MikeDev: yes and that is what the exercie is about

19:04 having clojure use a macro do evaluation for you

19:04 so if I understod macros, this would take 5 minutes

19:05 Chousuke: macros are really simple when you finally get them

19:06 MikeDev: do you know ML?

19:06 Chousuke: but I guess if you're used to languages where code is text instead of data, learning what "code is data" means and why it matters (and why it enables a macro system) takes a while

19:07 no :/

19:07 _ato: heh yeah, I avoided macros when learning common lisp because everyone said they were "black magic" and "confusing" and such. When I started using Clojure, it was basically a "Oh is that all you have to do? Why all the fear?" moment

19:07 they're so much simpler than metaprogramming in most other languages

19:07 Chousuke: I guess the problem is complicated further by the fact that most clojure code is still stored as text

19:08 so it's easy to be fooled into thinking that everything is like with other languages... namely, that text files go to the compiler/interpreter and you get program output.

19:09 MikeDev: what is @ for

19:09 michaeljaaka: @--->---

19:09 Chousuke: it's a splicing unquote

19:09 MikeDev: pretty flower?

19:09 Chousuke: ,(let [a [1 2 3]] `(5 ~@a))

19:09 clojurebot: (5 1 2 3)

19:10 michaeljaaka: yes it is

19:10 solussd: what the heck is (ensure ...) for?

19:11 MikeDev: Vitamin Supplementation for Seniors?

19:12 _ato: solussd: ensure protects a ref from modification during a transaction.

19:12 hiredman: solussd: you can ensure that your transaction is retried if a ref that you don't write to is modified

19:14 solussd: I guess I don't understand how that is different than a regular dosync transaction

19:14 like alter

19:15 hiredman: ,(dosync (alter a + @b))

19:15 clojurebot: java.lang.Exception: Unable to resolve symbol: a in this context

19:15 Chousuke: alter actually modifies the ref :P

19:15 hiredman: well

19:15 cark: kind of the same, only it won't retry as often

19:15 hiredman: (dosync (alter a + @b))

19:15 Chousuke: ensure is for the case where you read a ref in a transaction and depend on the value still being the same during the rest of the transaction

19:16 solussd: so it retrries it if b changes?

19:16 ah i c

19:16 Chousuke: if you were modifying some other refs based on the read value for instance.

19:17 solussd: interesting... wonder how many times I should have used ensure.. :)

19:20 so ensure goes around the ref that might be changing? e.g. (dosync (alter a + (ensure b))) ?

19:20 _ato: yep

19:25 MikeDev: Chousuke, can I PM you something?

19:27 Chousuke: MikeDev: if it's quick. I'm going to sleep soon

19:32 solussd: anyone here familiar with fill-queue ?

19:32 chouser: solussd: I might be

19:34 solussd: it generates a lazy-seq from a filler function you provide to it- I want to use it as a queue for a bunch of worker threads- How do I "pop" an element off of it? Can I just swap! in a replacement if I access it from an atom?

19:35 chouser: hm...

19:35 I suppose you could.

19:35 you might consider using a Java BlockingQueue directly.

19:36 solussd: if I have a filler function filling it full of files, I dont want it to grow forever

19:36 what is fill-queue intended for?

19:38 chouser: solussd: it's designed to allow inversion of control, when you want normal seq-consuming code to be able to use value from a stateful/imperative value-producing loop.

19:38 solussd: here's a Clojure direct use of a BlockingQueue: http://paste.lisp.org/display/91574

19:40 solussd: thanks

20:08 MikeDev: does closurebot not let you define macros?

20:11 (defmacro over[coll var-name & body]

20:11 `(doseq [~var-name ~coll] ~@body))

20:15 the-kenny: Is there a reason why you want to define such a macro?

20:16 somnium: the-kenny: for the sheer joy of syntax twiddling?

20:16 the-kenny: somnium: hm yeah.

20:17 MikeDev: the-kenny, I'm doing a macro excerise

20:22 chouser: MikeDev: clojurebot doesn't let you def anything

20:24 MikeDev: k

21:36 arohner: any emacs hackers around? I'm curious about the difference between hooks and advice

21:43 shrughes: http://www.gnu.org/software/emacs/manual/html_node/emacs/Hooks.html

21:43 "A hook is a Lisp variable which holds a list of functions, to be called on some well-defined occasion."

21:44 advice is much ickier

21:47 arohner: I'm thinking about writing a hooks library, and I'm wondering if it's clojure-y

21:47 or whether I'm thinking about this wrong

21:53 shrughes: the user could just use a var in many cases

21:58 arohner: yeah, but not in all cases. I have a data-driven system, and I want to build up the definition of a function based on the data

22:38 solussd: how is the future function suppose to be used?

22:38 It does not seem to evaluate its body 'in the future' but when it is defined

22:39 hiredman: nope, it does it in the future

22:39 solussd: i tried this: (def myatom (atom 1)) (def myfuture (future (swap! myatom inc)))

22:40 hiredman: and?

22:40 solussd: myatom is 2 after the myfuture def

22:40 i know im missing something obvious. :)

22:40 hiredman: there is a race condition in your brain

22:40 solussd: damn brain

22:41 hiredman: swap! is fast

22:41 (not really, but faste enough when talking about human perception)

22:42 solussd: oh.. no. .i was thinking future doesnt execute it's body until it is dereferenced

22:42 i see what you're saying

22:42 hiredman: nope

22:42 solussd: well that makes a lot more sense now. :)

22:42 thans

22:42 *thanks

22:42 hiredman: future is like do-async

22:42 rhickey: ,(do (future (Thread/sleep 1000) (prn 42)) (prn 41))

22:42 clojurebot: 41

22:43 chouser: thread-local binding of *out* strikes again.

22:43 hiredman: :P

22:43 clojurebot printed 42 at its repl

22:45 chouser: heh

22:47 solussd: are 'future' bodies always executed in their own thread or is there a thread pool they share?

22:47 e.g. if I kick off 50 of them

22:47 hiredman: the use the send-off threadpool

22:47 they

22:47 solussd: so it grows

23:09 technomancy: arohner: run-hooks is implemented similarly to just (doseq [h my-hook] (apply h))

23:09 in Emacs at least

23:09 there's not a lot to it

23:13 KirinDave_: have you tried htmlize.el for putting code in blog posts?

23:14 KirinDave: technomancy: No. I had a huge hassle for even doing that much

23:14 technomancy: arohner: your implementation is nicer than Emacs' since the hook itself is callable instead of just being a list.

23:14 KirinDave: Honestly, tumblr is totally terrible for code.

23:15 technomancy: I use htmlize for all my blog code

23:17 KirinDave: technomancy: Does that even work with aquamacs?

23:19 technomancy: Well, either way tumblr doesn't allow gist-style embeds or stylesheets, so it's totally balls for code pasting, I guess.

23:21 technomancy: oh, heh. yeah you're gonna need a stylesheet for code; no way around that

23:21 KirinDave: Grumblecakes.

23:22 I didn't know about htmlize tho, thank for the tip.

23:22 technomancy: that's crazy that a blogging service even exists that doesn't allow you to add styles though

23:22 I guess it's this new minimalism thing that everyone's been talking about+

23:22 ?

23:23 KirinDave: You can manipulate the stylesheet manually

23:23 but you can't add style tags to posts and shit.

Logging service provided by n01se.net