2009-09-13
| 02:46 | emma | Hi is anyone here awake? |
| 02:47 | arbscht | hi |
| 02:49 | emma | oh hai |
| 02:49 | emma | I 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:50 | emma | I wondered if anyone in Clojure had any good reasons why Clojure is a good lisp to learn or maybe the best. |
| 02:51 | arbscht | clojurebot: rationale |
| 02:51 | clojurebot | rationale is http://clojure.org/rationale |
| 02:58 | emma | so 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:59 | arbscht | it 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:03 | hiredman | ~blip.tv |
| 03:03 | clojurebot | blip.tv is http://clojure.blip.tv/ |
| 04:22 | rys | It's such a forward-thinking, portable Lisp, never mind the interaction with other languages on the JVM |
| 04:27 | rys | Add 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:14 | angerman | can I "undef" something? |
| 05:16 | Ibex_twin | @angerman: (ns-unmap namespace symbol) |
| 05:16 | rys | ns-unmap will remove the def'd symbol from the namespace |
| 05:18 | angerman | thanks |
| 05:41 | crios | hello. 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:42 | Chousuke | crios: an atom only guarantees an atomic change. |
| 05:42 | Chousuke | you can't coordinate changes between multiple atoms like you can with refs |
| 05:45 | crios | by "coordinating changes" do you mean making more-than-one update in an transaction way? |
| 05:46 | Chousuke | yeah. |
| 05:47 | crios | ok, thank you. |
| 05:48 | crios | and a function ending with a '!' means what ? like reset! (http://clojure.org/api#toc497) |
| 05:48 | crios | ! points to a function which changes shared state? |
| 05:49 | hiredman | it mutates something |
| 05:49 | crios | I don't understand why (alter does not end with '!' |
| 05:49 | hiredman | *shrug* |
| 05:50 | crios | I mean, both alter and swap alter a shared state |
| 05:50 | Chousuke | crios: alter can only be used inside a transaction, so it's "safe" I suppose |
| 05:50 | hiredman | ! is a convention, not something enforced anywhere |
| 05:51 | crios | so swap! is not changing an atom inside a transaction? |
| 05:51 | Chousuke | swap! works anywhere |
| 05:51 | hiredman | ,(swap! (atom 0) inc) |
| 05:51 | clojurebot | 1 |
| 05:51 | crios | '(doc swao) |
| 05:51 | crios | '(doc swap) |
| 05:51 | Chousuke | (doc swap!) |
| 05:51 | clojurebot | "([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:17 | LauJensen | Top 'o da top gents |
| 08:26 | drewr | hola |
| 09:11 | ole3 | j |
| 09:45 | crios2 | help 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:46 | rhickey | crios2: what's the question? |
| 09:46 | crios2 | the author says "The {:keys [body dir]} part makes the snake’s body and dir available as their own bindings" |
| 09:47 | crios2 | on Programming Clojure book |
| 09:47 | crios2 | I don't understand how :keys is binding [body dir] |
| 09:47 | crios2 | is it a sort of "destructuring"? |
| 09:48 | rhickey | , (let [{:keys [a b]} {:a 1 :b 2}] [a b]) |
| 09:48 | clojurebot | [1 2] |
| 09:48 | rhickey | yes |
| 09:48 | crios2 | Where can I find it on the APIs ? |
| 09:49 | crios2 | I've studied just the special form :as |
| 09:49 | rhickey | http://clojure.org/special_forms#let |
| 09:50 | crios2 | ah ok, I see it |
| 09:51 | crios2 | so "destructuring" is a sort of "anonymous let-ting" |
| 09:52 | crios2 | thank you |
| 09:52 | crios2 | by the way rhickey, I was asking myself what is the difference between (var and (resolve ? |
| 09:53 | crios2 | both return the Var pointed by a symbol? |
| 09:59 | crios | when should one use the former or the latter? (I'm a newby) |
| 10:01 | rhickey | crios: you should rarely use either |
| 10:04 | crios | just trying to well understand what I'm reading in the book :) |
| 10:05 | rhickey | var is to get a var you know exists |
| 10:05 | rhickey | ,(var rest) |
| 10:05 | clojurebot | #'clojure.core/rest |
| 10:05 | rhickey | resolve is to try to find out if a symbol has some meaning in the ns |
| 10:06 | rhickey | ,(resolve 'fred) |
| 10:06 | clojurebot | nil |
| 10:06 | rhickey | (var fred) |
| 10:06 | rhickey | ,(var fred) |
| 10:06 | clojurebot | java.lang.Exception: Unable to resolve var: fred in this context |
| 10:06 | rhickey | ,(resolve 'String) |
| 10:06 | clojurebot | java.lang.String |
| 10:06 | rhickey | (var String) |
| 10:06 | rhickey | ,(var String) |
| 10:06 | clojurebot | java.lang.Exception: Expecting var, but String is mapped to class java.lang.String |
| 10:08 | crios | so resolve is best suited for runtime checks |
| 10:08 | crios | ok |
| 10:39 | singhv | I wrote this Sudoku solver a little while back: http://github.com/vishsingh/lisp-toronto/blob/80ea008e80976d3ec08b9005ace7658ec5278472/meetings/04-2009/sudoku.clj |
| 10:41 | singhv | I 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:45 | singhv | What would be a more idiomatic way to do this sort of thing? I was thinking something like: (into #{} (mapcat ..whatever..)). |
| 11:27 | Chouser | singhv: 'for' would probably work nicely for your nested ranges, let, and if (for has a :when) |
| 11:28 | Chouser | and 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:29 | Chouser | so maybe (into #{} (for [y (range y1 y2), x (range x1 x2), :let [elem (get-in mat [y x])] :when (set? elem)] elem)) |
| 11:30 | Chousuke | singhv: also (doall (vec ...)) is redundant. vec is strict already |
| 11:31 | Chousuke | doesn't doseq also support multiple sequences like for? |
| 11:32 | Chousuke | ~def doseq |
| 11:32 | Chousuke | seems so. |
| 11:33 | Chousuke | I wonder why it's not just a wrapper for (dorun (for ...)) :/ |
| 11:34 | Chousuke | I guess looping explicitly is more efficient than consuming a lazy seq |
| 11:50 | ankou | hi, 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:52 | Chousuke | ankou: use the 1.0.0 compatible branch of contrib OR use clojure master branch from git |
| 11:56 | ankou | works, thanks |
| 12:09 | triyo | hhm, how do I check if a vector of chars contains a specific char? thought I could say ([\a \e \i \o \u] \a) |
| 12:22 | triyo | ok it works on sets (#{\a \e \i \o \u} \a) ...why is that this works on sets and not vectors? |
| 12:24 | Chousuke | what do you mean? |
| 12:24 | Chousuke | ,('[a e i o u] 3); vectors take an index as their parameter |
| 12:24 | clojurebot | o |
| 12:27 | Chousuke | triyo: 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:29 | triyo | ohh I see so its integers are keys for vectors. Set suites me perfectly for what I'm trying to do. thx |
| 12:39 | singhv | Chouser: 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:46 | singhv | Chousuke: You're right. I feel like I still haven't fully grokked laziness and how it works with different sequence types. |
| 12:46 | Chousuke | singhv: there's only one lazy structure in Clojure: the lazy seq |
| 12:47 | Chousuke | lists, vectors, maps and sets are all strict |
| 12:49 | Chousuke | and 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:50 | Chousuke | If I'm forgetting something, now's the time to correct me :D |
| 12:52 | Chouser | Chousuke: sounds right, though if finger trees are ever added, they'll be seqs too. |
| 12:52 | Chousuke | I wonder if the PersistentQueue type is a seq. |
| 12:52 | singhv | Is this "seq view" what clojure.lang.APersistentVector$Seq is? |
| 12:53 | Chousuke | yes. |
| 12:54 | singhv | gotcha. 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:56 | singhv | here's one of my other confusions: (type [1 2 3]) -> clojure.lang.LazilyPersistentVector. what's "lazily" about this type? |
| 13:01 | Chousuke | singhv: it's not actually a real PersistentVector |
| 13:02 | Chousuke | hmm |
| 13:02 | Chousuke | ,(type [1 2 3 4 5 6 7 8]) |
| 13:02 | clojurebot | clojure.lang.LazilyPersistentVector |
| 13:02 | Chousuke | ,(type (conj [1 2 3 4 5 6 7 8] 1)) |
| 13:02 | clojurebot | clojure.lang.PersistentVector |
| 13:03 | Chousuke | it's an optimisation for small literal vectors |
| 13:03 | Chousuke | ,(type (conj [1 2 3 4 5 6] 1)) |
| 13:03 | clojurebot | clojure.lang.PersistentVector |
| 13:03 | Chousuke | looks like it transforms into a PersistentVector on first conj |
| 13:04 | rhickey | it's bad to care about or rely upon the concrete types of things |
| 13:52 | beutdeuce | How would i be able to perform stdin and out in clojure? |
| 13:57 | Chouser | beutdeuce: the JVM's in and out are bound to Clojure vars *in* and *out* respectively. |
| 13:57 | Chouser | ,(.write *out* "hello") |
| 13:57 | clojurebot | hello |
| 13:57 | beutdeuce | thank you, what do the asterisks signify? |
| 13:58 | Chouser | that's a convetion for global vars that you're likely to want to set or bind thread-locally |
| 13:58 | Chouser | for example, with-out-str binds *out* to a stringwriter, and then returns that string. |
| 13:58 | Chouser | ,(with-out-str (prn "one") (prn "two")) |
| 13:58 | clojurebot | "\"one\"\n\"two\"\n" |
| 14:00 | beutdeuce | ah |
| 14:00 | beutdeuce | ty |
| 14:03 | Chouser | a 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:11 | beutdeuce | k |
| 15:19 | mikehinchey | hi. I've written a bunch of enhancements to clojure.stacktrace. Should I submit a ticket and patch? |
| 15:36 | StartsWithK | when using clojure.main how can i pass arguments to my script? |
| 15:37 | StartsWithK | i tried java -cp .. clojure.main -i @my/script.clj --help and i get clojure.main help screen |
| 15:38 | Chouser | -- |
| 15:41 | LauJensen | Chouser, rhickey, can't someone answer mikehinchey on how to submit enhancements? |
| 15:42 | StartsWithK | Chouser: http://paste.pocoo.org/show/UiT6ju0nmDX0yGozy4aW/ fails from clojure.main, not my app |
| 15:44 | hiredman | what does build.sh say? |
| 15:44 | StartsWithK | hiredman: http://paste.pocoo.org/show/h9amCLjkp3oiwWlKY4Ux/ |
| 15:45 | StartsWithK | without --, it takes --help as part of clojure.main arguments :/ |
| 15:46 | hiredman | and main.clj? |
| 15:47 | StartsWithK | main.clj prints *command-line-arg* and starts my app, then ends |
| 15:47 | StartsWithK | erorr message is then from clojure.main that scans for second -i (or other switch) as it consumed my @truba/main.clj |
| 15:47 | StartsWithK | finds -- |
| 15:48 | StartsWithK | and throws a exception |
| 15:48 | hiredman | ah |
| 15:49 | hiredman | remove the "-i" |
| 15:49 | StartsWithK | hiredman: thanks, that worked (no need for --) |
| 15:55 | Chouser | mikehinchey: 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:56 | Chouser | (to answer your question) |
| 15:59 | hiredman | http://twitter.com/dysinger/statuses/3959082485 |
| 16:00 | LauJensen | Thanks Chris |
| 16:05 | mikehinchey | Chouser: ok, thanks, I'll try that again |
| 16:09 | triyo | I 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:10 | triyo | could anyone have a look at my clojure impl. and please comment? http://gist.github.com/186313 |
| 16:11 | triyo | would this be the lispey way to write it? Could it be done better? thx |
| 16:43 | JAS415 | 32% is a lot! |
| 16:44 | Chouser | yes, it has given me hope. :-) |
| 16:49 | fps | hi |
| 16:51 | fps | somebody around here using slime+clojure? (don't worry: no setup question) |
| 16:51 | triyo | I 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:52 | triyo | in terms of best practice that is |
| 16:54 | Chouser | triyo: clojure has dynamic typing. do what makes sense. |
| 16:55 | Chouser | conj returns pretty much any kind of collection |
| 16:59 | triyo | Chouser: 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:00 | Chouser | (doc rand-int) |
| 17:00 | clojurebot | "([n]); Returns a random integer between 0 (inclusive) and n (exclusive)." |
| 17:02 | Chouser | why call toupper on \a, instead of just using \A / |
| 17:02 | Chouser | ? |
| 17:03 | Chouser | you can use (.charAt word 0) or (first word) instead of the .. expr you've got |
| 17:03 | Chouser | nothing else there really jumps out at me. |
| 17:05 | triyo | "why call toupper on \a, instead of just using \A /" -> because sometimes \a must be uppercase if it is for the first phrase |
| 17:05 | triyo | thanks for the rand-int |
| 17:05 | triyo | also for you last comment... greatly appreciate it. |
| 17:06 | Chouser | (if capitalize? \A \a) wouldn't work? |
| 17:06 | triyo | hmm, blind :) |
| 17:07 | triyo | I like first word) instead of (.. ) call I have |
| 17:08 | triyo | (first word) |
| 17:08 | JAS415 | (first word) |
| 17:10 | JAS415 | isn't there a built in java capitalizer |
| 17:11 | JAS415 | nope |
| 17:11 | JAS415 | looks like i was making that up |
| 17:11 | JAS415 | oh well |
| 17:12 | triyo | Chouser: now that I got rand-int, would it be a good idea to still keep the smaller ver of my random-word function? |
| 17:14 | triyo | hmm stupid question, sorry. I use it few places so makes sense to keep it as its on defined function |
| 17:14 | Chouser | (doc clojure.contrib.seq-utils/rand-elt) |
| 17:14 | clojurebot | "([s]); Return a random element of this seq" |
| 17:14 | Chouser | it makes so much sense, someone else already wrote it. :-) |
| 17:15 | triyo | hehehe, sure |
| 17:26 | technomancy | that didn't exist when I started... kids these days. |
| 17:33 | JAS415 | lol |
| 18:13 | singhv | Modified my sudoku.clj based on your feedback: http://github.com/vishsingh/lisp-toronto/commit/34aea588b13812315477053ca83922461bef1f13 |
| 19:00 | Nate75Sanders | has 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:03 | hiredman | Nate75Sanders: since clojure's datastructures are immutable, there is no set-cdr! |
| 19:03 | Nate75Sanders | hiredman: You'll have to explain to me how that's relevant....I don't understand |
| 19:03 | quidnunc | Anyone know if whoever wrote date.clj plans on contributing it to contrib? https://gist.github.com/raw/49656/badd0039ca9d75402ce0cff54e0289955ca92225/date.clj |
| 19:04 | Nate75Sanders | hiredman: 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:04 | hiredman | Nate75Sanders: a clojure list, cannot be made to reference ittself |
| 19:05 | hiredman | it is possible to have an issue with circular refs or atoms |
| 19:05 | Nate75Sanders | hiredman: doing external representations of shared structure right now involve a copy of a string if I'm not mistaken |
| 19:05 | hiredman | ah |
| 19:05 | Nate75Sanders | hiredman: you'd be storing state as if it were not shared |
| 19:05 | hiredman | I misunderstood |
| 19:05 | Nate75Sanders | hiredman: I want the state to be shared on-disk as well |
| 19:06 | hiredman | :( |
| 19:06 | hiredman | shared structure is an implementation detail/performance optimization |
| 19:07 | hiredman | exposing it for munging with seems like a bad idea |
| 19:07 | Nate75Sanders | I don't share your opinion |
| 19:07 | hiredman | *shrug* |
| 19:07 | Nate75Sanders | I don't think "printed representation of" is the same as "munging with" |
| 19:07 | hiredman | quidnunc: there was a thread about it on the group |
| 19:08 | Nate75Sanders | Again, if clojure is already doing these diffs for us, that's powerful and something I'd like to harness |
| 19:08 | Nate75Sanders | You could build a revision system/undo/redo/etc with the work that's already been done |
| 19:08 | hiredman | :( |
| 19:08 | hiredman | eww |
| 19:08 | Nate75Sanders | not just on strings, but on pretty much anything as far as I can tell |
| 19:09 | hiredman | no |
| 19:09 | hiredman | strings are java Strings |
| 19:09 | hiredman | any "sharing" is a jvm implementation detail |
| 19:11 | hiredman | and 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:11 | Nate75Sanders | yes, i understand how it works |
| 19:11 | Nate75Sanders | the history should be pretty easy to keep track of |
| 19:12 | quidnunc | hiredman: I searched for "date.clj" and turned up nothing on Google groups |
| 19:13 | hiredman | *shrug* |
| 19:13 | hiredman | I think it was technomancy's baby |
| 19:14 | quidnunc | "date" turns up nothing in clojure-dev and nothing relevant in the clojure group. |
| 19:15 | quidnunc | hiredman: Do you know approximately when it was discussed? |
| 19:17 | hiredman | http://groups.google.com/group/clojure/browse_thread/thread/659503e698ede0b5/f38621b4816302b0?q=date+clojure+technomancy#f38621b4816302b0 |
| 19:18 | hiredman | technomancy is in here from time to time, so he would be the one to ask about it |
| 19:18 | quidnunc | hiredman: Thanks for the link |
| 19:47 | oyiptong | what's a good way to get into clojure coming from a mostly imperative/OO experience? |
| 19:47 | oyiptong | I want to use clojure for AI-related work |
| 19:48 | arbscht | I hear Programming Clojure is good |
| 21:39 | emacsen | is there a good uri construction/deconstruction library? I realize it's trivial but I figured I'd ask |
| 21:52 | hiredman | http://www.thelastcitadel.com/lab/deps.svg still a few bugs to iron out |
| 21:53 | hiredman | I need to get dot to output a nicer looking graph |
| 21:53 | emacsen | good luck with that. dot's a beast |
| 21:53 | Chouser | I was just about to say the same. |
| 21:54 | hiredman | alternatively I could figure out some kind of java charting library |
| 21:54 | hiredman | but I just got dot output working |
| 21:55 | hiredman | there |
| 21:55 | hiredman | much nicer |
| 21:55 | hiredman | http://gist.github.com/186432 |
| 21:56 | hiredman | the ns form parsing is pretty primitive |
| 21:56 | hiredman | and I should wrap it up in a nice script |
| 21:57 | hiredman | and figure out why certain clojure files are not being recognized as such |
| 22:08 | hiredman | http://www.thelastcitadel.com/lab/ring-deps.svg |
| 22:19 | lowlycoder | is there any reason to use latest clojure instead of clojure-1.0.0.zip ? |
| 22:19 | hiredman | test-is is now in core |
| 22:19 | hiredman | uh, I'm sure there must be other stuff |
| 22:20 | hiredman | chunked sequences is post 1.0 |
| 22:22 | hiredman | clojurebot: graph? |
| 22:22 | clojurebot | I don't understand. |
| 22:23 | hiredman | clojurebot: graph is <reply>http://github.com/hiredman/clojure-dependency-grapher |
| 22:23 | clojurebot | In Ordnung |
| 22:53 | emacsen | is there a straightforward way within clj to have something be both a struct and a function? |
| 22:54 | hiredman | eh? |
| 22:54 | hiredman | strcuts are maps, and maps are functions of their keys |
| 22:55 | emacsen | well, here's what I want, and maybe there's another way to do it... |
| 22:55 | emacsen | I have a structure called a bounding box, which is 4 geographic points |
| 22:55 | emacsen | and I'd like to be able to take a set of points and filter it on that bounding box |
| 22:56 | emacsen | so it'd be (filter bbox points) |
| 22:56 | hiredman | well, there is a function called filter |
| 22:57 | hiredman | (filter (partial inside? bbox) points) |
| 22:57 | emacsen | I guess (in-bbox bbox) isn't TOO bad |
| 22:57 | emacsen | what's the partial for? |
| 22:58 | hiredman | partial application |
| 22:58 | emacsen | ie why not #(inside? bbox %) ? |
| 22:58 | hiredman | because I use higher order functions in preference to anonymous functions |
| 22:59 | emacsen | I've never used partial. What does partial buy me here? |
| 23:02 | hiredman | what does #() buy you? |
| 23:04 | hiredman | partial is a succint description of the function. it is the function you get from partially applying inside? to bbox |
| 23:04 | hiredman | #() is just noise |
| 23:04 | emacsen | yeah I don't get what that means |
| 23:04 | emacsen | "partially applying" |
| 23:04 | emacsen | what does that mean |
| 23:05 | hiredman | so inside? takes 2 args, (partial inside? x) returns a function that takes one arg |
| 23:05 | albino | it means passing a certain number of arguments into a function and getting a function back out which expects the rest of the arguments |
| 23:06 | emacsen | Oh I see, sort of. I'll need to play with that. I do a lot of anonymous function calling in my filters |
| 23:08 | albino | (add 1 2) -> 3 ... (def add1 (partial add 1)) ... (add1 5) -> 6 |
| 23:08 | hiredman | http://gist.github.com/184831 |
| 23:09 | emacsen | albino: wow that's wild |
| 23:10 | albino | hiredman's paste means less to me, but I don't read clojure code often, much more use to python |
| 23:11 | hiredman | a lot of my code ends up looking like that |
| 23:11 | hiredman | a big -> form |
| 23:11 | emacsen | yeah hiredman's code's very dense and w/o a lot of explanation |
| 23:11 | emacsen | part of the problem with the clojure docs is they assume you know a lot of the terms |
| 23:11 | emacsen | that is they're quite terse and use existing jargon |
| 23:12 | emacsen | and you have to know what end of the thing to pull at |
| 23:12 | hiredman | it's more of a warning about following my advice in ragards to style |
| 23:13 | albino | well partial function application is a cross language concept |