#clojure logs

2009-12-07

00:17somniumif you use clojure to generate code in 'blub' that depends on libraries that are not eclipse-compatible, but there is no dependency on clojure in the generated 'blub', are there any issues?
00:25JAS415wait hut
00:25JAS415what*
00:26JAS415am i generating source code to blub or bytecode to blub?
00:26JAS415and why am i generating blub code when i could be generating clojure code?
00:26JAS415and what does eclipse have to do with it?
00:26JAS415i dont even use eclipse, i use emacs
00:28_atowhat does eclipse-compatible even mean?
00:28_atoor do you mean the EPL?
00:29_atoclojure in no way sets what license code you write that uses it has to be
00:29_atoit's a weak-copyleft
00:29_atoyou just can't relicense clojure-itself to say GPL
00:29JAS415oh its a license thing
00:30_atoyeah I had to read the sentence 5 times before I realised he was talking about licenses
00:30_atobecause Eclipse-the-IDE-compatible makes absolutely no sense
00:30_atoso there's no issues
00:30JAS415yeah
00:32_atowhat the non-eclipse-compatible licenses say is another thing though. But if it's the GPL you're talking about I'd say that's probably okay. It's like using Visual Studio to compile a GPLed project. You don't have to supply the source code to visual studio
00:33JAS415yeah or if you submitted a patch to clojure that used GPL code
00:33JAS415that would be a no-no
00:33somniumpure-blub, not byte-code
00:34JAS415im generating LFE into a text file
00:34JAS415works great :-)
00:35somniumjust wondering, playing with js generation that calls libs like mootools/dojo/jquery
00:35JAS415oh like scriptjure
00:35JAS415yeah that works
00:35somniumclojure-script lite kind-of
00:36JAS415you can either include the (jquery for example) script file as a seperate link or you can slurp it and concatenate them (probably)
00:36somniumbut a clojure generated jquery plugin mould be okay to release under whatever license?
00:36JAS415oh
00:36JAS415we are on licenses
00:36JAS415i think the answer is 'yeah'
00:38somniumbtw, anyone know how clojure finds tail positions?
00:38_atolooks for the last argument in every do form?
00:38somniumdoing a bit of wheel reinvention implementing loop*, though its fun it its way
00:39_atothe recur I hacked into scriptjure looks like: (str "return arguments.callee(" (str/join ", " (map emit args)) ");")
00:40somniumhmm, need to add explicit return so really need to find last node
00:40_ato(that's a non-TCO version though)
00:41somnium_ato: not using scriptjure, but trying to implement loop* as a do-while for loop* and fn*
00:41somniumneed to find every actual tail position though... probably need a zipper
00:44somniumdo ... {blah} while (gensym__recur)
00:44somniumwhere is clojure's recur TCO implemented?
00:47JAS415you could look at core.clj
00:47hiredmanthat's not in core.clj
00:47_atoRecurExpr in Compiler.java
00:47hiredmanthat's in the compiler
00:47JAS415hmm
00:47_atoand various other places
00:47somniumyeah, ive read it, recur and loop* are special forms
00:48JAS415right
00:48JAS415but its like a goto or whatever, right?
00:49_atogen.goTo(loopLabel);
00:49_atodoes javascript have named loops?
00:50_atooh well I guess it doesn't need to if you implement your script's while in terms of loop
00:54timothypratley,(defmacro foo [form] `(println ~form))
00:54clojurebotDENIED
00:54JAS415you can probably implement loop in terms of while
00:55timothypratley(foo (1 2)) <--- doesn't do what I want :)
00:55JAS415err
00:55somniumIve got let* working, and destructuring will just-work (using js primitive arrays and objects), but was hoping someone knew a tail finder algorithm I could just use for TCO
00:55JAS415you need (foo (list 1 2))
00:55JAS415otherwise it evaluates (1 2)
00:56JAS415and 1 isn't a fn
00:56timothypratleyIndeed, but being a macro... isn't there some way to avoid evaluating (1 2)?
00:56_ato~'form
00:56clojurebotexcusez-moi
00:57_atoor wait
00:57_atoit's the other way '~form is what you want
00:57timothypratleyah great!
00:57JAS415yeah
00:57somnium,`(println ~(str '(form)))
00:57clojurebot(clojure.core/println "(form)")
00:57timothypratleythanks.... mindboggling
00:58_atomight be more obvious why as: (quote ~form)
01:00JAS415somnium, you can't do something like:
01:01JAS415while (recur)
01:01JAS415 {
01:01JAS415 (set recur false)
01:01JAS415 (do stuff)
01:01JAS415 }
01:01JAS415recur (bindings)
01:01JAS415 (set recur true bind-bindings)
01:01JAS415and make recur like a macro-ey thing
01:01JAS415and have that while for stand in for loop
01:02JAS415of course you'd still have to detect if it is actually a tail
01:03somniumI want to be able to macroexpand a subset clojure code and compile it to executable js
01:03_atoit's sort-of annoying as you have to track the return value
01:03somnium_ato: yes
01:04somniumI tried to read clojurescript.clj to see how chouser did it but its impenetrable to me
01:04_atoyou also need to deal with javascript's variable scoping, null out all the variables when you break out of the loop and such
01:05somniumno, scoping is easy with containing functions
01:05_atoah right, I thought you were trying avoid the overhead of that
01:05somniumlet* is more or less (function() { ...bindings ... body })()
01:05_atobut yeah, should be doable
01:05_atoah
01:06_atowell that makes your return values easier then
01:06_atocause you can just return
01:06somniumin what im hacking on anyway
01:06_atoif you wrap all loops in anonymous functions
01:06hiredmanthat is an odd way to do let
01:06somniumhiredman: how else to guarantee local scope?
01:07hiredman(function(...names..){body})(..values..)
01:07somniumhmm, almost the same no?
01:08_atohmm
01:08hiredmansure, which is way your way seems so odd
01:08hiredmanlet as a λ like that is right out of sicp
01:08somniumjs is quite lispy
01:09hiredmanit's scheme minus the good bits
01:09_ato(function(x) { while(true) { if (x < 5) { x = x + 1; continue; } else { return x; } } })(0);
01:09somniumat least it has more than a cons-cell :p
01:09_atowould be something like: (loop [x 0] (if (< x 5) (recur (inc x)) x))
01:10hiredmanI've been tinkering with a lisp -> php compiler
01:11hiredmanI'm stopped right now because I think I need to throw out my whol function call and recur implementation
01:11somniumIf I can get recur working, it should be enough to start writing clojure in js in clojure, which sounds fun
01:11hiredmanwhat I currently have won't support varargs nicely
01:12hiredman(or really at all)
01:12somniumI was planning on doing var
01:12somniumargs with the arguments object in js
01:12somniumat least until its possible to get seq working
01:12hiredmanyeah, matching the host is good
01:13hiredmanI did not, and match php up to lisp can be maddening
01:14hiredmanhttp://www.thelastcitadel.com/lab/pl/a.phps generated code
01:16somniumhiredman: it sounds so painful I cant imagine what compelled you :)
01:18somniumhttp://github.com/tenderlove/phuby
01:18somnium^^ might be worth inspiration, or a laugh
01:18technomancyheh... phuby is so ridiculous
01:18technomancy(but it's ridiculous on purpose.)
01:19hiredmancute
01:19technomancyhttp://www.rubyconf.org/talks/60-worst-ideas-ever-
01:28somniumhiredman: I can hardly distinguish your php-compiler's output from idiomatic php
01:28somniumother than the gensyms
01:31James__dWhat does k-lined mean?
01:32hiredmansomnium: well, I did run it through a beautifier for the nice formating
01:33hiredmanbut I would like the generated php code to be ok to deal with without the lisp source
01:34somniumhiredman: isnt 'being okay to deal with' always the achilles heel of php?
01:34hiredman:P
01:43TheBusbyWhat's the best way to return the counts of various values in a list? Ex. '(1 2 2 3 3 3 44) into {1 1, 2 2, 3 3, 4 2}
01:44TheBusbyer, the Example should be '(1 2 2 3 3 3 4 4) into {1 1, 2 2, 3 3, 4 2}
01:45arbscht,(doc frequencies)
01:45clojurebot"([coll]); Returns a map from distinct items in coll to the number of times they appear."
01:45arbschtfrom c.c.seq-utils
01:45TheBusbyarbscht, thank you!
01:46hiredman(apply merge-with + (map #(array-map % 1) (1 2 2 3 3 3 44)))
01:46hiredman,(apply merge-with + (map #(array-map % 1) (1 2 2 3 3 3 44)))
01:46clojurebotjava.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn
01:46hiredmanbleh
01:46hiredman,(apply merge-with + (map #(array-map % 1) '(1 2 2 3 3 3 44)))
01:46clojurebot{44 1, 3 3, 2 2, 1 1}
01:48timothypratley1,(reduce #(assoc %1 %2 (inc (%1 %2 0))) {} [1 2 2 3 3 3 4 4])
01:48clojurebot{4 2, 3 3, 2 2, 1 1}
01:50timothypratley1(defmacro foo [f] `(def ~(symbol (str "foo" (count (meta (var f))))))) <--- how can I make this work? :)
01:50arbschttimothypratley1: that's pretty much how c.c.seq-utils/frequencies is implemented :)
01:51somniumtimothypratley1: what is that supposed to do?
01:51timothypratley1arbscht: yup frequencies is the way to go :)
01:52timothypratley1somnium: I want a macro foo that I can call like (foo defn)
01:52timothypratley1and it will def foo7
01:53timothypratley1so that I can create tests with deftest with a symbol that is dependent on meta-data of another var
01:53timothypratley1(what a tongue twister)
01:56timothypratley1The bit I'm stuck on is getting (var f) hmmm maybe I should be doing (resolve f) or something
01:57timothypratley1omg - that actually works....
01:57timothypratley1sorry for the noise.
02:03KirinDaveMan I see a red line in my history but I cannot find it.
02:03KirinDaveDid someone mention my name or something?
02:27KirinDaveMan, I love it
02:28KirinDaveSomeone hacker-newses my clojure chat
02:28KirinDaveand within 2 hours someone says, "I have a better one in scala. Just install lift!"
03:31LauJensenMorning gents
04:12cgrandKirinDave: I'm interested to know what wasn't working for you with Enlive
04:39Licenser_good morning clojure world!
04:41Licenser_Is there a 'common and good aproach' for writing a clojure app that comunicates over network to send forth and back information/commands
04:41Licenser_implementing a low level protocoll seems a bit of an overkill to me for just sending a bit of information
04:42somniumLicenser_: I dont know, but if you write a wrapper for nio do put it on github :P
04:43carkLicenser : both the server and client are clojure applications ?
04:44Licenser_cark, yap
04:44Licenser_somnium: what is nio?
04:44clojurebotWhat is meta
04:44Licenser_and nice to hear from you again :) how is your mongo driver doing?
04:44carkwell you can easily serialize clojure data structures by printing these then use clojrue reader to get data structures back
04:45carkis that enswering the question ?
04:45carkanswering =/
04:46Licenser_cark: aside of not having a clue how to serialize or deserialzie (but I guess google will tell me that) yap that is what I was looking for I think
04:46somniumLicenser_: java.nio has tools for tcp/ip stuff, with os access to os streams, but a bit low level
04:46carki'm not talking about real serialization, just printing, which is the same, and very easy
04:46somniumbeen using for my attempts to reimplement the mongo driver in clj
04:47Licenser_somnium: ah I see, I don't really want to go into that low level, I mostly want something like sawpn a process, connect to a server be happy and not worry about anything as TCP or below
04:48cark,(read-string (with-out-str (pr '(a b :a :b [1 2 3]))))
04:48clojurebot(a b :a :b [1 2 3])
04:48carkso now you can devise your high lvl protocol based on it
04:49carkcarefull about *read-eval* though
04:49Licenser_cark: you're my hero
04:50cark=)
04:50Licenser_cark: it's a entirely non critical application so I don't worry much about read-eval also I don't think I'll even need it
04:50tomojmunges structmaps though :/
04:51carkwan't there a flag for that ?
04:51carkcan't remember it now =/
04:51tomoj*print-dup* ?
04:51carkah could be yes
04:51tomojthat will just make structmaps print unreadably
04:51tomojat least in my version
04:52carkahwell anyways you get a standard map in the end, so i guess that's good enough for communications
04:52Licenser_Yap it's good enough for me at least
04:53tomojpacking the regular maps you get back into structmaps wouldn't be too hard I guess
04:53tomojwell of course it wouldn't be hard, but I think it shouldn't slow you down much either
04:54tomoj,^(read-string (binding [*print-dup* true] (with-out-str (pr (with-meta [] {:foo 3})))))
04:54clojurebotjava.lang.RuntimeException: java.lang.Exception: EvalReader not allowed when *read-eval* is false.
04:54Licenser_Bottelneck won't be maps, rather waiting for the othser side to do something
04:54Licenser_so I don't worry much about it
04:54tomojoh
04:55tomojwell with *print-dup* and *read-eval* on, you get to keep your metadata
04:55carki think a protocol should be as simple as possible, and decoupled from your internal representation anyways
04:56Licenser_*nods*
04:56tomojc.c.json is easy :)
04:56carkjson isn't good enough in most cases
04:57carki mean, no decimals ?
04:57somniumcark: strings!
04:57carkbleh that's ugly =)
04:57carki have to do this for web stuff, but i hate it
04:57tomojI really like it
04:57tomojbut the choice was already made for me by couchdb anyway
04:57somniumhopefully c.c.json will speed up a lot with types/protocols
04:58carkif you want speed i'm pretty sure there must be som good java json libraries
04:58somniumrecursive multimethod calls really dont show closures strength
04:58tomojhmm that's a good idea
04:59tomojmaybe I will try converting c.c.json to learn the new stuff
04:59tomojstill don't understand it at all
04:59somniumthe one packed with mongo is crazy fast, and jackson is supposed to be really good
05:00somniumjackson has 200 or so classes though :/
05:00carkoh nice a streaming api =P
05:02somniumcark: thats what was recommended to me, but I havent had the determination to wade through the javadoc yet
08:07fliebelHey, What is a good Clojure editor?
08:07Chousukeemacs .)
08:08fliebelI tried emacs today, but its key combinations seem horrid to me.
08:12fliebelMaybe it's a good tool after having used it for years on the terminal, but for me it's not really friendly.
08:13cemerickfliebel: enclojure is pretty nice
08:14fliebelHmm, seems like a good choice since NetBeans also supports Python and PHP if I remember correctly. Somehow Netbeans always make me think 'Java'.
08:15cemerick...and ruby and C++ and scala and javascript... :-P
08:15esji'd say emacs
08:16esjbut really, nothing to get excited about
08:16cemerickI guess it's better to get the editor discussion of the week out of the way early
08:16esjyeah, then we can move onto seque :)
08:17fliebelesj: I find Clojure hard enough, I don't want to learn another 1000 keyboard commands.
08:18tomoj:D
08:18esjfliebel: fair play.
08:18fliebelesj: what's with seque?
08:18cemerickthe number of commands isn't the problem, it's the lack of discoverability because of the 70's terminal UI.
08:19tomojI love the lack of discoverability
08:19tomojit means I am always finding new things :)
08:19fliebelAt least it has the geek factor....
08:19esjfliebel: blocking queues etc
08:19cemericktomoj: yeah, I love a good game of "how the frig am I supposed to do X?" ;-)
08:20tomojluckily that question doesn't come up very often for me
08:20esjcemerick: its usually C-x A-w C-%
08:20tomojbut "oh shit, I can do Y too??" happens often
08:20cemerickesj: see, I don't know if you're agreeing with me or not now. ;-)
08:22esjcemerick: emacs is well weird, no doubt, but uniformly weird - but it work the same on all my computers, OS/s, virtualised blah blahs etc. Time saver.
08:23notallamai was reading about emacs history the other day. more keyboards should have a cokebottle modifier.
08:25esjnoallama: looking that up...
08:28fliebelis vim any better then emacs when dealing with keyboard shortcuts?
08:29esjfliebel: that's the question that has launched 1000 warships.
08:30fliebelI should have known that… especially with Lisp guys like you… Sorry…
08:30esjspace-cadet keyboard: n.
08:30esj A now-legendary device used on MIT LISP machines, which inspired several still-current jargon terms and influenced the design of EMACS. It was equipped with no fewer than seven shift keys: four keys for bucky bits (‘control’, ‘meta’, ‘hyper’, and ‘super’) and three regular shift keys, called ‘shift’, ‘top’, and ‘front’
08:30esjglorious !
08:30tomojwhat are my options for providing configuration for my library? take e.g. a database client library. I don't think I want to have to pass my database config to every library function (or do I?). I also don't think I want to put a binding that provides the config around every place I use the library. is there another way?
08:32tomojor maybe one of these is good and I'm just thinking about it wrong
08:32ordnungswidrighi all
08:33esji'd be interested to hear what ppl think here ? I'd plump for *my-config* and keep the function interface tidy, but then i'm usually wrong :)
08:33noidiis it possible to tell whether a module is being run from a command line as a script, or loaded as a library?
08:33noidiI'd like to have something like python's `if __name__ == "__main__"`
08:39cemericknoidi: (when *command-line-args* ...), if memory serves
08:40cemerickhrm, no, that's probably not right
08:40fliebelCan't you check the namespace? (just a guess)
08:40chousertomoj: having a rebindable var as the only way to pass in the db config is likely to get annoying in several contexts.
08:41tomojyeah, it sounds annoying
08:41chousertomoj: if possible, I'd recommend allow both -- a db arg that, if not given, defaults to *db*
08:41tomojthat doesn't sound too bad
08:42chousernoidi: hm, that's come up before. I have a vague memory of everyone reaching a consensus and then doing nothing about it.
08:43noidi:)
08:43tomoj-main is one way but requires compilation to classes :/
08:43noidithere seems to be a bug in parsing the command line arguments... clojure seems to treat `'foo bar' baz` as `foo bar baz`
08:44noidii.e. it doesn't understand command line arguments with spaces in them
08:44chouseron stackoverflow, someone's recommending *command-line-args*, but that doesn't seem quite right.
08:45chouserthat'll be true for all libs if any command line args were given.
08:47chouserhuh. it's quite a common question.
08:55jonathanturnerI've googled around a bit, but I was wondering if clojure has a zip command. Something like (zip [1 2 3] [4 5 6]) over lazy sequences?
08:55jonathanturnerI didn't know if the clojure one has a different name
08:56chouser,(map vector [1 2 3] [4 5 6])
08:56clojurebot([1 4] [2 5] [3 6])
08:56chouserso depending on what you want to do with it, you may be able to put the next operation right in the 'map' call.
08:59fliebelCan you define macros that do not use sexps? like define _some string_ to turn into (strong "some string") (whatever that might do)?
09:00Chousukethose are called reader macros, and no
09:01jonathanturnerchouser: thanks, and that's lazy as well?
09:01jonathanturnerI was thinking of the equivalent of a lazy seq that's pulling off zipped values
09:02Chousukejonathanturner: map is lazy, so yes. :)
09:02jonathanturnerChousuke: cool, thanks
09:02fliebelChousuke: would that be possible to implement… theoretically? It would be so cool to make your own data types and stuff...
09:02noidifliebel, you could read the code in and modify the result before passing it to eval
09:03Chousukefliebel: well, it wouldn't be too difficult to implement but Rich doesn't want to, at least for now
09:04noidi,(eval (map #(if (= 1 %) 3 %) (read-string "(+ 1 2)")))
09:04clojurebotDENIED
09:04Chousukenoidi: that's not quite as neat as a reader macro :P
09:05fliebelSo, how many kinds of macros are there(that would be cool to have in Clojure)?
09:05noidiyeah, maybe not, I've never used common lisp so I don't know
09:06Chousukefliebel: I think the primary reason for not having a user-extensible read-table is the namespacing issue
09:06noidiI don't like reader macros as an idea, but maybe that's just because I haven't used them
09:06fliebelI like anything that lets you fiddle with the language :D
09:06Chousukenoidi: clojure has many reader macros already. :)
09:06Chousukenoidi: they're just not user-definable.
09:07noidiyeah, I know
09:07fliebelChousuke: where are they defined?
09:07Chousukein the java source
09:07ChousukeLispReader.java
09:07ChousukeBut hm, Common Lisp also has compiler macros
09:07noidimaybe I should learn a bit of CL and give them a try
09:07ChousukeI'm not sure what those do, though.
09:08fliebelWhat are compiler macros? I guess I asked about them a while back, without knowing they where compiler macros.
09:08Chousukenoidi: they're pretty useful sometimes but having them might lead to fragmentation (everyone has their own reader macros for things they think are important) and collision :/
09:08noidiyeah, the collisions are the part that I'm worried about
09:09ChousukeIf you can solve those issues though, maybe you could convince Rich to allow user access to the read table. I don't know :)
09:10noidimy ignorant gut-feeling is that you might as well go all the way and implement a proper parser instead of messing with Clojure's reader
09:10noidiif you want to use a language radically different from Clojure
09:11cemerickI'm guessing that a most if not all of use cases for userland reader macros will be addressed when things wind around to supporting java-in-parens, and similar
09:11ChousukeI've been thinking about having some reader pragma for enabling a user read-table, which would be specific to each loaded file or character stream
09:11duperSay for example I want to use Clojure on the .NET runtime instead of the JVM, what are the advantages it has over pre-existing LISPy .NET dialects, i.e. why would I want to use Clojure instead of something like IronScheme for example?
09:12duper(I'm coming from a Dr/Mz-Scheme and GNU guile background if that makes any difference)
09:12Chousukeso at the top of your source file you could say something like #reader:(use-read-table foo.bar/my-readtable)
09:13fliebelor like the ns definition at the top of some code, just allow users to specify their own read table.
09:13Chousukethe reader doesn't care about the ns declaration though.
09:14Chousukebut if readtable mods were made explicit in every source file, it might not be so bad to have them.
09:15Chousukeat least you'd always have a "warning"
09:17stuartsierraOnce you start messing with the read table, though, you're basically implementing a parser.
09:18fliebelstuartsierra: A lot easier then writing your own language, don't you think? :D
09:18stuartsierrafliebel: maybe, but writing parsers really isn't that hard
09:19chouserduper: Clojure is unique from other lisps in it's first-class support of non-list collections (maps, sets), its seq abstraction, immutability, concurrency support, to name a few.
09:19stuartsierraAnd I've yet to see an example of user-defined reader macros that offers significant advantages over (function "string")
09:21fliebelstuartsierra: I think support for writing regexes or xml in your source is quite cool… sometimes… when used with caution… or not at all…
09:21stuartsierra:)
09:23chouserok, guys. The first chunk of the (as yet untitled) book _fogus_ and I have been working on is about to go out for technical review.
09:23cemerickstuartsierra: we'd *love* to have a reader macro for our regex impl *shrug*
09:23liebkecongrats chouser!
09:24chouserIf any of you have the time to read the whole thing and respond over the course of a week or two (not sure what the deadline is exactly), I can forward your contact info to the Manning editor that's running the review process.
09:24chouserI guess send me a private message with your real name and email address if you're interested.
09:25chouserotherwise you can wait a couple more weeks, get the early-release PDF of the same content, and comment on the book forum which will be up by then.
09:25chouserliebke: thanks!
09:26_fogus_liebke: Thanks!
09:27liebkehey _fogus_! So you still haven't settled the title issue yet?
09:27akingchouser: is it aimed at the beginner, intermediate or advanced user?
09:27fliebelAre you guys writing a Clojure book?
09:27_fogus_liebke: not yet :( Reviewers would probably have a say in the matter
09:28chouseraking: intermediate or advanced. If you're an ambitious beginner it should be sufficient for you, but we're concentrating on really getting inside Clojure's head, thinking the way Clojure thinks about things.
09:28chouserfliebel: yes
09:29shr3kst3rsounds fun
09:30akingin that case, I'll submit my name :)
09:31fliebelchouser: I would appreciate an intermediate book, I'm tired of reading the same beginner stuff at every tutorial, but I'm still not capable of doing anything in Clojure.
09:33noidichouser, sounds great!
09:34noidiimho there's a real need for a book that teaches OO programmers to think in a functional, lazy, immutable way
09:35fliebelnoidi: +1
09:36chouserManning also has "Clojure in Action" coming, which I think is more of an intro book, though it also digs into several very practical real-world examples. I think. I haven't read it yet, but the TOC and first chapters are up.
09:37rysAgreed, something to stop the "hang on, what?" moments if you've never programmed functionally before would be cool
09:39fliebelchouser & _fogus_: Are you programmers writing a book or writers doing Clojure? I read the author of "Clojure in Action" say somewhere on the MEAP forum "This is the first time I'm writing a book", which makes me fear for the quality.
09:41chouserfliebel: we're programmers, but we each have blogs you can peruse to get a sense of how we write. Also, Manning has a great set of (mostly non-technical) editors who have been working to keep up the over-all quality of the content.
09:42fliebelchouser: ok, fine :)
09:42esjthree cheers for more Clojure books ! Thanks chouser.
09:42fliebelChouser: what is the address of your blog?
09:43chouserok, thanks to everyone to volunteered, we'll pass your names along.
09:44_fogus_Yes, thank you all.
09:45chouserfliebel: http://blog.n01se.net/?cat=14
09:45fliebelthanks
09:45chouserfliebel: see also http://blog.fogus.me/
09:46ordnungswidrigchouser: off topic but nice, your md-lvm-migration. Finally I see I'm not the only one trying such things :-)
09:46chouserordnungswidrig: ah, yes ... I'm not the only author on that blog. But I endorse anything agriffis says about lvm :-)
09:46_fogus_fliebel: You will ultimately be the judge if we can write or not, but I can say that we likely have the only Clojure book that quotes Dr. Seuss.
09:48ordnungswidrigchouser: oh, I see. anyway lvm is great fun. Some years ago I remote-repartitioned a root server from a 2-partition installation of red hat into a lvm based debian. The reboots were exciting moment. No remote hands to my rescue...
09:49chouserordnungswidrig: I can relate to that kind of excitement. :-)
09:50ordnungswidrigchouser: btw twitter fails in hrefing your blog's urls. It stops at "?". How annoying
09:51chouserordnungswidrig: Clicking the links should work, I think, even though the url doesn't look right.
09:55ordnungswidrigcan lein do multi-project builds=
09:56ordnungswidrigs/=/?/
11:10patrkriswere there a discussion going on about the CACM-article "Software transactional memory: why is it only a research toy?" once? Can't seem to find it on Google Groups.
11:12reify'""""""""""""""
11:16samlgive me a tutorial for clojure. how to set up a project (or be leech aside java project) and the tutorial should teach frequently used emacs key bindings
11:18ordnungswidrigsaml: emacs can tell you itself
11:19samlbut it tries to tell me too much
11:19samlwell i'll figure out and write a tutotirl
11:20fliebelchouser: On your blog you're writing about Clojure-in-Clojure. Is this really going to happen soon? And will there be an implementation on Parrot?
11:22ordnungswidrigsaml: there are a lot of emacs tutorials around.
11:24samlit shouldn't take more than 10 minutes for the first timer to figure out buffer navigation. emacs fails
11:24_fogus_patrkris: http://groups.google.com/group/clojure/browse_thread/thread/82497ffad880de2b/ (maybe)
11:25samlnever mind. i fail. i found a toturial
11:25patrkris_fogus_: exactly that, thanks
11:29slyrusso, unless I'm missing something obvious, tools like lancet and leiningen are designed for building jars. what do folks use for loading .clj files into an already-running clojure instance?
11:31ordnungswidrigslyrus: swank/slime
11:32ordnungswidrigslyrus: that's what I'd use
11:32slyrusordnungswidrig: well, yeah, of course, i'm using swank/slime :)
11:35slyrusordnungswidrig: yes, a slime-asdf-like contrib that provided slime-load-system that worked with clojure projects would be nice, but it's the underlying asdf-like infrastructure that i'm having trouble finding, not the slime wrapper for such
11:36the-kennyEveryone is waiting for M-x swank-lein :)
11:36slyrusI guess i'm looking for the clojurey equivalent to (asdf:oos 'asdf:load-op ...)
11:36the-kennyslyrus: (require 'namespace)
11:36the-kenny(with the classpth set to the right files)
11:40slyrusthanks the-kenny
11:43MikeDevthe-kenny
11:43MikeDevthe-kenny: pm please?
11:43the-kennyMikeDev: Sure
11:43the-kennyDo it ;)
11:45KirinDave1the-kenny: I wanted to thank you and technomancy for your help yesterday. People seemed to like the chat server.
11:46KirinDave1I need to redditwhore it today, tho
11:47the-kennyKirinDave1: You're welcome :) I'm pleased when I can help
11:48KirinDave1Although the people on news.ycomb were… kinda ridiculous.
11:48KirinDave1Things like, "That's cool, but this scala version written with lift is wayyyy cooler I mean totally."
11:48cemerickKirinDave: live by the YC, die by the YC :-)
11:48KirinDave1Or, "Sure, but the Node.js will scale to thousands of users. Can Java do THAT?!"
11:49KirinDave1I think I am going to make a series out of it.
11:49KirinDave1next up is netty integration
11:50cemerickKirinDave: using what framework, do you think (or, none at all)?
11:50KirinDave1cemerick: ?
11:50KirinDave1cemerick: I dunno. I have never been a java man.
11:50KirinDave1cemerick: Any suggestions would be greatly appreciated.
11:51cemerickKirinDave1: there's a bunch of clojure frameworks that simplify jetty deployment (even beyond the already-simple java-native paths)
11:52KirinDave1cemerick: Jetty is a web framework, right?
11:52cemerickjetty is a webapp server
11:52KirinDave1cemerick: I think I am going to keep this as a raw socket application.
11:52KirinDave1cemerick: As in the spirit of the original node.js submission.
11:53KirinDave1cemerick: But adding major speed+scalability and maybe even SSL without too much code would be a pretty powerful demo.
11:53KirinDave1Don't you agree?
11:53cemerickindeed
11:54KirinDave1So netty provides non-blocking event-driven IO support.
11:54KirinDave1So I don't need to have a thread per user.
11:54cemerickhah, I was assuming 'netty' was a mistyping of jetty
11:54KirinDave1No, I think jetty is a punned name? :)
11:54KirinDave1Or netty.
11:55KirinDave1No idea which came first.
11:55KirinDave1Last time I did java for seriously was in college in 2003.
11:55cemerickjetty has been around for a *long* time, but that doesn't mean anything, I suppose
11:55KirinDave1Back in the Java 2 days
11:55KirinDave1I was happy to discover java.nio.
11:55KirinDave1I consider java.io to be kind of java.io.whoops-sorry-about-that
11:56KirinDave1and it looks like (and sounds like) java.nio is more like java.nio.relax-i-got-dis
11:56KirinDave1Which is good, because in college I was so effing screwed by java efficiency issues on a few of my projects.
11:58ordnungswidrigis there a json pretty-printer for clojure?
11:59ordnungswidrigoh there it is: (org.danlarkin.json/encode-to-str {:a :b :c :d} :indent 4)
12:00MikeDevIs there an HTML parser in clojure that doesn't require external libs?
12:01ordnungswidrigMikeDev: HTML or XHTML?
12:01hiredmanuse tagsoup
12:01MikeDevHTML
12:01hiredmanI should say "no, use tagsoup"
12:01replacaordnungswidrig: or there's a "more sophisticated" but slower version in clojure.contrib.pprint.examples.json
12:02replacaordnungswidrig: the pp version works more like a lisp pretty printer in that it keeps things together on a line when it makes sense
12:02replacaso it's "prettier" :-)
12:05replacaKirinDave1: that chat server example is sweet. Thanks for posting about it.
12:06MikeDevclojure.contrib.tagsoup?
12:07MikeDevdoes tagsoup require external jar file?
12:09replacaMikeDev: yeah. just google and you'll find it
12:10replacaMikeDev: it's a super-common java library
12:10replacaMikeDev: not a contrib piece
12:10MikeDevhttp://home.ccil.org/~cowan/XML/tagsoup/tagsoup-1.2.jar ?
12:10replacaMikeDev: sounds right
12:11MikeDevo great, it has no closure docs
12:13the-kennyMikeDev: I think there isn't a clojure-interface to tagsoup.. just call the java-methods
12:14patrkrisMikeDev: there is a pretty neat interface to tagsoup, it's called enlive
12:14the-kennyOh.. forget what I've said
12:14patrkrisMikeDev: http://clj-me.blogspot.com/2009/01/enlive-yet-another-html-templating.html gives a pretty good idea of what you can do with it
12:15MikeDevgood because i didnt see any docs on it at it's webpage even in java
12:15patrkrisit's pretty cool, since you can select HTML elements using CSS-style selector syntax
12:16replacapatrkris: although enlive is mostly aimed at templating (i.e. transforming html) as opposed to reading
12:16replacareplaca: a cool project would be a tagsoup -> clojure.zip interface
12:17patrkrisreplaca: you are probably correct, but the link I gave above shows how well it can be used for reading HTML (scraping in this case of websites)
12:17replacapatrkris: yeah, I think it woulld just be a simplification of stuff Christophe haas already done in enlive
12:18patrkrisreplaca: as far as I can see it's right there :)
12:18cgrandI started enlive as a templating system but I think there are more people using it for screenscraping than for templating
12:18dnolenpatrkris: enlive is very good at scraping, probably the simplest use of enlive really. enlive also uses clojure.zip. and at 600 LOC can't get much simpler I think ;)
12:19MikeDevWhat I'm trying to accomplish is fetching the text out of header tags
12:19cgrand(-> your-url duck-streams/reader html-source (select [:h1]) text)
12:20MikeDevmy regexp isnt good enough though I was fairly warned by people in #perl
12:20MikeDevso it's my fault
12:20MikeDevit was quicker at the time though
12:20MikeDevcgrand thx
12:20patrkrisMikeDev: forget about regex in this case :)
12:21ordnungswidrigparsing HTML with regex is your way to hell
12:21MikeDevlesson learned
12:21MikeDevbut this isnt production code
12:22patrkrisi think tagsoup is really good at handling almost any html you can throw at it (as far as I've read)
12:22cgrandMikeDev: oops, (map text (-> your-url duck-streams/reader html-source (select [:h1])))
12:23MikeDevjust letting me know that duck-streams reader html-source is what I want is fine
12:24MikeDevbut thnx very much
12:26Licenseraloa
12:30replacacgrand: it doesn't get much simpler than that. very cool - I seem to use only the complex use case and forgot about the simple one :-)
12:35MikeDevis text text that I'm supposed to be matching?
12:35MikeDevit would have to be a function though?
12:36patrkrisMikeDev: not sure if I understand, but text is a function to get the textual contents of a tag
12:36MikeDevdoesnt seem to be defined for me
12:36MikeDevi've use'd duckstreams and reader is defined
12:37patrkrisyes, but these are from clojure-contrib
12:38patrkrishave you referred to enlive correctly (it's on you classpath, you have imported it by means of use/refer/require)?
12:38MikeDevo i need enlive
12:38MikeDevokay
12:38MikeDevi thought i only needed duckstreams
12:38patrkristhat must have been a big surprise for you :D
12:39patrkrisyou need enlive to be able to traverse the HTML from the duck-stream reader
12:41MikeDevI like how github does "hardcore archiving action"
12:42patrkrisyeah :) alternatively you could just get git and clone the repository... probably less hardcore
12:42patrkrisin the archiving-sense of the word
12:46MikeDevdoes enlive depend on tagsoup?
12:47patrkrisyes
12:48MikeDevmy system doesnt have git
12:51hiredmanjust get tagsoup
12:51samltofu soup is good
12:52hiredmanclojurebot: zipsoup?
12:52clojurebotHuh?
12:53hiredmanhttp://github.com/hiredman/odds-and-ends/blob/master/newegg.clj <-- use the zipsoup function from here, Chouser wrote but I can't find the original anymore
12:55MikeDevwhat do you "use" for tagsoup?
12:56cgrandMikeDev: have you leiningen?
12:57MikeDevhuh?
12:58cgrandLeiningen is a build tool that manages dependencies for you.
12:59MikeDevI just dl'ed the jar and included it in my classpath
12:59cgrandAnyway if you click download on github for enlive you should get a zip which include tagsoup
12:59the-kennyleiningen is really cool :)
12:59MikeDevbut having a hard time finding API docs
12:59MikeDevlet alone cloure docs
13:00MikeDevit is SAX compliant though
13:00MikeDevso that's sweet
13:00MikeDevwhatever that is
13:01MikeDevhttp://home.ccil.org/~cowan/XML/tagsoup/tagsoup.pdf maybe
13:01MikeDevboy was that well hidden
13:02cgrandMikeDev: so you have contrib, tagsoup and enlive on your classpath?
13:02KirinDave1Ah, am I not the only person having problems with enlive? :)
13:02MikeDevjust contrib and tagsoup
13:03MikeDevand contrib is use'd
13:03MikeDevtagsoup is a jar
13:03MikeDevuse'd within clojure
13:05cgrandok, then copy the function startparse-tagsoup that hiredman pointed you to http://github.com/hiredman/odds-and-ends/blob/master/newegg.clj
13:05cgrandthen (clojure.xml/parse url startparse-tagsoup) should return a tree of your HTML resource
13:07cgrandKirinDave1: I'd like you know what problems you encountered with enlive
13:08cgrandMikeDev: http://clojars.org/repo/enlive/enlive/1.0.0-SNAPSHOT/enlive-1.0.0-20091121.091400-3.jar if you still want to use enlive
13:09MikeDevand what does zip-soup return?
13:10MikeDevThat tree zipped?
13:10cgrandyup
13:10MikeDevwhat does that mean
13:10MikeDevhere let me see
13:12MikeDevReturns a zipper for xml elements (as from xml/parse),
13:12MikeDevgiven a root element
13:12MikeDevI wish I knew what a zipper was
13:12MikeDevlet me see
13:13MikeDevnavigation, editing,
13:13MikeDevand enumeration.
13:14MikeDevI hate trees in functional langs
13:15cgrandwhich tags do you want to retrieve?
13:16MikeDevheader tags
13:17MikeDevBTW, if this wasnt due this second and for a job, I wouldnt be this stupid
13:17cgrandh1..h4, nothing else, no special classes or any other rules (only header in this div or...)
13:17cgrand?
13:17MikeDevcorrect
13:18MikeDevI just need the header tag's text
13:19cgrand(map enlive/text (-> your-url duck-streams/reader enlive/html-source (enlive/select [#{:h1 :h2 :h3 :h4}])))
13:19cgrandusing zippers directly won't be easier
13:20MikeDevdo I have to 'use' anything for enlive?
13:20cgrand(use 'net.cgrand.enlive-html) ; once enlive is on you classpath
13:22cgrandor (require '[net.cgrand.enlive-html :as enlive]) to match my code snippet
13:23MikeDevnet.cgrand.enlive-htm
13:23MikeDevjava.lang.NoSuchMethodError: clojure.lang.Namespace.importClass(Ljava/lang/Class;)Ljava/lang/Class; (exercises.clj:0)
13:23cgrandnet.cgrand.enlive-html with a L after htm
13:23MikeDev(ns Exercises
13:23MikeDev (:use compojure clojure.contrib.duck-streams net.cgrand.enlive-html)
13:23MikeDev)
13:24MikeDevsee Exercises
13:24MikeDev-l was copying error
13:24cgrandah ok
13:24MikeDevCLASSPATH=Compojure/compojure.jar:/usr/local/jline/jline.jar:tagsoup-1.2.jar:enlive-1.0.0.jar
13:26MikeDev:(
13:26cgrandclasspath hell...
13:28KirinDave1cgrand: Actually I'm just being glib
13:28KirinDave1cgrand: After you put in that zipper patch, it worked.
13:28KirinDave1cgrand: Are you open to patches? Some simple failure cases don't report very informative errors.
13:30MikeDevjava -cp clojure.jar clojure.lang.Repl
13:30MikeDevShould that work?
13:30cgrandKirinDave1: ah, ok it was that bug and yes I'm open to patches
13:30MikeDevHello?
13:31KirinDave1cgrand: Cool.
13:31MikeDevWhy does that work in a shell script but not in cmd line
13:31cgrandMikeDev: try to put your whole classpath after -cp
13:31MikeDevmaybe because I mispelled clojure.jar
13:32cgrandMikeDev: ok, let's try simply java -cp clojure.jar:enlive.jar clojure.lang.Repl
13:33MikeDevyeah that's what I was gonna don
13:33cgrandand then (use 'net.cgrand.enlive-html)
13:33MikeDevnope
13:33MikeDevsame error
13:35cgrandand both jars are in your working directory?
13:35MikeDevO I C. this is your code
13:35MikeDevyes they are
13:36cgrandoops I forgot to include tagousp in the classpath -- did you include it?
13:36MikeDevnope, will try
13:36MikeDevthat works
13:37cgrandphew :-)
13:37MikeDevwait
13:37cgrand:-(
13:37MikeDev1 sec
13:37MikeDevnope
13:37MikeDevdo you have another build?
13:38cgrandyou used the one from clojar?
13:38MikeDevi used the one you had me dl
13:38MikeDevi dont have git on my machine
13:39MikeDevand dont know how to build
13:39cgrandthe one I directly linked to?
13:39MikeDevat least in this stuff
13:40MikeDevi dl'ed:
13:40cgrandthis one: http://clojars.org/repo/enlive/enlive/1.0.0-SNAPSHOT/enlive-1.0.0-20091121.091400-3.jar ?
13:40MikeDevyes
13:40MikeDevlet me do it again
13:40MikeDevcan I rename it?
13:41cgrandsure
13:41MikeDevWhich version of tagsoup u using?
13:41MikeDevi've got 1.l2
13:41MikeDev1.2 excuse me
13:42cgrand1.2 too
13:49MikeDevDO I need to use anything for tagsoup???
13:54MikeDevSo if you do first <zipper> what does that mean?
13:54MikeDevhow are the nodes in a zipper flattened?
13:54stuartsierra48 cores on a chip http://arstechnica.com/business/news/2009/12/intel-demos-48-core-cloud-datacenter-on-a-chip.ars
13:55MikeDevbut I wanted 49 :(
13:56MikeDevdo you have to 'use' anything for tagsoup?
13:57MikeDevit would appear not
14:04MikeDevIs there any way to flatten a zipper? Children?
14:06hiredmantree-seq
14:06hiredmanif you look at newegg.clj it is basically doing what you want to do
14:07MikeDevI am indeed
14:07hiredmanit is grabbing all the td elements from a page, filter out things that don't have their class attribute set to "totalPrice" and picking the last one
14:15MikeDevcomp:
14:15MikeDevcomp f g is f(g)?
14:18hiredman(comp f g)
14:18_fogus_,((comp #(+ 3 %) #(+ 1 1)))
14:18clojurebot5
14:18MikeDevyes is that f(g)
14:18hiredmanf(g) in what?
14:18stuartsierramore like f o g
14:18MikeDevnormal language
14:19hiredmanin algol like syntax f(g) is the function f applied to the argument g
14:19hiredmanwhich comp is not
14:19MikeDevf(g(x))
14:19hiredman,(doc comp)
14:19clojurebot"([f] [f g] [f g h] [f1 f2 f3 & fs]); Takes a set of functions and returns a fn that is the composition of those fns. The returned fn takes a variable number of args, applies the rightmost of fns to the args, the next fn (right-to-left) to the result, etc."
14:19MikeDevyes it's either g(f) or f(g)
14:21_fogus_,(let [f #(println "f o" %) g #(str 'g)] ((comp f g)))
14:21clojurebotf o g
14:21hiredmanf(g) is not function composition in any syntax that I know of
14:22MikeDevand why use first?
14:22MikeDevI have junk at the end
14:22MikeDevis it to get rid of that
14:22MikeDevan extra nil?
14:23hiredman"junk at the end"
14:25_fogus_,(let [f #(println "f o" %) g #(str 'g %) u #(str 'u %) s #(str 's)] ((comp f g u s)))
14:25clojurebotf o gus
14:25_fogus_Couldn't resist
14:25chouserheh
14:27MikeDevYeah, when I do zipsoup I get a vector of what is my html ad then a nil
14:28MikeDevYeah, when I do zipsoup I get a vector of what is my html and then a nil
14:28devlinsfWhy is there space after the o?
14:28MikeDev2 element vector
14:28MikeDevfirst gets rid of the nil
14:28MikeDev(partial tree-seq map? (comp seq :content)) appears to strip out the style
14:29_fogus_devlinsf: println does that
14:29devlinsf_fogus_: Hmm... gonna have to experiment with that
14:29hiredmanMikeDev: it doesn't
14:30devlinsf_fogus_: Oh, i get it! I was assuming that (println "a" "b") is the same as (println (str "a" "b"))
14:30devlinsf,(println "a" "b")
14:30clojurebota b
14:31devlinsf,(println (str "a" "b"))
14:31clojurebotab
14:31devlinsf_fogus_: Hmmm... Interesting behavior
14:31ChousukeI think println is supposed to print a newline
14:31Chousukebut clojurebot filters them out
14:32devlinsfI don't have access to a normal REPL now.
14:32clojurebota is t
14:32chouserMikeDev: the fact that a zip loc is a two-element vector is an implementation detail. use 'node' to get the node at a loc
14:32devlinsfCan sombody quick run it at a normal REPL?
14:33MikeDevor use first
14:34rhickeyfine-grained locals clearing - core and contrib - all tests pass!
14:34rhickeyanyone got any test cases for head-retention? (no big files required please)
14:35devlinsfChousuke: println doesn't interpose a newline
14:35Chousukehm
14:36enouser=> (println "f o" "gus")
14:36enof o gus
14:36enonil
14:36devlinsfTry this at you REPL (println "a" "\n" "b")
14:36devlinsfOnly one newline
14:38MikeDev(partial tree-seq map? (comp seq :content)) appears to add :content in front of every subvector
14:38scellusbtw, what is pmap supposed to do (in the master branch) if i have a lazy seq of lazy seqs. i don't have an example, but i had problems until i wrote doall to realize elements for pmap. otherwise nothing parallelized.
14:38hiredmanMikeDev: it doesn't
14:39stuartsierrarhickey: I was working on this
14:39lisppaste8stuartsierra pasted "Laziness examples" at http://paste.lisp.org/display/91726
14:40MikeDevwell it appears to add something
14:41hiredmanMikeDev: it doesn't
14:42devlinsfChousuke: I just checked the source of println. It eventually calls pr. (pr "a" "b") appears to be the same as (pr (str-join " " ["a" "b"]))
14:42devlinsfChousuke: That is to say, it injects a space
14:43MikeDev(first (zip-soup url))
14:44MikeDev((partial tree-seq map? (comp seq :content)) (first (zip-soup url)))
14:44MikeDevIt appears to create a list of every subtag?
14:44hiredmanMikeDev: does it?
14:45MikeDevyes
14:45chouserMikeDev: the fact that a zip loc is a two-element vector is an implementation detail. use 'node' to get the node at a loc
14:45MikeDevI'm talking about (partial tree-seq map? (comp seq :content))
14:45chouseror don't use zip-xml at all if all you want is the tree and not a zipper
14:46MikeDevI dont think it makes a big diff and I'd prefer to follow hiredman as closely as possible
14:47MikeDev(partial tree-seq map? (comp seq :content)) appears to take the html tree and make a list with every subtag
14:47MikeDevthe first tag is repeated, then the body tag, etc.
14:48rhickeywhere'd stuartsierra go? all of his tests work now. Any others?
14:48rhickeypreferably non-tail usage of seqs, in lets etc
14:49rhickeystuartsierra: all of your examples now work, any others?
14:49MikeDevwhich makes it easier to search for tags
14:50MikeDevbecaue they're all in a sequence now
14:50stuartsierrarhickey: awesome; I will try to come up with some more
14:50MikeDevnext, you search for td tags with
14:50MikeDev(partial filter #(= :td (:tag %)))
14:50stuartsierracgrand or Chouser had an example with large arrays
14:51MikeDevPlease tell me if I'm wrong
14:51MikeDevI'm trying to learn
14:51rhickeystuartsierra: that one runs indefinitely - how long is it supposed to take when it doesn't fail?
14:52LicenserHmm wow network programming (at lest server side) is incredible easy with clojure o.O I'm impressed!
14:52chouserI had one that would run forever if it didn't break.
14:53hiredmanMikeDev: yes
14:53chouserrhickey: ,(let [s (iterate #(java.util.Arrays/copyOf % (count %)) (int-array (range 1e7)))] [(first s) (last s)])
14:54chouserrhickey: rather, (let [s (iterate #(java.util.Arrays/copyOf % (count %)) (int-array (range 1e5)))] [(first s) (last s)])
14:54MikeDevcould I replace (= :td (:tag %)) with some kind of regexp for maching any h1-h6
14:54MikeDevtags
14:54MikeDevyes I'm wrong?
14:54chouserit's meant to fail fast, not necessarily demonstrate somethng that's supposed to work.
14:54rhickeychouser: yeah, ran that, runs indefinitely
14:55chouserok
14:55cgrandMikeDev: (#{:h1 :h2 :h3 :h4 :h5 :h6} (:tag %))
14:55rhickeyso, this is full liveness tracking for all locals
14:55chouserwait, really? I assumed that would be impossible
14:55stuartsierrame too
14:55hiredmanMikeDev: you can replace it with any function that will return a logical true value for things you want to keep
14:56rhickeywith liveness tracking, s is cleared before last is called
14:56chouserwow!
14:56rhickeyyeah, Clojure's biggest incidental complexity now gone
14:57rhickeypending lots of testing, this was a very complex change
14:57stuartsierraawesome, amazing, unbelievable!
14:57chouserI can only imagine.
14:57rhickeyI'd just like to run a few more tests if anyone's got any failure cases, before I push
14:57chouserat this rate we're never going to need clojure-in-clojure
14:58cgrandliveness tracking? awesome!
14:58rhickeychouser: I really wanted to wait, but too many people are tripping over it, and worse, designing clunky non-workarounds
14:58stuartsierrayes
14:58ericthorsenrhickey: is this change in the 'new' branch as well?
14:58rhickeyso now, if you aren't using it any more, you aren't holding it
14:58rhickeyericthorsen: will be in a few minutes
14:58rhickeyyou can use large seqs in let etc
14:59rhickeyno more limit to tail call clearing
14:59rhickeyjust one extremely painful lost weekend :)
15:00stuartsierraThis is really going to make sequences much more powerful, instead of a clever trick.
15:00rhickeythere must be some more examples in the group...
15:00MikeDev{}'s are sets?
15:00stuartsierraThe most common case is reading a large file line-by-line.
15:01stuartsierrarhickey: I assume this will also work with iterator-seq?
15:01rhickeystuartsierra: it is independent of the type of seq
15:01LauJensenliveness tracking O_o? :) Does that incur some kind of overhead or how is that implemented?
15:01MikeDevSo the last thing I need is to filter based on the text'edness of the content
15:02rhickeyLauJensen: basically the last use of a local clears it (before the use)
15:02rhickeywherever that use occurs, not limited to tail call arg
15:03rhickeydata structure inits, callis in the middle of do, lets, etc
15:03LauJensenWow, cant wait to give that a test-drive
15:03chouserMikeDev: {} make a map, #{} makes a set
15:03stuartsierrarhickey: Is this pushed yet? I want to test with my hadoop wrapper lib.
15:03rhickeyso, now based upon use, not merely local bound in scope
15:03chouserMikeDev: rather, {} is a map, #{} is a set
15:04rhickeyI guess pushing it is the best way to get it tested...
15:04stuartsierra:)
15:04Chousukeyay
15:04stuartsierraWill this make it into 1.1 then?
15:05chouserheh
15:05ChousukeThis is a big usability improvement for Clojure. It was sometimes pretty difficult to tell whether you were holding onto something or not :/
15:05stuartsierraAnd all because of a bug in the JVM. :)
15:06MikeDevWould it be worng once I had a handful of headers to use regexps on the contents?
15:06LauJensen~regex
15:06clojurebotSometimes people have a problem, and decide to solve it with regular expressions. Now they have two problems.
15:06chouserthis is true.
15:07rhickeystuartsierra: not in 1.1, no
15:07cp2sounds neat
15:07stuartsierrachouser: Of every technology ever invented.
15:07chouseralso true is that if you have some text you need to process, regex is frequently the best solution available.
15:07chouserstuartsierra: yessir
15:08LauJensenWhats the name of that functional text parser in Clojure, which gives an alternative to regex?
15:08stuartsierrarhickey: I guess that's reasonable, given the newness.
15:08MikeDevOkay so how should I approach finding only textful headers given that I have all of them in a map?
15:08hiredmanLauJensen: fnparse?
15:08MikeDevA list of maps
15:08LauJensenhiredman: Thats the one
15:09rhickeystuartsierra: it's also a huge compiler change, and there are already a lot of huge compiler changes in new - I dread merging them
15:09stuartsierrarhickey: fair enough
15:09rhickeyok, it's up
15:10LauJensenMikeDev: Are you looking for items that are solely alpha-numerical ?
15:10MikeDevPretty much
15:10MikeDevcertainly no subtags
15:12MikeDevthis is only an exercise
15:13stuartsierrarhickey: great, is it on a particular branch?
15:13rhickeynew
15:13stuartsierraok
15:13rhickeyhttp://github.com/richhickey/clojure/commit/76c8f45293987b80e3599535dd86482e1180661d
15:14MikeDevI might do "[A-Za-z0-9 .-]"
15:14MikeDevI might do "[A-Za-z0-9 .-]+"
15:14_fogus_That's a lot of green
15:16rhickey_fogus_: heh, I was just going to say - it doesn't look like much now, the hard part being figuring out how to enable the feature with minimal change
15:19rhickeywe need to get 1.1 out so we can get 1.2 out
15:19_fogus_rhickey: I take that back, relative to the total file size it's actually *not* a lot of green. Github just highlights the greeness in the commit view.
15:21stuartsierrarhickey: yes yes
15:21MikeDevWhat is #(= :td (:tag %))
15:21rhickeyfeedback welcome on the locals clearing in new - be on the lookout for 2 things - 1)bad - premature clearing (set to null before last use), most likely will show up as NPE, 2)insufficient clearing - local stays around
15:21hiredmanMikeDev: it is a function
15:22MikeDevwhat arg does it expect?
15:23MikeDevIt's comparing its arg to what tag maps to to see if it's equal to td
15:23MikeDevbut I dont understand how it doesn that
15:24LauJensenMikeDev: Do you know how to do the basic selecting with Enlive?
15:24MikeDevcgrand and I couldnt get enlive working for me
15:24devlinsfrhickey: if I'm reading assembla right, ticket 218 is the only thing holding up RC1 (or Beta 1, whatever you want to call it)
15:25LauJensenMikeDev: 'Cgrand .... couldnt get it working' is not a possible scenario
15:25MikeDev (map text (-> your-url duck-streams/reader html-source (select [:h1])))
15:25dnolenI missed the early part of the locals clearing discussion, is not have to care about holding onto the head of a lazy data structure the main benefit or are there others?
15:25rhickeydevlinsf: 1.1 is not waiting for patches, but all the peripheral stuff surrounding a release
15:25MikeDevWhat are you talking about
15:25devlinsfrhickey: docs, tests & stuff?
15:26LauJensenMikeDev: Enlive requires 2 things, enlive.jar and tagsoup.jar, put those on your class path, see in (System/getProperty "java.class.path") that they are there, and Enlive will work
15:26MikeDevi did that and got
15:26drewrlooks like locals clearing breaks something in the socket code with swank-clojure
15:27drewrtrying to isolate
15:27hiredmanMikeDev: so the zip-soup function returns the html structure as a set of nested maps and vectors
15:27MikeDevjava.lang.NoSuchMethodError: clojure.lang.Namespace.importClass(Ljava/lang/Class;)Ljava/lang/Class;
15:27drewrgetting an NPE in a macro that I need to expand
15:27hiredmantree-seq flattens it out
15:27rhickeydevlinsf: http://groups.google.com/group/clojure-dev/browse_frm/thread/be3f0a7c26ee2fd6
15:28hiredmanMikeDev: import is for java classes only
15:28rhickeydnolen: it is primarily a benefit for use of lazy seqs, yes
15:28dnoleni note that the locals clearing change breaks swank-clojure: java.lang.Exception: No such var: swank.swank/ignore-protocol-version (NO_SOURCE_FILE:3)
15:28MikeDevso
15:28MikeDevI dont use import
15:28MikeDevenlive must
15:28devlinsfrhickey: yeah, I'm in that thread.
15:28dnolenrhickey: fantastic
15:28devlinsfrhickey: So can I assume master is stable, and I can start testing that?
15:28hiredmanMikeDev: I hear enlive depends on tagsoup
15:28LauJensenMikeDev: Try putting all 3 jars in the same directory and run java -cp clojure.jar:enlive.jar:tagsoup.jar clojure.main and then type import enlive
15:29hiredmanLauJensen: import?
15:29MikeDevuse
15:29LauJensenuse, require, something :)
15:29MikeDevhe told me to use
15:30LauJensenthen use
15:30hiredmananyway, when I did newegg.clj I was thinking of using enlive or zip-filter, but by the time chouser answered the question I asked here, I had the tree-seq version working :P
15:30LauJensenIf you do that, it will work, or you're on Windows
15:30MikeDev<cgrand> (use 'net.cgrand.enlive-html) ; once enlive is on you classpath
15:30LauJensenyes, thats correct
15:30MikeDevthat's what causes the error above
15:31hiredmanodd
15:31MikeDevhe left
15:31hiredmanwhere did you get the enlive jar from?
15:31MikeDevcgrand ent me a link
15:31MikeDev1 sec
15:31hiredmanwhat version of clojure are you using?
15:32MikeDevhttp://clojars.org/repo/enlive/enlive/1.0.0-SNAPSHOT/enlive-1.0.0-20091121.091400-3.jar
15:32MikeDev1.0.0
15:33MikeDevclosure v1.0.0
15:33hiredmanj
15:33MikeDevis there something to print on the repl to doublecheck
15:34hiredmanthat enlive jar might not work with clojure 1.0
15:34hiredmananyway
15:34rhickeydevlinsf: yes, please use master
15:34MikeDevwhich should I try?
15:34hiredmanyou were 70 to 80 percent done with tree-seq
15:34MikeDevyeah
15:35hiredmanbefore random people popped in and started suggesting you do other things
15:35MikeDevand u said I should do things that way
15:35MikeDevand u r smart
15:35hiredman#() is an anonymous function
15:35MikeDevplus it helps me learn
15:36hiredman#(a b %) ~= (fn [x] (a b x))
15:36MikeDevwell basically if I'm not using regexps, what do I use on the content of my headers?
15:37jonase_I pulled the 'new' branch and now I get "java.lang.IllegalStateException: Var null/null is unbound. (matrix.clj:37)" when trying to load the code in http://gist.github.com/234535
15:37hiredmanMikeDev: you can use regexs or whatever you want
15:37MikeDevthey told me not to
15:37hiredmanMikeDev: you understand how filter works?
15:37twbrayWhat's the idiomatic way to turn {:a 10 :b 20 } into {:a 11 :b 21}, i.e. do a map on a map and get a map?
15:37hiredmanMikeDev: I imagine they were not paying attention and assumed you were parsing the entire html document with regexs
15:37MikeDevok
15:38MikeDevi did clearly say I had the headers
15:38MikeDevbut no complaints
15:38lpetittwbray: it depends, what do you want to do ?
15:38lpetit,(doc merge-with)
15:38clojurebot"([f & maps]); Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with the mapping in the result by calling (f val-in-result val-in-latter)."
15:38lpetitwhoops
15:38MikeDevfilter takes a function, applies it to each element and returns those elements for which the functions returned true
15:38Licenseruch
15:38hiredman,(let [m {:a 10 :b 20 }] (reduce #(update-in %1 [%2] inc) m (keys m))
15:38clojurebotEOF while reading
15:38hiredman,(let [m {:a 10 :b 20 }] (reduce #(update-in %1 [%2] inc) m (keys m)))
15:38clojurebot{:a 11, :b 21}
15:39Chousuketwbray: (into {} (map (fn [[k v]] [k (inc v)]) themap) will work
15:39twbraylpetit: I have a map. I want to produce a new map with the same keys and values produced by running a func over the input values
15:39lpetittwbray: you have the answer above :)
15:39clojurebotYou will not become skynet
15:39twbrayChousuke: Thanks
15:39hiredmanMikeDev: so you can write any function you want
15:39lpetit,(doc map-vals)
15:39clojurebotPardon?
15:39MikeDevyes
15:40hiredmanI would first recommend filtering for headings, which I think chouser or Chousuke pasted a function for
15:40MikeDevthat's what I'm doing I think
15:40rhickeylpetit: one question about a map-vals, should ht efn take the val or key + val, or [key val]?
15:40MikeDevhere:
15:40MikeDev((partial filter #(#{:h1 :h2 :h3 :h4 :h5 :h6} (:tag %))) ((partial tree-seq map? (comp seq :content)) (first (zip-soup URLArg))))
15:41MikeDevthat gets me the headers I want
15:41hiredman:(
15:41hiredmanI guess
15:41Chousukeurgh, too much point-freedom
15:42hiredmanso then you need to filter again based on whatever regex or what have you
15:42rhickeywas anyone able to isolate the swank problem with fine-grained locals clearing?
15:42MikeDevok
15:42MikeDevi was trying that
15:43MikeDev(partial filter #(re-find #"^[A-Za-z0-9 .-]+$" (:tag %)))
15:43MikeDevnope
15:43MikeDevoh, hell i mean content
15:45lpetitrhickey: is it a serious question, or was it asked to demonstrate that it's not possible to provide such a function ?
15:45MikeDevnetsplits!!!
15:46MikeDevwelcome back
15:46MikeDevjava.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.CharSequence
15:46rhickeylpetit: yes, serious, not a difficult function, just tricky to spec a useful version. Mapping inc across vals isn't too hard without it, but there aren't many k+v - taking functions around yet.
15:46Chousukethere's nothing wrong with using parametrised functions, you know.
15:46Chousukewhy are you even using partials there?
15:46hiredmanChousuke: he doesn't know clojure so he is just copy and pasting me code around
15:46rhickeylpetit: that's what's held up something like map-vals
15:46MikeDevChousuke, because hiredman and jesus wanted it that way
15:47Chousukeisn't that just (filter (comp :tag #{:h1 ...}) (tree-seq map? (comp seq :content) (first (zip-soup URLArg))))
15:47Chousukehiredman: you have a bad influence on people :(
15:47hiredmanMikeDev: I didn't, I showed you an example of code that does something similar to what you want
15:47hiredmanand you are cargo culting it
15:47MikeDevcargo culting: I like it
15:48hiredmanhttp://en.wikipedia.org/wiki/Cargo_cult_programming
15:48MikeDevis that a real phrase?
15:48Chousukehm, wait. args in comp are the wrong way around
15:48MikeDevI'd have said black boxing
15:48Chousuketry to write code that you understand yourself :)
15:48hiredmanor at least try to understand the code you write
15:49lpetitrhickey: here are my own (freshly translated from french for your pleasure :-) versions I used at work : http://paste.lisp.org/display/91728
15:49MikeDevi will when it's not due 5 hours ago
15:49chouserrhickey: have you thought at all about compiler-macros, or something like them?
15:50hiredmanMikeDev: well, maybe it is for the best
15:50rhickeychouser: not too much
15:50lpetitrhickey: needs were value (not key+val).
15:50rhickeychouser: I'd much rather have symbol-macrolet
15:52devlinsflpetit: I've been talking about this on the dev list for a while
15:52stuartsierrarhickey: someone did symbol-macrolet in contrib http://richhickey.github.com/clojure-contrib/macro-utils-api.html
15:52devlinsfhttp://groups.google.com/group/clojure-dev/browse_thread/thread/9a518c853bfbba8b
15:52chousera macro that expands to something that includes a symbol-macrolet would be pretty powerful.
15:52devlinsflpetit: I'm partial to a visitor solution now
15:53lpetitdevlinsf: ?
15:53devlinsflpetit: You'll see it at the end of the thread
15:53thehcdreamerAnyone know how I can uninstall gitosis from my server? Google isn't helping me
15:53thehcdreamersorry wrong channel
15:53chouserdevlinsf: I've read your latest proposal at least once -- sorry I haven't responded. My gut reaction is much more positive now.
15:54devlinsfchouser: Life happens
15:54dnolenrhickey: not sure if this helps, http://gist.github.com/251096, this is the source of the error and the related fns
15:54devlinsfchouser: Good to hear it
15:57dnolenrhickey: also this is the macroexpansion for the offending function, http://gist.github.com/251100
15:58MikeDevhiredman, but you dont understand the business implications. Clojure is the sort of thing where I bet it's really hard to find someone who knows it so they're actually hiring newbies. To get a PHP job you need 5 years experience plus high volume experience the latter of which I'll never get
15:58MikeDevPlus when you do get a PHP job, you have a PHP job and why would you want that
15:59Chousuke:)
15:59hiredmanMikeDev: sure, but you plainly don't know any clojure
15:59MikeDevI've been at it for 3 days. I can learn
15:59ChousukeDo you have the book?
15:59MikeDevnot yet
16:00arohnerlpetit: those functions look pretty similar to mine
16:00lpetitdevlinsf: sorry, but I don't know exactly why, but when I read "visitor pattern", some warning flashes in the back of my head. Must read your (rather comprehensive!) post carefully, not sure I'll be able to do so right now.
16:00MikeDevIf I get the job I will buy the soft and hard copy
16:01rhickeydnolen: thanks, I'll see what I can make of that
16:01devlinsflpetit: No problem. Feel free to post or email any questions
16:01lpetitdevlinsf: sure
16:02ChousukeMikeDev: anyway, try to avoid point-free style (the partials and comps) in the beginning
16:02MikeDevI just need to get this job. They'll help me learn it if I can just get my foot in the door
16:02ChousukeIt's so easy to make code look magical when you omit the explicit parameters :/
16:03Chousukewhat's your current problem?
16:03MikeDeva couple of exercises. i've given up on the second
16:03MikeDevright now the problem is a regexp for the contents
16:03MikeDevof the headers
16:05lpetitarhoner: I guess lots of uses of maps are for easily accessing their values. And then, either the keys are not relevant for functions having to process the values (e.g. keys are at a different level of abstraction than the values, e.g. keys are technical identifiers, values are business meaningful), either the keys have some meaning at the same level of abstraction than the values, and then...
16:06lpetit...chances are that the value already embeds the key value somewhere inside it. But that's just a quick generalization from the kind of problems I'm faced with, so maybe it's not true at all for most of the cases (I don't say "the general case", I don't think there exists a general case for such generic functions ?)
16:06ChousukeMikeDev: doesn't sound too difficult
16:06MikeDevand eventually I'd like to turn the list of maps into a list of 2ple vectors
16:06MikeDev([headername headercontent] ...)
16:06ChousukeMikeDev: just keep in mind the structure of the data you're working with, and then filter and process it one step at a time.
16:07MikeDevwhen I think back to learning ML, this was not how I did it
16:07arohnerlpetit: I don't need to go that far for an explaination. Often, I just need to transform a map, like
16:07arohner(map-keys keyword coll)
16:08lpetitarohner: I was testing my arguments on you, before explicitly directing them to Rich :-)
16:08MikeDevat least I can read what most stuff is now
16:08MikeDevtypes
16:09ChousukeMikeDev: well, say you have a list of strings and you want a list of all strings starting with "s", uppercased. The easiest way to do that is of course is to filter first, yielding another seq of strings, and then uppercase those
16:09rhickeydnolen: did swank-clojure work with the prior checkin of new branch?
16:09dnolenrhickey: yes, I did a git reset --hard HEAD^ just to make sure
16:09MikeDevU have all been very patient, ty
16:10ChousukeMikeDev: it really doesn't get much more complicated, if the problem really is just data filtering
16:10ChousukeMikeDev: and thanks to lazy seqs, you won't actually be going through all the data multiple times.
16:12ChousukeMikeDev: and remember, even maps can be treated as seqs of [key value] pairs
16:12MikeDevthen maybe I wont have to convert that then
16:13MikeDevwait, yes I will
16:13MikeDevcuz I want [headername headertext] not [:tag h1, :content "blah"]
16:14MikeDevexcuse me, {:tag h1, :content "blah"}
16:14Chousukeyou have a seq of maps {:tag "h1", :content "blah"} or something?
16:14Chousukeand you want to select all "hN" tags, right?
16:14MikeDev({:tag :h1, :attrs {:style "width: 200px; margin: 20px auto; text-align: center"}, :content ["Results Table"]} ...)
16:14arohnerdo deftypes respect *print-length* yet? I seem to be getting stackoverflows when printing a circular datastructure of deftypes
16:15MikeDevlist of maps
16:15MikeDevI want to get all the tags whose content is text
16:15hiredmanChousuke: the selecting all the hN tags should already be taken care of
16:15MikeDevdoesnt have subtags
16:15Chousukehmm, right.
16:16Chousukethat's why you need the tree-seq
16:16MikeDevyes, it flattens
16:16MikeDevbut some of the header tags could have ,a. tags
16:16MikeDev<a> tags
16:16MikeDevOr more likely with bad html, god knows what
16:17Chousukewell, filter those out after you've selected the header tags?
16:17MikeDevI dont wanna have to parse that crap further
16:17MikeDevso now that I have the header tags, I just wanna dump everything without nice text in it
16:18Chousukethat's another filter then, right?
16:18MikeDevyep
16:18MikeDevbut this one I cant copy from hiredman
16:18Chousukehmm. can't tagsoup sanitise html?
16:19Chousukemaybe it could remove any malformed crap for you.
16:19MikeDevaccording to it's site, htmltidy is what you'd want for that
16:19Chousukeah. okay.
16:19MikeDevbut this isnt production
16:19Chousukewell, maybe you can just use a regexp then :/
16:19MikeDevthis is just for an exercise
16:20MikeDevbut I dont want it to bomb on certain sites like it was before
16:20MikeDevwhen I did this:
16:20MikeDev"<(h[1-6])>(?:<.*?>)*(.*?)(?:</.*?>)*</h[1-6]>
16:20MikeDevthought that was an attempt to drill down into tags
16:21MikeDevthe worst thing about that was, it allowed <h1></h2>
16:21Chousukemaybe select h-tags without flattening first and then filter out any tag content from them?
16:21MikeDevi dont like that
16:21Chousukeupdate-in is pretty good for transforming maps
16:22MikeDevwell it doesn't flatten recursively
16:22MikeDevit does a search and makes copies into a list
16:22Chousukehmm :/
16:22MikeDevthink of it as any header subtree is added to a list
16:24MikeDevactually I suppose if someone did <h1><h2>srgwrg</h2></h1> i'd get the h2
16:24MikeDevthe list would be 2 elements, the h1 tag and the h2 tag
16:25arohnerrhickey: I seem to have a bug, where I get a stack overflow if I try to print a deftype that contains a cycle with other deftypes. should I file a bug?
16:26MikeDevcan you use - ' " in clojure regexps
16:26arohneractually, it's worse than just printing, because using slime to reload the file can also cause the stack overflow, if the last expression returns the type with a cycle
16:27MikeDevwith escapes \?
16:27MikeDevdont think it's letting me
16:28rhickeypotential fix for swank-clojure + fine-grained locals clearing up in new branch: http://github.com/richhickey/clojure/commit/6c0c37e048f49ee5cd3afa79ce461abbc6a0c367
16:28rhickeyarohner: yes, thanks
16:29chouserMikeDev: you can use \" in a literal regex to match " ... no need to escape '
16:29technomancyrhickey: I haven't gotten a chance to give the new branch much attention; does it necessitate changes to swank-clojure?
16:29chouser,#"'"
16:29clojurebot#"'"
16:29arohnerrhickey: should I work on a patch? I'm effectively blocked. the fix looks simple, just add checks for *print-level* to print-deftype
16:30rhickeytechnomancy: hopefully not, I pushed a change today that broke swank, just pushed a fix - need someone to try it
16:30rhickeyarohner: sure
16:32MikeDevhow about POSIX character classes like [:alpha:]
16:32chouserMikeDev: everything Java regex supports.
16:33chouserMikeDev: http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html
16:34arohnerrhickey: can you please promote me to member on assembla?
16:36technomancyrhickey: trying new+swank now. anything specific I need to do to trigger the potential problem or is it pretty obvious?
16:37chouser(deftype Foo [x]) fails with java.lang.IllegalStateException: Var null/null is unbound. for me, latest 'new'
16:37chouseranybody else seeing that?
16:38rhickeytechnomancy: got me, seems like it fell right down before
16:39rhickeychouser: yes, looking at it now
16:40MikeDevThis seems to be serviceable: (re-seq #"<(h[1-6])>([^<>]+?)</h[1-6]>" HTMLArg)
16:42ataggartwas the change from ^ to #^ just for consistency?
16:43MikeDevwho me?
16:44MikeDevAFAIK #"blah" is a regexp pattern
16:44chouserataggart: #^ hasn't changed. ^ is going away because (meta ...) is already there, ^ is not the inverse of #^, and ^ is wanted for other things
16:44ataggartah, no I meant the change to the reader. https://www.assembla.com/spaces/clojure/tickets/215-Deprecate-^-reader-macro
16:45ataggartk
16:46rhickeychouser: fixed
16:46technomancyrhickey: hrm; looks like the example dnolen gave doesn't compile regardless of the new branch or swank version. =\
16:48technomancyI'll try again if I see him come back online
16:50rhickeytechnomancy: this was is first report: i note that the locals clearing change breaks swank-clojure: java.lang.Exception: No such var: swank.swank/ignore-protocol-version (NO_SOURCE_FILE:3)
16:50chouserrhickey: great, thanks.
16:51chouserdeftype objects seem to respect *print-level* for me
16:53chouser(deftype Foo [x]) (nth (iterate Foo 1) 20)
16:53chouserinnermost prints as #:Foo{:x #:Foo#} if capped by *print-level*
16:55rhickeychouser: maybe the problem was mutually recursive structures?
16:56arohnermy structure is mutually recursive. trying to reproduce with a smaller example now
16:58chousernot sure what you mean. this also works (nth (iterate (fn [x] #{(Foo x)}) 1) 20)
16:59arohnerlisppaste8: url
16:59lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
17:00lisppaste8arohner pasted "deftype circular explosion" at http://paste.lisp.org/display/91733
17:01chouserare you sure you have *print-level* set?
17:02arohnerchouser: arg, no, only *print-length*
17:03chouserah, that'll do it. :-/ sorry.
17:03arohnerwell, thanks for "fixing my bug"
17:03arohner:-)
17:03chouserI generally set *print-length* to 103 and *print-level* to 15
17:03chouserseems to work well most of the time for me.
17:04MikeDevSo to what extent do people here think clojure has a bright business future?
17:04arohnerI'm surprised the default for print-level is nil. once I had a circular structure, everything broke quickly
17:05arohner102 is too small, but 103 is just right?
17:05arohner;-)
17:05chouserexactly
17:06hiredmanMikeDev: there are four or five startups with JRuby on Rails frontends and Clojure backends
17:06chouserarohner: don't want an even number in case it makes me think something is working (stopping at the right length) when it's not.
17:06LauJensen~source ->
17:06MikeDevhow long has the lang existed?
17:07durka42two years
17:08MikeDevwell basically the way you make money is by picking up a lang early, having it grow like crazy while getting 5 years experience with it
17:08chouserreally?
17:08MikeDevthen you're set
17:08MikeDevyep
17:08chouserhuh
17:08MikeDevthen you can consult wherever
17:08hiredmanchouser: and here you thought it was in publishing books
17:09chouserif only I'd known!
17:09MikeDevchouser, you publish the book?
17:09chouserMikeDev: working on writing one. It's not out yet.
17:13MikeDevThe company I want to work for is somehow gonna use it to make websites work on mobile phones more automagically
17:13MikeDevat least that's the plan
17:14MikeDevsound like a good idea?
17:14MikeDevgood pairing of lang with problem?
17:20the-kennyhm.. I think clojure is well-suited for that problem
17:21MikeDevhi, well I gave up on the macro thing
17:22the-kennyMikeDev: I don't understand why you don't understand macros, so I can't help you... sorry.
17:22MikeDevwell I think I kinda understand macros, just not how they could do what is in that problem
17:23MikeDevI understand how they can be used to replace text however
17:26ChousukeMikeDev: I think that's the problem. they are not text replacement :/
17:28Chousukemacros are code-generating functions; and unlike most languages, Clojure code is made of lists and symbols and other data elements and structures.
17:28the-kennyMikeDev: they are there for modifying clojure syntax at compile time
17:29hiredman,pl
17:29clojurebotjava.lang.Exception: Can't take value of a macro: #'sandbox/pl
17:29hiredmanexcellent
17:31hiredman,(pl reverse $ (↕reduce range $ 10 () λxy (↕conj inc $ y x)))
17:31clojurebot(1 2 3 4 5 6 7 8 9 10)
17:32the-kennyclojurebot: with-out-str
17:32clojurebotExcuse me?
17:32ChousukeMikeDev: anyway, to build the macro, start with manually coding one instance of the code your macro is supposed to generate
17:33the-kennyMikeDev: For an example take a look at with-out-str
17:34hiredman,(macroexpand-1 '(with-out-str (println "foo")))
17:34clojurebot(clojure.core/let [s__6049__auto__ (new java.io.StringWriter)] (clojure.core/binding [clojure.core/*out* s__6049__auto__] (println "foo") (clojure.core/str s__6049__auto__)))
17:34the-kennyMikeDev: For an example take a look at with-out-str at: http://github.com/richhickey/clojure/blob/master/src/clj/clojure/core.clj#L3129
17:34hiredman(with-out-str (println "foo"))
17:34hiredman,(with-out-str (println "foo"))
17:34clojurebot"foo\n"
17:35the-kennyIt binds *out* to a string-writer and evaluates it's "arguments" in the let
17:35the-kennys/let/context/
17:35Chousuke,(letfn [(foo [x] `(+ y ~x)] (foo 'somesymbol)) ; foo is basically a macro... it's just not marked as one, so its arguments need to be quoted and the result is not evaluated :)
17:35clojurebotUnmatched delimiter: ]
17:35Chousukegah
17:35the-kennywhops, I pasted the code to wth-in-str, but it's basically the same
17:35Chousuke,(letfn [(foo [x] `(+ y ~x))] (foo 'somesymbol))
17:35clojurebot(clojure.core/+ sandbox/y somesymbol)
17:41Chousukehmm
17:42ChousukeI suppose it might help to just think of the syntax-quoted form as a template rather than worry about constructing lists too much :/
17:44ChousukeI guess it'd enable writing simple macros even without completely understanding them
17:47piccolinoI'm trying to write a library that has some macros that generate Clojure code. And I'd like to be able to insert calls to private functions from the library's namespace into the code that gets output. But it seems I need to make those functions public for this to work at runtime.
17:47piccolinoIs that corret?
17:48piccolinocorrect?
17:48ataggartyes.
17:49jwhitlarkAm I doing something wrong, or does -Xbootclasspath not play nice with files like clojure.test?
17:49chouserpiccolino: I don't know if it's passed to the level of idiomatic yet or not, but you can use the var instead
17:49ataggartsince the funciton is actually being called from the ns intowhich the macro was expanded
17:49MikeDevthanks everybody
17:49piccolinoThe var?
17:49chouserpiccolino: ((var myns/foo) ...) instead of (myns/foo ...) -- then foo can be private
17:50jwhitlarkWhen I (use 'clojure.test) with the -Xbootclasspath, I get java.lang.ExceptionInInitializerError (NO_SOURCE_FILE:0)
17:50polypusis there some convention for namespace naming of clojure projects hosted on github and clojars? like should i use my username in the namespace, etc?
17:52piccolinoOh, cool, thanks chouser. Wasn't aware of that.
17:53chouserpiccolino: for short, (#'foo ...)
17:53piccolinoYeah, I just saw that in the docs.
18:19technomancyjwhitlark: I saw that too.
18:19technomancyjwhitlark: transitive requires inside -Xbootclasspath files are problematic
18:20technomancyyou can solve it by requiring what clojure.test requires before you load clojure.test
18:20technomancysee leiningen/test.clj inside leiningen for an example
18:20technomancy(that was a crazy error to track down)
18:21hiredmanhttp://www.tedneward.com/files/Papers/BootClasspath/index.html
18:28dnolenrhickey: seems like you figured out the issue? swank-clojure working for me again.
18:32rhickeydnolen: I think so - you weren't here when I put it up - thanks for the report!
18:36jwhitlarkThat's great. Thanks for all the help
18:44devlinsfrhickey: I'm going through a diff of core.clj between 1.0 and master. I'm finding a few things you might want to look at yourself before releasing 1.1
18:44devlinsfrhickey: should I post them on the dev group?
18:45drewrfwiw, swank-clojure works for me again on new as well
19:21technomancyanybody used Joda time? does it support parsing dates of an unknown format?
19:21technomancylike just "give it your best shot to figure out what format it is"?
19:24devlinsftechnomancy: I don't think so
19:26devlinsftechnomancy: I've only used it a little. To me, it seemed that Joda's strength was time zones, dst, and date calculations
19:27devlinsftechnomancy: It'll support all sorts of explicit parsing. Adding a Clojure front end to that would probably be straightforward
19:29defnIs there a good tutorial out there on how to build simple clojure applications?
19:31defnI've never used things like ant or maven in the past, leiningen looks cool, but I guess I don't really understand the big picture well enough to get how to use it
19:32rhickeydevlinsf: yes, post to the group would be best - thanks
19:33devlinsfrhickey: n/p
19:35dnolendefn: lein makes it possible to build clojure apps simply. There's a lot of pain around managing dependencies and classpaths, particular because Clojure inherits a most if not all of these issues from Java.
19:35dnolendefn: good tutorial here, http://incanter-blog.org/2009/11/20/leiningen-clojars/
19:39defnawesome, thanks dnlen
19:59hiredmanI wonder if you could use the bootclasspath option to replace the system classloader with something more dynamic
20:02rhickeyhiredman: -Djava.system.class.loader could be used for interactive use
20:03hiredmanoh!
20:08jwhitlarkdnolen: I'm trying the lein tutorial, and while it downloads the lein jar, It's not downloading the clojure jar it's expecting.
20:09jwhitlarkNow, I've already got clojure, so I guess I could just hack up the lein script, but I wanted to see if there was a simple answer first...
20:09dnolenjwhitlark: what do you mean not downloading the clojure.jar it's expecting?
20:10jwhitlarklein self-install. The docs says it'll put a clojure jar in .m2, but it's just getting lein.
20:10dnolenjwhitlark: did you install lein from github?
20:11jwhitlarkwell, I pulled down the lein bin script from http://github.com/technomancy/leiningen/raw/master/bin/lein, and tried lein self-install
20:12jwhitlarkI didn't clone the repo, but I got the script from there.
20:12dnolenjwhitlark: so nothing in .m2?
20:13technomancyjwhitlark: self-install only works with the stable branch; see the readme.
20:13jwhitlarkjw@jw-cisco-dt:~/.m2$ find .
20:13jwhitlark.
20:13jwhitlark./repository
20:13jwhitlark./repository/leiningen
20:13jwhitlark./repository/leiningen/leiningen
20:13jwhitlark./repository/leiningen/leiningen/1.0.1-SNAPSHOT
20:13jwhitlark./repository/leiningen/leiningen/1.0.1-SNAPSHOT/leiningen-1.0.1-SNAPSHOT-standalone.jar
20:14jwhitlarkah.
20:14dnolenjwhitlark: there you go, spoken by the man himself :)
20:15jwhitlarkThe tutorial on the Incanter site has a link to master.
20:15technomancyliebke: ^^ any chance you could fix that?
20:16liebkesure, where do you want me to point to?
20:16technomancyjust the stable branch
20:17liebkehttp://github.com/technomancy/leiningen/raw/stable/bin/lein?
20:18liebkedone
20:18polypusthere's also this one
20:18jwhitlarkThere we go. That's working nicely. Thanks for the help.
20:18polypushttp://zef.me/2470/building-clojure-projects-with-leiningen
20:19jwhitlarkyea, that one seems to point to master instead of stable, also.
21:07tolstoyAnyone know what 'Can't refer to qualified var that doesn't exist' means in the context of a macro?
21:07tolstoyHm.
21:07JAS415is it inside a syntax quote?
21:08JAS415because sq qualifies everything
21:08JAS415so you might have forgotten to escape something
21:08JAS415or gensym it
21:08JAS415either/or
21:09JAS415or it could be a typo
21:09tolstoyYes, I was thinking I have a stray backquote or ~ or something in there.
21:10JAS415yeah
21:10JAS415qualified var refers to like namespace/varname
21:11JAS415it might be more obvious if you macroexpand it
21:12tolstoySo, defmacro foo [name] `(do (println ~name))
21:12tolstoyI'm running this as a script, so it'll be a bit of a task to macroexpand. I was hoping to avoid that....
21:13JAS415hm
21:14JAS415you can't fire up a repl and past it in there?
21:14tolstoyYes. I'll just need to get my classpath loading stuff working.
21:14JAS415ah
21:15JAS415is name a var?
21:16tolstoyIt's a string.
21:16JAS415hm
21:17tolstoyOk, think I've got things set up to do macroexpand.
21:19JAS415ok
21:23tolstoyIf you're defining a macro you'd like to use everywhere, is there a namespace you can put it in so you don't have to always use the namespace?
21:23tolstoyI guess the right kind of require/use or something solves that.
21:27JAS415yeah if you do a use then you don't have to namespace it
21:27JAS415for repl you can also switch to the namespace itself
21:28arohnercan anyone recommend a library for cron-like tasks?
21:28arohneri.e. go run this fn in an hour, or twice a day, etc
21:30lisppaste8tolstoy pasted "can't refer to qualified var?" at http://paste.lisp.org/display/91745
21:30JAS415oh
21:30hiredmanarohner: http://github.com/hiredman/clojurebot/blob/56f8e9d824c3447036a88fbfea027f518f4ce627/hiredman/schedule.clj
21:30JAS415yeah can fix that
21:30JAS415you need to do like ~'log-info
21:31JAS415then i think it doesn't get qualified
21:31tolstoyI guess I'm wondering which "var" the error is talking about. ;)
21:31tolstoyOk, I'll try that.
21:31JAS415is talking about all the function names
21:31hiredmanit doesn't expose all of the functionality of a scheduledthreadpoolexecutor
21:32tolstoyJAS415: Ah, right! Okay. I think I get it now.
21:32JAS415the log-info functions will be in whatever ns it expands in
21:33JAS415good :-)
21:33arohnerhiredman: thanks
21:33tolstoyRight. It's so easy to forget that macros produce sexps.
21:33hiredmanarohner: it's a start
21:34tolstoyEven when you remember it to yourself as you're writing them.
21:35JAS415after a few months you get used to it
21:35JAS415months/years
21:36tolstoyYeah.
21:47ataggarttolstoy: just fyi, there's already logging stuff in contrib
21:48tolstoyYes, I've seen that. Thought I'd just try this to demo to folks how "easy" it is to craft up stuff in closure.
21:48ataggartgotcha
21:48tolstoyHowever, using a macro to generate another macro is maybe not such a good idea. ;)
21:49dnolentolstoy: actually that's a pretty common use case ;)
21:49ataggartit's macros all the way down
21:50tolstoySo, (defmacro foo [a] '(blah blah (defmacro other [].....))
21:51dnolentolstoy: more like (defmacro foo [a] `(bar (amacro baz ...)))
21:52tolstoyWell, but I want to create a macro which is defined at the time of the outer macro is, uh, compiled.
21:52tolstoy(let [foo val] (defn func ..) (defn func2 ..) (defmacro mac [] (use foo)))
21:53tolstoyBut, like I say, it might not be such a hot idea.
21:54tolstoyActually, it works, but the code that the embedded macro generates has a problem, and that's hard to debug.
21:54tolstoyI think a helper function is what's needed.
22:09JAS415macros generating macros is hard
22:10tolstoyYeah.
22:10tolstoyI want a defmacro to produce another defmacro, but only because I need it to have a reference to the "log" variable.
22:11tolstoyProbably I could just use something other than let. That might do it, actually.
22:11defnwhy does (def agent1 (agent 0)) (send agent1 increment 5) => 5, while @(send agent1 increment 5) => 0
22:11JAS415is helpful to use helper functions for that type of stuff
22:11JAS415split complicated things out
22:12defnuser.oO (send agent1 increment 5) #<Agent@4532be10: 40>
22:12defnuser.oO @(send agent1 increment 5) 40
22:14defnit's like it's always 1 call behind the current version
22:18_mstdefn: agents are asynchronous so there's no guarantee your action will have been handled by the agent at the point you dereference it
22:19_mstso you might observe it in a state either pre or post update
22:19defnhow do we know if we're at post update time?
22:20_mstyou can call (await) on the agent to have the current thread blocked until your action has been dispatched
22:20defnah-ha
22:22defnso if agent1 is 0, (await (send agent1 increment 10)) (await (send agent1 increment 10)) agent1 => 20
22:22defnotherwise i'd get 10
22:22defnerr nevermind, deref'ing is different