#clojure logs

2010-06-28

00:00somniumis this just wrong?
00:00somniumhttp://paste.pocoo.org/show/230792/
00:03somniumlots and lots of one-line (def x y) started to feel so noisy
00:04tomojyou are hereby excommunicated from the church of the holy parenthesis
00:04somniumO_o
00:04somniumthats what I was afeard of
00:07somniumhmm, I guess it shouldnt be too hard to parse it back into (def ...) expressions so I dont have to subject my paren-brothers to this private heresy in any shared code
00:08tomojhehe
01:04arrummzenI notice a lot of functions in the clojure library seem to support named parameters. How do I use these in my clojure functions?
01:06arrummzen(by named I mean optional named parameters).
01:06tomojwhat's an example? you mean in contrib or core?
01:06arrummzenFor example, with use you can give :only
01:07somniumarrummzen: usually its (fn [x y & options] (let [{:keys [this that]} (apply hash-map options)] ...))
01:07somniumarrummzen: if youre on 1.2 you can do (fn [x y & {:keys [this that]}] ...) now too
01:08somniumIm still scared of 1.2 though
01:08arrummzenHmm... but isn't that just passing in a map of options? with use you aren't giving a dictionary...
01:09somniumarrumzen youre passing in an unrolled alist I guess
01:09tomojwas that release date for 1.2 for real?
01:09somniumtheres a release date?
01:10tomojI saw it on planet clojure
01:10tomojit was somewhat speculative, not official
01:10tomojhttp://coldbox.assembla.com/spaces/clojure/milestones/149827-release-1-2
01:10somniumI was experimenting with in november last year, and it was 'right around the corner' :/
01:10tomojthe milestone is set for 3 days from now
01:10somniumooh
01:10arrummzenwith, for example "(use '[namespace :only (function)])" you it seems :only is somehow grouping to the list after it but I don't understand how. I'd understand something like (use '[namespace {:only (function)])
01:10somniumI really want to switch, but it broke once and 1.1 is plenty powerful
01:10tomojand the burndown chart is lookin good
01:12somniumarrummzen: use probably implements a mini-parser, but there are many examples of the [& key-vals] style
01:12somniumdefmulti, for example
01:14somniumclojurebot: ping
01:14clojurebotPONG!
01:16somnium,(let [[n & options] '[namespace :only [functions]]] (assoc (apply hash-map options) :name n))
01:16clojurebot{:only [functions], :name namespace}
02:08Dranikhi all!
02:10DranikI do image processing using really large matricies, changing their cells in some quirky algorithms. I need multithreaading and FP, so I'd like to try clojure
02:10Dranikbut the data in clojure is immutable. How can i process those matricies avoid memory leak?
02:13tomojyou won't be leaking memory unless you hang on to every version
02:13tomojbut you probably don't want to use immutable data structures for that anyway
02:14tomojincanter has some matrix stuff which might be helpful
02:14tomojthough, hmm
02:14Draniktomoj, so, the idea than is to use pure java collections?
02:14tomojI haven't done matrix stuff yet so I'm not sure exactly
02:15tomojbut I think it's very likely that vectors of vectors will be too slow
02:15Dranikyep, and also it will eat the memory badly
02:15tomojare you keeping every version?
02:15Dranikno
02:15tomojthen your memory use will be bounded
02:16DranikI just need a binary matrix which I process cell by cell changing the cell's value from 0 to 1 and vice versa
02:17Dranikbut as any function over a collection returns a new collection it will contain at least hashes of the cells
02:17Dranikthat's why I guess the size of the outcome will be the same as the size of the source matrix
02:18DranikOr I've got it wrong?
02:18Dranik(I didn't dig into the clojre sources)
02:19tomojthe size of the outcome will be the same as the size of the source matrix, yes
02:19tomojbut they share structure
02:19tomojand old versions will be GC'd
02:19Dranikhow about the old version? will it be saved?
02:20DranikOK, then, just have a look
02:20DranikI've got a matrix 1Gb size. I change just one cell. How much memory it will cost?
02:21tomojI couldn't tell you
02:21tomojless than 1Gb
02:21Dranik:-)
02:21tomojbut you're right, I hadn't been thinking in such large terms
02:21tomojI expect there are pathological cases in which it could cost quite a lot of memory
02:22tomojbut I'm not sure
02:22DranikIm a newbie here. Is Rich around or someone from core development?
02:22tomojit looks like incanter's matrix stuff is based on cern.colt.matrix.tdouble.impl.DenseColDoubleMatrix2D
02:22tomojso not helpful
02:26tomojwhat are the dimensions like?
02:29tomojthe depth of the tree behind the vector is O(log32 n)
02:30tomojso for an NxN matrix you need to allocate 2*log32(N) new 32-element arrays on average to change one element
02:31tomojso for a million by million element matrix that's like 8 32-element arrays
02:31tomojnot much at all, I think
02:35DranikI can hardly get it
02:35Dranikhow the new vector will share the old vector's data if it will not contain the links?
02:35Dranikand one link will have the cost
02:36tomojvectors are trees of arrays
02:36Dranikprobably 8 bytes
02:36tomojso you only have to replace from the leaf changed up to the root
02:36tomojthe other arrays in the tree will never change so you can just copy pointers to them into the new arrays you make
02:37Dranikdid I get it correctly, that one array in the vector is 32 elements size?
02:37DranikI mean one array in the tree?
02:37tomojright
02:38DranikAha! I see....
02:38tomojhttp://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation/
02:39DranikYeah, it's very effective solution for vectors.
02:39tomojbut not super fast
02:40tomojmaybe using transients would be fast enough for you, I dunno
02:40DranikAnd when changing a bunch of elements at a time, it will cost much less memory than changing one cell at a time.
02:40Dranikwhat do you mean by transients?
02:40tomojhttp://clojure.org/transients
02:40Dranik(thanks, btw, for your explanations about vectors. it was very helpful!)
02:41tomojsafe mutable data structures
02:41tomojyou could bundle up a bunch of changes (as you said) and do them all to a transient version before converting it back into a persistent vector
02:42Dranikthanks a lot! it's clear now what to grok!
02:42tomojand the conversion back and forth is O(1)
02:42tomojbut even transients may be too slow, I dunno...
02:42tomojwhat would you put in your vectors? booleans? :(
02:42Dranikyeah, they probably will be. Java is rather slow
02:42DranikI'd like to put jus one byte in a cell
02:44Draniksometimes it is much cheaper to use slow solutions at wait for a couple of seconds than to spend weeks on fast solutions which will produce the result immediately
02:44tomojyep, working with persistent and transient vectors would be pretty pleasant
02:45tomojand you get the multithreading benefits from clojure
02:45Dranikthat is my case. The basic image processing I make on CUDA -- it is extreamely mega super-duper fast!
02:45Dranikand some processing I do on client inside the java gui
02:45Dranikthat is why I'd like to have multithreading
02:46Dranikjava's multithreading is ugly! brrr....
02:53tgkDoes anybody know of a function like spit that expects a lazy seq instead? Or something similar to that.
02:53tgkMy problem is that I'm building a huge string before outputting it, and that's eating all my mem...
02:55tgkOh! Just found write-lines, sorry for the inconvenice
02:58Dranikwhere may I find the development version of clojure? 1.2 probably? I looked for it in git but found only 1.1
03:00tgkIt should be the master branch
03:01tgkYou probably want something precompiled though.
03:01Dranikhttp://github.com/richhickey/clojure.git -- is it?
03:01tgkYup, should be the right one
03:02Draniktgk, that is no problem, I just want to look at the new sources.
03:02Dranikthx!
03:07Dranikinteresting... clojure 1.1 builds also 1.2 snapshot...
03:08tomojhuh?
03:09Draniki've got the stable branch and it has built clojure.jar and clojure-1.2.0-master-SNAPSHOT.jar
03:10tomojI don't see a "stable" branch
03:10tomojyou mean 1.1.x?
03:10Dranikright
03:11Dranikor it is not?
03:14tomojthe 1.1.x branch builds clojure-1.1.0.jar for me
03:16DranikI used the http://github.com/richhickey/clojure.git, and it has built also 1.2... weird...
03:25LuminousMonkeyAnyone know of a better, more elegant way of doing something like this? http://pastebin.com/f5iw0q9U Or if there's something that does it already that I missed?
03:27tomoj,(dorun (map #(when (and %1 %2) (println %1 %2)) [1 2 3] [4 5 6]))
03:27clojurebot1 4 2 5 3 6
03:28LuminousMonkeyAwesome, thanks!
03:28LuminousMonkeyHow did I miss something like that? :/
03:38LuminousMonkeyCool, don't even need the #(when....) in there for my purposes.
03:39tomojoh, I misunderstood the purpose of the when in your paste
03:40tomojs/when/if/
03:40sexpbotoh, I misunderstood the purpose of the if in your paste
03:41LuminousMonkeyI feel a little stupid now, was looking for something to do that, and I didn't realise that's exactly what map does. :)
03:41LuminousMonkeyBut, good to learn.
03:42tomojjust don't do this
03:43tomoj,(dorun (take 3 (map println (range 20))))
03:43clojurebot0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
03:43tomojoh, just realized the anonymous function is superfluous as well..
03:43tomoj,(dorun (map println [1 2 3] [4 5 6]))
03:43clojurebot1 4 2 5 3 6
03:45LuminousMonkey,(dorun (map println [1 2 3 4 5] (cycle [6 7])))
03:45clojurebot1 6 2 7 3 6 4 7 5 6
03:46LuminousMonkeySo if I wanted to replace println with my own function, I would just need to make sure it will take two args?
03:47tomojyep
03:47LuminousMonkeyCool
03:47tomojthe function needs to take as many args as seq arguments you pass to map
03:48LuminousMonkeyBrilliant, that gets rid of a few more lines of code, thanks. :)
03:54LauJensenMorning gentlemen
03:54raekgomorron
03:54LuminousMonkeyGentlement? I've been promoted.
03:55LuminousMonkeyDespite my typing.
03:55LauJensenraek: 'go moron'??? Ah the swedish language is so poetic :)
03:58raekheh, guess i'll have to be more careful when saying that in english speaking communities
04:26rrc7czI'm curious: when was the last time you used the state monad, and what did you use it for?
04:31Fossirrc7cz: ist that a haskell question or do you refer to clj-monad or such?
04:32rrc7czFossi: clojure.contrib.monads, but I don't care about even about keeping it specific to Clojure, I would be happy to know in general
04:47LauJensenrrc7cz: I see no purpose for monads in Clojure, as Clojure has a uniform and effective way to manage state through reference types
04:49tomojno purpose for the state monad, then, you mean?
04:50LauJensentomoj: There shouldnt be. We have a state monad in ClojureQL at present, but Im working on trying to get it out :)
04:57rrc7czLauJensen: the only case I could think of where the state monad might be useful in Clojure is to build larger components
04:58rrc7czthen again maybe not, because you just wrap them in a transaction anyway
04:59LauJensenTo me, monads have always represented a way of hiding or wrapping state, to maintain a purely functional setting. This task is obsolete with Clojures approach to state
04:59rrc7czLauJensen: what about the idea of "global, implicit" state versus local, explicit state?
05:00LauJensenWhat about it?
05:00rrc7czI mean a ref makes concurrency safe, but you can still have this global, invisible state being modified from 100 places
05:00rrc7czwith a state monad you're forced to handle the state explicitly on a more local level
05:00rrc7czdoes that make sense?
05:01rrc7czfor example, I could have a ref sitting in a namespace being modified from 100 places. While safe, it's still the sort of spaghetti you get from global state. Maybe since the state monad forces you to deal with state explicitly and locally, you can prevent that sort of thing
05:02LauJensenClojure revolves around pure functions (ie no pushing global state) and immutable data. I dont see any libs in Clojure land containing global state, which would benefit from monad semantics.
05:02LauJensenFor the instances where you need to have some kind of state - Refs are also explicit and can be both local or global. In either case, spaghetti comes from incidental complexity, and I just dont see references adding any of that
05:04rrc7czwhat do you mean by refs as local? you don't mean a ref within a fn, right? You mean local to a specific namespace?
05:04somniumIm using them (monads) left and right at the moment, state+maybe for parsing and cont a littile for making cps stype code more readable
05:05LauJensenrrc7cz: yes
05:05LauJensensomnium: Interesting - Got some code up somewhere to see ?
05:05somniumsure, several buffers to choose from atm :D
05:06rrc7czsomnium: sorry, what is cps?
05:06somniumcontinuation-passing-style
05:06LauJensensomnium: M-x gist-buffer is your new best friend :)
05:07somniumhmm, is it on elpa?
05:07rrc7czsomnium: I've only ever seen that in web frameworks (like Seaside). What else are you using that for? What is easier with cps?
05:08LauJensensomnium: no, I found gist.el on github somewhere
05:10LauJensensomnium: I mostly use gist-fetch, gist-region, gist-region-private
05:10somniumrrc7cz: compilers
05:11somniumtracking tail positions and embedding contexts, ah, closures
05:14somniumLauJensen: okay, so Im not really a fan of the c.c.monads implementation so I write a lib I can use like
05:14somniumhttp://gist.github.com/455612
05:14somnium(so the usage will make sense)
05:16LauJensenk
05:16rrc7czsomnium: i understand bind/return/zero/plus from Konrad's tutorials, but name/do/modules.. guess I gotta open up one of the haskell monad tutorials?
05:17rrc7czsomnium: btw, I like the syntax and naming changes; they match haskell a lot better than c.c.monad
05:17somnium:do is the name of the do-monad macro, :modules is kind of a hack, it loads evals monad functions that depend on vars named 'bind 'return etc
05:18somniumIMHO its preferable to the with-monad, do-monad, and symbol-macros etc. in c.c.
05:18rrc7czsomnium: so modules is like with-modules, allowing you to ref existing monads
05:18rrc7czokay
05:18LauJensensomnium: And no way for you to model with using only Clojure data structures?
05:19somniumLauJensen: its just a method of composing functions thats sometimes useful
05:20somnium(Ive never been tempted to write an IO monad in clojure, for example)
05:20somnium;)
05:20somniumLauJensen: or did you mean the modules?
05:21somniumwe cant really gen namespaces programmatically so I resorted to eval
05:21LauJensenThe whole thing. You're abstracting away your relationship to state (or the accumulation thereof) in your program, and so Im wondering if it couldnt be expressed in a simpler way which didnt relate on many macros
05:22somniumsure, but Ive found the resulting code can be really clean
05:22LauJensenthus the appeal of macros
05:22LauJensen:)
05:22somniumplus they never suffer from trouble with laziness, since the order of evaluation is fixed
05:23rrc7czsomnium: why would there be a laziness problem when clj isn't lazy?
05:23somniumif you mix lazy-seq and *binding* you can suffer
05:24somniumhttp://gist.github.com/455628
05:24bartjmy initial attempt at removing stop-words - http://pastebin.org/363105
05:24bartjI do not want to use fancy stuff like Lucene or any libraries
05:25somniumrandom snippet, that files kinda big but thats typical of my usage I guess
05:25bartjcomments please ?
05:27tomoj(remove stop-words-map (re-seq #"[^\s]+" s))
05:28tomojthough..
05:28rrc7czbartj: also consider something like: (apply str (interpose " "(filter (complement stop-words) (.split "the quick brown fox" " "))))
05:29rrc7czbartj: which works if you switch stop-words to a set, which makes sense anyway since you don't care about testing for inclusion
05:29tomojhttps://gist.github.com/7fbff0775cf072e2efac
05:29LauJensenrrc7cz: that split doesnt work exactly like his regex, and (apply str (interpose )) is clojure.string/join
05:30rrc7czLauJensen: you can pass split() his regex instead of the space
05:32bartjtomoj: your version definitely is more terse
05:32LauJensenand effecient, and idiomatic
05:34LauJensenThe first version allocates a new seq for both re-seq, map and remove, tomojs has 2 thirds of the allocation, but ofc I dont know if this has to be performant in any way
05:36somniumLauJensen: you could say reduce is kind of like a poor man's state monad and its perfectly idiomatic in clojure
05:37bartjunderstanding tomoj's implementation:
05:37LauJensenor a rich mans, depending on how you look at it :)
05:37somniumI guess its more like composing a bunch of (partial reduce f ...)
05:37bartj, (#{"the" "a"} '("the" "blah"))
05:37clojurebotnil
05:38tomojremove calls the function on elements of the seq, not the seq itself
05:38bartjwhen a list is passed to a map it returns the keys
05:39LauJensenbartj: when a element (like in remove) is passed to a set, it will return either an element or nil. Nil will cause remove to keep the item
05:39LauJensen,(map #{\a \b} "abcdefg")
05:39clojurebot(\a \b nil nil nil nil nil)
05:41bartjLauJensen: ok, thanks!
05:41rrc7czsomnium: your parser looks just like Parsec. Are you porting it to Clojure?
05:42somniumrrc7cz: I actually dont know parsec that well
05:43somniumbut similar I think, it can do pegs already
05:43somniumonly a week old though, not qutie baked
05:43somniumhttp://gist.github.com/455646
05:43somniumLauJensen: ^^ I challenge you to offer a more appropriate abstraction for this case
05:44LauJensenI like challenges - are we putting some money on it? :)
05:44somniumwhat's the going rate for a cup of tea in Denmark?
05:45LauJensenI think right around 2kr
05:45tomojsomnium: better than fnparse?
05:46LauJensensomnium: I'd still prefer it represented in some kind of meaningful datastructure, isntead of abstraction by macros
05:46somniumtomoj: I dont know if its better, it started as some unit tests for my monad lib and became useful rapidly
05:47tomojah
05:47bartj, (dorun (#{"the"} '("the" "blah")))
05:47clojurebotnil
05:47bartjwhy can't expect a "blah" in the output ?
05:47LauJensenbartj: AFAIK sets accept arguments as elements, not seqs
05:48somniumLauJensen: youre not actually proposing we do ((fn [x] (+ x x)) 42) instead of (let [x 42] (+ x x)) are you :P
05:48LauJensensomnium: ofc not
05:48LauJensenbartj: put a map there instead of dorun
05:48LauJensenthat will pass _each element_ individually as the argument
05:49bartj, (map #(#{"the"} %) '("the" "blah"))
05:49clojurebot("the" nil)
05:49bartjLauJensen: thanks again!
05:50LauJensen,(->> (map #{"the"} #{"the" "blah"}) (filter indentity))
05:50clojurebotjava.lang.Exception: Unable to resolve symbol: indentity in this context
05:50LauJensen,(->> (map #{"the"} #{"the" "blah"}) (filter identity))
05:50clojurebot("the")
05:51LauJensenbartj: the anonymous #(set %) notation was redundant, as sets really are functions of their arguments
05:51rrc7czLauJensen: why wouldn't you just use set/intersection?
05:52LauJensenrrc7cz: because I dont think he's using sets for the input
05:52rrc7czaha
05:53bartjjust as maps are functions of their keys ?
05:53LauJensenexactly
05:55LauJensenand vectors of their indices
05:56LauJensen,([1 2 3] 1)
05:56clojurebot2
05:56bartjLauJensen: thank you very very much
05:56LauJensenbartj: np, thats what we're here for :)
05:56bartjwhich is why the stop-words-map wasn't necessary in the first place :)
05:57LauJensenbartj: yes. Interestingly, a hash-map is actually using the same lowlevel implementation as a set. The set is just different in that all keys equal their values. (zipmap vals vals) is repeated what the compiler is doing, just like #(set %) is doing what the compiler is doing
06:00bartjLauJensen: thanks again for the explanation
06:01LauJensennp
06:05LauJensensomnium: Im wondering, what exactly is going on in anf and return ?
06:05rrc7czreturn = m-result, no?
06:06rrc7czbut "return" is haskell
06:06somniumLauJensen: actually the interface of run-cps is slightly different, so its not really one to one, but its one partial application away
06:08LauJensenThere are too many unknowns for me to offer an alternative. But generally, I'm more interested in data designs like [:a :< (fn [] ..)] than (macro a < (fn []))
06:08somniumLauJensen: but its not a macro, the macro is just syntax sugar, you can ALWAYS apply a monad
06:09somniumsometimes the shorter form is even easier to read
06:25somniumLauJensen: its an ugly one-liner, but that anf fn uses closures to add 'contexts where needed, so '(foo (bar (baz zonk) zam) zow) become
06:25somnium,(letfn [(f [t k] (if (symbol? t) (k t) (g t (fn [x] [:let ['v x] (k 'v)])))) (g [ts k](if-let [[x & xs] (seq ts)] (f x (fn [y] (g xs (fn [ys] (k (cons y ys)))))) (k nil)))](f '(foo (bar (baz zonk) zam) zow) identity))
06:25clojurebot[:let [v (baz zonk)] [:let [v (bar v zam)] [:let [v (foo v zow)] v]]]
06:26LauJensenah nice. note that Clojure now support locals with names longer than 2 chars :)
06:57BahmanHi again all!
06:58Bahmanttmrichter: Hi there!
06:58ttmrichterHey-o.
09:22jcromartieeverybody has seen this, right? http://gregslepak.posterous.com/clojures-n00b-attraction-problem
09:23jcromartieMy only beef with the rant is that I think Clojure's documentation is pretty good.
09:32jcromartieI'd like to write a real ground-up getting started guide
09:32jcromartiefor people that know absolutely nothing about the prerequisites
09:33jcromartielike the command line, Java, version control, build systems, editors, etc.
09:33jcromartiebecause there are so many points to get stuck on
09:35zmilajcromartie - do it, it will be very usefull
10:33jcromartie*phew* this is going to be exhaustive :)
10:33jcromartieis there a good place to post it aside from my blog or something?
10:34fogusjcromartie: Why not try to get it rolled into the Assembla wiki?
10:34jcromartiewill do
10:36Scriptor_sleepyjcromartie: what level is it for? are you targeting those who have virtually no experience with running scripts from the command-line?
10:37rhickeyaargh... maybe everyone should just leave their browser window in the infinite login loop until google groups recognizes the problem...
10:38bhenryrhickey: i searched for ants.clj and ended up in a redirecting loop with the first hit on google.
10:41djpowellhmm, I have a script containing a kind of dsl thing, and I want to load-file it in the context of a certain namespace
10:41djpowellany way of doing that?
10:43chousersure. load-file
10:44djpowellif I call load-file from a different namespace tho, it loads it into my namespace
10:44djpowelli always want to load into the same namespace
10:44chouserperhaps (binding [*ns* (find-ns 'my.special.ns)] (load-file ...))
10:44djpowellbut I didn't really want to put an ns decl at the top of the file
10:44djpowellyeah - i was thinking something like that
10:45djpowellis it ok to rebind *ns* then? is that how require works?
10:45chouserthat's one of the things 'ns' and 'in-ns' do
10:45chouseractually, they re-set it
10:45chouserbut yeah, I think it's ok to rebind *ns* for this kind of situation. I certainly do it.
10:46jcromartieScriptor_sleepy: I'm targeting complete and utter n00bs... let me qualify that with a list of topics
10:48jcromartievirtual machines, executables and libraries, the JVM, classes, methods, UNIX shell concepts, shell programming, running Clojure, REPL concepts, Lisp concepts, Clojure code organization
10:49Scriptornice, what does shell programming entail?
10:49jcromartiethis is the "I dabbled in PHP once" to "beginning Clojure hacker" guide
10:49jcromartiejust enough to understand how to write your own clj launcher shell script
10:50jcromartiecommands, variables, arguments
10:51Scriptorif it's not too much, do you think you could cover automated testing as well?
10:51jcromartieI see my ability to understand how to use Clojure *at all* as a product of the sum of my experience over the last 20 years :P
10:52jcromartieerr, 15 years or so I guess
10:53jcromartiefrom doing Logo in the 3rd grade to learning Unix commands on my dad's Wyse terminal at home... most people don't have it so easy
10:54Scriptoryea, it's interesting just how much knowledge you can take for granted
10:54Scriptorsomething like "open a shell, cd into the download directory" is obvious to some, but could be a complete mystery to others
10:55jcromartiea lot of my peers hate Java because of the classpath
10:55jcromartiethey won't even go near Clojure just because of bad experiences in school
10:55LauJensenthey?
10:56jcromartie3 I can think of have said "no way, that's Java, I can't get Java to work"
10:56eevar2they should probably stick with php
10:56jcromartiePHP and C#, between them
10:56LauJensenYea, they sound like ideal PHP experts :)
10:56LauJensenjcromartie: Please dont show them the mailing list :D
10:57jcromartiewell it's not that they are dumb, it's just that early on in their experience the Java environment was not very friendly
10:57LauJensenI wonder when this 'how far can we dumb down Clojure' race will end. I mean eventually we'll hit a level where it just doesnt make sense anymore
10:57jcromartieand it still isn't, really
10:57jcromartieI don't think we need to dumb it down, it just needs to be unified
10:57djpowelluh? is anyone dumbing down clojure?
10:57Scriptorpeople just like to poke fun at PHP programmers
10:58LauJensendjpowell: The continous discussion these days, is 'how can we present Clojure in a less terrifying way', and the solution seems to be less of Emacs and more of Netbeans...
10:58djpowellhmm, all the hip ruby programmers don't use IDEs though do they?
10:58LauJensendjpowell: No I dont think so
10:58jcromartiethey all use TextMate
10:59Scriptorone issue I have with that is it's geared for noobs who use IDEs
10:59jcromartiebut Emacs has some good Ruby and Rails modes
10:59LauJensenAnd I think the Ruby crowd is actually very interested in Clojure - I would imagine the Ruby/Python transition is less painful than the one from PHP
10:59eevar2the hip ruby programmers should be able to cope with java / classpath issues, tho
10:59jcromartieonce the classpath is explained, it's easy
11:00LauJensenyou need to have the classpath explained?
11:00jcromartieit's rarely explained
11:00jcromartieit's usually just rote
11:00jcromartiein school, at least
11:00LauJensenok
11:01jcromartieand most "enterprisey" Java programmers don't even use it explicitly
11:01jcromartiethey let Eclipse manage it
11:01jcromartiebut it's practically a one-sentence explanation
11:01LauJensenAt the recent Conj Labs session in Brussels, I put some emphasis on showing off the areas where Emacs really boosts your productivity, I think quite a few people enjoyed that
11:03Scriptorwere you talking about modes designed for productivity stuff, or about the editor itself?
11:03rrc7czI think the idea isn't to hide Emacs, but let people discover it on their own time once they move forward. I can testify that clojure + emacs was a bigger bite to chew in the beginning; if you could focus on language first, then a new IDE second, it might make it easier to digest
11:03LauJensenScriptor: The editor, as well as its integration with gist, git, slime etc
11:04LauJensenrrc7cz: Right, what Im saying is that its a non-issue. Some people try to tackle Emacs along side Clojure, and many of them are succesful. Others prefer Visual IDEs. I dont think that Emacs in itself should scare anybody, because alternatives exist
11:05bhenryrrc7cz i found it very helpful to take a week or two focusing specifically on emacs. then i moved on to learning clojure.
11:05ScriptorI'm trying to force myself to learn emacs, mainly because I feel deep-down it gives the optimal experience, even if others say it's not necessary
11:05bhenryi was certainly no emacs pro after that week or two, but it was helpful anyway.
11:05jcromartieEmacs is just useful period.
11:06jcromartieClojure integration is just icing on the cake.
11:06jcromartieI use Emacs + clojure-mode + paredit without slime and it's still great.
11:06LauJensensure - except paredit :)
11:06nachtalpimho wanting to learn clojure is a good reason to learn some emacs as well :)
11:06LauJensenThe more I've experienced of paredit, the more I see it only as crutches
11:07jcromartienuclear-powered robot crutches with lasers
11:07jcromartiemore like it
11:07LauJensenhehe :)
11:07somniumI tried to learn common lisp and emacs at the same time but only the emacs took
11:08somniumprobably for the best
11:08LauJensenI also picked up Emacs while learning SBCL - No regrets
11:09jcromartieI learned Emacs to write Lua just because someone convinced me I'd be more awesome for it
11:09jcromartieand here I am, surrounded by women and swimming in money
11:09rrc7czI guess I'm just thinking about pace. Chapter 1 of any programming book isn't about the STM or monads, it's about hello world. These are powerful, productive tools, but they aren't even in the vocab of many potential users, why start with the whole shebang?
11:10LauJensenrrc7cz: yea, you can leave out monads entirely
11:10eevar2mixing up vim/emacs/os x keybindings tends to get messy
11:10rrc7czLike, some users might want a more powerful IDE after 1 hour, while others after 1 week. The idea though is to lower that initial barrier
11:11LauJensenI think I need to do another Emacs / Dev Env tutorial/screencast
11:11rrc7czI would love that
11:11jcromartieeevar: I'm happily using C-a C-e C-b C-f C-k C-y in OS X
11:11rrc7czI use clojure-mode + slime to lein swank, but I still feel the env could be improved on
11:11jcromartieC-p C-n... also the kill ring works
11:11jcromartiein some apps
11:12jcromartienow to really mix it up, I use Visual Studio in VMWare on OS X
11:12jcromartiethat's fun
11:12jcromartie:(
11:12LauJensenI use Arch + Awesome + Emacs (Magit, gist, Org-Mode, Clojure-mode, Swank) and a few other helpers. But its a very specific setup which is so fast it feels like its almost reading my mind
11:13rrc7czmy #1 pain point is starting the whole thing up. M-x shell, then lein swank, then slime-connect, etc. I know it can be scripted, but I haven't gotten that far
11:13jcromartiecool http://mobileorg.ncogni.to/
11:13LauJensenrrc7cz: use M-x swank-clojure-project
11:13LauJensenThat automatically configures classpath, starts swank/slime etc
11:13rrc7czI used to, but it's deprecated now, right?
11:13LauJensenWho cares, still the best thing out there
11:13rrc7czhow do you doodle?
11:15rrc7czright now I just have a "scratch" lein project I use to set up the classpath w/contrib and such, bring up a repl, etc. but it feels like overkill
11:18LauJensenrrc7cz: for doodling I have a very specific set up, where a bunch of projects that I use and contrib to, are setup - I manually fetch the branch of Clojure/contrib I want
11:18LauJensenthen hit M-x slime
11:19rrc7czLauJensen: I think a screencast explaining your setup would be pretty sweet
11:19rrc7czI looked at your IDE comparison back in the day, but I never saw one about your Emacs config
11:19LauJensenrrc7cz: I think most of my setup, in terms of .emacs is already in some blogpost on my site - What I would like to show is how this setup makes me extremely effective
11:20LauJensenhttp://bestinclass.dk/index.clj/2009/12/clojure-101-getting-clojure-slime-installed.html
11:20LauJensenI did that one, but its a little outdated
11:21AWizzArdLauJensen: this howto for Clojure 1.2 with newest Slime would be very intersting (:
11:21LauJensenIm also tempting to do some kind of handholding. But I firmly believe that if you're coming from C#, Python etc, and you cannot figure out Emacs, I might get you through that phase, but then you'll die when trying to grasp functional programming. I might be wrong
11:22rrc7czI don't think it's about "figuring out" Emacs, but getting used to it. My problem is key bindings
11:22rrc7czI think anyone can figure out Emacs if they want to, but dumping the many years of motor memory in your fingers takes time
11:23Scriptortry going from vi to emacs
11:23LauJensenScriptor: Only then will you know how Neo felt when he woke up outside of the Matrix
11:23chouserdepressed?
11:23chousergrubby?
11:24LauJensenfree
11:24Scriptorweak from no muscles?
11:24chouseroh, right.
11:24rrc7czlol
11:24LauJensenBut look - The vi guy woke up :)
11:24LauJensenchouser: I have great news. Vim now supports a special 'insert mode', which actually lets you edit code, and not just view it! Hooray! No more copy/paste
11:26LauJensenWell.. I mean, you probably still have to paste into your repl :(
11:26chouseryou mock what you do not know
11:27rrc7czsomething else bothers me: in the age of iPhone, UX, Web 2.0 UIs, there is this massive push to have computers fit the human, not the other way around. Hell, that's part of Lisp! Write what you want declaratively and let the computer figure out _how_ to actually do it. Then you have this editor that literally breaks your hands and forces you to memorize 2389023 keybindings... wrong track?
11:28LauJensenrrc7cz: Its the ideal interface
11:28rrc7czOn LtU there was some research IDE some kid made with "Code Bubble", basically rethinking the whole IDE experience.. that seemed nice
11:28rrc7czLauJensen: define interface. You could argue a shell is the ideal interface to any computer, but it may not be the most user friendly
11:29LauJensenrrc7cz: What I mean is. Emacs is making me so productive, that Im not seeing much room for improvement anymore. Maybe its my imagination that failing, but maybe not
11:29nachtalpnot all interfaces are equally friendly to any user :)
11:29rrc7czLauJensen: think of a game where you have to navigate a maze. In this case the best interface is a graphical - rather than textual - one. Who says the best interface for code editing looks like Emacs? Maybe it hasn't even been thought up yet
11:29somniumLauJensen: it could be hubris
11:30LauJensenrrc7cz: True - And if something better comes along, Im switching
11:30Scriptorjcromartie: just thought of something, is your tutorial oriented around windows? most utter noobs are probably using that
11:30LauJensenIts not like chouser and kotarak havent tried teaching me Vi
11:30LauJensenScriptor: In fact that might be the very definition of an 'utter noob' :)
11:30HodappEDITOR WAR! EDITOR WAR!
11:30rrc7cz:-D
11:30somnium:D
11:31jcromartieScriptor: yes, it caters to Windows users
11:31jcromartiebut not exclusively
11:31LauJensenWar? Where?
11:31jcromartiewe get into Cygwin, as a special note for Windows users, before going on to shell scripting
11:31rrc7czjcromartie: you might want to briefly mention lein.bat in that case. I actually dev clojure at work on Windows and lein.bat has worked out better for me than lein.sh in mysis
11:32Scriptorgit for windows comes with a shell, which is pretty handy by knocking out 2 birds with one stone
11:32jcromartieas an aside, I got a great old shell programming book from my dad called UNIX Shell Programming by Kochan which is a great treatment of the basics that lots of more advanced tuts either miss or just skip over
11:32rrc7czScriptor: that's exactly what I had problems with, but it's very possible I did something stupid. I just didn't spend much time on it
11:32jcromartierrc7cz: good tip, thanks
11:33jcromartieyeah, Cygwin + git is better than mysis
11:33rrc7czjcromartie: i'll have to remember that next time i upgrade. I downloaded some msi pack and it shipped with mysis
11:34rrc7czworks great w/git, but I should be switching to emacs git client anyway
11:34LauJensenrrc7cz: try magit, or egg if you need a soft start
11:34rrc7czthanks for the tip
11:47jcromartiewow, org-mode is rocking my socks off
11:53Capricais there a way to append to the end of a list?
11:53chouserappending to the end of a vector is very fast. use conj.
11:53chouser(conj [1 2 3 4] 5)
11:53chouser,(conj [1 2 3 4] 5)
11:53clojurebot[1 2 3 4 5]
11:58Capricais there a nice way to convert a list to vector (or more specifically a range to a vector)?
11:58jcromartievec
11:58dnolen,(into [] '(1 2 3))
11:58clojurebot[1 2 3]
11:59jcromartieoh that's better
11:59chouser,(conj (vec (range 10)) :hi)
11:59clojurebot[0 1 2 3 4 5 6 7 8 9 :hi]
11:59jcromartie,(vec '(1 2 3))
11:59clojurebot[1 2 3]
11:59rrc7czwhy is into better than vec?
11:59jcromartieah
11:59chouservec is better
12:00jcromartiednolen had me thinking that vec maybe made a vector with its arguments at each index
12:00jcromartie,(vec 1 2)
12:00clojurebotjava.lang.IllegalArgumentException: Wrong number of args (2) passed to: core$vec
12:00jcromartieright
12:00rrc7cz,(vector 1 2)
12:00clojurebot[1 2]
12:01jcromartiehuh, didn't know about vector
12:02CapricaThanks for the help
12:04chouservector takes multiple args, like list, hash-set, hash-map, sorted-set, and sorted-map
12:04chouservec works on an existing collection, like set and seq do.
12:07jcromartieright :P
12:08jcromartiealright time to focus... IRC has to go bye-bye
13:33yacini have some data parsing routines that need to be done whenever a program of mine is launched
13:33yacinis there anyway i can have it parse the files at compile time?
13:33yacinso i don't have to distribute the data along with the jar?
13:35LauJensenyacin: If it needs to parse when start up, it needs to be in the jar or go along side the jar. I guess you could serialize it to a Clojure datatype if you wanted, and just def it
13:36yacinthat's what i would like to do
13:37LauJensenSo whats keeping you from doing so ?
13:42yacinme just being silly :P
13:53yacini guess i don't understand how to do it
13:53yacini'd like to be able to do:
13:53yacin(def-now *var-name* (funcs (to (parse "path/to/data"))))
13:53yacinand have this all run when it compiles
13:53yacinrather than at runtime
14:24dsopis there a form to make this simpler: http://pastebin.com/1BF2RdUf?
14:24dsophttp://pastebin.com/1BF2RdUf
14:27cmiles74You could (let [repository (data "repository")...]) and remove some of the nesting.
14:29chouseror (let [[rname rowner rfolks] (map (data "repository") ["name" "owner" "forks"])] ...)
14:48dsopchouser: thanks
15:44itistodayfor some reason when I do 'lein compile' it runs the jar file. I've defined :main in the project.clj, could that be why? Is there a way to prevent it from doing that? I don't see why "compile" is "compile+run"...
15:45chousercompile has to "run" all the top-level things. so (def foo (bar)) will run bar during compilation
15:46chouserbut (defn foo [] (bar)) will not run bar until you call (foo) at runtime. so just make sure anything you *don't* want to happen at compile time is inside a function definition.
15:47itistodaychouser: I see... thanks!
16:02ska2342Hi. Is someone around, who can explain the history of Refs to someone, who didn't get it after reading the article by Volkman and the source code, i.e. me?
16:02chouserheh, well, someone can try.
16:03ska2342I'm all ears
16:03chouserwhat don't you understand?
16:04chouserby history you mean the set of past values each ref keeps?
16:04ska2342Yes, I am refering to the old values that keep hanging around in a ref during a transaction. Und which circumstances will the history grow?
16:06chouserwhen a transaction starts it has a "now" that it can use to find the correct value inside all refs
16:07chouserif it asks for that timestamp in a ref, and that ref doesn't have timestamps that old, the ref increases it's history size limit and the transaction retries
16:08ska2342is the now measured in time or in counts?
16:08chouserI think it's counts
16:08anarswhich contention management strategy does the stm in clojure use?
16:08ska2342so, every deref/read will also pass a timestamp?
16:09chouserI don't think so -- probably only derefs in a transaction. let me check.
16:10chouseryes, only when inside a transaction. flying reads just grab the latest value
16:11chousertimestamp is a count, an AtomicLong
16:12ska2342So, a read during a transaction leads to one stored value. Will another read from another transaction lead to the second value? And does the history disappear if one transaction commits?
16:13chouserall reads within a single transaction will use the same timestamp for all refs.
16:14ska2342all reads from all threads?
16:14chousera transaction is within a single thread
16:15ska2342yes, sorry.
16:16chousereach ref's history is trimmed when it gets too long, based on the min/max history knobs for that ref
16:16ska2342so it's the other threads that may try to read a value that will cause the history to grow, right?
16:16ska2342no, wait with the trimming. I'm still trying to understand the growing of the history, please.
16:16chouserany thread that tries to read a value older than a ref's oldest history will cause that ref's history to grow.
16:17chouseryou asked about trimming. :-)
16:17chousermost of this is detail that you rarely have to think about, though.
16:17ska2342(yeah, I asked two questions in one, too fast for my old brain)
16:17chouserit's like asking details about the garbage collector's algorithm, when most of the time you simply don't need to care.
16:18ska2342I'd like to really understand this, because I'd like to list some gotchas in our book...
16:18ska2342I need to know or at least give a hint, when incrementing the max-history may be necessary
16:19chouserah, well that's a somewhat different question
16:19ska2342maybe a better question would be: in what situation will the history overflow?
16:20ska2342obviously for that I need to understand how the history starts growing at all :)
16:20chouserthe history will grow automatically based on the actual workflow fo the program
16:21chouserif you're getting lots of transaction retries because of insufficient history while the program is "warming up", setting the min-history can cause the warm up time to be less
16:21chouser...as you'd be starting it off with more appropriately-sized histories.
16:22ska2342Yes, I think I understand the retrying at the lower end (min history).
16:23chouserI've not personally had to set :max-history, and don't remember ever hearing about someone who did.
16:23ska2342How can the history grow to two items? What do threads have to do to grow history?
16:24chouserpresumably that would be in a situation where the retries had take place, the history had grown to max, and some transactions were still never succeeding (or only occasionally succeeding in "racy" conditions) because of insufficient history.
16:26ska2342transaction 1 (ta1) starts, reads value with timestamp T1, ta2 starts... something like that...
16:26chouseryeah, hang on a sec.
16:32chouserheh, I'm trying to make a stress test to get the history up high, and I can't get it above 6
16:32ska2342hm, I'm trying to understand how ref.faults get's increased in doGet in LockingTransaction.java
16:35ska2342but I'm really interested in how you raise the history (and how you know it's size, BTW)
16:35chouser(.getHistoryCount my-ref)
16:38chouserska2342: http://gist.github.com/456326
16:39chouserthe future is a slow transaction, and we only ask it to run once.
16:40chouserBut since the transaction uses the current timestamp when it's created, by the time the deref happens a second later, the current time may have changed quite a bit.
16:41ska2342so that's 2 threads: one slow and keeping the transaction "open" while the other one tries to alter the value rather fast
16:41chouserIndeed, the dotimes below keeps running fast transactions the keep bumping up the timestamp by commiting new values.
16:41chouserright.
16:41chouserbumping up the timestamp have having transactions, and filling a's history by altering it, to be more precise.
16:42chouserfor me, when it's done, it reports a's history has maxed out at 10.
16:43ska2342yes, a is 1000 and history is 10 for me, too.
16:43chouserand all the :try's fail until the dotimes quits looping
16:43ska2342So, isn't it a bad thing to happen when the max history is reached? I imagined bad things happening, like the transaction will fail with an exception or sth.
16:44chouserI think if any one transaction fails enough times you get an exception
16:44chouserbut like in this case, the dotimes kept doing fast transactions, but after a while it was done and slower transactions could complete
16:45chouseranyway, now you can add :min-history 100 :max-history 100 to the ref, and you'll the slow transaction will succeed on its first try
16:47ska2342which of the two transactions is causing the read fault in the ref and why?
16:47ska2342(man, I feel so stupid)
16:48chouserthe slow one.
16:49chouserthe first time the future tries, let's say a's historyCount is 0 and the current timestamp is 0
16:49ska2342aye
16:49chouserthus the future's transaction "now" is 0. It sits there for a second and then does @a
16:49chouserbecause the @a is in a transaction, it asks a for it's value at time 0
16:49clojurebotmultimethods is what separates the boys from the men.
16:50ska2342wait a sec..
16:51chouserbut a's value has been getting bumped every 10 milliseconds, so it's current value is at time 100 or something. and since it has no history a all, it has no idea what it's value was at time 0.
16:52ska2342ok, the now=0 is from getReadPoint(), right?
16:52chouserright
16:53ska2342ok, I catched up with you...
16:54chouserok, so a's history is now known to be insufficient, so the amount of history it keeps is increased (I think just incremented)
16:54ska2342@a calls doGet
16:55chouserand the slow transaction retries, with now=100 or something, it waits, asks for a's value at 100, but a only has a history of 1, that is probably a value at time 199 and a value at time 200. a still doesn't know what it's value was 99 timestamps ago. So the history is bumped and we go around again.
16:56ska2342in which case will vals.containsKey(ref) in doGet have a value? (I think I understand the next part which does the job with the timestamps there)
16:57chouserhm, I'm not sure what 'vals' is there.
16:58chouseroh, I think that's just for uncommitted in-transaction values
16:58chouserwhich we're not talking about at all here. :-)
16:58ska2342OK, so I can safely ignore that.
16:59ska2342So, @a causes a read fault in doGet and the code in run() (around line 320) from the _fast_ transaction will cause the history to grow. (slowly, very slowly, getting it, I think)
17:01chouserI think it's the slow transaction that would run that code and cause the history to increase
17:01chouserusing (ref 0 :min-history 95 :max-history 100) for a is instructive
17:02chouseryou can see that after 5 tries of the slow transaction, the history has grown to the 99 needed for the slow one to complete, even though the fast one is still cranking away.
17:03ska2342hm, here it just quietly returns nil
17:04chouserhuh
17:05ska2342no, wait, everything is fine. the output was in *inferior-lisp*
17:06chouserah, slime.
17:06ska2342even worse: a manually installed, partly changed Slime :)
17:06chouser:-)
17:07ska2342anyway, I now see: "a is: 391 history: 98" .. obiwan is probably ok
17:08ska2342but I still think that the fast TA is growing the history upon commit since it detects a read-fault that happened in the meantime. No?
17:10chouserI think the fast TA is fat and happy. It keeps cranking away on the ref and doesn't know anything's wrong.
17:10chouserit's the slow one that keeps realizing the history is not yet sufficient and needs to grow
17:12ska2342are you sure?
17:13chouserwell ... pretty sure, but I've been wrong before
17:13chouseron very rare occasions. ;-)
17:14ska2342doesn't the code starting around line 320 in the run()-method indicate that it's _writing_ values? It gets a commit point and the comment seems to say so, too
17:14chouserI'll have a better example for you in a moment.
17:14ska2342you are very patient.
17:15chouserhmmm.... ok, I think I see what's going on.
17:15chouserwhich is perhaps what you've been saying all along
17:15ska2342huh?
17:15chouserthat is, the slow transaction records a fault, but the fast one actually increases the history
17:16chouser(and sets the fault counter back to zero)
17:16chouserI was noticing the history only grew as fast as the slow transaction failed, and assumed that meant it was the one increasing the history
17:17ska2342ok, that's enough for me. Then I think I get this. Final question: what happens when max history was exceeded? Dropping some tvals and retrying?
17:17chouserbut of course it can't actually increase the history until there's a new value to push onto the history, so it's when the fast one writes the value that the history actually increases.
17:17chouserI doubt it retries
17:17rhickeyhistory is just a sliding window, last N
17:18rhickeya failed reader will mark the failure, next writer will extend history if not over max
17:19rhickeyin general, having a long running transaction fight short running ones is something to re-architect, unless you are trying to demonstrate something
17:19ska2342so, in the worst case readers will fail again and again if the history is too small.
17:19anarsrhickey, ladies and gentlemen
17:19rhickeyska2342: until they reach the retry limit
17:20ska2342yes, the timing of transactions will be something that programmers will have to have in mind for concurrent programming
17:20chouserska2342: http://gist.github.com/456326 is updated
17:22ska2342chouser: that is a very nice summary of a rather long discussion, especially the comments! Thank you very much for your patience.
17:23ska2342May I use the source for our book?
17:23chouserheh. sure!
17:23chouserbut but... I'm supposed to be writing my book, not yours!
17:23chouserno, it's fine.
17:24chouserthis is the german book?
17:24ska2342yes. and I want to finish it this very week. Afterwards we'll only be waiting for 1.2 to come out and redo all our examples.
17:25chouseroh man. you're fast!
17:25ska2342(unless there will be things like the primitives that will enter 1.2, that is) ...?
17:26ska2342Actually I've spent almost every single minute of my sparetime since 2009-10. Ask my kids...
17:26chouserah, perhaps you started earlier than I realized.
17:26anarshopefully not the "The Cat's In The Cradle"-type of every single minute ;-)
17:27ska2342And of course Emacs, LaTeX and AUCTeX help a *lot* :-) We're at 330 pages
17:27chouserone thing that I hope is better about a book project than a software project is that there's a definite *end*
17:27ska2342anars: sorry, I don't understand that one
17:28ska2342chouser: what about the second edition next year? ;-)
17:28anarsska2342: http://en.wikipedia.org/wiki/Cat's_in_the_Cradle - I was kidding, but seriously - the song is great.
17:28chouserska2342: nooo! ;-)
17:29ska2342anars: not, that bad. but they had to go to bed early every day :)
17:29ska2342So, what about the work on primitives? Will it be in 1.2?
17:34hugoddoes anyone have something to show the use/require namespace graph?
17:58lpetithugod: I don't see anything like that in contrib. Maybe you'll have to roll your own via the ns-* clojure.core functions ...
18:00hugodlpetit: an excuse to try vijual maybe...
18:00lpetithugod: sure
18:12arohnerhugod: you might want to check out c.c.find-namespaces
18:12arohnerhugod: it won't give you the graph, but you can get a seq of the ns declarations
18:13hugodarohner: thanks, I'll take a look. Together with lpetit's hints, that should work.
18:20DuneMansomnium`: You around?
19:12polypusjust wrote this macro
19:12polypushttp://gist.github.com/456523
19:13polypuscomes in handy when you want to let a whole bunch of things differently depending on an if expression, but use the same body
19:14polypusas opposed to if-let where the bindings are the same but the bodies different.
19:14polypusis there already something like this anywhere? couldn't think of a better name. suggestions?
19:28arohnerpolypus: I've wanted something similar. Does that output [1 3] when true, and [2 4] when false?
19:30dsoparohner: yes
19:37polypusaroher: yep
19:37polypusarohner*
19:38dsoppolypus: nice one, maybe something for contrib?
19:39polypusdsop: ty. yeah, i think it may be generally useful
19:39polypusbut i need a better name :)
22:10dnolenhmm for some reason I thought you could use [:tag _] in multimethods to say you don't care about the second element in the match.
22:16itistodayso i saw this piece of code recently: (.start (Thread. #(println "foo")))
22:17itistodayI didn't know that java.lang.Thread could take a function in its constructor
22:17itistodayi'm guessing this is clojure overriding it?
22:17hiredmandnolen: [:tag Object[ is pretty close
22:17hiredmanitistoday: Thread takes a Runnable and Clojure Fns are Runnable
22:17dnolenhiredman: yeah I was just thinking that. will I need to use a prefer-method?
22:18hiredmanI don't think so
22:18hiredmanbut I am not sure
22:18itistodayhiredman: ah, didn't know that, thanks. is there a page somewhere that lists that info? i'm wondering what other interfaces Fns conform to
22:19hiredman,(ancestors clojure.lang.IFn)
22:19clojurebot#{java.util.concurrent.Callable java.lang.Runnable}
22:19hiredman,(supers clojure.lang.IFn)
22:19clojurebot#{java.util.concurrent.Callable java.lang.Runnable}
22:20itistodayis there a sight somewhere with javadoc for clojure's internals?
22:20itistoday*site
22:20hiredmannope
22:21itistodayany reason for that?
22:21hiredmanimplementation detail?
22:25Lajla,(apply + (range 10))
22:25clojurebot45
22:25Lajla,(range 10)
22:25clojurebot(0 1 2 3 4 5 6 7 8 9)
22:25Lajla,(apply + [0 1 2 3 4])
22:25clojurebot10
22:26itistoday,(.start (Thread. #(println "foo")))
22:26clojurebotnil
22:26itistodaydoesn't run threads...
23:49BahmanHi all!
23:51lancepantzhi Bahman