2009-10-25
| 00:51 | qed | how do you compare to strings |
| 00:51 | qed | like (= str str) |
| 00:51 | qed | or (== str str) |
| 01:04 | danlarkin | (doc =) |
| 01:04 | danlarkin | (doc ==) |
| 01:04 | scottj | qed, = |
| 01:21 | defn | How do I do a decrementing while loop in clojure? |
| 01:22 | defn | I'm taking some input to this function, an integer |
| 01:22 | defn | I want to decrement that integer until a function on the same input is true |
| 01:22 | defn | and return that integer |
| 01:26 | lisppaste8 | cema pasted "md5" at http://paste.lisp.org/display/89237 |
| 01:29 | Guest16869 | defn: for example like this: (defn foo [n] (if (<= n 3) n (recur (dec n)))) |
| 01:30 | defn | danlei: what about with true/false? |
| 01:30 | danlei | what do you mean? |
| 01:32 | defn | danlei: http://pastie.org/private/dg1vj8nxhvmk00hjw0jpg |
| 01:32 | defn | that first function, reverse-and-test is testing to see if the input and the reverse of the input are equal |
| 01:32 | defn | it takes an int |
| 01:33 | defn | in test-down we want to sart at 998001, and decrement that number until we find a palindrome |
| 01:33 | defn | danlei: does that make sense? |
| 01:36 | danlei | defn: (defn palindromep [n] |
| 01:36 | danlei | (= n (read-string (apply str (reverse (str n)))))) |
| 01:36 | danlei | defn: if you use that instead of (<= n 3) in the example above, it'll work |
| 01:36 | danlei | don't know if it's elegant, I just followed the string-reversion approach |
| 01:37 | danlei | (defn foo [n] (if (palindrome? n) n (recur (dec n)))) [untested] |
| 01:39 | defn | string-reversion approach? |
| 01:39 | danlei | number -> string -> reverse -> number |
| 01:39 | defn | are you a Haskell guy? |
| 01:40 | defn | the '->'s make me suspicious |
| 01:40 | danlei | no :) |
| 01:42 | defn | that doesn't work |
| 01:42 | danlei | (palindrome? 11) true |
| 01:42 | danlei | (palindrome? 12) false |
| 01:42 | danlei | what shouldn't work there? |
| 01:43 | defn | that works fine |
| 01:43 | danlei | (defn find-palindrome [n] |
| 01:43 | danlei | (if (palindrome? n) |
| 01:43 | danlei | n |
| 01:43 | danlei | (recur (dec n)))) |
| 01:44 | defn | but let's say we're starting at the number 998001 and want to test every number, decrementing by 1, until we find a case that is true |
| 01:44 | danlei | (find-palindrome 15) |
| 01:44 | danlei | 11 |
| 01:44 | danlei | I don't see the problem, can you elaborate? |
| 01:44 | danlei | or, if you don't like recur ... |
| 01:45 | danlei | (first (drop-while #(not palindrome? %) (iterate dec 998001))) [untested] |
| 01:46 | defn | java.lang.NumberFormatException: Invalid number: 000899 |
| 01:46 | defn | |
| 01:46 | danlei | ah, ok |
| 01:46 | danlei | wrap it in a try block |
| 01:46 | danlei | not elegant, but should do |
| 01:46 | defn | this started out so pretty |
| 01:47 | defn | and now is descending into a pool of liquid shit |
| 01:47 | defn | lol |
| 01:49 | danlei | or just use Integer/parseInt instead of read |
| 01:54 | danlei | defn: btw. I tested it and it found the number without any problems |
| 01:55 | danlei | (without changing anything) |
| 01:55 | qed | even from 998001 |
| 01:55 | qed | ? |
| 01:56 | qed | oopa |
| 01:56 | defn | even from 998001? |
| 01:57 | danlei | with parseInt: (defn palindrome? [n] |
| 01:57 | danlei | (= n (Integer/parseInt (apply str (reverse (str n)))))) |
| 01:57 | danlei | (first (drop-while #(not (palindrome? %)) (iterate dec 998001))) |
| 02:03 | defn | thanks |
| 02:04 | danlei | not without changing anything tough: forgot () around (palindrome? %) above |
| 02:08 | danlei | defn: this is better: (first (filter palindrome? (iterate dec 998001))) |
| 02:08 | defn | nice filter |
| 02:08 | defn | thanks |
| 02:09 | danlei | welcome |
| 02:12 | defn | danlei: could you explain how (let [products (for [a (range 100 1000) b (range 100 a)] (* a b))] (reduce max (filter palindrome? products))) works? |
| 02:12 | defn | I don't understand the [ [ []]] stuff within the let, nor how it is passed forward to the reduce max fn |
| 02:13 | qed | im still here |
| 02:13 | qed | fwiw |
| 02:22 | danlei | defn: (for [a (range 100 1000) b (range 100 a)] (* a b)) iterates for a from 100 to 100 and b from 100 to a, computing the product of them. this gets bound to procucts, which is then passed to filter in the body of the let |
| 02:24 | danlei | defn: try to reduce the code to smaller examples, and you'll understand. like: (for [x '[a b] y '[c d]] (list x y)) will give you the permutations of [a b] [c d] ... |
| 02:25 | danlei | where in [x y] x is out of [a b] and y is out of [c d] |
| 04:37 | yason | In an agent action, how do I know which agent was it sent to? |
| 04:38 | yason | If I'm to resend the action again from the action itself, I kind of need to know the agent. ants.clj used *agents* that was defined nowhere in ants.clj but didn't seem to be in Clojure 1.0 either. |
| 04:48 | cgrand | yason: *agent* |
| 04:48 | cgrand | is bind to the current running agent |
| 04:53 | yason | cgrand: I saw that and I think I tried that; perhaps I'll cross-check my experiments. Was it documented somewhere? |
| 04:54 | hiredman | it is |
| 04:55 | hiredman | also documented is the fact that agents hold sends until the completion of an action |
| 04:56 | yason | The docstring for *agent* is there, perhaps I just didn't find it on the Clojure website. |
| 04:56 | cgrand | yason: http://clojure.org/api#toc9 |
| 04:56 | yason | cgrand: of course, thanks! |
| 04:56 | cgrand | but no mention of it on clojure.org/agents |
| 04:57 | yason | cgrand: would've helped if it had been mentioned on the Agents page :) |
| 06:18 | ambient | threads are still completely controlled with Java interop, right? |
| 06:18 | ambient | and the message passing between threads |
| 06:32 | Chousuke | ambient: you can use any of the clojure concurrency constructs instead of using threads directly |
| 06:33 | Chousuke | but yeah, if you do need full control for some reason, it's done via Java interop. |
| 06:33 | ambient | but if i need to run high-performance computing in the background and send and receive messages from and to that "engine"? |
| 06:34 | ambient | what would be the best way to do this with clojure? |
| 06:35 | ambient | (not HPC, just fast math) |
| 06:36 | Chousuke | hmm. |
| 06:37 | ambient | the point is to control it from REPL like this: (start-engine) (send-stuff some-stuff) (stop-engine) |
| 06:37 | Chousuke | well, you might be able to use watchers. |
| 06:37 | Chousuke | and an agent for serialising the message sends |
| 06:38 | ambient | ok, going to check out watchers |
| 06:39 | ambient | the engine might run with IO call-back thread |
| 06:39 | ambient | minus thread |
| 06:40 | ambient | basically it can be considered as an audio mixer that's constantly sending data. (send-stuff) sends a buffer that contains some information how to generate a wave |
| 06:40 | ambient | or changes some values in the engine |
| 06:41 | ambient | if it got no inputs, it just generates and plays silence |
| 06:41 | Chousuke | I guess you should just use plain threads. |
| 06:55 | AWizzArd | Is it only me, or do you also see http://github.com/richhickey/ as pretty empty? |
| 06:55 | ambient | AWizzArd only you |
| 06:55 | AWizzArd | ah ok, website is back |
| 06:55 | ambient | depending of your definition of empty |
| 06:56 | AWizzArd | got a 404, nginx |
| 06:56 | ambient | k |
| 06:56 | ambient | http://downforeveryoneorjustme.com/ is pretty useful site |
| 07:57 | ambient | anyone care to interpret this error message? java.lang.IllegalStateException: src already refers to: #'amb.synth.audioloop/src in namespace: amb.synth.audioloop (audioloop.clj:1) |
| 08:16 | ambient | if i have (def src foo) somewhere else and then try (let [src bar] ...) it gives an error? |
| 08:17 | AWizzArd | no |
| 08:18 | AWizzArd | You shadow the def'ed src with your let, but this throws no error. |
| 08:18 | ambient | if i have src defined in amb.synth.engine and try to (def src foo) in amb.synth.audioloop, which uses ...engine it gives an error? |
| 08:19 | ambient | what is weird that i don't have "src" anywhere in my code |
| 08:19 | AWizzArd | That could throw an error, because src is imported and you try to name something else like that. |
| 08:19 | ambient | it's some reserved variable? |
| 08:19 | AWizzArd | No |
| 08:20 | AWizzArd | do you know in which package src is? |
| 08:21 | ambient | hmm, (ns (:use)) doesn't seem to inherit the uses |
| 08:21 | ambient | amb.synth.audiochan > amb.synth.engine > amb.synth.audioloop => audioloop can't find audiochan |
| 08:22 | ambient | so perhaps all the error were caused by leftovers in the SLIME environment |
| 08:25 | ambient | yep |
| 08:29 | AWizzArd | you started a fresh jvm? |
| 08:29 | ambient | yes |
| 08:40 | adityo | hello |
| 08:40 | AWizzArd | Hi Adi |
| 08:42 | adityo | hey AwizzArd :) |
| 08:43 | adityo | im trying to traverse a directory tree , get something from each file |
| 08:43 | ambient | clojure really needs a native power function :/ |
| 08:43 | adityo | (for [file (file-seq (File. "dir"))]) |
| 08:44 | adityo | yet i get an error FileNotFoundException (is a directory) |
| 08:48 | spuz | Does anyone know what this error means? "java.lang.IllegalArgumentException: recur arg for primitive local: x must be matching primitive" |
| 08:52 | spuz | This seems to happen when I try to cast a local variable to a primitive type inside a 'loop' definition |
| 09:01 | chouser | spuz: you need to make sure that the matching arg in the 'recur' is also primitive |
| 09:04 | spuz | chouser: if I say (let x 2.0), is x not a primitive? |
| 09:04 | spuz | or (let [x 2.0]) even |
| 09:05 | chouser | spuz: right, literal numbers are boxed |
| 09:05 | chouser | so instead try (let [x (double 2.0)]) |
| 09:05 | spuz | chouser: ah ok |
| 09:07 | AWizzArd | adityo: did you try (.list (File. "/"))? |
| 09:08 | AWizzArd | btw, how do I get a sequence of all namespaces that are currently loaded? |
| 09:08 | chouser | AWizzArd: all-ns |
| 09:08 | AWizzArd | ah right |
| 09:08 | AWizzArd | ambient: why? |
| 09:10 | chouser | adityo: (for [f (file-seq (java.io.File. ".")) :when (.isFile f)] ...) |
| 09:35 | ambient | AWizzArd so i dont have to do (bit-shift-left 2 32) or (int (Math/pow 2 32)) all the time |
| 09:36 | ambient | (.start (Thread. foo-bar)) seems to block. how do i get a non-blocking thread? |
| 09:36 | ambient | from the REPL |
| 09:37 | chouser | that doesn't block the current thread |
| 09:38 | ambient | yes |
| 09:39 | ambient | my code currently looks like this: http://paste.pocoo.org/show/146866/ |
| 09:39 | ambient | the intention is to call (eng-start) from the REPL, then after (eng-stop) |
| 09:40 | ambient | waiit.. perhaps i need to give a fn to the Thread. |
| 09:40 | chouser | yes you do. |
| 09:40 | ambient | hah! :P |
| 09:40 | ambient | thanks |
| 09:40 | chouser | btw, don't use 'def' inside a 'defn' like that. |
| 09:41 | chouser | 'def' does not make a local |
| 09:41 | ambient | i know |
| 09:41 | ambient | but (def dl (atom (audiochan-open 44000))) does IO which I don't want to happen until (eng-start) |
| 09:42 | chouser | then do (def dl (atom nil)) at the top level, and (reset! dl (audio-chan-open 44000)) in the fn |
| 09:42 | ambient | ok |
| 09:48 | ambient | this is a bit embarassing how much functionality i can pack into so little amount of lines :/ |
| 09:52 | ambient | heh, i now have a fully functioning FM synthesizer from the REPL :p |
| 09:52 | ambient | now just to connect midi-input |
| 09:52 | rhickey | ambient: cool! |
| 09:52 | ambient | thanks :) |
| 09:56 | AWizzArd | ambient: can you play the piano in the repl? :) |
| 09:56 | ambient | not yet |
| 09:56 | rhickey | http://emusician.com/images/archive/backissues85-90.html EM March 1988 REVIEWS: Savant Audio Edit-8000 (mine) |
| 09:56 | ambient | i need to do envelope-generator that's triggered by the midi |
| 09:59 | AWizzArd | oh, 20 years og |
| 09:59 | AWizzArd | ago |
| 10:00 | rhickey | I should have said waaay back :) |
| 10:01 | chouser | I may have been transitioning from QuickBasic to Pascal around then |
| 10:02 | AWizzArd | progress :) |
| 10:03 | chouser | "Desk accessory to load patch files available free via BBS" |
| 10:03 | AWizzArd | does the new branch now have everything from master (and more, like defclass*)? |
| 10:07 | rhickey | http://www.atarimagazines.com/st-log/issue29/08-1_ST_NEWS_KORG_DSS-1_EDITING_SOFTWARE.php |
| 10:07 | AWizzArd | cute |
| 10:08 | rhickey | "but it does require one megabyte of RAM" :) |
| 10:08 | dreish | But, the Amiga had more colors and was therefore better! |
| 10:08 | ambient | atari had a midi-port built-in |
| 10:08 | ambient | :) |
| 10:09 | ambient | the times when normal computer magazines had articles like "how to program your C64 to read data from weather satellite" |
| 11:53 | lambdatronic | howdy folks. I've just run into something that just threw me a bit, and I'm looking for the rationale (or if this is a bug). |
| 11:54 | lambdatronic | I'm currently using Clojure 1.0.1-alpha-SNAPSHOT, and (= [] ()) and therefore (isa? [] ()) returns true. |
| 11:55 | lambdatronic | (isa? () []) also returns true. |
| 11:56 | lambdatronic | however, none of the other empty collection values are equivalent [i.e. (isa? () {}) (isa? () #{}) (isa? [] {}) (isa? [] #{}) (isa? {} #{}) (isa? {} []) (isa? {} ()) (isa? #{} ()) (isa? #{} []) (isa? #{} {})] |
| 11:56 | lambdatronic | So what gives? |
| 11:57 | rhickey | lambdatronic: isa? is not about instances, it's about types, so don't confuse with instance? or = |
| 11:57 | rhickey | when used with aggregates (i.e. vectors), it is about aggregates of types |
| 11:57 | lambdatronic | however, isa? performs = first before traversing type hierarchies. |
| 11:58 | rhickey | (isa? [String String] [Object Object]) |
| 11:58 | lambdatronic | and its (= () []) that's throwing this all off. |
| 11:58 | lambdatronic | the = fails on all the other sentinel values as well. |
| 11:59 | rhickey | (isa? {} []) is not meaningful |
| 11:59 | rhickey | they are not types not aggregates of types |
| 11:59 | rhickey | the only supported aggregate is a vector of types/tags |
| 12:00 | lambdatronic | When would I see this in use? (and this still doesn't get at the heart of my question, which is why does (= () []) return true?) |
| 12:01 | Chousuke | an empty list is structurally equivalent to an empty vector, I suppose. |
| 12:01 | rhickey | lambdatronic: that's a different question having nothing to do with isa? - = on collections divides collections into families - sequential, map, set - members of the same family with the same contents compare =, otherwise equality would have extreme type brittleness |
| 12:03 | rhickey | (and (sequential? []) (sequential? ())) -> true |
| 12:03 | lambdatronic | hmm...but {} and [] don't compare equal although the key/val mapping functions both work on them. |
| 12:04 | rhickey | right, there will always be overlap in behaviors of collections, sequential/map/set is just one way to separate them |
| 12:04 | rhickey | a vector is not a full map, even though it is somewhat associative |
| 12:05 | lambdatronic | alright, but = always follows this particular rule, so of the four underlying collection type, vectors and lists are lumped together while the others remain separate. |
| 12:06 | rhickey | the whole phrase 'underlying collection type' implies a lumping already, i.e. sorted and hashed sets, many flavors of maps |
| 12:08 | lambdatronic | right, I got that. But given the way the language documentation stands, those lumpings were already presented as being pretty intuitive. saying that lists and vectors are = if their contents are equal just crosses a boundary in my mind that comparing array-maps and struct-maps wasn't likely to. |
| 12:08 | lambdatronic | but now I know, I guess, and knowing is the half the battle. |
| 12:08 | lambdatronic | ;) |
| 12:08 | rhickey | equality deals with the collection taxonomy at a level where there are 3 lumps, and that matches the lumping that occurs in j.u.Collections as well |
| 12:09 | lambdatronic | ah, therein lieth the rationale. |
| 12:09 | lambdatronic | it's a javaism. |
| 12:11 | lambdatronic | I see now the other spooky things one can do with this => (= [1 2 3 4] (seq #{1 2 3 4})) |
| 12:11 | lambdatronic | or (= '([1 2] [3 4]) (seq {1 2 3 4})) |
| 12:12 | rhickey | lambdatronic: no, it is not a Javaism, it was there before they were aligned. I think there's more utility to sequential equality than separating the two |
| 12:13 | lambdatronic | yeah, I'm seeing that rich. hence my last two examples. |
| 12:13 | rhickey | the rationale is simply one of at what level is it most useful to use the abstractions, presuming one would never want exact type match included in collection equality |
| 12:13 | lambdatronic | that is the presumption, yes. |
| 12:14 | lambdatronic | it's the one that threw me. I was working through a haskell book and implementing all the exercises in their equivalent clojure, to compare and contrast the language features. |
| 12:14 | rhickey | it can be difficult to see the abstraction due to the overlaps, but a lot of the utility in Clojure comes from maximizing the use of the abstractions, i.e. extending to as many cases as makes sense and are efficient |
| 12:15 | lambdatronic | I was examining pattern matching, and I noted that a lot of pattern matching is just for destructuring binding (which was easy enough to map to clojure). |
| 12:15 | lambdatronic | sure enough, dynamicity is the name of the game, after all. |
| 12:16 | rhickey | I thought there were some docs on how collection equality worked, but can't find them now... |
| 12:16 | lambdatronic | it's when I was looking for a native way to map pattern matching for different argument values that I switched over to multimethods and hit the wall when trying to distinguish between an empty list and an empty vector. hence my question (and its original phrasing with isa?). |
| 12:16 | lambdatronic | nor can I... |
| 12:16 | rhickey | instance? is what you want there |
| 12:17 | rhickey | or the abstraction-blah? predicates |
| 12:17 | lambdatronic | you mean like vector?, map?, seq?, list?, set? |
| 12:18 | rhickey | yeah: |
| 12:18 | rhickey | user=> (seq? ()) |
| 12:18 | rhickey | true |
| 12:18 | rhickey | user=> (seq? []) |
| 12:18 | rhickey | false |
| 12:18 | lambdatronic | hmm...sneaky |
| 12:19 | lambdatronic | so let me ask again quickly about the aggregates of types you were discussing earlier. |
| 12:19 | lambdatronic | how would I use that with isa? |
| 12:20 | lambdatronic | is it something like the opportunity to match multiple values? |
| 12:20 | rhickey | exactly |
| 12:21 | lambdatronic | sorry, I didn't phrase that correctly...too ambiguous |
| 12:21 | lambdatronic | as in, is this a disjunctive or a conjunctive match? |
| 12:22 | rhickey | conjunctive |
| 12:23 | rhickey | since dispatch functions in multimethods can return only a single value, this lets you return a value (vector of types/tags) and have the built in isa? match all |
| 12:24 | lambdatronic | so my multimethod dispatch function has to return a sequence of values (which may be anything sequential), and my matching dispatch values will all use a vector to represent them? |
| 12:24 | lambdatronic | ok |
| 12:25 | rhickey | vectors only |
| 12:25 | lambdatronic | so why are vectors the only allowed matchable collections? |
| 12:25 | rhickey | fast count test |
| 12:25 | lambdatronic | hmm |
| 12:27 | rhickey | basically, they do the job and adding generatily wil lslow things down, no need here |
| 12:28 | lambdatronic | no worries, I've got a heuristic lexer/parser in my brain. ;) |
| 12:29 | lambdatronic | but I see that multimethods will match on maps, sets, etc. |
| 12:29 | lambdatronic | as in, I just tried it, and it worked. |
| 12:30 | lambdatronic | so remind me again where the vector-only restriction comes into play? I get the sense I'm missing something important here. |
| 12:30 | lambdatronic | or just being dense. |
| 12:31 | chouser | since you want to compare two collections with different values in them, you need them to be sequential to get sensible results, right? maps and sets don't make sense. |
| 12:32 | lambdatronic | chouser: please see 3 posts back. |
| 12:32 | chouser | but the position matters. |
| 12:32 | lambdatronic | (= {:a :b :c :d} {:c :d :a :b}) |
| 12:32 | lambdatronic | |
| 12:33 | lambdatronic | and of course, that works just fine, as expected. |
| 12:33 | lambdatronic | again, see the post I just made. |
| 12:33 | chouser | right, but often you want to check inheritence, not equality |
| 12:34 | lambdatronic | so when we're talking about the vector-only matching, we're strictly speaking about the inheritance checking post-equality testing? |
| 12:35 | chouser | well -- I'm saying non-sequential things don't even make sense because of that. The restriction to vectors only may be more involved. |
| 12:36 | rhickey | lambdatronic: the only collection supported for isa? is vector, and the only reason to pass a vector is that you have more than one type relationship you want to test in a single isa? call. isa? is not instance? |
| 12:36 | chouser | (derive ::A ::D) (derive ::B ::C) |
| 12:36 | chouser | (isa? [::A ::B] [::D ::C]) ;=> true as you'd expect |
| 12:37 | chouser | (isa? #{::A ::B} #{::D ::C}) ;=> false, because it doesn't really make sense |
| 12:38 | lambdatronic | okay, I see your point now. |
| 12:38 | lambdatronic | it's just helpful with the clojure derive functionality. |
| 12:39 | lambdatronic | or the java class hierarchy too, of course |
| 12:40 | rhickey | isa? is about types/tags - saying (isa? () []) doesn't ask the question, "isa list a vector?', it asks the (unsupported) question, "is each member of this list isa? the corresponding member of the vector?" - being empty means you are not testing anything really |
| 12:41 | chouser | addMethod could throw something if given an non-vector collection |
| 12:41 | rhickey | isa? isn't bound to multimethods |
| 12:42 | chouser | right, but defmethod isn't speed critical like isa? |
| 12:42 | lambdatronic | yep, got that, rich. thanks. it was never the deriving part of isa that I was confused about. as I said earlier, what I didn't understand was why the two were =. Since isa? performs = first and I was doing the comparison with multimethods in my code, I just associated the problem with isa? in my first post (though I meant =). |
| 12:43 | lambdatronic | but you cleared up your rationale for why (= [] ()) is true. so all is well in the world. |
| 12:43 | rhickey | chouser: but non vectors aren't wrong, if you want the equality test |
| 12:43 | lambdatronic | thanks again, guys. keep on hackin' in the free world. I'm out. |
| 12:45 | rhickey | i.e. you could dispatch on sets, vectors just get 'isa-enhanced' equality |
| 12:46 | chouser | ah, I see. I didn't realize isa? was explicitly checking for vectors before doing isa? on the items. |
| 12:47 | rhickey | that needs better docs I guess |
| 12:48 | rhickey | so it looks like we can do the vast majority of the rest of deftype and defclass on the macro side of things, expanding into defclass* thus far |
| 12:49 | rhickey | the one big sticking point is the unavailability of the class being defined, and the fact that all interop compilation uses reflection and thus needs a Class object... |
| 12:50 | rhickey | and you end up needing the class-being-compiled quite often to avoid reflective calls to: its ctor in copying ops, fields of other instances of the same type, instance? checks, arg hints of same type |
| 12:52 | chouser | gotta go buy carving pumpkins. bbl. |
| 13:22 | ambient | how can I stop a macro from adding the namespace to the variable? http://paste.pocoo.org/show/146907/ |
| 13:23 | ambient | i need evt and val just as they are, without any namespaces in front of them |
| 13:23 | spuz | Does the clojure compiler generate intermediate .java files before the .class files are generated? |
| 13:24 | robsynnott | Doubt it; doesn't it generally compile to JVM bytecode, not java? |
| 13:25 | spuz | I expect so |
| 13:26 | spuz | but perhaps there is some way to view the output of the compiler as generated java code...? |
| 13:26 | ankou_ | hi, what exaclty is the graphical inspector? |
| 13:26 | ankou_ | is there an article or something like that? can't find anything about this topic |
| 13:26 | spuz | I've tried decompiling the generated .class files but it really doesn't make sense as the code generated wouldn't appear to compile |
| 13:27 | ambient | clojure.contrib.swing-utils is a bit useless for me without a tutorial :( |
| 13:32 | notallama | ambient: ` adds namespace, ' doesn't. so you can unquote something and requote it like `(blah blah ~'x blah blah) |
| 13:33 | ambient | aha :) |
| 13:34 | chouser | spuz: Clojure compiles directly to bytecode that can in many cases not be represented correctly as .java |
| 13:34 | spuz | chouser: heh, thought as much :p |
| 13:35 | somnium | anyone tried using jad or similar on clojure's .class files? |
| 13:37 | chouser | ankou_: (require 'clojure.inspector) (clojure.inspector/inspect-tree {:a 1 :b {:c 2 :d 3}}) |
| 13:43 | spuz | somnium: I've tried JD-GUI: http://java.decompiler.free.fr/?q=jdgui |
| 13:43 | spuz | sometimes it gives useful results |
| 13:44 | spuz | in my case though it seems the body of the function I'm looking at does absolutely nothing! |
| 13:51 | AWizzArd | ~seen kotarak |
| 13:51 | AWizzArd | hiredman: bot gone? |
| 13:53 | chouser | rhickey: even if interop didn't use reflection, but instead examined .jar and .class files, that wouldn't help avoid reflective calls to defclass* classes. |
| 13:59 | chouser | right? so interop using reflection but sharing a classloader for a whole file might be closer to the right answer? |
| 14:22 | spuz | I'm still not really sure what the difference is between a closure and an anonymous function. Can someone explain what this example would do if Clojure did not support closures? http://lispwannabe.wordpress.com/2008/10/24/closures-in-clojure/ |
| 14:25 | rys | the closure closes over state |
| 14:25 | rys | The anonymous function is just that |
| 14:26 | rys | It's a function with no ident |
| 14:26 | chouser | spuz: without closures, 'x' would not be defined in (fn [y] (+ x y)) |
| 14:27 | spuz | chouser: so you would get an error saying "x not defined in this context"? |
| 14:27 | toups | Is there something like doseq but which executes in parallel? I have a body for which has side effects (writes to files) but not to any of the same files for a given element of the seq, so I should be able to parallelize it trivially. |
| 14:28 | Chousuke | use pmap with dorun |
| 14:28 | chouser | spuz: right |
| 14:29 | toups | (dorun (pmap (fn ...) sq))? |
| 14:30 | toups | Chousuke: like th at? |
| 14:30 | Chousuke | yeah |
| 14:30 | toups | Thanks |
| 14:30 | Chousuke | spuz: anonymous functions and closures are orthogonal concepts. a named function can form a closure too. |
| 14:31 | AWizzArd | spuz: you have a function F with a parameter vector P and a body B. In B a variable is accessed which is not in P, but also not a global var. |
| 14:31 | Chousuke | just do (let [foo bar] (defn ...)) |
| 14:31 | spuz | I've only ever seen closures using anonymous functions but that makes sense |
| 14:32 | AWizzArd | spuz: you can use Closures in non-anon functions as replacement for (Java) classes. |
| 14:32 | Chousuke | they're much more common as anonymous functions |
| 14:32 | AWizzArd | Imagine you have a Point object, with the members x and y. You want to create a new point, or update one. |
| 14:33 | AWizzArd | You could have a (let [x 0, y 0] (defn make-point ..) (defn distance ...)) and so on. |
| 14:33 | AWizzArd | Then make-point and distance adn your other functions would be like methods in a Java class, and x and y are like the fields of the class Point. |
| 14:37 | toups | wheee - clojure is pretty fun. |
| 15:03 | Qvintvs | does anyone know why I'm getting clojure.lang.PersistentArrayMap cannot be cast to java.lang.Number from this code (line 33): http://pastebin.org/48210 |
| 15:04 | The-Kenny | Qvintvs: Where in this code? |
| 15:04 | Qvintvs | line 33 |
| 15:08 | The-Kenny | Qvintvs: The problem is in add-to-map called by get-words. |
| 15:08 | The-Kenny | Qvintvs: Do you really want to emit "words" two times to add-to-map? |
| 15:11 | Qvintvs | The-Kenny, ah, thx |
| 15:13 | The-Kenny | Qvintvs: I think zou also switched the last two values... v should be a number and not an object. |
| 15:13 | The-Kenny | s/zou/you/ |
| 15:13 | Qvintvs | The-Kenny, ya, i noticed that too |
| 15:57 | hiredman | clojurebot: ping? |
| 15:57 | clojurebot | PONG! |
| 15:57 | somnium | ,(#(%) #(+ 2 3)) |
| 15:57 | clojurebot | 5 |
| 15:58 | somnium | hiredman: you turned off the I-Ching? |
| 15:58 | hiredman | (+ 1 4) |
| 15:58 | clojurebot | *suffusion of yellow* |
| 15:59 | somnium | oh good |
| 16:05 | somnium | ,(doc rfirst) |
| 16:05 | clojurebot | Excuse me? |
| 16:06 | somnium | some functions on the cheatsheet http://clojure.org/cheatsheet don't seem to be there |
| 16:08 | hiredman | the cheatsheat is kind of out of date |
| 16:08 | hiredman | ,(doc nfirst) |
| 16:08 | clojurebot | "([x]); Same as (next (first x))" |
| 16:09 | somnium | is that what rfirst did, or was it (rest (first x))? |
| 16:10 | licoresse | IMO, look at http://www.daimi.au.dk/~eernst/dPersp08/cheatsheet.pdf for what I think clojure.org needs |
| 16:11 | licoresse | there was a similar "terse guide to Smalltalk", but I cannot find it anylonger |
| 16:11 | somnium | yeah, that would be nice, python has some good ones too |
| 16:12 | somnium | makes it easy for anyone to get started |
| 16:13 | licoresse | ah, found it: http://74.125.77.132/search?q=cache:oaN12i4Gg0EJ:wiki.squeak.org/squeak/5699+terse+guide+to+squeak&hl=en&client=safari&strip=1 |
| 16:13 | licoresse | that one helped me a lot when I was beginning squeaking |
| 16:14 | hircus | man, Clojure maps are *fast* -- http://hircus.wordpress.com/2009/10/25/mini-kanren-benchmarking-different-substitution-data-structures/ |
| 16:15 | hircus | rhickey: any chance we could get IMapEntry's getter renamed to value() ? |
| 16:16 | somnium | licoresse: how did you learn to like the squeak gui? |
| 16:17 | licoresse | I didn't |
| 16:17 | licoresse | but when you have turtles all the way down |
| 16:17 | licoresse | you learn to like anything |
| 16:17 | licoresse | !! |
| 16:17 | licoresse | so I was in love for a couple of years |
| 16:17 | somnium | licoresse: too bad there's no emacs mode with buffers instead of windows |
| 16:18 | danlei | pharo looks a lot nicer than the vanilla squeak images imho |
| 16:18 | licoresse | somnium: you mean workspaces? |
| 16:18 | licoresse | the problem with squeak as many other similar things is that they have their own ecosystem |
| 16:19 | licoresse | and integrate poorly to the rest of the world |
| 16:20 | danlei | I'd love to have something like squeak/pharo for lisp. I ran medley in a VM (like genera, but for InterLisp), but it's quite aged ... |
| 16:21 | danlei | it still is a nice environment though |
| 16:21 | licoresse | well, I am happy to admit that Clojure is my new love now |
| 16:21 | somnium | I think if I had found smalltalk before I learned emacs I would have liked it, but when I tried it was already too unbearable to get started |
| 16:21 | licoresse | I only wish someone would do a proper debugger thing in emacs |
| 16:21 | danlei | somnium: I know what you mean :) |
| 16:22 | licoresse | somnium: it's not so much the language, which is fine, but more the environment |
| 16:23 | licoresse | the concepts of do-its, print-its etc |
| 16:23 | licoresse | and that brilliant debugger |
| 16:23 | danlei | for cl, the inspector and debugger are actually quite nice, don't get in your way |
| 16:23 | danlei | (slime) |
| 16:24 | licoresse | danlei: but none of that is avail to clojure, is it? |
| 16:24 | danlei | no, not that i'm aware of |
| 16:28 | somnium | 'show and 'source in repl-utils do most of what I want for insepcting, but I don't what the CL inspector does |
| 16:28 | notallama | pointfree stuff is coming along nicely. i should probably do my homework, though :V http://github.com/hclarke/pointfree-clojure |
| 16:29 | danlei | somnium: there are restarts, eval-in-frame, goto-source ... |
| 16:29 | hiredman | oooo |
| 16:29 | danlei | somnium: you can eval code in a stack frame an restart it, for example |
| 16:29 | danlei | *and |
| 16:30 | somnium | notallama: that looks nice, I was lamenting the lack of something like your &&& and *** just yesterday |
| 16:30 | djork | oh man I would kill for a Squeak-like debugger in Clojure |
| 16:31 | djork | actually I just want Clojure errors instead of Java errors |
| 16:31 | djork | stack traces tha tis |
| 16:31 | licoresse | djork: that would help |
| 16:32 | licoresse | or that the *slime-messages* buffer scrolls correctly |
| 16:32 | djork | heh yes that too |
| 16:32 | hiredman | have you tried out clojure.stacktrace? |
| 16:32 | somnium | my favorite is 'no message', java null pointer, no source |
| 16:32 | licoresse | guess that is an easy thing to "fix" |
| 16:33 | licoresse | hiredman: no, I have not |
| 16:33 | licoresse | anyone written about it, a blog or something? |
| 16:34 | hiredman | nope |
| 16:34 | hiredman | I only found it because my reader was barfing on it while I was using it to build clojure |
| 16:34 | djork | hah |
| 16:35 | licoresse | ooo |
| 16:35 | licoresse | http://img.skitch.com/20090721-efy2e4wgsrhxs2cxsbnu4c4ftx.png |
| 16:36 | somnium | isn't that what slime does? |
| 16:36 | licoresse | sans colors |
| 16:36 | somnium | true |
| 16:37 | robsynnott | ooh, pretty |
| 16:38 | djork | wow, nice |
| 16:38 | djork | slime doesn't look like that for me |
| 16:39 | djork | 1: user$eval__6140.invoke(NO_SOURCE_FILE:1) |
| 16:39 | djork | oh duh |
| 16:39 | djork | nevermind |
| 16:41 | danlei | http://danlei.nfshost.com/sldb.png |
| 16:41 | danlei | that would be nice to have in clojure too |
| 16:42 | somnium | wow |
| 16:42 | somnium | I hope something like that is in the works somehow or other |
| 16:42 | danlei | and that's just the top of the iceberg |
| 16:43 | danlei | well, |
| 16:43 | danlei | the problem is, that for example "restart" are a feature of the cl condition system |
| 16:43 | danlei | it's not a slime thing per se ... |
| 16:43 | Chousuke | the JVM just has exceptions :/ |
| 16:43 | licoresse | 'clojure.stacktrace is actually quite nice |
| 16:44 | licoresse | just need to connect it properly to the 'slime-compilation-finished-hook |
| 16:44 | danlei | in short: there are conditions, handlers, and restarts. somewhere, a condition gets signalled, then, if a handler handles it, a restart is invoked. the restart is usually down the stack, the handler up the stack ... |
| 16:45 | danlei | if no handler handles a condition, it will be handled by a human, in the debugger |
| 16:45 | Chousuke | I wonder what it would require for Clojure to emulate the condition system. |
| 16:45 | somnium | licoresse: could you paste the .emacs line you used? |
| 16:45 | Chousuke | there's error-kit but... hm. |
| 16:46 | licoresse | somnium: it's just a (add-hook 'clime-compilation-finished-hook 'whatever-you-like) |
| 16:46 | licoresse | slime (not clime) |
| 16:46 | somnium | licoresse: so just 'clojure.stacktrace there? |
| 16:46 | licoresse | no no |
| 16:46 | licoresse | you need to call swank |
| 16:47 | licoresse | or send something to the swank process or whatever |
| 16:47 | licoresse | I am not completely understanding this yet |
| 16:47 | somnium | licoresse: ah, I thougt you had it hooked up already |
| 16:47 | licoresse | :-( |
| 16:48 | Chousuke | or you can bug technomancy to add it to swank-clojure next time he joins :P |
| 16:48 | somnium | licoresse: I've been putting off reading swank-clojure.el |
| 16:48 | licoresse | anyway, I think that the above-mentioned hook is only called when the compilation is successful, I have to test it more |
| 16:49 | Chousuke | it shouldn't be too difficult to conditionally enhance the repl if contrib is available. |
| 16:49 | licoresse | I lost the link, there was someone mentioning clojure in emacs |
| 16:50 | licoresse | like, extending elisp with clojure stuff |
| 16:50 | licoresse | somnium: swank-clojure.el is a mess |
| 16:51 | licoresse | I guess that is what you get when everything is global |
| 16:51 | somnium | licoresse: I know, I looked at it once :) |
| 16:51 | Licenser | ow a lot is going on here |
| 16:52 | somnium | I think I like it best as a black box |
| 16:52 | licoresse | heh |
| 16:54 | licoresse | wait a minute, I don't mean the swank-clojure.el is a mess, it's just a mess to my eyes - I am sure it's brilliant in it's own way ;-) |
| 16:55 | licoresse | it's just 250 lines long |
| 16:55 | somnium | I'm sure it makes perfect sense once it makes sense to you |
| 16:57 | hiredman | http://www.thelastcitadel.com/images/syntax.png this is a mess |
| 16:57 | somnium | heh |
| 16:57 | licoresse | hehe |
| 16:58 | licoresse | is that object oriented?? :D |
| 16:58 | hiredman | I spent a large chunk of yesterday tracing that out |
| 16:58 | somnium | I like in once of rich's presentations he had one of those with "There Will Be A Quiz!" in big letters |
| 16:59 | hiredman | that is the syntaxQuote method from SyntaxQuoteReader in clojure.lang.LispReader |
| 16:59 | hiredman | that is all in one method |
| 16:59 | somnium | good god |
| 16:59 | licoresse | ouch |
| 16:59 | hiredman | once I made the graph it made sense, but before that :( |
| 17:01 | somnium | hiredman: it reminds me of the inside of a neglected server |
| 17:02 | licoresse | actually most of it makes sense, it's just that when you graph it... |
| 17:02 | somnium | http://www.michaelaulia.com/blogs/wp-content/uploads/2009/10/messy-cable-solution.png |
| 17:03 | licoresse | hmm |
| 17:08 | Chousuke | hiredman: I think the worst part of implementing syntax-quote is the symbol resolution :P |
| 17:10 | licoresse | hehe, reading about CIP (Clojure Idiomatic Police)... |
| 17:10 | hiredman | we have those? |
| 17:10 | Chousuke | http://github.com/Chousuke/clojure/blob/sq-macro/src/clj/clojure/core.clj#L562 I'm still not sure this is right. |
| 17:11 | Chousuke | also I wonder why there is no syntax-highlighting :/ |
| 17:12 | hiredman | the graph really helped me understand the flow |
| 17:14 | hiredman | I have five places where my reader still relies on LispReader: ReaderException, FnReader, ArgReader, EvalReader, and readDelimitedList |
| 17:14 | Chousuke | ! |
| 17:14 | Chousuke | I might just have figured out the bug I have compiling Clojure with my reader. |
| 17:15 | Chousuke | epiphany out of nowhere |
| 17:15 | hiredman | huzzah! |
| 17:15 | licoresse | how wonderful! |
| 17:15 | Chousuke | now I hope I'm right. |
| 17:17 | notallama | is there a way to not have to type the classname for java static functions? like (sin x) instead of (Math/sin x) ? or do i just have to def the ones i want to something shorter? |
| 17:17 | Chousuke | contrib has static-import I think. maybe that would help? |
| 17:21 | somnium | does (into {} ...) always create an ArrayMap regardless of number of args? |
| 17:21 | Chousuke | ,(class (into {} [1 2])) |
| 17:21 | clojurebot | java.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer |
| 17:22 | Chousuke | ... ? |
| 17:22 | Chousuke | ah |
| 17:22 | Chousuke | ,(class (into {} [[1 2]])) |
| 17:22 | clojurebot | clojure.lang.PersistentArrayMap |
| 17:23 | Chousuke | hmm. |
| 17:23 | Chousuke | ,(class (into {} (take 15 (repeatedly [1 2]))) |
| 17:23 | clojurebot | EOF while reading |
| 17:23 | Chousuke | ,(class (into {} (take 15 (repeatedly [1 2])))) |
| 17:23 | clojurebot | java.lang.RuntimeException: java.lang.RuntimeException: java.lang.IllegalArgumentException: Wrong number of args passed to: PersistentVector |
| 17:23 | notallama | Chousuke: yes, that is exactly what i needed. thanks! (it's called import-static) |
| 17:23 | Chousuke | ,(class (into {} (take 15 (repeat [1 2])))) |
| 17:23 | clojurebot | clojure.lang.PersistentArrayMap |
| 17:23 | somnium | ,(class (into {} (interleave (range 100) (range 100)))) |
| 17:23 | clojurebot | java.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer |
| 17:23 | Chousuke | ,(class (into {} (take 50 (repeat [1 2])))) |
| 17:23 | clojurebot | clojure.lang.PersistentArrayMap |
| 17:24 | Chousuke | apparently :/ |
| 17:24 | somnium | hmm |
| 17:24 | Chousuke | ,(class (into {} (take 5000 (repeat [1 2])))) |
| 17:24 | clojurebot | clojure.lang.PersistentArrayMap |
| 17:24 | Chousuke | ... |
| 17:24 | somnium | well, on the bright side, that means I have some very easy optimizations to implement :) |
| 17:24 | Chousuke | sorry, I'm stupid :D |
| 17:24 | Chousuke | all those maps had only one element. |
| 17:24 | hiredman | haha |
| 17:24 | Chousuke | should go to sleep. |
| 17:25 | somnium | ,(class (into {} (partition 2 (interleave (range 100) (range 100))))) |
| 17:25 | clojurebot | java.lang.ClassCastException: java.lang.Integer cannot be cast to java.util.Map$Entry |
| 17:25 | hiredman | ,(class (into {} (map vector (range 100) (range 100)))) |
| 17:25 | clojurebot | clojure.lang.PersistentHashMap |
| 17:25 | somnium | ah |
| 17:25 | somnium | well, that solves that |
| 17:32 | somnium | (conj {} [1 2]) |
| 17:32 | somnium | ,(conj {} [1 2]) |
| 17:32 | clojurebot | {1 2} |
| 17:32 | div | hiredman: you should consider spending an hour or 2 playing with graphviz nxt time you need to graph something like http://www.thelastcitadel.com/images/syntax.png |
| 17:32 | somnium | ,(conj {} '(1 2)) |
| 17:32 | clojurebot | java.lang.ClassCastException: java.lang.Integer cannot be cast to java.util.Map$Entry |
| 17:33 | hiredman | div: that is graphviz |
| 17:33 | div | what's with the scary lines :) |
| 17:34 | div | the boxes are familiar yes, but it just seems like you drew the connections with paint :p |
| 17:34 | hiredman | the dark arrows are control flow and the thin lines are, uh?, state flow? |
| 17:34 | hiredman | nah, it's all dot |
| 17:35 | div | i see |
| 17:36 | somnium | hmm, I guess (into {} '(:foo :bar)) isn't supported for performance reasons? |
| 17:37 | hiredman | eh? |
| 17:37 | hiredman | where are the keys and values? |
| 17:38 | somnium | it seems to be because lists don't implement IEditableCollection |
| 17:38 | somnium | but [:foo :bar] does |
| 17:38 | somnium | so that was the basis for my guess |
| 17:39 | hiredman | no |
| 17:40 | somnium | er, scratch that, re-reading into |
| 17:40 | hiredman | (into {} [:foo :bar]) and (into {} '(:foo :bar)) both won't work |
| 17:40 | somnium | I know |
| 17:40 | hiredman | (into {} '([:foo :bar])) does work |
| 17:41 | somnium | hmm |
| 17:41 | hiredman | (conj {} :foo :bar) doesn't work |
| 17:41 | hiredman | (conj {} [:foo :bar]) does |
| 17:46 | AWizzArd | though i find (assoc {} :foo :bar) documents the code better |
| 17:47 | hiredman | sure |
| 17:47 | hiredman | I'm not advocating conj over assoc for associative things, I am just trying to illustrate why '(:foo :bar) does not work and '([:foo :bar]) does in into |
| 17:48 | AWizzArd | yes |
| 17:51 | Licenser | somnium: how is the mongodb driver going? |
| 17:51 | somnium | Licenser: a pre-alpha version is on github, its working but test coverage is poor |
| 17:52 | Licenser | wooh |
| 17:52 | somnium | Licenser: would be happy if you give it a try and let me know how it goes |
| 17:52 | somnium | been writing tests this afternoon |
| 17:52 | Licenser | somnium: I'm planing on it ;) |
| 17:53 | Licenser | somnium: how is it named? |
| 17:54 | hiredman | clojurebot: how is it named? |
| 17:54 | clojurebot | with style and grace |
| 17:55 | Licenser | ah found it |
| 17:56 | somnium | I considered mongojure and clomongo but they didn't appeal |
| 17:56 | Licenser | hah I tried mongojure :P |
| 17:57 | somnium | maybe 'clongo wouldn't be so bad |
| 17:58 | piccolino | somnium, so cool. I was just a week ago wishing there was a MongoDB driver for clojure taht worked like this. |
| 17:59 | somnium | piccolino: pre-alpha! :) please, let me know what breaks, I've a lot of improvements in mind, and it wasn't test-driven, more like repl-hacked |
| 18:00 | somnium | hiredman: sorry I'm being slow about this, how does the line in the source of conj ([coll x] (. clojure.lang.RT (conj coll x)) work ? |
| 18:02 | Licenser | somnium: I'm excited over your driver :P |
| 18:02 | hiredman | it's a call to the conj static method on RT |
| 18:03 | hiredman | anway, conj on maps takes a key-value pair |
| 18:03 | hiredman | '([:key :value]) is a sequence containg a key-value pair |
| 18:04 | hiredman | '(:foo :bar) is not |
| 18:04 | somnium | hiredman: ok, been putting off reading the .java portion of clojure, thanks |
| 18:05 | hiredman | somnium: you don't need to |
| 18:06 | hiredman | the point is '(:foo :bar :baz :bleep) is a flat sequence, '([:foo :bar] [:baz :bleep]) is a sequence of two element vectors |
| 18:07 | somnium | hiredman: right, but (list (list 1 2) (list 2 3)) also doesn't work, which is a sequence of two element sequences, or no? |
| 18:07 | hiredman | the first will not work because a. into uses conj (or did last time I checked) and b. it contains no key/value groupings |
| 18:07 | somnium | so I assume it has to do with how conj works |
| 18:07 | hiredman | that is because conj for maps takes a map entry, and two element vectors are map entries |
| 18:08 | hiredman | ,(class (first {:a :b})) |
| 18:08 | clojurebot | clojure.lang.MapEntry |
| 18:08 | hiredman | ,(first {:a :b}) |
| 18:08 | clojurebot | [:a :b] |
| 18:10 | somnium | hiredman: ah, now it clicked, I wasn't thinking about the definition of map entries |
| 18:24 | hiredman | interesting trivia, (eval (eval (quote (list + 1 2 3)))) calls the reader to read (X.) where X is the name of the class the + fn is compiled to |
| 18:24 | LauJensen | ~seen jdz |
| 18:24 | clojurebot | no, I have not seen jdz |
| 18:30 | Licenser | somnium: from the docs your API looks very neat |
| 18:32 | somnium | Licenser: it can still be improved, I'd like to completely suppress the class hierarchy defined by the java-api, but that will negatively impact performance for mass operations |
| 18:33 | Licenser | hmmm |
| 18:34 | somnium | Licenser: hopefully I'll get the core test suite finished this evening |
| 18:34 | Licenser | I have a request so :P fetch-one-with-defaults that would be very sweet |
| 18:34 | Licenser | s |
| 18:34 | Licenser | i |
| 18:34 | Licenser | since in the KV store you never can know what you get |
| 18:34 | somnium | Licenser: how would that work? |
| 18:34 | Licenser | well like: |
| 18:35 | Licenser | (fetch-one-with-defaults :robots :where {:name 'rodney'} :defaults {:type 'killer robot with laser eyes'}) |
| 18:36 | Licenser | so it either returns {:name 'rodney' :type 'a cute little robot kitten'} or if rodney had no type {:name 'rodney' :type 'killer robot with laser eyes'} |
| 18:36 | hiredman | watch the single quotes |
| 18:36 | somnium | ah |
| 18:36 | Licenser | since I don't think mongodb allows field defaults as it has no scemes |
| 18:36 | Licenser | hiredman: thanks |
| 18:37 | piccolino | Does it work with hierarchical objects? |
| 18:37 | Licenser | piccolino: it does not work at all :P it's a dream of mien |
| 18:37 | piccolino | Sorry, I was asking somnium about the main functionality. :) |
| 18:38 | piccolino | I see that map-to-object just calls the mongo-java function, not sure how that one works yet. |
| 18:38 | somnium | piccolino: the core api is all json, so anything you can write in json you should be aple to express with a POCM (plain old clojure map) |
| 18:39 | somnium | or BSON I guess, but whatever, the structure is just like JSON |
| 18:39 | piccolino | So if I put a clojure map in a clojure map, the Java API will correctly structure that? |
| 18:39 | AWizzArd | yes |
| 18:39 | piccolino | Cool. |
| 18:40 | AWizzArd | you can also use the json parser in Clojure Contrib. |
| 18:42 | somnium | piccolino: they mongodb-java-driver also has a JSON/parse method that creates mongo objects, will probably wrap that in the next release |
| 18:43 | somnium | piccolino: but for the most part my goal was to create an illusion that youre using a DB that just knows how to speak clojure |
| 18:43 | piccolino | Totally, that's how it should be. |
| 18:47 | piccolino | I just guess the Java MongoDB driver had more reflection than I realized. |
| 18:48 | ankou_ | hi, is there a simple search function like (first (filter x y)) but more efficient? |
| 18:49 | somnium | piccolino: far off in the future there could be a low level driver that does BSON to clojure, in the near future I want something easy and not broken to use for my own projects :) |
| 18:49 | piccolino | What would be the advantage of that? |
| 18:49 | somnium | piccolino: speed most likely |
| 18:50 | somnium | ankou_: try (some x y) |
| 18:50 | hiredman | some returns the result of the predicate |
| 18:51 | ankou_ | which is true and not the element itself |
| 18:52 | hiredman | ankou_: what is the problem with (first (filter ...)) |
| 18:53 | ankou_ | well I thought that even if it uses a lazy sequence it might be slower then a real (convenient) find function or am I wrong? |
| 18:54 | somnium | ,(some #(if (string? %) % nil) '(:foo :bar "yes" :wow)) |
| 18:54 | clojurebot | "yes" |
| 18:54 | somnium | though I don't suppose that's better than (first (filter ...)) |
| 18:56 | hiredman | ankou_: unless the input is sorted you are going to have to do a linear search, which is exactly what (comp first filter) does |
| 18:58 | somnium | ,(time (first (filter #(= 2000 %) (iterate inc 1)))) |
| 18:58 | clojurebot | 2000 |
| 18:58 | clojurebot | "Elapsed time: 13.013 msecs" |
| 18:59 | somnium | ,(time (some #(if-let [x (= 2000 %)] x) (iterate inc 1))) |
| 18:59 | clojurebot | true |
| 18:59 | clojurebot | "Elapsed time: 9.003 msecs" |
| 18:59 | somnium | bah |
| 19:00 | somnium | ,(time (some #(if (= 2000 %) %) (iterate inc 1))) |
| 19:00 | hiredman | ,(time (some #{2000} (iterate inc 1))) |
| 19:00 | clojurebot | 2000 |
| 19:00 | clojurebot | "Elapsed time: 11.467 msecs" |
| 19:00 | somnium | nice, I don't use sets nearly often enough |
| 19:02 | somnium | ,(time (first (filter #(= 100000 %) (iterate inc 1)))) |
| 19:02 | clojurebot | 100000 |
| 19:02 | clojurebot | "Elapsed time: 383.559 msecs" |
| 19:02 | somnium | ,(time (some #(if (= 100000 %) %) (iterate inc 1))) |
| 19:02 | clojurebot | 100000 |
| 19:03 | clojurebot | "Elapsed time: 168.427 msecs" |
| 19:04 | somnium | (time ((comp first filter) #(= 100000 %) (iterate inc 1))) |
| 19:04 | somnium | ,(time ((comp first filter) #(if (= 100000 %) %) (iterate inc 1))) |
| 19:04 | clojurebot | 100000 |
| 19:04 | clojurebot | "Elapsed time: 218.176 msecs" |
| 19:05 | somnium | hiredman: internally, how different are (first (filter ...)) (comp first filter) ... and (some ...) ? |
| 19:05 | somnium | or at all? |
| 19:06 | hiredman | (comp first filter) creates a new function |
| 19:07 | hiredman | (first (filter ...)) doesn't |
| 19:07 | hiredman | which means there is an extra function invocation too |
| 19:08 | somnium | hmm, some and filter are very different |
| 19:09 | hiredman | ~def some |
| 19:09 | somnium | why is filter so complicated? |
| 19:09 | ataggart | some is the complement of any |
| 19:09 | ataggart | erm |
| 19:09 | hiredman | some is not lazy |
| 19:09 | hiredman | filter is |
| 19:10 | ataggart | every? not any, sry |
| 19:10 | somnium | of course, and filter returns a whole collection, duh |
| 19:11 | somnium | 'some' maybe isn't the best name for what it actually does, 'first-truthy' ? |
| 19:11 | hiredman | true for some elements |
| 19:11 | hiredman | some |
| 19:11 | ataggart | I like "any?" |
| 19:12 | somnium | hiredman: is there any way you could wire up clojurebot to 'source in repl-utils? |
| 19:12 | somnium | -> (defn some [pred coll] (when (seq coll) (or (pred (first coll)) (recur pred (next coll))))) |
| 19:13 | hiredman | ,(use 'clojure.contrib.repl-utils) |
| 19:13 | clojurebot | java.lang.ExceptionInInitializerError |
| 19:13 | hiredman | clojurebot: same to you! |
| 19:13 | clojurebot | It's greek to me. |
| 19:14 | danlei | ,(require '[clojure.contrib.repl-utils :as ru]) |
| 19:14 | clojurebot | java.lang.NoClassDefFoundError: Could not initialize class clojure.contrib.repl_utils__init |
| 19:15 | danlei | didn't that use to work? |
| 19:21 | hiredman | ,(use 'clojure.contrib.repl-utils) |
| 19:21 | clojurebot | nil |
| 19:21 | hiredman | ,(source 'some) |
| 19:21 | clojurebot | java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol |
| 19:21 | hiredman | ,(source some) |
| 19:21 | clojurebot | Source not found |
| 19:21 | hiredman | :P |
| 19:21 | somnium | hiredman: is there anyway you could put the .clj files on his classpath without compromising his sandbox? |
| 19:49 | merijn | Do I understand it right that multi-methods are pretty much the same as pattern matching in Haskell, but with an explicit syntax to mark it? |
| 19:51 | notallama | they can be. i think it's closer to guards. |
| 19:52 | somnium | -> ((f x y z) x y z) |
| 19:53 | somnium | how does haskell's pattern matching work? |
| 19:56 | merijn | somnium: To use a trivial example (sum over a list, where [] is an empty list): "sum [] = 0; sum (x:xs) = x + sum xs" (or alternatively "sum [] = 0; sum list = head list + tail list") |
| 19:56 | merijn | err.. sum (tail list) in the latter example, of course |
| 19:57 | notallama | it's basically a destructuring bind, and you can put literals in it to match against. |
| 19:58 | somnium | x:xs = [x & xs] ? |
| 19:59 | hiredman | sort of |
| 20:00 | notallama | somnium: [[x & xs]], i think |
| 20:00 | merijn | somnium: ":" is list concatenation, so (x:xs) is a list with the first element bound as x and the tail bound as xs |
| 20:00 | hiredman | some wrote a pattern matching macro |
| 20:00 | hiredman | someone |
| 20:00 | hiredman | ~matches |
| 20:00 | clojurebot | excusez-moi |
| 20:01 | hiredman | ~google clojure pattern matching |
| 20:01 | clojurebot | First, out of 1630 results is: |
| 20:01 | clojurebot | brool » Pattern Matching In Clojure |
| 20:01 | clojurebot | http://www.brool.com/index.php/pattern-matching-in-clojure |
| 20:01 | somnium | hiredman: ooh, I was thinking about writing one yesterday |
| 20:02 | merijn | hiredman: Well, the point wasn't so much how to do pattern matching but if I could compare multi-methods to pattern matching in Haskell. |
| 20:03 | somnium | (doc match) |
| 20:03 | clojurebot | "clojure.contrib.types/match;[[value & clauses]]; Given a value and a list of template-expr clauses, evaluate the first expr whose template matches the value. There are four kinds of templates: 1) Lists of the form (tag x1 x2 ...) match instances of types whose constructor has the same form as the list. 2) Quoted lists of the form '(x1 x2 ...) match lists of the same length. 3) Vectors of the form [x1 x2 ...] match vector |
| 20:03 | notallama | merijn: multi-methods are more general. they dispatch on any function of the arguments you can think of. |
| 20:04 | somnium | are there any code examples for contrib.macros/macro-utils ? in the wild or elsewhere ? |
| 20:04 | hiredman | nice |
| 20:04 | hiredman | matching on constructor forms is great |
| 20:04 | notallama | so, it could choose a method by type, or by value, or by length of a string, or whatever. |
| 20:05 | somnium | I really wish there was a cheatsheet for contrib, I keep finding stuff I didn't know was thre |
| 20:05 | merijn | notallama: ok |
| 20:19 | Licenser | wow the mongodb community is quite fun |
| 20:22 | somnium | Licenser: ? |
| 20:23 | Licenser | somnium: yap, I just asked a question and ran into a bug, they are very helpfull in the channel :P |
| 21:20 | tomoj | technomancy: do you happen to know who maintains elpa gist.el? |
| 23:12 | technomancy | tomoj: no, sorry |
| 23:21 | lisppaste8 | djork pasted "why does this throw a NPE?" at http://paste.lisp.org/display/89274 |
| 23:22 | djork | If anybody can explain this mysterious error to me, I'd appreciate it. |
| 23:22 | hiredman | ,(first '()) |
| 23:22 | clojurebot | nil |
| 23:22 | djork | ah |
| 23:22 | djork | ,(dec nil) |
| 23:22 | hiredman | ,(dec (first '())) |
| 23:22 | clojurebot | java.lang.NullPointerException |
| 23:22 | clojurebot | java.lang.NullPointerException |
| 23:22 | djork | :) |
| 23:23 | djork | thanks |
| 23:23 | djork | by the way, iterate is a brilliant thing |
| 23:24 | djork | I love the fact that I can just do (nth (iterate next-day [5]) 1234) |
| 23:24 | djork | brilliant stuff |
| 23:24 | djork | of course my algo. here is not going to work (stack overflow) |
| 23:26 | djork | what's the best way to put conj and recur together so that I have a tail-recursion going on? |
| 23:58 | chouser | djork: walking a lazy seq shouldn't overflow the stack |