2009-12-06
| 00:01 | ngoc | I think filter must be used instead of map? |
| 00:01 | ngoc | Because of the condition |
| 00:03 | somnium | ngoc: (filter identity (map (fn [a b] (when test [...])) seq1 seq2)) |
| 00:13 | technomancy | Leiningen 1.0 released: http://github.com/technomancy/leiningen/blob/1.0.0/NEWS |
| 00:16 | slyrus | technomancy: congrats |
| 00:34 | replaca | congrats, technomancy! Leiningen is another great step forward for Clojure |
| 00:53 | DeusExPikachu | I just gotta say, clojure has beautiful reader syntax, it feels natural |
| 00:54 | DeusExPikachu | I suppose I feel that way because I'm coming from some common lisp background... |
| 01:11 | ngoc | I think Lein is feature-complete if live-repl is integrated: http://github.com/djpowell/liverepl |
| 01:22 | mtm_ | technomancy: congrats on 1.0 |
| 01:26 | msingh | has anyone experimented with clojure on a blackberry? |
| 01:54 | slyrus | is there a good directory of various available clojure libraries (besides clojure-contrib)? |
| 01:54 | _ato | http://clojure.org/libraries has some |
| 01:55 | slyrus | thanks! |
| 01:55 | slyrus | (I suppose I should have thought of looking there...) |
| 02:18 | ataggart | anyone awake that's played around with extend-* in the new branch? |
| 05:15 | the-kenny | Is there a library for refactoring lisp-code for emacs? |
| 06:17 | fliebel | How much optimization is done while compiling Clojure? |
| 06:34 | cark | i believe not much |
| 06:34 | cark | isn't that the work of hotspot anyways ? |
| 06:34 | cark | work/job |
| 06: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. |
| 06:44 | fliebel | But the same thing might be useful for regexes, templates or other stuff. |
| 06:44 | cark | don't you think hotspot does it ? i don't know much about it but that seems quite easy |
| 06:45 | fliebel | But then it has to do it every time the file is ran, right? |
| 06:45 | cark | i think literal regexes are compiled only once |
| 06:46 | cark | ah you're using clojure as a scripting language ? |
| 06:46 | fliebel | I'm not using Clojure at all at the moment actually... |
| 06:46 | cark | among the dynamic languages, clojure is pretty good perfomance-wise |
| 06:47 | fliebel | I figured that. :) |
| 06:47 | angerman | ~source re-seq |
| 06: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. |
| 06:48 | cark | heh compiler macros =P |
| 06:49 | cark | we don't have that |
| 06: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. |
| 06:50 | cark | what's the use case you're investigating clojure for ? |
| 06:51 | cark | well yes you can do that (if i understand you correctly) ... have a look at memoize |
| 06: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. |
| 06:52 | cark | oh man you don't need to optimize anything for a web app =) |
| 06:52 | cark | unless you're facebook or something |
| 06:53 | fliebel | It's not even a web app… :$ I intend to produce static html form source and template files. |
| 06:53 | cark | oh i see |
| 06:53 | cark | well it's very possible to do this with macros |
| 06:53 | cark | tho i think most html libraries do it with functions |
| 06:53 | cark | in clojure i mean |
| 06:54 | cark | there are macro based html libraries in CL |
| 06: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. |
| 06:55 | cark | well that's an easy project, macro based html template, good for learning |
| 06:55 | fliebel | Hmhm, but so far I failed... |
| 06:55 | cark | oh what's the problem point ? |
| 06:56 | fliebel | I want to do impossible thing… at least for a beginner like me. |
| 06:57 | angerman | technomancy: can I add jvm arguments to lein swank? |
| 06:57 | cark | if you have some specific question, i'm pretty sure you'll find help in this channel |
| 06:57 | tomoj | what is the point of generating static html with macros instead of functions? |
| 06:57 | fliebel | tomoj: fun, and possibly speed… |
| 06:58 | fliebel | or at least a nicer looking template language. |
| 06:58 | tomoj | what I mean is that I think speed is irrelevant for this use case |
| 06:58 | fliebel | I agree |
| 06:58 | tomoj | at least the difference between macros and functions is irrelevant |
| 06:58 | cark | right, even using functions, you can always memoize and you can't go much faster than that |
| 06:58 | tomoj | I guess you've seen compojure's html language? |
| 06:58 | clojurebot | compojure is http://github.com/weavejester/compojure/tree/master |
| 06:59 | fliebel | no, don't think so. |
| 06:59 | tomoj | if you think of a nicer looking language, let me know :) |
| 07:00 | tomoj | of course personally I'd rather use actual html and manipulate it with enlive |
| 07:00 | cark | i liked cl-who |
| 07:01 | opqdonut | hrgh, cl-who was a hack |
| 07:01 | cark | the syntax was nic |
| 07:01 | cark | e |
| 07:01 | opqdonut | yes |
| 07:01 | opqdonut | but the implementation was horrible, side effects and all |
| 07:01 | tomoj | do you like compojure's html syntax? |
| 07:01 | cark | i don't like the parameters as map in compojure |
| 07:02 | tomoj | I guess vectors and maps can look pretty inscrutable |
| 07:02 | opqdonut | i understand it was because they wanted to avoid first building the whole syntax tree and then outputting html |
| 07:02 | cark | i think it's more because he wanted speed |
| 07:02 | cark | edi is a pretty good programmer i think |
| 07:03 | cark | tho i had to do a function based html library in cl =P |
| 07:03 | cark | same syntax as cl-who, but functions |
| 07:03 | fliebel | Is there some sort of 'with' macro that lets me use a lot of functions that would otherwise clutter the current namespace? |
| 07:03 | tomoj | I guess sexp-based html templating is a touchy topic |
| 07:04 | fliebel | tomoj: why? |
| 07:04 | tomoj | well, maybe most everything is a touchy topic in our area |
| 07:04 | tomoj | but some people love it, some people think it's totally stupid |
| 07:04 | cark | hehe i guess =) |
| 07:04 | cark | i love sexp based html |
| 07:04 | cark | so much easier |
| 07:05 | fliebel | tomoj: I acutally wanted to do the sexp approach… |
| 07:05 | tomoj | cark: just curious, have you looked at enlive? |
| 07:05 | tomoj | (and if so, what do you think?) |
| 07:05 | cark | i glanced at it from a distance... looks like a good one |
| 07:05 | fliebel | But that leaves me with the problem of how to define so many functions properly. |
| 07:05 | tomoj | so far I have only used enlive for screen scraping but the approach for templating really appeals to me |
| 07:06 | tomoj | well, not really a problem in clojure |
| 07:06 | cark | fliebel : explain better what you want |
| 07:06 | tomoj | you only need one function, html |
| 07:06 | cark | in a function scope ? |
| 07:06 | tomoj | the argument to this function can be a vector |
| 07:07 | tomoj | don't have to make fake functions for the various tags, just [:tag-name contents] |
| 07:07 | tomoj | though that may look ugly to you :/ |
| 07:07 | fliebel | indeed |
| 07:08 | fliebel | even worse, you would nee [:tag {:attr "value"} content] |
| 07:08 | fliebel | *need |
| 07: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 |
| 07:09 | fliebel | what do you mean? |
| 07:09 | tomoj | you want something like (html (h1 "foo") (p "bar baz")) ? or what? |
| 07:09 | cark | you could make it [:tag :attr1 "val" :attr2 "val" "content"] |
| 07:09 | fliebel | tomoj: yea, something like that I guess |
| 07:10 | fliebel | cark: how would you distinguish between attributes and content? |
| 07:10 | tomoj | if html is a function that seems doomed to me |
| 07:10 | cark | fliebel : as long as you have keyword value pair, it's attributes, after that it's content |
| 07: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 :( |
| 07:11 | tomoj | compojure is like (html [:h1 "foo"] [:p "bar baz"]) |
| 07:11 | fliebel | how about this: make html a macro that transforms (a content) to (tag "a" content) that would leave you with one function. |
| 07:12 | tomoj | yeah, that doesn't sound too bad |
| 07:12 | tomoj | except.. |
| 07:12 | tomoj | this transformation would need to be recursive to be useful, no? |
| 07:12 | fliebel | yea... |
| 07:12 | tomoj | and that means you can't call actual functions anywhere inside this html macro? |
| 07:12 | cark | well that's only a matter of walking the tree |
| 07:13 | cark | you need special syntax, hum that's ugly |
| 07:13 | tomoj | whereas with compojure we can say (html [:h1 (some-func "foo")]) for example |
| 07: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? |
| 07:13 | fliebel | tomoj: good point :S |
| 07:13 | the-kenny | If so: there is already a library in contrib to do that. |
| 07:15 | fliebel | the-kenny: using vectors and :keywords? |
| 07:15 | the-kenny | fliebel: Yes |
| 07:15 | the-kenny | (prxml [:p {:class "greet"} [:i "Ladies & gentlemen"]]) |
| 07:15 | the-kenny | -> ; => <p class="greet"><i>Ladies & gentlemen</i></p> |
| 07:15 | fliebel | the-kenny: I was thinking about some magic with functions and macros, but it seems impossible, or at least hard. |
| 07:16 | the-kenny | fliebel: Nothing is impossible in a lisp |
| 07: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 |
| 07:17 | fliebel | the-kenny: But it could be impossible for a beginner like me... |
| 07:18 | the-kenny | fliebel: But you can learn ;) |
| 07:19 | fliebel | I was discussing how to do it with those guys... |
| 07:20 | the-kenny | hm... sorry if I interrupted you |
| 07:20 | fliebel | A key problem with the function approach is that there might be naming clashes with built in functions. |
| 07:21 | fliebel | or you would need to define a subset of tags or lose the ability to call functions in the macro |
| 07:22 | the-kenny | Why not use keywords for tags? |
| 07: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. |
| 07:26 | fliebel | 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. |
| 07:27 | the-kenny | I don't think it's ugly. It's almost perfect for this use case |
| 07:27 | tomoj | the ugliness is what, the extra :? |
| 07:27 | tomoj | and I guess square brackets instead of parentheses? |
| 07: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 ;) |
| 07:29 | fliebel | mostly, yes… Of course I could use that, but I like to try out what is possible with a language. |
| 07:29 | the-kenny | tomoj: I think it would be possible to avoid the parenthesis with some magic in a macro |
| 07:30 | the-kenny | s/parenthesis/square brackets/ |
| 07:30 | fliebel | the-kenny: how? |
| 07:30 | tomoj | well, that's the problem |
| 07:30 | tomoj | if you really want paretheses instead of square brackets, seems to me you lose the ability to call functions inside your template |
| 07:30 | tomoj | which makes me think that vectors are perfect :) |
| 07: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 |
| 07:31 | the-kenny | (and then evaluate it) |
| 07:31 | tomoj | ah, but possible conflicts where the tag you want is actually a function? |
| 07:31 | the-kenny | But vectors are easier :) |
| 07:31 | tomoj | yap |
| 07:31 | fliebel | the-kenny: that is what i was thinking about, but how do I do that? is the something like 'function-exists?'? |
| 07:32 | the-kenny | tomoj: I'm talking about keywords + parenthesis. I don't think there will be conflicts |
| 07:32 | tomoj | ah yes |
| 07:32 | the-kenny | fliebel: I'm sure there is. |
| 07:32 | tomoj | that works I suppose as long as you don't use a keyword as a function |
| 07:32 | the-kenny | (Or it's simple to write one) |
| 07:32 | tomoj | and that would be a particularly daft thing to do when it looks just like a tag |
| 07:32 | the-kenny | tomoj: Heh yeah, that will break it |
| 07:32 | cark | ,(fn? seq) |
| 07:32 | clojurebot | true |
| 07:32 | the-kenny | ,(:foo {:bar 42 :foo 23}) |
| 07:33 | clojurebot | 23 |
| 07:33 | the-kenny | That won't be possible |
| 07:33 | cark | i think keywords as tag is cool because of the syntax coloring in emacs |
| 07:33 | tomoj | vectors are indeed easier, of course |
| 07:33 | fliebel | hmhm |
| 07:33 | the-kenny | cark: that's another argument for keywords :) |
| 07:33 | clojurebot | for is not a loop |
| 07:33 | the-kenny | bad clojurebot, bad. |
| 07:34 | fliebel | how would i transform (a) to (tag a) with a macro |
| 07:34 | fliebel | ? |
| 07:36 | tomoj | maybe something like (defmacro the-macro [& body] (map #(conj % 'tag) body)) |
| 07:37 | tomoj | no.. |
| 07:37 | tomoj | need a list or something |
| 07:37 | tomoj | otherwise the first (tag ...) will be called as a function |
| 07:38 | Chousuke | ,(conj '(a) 'tag) |
| 07:38 | clojurebot | (tag a) |
| 07:38 | Chousuke | like that. |
| 07: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? :) |
| 07:39 | Chousuke | doto? |
| 07:39 | Chousuke | ,(macroexpand '(doto a b c)) |
| 07:39 | clojurebot | (let* [G__6085 a] (b G__6085) (c G__6085) G__6085) |
| 07:40 | Chousuke | hm |
| 07:40 | thomaslee | Chousuke: I think that might be close enough to what I'm after |
| 07:40 | Chousuke | usually used with mutable java stuffthough |
| 07:40 | thomaslee | well that's what I'm doing here :) |
| 07:40 | thomaslee | working with a URLConnection object |
| 07:41 | thomaslee | calling all sorts of horrible setters and stuff |
| 07:41 | Chousuke | yeah |
| 07:41 | Chousuke | that's what doto is for |
| 07:41 | thomaslee | thanks very much! |
| 07:41 | clojurebot | much is permittted |
| 08:48 | fliebel | can I use doto on Clojure functions? |
| 08:49 | Chousuke | sure. |
| 08:49 | Chousuke | it's just (doto x .method (f args)) |
| 08:49 | fliebel | But how do java classes map to clojure and the other way around? I guess something with namespaces? |
| 08:49 | Chousuke | hm? :/ |
| 08:51 | fliebel | Well, in Java everything is organized in packages and classes, so you can do java.package.class.method, in clojure… ? |
| 08:51 | _ato | clojure.namespace/function |
| 08:52 | Chousuke | for java static methods, you'd do java.package.class/staticMethod |
| 08: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)) |
| 08: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? |
| 08:53 | Chousuke | fliebel: um, no. |
| 08:54 | Chousuke | fliebel: doto is for calling functions or methods on its first argument. |
| 08:54 | Chousuke | that expression would become (do (function1 clojure.user "bla") ...) which makes no sense |
| 08:55 | fliebel | so it becomes (.getitem class argument) but getitem is no valid clojure method is it? |
| 08:55 | Chousuke | fliebel: but .getitem is a method symbol |
| 08:55 | Chousuke | because it has the leading . |
| 08:56 | Chousuke | so (doto x .foo bar) becomes (do (.foo x) (bar x) x) which is completely valid clojure code |
| 08:56 | _ato | clojure namespaces are not java classes, they behave completely differently |
| 08:56 | Chousuke | and x is not a java class, but an object |
| 08:56 | Chousuke | though it can be a Class object :P |
| 08:57 | fliebel | wait a moment… *grinding gears* |
| 08:58 | fliebel | so doto is just a temporarily partial? |
| 08:58 | Chousuke | doto is just a macro for avoiding repetition in cases where in java you'd do: |
| 08:58 | _ato | no, doto is a macro, it just rewrites the code at compilation time |
| 08:58 | Chousuke | x.foo(); x.bar(); x.foobar(); |
| 08:58 | Chousuke | which with doto is (doto x .foo .bar .foobar) |
| 08:59 | Chousuke | and doto returns x |
| 08:59 | fliebel | so it is of no particular use in clojure? |
| 08:59 | Chousuke | sure it is. |
| 08:59 | fliebel | with clojure code i mean |
| 08:59 | Chousuke | when dealing with mutable java objects, mainly |
| 09:00 | _ato | it is less useful, if you're writing functional code |
| 09:00 | _ato | but you could do something like: (doto some-agent (send foo) (send bar)) |
| 09:01 | fliebel | :( I was actually looking for the opposite :D like (do-with foo bar egg) -> (do (foo bar) (foo egg)) |
| 09:02 | _ato | (doseq [x [bar egg]] (foo x)) |
| 09:02 | _ato | or (map foo [bar egg]) if you care about the return value |
| 09: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? |
| 09:03 | fliebel | map has a cooler syntax in my opinion, i don't get doseq. |
| 09:03 | Chousuke | angerman: reify can't extend classes |
| 09:03 | Chousuke | only interfaces |
| 09:03 | _ato | angerman: you want proxy |
| 09:03 | Chousuke | (Object is an exception) |
| 09:04 | angerman | Hm. but I thought proxys performance was questionable |
| 09:04 | Chousuke | use gen-class then |
| 09:05 | fliebel | Is map recursive? |
| 09:05 | _ato | fliebel: you mean if you have nested lists? no |
| 09:06 | fliebel | ato: yea, that is what I mean… how can I do that? |
| 09:06 | _ato | ,(map inc (flatten [[1][[[2]][3]])) |
| 09:06 | clojurebot | Unmatched delimiter: ) |
| 09:06 | _ato | ,(map inc (flatten [[1][[[2]][3]]))) |
| 09:06 | clojurebot | Unmatched delimiter: ) |
| 09:06 | _ato | ,(map inc (flatten [[1][[[2]][3]]]))) |
| 09:06 | clojurebot | (2 3 4) |
| 09:07 | _ato | stupid nested vectors :p |
| 09:07 | _ato | ,flatten |
| 09:07 | clojurebot | #<seq_utils$flatten__685 clojure.contrib.seq_utils$flatten__685@1aca0d9> |
| 09:07 | _ato | not that flatten is in clojure.contrib.seq-utils not core |
| 09:08 | fliebel | ato: macports does not install contrib. :( |
| 09:08 | _ato | (for [row [[1][2][3 4]], col row] (inc col)) |
| 09:08 | _ato | ,(for [row [[1][2][3 4]], col row] (inc col)) |
| 09:08 | clojurebot | (2 3 4 5) |
| 09:08 | _ato | but that's not recursive, just two levels |
| 09:09 | _ato | ~def flatten |
| 09:09 | _ato | ^ you can of course just define it in your own code if you don't want to use contrib |
| 09:10 | fliebel | could I just do (map #(if (vector? %) (map this %) (inc %) [[2][3]]) or something like that? |
| 09:10 | Chousuke | guess you could |
| 09:11 | Chousuke | though not like that |
| 09:11 | Chousuke | you need (fn this [x] (if (vector? x) ...)) |
| 09:11 | fliebel | hm, i see… Good place to make a macro? |
| 09:13 | _ato | don't see how a macro would help |
| 09:13 | fliebel | a recursive map macro I guess... |
| 09:14 | _ato | ,(map (fn this [x] (if (sequential? x) (map this x) (inc x))) [[2][[3]]]) |
| 09:14 | clojurebot | ((3) ((4))) |
| 09:14 | _ato | it doesn't need to be a macro |
| 09:14 | _ato | map is just a function |
| 09:15 | fliebel | :( I like macros a little to much I guess, just like learning design patters :D |
| 09: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 |
| 09:16 | fliebel | like when? |
| 09:17 | _ato | like when trying to implement something like doto or -> or a new type of conditional |
| 09:18 | fliebel | what is ->? |
| 09:25 | angerman | ~letfn |
| 09:25 | clojurebot | Titim gan éirí ort. |
| 09:26 | _ato | ~def letfn |
| 09:39 | fliebel | wow! My first bit of code that actually has a use: http://pastebin.com/m1dc20c30 recursive map |
| 09:40 | fliebel | uuhm, mace that middle map an rmap. |
| 09:40 | fliebel | *make |
| 09:41 | fliebel | http://pastebin.com/m21efd720 |
| 09:44 | fliebel | If I define a nested function, how can I recur the outer function? It would be cool to make my rmap work with TCO... |
| 09:44 | The-Kennz | fliebel: Maybe trampoline? |
| 09:46 | fliebel | the-kennz: Could be, bu it's going to take me some experimenting before I can get the above example to work. |
| 09:51 | fliebel | the-kennz: I can't get it to work :( |
| 09: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... |
| 09:57 | ngoc | It will help a lot when there are many people in a team |
| 09:57 | fliebel | The only special thing I know about it is 2 space indent and hyphens in names instead of camelcase, |
| 09:58 | fliebel | I'm not sure where I red that, I'm quite noobish. |
| 09:59 | The-Kennz | Use te indent provided by clojure-mode :) |
| 09:59 | clojurebot | clojure is not scheme |
| 09:59 | The-Kennz | s/te/the/ |
| 10:00 | The-Kennz | 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 | ngoc | problems |
| 10:02 | ngoc | 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 | The-Kennz | Very good for writing lisp code. |
| 10:06 | fliebel | seems good enough for me... |
| 10:06 | fliebel | 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 | Chousuke | The-Kennz: well, tramp integrates with that. |
| 10:12 | Chousuke | 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 | The-Kennz | Chousuke: Yeah, "File Name Cache" does this too |
| 10:13 | The-Kennz | 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 | ngoc | 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 | ngoc | 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 | angerman | 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 | jasapp | 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 | Chousuke | 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 | jasapp | no one is going to blame you for using java if something catastrophic happens |
| 10:50 | jasapp | 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 | esj | 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 | esj | Our issue with Ruby are performance and growing complexity. |
| 11:01 | esj | 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 | regularfry | 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 | ngoc | 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 | regularfry | 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 | KirinDave | Makes me wonder |
| 12:22 | KirinDave | 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 | KirinDave | 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 | KirinDave | 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 | The-Kennz | 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 | scellus | 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 | fliebel | I got this now: |
| 13:48 | fliebel | (defn testmap [function body] |
| 13:48 | fliebel | (function (first body)) |
| 13:48 | fliebel | (println function body) |
| 13:48 | fliebel | (recur function (rest body)) |
| 13:48 | fliebel | ) |
| 13:48 | fliebel | But that returns nothing and gives a nullpointerexception |
| 13:51 | durka42 | fliebel: you need a base case to stop the recursion |
| 13:51 | durka42 | eventually (rest body) is null |
| 13:51 | durka42 | 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 | fliebel | ,(= (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 | technomancy | 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 | technomancy | 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 | technomancy | 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 | KirinDave | the-kenny: Let me show you my plan. :) |
| 14:13 | KirinDave | the-kenny: https://gist.github.com/39e337dd0e8afa822dda |
| 14:13 | KirinDave | Can you see what I'm up to there? |
| 14:13 | micampe | I am looking at the http-agent contrib code |
| 14:13 | micampe | 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 | KirinDave | the-kenny: Just gonna doa classic thread spawn for handing the user loop itself |
| 14:15 | KirinDave | Although remove-user-room isn't working and I don't get why. |
| 14:15 | the-kenny | KirinDave: Looks good. |
| 14:15 | the-kenny | 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 | KirinDave | Are the java SSL libraries relatively easy to work with? |
| 14:16 | KirinDave | it'd be cool to show a pure-clojure version of this then use a java lib to add SSL. |
| 14:16 | KirinDave | 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 | KirinDave | 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 | ngoc | (defn hanoi [n from to spare] |
| 14:18 | ngoc | (if (> n 0) |
| 14:18 | ngoc | (do |
| 14:18 | ngoc | (hanoi (dec n) from spare to) |
| 14:18 | ngoc | (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 | the-kenny | 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 | micampe | 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 | technomancy | guess I,d need more context |
| 14:33 | michaeljaaka | hi |
| 14:33 | michaeljaaka | is there any way to check if seq is lazy? |
| 14:33 | michaeljaaka | I would like to see If groups of values in a sequence coming as a result of partition is a lazy group |
| 14:34 | michaeljaaka | 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 | rhickey | 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 | rhickey | both have problems |
| 14:42 | rhickey | 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 | KirinDave | technomancy: So its return value should be identity in that case. |
| 14:43 | KirinDave | 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 | arohner | 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 | KirinDave | 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 | seths | does the map function seem like a reasonable approach? |
| 15:56 | seths | example: |
| 15:56 | seths | (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 | Licenser | 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 | seths | 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 | defn | 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 | defn | or is it proper to differentiate |
| 16:17 | defn | for the purposes of documentation, let's say |
| 16:20 | hiredman | that is an interesting question |
| 16:20 | hiredman | lisp certainly does not differentiate |
| 16:20 | hiredman | a macro call, special form, and function all look the same |
| 16:20 | hiredman | 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 | defn | but im not a long-time lisper so I thought I'd ask the brotherhood |
| 16:23 | defn | what do you mean by never qualified |
| 16:23 | defn | I'm not familiar with that terminology |
| 16:23 | arohner | special forms don't belong to a namespace |
| 16:24 | arohner | 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 | technomancy | sup? |
| 16:26 | hiredman | what defines the special form fn* is a list with the symbol fn* at the front |
| 16:27 | hiredman | 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 | arohner | (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 | arohner | 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 | hiredman | (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 | hiredman | 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 | seths | ,(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 | technomancy | 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 | technomancy | 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 | KirinDave | Is that repeated (let [room (make-get-room! roomname)] …) |
| 16:46 | KirinDave | 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 | technomancy | 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 | KirinDave | If there were even a few more commands I would write this with a macro |
| 16:48 | KirinDave | But I said, "No macros for this example.? |
| 16:48 | KirinDave | When i wsa learning lisp, long ago, every asshole seemed to insist on a macro in their introduction |
| 16:48 | KirinDave | and it pissed me off when I didn't understand them. |
| 16:48 | technomancy | hehe; yeah. |
| 16:49 | technomancy | 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 | KirinDave | 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 | KirinDave | But I won't post till tonight |
| 16:53 | KirinDave | 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 | arohner | (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:57 | KirinDave | God even knows what I'm frontpaging up there. |
| 16:57 | KirinDave | 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 | KirinDave | As difficult as it is to make xkcdexplained funny |
| 16:59 | KirinDave | 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 | technomancy | 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 | KirinDave | 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 | KirinDave | 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 | polypus | 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 | polypus | [Thrown class java.lang.Exception] |
| 17:33 | polypus | 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 | technomancy | 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 | defn | clojure, etc. |
| 17:34 | defn | 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 | polypus | 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 | technomancy | I should add it to the swank-clojure readme |
| 17:40 | technomancy | even though it's technically part of slime |
| 17:40 | polypus | yeah that was it. ty |
| 17:41 | polypus | i was testing with two files one with a namespace and one without and didn;t notice |
| 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 | technomancy | 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 | seths | 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 | MikeDev | 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 | seths | 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 | MikeDev | which would seem trivial |
| 17:51 | MikeDev | 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 | technomancy | thoughts? |
| 17:52 | technomancy | (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 | technomancy | someone ported the leiningen 0.5.0 launch script to powershell |
| 17:57 | technomancy | but I don't think it's been updated for 1.0 |
| 17:57 | technomancy | 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 | technomancy | at least until leiningen gets ported |
| 17:59 | MikeDev | i could use syntax colors |
| 18:02 | MikeDev | 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 | michaeljaaka | can (map #(partition 2 (read-data (data-reader %))) inter-files) be turned into (map #(-> % data-reader read-data (partition 2)) inter-files) ? |
| 18:10 | michaeljaaka | 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 | michaeljaaka | (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 | hiredman | 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 | michaeljaaka | (a b) |
| 18:14 | michaeljaaka | (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 | michaeljaaka | 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 | polypus | 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 | michaeljaaka | hiredman: wow thanks |
| 18:20 | michaeljaaka | 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 | michaeljaaka | nesting functions or use of -> |
| 18:27 | michaeljaaka | 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 | Chousuke | 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 | michaeljaaka | list processing language |
| 18:29 | michaeljaaka | ;) |
| 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 | michaeljaaka | 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 | michaeljaaka | with nested calls it seems to feel more imperative |
| 18:33 | michaeljaaka | so I will to use -> now |
| 18:33 | michaeljaaka | 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 | MikeDev | (defmacro over[coll var-name & body] |
| 18:39 | Chousuke | it's the rest arg |
| 18:40 | Chousuke | ,((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 | Chousuke | ,(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 | Chousuke | with a symbol and a number |
| 18:44 | Chousuke | ,'(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 | Chousuke | 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 | MikeDev | not senior |
| 18:45 | Chousuke | sure it is! Once you get to know Clojure better :) |
| 18:45 | Chousuke | the key point to understanding macros is realising that clojure code is never text |
| 18:46 | Chousuke | 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 | MikeDev | ML didnt have macros AFAIK |
| 18:47 | Chousuke | Most languages that have macros are lisp-derivatives |
| 18:48 | Chousuke | 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 | MikeDev | 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 | MikeDev | for variables |
| 18:50 | seths | The C preprocessor enables plenty of unhygenic evil... |
| 18:50 | MikeDev | Kinda like "Blah $MyVar" in PHP |
| 18:51 | MikeDev | `(Blah ~MyVar) |
| 18:51 | Chousuke | seths: C macros are just search-and-replace :P |
| 18:51 | Chousuke | MikeDev: it's *not* treated a string |
| 18:52 | Chousuke | that's the key point to understand. it's a list. |
| 18:52 | Chousuke | not a string. |
| 18:53 | MikeDev | then it's `(Blah ~MyVar) is like ("Blah" MyVar) |
| 18:53 | Chousuke | hm |
| 18:54 | Chousuke | (let [x 5, form '`(x ~x), evaled-form `(x ~x)] [form, evaled-form]) |
| 18:54 | Chousuke | ,(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 | Chousuke | it doesn't generate strings |
| 18:54 | Chousuke | when that code is evaluated, it forms the evaled-form you see there |
| 18:55 | Chousuke | (if x happens to be 5 in the environment) |
| 18:56 | Chousuke | 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 | Chousuke | MikeDev: to show you what `(x ~x) expands to at read-time |
| 18:58 | Chousuke | the ' prevents the evaluation |
| 18:59 | Chousuke | 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 | Chousuke | 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 | Chousuke | you could technically write a Clojure macro in java. |
| 19:02 | Chousuke | kind of, anyway. it could be a static method that takes some parameters and returns a PersistentList |
| 19:03 | Chousuke | you could then eval the result |
| 19:03 | Chousuke | 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 | MikeDev | having clojure use a macro do evaluation for you |
| 19:04 | MikeDev | 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 | Chousuke | 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 | _ato | 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 | Chousuke | 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 | solussd | 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 | solussd | 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 | solussd | 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 | chouser | I suppose you could. |
| 19:35 | chouser | 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 | solussd | 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 | chouser | 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 | MikeDev | (defmacro over[coll var-name & body] |
| 20:11 | MikeDev | `(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 | shrughes | "A hook is a Lisp variable which holds a list of functions, to be called on some well-defined occasion." |
| 21:44 | shrughes | 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 | arohner | 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 | solussd | 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 | solussd | 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 | hiredman | (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 | solussd | i see what you're saying |
| 22:42 | hiredman | nope |
| 22:42 | solussd | well that makes a lot more sense now. :) |
| 22:42 | solussd | thans |
| 22:42 | solussd | *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 | hiredman | 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 | solussd | e.g. if I kick off 50 of them |
| 22:47 | hiredman | the use the send-off threadpool |
| 22:47 | hiredman | 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 | technomancy | in Emacs at least |
| 23:09 | technomancy | there's not a lot to it |
| 23:13 | technomancy | 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 | KirinDave | 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 | KirinDave | 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 | technomancy | I guess it's this new minimalism thing that everyone's been talking about+ |
| 23:22 | technomancy | ? |
| 23:23 | KirinDave | You can manipulate the stylesheet manually |
| 23:23 | KirinDave | but you can't add style tags to posts and shit. |