#clojure logs

2009-12-06

00:01ngocI think filter must be used instead of map?
00:01ngocBecause of the condition
00:03somniumngoc: (filter identity (map (fn [a b] (when test [...])) seq1 seq2))
00:13technomancyLeiningen 1.0 released: http://github.com/technomancy/leiningen/blob/1.0.0/NEWS
00:16slyrustechnomancy: congrats
00:34replacacongrats, technomancy! Leiningen is another great step forward for Clojure
00:53DeusExPikachuI just gotta say, clojure has beautiful reader syntax, it feels natural
00:54DeusExPikachuI suppose I feel that way because I'm coming from some common lisp background...
01:11ngocI think Lein is feature-complete if live-repl is integrated: http://github.com/djpowell/liverepl
01:22mtm_technomancy: congrats on 1.0
01:26msinghhas anyone experimented with clojure on a blackberry?
01:54slyrusis there a good directory of various available clojure libraries (besides clojure-contrib)?
01:54_atohttp://clojure.org/libraries has some
01:55slyrusthanks!
01:55slyrus(I suppose I should have thought of looking there...)
02:18ataggartanyone awake that's played around with extend-* in the new branch?
05:15the-kennyIs there a library for refactoring lisp-code for emacs?
06:17fliebelHow much optimization is done while compiling Clojure?
06:34carki believe not much
06:34carkisn't that the work of hotspot anyways ?
06:34carkwork/job
06:43fliebelcark: 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:44fliebelBut the same thing might be useful for regexes, templates or other stuff.
06:44carkdon't you think hotspot does it ? i don't know much about it but that seems quite easy
06:45fliebelBut then it has to do it every time the file is ran, right?
06:45carki think literal regexes are compiled only once
06:46carkah you're using clojure as a scripting language ?
06:46fliebelI'm not using Clojure at all at the moment actually...
06:46carkamong the dynamic languages, clojure is pretty good perfomance-wise
06:47fliebelI figured that. :)
06:47angerman~source re-seq
06:48fliebelI 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:48carkheh compiler macros =P
06:49carkwe don't have that
06:50fliebelOk, 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:50carkwhat's the use case you're investigating clojure for ?
06:51carkwell yes you can do that (if i understand you correctly) ... have a look at memoize
06:52fliebelJust 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:52carkoh man you don't need to optimize anything for a web app =)
06:52carkunless you're facebook or something
06:53fliebelIt's not even a web app… :$ I intend to produce static html form source and template files.
06:53carkoh i see
06:53carkwell it's very possible to do this with macros
06:53carktho i think most html libraries do it with functions
06:53carkin clojure i mean
06:54carkthere are macro based html libraries in CL
06:54fliebelIt'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:55carkwell that's an easy project, macro based html template, good for learning
06:55fliebelHmhm, but so far I failed...
06:55carkoh what's the problem point ?
06:56fliebelI want to do impossible thing… at least for a beginner like me.
06:57angermantechnomancy: can I add jvm arguments to lein swank?
06:57carkif you have some specific question, i'm pretty sure you'll find help in this channel
06:57tomojwhat is the point of generating static html with macros instead of functions?
06:57fliebeltomoj: fun, and possibly speed…
06:58fliebelor at least a nicer looking template language.
06:58tomojwhat I mean is that I think speed is irrelevant for this use case
06:58fliebelI agree
06:58tomojat least the difference between macros and functions is irrelevant
06:58carkright, even using functions, you can always memoize and you can't go much faster than that
06:58tomojI guess you've seen compojure's html language?
06:58clojurebotcompojure is http://github.com/weavejester/compojure/tree/master
06:59fliebelno, don't think so.
06:59tomojif you think of a nicer looking language, let me know :)
07:00tomojof course personally I'd rather use actual html and manipulate it with enlive
07:00carki liked cl-who
07:01opqdonuthrgh, cl-who was a hack
07:01carkthe syntax was nic
07:01carke
07:01opqdonutyes
07:01opqdonutbut the implementation was horrible, side effects and all
07:01tomojdo you like compojure's html syntax?
07:01carki don't like the parameters as map in compojure
07:02tomojI guess vectors and maps can look pretty inscrutable
07:02opqdonuti understand it was because they wanted to avoid first building the whole syntax tree and then outputting html
07:02carki think it's more because he wanted speed
07:02carkedi is a pretty good programmer i think
07:03carktho i had to do a function based html library in cl =P
07:03carksame syntax as cl-who, but functions
07:03fliebelIs there some sort of 'with' macro that lets me use a lot of functions that would otherwise clutter the current namespace?
07:03tomojI guess sexp-based html templating is a touchy topic
07:04fliebeltomoj: why?
07:04tomojwell, maybe most everything is a touchy topic in our area
07:04tomojbut some people love it, some people think it's totally stupid
07:04carkhehe i guess =)
07:04carki love sexp based html
07:04carkso much easier
07:05fliebeltomoj: I acutally wanted to do the sexp approach…
07:05tomojcark: just curious, have you looked at enlive?
07:05tomoj(and if so, what do you think?)
07:05carki glanced at it from a distance... looks like a good one
07:05fliebelBut that leaves me with the problem of how to define so many functions properly.
07:05tomojso far I have only used enlive for screen scraping but the approach for templating really appeals to me
07:06tomojwell, not really a problem in clojure
07:06carkfliebel : explain better what you want
07:06tomojyou only need one function, html
07:06carkin a function scope ?
07:06tomojthe argument to this function can be a vector
07:07tomojdon't have to make fake functions for the various tags, just [:tag-name contents]
07:07tomojthough that may look ugly to you :/
07:07fliebelindeed
07:08fliebeleven worse, you would nee [:tag {:attr "value"} content]
07:08fliebel*need
07:08carkyou 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:09fliebelwhat do you mean?
07:09tomojyou want something like (html (h1 "foo") (p "bar baz")) ? or what?
07:09carkyou could make it [:tag :attr1 "val" :attr2 "val" "content"]
07:09fliebeltomoj: yea, something like that I guess
07:10fliebelcark: how would you distinguish between attributes and content?
07:10tomojif html is a function that seems doomed to me
07:10carkfliebel : as long as you have keyword value pair, it's attributes, after that it's content
07:10tomojhave 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:11tomojcompojure is like (html [:h1 "foo"] [:p "bar baz"])
07:11fliebelhow about this: make html a macro that transforms (a content) to (tag "a" content) that would leave you with one function.
07:12tomojyeah, that doesn't sound too bad
07:12tomojexcept..
07:12tomojthis transformation would need to be recursive to be useful, no?
07:12fliebelyea...
07:12tomojand that means you can't call actual functions anywhere inside this html macro?
07:12carkwell that's only a matter of walking the tree
07:13carkyou need special syntax, hum that's ugly
07:13tomojwhereas with compojure we can say (html [:h1 (some-func "foo")]) for example
07:13the-kennyUhm.. 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:13fliebeltomoj: good point :S
07:13the-kennyIf so: there is already a library in contrib to do that.
07:15fliebelthe-kenny: using vectors and :keywords?
07:15the-kennyfliebel: Yes
07:15the-kenny(prxml [:p {:class "greet"} [:i "Ladies & gentlemen"]])
07:15the-kenny-> ; => <p class="greet"><i>Ladies &amp; gentlemen</i></p>
07:15fliebelthe-kenny: I was thinking about some magic with functions and macros, but it seems impossible, or at least hard.
07:16the-kennyfliebel: Nothing is impossible in a lisp
07:16angermanlol. 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:17fliebelthe-kenny: But it could be impossible for a beginner like me...
07:18the-kennyfliebel: But you can learn ;)
07:19fliebelI was discussing how to do it with those guys...
07:20the-kennyhm... sorry if I interrupted you
07:20fliebelA key problem with the function approach is that there might be naming clashes with built in functions.
07:21fliebelor you would need to define a subset of tags or lose the ability to call functions in the macro
07:22the-kennyWhy not use keywords for tags?
07:23fliebelAre 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:26fliebelthe-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:27the-kennyI don't think it's ugly. It's almost perfect for this use case
07:27tomojthe ugliness is what, the extra :?
07:27tomojand I guess square brackets instead of parentheses?
07:28the-kennyEither 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:29fliebelmostly, yes… Of course I could use that, but I like to try out what is possible with a language.
07:29the-kennytomoj: I think it would be possible to avoid the parenthesis with some magic in a macro
07:30the-kennys/parenthesis/square brackets/
07:30fliebelthe-kenny: how?
07:30tomojwell, that's the problem
07:30tomojif you really want paretheses instead of square brackets, seems to me you lose the ability to call functions inside your template
07:30tomojwhich makes me think that vectors are perfect :)
07:30the-kennyfliebel: 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:31the-kenny(and then evaluate it)
07:31tomojah, but possible conflicts where the tag you want is actually a function?
07:31the-kennyBut vectors are easier :)
07:31tomojyap
07:31fliebelthe-kenny: that is what i was thinking about, but how do I do that? is the something like 'function-exists?'?
07:32the-kennytomoj: I'm talking about keywords + parenthesis. I don't think there will be conflicts
07:32tomojah yes
07:32the-kennyfliebel: I'm sure there is.
07:32tomojthat works I suppose as long as you don't use a keyword as a function
07:32the-kenny(Or it's simple to write one)
07:32tomojand that would be a particularly daft thing to do when it looks just like a tag
07:32the-kennytomoj: Heh yeah, that will break it
07:32cark,(fn? seq)
07:32clojurebottrue
07:32the-kenny,(:foo {:bar 42 :foo 23})
07:33clojurebot23
07:33the-kennyThat won't be possible
07:33carki think keywords as tag is cool because of the syntax coloring in emacs
07:33tomojvectors are indeed easier, of course
07:33fliebelhmhm
07:33the-kennycark: that's another argument for keywords :)
07:33clojurebotfor is not a loop
07:33the-kennybad clojurebot, bad.
07:34fliebelhow would i transform (a) to (tag a) with a macro
07:34fliebel?
07:36tomojmaybe something like (defmacro the-macro [& body] (map #(conj % 'tag) body))
07:37tomojno..
07:37tomojneed a list or something
07:37tomojotherwise the first (tag ...) will be called as a function
07:38Chousuke,(conj '(a) 'tag)
07:38clojurebot(tag a)
07:38Chousukelike that.
07:39thomasleehi 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:39Chousukedoto?
07:39Chousuke,(macroexpand '(doto a b c))
07:39clojurebot(let* [G__6085 a] (b G__6085) (c G__6085) G__6085)
07:40Chousukehm
07:40thomasleeChousuke: I think that might be close enough to what I'm after
07:40Chousukeusually used with mutable java stuffthough
07:40thomasleewell that's what I'm doing here :)
07:40thomasleeworking with a URLConnection object
07:41thomasleecalling all sorts of horrible setters and stuff
07:41Chousukeyeah
07:41Chousukethat's what doto is for
07:41thomasleethanks very much!
07:41clojurebotmuch is permittted
08:48fliebelcan I use doto on Clojure functions?
08:49Chousukesure.
08:49Chousukeit's just (doto x .method (f args))
08:49fliebelBut how do java classes map to clojure and the other way around? I guess something with namespaces?
08:49Chousukehm? :/
08:51fliebelWell, in Java everything is organized in packages and classes, so you can do java.package.class.method, in clojure… ?
08:51_atoclojure.namespace/function
08:52Chousukefor java static methods, you'd do java.package.class/staticMethod
08:53fliebelso 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:53interferonlet'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:53Chousukefliebel: um, no.
08:54Chousukefliebel: doto is for calling functions or methods on its first argument.
08:54Chousukethat expression would become (do (function1 clojure.user "bla") ...) which makes no sense
08:55fliebelso it becomes (.getitem class argument) but getitem is no valid clojure method is it?
08:55Chousukefliebel: but .getitem is a method symbol
08:55Chousukebecause it has the leading .
08:56Chousukeso (doto x .foo bar) becomes (do (.foo x) (bar x) x) which is completely valid clojure code
08:56_atoclojure namespaces are not java classes, they behave completely differently
08:56Chousukeand x is not a java class, but an object
08:56Chousukethough it can be a Class object :P
08:57fliebelwait a moment… *grinding gears*
08:58fliebelso doto is just a temporarily partial?
08:58Chousukedoto is just a macro for avoiding repetition in cases where in java you'd do:
08:58_atono, doto is a macro, it just rewrites the code at compilation time
08:58Chousukex.foo(); x.bar(); x.foobar();
08:58Chousukewhich with doto is (doto x .foo .bar .foobar)
08:59Chousukeand doto returns x
08:59fliebelso it is of no particular use in clojure?
08:59Chousukesure it is.
08:59fliebelwith clojure code i mean
08:59Chousukewhen dealing with mutable java objects, mainly
09:00_atoit is less useful, if you're writing functional code
09:00_atobut you could do something like: (doto some-agent (send foo) (send bar))
09:01fliebel:( 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_atoor (map foo [bar egg]) if you care about the return value
09:03angermanChousuke: 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:03fliebelmap has a cooler syntax in my opinion, i don't get doseq.
09:03Chousukeangerman: reify can't extend classes
09:03Chousukeonly interfaces
09:03_atoangerman: you want proxy
09:03Chousuke(Object is an exception)
09:04angermanHm. but I thought proxys performance was questionable
09:04Chousukeuse gen-class then
09:05fliebelIs map recursive?
09:05_atofliebel: you mean if you have nested lists? no
09:06fliebelato: yea, that is what I mean… how can I do that?
09:06_ato,(map inc (flatten [[1][[[2]][3]]))
09:06clojurebotUnmatched delimiter: )
09:06_ato,(map inc (flatten [[1][[[2]][3]])))
09:06clojurebotUnmatched delimiter: )
09:06_ato,(map inc (flatten [[1][[[2]][3]]])))
09:06clojurebot(2 3 4)
09:07_atostupid nested vectors :p
09:07_ato,flatten
09:07clojurebot#<seq_utils$flatten__685 clojure.contrib.seq_utils$flatten__685@1aca0d9>
09:07_atonot that flatten is in clojure.contrib.seq-utils not core
09:08fliebelato: 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:08clojurebot(2 3 4 5)
09:08_atobut 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:10fliebelcould I just do (map #(if (vector? %) (map this %) (inc %) [[2][3]]) or something like that?
09:10Chousukeguess you could
09:11Chousukethough not like that
09:11Chousukeyou need (fn this [x] (if (vector? x) ...))
09:11fliebelhm, i see… Good place to make a macro?
09:13_atodon't see how a macro would help
09:13fliebela recursive map macro I guess...
09:14_ato,(map (fn this [x] (if (sequential? x) (map this x) (inc x))) [[2][[3]]])
09:14clojurebot((3) ((4)))
09:14_atoit doesn't need to be a macro
09:14_atomap is just a function
09:15fliebel:( I like macros a little to much I guess, just like learning design patters :D
09:16_atoyes.. 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:16fliebellike when?
09:17_atolike when trying to implement something like doto or -> or a new type of conditional
09:18fliebelwhat is ->?
09:25angerman~letfn
09:25clojurebotTitim gan éirí ort.
09:26_ato~def letfn
09:39fliebelwow! My first bit of code that actually has a use: http://pastebin.com/m1dc20c30 recursive map
09:40fliebeluuhm, mace that middle map an rmap.
09:40fliebel*make
09:41fliebelhttp://pastebin.com/m21efd720
09:44fliebelIf I define a nested function, how can I recur the outer function? It would be cool to make my rmap work with TCO...
09:44The-Kennzfliebel: Maybe trampoline?
09:46fliebelthe-kennz: Could be, bu it's going to take me some experimenting before I can get the above example to work.
09:51fliebelthe-kennz: I can't get it to work :(
09:56ngocHi, 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:57ngocIt will help a lot when there are many people in a team
09:57fliebelThe only special thing I know about it is 2 space indent and hyphens in names instead of camelcase,
09:58fliebelI'm not sure where I red that, I'm quite noobish.
09:59The-KennzUse te indent provided by clojure-mode :)
09:59clojurebotclojure is not scheme
09:59The-Kennzs/te/the/
10:00The-KennzMost of the guidelines from common lisp can be applied to clojure code
10:01fliebelthe-kennz: what is clojure-mode?
10:01ngocindent is only one of the problem
10:01ngocproblems
10:02ngocThe-Kennz: For a team of average developers, it is almost impossible to force everyone to use Emacs?
10:03The-Kennzfliebel: Clojure indenting, highlighting etc. for emacs
10:04fliebelwhat is emacs? no, sorry, I should know that… Or at least be able to google it.
10:04The-Kennzfliebel: The most powerful text editor in the universe. Written in Emacs Lisp :)
10:04The-KennzVery good for writing lisp code.
10:06fliebelseems good enough for me...
10:06fliebelhttp://aquamacs.org/
10:07The-KennzEmacs + Slime is the killer-ide for clojure, common lisp and any other lisp where a swank-backend exist
10:08ngocThe file browser of Emacs is awful, for project that contains many files and directories, file browser is a must
10:09The-Kennzngoc: There are so many extension for everything.. I'm sure that what you want exists
10:10fliebelslime? Clojure is not common lisp, right?
10:10The-Kennzfliebel: Yes, but slime works with clojure.
10:10fliebelcool
10:10Chousukefile browser? I just use tramp :/
10:11fliebelI'm off, bye!
10:11ChousukeThe-Kennz: well, tramp integrates with that.
10:12Chousukeusually it just finds the file and I don't even need to know where exactly it is :P
10:12The-Kennzngoc: What exactly is a "file browser" for you?
10:12The-KennzChousuke: Yeah, "File Name Cache" does this too
10:13The-KennzI'm a bit afraid to add my whole ~/Development directory because of the bazillion .classfiles there
10:13Chousukecan't you exclude classfiles?
10:14The-KennzChousuke: I think so. But I haven't really tried it. I just found out it exists yesterday
10:15ngocThe-Kennz: I mean the left pannel in this screenshot of Eclipse: http://www.gesource.jp/weblog/archives_img/eclipse-pydev03.png
10:16The-Kennzngoc: M-x speedbar
10:16ngocThe code hightlight of the Clojure plugin for Eclipse is good, but it does not do auto indent
10:16The-Kennzngoc: Example: http://www.telecom.otago.ac.nz/tele402/files/speedbar-customise.gif
10:17ngocyes, that what I mean awful, compared with the file browser of Eclipse :D
10:18The-Kennzngoc: I'm sure there are plenty of customizations and extensions for it
10:26ngocMy 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:29ngocI want to build a good common coding style from the start, the people are too deep in the mess culture of Perl :(
10:29tomojtotally average people :(
10:33ngocYes, I have to admit that we are average people, so we need an easy start
10:34ngocEmacs is too hard to start
10:35angermanEnclojure?!
10:36ngocDoes Enclojure have auto indenting?
10:37angermanNot sure. But if I was looking for a clojure support plugin and an IDE I'd check out enclojure+netbeans
10:37angermanthough I heard that IDEA has a nice plugin too... maybe I'm wrong
10:42ngocCan 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:43angermanngoc: I think it's mostly a personal matter. Either you like Scalas syntax or not. Either you want a lisp or not.
10:45jasappI'm just curious, but what benefits do you see for moving to lisp if you've got "average" people?
10:45jasappa lisp, I should say
10:46Chousukemaking them non-average :)
10:46jasappthat'll do the trick :)
10:47ngocThe 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:49ChousukeI can't answer that question :/
10:49ChousukeI know next to nothing about scala, save that the syntax is scary
10:50jasappfrom a cover your ass point of view, it seems like java is the safest bet
10:50jasappno one is going to blame you for using java if something catastrophic happens
10:50jasappbut you're not going to be nearly as productive either
10:50angermanI'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:51ngocFor 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:51konrWhat do you use to wrap jars and the JVM in a single file? JSmooth?
10:53esjngoc, 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:55ngocesj: 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:57esjngoc: We were mostly consolidating our code base and Ruby allowed us to that very quickly and quite painlessly.
10:58esjWe 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:00esjOur issue with Ruby are performance and growing complexity.
11:01esjbut 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:02ngocesj: Can Ruby 1.9 solve your performance issue? What is the complexity? Is that because class openning makes your code hard to maintain?
11:04esjRuby 1.9 should help on the performance front, but Clojure promises a lot more. Complexity is concurrency.
11:05regularfryNoon 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:08regularfryI can't see much documentation on using java generics from Clojure, which makes me think I must be missing something obvious.
11:08ngocregularfry: http://groups.google.com/group/clojure/browse_thread/thread/4b127c9374ece307/1062db714c991bc2
11:10ngocI think you should see the Java Interop instruction to create a Java HashTable
11:12regularfryngoc: I've seen that, and don't understand.
11:12regularfryngoc: the google groups post doesn't explain anything, and the java-interop page doesn't involve generics.
11:13ngocI 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:14Drakesonhave you tried to provide nailMain(NGContext context) in clojure?
11:15ngocCreate an object of a subclass of HashTable, manipulate that object, then pass it to the Java library
11:15regularfryngoc: 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:17ngocIf hash-map is a subclass of HashTable, then you're done, but I'm not sure about that
11:20scellusbtw, is it easy (or possible) to generate such a subclass in clojure?
11:41ngocscellus: yes, buy this book, it's a must for learning Clojure: http://pragprog.com/titles/shcloj/programming-clojure
11:42scellusngoc: i have it, have to read it :)
11:44ngocUnfortunately 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:46ChousukeMark Volkmann's Clojure article is also great.
11:48ngocah yes, sorry I forgot that wonderful summary
11:52scellusngoc: 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:12ngocscellus: the cheat sheet may be the most "must have": http://clojure.org/cheatsheet because there are too many functions in the default namespace
12:22KirinDaveSo I saw this: http://dhotson.tumblr.com/post/271733389/a-simple-chat-server-in-node-js
12:22KirinDaveMakes me wonder
12:22KirinDavewhat's the java-world answer to node's evented IO?
12:23ngocJBoss Netty and Servlet 3
12:23micampeor apache mina
12:23ngocNetty and Mina have good doc
12:24KirinDaveWell i found this
12:24KirinDavehttp://github.com/ngocdaothanh/telchat-clojure
12:24ngoc... than some others
12:25KirinDaveAnd it seemed like Netty was something of a pain to use with clojure because it lacks annotation support?
12:26ngocyes, but you have to create only one Java class to use annotation in it, for others you can use proxy that Clojure provides
12:27KirinDaveWell I was pondering if there was as elegant way to do this in clojure that would make a good blog post
12:27ngocand the class is super short: http://github.com/ngocdaothanh/telchat-clojure/blob/master/src/main/java/telchat/net/Handler.java
12:28KirinDaveYes, but that approach doesn't fit in a single blog post. :)
12:29ngocIs that true that on theory it is impossible to add annotation support to Clojure?
12:31KirinDaveI wonder if the clojure-esque architecture is to have rooms as agents holding lists of sockets to write to.
12:32KirinDaveAlthough I dunno how to do non-blocking reads in clojure.
13:27The-KennzKirinDave: I'm sure the iostreams provided by the socket-classes have options to do non-blocking reading
13:28The-KennzBut 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:33fliebelWhat is a proper way to write my own custom map function?
13:44scellusfliebel: be a bit more specific. what's wrong with the standard map?
13:45fliebelscellus: Nothing, just for learning purposes.
13:46scellusfliebel: look at the sources. it's a bit tricky with the laziness.
13:47scelluswithout laziness, in a typical lisp, you'd use tail recursion
13:47fliebelscellus: I don't need to something advanced like that. Just how to use recur to execute and return for every value.
13:48fliebelI got this now:
13:48fliebel(defn testmap [function body]
13:48fliebel (function (first body))
13:48fliebel (println function body)
13:48fliebel (recur function (rest body))
13:48fliebel)
13:48fliebelBut that returns nothing and gives a nullpointerexception
13:51durka42fliebel: you need a base case to stop the recursion
13:51durka42eventually (rest body) is null
13:51durka42and since this isn't lazy you want to be using next, not rest
13:52The-Kennzhm.. I think this map is missing a cons or conj
13:53scellus(defn mymap [f l] (loop [l l r []] (if (empty? l) r (recur (rest l) (conj r (f (first l)))))))
13:53fliebeldurka42: But if I supply next to recur, the next iteration does not have access to the list.
13:53durka42fliebel: huh? you want (next body) instead of (rest body)
13:54fliebelwhat is the difference?
13:55fliebel,(= (rest [:a :b :c]) (next [:a :b :c]))
13:55clojurebottrue
13:55scellushttp://clojure.org/lazy
14:05fliebelCan I do optional arguments? I noticed a question mark somewhere, but I can't figure out how it works.
14:06technomancyfliebel: (fn [req & [opt1 opt2]])
14:07technomancybasically you destructure on your rest param.
14:07fliebelhow do I destructure?
14:07technomancyyou can also use a multi-body fn where the N-1 arity body calls the N
14:08technomancyN-arity one with the optional args filled in
14:08fliebelSo what does this function do? (defn optional [a b? c] (println a c))
14:09technomancythat just means you have a local with "b?" as its name
14:09technomancythe question mark is a valid name for a local
14:09fliebelah, how stupid of me...
14:09technomancyerr--valid in a local name
14:10fliebelI guess I'll go for the multi-body fn...
14:10scellusit goes as a local as well :)
14:10technomancyfliebel: that's better if you want a default value that's non-nil.
14:12fliebelWhat is the definition of the tail position? I mean in what ways I can nest and move the recur call.
14:12KirinDavethe-kenny: I don't think they do, at least without calling to java.
14:12KirinDavethe-kenny: Let me show you my plan. :)
14:13KirinDavethe-kenny: https://gist.github.com/39e337dd0e8afa822dda
14:13KirinDaveCan you see what I'm up to there?
14:13micampeI am looking at the http-agent contrib code
14:13micampewhat are the double-colon ::keywords?
14:14KirinDavemicampe: They're keywords in the current namespace
14:14rhickey,:foo
14:14clojurebot:foo
14:14rhickey,::foo
14:14clojurebot:sandbox/foo
14:14scellusfliebel: 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:14fliebelWow, that was actually something I knew!
14:14the-kennyKirinDave: Looks good.
14:14micampeI see, namespaced keywords, thanks
14:14KirinDavethe-kenny: Yeah, simple enough
14:15KirinDavethe-kenny: Just gonna doa classic thread spawn for handing the user loop itself
14:15KirinDaveAlthough remove-user-room isn't working and I don't get why.
14:15the-kennyKirinDave: Looks good.
14:15the-kennyoops sorry
14:16fliebelscellus: 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:16micampenow I just have to figure out when I would use those.
14:16KirinDaveI think I am gonna do a multi-part series
14:16KirinDaveAre the java SSL libraries relatively easy to work with?
14:16KirinDaveit'd be cool to show a pure-clojure version of this then use a java lib to add SSL.
14:16KirinDaveA real one-two-punch hitfest.
14:17scellusfliebel: recur can be anywhere within (loop ) afaik
14:17micampeKirinDave: I am interested, where are you going to post this?
14:17KirinDavemicampe: On kirindave.tumblr.com
14:17KirinDaveDid you see that node.js chat server?
14:18ngocHow to recur if there are 2 recursion call? I can only convert the second call to recur:
14:18ngoc(defn hanoi [n from to spare]
14:18ngoc (if (> n 0)
14:18ngoc (do
14:18ngoc (hanoi (dec n) from spare to)
14:18ngoc (println n ":" from "->" to)
14:18technomancyso commands can be added without pushing out new versions to elpa
14:18ngoc (recur (dec n) spare to from))))
14:18the-kennyngoc: Use lisppaste for multi-line pastes
14:18the-kennylisppaste8: url
14:18lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
14:18micampeKirinDave: yes, I looked at it when you linked it earlier
14:19micampeKirinDave: actually, my objective is using sockets, at the moment, but that would be useful
14:19KirinDavetechnomancy: Isn't that how swank normally does it?
14:19solussdwhat is the most idiomatic way to leverage the executors framework in clojure? Is there a clojure specific way to schedule periodic thread execution?
14:20the-kennysolussd: I think there's scheduledThreadExecutor somewhere in java.util.concurrent. I'm using the thread-pools for a project
14:20lisppaste8ngocdaothanh pasted "2 recurs" at http://paste.lisp.org/display/91690
14:21KirinDavetechnomancy: Any input you have would be appreciated. :)
14:21solussdthe-kenny: yeah, I know about the scheduledExecutorService. I was wondering if there is maybe a contirb library that clojurifies it a bit. :)
14:22technomancyKirinDave: 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:23ngocthe-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:24technomancyKirinDave: re: the gist: are you using "get" on line 8 just for readability? (you know it's not required?)
14:24the-kennyngoc: I'm not very familiar with recursive function in clojure
14:24technomancyKirinDave: also: I'm not sure what I think about the fact that write-room has both side-effects and a return value
14:24technomancyguess I,d need more context
14:33michaeljaakahi
14:33michaeljaakais there any way to check if seq is lazy?
14:33michaeljaakaI would like to see If groups of values in a sequence coming as a result of partition is a lazy group
14:34michaeljaakaseqence of these groups is lazy but groups?
14:35ngocWhy it is said that in Clojure Java integration is smoother and more complete than in Scala?
14:35Chousukeis it? :P
14:36technomancyngoc: I don't think I've heard that personally.
14:36fliebelI have heard the same stories...
14:36technomancypeople complain about the lack of annotations
14:36rhickeyngoc: 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:37rhickeyno wrappers in either direction
14:38fliebelI heard Scala is proud not to implement them because they say java collections are broken.
14:38michaeljaakabut you have to live with Java
14:38rhickeyfliebel: fine, but that would effect 'smooth' wouldn't it?
14:39ngocFrom the last comment: http://codemonkeyism.com/scala-vs-clojure. I also heard this somewhere else, don't remember now.
14:39fliebelrhickey: I guess so, but maybe they are transparently converted or something like that.
14:40rhickeytransparent conversion implies either a wrapper or a copy
14:40rhickeyboth have problems
14:42rhickeytry both - there's no reason to rely on hearsay
14:42arohnerivy dumps its jars in ~/.m2, right?
14:43KirinDavetechnomancy: write-room is an agent transformer.
14:43KirinDavetechnomancy: So its return value should be identity in that case.
14:43KirinDavetechnomancy: It's used only for side effects.
14:44ngocarohner: no, just checked, there's ~/.ivy2 on my machine
14:44arohnerngoc: thanks. Though it appears ivy also dumped the files in project/lib
14:45KirinDavetechnomancy: I haven't seen any idiom or glyph to signify something is an agent transformer.
14:45arohnermaven / ivy make it more annoying than necessary to compile against e.g. a non-standard clojure.jar
14:46arohnerI really don't want some random library off the internet assuming I run clojure-1.0.0.jar
14:47KirinDaveYay, 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:59technomancyKirinDave: makes sense; nice
14:59KirinDavetechnomancy: I guess I am going to use agent-method-name to denote agent xformers.
15:00KirinDaveAs 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:05ngocWhere can I find the roadmap of Clojure?
15:07Chousukengoc: I don't think there's a roadmap but you can read about upcoming features on the assembla wiki pages.
15:07rhickeyngoc: https://www.assembla.com/spaces/clojure
15:08ngocThanks a lot
15:28KirinDaveIs there a way to unbind a symbol?
15:29rhickey,(doc ns-unmap)
15:29clojurebot"([ns sym]); Removes the mappings for the symbol from the namespace."
15:29KirinDaveThanks
15:48defn'lo
15:56sethsa question on pulling items from a vector at specific indexes...
15:56sethsdoes the map function seem like a reasonable approach?
15:56sethsexample:
15:56seths(map [:boat :plane :fish] [0 2])
15:56clojurebotmap is lazy
15:56seths(:boat :fish)
15:57Licenserhmm some kind of filter?
15:58Licensergive me a second I've an ida
16:02scellus,(map (partial nth [:boat :plane :fish]) [0 2])
16:02clojurebot(:boat :fish)
16:04Chousuke,(map [:foo :bar :zonk] [0 2])
16:04clojurebot(:foo :zonk)
16:05sethsI haven't used partial function application before. It does the trick here, but what is the advantage over Chousuke's example?
16:05KirinDaveHum
16:06scellusnone i guess :)
16:06Chousukethere's no real difference
16:06KirinDavetechnomancy: Got a sec?
16:06sethsgood to see it in action though
16:06sethsthanks everyone
16:06Licenserwow all so much easyer then my idea o.O
16:08KirinDavetechnomancy: I borrowed a bit of code from mire, specifically your response loop
16:13defnis it okay to call a special form a method?
16:13defnerr a function
16:16hiredmanspecial forms are more like macros in that they have control over the evaluation of their arguments
16:16defnin 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:16defnor is it proper to differentiate
16:17defnfor the purposes of documentation, let's say
16:20hiredmanthat is an interesting question
16:20hiredmanlisp certainly does not differentiate
16:20hiredmana macro call, special form, and function all look the same
16:20hiredmanbut you can't use a macro or a special form as a function object
16:21arohnerspecial forms are never qualified
16:21hiredmanhmm
16:22arohnerI would guess they're all 'forms'
16:22defnsee that was sort of my intuition
16:23defnbut im not a long-time lisper so I thought I'd ask the brotherhood
16:23defnwhat do you mean by never qualified
16:23defnI'm not familiar with that terminology
16:23arohnerspecial forms don't belong to a namespace
16:24arohnerso they're not qualified by a namespace, like foo/bar
16:24defnbut the builtin clojure.core stuff could all be called qualified, yes?
16:24arohnerI didn't quite understand what you were asking when I said that, though
16:24hiredmanthere is nothing stopping them from being namespace qualified
16:25arohnerthey're not vars
16:25hiredmanso?
16:25arohner,`(map [42])
16:25clojurebot(clojure.core/map [42])
16:25arohner,`(if [42])
16:25clojurebot(if [42])
16:25technomancyKirinDave: hey
16:25technomancysup?
16:26hiredmanwhat defines the special form fn* is a list with the symbol fn* at the front
16:27hiredmanthe symbol fn* could be replaced with the symbol a qualified symbol and what would the difference be?
16:27scellusspecial forms cannot be function args, can they?
16:27arohnerscellus: no, they can't
16:28arohner(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:29arohnernamespaces only hold vars. the special forms aren't vars. They're not even functions.
16:29hiredmanarohner: foo/fn* is just a namespace qualified symbol
16:29scellusspecial forms have no values nor the fn interface, or whatever it is called in clojure
16:29hiredmanso the compiler could just as easily use namespace qualified symbols for special forms
16:30arohneryes, I can imagine a language that does that. But that's not the way clojure is today
16:30hiredmansure
16:31hiredman(x y z) ;is x a special form, macro, or a function?
16:32scellusx is just the first item in a list - if it is evaluated, x can represented any of those, right?
16:33rhickeyscellus:no, if x is a special form or macro it is not evaluated
16:33hiredman,(@#'fn [] 1)
16:33clojurebot(fn* ([] 1))
16:33scellusrhickey: i mean if the list is evaluated
16:35hiredmanthats kind of the point
16:36hiredmanyou can't know until you evaluate the form, and even then differentiating between macros and special forms can be difficult
16:36arohnerrhickey: 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:37polypusi'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:37technomancypolypus: that's correct.
16:38scellusarohner: 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:39KirinDavetechnomancy: I just wanted to solicit advice before I posted that code. Since I did kinda steal from mire to do it. :)
16:39polypuswhere is that jar, if i installed swank via elpa?
16:39KirinDavetechnomancy: https://gist.github.com/39e337dd0e8afa822dda
16:39rhickeyarohner: 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:40technomancypolypus: elpa only handles elisp dependencies; for clojure/jvm dependencies a tool like leiningen or maven is more appropriate
16:40arohnerrhickey: ah, thanks
16:40technomancypolypus: 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:42sethsscellus: your answer to my question was more robust.
16:42seths,(map [1 2 3] [0 2])
16:42clojurebot(1 3)
16:42seths,(map '(1 2 3) [0 2])
16:42clojurebotjava.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn
16:42seths,(map (partial nth '(1 2 3)) [0 2])
16:42clojurebot(1 3)
16:43technomancyKirinDave: 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:43technomancyKirinDave: I'd also rename "output" to just "out"
16:44polypustechnomancy: 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:44technomancypolypus: cool
16:44technomancyKirinDave: might want to declare *username* instead of def'ing it to a dummy value.
16:44KirinDavetechnomancy: Okay.
16:44technomancythough I guess def'ing it makes repl-time experimentation easier. it's a trade-off there.
16:45KirinDaveYeah, that's why i did it. :)
16:45technomancysince it's pretty clear that "Someone" is a dummy value.
16:45KirinDaveI am just adding "has disconnected" messages.
16:45scellusseths: yes, only collections have this fn interface or whatever it is. and a list is not.
16:45KirinDaveAnd then I'll have 100% parity with the node.js example, except i have rooms.
16:45sethsI wonder why PersistentList doesn't implement IFn?
16:45technomancyKirinDave: sweet
16:45sethsah, thx
16:45KirinDaveAnd if I change that if-let to an (or) I will be the same number of lines.
16:45technomancyheh
16:46KirinDavetechnomancy: The only thing that bugs me
16:46KirinDaveIs that repeated (let [room (make-get-room! roomname)] …)
16:46KirinDaveI see it three times, feels weird.
16:47arohnerseths: my guess is that lists don't have sub-linear lookups to their values, unlike vectors and maps
16:47solussdcan someone explain clojure.contrib.fill-queue to me? docsstring isn't doing it. :)
16:47technomancyKirinDave: you could inline it in line 37 since it's only used once
16:47technomancyif it were significantly more than three times it might justify a with-room macro
16:48KirinDaveYeah, at 5 times I feel like I have a pattenr.
16:48KirinDaveIf there were even a few more commands I would write this with a macro
16:48KirinDaveBut I said, "No macros for this example.?
16:48KirinDaveWhen i wsa learning lisp, long ago, every asshole seemed to insist on a macro in their introduction
16:48KirinDaveand it pissed me off when I didn't understand them.
16:48technomancyhehe; yeah.
16:49technomancybecause people pull them in when they're not justified
16:52sethsarohner: is it easy/possible to make vectors and maps infinitely large, like lists with (cycle 1)?
16:52KirinDaveOkay, now to blog about it, I guess.
16:52KirinDaveAhh, no. First, github. Can't forget these things.
16:52sethsKirinDave: what's the blog url?
16:53KirinDaveseths: kirindave.tumblr.com
16:53KirinDaveBut I won't post till tonight
16:53KirinDaveI've got errands of the ikea variety. :)
16:53arohnerseths: 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:54arohner(cycle 1) creates a lazy seq whose current value is 1, and the next value is (cycle 1)
16:55hiredmanif you find yourself repeatedly calling nth on an infinite sequence a rethink might be in order
16:55sethsKirinDave: great, I'll lob it into Google Reader now
16:56KirinDaveseths: Beware. I am not what you'd call a "focused subject blog" ;)
16:57KirinDaveGod even knows what I'm frontpaging up there.
16:57KirinDaveseths: But while you have greader open and adding subs, xkcdexplained.tumblr.com ;)
16:58technomancy_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:58the-kennyKirinDave: http://the-kenny.tumblr.com/post/257607877/evolution-of-xkcd
16:58sethsKirinDave: done -- looks neat. enjoy ikea!
16:59KirinDavethe-kenny: Heh. I gotta say though, I don't think she realized what she was in for with xkcdexplainedexplained
16:59KirinDaveAs difficult as it is to make xkcdexplained funny
16:59KirinDaveJas has got it like 10x harder.
16:59technomancyKirinDave: can you explain some of those earlier strips with the red spiders and such?
16:59technomancythat would really be helpful.
17:00the-kennyWait... are you involved with xkcdexplained, KirinDave?
17:02KirinDavethe-kenny: Yes. I am "Dave" from the title.
17:02KirinDaveI have written about 1/3
17:02the-kennyWow, awesome. Nice to meet you :)
17:04KirinDavethe-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:04KirinDaveOf course, Toby had a family emergency and I got married.. but… there are *no excuses*
17:26polypusok 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:30technomancypolypus: is it a problem with a hook?
17:30polypusyou mean one i've defined?
17:30polypuscuz i haven't defined any
17:31technomancyno, I mean does the error message say something about a hook not being defined
17:33polypusUnable to resolve symbol: server in this context
17:33polypus [Thrown class java.lang.Exception]
17:33polypusthats all i get, with a stack trace
17:33defnthat could be the class path no?
17:33polypusserver was just a symbol defined in the buffer
17:33technomancythat's a new one to me
17:33technomancypolypus: oh, so it connects; you get that error when you eval the buffer?
17:33defnpolypus: how'd you install swank
17:34defnclojure, etc.
17:34defndid you use technomancy's elpa pkg?
17:35polypusyeah 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:35polypusbuffer*
17:35technomancypolypus: my guess is your buffer is in one namespace but your repl is in "user" still
17:36polypusdoh
17:36technomancyC-c M-p from your code buffer will let you change the repl namespace automatically
17:39the-kennyI have to remember this shortcut
17:39technomancyit's handy
17:40technomancyI should add it to the swank-clojure readme
17:40technomancyeven though it's technically part of slime
17:40polypusyeah that was it. ty
17:41polypusi was testing with two files one with a namespace and one without and didn;t notice
17:42technomancybut they exist
17:44MikeDevIs a macro just like a #DEFINE in C?
17:44hiredmanno
17:44sethsSurrounding a symbol with * like *this* means this is a "global"? does it imply mutability?
17:45polypusit would be pretty cool to get slime working over http to access a running web app in emacs. is this possible yet?
17:45technomancyseths: not mutability per se, but it does imply that the var will be rebound to another value using binding.
17:45MikeDevThis: http://clojure.org/macros is not helpful
17:45technomancypolypus: you can connect to compojure (etc) apps just fine, but it doesn't work over HTTP
17:45technomancyyou either need to be local or tunnel over SSH
17:46polypusyeah, i was thinking in cases where you only have http access with managed hosting or something
17:46_atoMikeDev: 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:47technomancypolypus: oh for like google app engine or something? maybe.
17:47polypusexactly
17:47sethsMikeDev: 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:48sethsAlso the Programming Clojure book by Halloway has a good chapter on them
17:48MikeDevThis is kinda for a homework assignment
17:48MikeDevfair disclojure
17:48technomancypolypus: no reason why it couldn't be done... are you volunteering? =)
17:48sethsYou can get an ebook of it I think
17:48sethsMikeDev: using Clojure for homework?
17:49polypustechnomancy: maybe after i'm over the noob hump :)
17:49hiredmansomeone did a blog post about getting slime to connect to the appengine dev server
17:49technomancypolypus: unfortunately it would involve writing some elisp too.
17:49hiredmanso you can do local developement at the repl
17:49technomancyoh cool
17:49_atohttp://www.hackers-with-attitude.com/2009/08/intertactive-programming-with-clojure.html
17:49MikeDevseths, I am doing exercise for a possible job
17:50hiredman
17:50polypusyeah i saw that blog post. that's pretty good but only local
17:51MikeDevthe 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:51MikeDevwhich would seem trivial
17:51MikeDevcompared to the first exercise
17:51sethsMikeDev: best of luck! I'm hoping to land a Clojure day job in 6 months to a year or so.
17:51technomancyso 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:51technomancythoughts?
17:52technomancy(started using leiningen or clojure-maven-plugin, etc)
17:56sethstechnomancy: is it easy to start swank on Windows?
17:57technomancyseths: I don't know.
17:57technomancysomeone ported the leiningen 0.5.0 launch script to powershell
17:57technomancybut I don't think it's been updated for 1.0
17:57technomancyclojure-maven-plugin could probably do it
17:58sethstechnomancy: 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:58solussdhmm.. how do you "remove" items from a fill-queue?
17:58hiredmanpowershell or just a bat file?
17:58MikeDevit look like macros are imperative
17:58technomancyhiredman: 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:58MikeDevdefn count-and-print-words
17:58hiredmaninteresting
17:58technomancyseths: on windows I would still recommend launching it from within Emacs with M-x swank-clojure-project
17:59technomancyat least until leiningen gets ported
17:59MikeDevi could use syntax colors
18:02MikeDevwhat is a macro's docstring and attribute map?
18:03ChousukeMikeDev: (defmacro foo {:metadata 'here} "docstring" [args] ...)
18:03sethsMikeDev: strongly recommend $21 ebook for Programming Clojure: http://pragprog.com/titles/shcloj/programming-clojure
18:04patrkrisHey. 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:05MikeDevzipper?
18:05hiredmantree-seq and filter are nice for that
18:06patrkriswow... and that was *really* hard finding online... I have to look better next time ;)
18:06hiredman(filter #(= :some-tag (:tag %)) (tree-seq map? (comp seq :content) xml))
18:06patrkrishiredman: thanks man
18:07rhickeypatrkris: http://richhickey.github.com/clojure-contrib/zip-filter-api.html
18:07patrkrisrhickey: yeah, i just stumpled upon that - I should really learn to use search engines
18:09michaeljaakahi
18:09michaeljaakacan (map #(partition 2 (read-data (data-reader %))) inter-files) be turned into (map #(-> % data-reader read-data (partition 2)) inter-files) ?
18:10michaeljaakaright 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:10hiredmanmichaeljaaka: what does -> do?
18:11MikeDevannoys me
18:11michaeljaakatakes argument and applies functions passing result to the next
18:12michaeljaaka(defn zz[x y] (+ x y )) (-> [ [ 1 2 ] [ 2 3 ] ] first second (zz 3) ) gives 5
18:12hiredmanmichaeljaaka: and how does it do that?
18:12hiredmanspecificly in the more complicated case of, for example, (-> x (a b))
18:14michaeljaakawell it will pass x as argument to a list
18:14michaeljaaka(a b)
18:14michaeljaaka(a b x)
18:14hiredmanmichaeljaaka: that is wrong
18:14MikeDev,(a b x)
18:14clojurebotjava.lang.Exception: Unable to resolve symbol: a in this context
18:15hiredman,(macroexpand-1 '(-> x (a b)))
18:15clojurebot(a x b)
18:15hiredman,(macroexpand-1 '(->> x (a b)))
18:15clojurebot(a b x)
18:15MikeDev,(kill closurebo)
18:15clojurebotjava.lang.Exception: Unable to resolve symbol: kill in this context
18:15hiredmanMikeDev: I can arrange for clojurebot to ignore you
18:17michaeljaakahmmm, well I will have to switch to clojure 1.1
18:17michaeljaakaI miss the ->>
18:17polypuslooks like somebody has already messed around with the idea of slime over http in common lisp:
18:17polypushttp://avodonosov.blogspot.com/2008/01/it-is-problematic-at-first-sight-to-use.html
18:17hiredmanmichaeljaaka: or change the argmuent order expected by partition
18:17sethsmichaeljaaka: consider using leiningen to help you switch to clojure 1.1
18:17hiredman,(macroexpand-1 '(-> x ((partial partition 2))))
18:17clojurebot((partial partition 2) x)
18:17sethsI could not be happier, using it to run tests, package code, get dependencies...
18:18michaeljaakaok, I will try it
18:20michaeljaakahiredman: wow thanks
18:20michaeljaakait helped
18:26sethswould a code coverage tool make any sense for a Clojure codebase? Would lazy evaluation be a complication?
18:26michaeljaakahiredman: btw. which style do you prefer?
18:26michaeljaakanesting functions or use of ->
18:27michaeljaakanesting calls actualy
18:27MikeDevwhat is the rationale for requiring that everything be a list?
18:28Chousukewhat do you mean? :/
18:28MikeDev(func a b)
18:28ChousukeNot everything is a list in Clojure.
18:28MikeDevWhy does that have to be in a list
18:28Chousukewhy not?
18:28Chousukeit's a neat representation for a function call
18:28MikeDevwhy not func a b
18:29Chousukebut that's a list too
18:29MikeDevworks in ML
18:29Chousukejust without the parens
18:29michaeljaakabecause it is LISP
18:29michaeljaakalist processing language
18:29michaeljaaka;)
18:29MikeDevah
18:29Chousukenon-parenthesised syntax wouldn't be homoiconic
18:29rhickeyhttp://en.wikipedia.org/wiki/Homoiconicity
18:30MikeDevI'm afraid to look in a public place
18:30Chousuke:P
18:30michaeljaakait is a beauty of that lang
18:30hiredmanmichaeljaaka: I use -> a lot
18:31michaeljaakaI like the statment: show data structure and when going to the syntax you say: hay you already seen it
18:32michaeljaakahiredman: -> seems to be more declarative
18:32ChousukeMikeDev: Clojure code is made of lists and vectors and such things, and the parenthesised form is just the visual representation.
18:32michaeljaakayou say do that that that having rule of result is an argument of the next func
18:32michaeljaakawith nested calls it seems to feel more imperative
18:33michaeljaakaso I will to use -> now
18:33michaeljaakatoo
18:33ChousukeMikeDev: 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:34MikeDevI think I need to understand this: http://sardakcode.blogspot.com/2009/02/my-first-clojure-macro-inspired-by.html
18:34ChousukeMikeDev: I think the parenthesised syntax was chosen because it was plainly the simplest possible textual representation of a list.
18:38MikeDevwhy is the & there?
18:38MikeDev(defmacro over[coll var-name & body]
18:39Chousukeit's the rest arg
18:40Chousuke,((fn [a b & c] [a b c]) 1 2 3 4 5 6)
18:40clojurebot[1 2 (3 4 5 6)]
18:42MikeDevwhat's the deal with the ~
18:42Chousukeit's unquote
18:42hiredmanclojure.org/reader
18:42Chousukea feature specific to syntax-quote, not macros
18:42Chousuke,(let [x 5] `(x ~x))
18:42clojurebot(sandbox/x 5)
18:43MikeDevi have no idea what happened there
18:43Chousukeit returned a list
18:43Chousukewith a symbol and a number
18:44Chousuke,'(x 5); kind of like this
18:44clojurebot(x 5)
18:44MikeDevso it let x=5
18:44Chousukeyeah
18:44Chousukeand then constructed the list
18:44hiredmanMikeDev: I have to ask, are you sure a job where you write clojure is the best thing for you?
18:45MikeDevit's a starting job
18:45MikeDevnot senior
18:45Chousukesure it is! Once you get to know Clojure better :)
18:45Chousukethe key point to understanding macros is realising that clojure code is never text
18:46Chousukeit has a textual representation, but that's not clojure code until it has been transformed into data structures by the reader
18:46MikeDevbesides, my halfassed qualification is knowing ML and functional programming concepts in general
18:46MikeDevML didnt have macros AFAIK
18:47ChousukeMost languages that have macros are lisp-derivatives
18:48Chousukethough I guess there might be some others that have a similar macro system but are not based on s-exprs
18:48MikeDevBob Harper was my teacher and he hated Java
18:48MikeDevlol
18:50sethsI am still trying to see the difference between C macros and Lisp macros
18:50MikeDevso if you do `() it treats the whole thing as a string which is only escaped by ~
18:50MikeDevfor variables
18:50sethsThe C preprocessor enables plenty of unhygenic evil...
18:50MikeDevKinda like "Blah $MyVar" in PHP
18:51MikeDev`(Blah ~MyVar)
18:51Chousukeseths: C macros are just search-and-replace :P
18:51ChousukeMikeDev: it's *not* treated a string
18:52Chousukethat's the key point to understand. it's a list.
18:52Chousukenot a string.
18:53MikeDevthen it's `(Blah ~MyVar) is like ("Blah" MyVar)
18:53Chousukehm
18:54Chousuke(let [x 5, form '`(x ~x), evaled-form `(x ~x)] [form, evaled-form])
18:54Chousuke,(let [x 5, form '`(x ~x), evaled-form `(x ~x)] [form, evaled-form])
18:54clojurebot[(clojure.core/seq (clojure.core/concat (clojure.core/list (quote sandbox/x)) (clojure.core/list x))) (sandbox/x 5)]
18:54Chousukethe ` reader magic generates code that constructs a list at runtime
18:54Chousukeit doesn't generate strings
18:54Chousukewhen that code is evaluated, it forms the evaled-form you see there
18:55Chousuke(if x happens to be 5 in the environment)
18:56Chousukeit's very handy in macros, because it allows you to write "template-like" code
18:57MikeDevwhy form '`(x ~x) and not form `(x ~x)
18:58Chousukebut you could just as well write all macros like (defmacro foo [x] (list '+ x 6 'y))
18:58ChousukeMikeDev: to show you what `(x ~x) expands to at read-time
18:58Chousukethe ' prevents the evaluation
18:59Chousukebut, 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:00Chousukeagain, no strings involved.
19:00MikeDevyeah seqences, cats and lists
19:01Chousukewell, symbols and numbers too.
19:01MikeDevoh those are functions
19:01Chousukeyeah
19:01MikeDevok
19:01Chousukeclojure macros are functions of arbitrary arguments that output lists, vectors or maps... that is, clojure code.
19:02Chousukeyou could technically write a Clojure macro in java.
19:02Chousukekind of, anyway. it could be a static method that takes some parameters and returns a PersistentList
19:03Chousukeyou could then eval the result
19:03Chousukethe trick with macros created with defmacro is, the function is marked special so that the clojure compiler does the evaluation for you.
19:03MikeDevyes and that is what the exercie is about
19:04MikeDevhaving clojure use a macro do evaluation for you
19:04MikeDevso if I understod macros, this would take 5 minutes
19:05Chousukemacros are really simple when you finally get them
19:06MikeDevdo you know ML?
19:06Chousukebut 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:07Chousukeno :/
19:07_atoheh 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_atothey're so much simpler than metaprogramming in most other languages
19:07ChousukeI guess the problem is complicated further by the fact that most clojure code is still stored as text
19:08Chousukeso 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:09MikeDevwhat is @ for
19:09michaeljaaka@--->---
19:09Chousukeit's a splicing unquote
19:09MikeDevpretty flower?
19:09Chousuke,(let [a [1 2 3]] `(5 ~@a))
19:09clojurebot(5 1 2 3)
19:10michaeljaakayes it is
19:10solussdwhat the heck is (ensure ...) for?
19:11MikeDevVitamin Supplementation for Seniors?
19:12_atosolussd: ensure protects a ref from modification during a transaction.
19:12hiredmansolussd: you can ensure that your transaction is retried if a ref that you don't write to is modified
19:14solussdI guess I don't understand how that is different than a regular dosync transaction
19:14solussdlike alter
19:15hiredman,(dosync (alter a + @b))
19:15clojurebotjava.lang.Exception: Unable to resolve symbol: a in this context
19:15Chousukealter actually modifies the ref :P
19:15hiredmanwell
19:15carkkind of the same, only it won't retry as often
19:15hiredman(dosync (alter a + @b))
19:15Chousukeensure 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:16solussdso it retrries it if b changes?
19:16solussdah i c
19:16Chousukeif you were modifying some other refs based on the read value for instance.
19:17solussdinteresting... wonder how many times I should have used ensure.. :)
19:20solussdso ensure goes around the ref that might be changing? e.g. (dosync (alter a + (ensure b))) ?
19:20_atoyep
19:25MikeDevChousuke, can I PM you something?
19:27ChousukeMikeDev: if it's quick. I'm going to sleep soon
19:32solussdanyone here familiar with fill-queue ?
19:32chousersolussd: I might be
19:34solussdit 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:35chouserhm...
19:35chouserI suppose you could.
19:35chouseryou might consider using a Java BlockingQueue directly.
19:36solussdif I have a filler function filling it full of files, I dont want it to grow forever
19:36solussdwhat is fill-queue intended for?
19:38chousersolussd: 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:38chousersolussd: here's a Clojure direct use of a BlockingQueue: http://paste.lisp.org/display/91574
19:40solussdthanks
20:08MikeDevdoes closurebot not let you define macros?
20:11MikeDev(defmacro over[coll var-name & body]
20:11MikeDev`(doseq [~var-name ~coll] ~@body))
20:15the-kennyIs there a reason why you want to define such a macro?
20:16somniumthe-kenny: for the sheer joy of syntax twiddling?
20:16the-kennysomnium: hm yeah.
20:17MikeDevthe-kenny, I'm doing a macro excerise
20:22chouserMikeDev: clojurebot doesn't let you def anything
20:24MikeDevk
21:36arohnerany emacs hackers around? I'm curious about the difference between hooks and advice
21:43shrugheshttp://www.gnu.org/software/emacs/manual/html_node/emacs/Hooks.html
21:43shrughes"A hook is a Lisp variable which holds a list of functions, to be called on some well-defined occasion."
21:44shrughesadvice is much ickier
21:47arohnerI'm thinking about writing a hooks library, and I'm wondering if it's clojure-y
21:47arohneror whether I'm thinking about this wrong
21:53shrughesthe user could just use a var in many cases
21:58arohneryeah, 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:38solussdhow is the future function suppose to be used?
22:38solussdIt does not seem to evaluate its body 'in the future' but when it is defined
22:39hiredmannope, it does it in the future
22:39solussdi tried this: (def myatom (atom 1)) (def myfuture (future (swap! myatom inc)))
22:40hiredmanand?
22:40solussdmyatom is 2 after the myfuture def
22:40solussdi know im missing something obvious. :)
22:40hiredmanthere is a race condition in your brain
22:40solussddamn brain
22:41hiredmanswap! is fast
22:41hiredman(not really, but faste enough when talking about human perception)
22:42solussdoh.. no. .i was thinking future doesnt execute it's body until it is dereferenced
22:42solussdi see what you're saying
22:42hiredmannope
22:42solussdwell that makes a lot more sense now. :)
22:42solussdthans
22:42solussd*thanks
22:42hiredmanfuture is like do-async
22:42rhickey,(do (future (Thread/sleep 1000) (prn 42)) (prn 41))
22:42clojurebot41
22:43chouserthread-local binding of *out* strikes again.
22:43hiredman:P
22:43hiredmanclojurebot printed 42 at its repl
22:45chouserheh
22:47solussdare 'future' bodies always executed in their own thread or is there a thread pool they share?
22:47solussde.g. if I kick off 50 of them
22:47hiredmanthe use the send-off threadpool
22:47hiredmanthey
22:47solussdso it grows
23:09technomancyarohner: run-hooks is implemented similarly to just (doseq [h my-hook] (apply h))
23:09technomancyin Emacs at least
23:09technomancythere's not a lot to it
23:13technomancyKirinDave_: have you tried htmlize.el for putting code in blog posts?
23:14KirinDavetechnomancy: No. I had a huge hassle for even doing that much
23:14technomancyarohner: your implementation is nicer than Emacs' since the hook itself is callable instead of just being a list.
23:14KirinDaveHonestly, tumblr is totally terrible for code.
23:15technomancyI use htmlize for all my blog code
23:17KirinDavetechnomancy: Does that even work with aquamacs?
23:19KirinDavetechnomancy: Well, either way tumblr doesn't allow gist-style embeds or stylesheets, so it's totally balls for code pasting, I guess.
23:21technomancyoh, heh. yeah you're gonna need a stylesheet for code; no way around that
23:21KirinDaveGrumblecakes.
23:22KirinDaveI didn't know about htmlize tho, thank for the tip.
23:22technomancythat's crazy that a blogging service even exists that doesn't allow you to add styles though
23:22technomancyI guess it's this new minimalism thing that everyone's been talking about+
23:22technomancy?
23:23KirinDaveYou can manipulate the stylesheet manually
23:23KirinDavebut you can't add style tags to posts and shit.