#clojure logs

2009-09-13

02:46emmaHi is anyone here awake?
02:47arbschthi
02:49emmaoh hai
02:49emmaI have learned a little bit of scheme, and a little bit of common lisp. Because I want to learn a programming language and I want the first one I actually know to be a lisp.
02:50emmaI wondered if anyone in Clojure had any good reasons why Clojure is a good lisp to learn or maybe the best.
02:51arbschtclojurebot: rationale
02:51clojurebotrationale is http://clojure.org/rationale
02:58emmaso it seems to be a lisp that can be used in place of Java and have all the good things about lisp but all the good things about java?
02:59arbschtit combines some of the good things of other lisps, some of the good things of java, some from other languages, and some new ideas and features too
03:03hiredman~blip.tv
03:03clojurebotblip.tv is http://clojure.blip.tv/
04:22rysIt's such a forward-thinking, portable Lisp, never mind the interaction with other languages on the JVM
04:27rysAdd the community and the JVM to that, and the fact it's not a research-driven language, and you have a really brilliant place to be if you want to learn a Lisp. Plus, the Clojure core has made some pretty big strides in recent months, so it keeps getting better
05:14angermancan I "undef" something?
05:16Ibex_twin@angerman: (ns-unmap namespace symbol)
05:16rysns-unmap will remove the def'd symbol from the namespace
05:18angermanthanks
05:41crioshello. Could someone clarify me the difference between ref and atom? In my understanding, ref lives inside a transaction, atom not. So updating an atom is like changing a static Java variable in a multithread (not safe) environment?
05:42Chousukecrios: an atom only guarantees an atomic change.
05:42Chousukeyou can't coordinate changes between multiple atoms like you can with refs
05:45criosby "coordinating changes" do you mean making more-than-one update in an transaction way?
05:46Chousukeyeah.
05:47criosok, thank you.
05:48criosand a function ending with a '!' means what ? like reset! (http://clojure.org/api#toc497)
05:48crios! points to a function which changes shared state?
05:49hiredmanit mutates something
05:49criosI don't understand why (alter does not end with '!'
05:49hiredman*shrug*
05:50criosI mean, both alter and swap alter a shared state
05:50Chousukecrios: alter can only be used inside a transaction, so it's "safe" I suppose
05:50hiredman! is a convention, not something enforced anywhere
05:51criosso swap! is not changing an atom inside a transaction?
05:51Chousukeswap! works anywhere
05:51hiredman,(swap! (atom 0) inc)
05:51clojurebot1
05:51crios'(doc swao)
05:51crios'(doc swap)
05:51Chousuke(doc swap!)
05:51clojurebot"([atom f] [atom f x] [atom f x y] [atom f x y & args]); Atomically swaps the value of atom to be: (apply f current-value-of-atom args). Note that f may be called multiple times, and thus should be free of side effects. Returns the value that was swapped in."
08:17LauJensenTop 'o da top gents
08:26drewrhola
09:11ole3j
09:45crios2help on the :keys binding on the function: (defn move [{:keys [body dir] :as snake} & grow] ( etc )) see the code on: http://pastebin.com/d45e8b3d7
09:46rhickeycrios2: what's the question?
09:46crios2the author says "The {:keys [body dir]} part makes the snake’s body and dir available as their own bindings"
09:47crios2on Programming Clojure book
09:47crios2I don't understand how :keys is binding [body dir]
09:47crios2is it a sort of "destructuring"?
09:48rhickey, (let [{:keys [a b]} {:a 1 :b 2}] [a b])
09:48clojurebot[1 2]
09:48rhickeyyes
09:48crios2Where can I find it on the APIs ?
09:49crios2I've studied just the special form :as
09:49rhickeyhttp://clojure.org/special_forms#let
09:50crios2ah ok, I see it
09:51crios2so "destructuring" is a sort of "anonymous let-ting"
09:52crios2thank you
09:52crios2by the way rhickey, I was asking myself what is the difference between (var and (resolve ?
09:53crios2both return the Var pointed by a symbol?
09:59crioswhen should one use the former or the latter? (I'm a newby)
10:01rhickeycrios: you should rarely use either
10:04criosjust trying to well understand what I'm reading in the book :)
10:05rhickeyvar is to get a var you know exists
10:05rhickey,(var rest)
10:05clojurebot#'clojure.core/rest
10:05rhickeyresolve is to try to find out if a symbol has some meaning in the ns
10:06rhickey,(resolve 'fred)
10:06clojurebotnil
10:06rhickey(var fred)
10:06rhickey,(var fred)
10:06clojurebotjava.lang.Exception: Unable to resolve var: fred in this context
10:06rhickey,(resolve 'String)
10:06clojurebotjava.lang.String
10:06rhickey(var String)
10:06rhickey,(var String)
10:06clojurebotjava.lang.Exception: Expecting var, but String is mapped to class java.lang.String
10:08criosso resolve is best suited for runtime checks
10:08criosok
10:39singhvI wrote this Sudoku solver a little while back: http://github.com/vishsingh/lisp-toronto/blob/80ea008e80976d3ec08b9005ace7658ec5278472/meetings/04-2009/sudoku.clj
10:41singhvI enjoyed writing it.. most interesting was the "parse-block" function. It uses a construction I invented called "union-map". It takes the union of the results of a map operation.
10:45singhvWhat would be a more idiomatic way to do this sort of thing? I was thinking something like: (into #{} (mapcat ..whatever..)).
11:27Chousersinghv: 'for' would probably work nicely for your nested ranges, let, and if (for has a :when)
11:28Chouserand since a false in the :when clause produces no output item at all, you don't need to use an empty set to skip things.
11:29Chouserso maybe (into #{} (for [y (range y1 y2), x (range x1 x2), :let [elem (get-in mat [y x])] :when (set? elem)] elem))
11:30Chousukesinghv: also (doall (vec ...)) is redundant. vec is strict already
11:31Chousukedoesn't doseq also support multiple sequences like for?
11:32Chousuke~def doseq
11:32Chousukeseems so.
11:33ChousukeI wonder why it's not just a wrapper for (dorun (for ...)) :/
11:34ChousukeI guess looping explicitly is more efficient than consuming a lazy seq
11:50ankouhi, the documentation says that clojure.contrib.test-is is just a compatibility layer on top of clojure.test but in clojure 1.0.0 there is no clojure.test, how can I use test-is?
11:52Chousukeankou: use the 1.0.0 compatible branch of contrib OR use clojure master branch from git
11:56ankouworks, thanks
12:09triyohhm, how do I check if a vector of chars contains a specific char? thought I could say ([\a \e \i \o \u] \a)
12:22triyook it works on sets (#{\a \e \i \o \u} \a) ...why is that this works on sets and not vectors?
12:24Chousukewhat do you mean?
12:24Chousuke,('[a e i o u] 3); vectors take an index as their parameter
12:24clojureboto
12:27Chousuketriyo: basically, maps, sets and vectors are associative things, and when used as functions take as a parameter a key and return the associated value. for vectors, this key is an integer; for maps, anything, and for sets, the key is the value
12:29triyoohh I see so its integers are keys for vectors. Set suites me perfectly for what I'm trying to do. thx
12:39singhvChouser: Thanks. That's clever, and it really simplifies the code. I was leaning towards using 'for', but didn't know that it was possible to use a ':let' clause inside it.
12:46singhvChousuke: You're right. I feel like I still haven't fully grokked laziness and how it works with different sequence types.
12:46Chousukesinghv: there's only one lazy structure in Clojure: the lazy seq
12:47Chousukelists, vectors, maps and sets are all strict
12:49Chousukeand the only clojure data structure that is also a sequence (besides lazy seqs, of course) is the list. for vectors etc. you get a "seq view" by calling seq on them
12:50ChousukeIf I'm forgetting something, now's the time to correct me :D
12:52ChouserChousuke: sounds right, though if finger trees are ever added, they'll be seqs too.
12:52ChousukeI wonder if the PersistentQueue type is a seq.
12:52singhvIs this "seq view" what clojure.lang.APersistentVector$Seq is?
12:53Chousukeyes.
12:54singhvgotcha. So when you call (rest ..) on a vector, you're not actually creating a new vector, but a new view into that same vector.
12:56singhvhere's one of my other confusions: (type [1 2 3]) -> clojure.lang.LazilyPersistentVector. what's "lazily" about this type?
13:01Chousukesinghv: it's not actually a real PersistentVector
13:02Chousukehmm
13:02Chousuke,(type [1 2 3 4 5 6 7 8])
13:02clojurebotclojure.lang.LazilyPersistentVector
13:02Chousuke,(type (conj [1 2 3 4 5 6 7 8] 1))
13:02clojurebotclojure.lang.PersistentVector
13:03Chousukeit's an optimisation for small literal vectors
13:03Chousuke,(type (conj [1 2 3 4 5 6] 1))
13:03clojurebotclojure.lang.PersistentVector
13:03Chousukelooks like it transforms into a PersistentVector on first conj
13:04rhickeyit's bad to care about or rely upon the concrete types of things
13:52beutdeuceHow would i be able to perform stdin and out in clojure?
13:57Chouserbeutdeuce: the JVM's in and out are bound to Clojure vars *in* and *out* respectively.
13:57Chouser,(.write *out* "hello")
13:57clojurebothello
13:57beutdeucethank you, what do the asterisks signify?
13:58Chouserthat's a convetion for global vars that you're likely to want to set or bind thread-locally
13:58Chouserfor example, with-out-str binds *out* to a stringwriter, and then returns that string.
13:58Chouser,(with-out-str (prn "one") (prn "two"))
13:58clojurebot"\"one\"\n\"two\"\n"
14:00beutdeuceah
14:00beutdeucety
14:03Chousera var like *out* isn't actually any different from a var like str, but it's much more likely you'll want to rebind *out* than str.
14:11beutdeucek
15:19mikehincheyhi. I've written a bunch of enhancements to clojure.stacktrace. Should I submit a ticket and patch?
15:36StartsWithKwhen using clojure.main how can i pass arguments to my script?
15:37StartsWithKi tried java -cp .. clojure.main -i @my/script.clj --help and i get clojure.main help screen
15:38Chouser--
15:41LauJensenChouser, rhickey, can't someone answer mikehinchey on how to submit enhancements?
15:42StartsWithKChouser: http://paste.pocoo.org/show/UiT6ju0nmDX0yGozy4aW/ fails from clojure.main, not my app
15:44hiredmanwhat does build.sh say?
15:44StartsWithKhiredman: http://paste.pocoo.org/show/h9amCLjkp3oiwWlKY4Ux/
15:45StartsWithKwithout --, it takes --help as part of clojure.main arguments :/
15:46hiredmanand main.clj?
15:47StartsWithKmain.clj prints *command-line-arg* and starts my app, then ends
15:47StartsWithKerorr message is then from clojure.main that scans for second -i (or other switch) as it consumed my @truba/main.clj
15:47StartsWithKfinds --
15:48StartsWithKand throws a exception
15:48hiredmanah
15:49hiredmanremove the "-i"
15:49StartsWithKhiredman: thanks, that worked (no need for --)
15:55Chousermikehinchey: it's good to get permission from a contrib commiter, best if from whoever has been most active in the lib you're patching. Use the clojure-dev or clojure groups to make contact.
15:56Chouser(to answer your question)
15:59hiredmanhttp://twitter.com/dysinger/statuses/3959082485
16:00LauJensenThanks Chris
16:05mikehincheyChouser: ok, thanks, I'll try that again
16:09triyoI came across this "CS Topic Generator" http://www.cs.purdue.edu/homes/dec/essay.topic.generator.html and thought I'd implement it myself for fun in clojure.
16:10triyocould anyone have a look at my clojure impl. and please comment? http://gist.github.com/186313
16:11triyowould this be the lispey way to write it? Could it be done better? thx
16:43JAS41532% is a lot!
16:44Chouseryes, it has given me hope. :-)
16:49fpshi
16:51fpssomebody around here using slime+clojure? (don't worry: no setup question)
16:51triyoI have a function that can return a string or a char. Is that valid or should my function always return a same data type?
16:52triyoin terms of best practice that is
16:54Chousertriyo: clojure has dynamic typing. do what makes sense.
16:55Chouserconj returns pretty much any kind of collection
16:59triyoChouser: could you pls have a look at this piece of code I wrote and let me know if there is anything glaringly obvious that could be done better (clojure way) http://gist.github.com/186313
17:00Chouser(doc rand-int)
17:00clojurebot"([n]); Returns a random integer between 0 (inclusive) and n (exclusive)."
17:02Chouserwhy call toupper on \a, instead of just using \A /
17:02Chouser?
17:03Chouseryou can use (.charAt word 0) or (first word) instead of the .. expr you've got
17:03Chousernothing else there really jumps out at me.
17:05triyo"why call toupper on \a, instead of just using \A /" -> because sometimes \a must be uppercase if it is for the first phrase
17:05triyothanks for the rand-int
17:05triyoalso for you last comment... greatly appreciate it.
17:06Chouser(if capitalize? \A \a) wouldn't work?
17:06triyohmm, blind :)
17:07triyoI like first word) instead of (.. ) call I have
17:08triyo(first word)
17:08JAS415(first word)
17:10JAS415isn't there a built in java capitalizer
17:11JAS415nope
17:11JAS415looks like i was making that up
17:11JAS415oh well
17:12triyoChouser: now that I got rand-int, would it be a good idea to still keep the smaller ver of my random-word function?
17:14triyohmm stupid question, sorry. I use it few places so makes sense to keep it as its on defined function
17:14Chouser(doc clojure.contrib.seq-utils/rand-elt)
17:14clojurebot"([s]); Return a random element of this seq"
17:14Chouserit makes so much sense, someone else already wrote it. :-)
17:15triyohehehe, sure
17:26technomancythat didn't exist when I started... kids these days.
17:33JAS415lol
18:13singhvModified my sudoku.clj based on your feedback: http://github.com/vishsingh/lisp-toronto/commit/34aea588b13812315477053ca83922461bef1f13
19:00Nate75Sandershas there been any talk of something like SRFI-38 for Clojure? ( http://srfi.schemers.org/srfi-38/srfi-38.html ) or does Clojure already have some method for externalizing shared structure?
19:03hiredmanNate75Sanders: since clojure's datastructures are immutable, there is no set-cdr!
19:03Nate75Sandershiredman: You'll have to explain to me how that's relevant....I don't understand
19:03quidnuncAnyone know if whoever wrote date.clj plans on contributing it to contrib? https://gist.github.com/raw/49656/badd0039ca9d75402ce0cff54e0289955ca92225/date.clj
19:04Nate75Sandershiredman: All I'm saying is that if Clojure is already handling these data structure diffs, we should be able to externalize them that way if we wish
19:04hiredmanNate75Sanders: a clojure list, cannot be made to reference ittself
19:05hiredmanit is possible to have an issue with circular refs or atoms
19:05Nate75Sandershiredman: doing external representations of shared structure right now involve a copy of a string if I'm not mistaken
19:05hiredmanah
19:05Nate75Sandershiredman: you'd be storing state as if it were not shared
19:05hiredmanI misunderstood
19:05Nate75Sandershiredman: I want the state to be shared on-disk as well
19:06hiredman:(
19:06hiredmanshared structure is an implementation detail/performance optimization
19:07hiredmanexposing it for munging with seems like a bad idea
19:07Nate75SandersI don't share your opinion
19:07hiredman*shrug*
19:07Nate75SandersI don't think "printed representation of" is the same as "munging with"
19:07hiredmanquidnunc: there was a thread about it on the group
19:08Nate75SandersAgain, if clojure is already doing these diffs for us, that's powerful and something I'd like to harness
19:08Nate75SandersYou could build a revision system/undo/redo/etc with the work that's already been done
19:08hiredman:(
19:08hiredmaneww
19:08Nate75Sandersnot just on strings, but on pretty much anything as far as I can tell
19:09hiredmanno
19:09hiredmanstrings are java Strings
19:09hiredmanany "sharing" is a jvm implementation detail
19:11hiredmanand it's not mutating something and keeping a history of the mutation, it's creating new things that incidentally shares some parts with the old thing
19:11Nate75Sandersyes, i understand how it works
19:11Nate75Sandersthe history should be pretty easy to keep track of
19:12quidnunchiredman: I searched for "date.clj" and turned up nothing on Google groups
19:13hiredman*shrug*
19:13hiredmanI think it was technomancy's baby
19:14quidnunc"date" turns up nothing in clojure-dev and nothing relevant in the clojure group.
19:15quidnunchiredman: Do you know approximately when it was discussed?
19:17hiredmanhttp://groups.google.com/group/clojure/browse_thread/thread/659503e698ede0b5/f38621b4816302b0?q=date+clojure+technomancy#f38621b4816302b0
19:18hiredmantechnomancy is in here from time to time, so he would be the one to ask about it
19:18quidnunchiredman: Thanks for the link
19:47oyiptongwhat's a good way to get into clojure coming from a mostly imperative/OO experience?
19:47oyiptongI want to use clojure for AI-related work
19:48arbschtI hear Programming Clojure is good
21:39emacsenis there a good uri construction/deconstruction library? I realize it's trivial but I figured I'd ask
21:52hiredmanhttp://www.thelastcitadel.com/lab/deps.svg still a few bugs to iron out
21:53hiredmanI need to get dot to output a nicer looking graph
21:53emacsengood luck with that. dot's a beast
21:53ChouserI was just about to say the same.
21:54hiredmanalternatively I could figure out some kind of java charting library
21:54hiredmanbut I just got dot output working
21:55hiredmanthere
21:55hiredmanmuch nicer
21:55hiredmanhttp://gist.github.com/186432
21:56hiredmanthe ns form parsing is pretty primitive
21:56hiredmanand I should wrap it up in a nice script
21:57hiredmanand figure out why certain clojure files are not being recognized as such
22:08hiredmanhttp://www.thelastcitadel.com/lab/ring-deps.svg
22:19lowlycoderis there any reason to use latest clojure instead of clojure-1.0.0.zip ?
22:19hiredmantest-is is now in core
22:19hiredmanuh, I'm sure there must be other stuff
22:20hiredmanchunked sequences is post 1.0
22:22hiredmanclojurebot: graph?
22:22clojurebotI don't understand.
22:23hiredmanclojurebot: graph is <reply>http://github.com/hiredman/clojure-dependency-grapher
22:23clojurebotIn Ordnung
22:53emacsenis there a straightforward way within clj to have something be both a struct and a function?
22:54hiredmaneh?
22:54hiredmanstrcuts are maps, and maps are functions of their keys
22:55emacsenwell, here's what I want, and maybe there's another way to do it...
22:55emacsenI have a structure called a bounding box, which is 4 geographic points
22:55emacsenand I'd like to be able to take a set of points and filter it on that bounding box
22:56emacsenso it'd be (filter bbox points)
22:56hiredmanwell, there is a function called filter
22:57hiredman(filter (partial inside? bbox) points)
22:57emacsenI guess (in-bbox bbox) isn't TOO bad
22:57emacsenwhat's the partial for?
22:58hiredmanpartial application
22:58emacsenie why not #(inside? bbox %) ?
22:58hiredmanbecause I use higher order functions in preference to anonymous functions
22:59emacsenI've never used partial. What does partial buy me here?
23:02hiredmanwhat does #() buy you?
23:04hiredmanpartial is a succint description of the function. it is the function you get from partially applying inside? to bbox
23:04hiredman#() is just noise
23:04emacsenyeah I don't get what that means
23:04emacsen"partially applying"
23:04emacsenwhat does that mean
23:05hiredmanso inside? takes 2 args, (partial inside? x) returns a function that takes one arg
23:05albinoit means passing a certain number of arguments into a function and getting a function back out which expects the rest of the arguments
23:06emacsenOh I see, sort of. I'll need to play with that. I do a lot of anonymous function calling in my filters
23:08albino(add 1 2) -> 3 ... (def add1 (partial add 1)) ... (add1 5) -> 6
23:08hiredmanhttp://gist.github.com/184831
23:09emacsenalbino: wow that's wild
23:10albinohiredman's paste means less to me, but I don't read clojure code often, much more use to python
23:11hiredmana lot of my code ends up looking like that
23:11hiredmana big -> form
23:11emacsenyeah hiredman's code's very dense and w/o a lot of explanation
23:11emacsenpart of the problem with the clojure docs is they assume you know a lot of the terms
23:11emacsenthat is they're quite terse and use existing jargon
23:12emacsenand you have to know what end of the thing to pull at
23:12hiredmanit's more of a warning about following my advice in ragards to style
23:13albinowell partial function application is a cross language concept