2011-03-13
| 01:18 | waxrose | >.> |
| 01:19 | scottj | I'm not very good at reading ascii art |
| 01:21 | waxrose | why's that? |
| 01:23 | scottj | lack of imagination I suppose |
| 01:24 | waxrose | What are you up to tonight? |
| 01:25 | scottj | was reading programming pearls first chapter (reduce (fn [bitmap n] (aset bitmap (dec n) 1) bitmap) (int-array 27000 0) file) then I got distracted by grooveshark |
| 01:26 | waxrose | I've never had a chance to read that one. |
| 01:26 | waxrose | Between class and doing every thing else. |
| 01:30 | scottj | reading's overrated |
| 01:32 | waxrose | how so? |
| 01:33 | waxrose | I find reading the only way to progress outside of pure experience. |
| 01:34 | scottj | I find reading uninspired by experience produces poor comprehension and short retention |
| 01:35 | scottj | I'm skeptical of the value of reading not motivated by problem solving |
| 01:39 | waxrose | mmhmm |
| 01:40 | waxrose | But then again, not every one reacts to stimulus the same way. |
| 03:44 | hiredman | ~search for rhickey |
| 08:42 | pyr | hi |
| 09:02 | nawk | gud morning |
| 09:24 | raek | CompilerException java.lang.NoSuchMethodError: clojure.lang.RestFn.<init>(I)V (autodoc.clj:1) |
| 09:24 | raek | grrr |
| 13:08 | zoldar | ,(do (defn pad [coll n x] (let [cnt (- n (count coll))] (if (pos? cnt) (concat coll (take cnt (repeat x))) coll))) (pad [1 2 3] 5 nil)) |
| 13:08 | clojurebot | DENIED |
| 13:08 | zoldar | hmm, anyway, isn't such function already somewhere in core or contrib ? |
| 13:10 | david` | https://gist.github.com/868264 |
| 13:10 | david` | :( |
| 13:12 | nickik | ,((fn [coll n x] (let [cnt (- n (count coll))] (if (pos? cnt) (concat coll (take cnt (repeat x))) coll))) [1 2 3] 5 nil) |
| 13:12 | clojurebot | (1 2 3 nil nil) |
| 13:13 | MayDaniel | ,((fn [coll n x] (take n (concat coll (repeat x)))) [1 2 3] 5 nil) |
| 13:13 | clojurebot | (1 2 3 nil nil) |
| 13:13 | zoldar | ah, nice |
| 13:14 | zoldar | david`, your (ns ..) form seems wrong to me. "use" instead of ":require" would probably work here |
| 13:15 | nickik | i edit de function in the irc. very lucky that i got all the parans right the first time. |
| 13:16 | david` | zoldar: thx! |
| 13:16 | TimMc | zoldar: ##(take 5 (concat [1 2 3] (repeat nil))) |
| 13:16 | sexpbot | ⟹ (1 2 3 nil nil) |
| 13:18 | raek | david`: note that since 1.2 there is also clojure.string: (ns foo (:require [clojure.string :as str])) (str/replace ...) |
| 13:18 | zoldar | that just shows how my clojure-fu still sucks... |
| 13:19 | raek | though, some of the functions did not "make it" there |
| 13:19 | raek | or was renamed, so you'd have to read through the docs to see what's changed |
| 13:19 | raek | http://clojuredocs.org/clojure_core/clojure.string |
| 13:29 | joodie | ... |
| 14:00 | avdi | I'm learning about metadata righ now, but "^" doesn't seem to be working. Has this changed? |
| 14:01 | joodie | Should work. Which version of clojure are you using? |
| 14:02 | spewn | &(let [x ^{:a 1 :b 2} [1 2 3]] (meta x)) |
| 14:02 | sexpbot | ⟹ nil |
| 14:02 | avdi | 1.2 |
| 14:02 | avdi | hmmm |
| 14:02 | spewn | Strange. That works for me with 1.2.0. What's wrong with sexpbot? |
| 14:03 | avdi | The Halloway book shows ^foo returning metadata for ^foo |
| 14:03 | joodie | works for me too @ 1.2 |
| 14:04 | raek | avdi: this has indeed changed. since clojure 1.2, you have to use (meta ...) to extract the metadata |
| 14:05 | avdi | raek: gotcha, that explains it. |
| 14:05 | avdi | raek: thanks |
| 14:05 | raek | avdi: and ^ is the new reader syntax for adding metadta (#^ still works, though, but should be avoided for future compability) |
| 14:05 | joodie | and since 1.2 you can use ^{ ... } to set metadata |
| 14:06 | joodie | If you want the details of these sort of short-hands, look at the reader docs: http://clojure.org/reader |
| 14:06 | raek | also, with-meta is the function you'd use in you program (^ only adds metadata to the *code literal*) |
| 14:07 | avdi | raek: I'm going to have to think about that last statement for a bit |
| 14:10 | raek | if the evaluator sees a collection literal with metadata on it, it will evaluate the contents and make a new data structure of the same kind. the metadata map will also be evaluated. then, the evaled metadata will be attached to the new data structure |
| 14:10 | raek | ,(let [x 1] (meta ^{:foo x} [1 x 3])) |
| 14:10 | clojurebot | {:foo 1} |
| 14:11 | raek | but |
| 14:11 | raek | ,(let [x 1] (meta ^{:foo x} (list 1 x 3))) |
| 14:11 | clojurebot | nil |
| 14:12 | raek | (list ...) is not a data literal, so the metadata on the code won't be attached to the result |
| 14:12 | raek | ,(let [x 1] (meta (with-meta (list 1 x 3) {:foo x}))) |
| 14:12 | clojurebot | {:foo 1} |
| 14:13 | raek | ,(let [x 1] (meta (with-meta [1 x 3] {:foo x}))) |
| 14:13 | clojurebot | {:foo 1} |
| 14:14 | avdi | In the first (list) example, what exactly is the metadata attached to? |
| 14:14 | avdi | the list form? |
| 14:15 | joodie | could be |
| 14:15 | raek | it's attached to the list whose elements are the symbol "list", the number 1, the symbol "x" adn the number 2 |
| 14:15 | raek | *3 |
| 14:15 | avdi | raek: gotcha. Makes sense. |
| 14:16 | raek | that is, the thing that is sent to the compiler |
| 14:17 | raek | so, symbols and list have special behaviour for metadata, just as they have special behaviour for evaluation in general |
| 15:42 | angerman | how do i get c.c.string/join to not return LazySeq@… ? |
| 15:43 | angerman | I hoped, doall would do… but doesn. |
| 15:43 | fliebel | angerman: apply str? |
| 15:44 | angerman | fliebel: ? |
| 15:44 | amalloy | angerman: ##(str (range)) |
| 15:45 | sexpbot | Execution Timed Out! |
| 15:45 | amalloy | angerman: ##(str (range 2)) |
| 15:45 | sexpbot | ⟹ "clojure.lang.LazySeq@3c2" |
| 15:45 | fliebel | &(apply str (reng 5)) |
| 15:45 | sexpbot | java.lang.Exception: Unable to resolve symbol: reng in this context |
| 15:45 | amalloy | &(apply str (range 2)) |
| 15:45 | sexpbot | ⟹ "01" |
| 15:45 | fliebel | &(apply str (range 5)) |
| 15:45 | sexpbot | ⟹ "01234" |
| 15:45 | fliebel | right, finally |
| 15:45 | amalloy | string/join is the same, iirc - it wants multiple params, not a single coll |
| 15:46 | amalloy | so if you have a coll you should be able to apply it |
| 15:46 | raek | angerman: you can use pr-str to turn clojure data structures into strings |
| 15:46 | raek | *a string |
| 15:46 | amalloy | ,(pr-str (promise)) |
| 15:46 | clojurebot | Execution Timed Out |
| 15:46 | amalloy | raek: not entirely true :P ^ |
| 15:47 | fliebel | &(pr-str [1 2 3]) |
| 15:47 | sexpbot | ⟹ "[1 2 3]" |
| 15:47 | raek | I don't know if I would call a promise a data structure |
| 15:48 | raek | ,((juxt str pr-str) (range 5)) |
| 15:48 | clojurebot | ["clojure.lang.LazySeq@1b554e1" "(0 1 2 3 4)"] |
| 15:48 | angerman | what for is clojure.string/join? |
| 15:48 | angerman | so I tried to write code according to clojure.string/join whil eusing c.c.string/join. ouch. |
| 15:49 | raek | clojure.string/join takes a seq of strings as its input (if the elements are not strings they will probably be converted with 'str') |
| 15:50 | raek | so if you want to turn the elements into strings in some other way (e.g. pr-str) you should (map pr-str ...) them first |
| 15:50 | angerman | no. I actually wanted to use "join" because I wanted the seperator. |
| 15:51 | raek | yes, but the stuff you want to join with the separator must be a seq of strings |
| 15:52 | angerman | reak, yes, that's what I get from (format…) |
| 15:52 | amalloy | &(use '[clojure.string :only [join]]) |
| 15:52 | sexpbot | ⟹ nil |
| 15:52 | amalloy | &(join "," (range 5)) |
| 15:52 | sexpbot | ⟹ "0,1,2,3,4" |
| 15:52 | angerman | the problem was that i tried (join coll sep) instead of (join sep coll) |
| 15:52 | raek | format will also call str on its arguments |
| 15:52 | raek | ah |
| 15:53 | angerman | &(doc clojure.string/join) |
| 15:53 | sexpbot | ⟹ "([coll] [separator [x & more]]); Returns a string of all elements in coll, separated by an optional separator. Like Perl's join." |
| 15:53 | angerman | &(doc clojure.contrib.string/join) |
| 15:53 | sexpbot | ⟹ "([separator coll]); Returns a string of all elements in coll, separated by separator. Like Perl's join." |
| 15:53 | angerman | that is plain weird! |
| 15:53 | amalloy | angerman: you're just misreading the arglists |
| 15:53 | amalloy | both of them take sep coll |
| 15:54 | angerman | amalloy: ahh, multi arity |
| 15:54 | angerman | dang. |
| 15:54 | amalloy | indeed |
| 16:39 | User | hey |
| 16:39 | jaley | hi guys - can anyone offer me some best-practice advice wrt wrapping up java APIs and mocking? |
| 16:39 | User | anyone familiar with Enlive? |
| 16:41 | jaley | I'm using java api generated by apache axis to talk to some servers with soap. I think for test purposes I'd like to mock out the real function calls with c.c.mock, but clearly I can't use binding to mock out a java method call. Is this an acceptable time to break idioms and wrap the java API with clojure function calls? Or would another approach altogether be better maybe? |
| 16:43 | User | what does the soap client look like |
| 16:43 | User | I generally extend the soap client with a class of my own |
| 16:44 | jaley | @User ; (.getEvents *service*) |
| 16:44 | jaley | where service is a java object, code generated by axis |
| 16:47 | anthony | I'm working with a datastore, which has an int field representing an enum. In Clojure, I need to translate these ints to/from keywords (with hard-coded associations). What's the cleanest way to do this? I've had a map like asc = {0 :start 1 :inprogress 2 :end}, which allows me to do (asc 1) to get a value from a key, but how about the other way around (given a value, find the key)? |
| 16:48 | User | make a java class with public static final variables then refer to it as class/CONSTANT |
| 16:48 | User | *trollface* |
| 16:49 | amalloy | &(clojure.walk/walk reverse hash-map {0 :start 1 :inprogress 2 :end}) |
| 16:49 | sexpbot | java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.util.Map$Entry |
| 16:49 | amalloy | booo |
| 16:49 | raek | I would use two maps. maybe initialize them from the same data |
| 16:49 | amalloy | &(clojure.walk/walk (comp vec reverse) hash-map {0 :start 1 :inprogress 2 :end}) |
| 16:49 | sexpbot | java.lang.IllegalArgumentException: No value supplied for key: {:start 0, :inprogress 1, :end 2} |
| 16:49 | anthony | Is there an easy way to "flip" a map? Or should I store the data a different way, then create maps out of it (like an even-length vector?)? |
| 16:50 | amalloy | ugh, whatever |
| 16:50 | amalloy | anthony: there are a number of ways to flip a map. the one that requires the least thinking for me is ##(into {} (for [[k v] {0 :start 1 :inprogress 2 :end}] [v k])) |
| 16:50 | sexpbot | ⟹ {:start 0, :inprogress 1, :end 2} |
| 16:51 | anthony | amalloy: Awesome. That works perfectly. Thanks a ton. |
| 16:51 | amalloy | i was trying to use walk because it's cleaner, but i was doing it wrong :P |
| 16:51 | amalloy | &(clojure.walk/walk (comp vec reverse) identity {0 :start 1 :inprogress 2 :end}) |
| 16:51 | sexpbot | ⟹ {:start 0, :inprogress 1, :end 2} |
| 16:51 | phenom_ | anyone know how to fix indentation in amcs when declaring deftypes with multiple protocols ? |
| 16:51 | amalloy | there |
| 16:51 | sattvik | ,(let [m {0 :a 1 :b}] (zipmap (vals m) (keys m))) |
| 16:51 | anthony | Even better. |
| 16:51 | clojurebot | {:b 1, :a 0} |
| 16:51 | amalloy | sattvik: ##(apply zipmap ((juxt vals keys) {0 :a 1 :b})) |
| 16:51 | sexpbot | ⟹ {:b 1, :a 0} |
| 16:52 | raek | ,(into {} (map (juxt val key) {:a 1, :b 2})) |
| 16:52 | clojurebot | {1 :a, 2 :b} |
| 16:52 | jaley | oh my, so many ways to skin that cat? |
| 16:52 | amalloy | ah, score one for raek, i think |
| 16:52 | anthony | haha dangit, now I have too many options to pick from. :-) |
| 16:52 | raek | phenom_: in emasc? |
| 16:52 | raek | *emacs |
| 16:52 | anthony | I like the juxt one, though. Thanks for all the help, amalloy and raek |
| 16:54 | User | I came upon the following code when looking at enlive: |
| 16:54 | User | (transformation [:.text] (content item) {[:input][:br]} (clone-for [x choices] |
| 16:54 | phenom_ | raek: yea |
| 16:55 | User | what kind of selector is {[:input][:br]} |
| 16:55 | User | I thought selector had to be a vector |
| 16:55 | raek | phenom_: you can use M-x customize-variable, clojure-mode-use-backtracking-indent |
| 16:55 | amalloy | User: that doesn't look like a selector to me |
| 16:55 | phenom_ | raek: http://pastie.org/1667951 |
| 16:55 | jaley | @User from memory, can a selector not also be a function? |
| 16:56 | brehaut | User: enlive uses a map as a range selector for some things |
| 16:56 | raek | phenom_: yes, enabling backtracking indent makes that indent correctly |
| 16:57 | phenom_ | raek: perfect, thnx |
| 16:57 | amalloy | maps...as range selectors? gross |
| 16:58 | User | I have no idea what that is |
| 16:58 | User | http://groups.google.com/group/enlive-clj/browse_thread/thread/45e0e64f51ec6bdb?pli=1 |
| 16:58 | User | look at cgrand's answer |
| 16:58 | User | first code snippet |
| 16:59 | brehaut | User: {:input :br} selects (inclusively) everything between an input and br |
| 16:59 | User | oh |
| 16:59 | User | intredasting |
| 17:01 | brehaut | amalloy: why is maps as ranges bad? |
| 17:03 | amalloy | brehaut: it clashes conceptually with the notion of key=>value; he's just using it to store a pair. if [[:input][:br]] isn't used for anything else i'd like it better |
| 17:03 | brehaut | i think it is used |
| 17:04 | amalloy | i imagine so |
| 17:04 | amalloy | otherwise he'd use it here :) |
| 17:04 | brehaut | indeed :P |
| 17:07 | User | what's [[:input][:br]] used for ? |
| 17:10 | brehaut | [[#{:ul :ol} :.outline] :> :li] ul.outline > li, ol.outline > li |
| 17:10 | brehaut | thats from the readme |
| 17:10 | brehaut | under 'syntax' |
| 17:11 | brehaut | roughly parenthisis basicly (which CSS doesnt have) |
| 17:13 | User | so set is used for OR |
| 17:13 | User | and vector is and |
| 17:14 | TimMc | amalloy: Yeah, I was cringing when I saw that in his (not= DSL macros) talk |
| 17:14 | brehaut | its not and, its grouping |
| 17:14 | User | it has to match both selectors in the inner vector |
| 17:14 | brehaut | s/grouping/parenthsis |
| 17:14 | sexpbot | <brehaut> its not and, its parenthsis |
| 17:14 | User | does it not? |
| 17:15 | User | what the hell is parenthesis |
| 17:15 | amalloy | lol |
| 17:15 | brehaut | well yes, but not in an and way |
| 17:15 | User | parenthesis is a character |
| 17:15 | brehaut | (1 + 2) * 3 |
| 17:15 | brehaut | parenthsis |
| 17:15 | User | I read it as such |
| 17:16 | brehaut | it makes that subselector atomic to the operators that contain it |
| 17:16 | TimMc | parenthes*e*s |
| 17:17 | User | ok so if I have this selector [:ul :.outline] it will select all elements that are ul tag and outline style |
| 17:17 | brehaut | TimMc: sorry |
| 17:17 | User | because I always thought that would select an element with outline style that is a child of ul element |
| 17:18 | brehaut | User: no, it will select all elements with the "outline" class that are inside a ul element |
| 17:18 | brehaut | wait, i think you might be right in that case |
| 17:18 | joshua__ | Is there a Clojure library out there for converting HTML to Markdown. I've been trying to do it with an XSLT and Saxon, but I've been having a bit of trouble. |
| 17:18 | brehaut | hah excuse me for being a complete arse |
| 17:19 | brehaut | but i think you are right that it is actually an and in this case |
| 17:20 | User | that's what confused me immensely |
| 17:21 | User | the outermost vector is processed differently than any inner vectors |
| 17:21 | brehaut | yeah you are right |
| 17:21 | amalloy | brehaut: you forgot to pretend you prefer tea |
| 17:21 | User | off to my REPL |
| 17:21 | User | got to test this |
| 17:22 | brehaut | amalloy: oh crap |
| 17:22 | brehaut | User: good plan |
| 17:25 | User | http://pastebin.com/5AfExvj5 |
| 17:25 | User | look at this |
| 17:26 | User | the difference between [:ul :.content] [:body :.content] and [[:ul :.content]] |
| 17:26 | User | or lack there-of |
| 17:30 | brehaut | TimMc: well done :) |
| 17:30 | tufflax | I don't like that clojurebot uses notice for that :P |
| 17:31 | TimMc | brehaut: Thanks! |
| 17:33 | brehaut | User: that does appear surprising |
| 17:34 | amalloy | tufflax: what would you prefer? |
| 17:35 | tufflax | Normal message maybe. The thing is that it makes a sound, which I turned off now, but it's handy to have that sound if someone needs to reach me |
| 17:36 | TimMc | Is it a new feature? |
| 17:38 | amalloy | tufflax: that's a weird thing for your client to do |
| 17:38 | amalloy | notices are supposed to be lower-impact than regular messages, not higher |
| 17:38 | tufflax | oh, is that so :P |
| 17:39 | tufflax | WHat's supposed to be higher then? |
| 17:39 | Derander | amalloy: textual makes them show up with a red background and red text |
| 17:41 | amalloy | The NOTICE message is used similarly to PRIVMSG. The difference between NOTICE and PRIVMSG is that automatic replies must never be sent in response to a NOTICE message. |
| 17:43 | Raynes | amalloy: I'd use notice for that as well assuming we had a similar feature in sexpbot. |
| 17:43 | amalloy | Raynes: github commits? |
| 17:43 | brehaut | whoa, raynes has taken time out from trying android apps to visit irc!? |
| 17:43 | Raynes | Ghats |
| 17:44 | Raynes | brehaut: I'm actually just on my phone. |
| 17:44 | tufflax | amalloy: I don't think it clear from that that notices are lower-impact than regular messages. But, anyway, it's not a big problem :) |
| 17:45 | Raynes | amalloy: That's a ripoff of someone else's bot. Never occurred to me to use notices for that. |
| 17:45 | Raynes | A more sophisticated ripoff, but a ripoff nonetheless. |
| 17:46 | Raynes | Brb, getting on the desktop. |
| 17:46 | amalloy | tufflax: agreed, that in itself is insufficient to show that notices are lower-impact. but i think it does demonstrate that they shouldn't be *higher* impact |
| 17:49 | tufflax | amalloy: Yeah, perhaps. Thank you for making me aware :) |
| 17:50 | Raynes | Back. |
| 17:51 | Raynes | amalloy: Don't we have a contributor list that isn't on my blog? Like, in the README? |
| 17:51 | Raynes | If so, we should add brehaut to that. I never intended to edit that blog post every time someone committed to sexpbot. |
| 17:52 | Raynes | I'll check and do that in a moment. Got to get my environment going. |
| 17:56 | Raynes | brehaut: But yes, Android is awesome. :> |
| 17:56 | brehaut | ha |
| 18:01 | nickik | What does this mean in java |
| 18:01 | nickik | int iterations = 1 << (maxDepth - depth + minDepth); |
| 18:02 | amalloy | << is left-bit-shift |
| 18:02 | User | it's a retarded shift trick |
| 18:02 | User | It basically says 2^(maxdepth-depth + mindepth) |
| 18:02 | brehaut | looks liek someone is trying to (perhaps naively) optimize multiplication |
| 18:03 | nickik | i doing a benchmark |
| 18:03 | amalloy | tbh i can't imagine why you'd want to add max+min depths together, and subtract some other depth |
| 18:03 | nickik | im |
| 18:03 | User | it might make it faster but unless this is rolling in a loop like crazy |
| 18:03 | User | it's not worth the obfuscation |
| 18:04 | raek | it's like when people write x >> 1 instead of x / 2 |
| 18:04 | User | yeah |
| 18:04 | brehaut | it also makes assumptions about the compiler(s) |
| 18:04 | nickik | http://shootout.alioth.debian.org/u64/program.php?test=binarytrees&lang=java&id=2 |
| 18:05 | amalloy | wow, it's been a while since i saw such unanimous unbridled hate for shift operators |
| 18:05 | User | not worth it in this case |
| 18:05 | brehaut | amalloy: ha |
| 18:05 | nickik | how should I writ it in clojure? |
| 18:06 | User | the cost of other things in the outer loop is many many many times bigger than the difference between bitshift and multiplication |
| 18:06 | Raynes | brehaut: I just wrote a contributor section into the sexpbot readme and put you in it. Congratulations in becoming an honorary sexpbot contributor. You win a brand new internet! |
| 18:06 | brehaut | Raynes: cheers :) |
| 18:06 | brehaut | its trying hard to be the least used contribution too :P |
| 18:07 | User | (bit-shift-left 1 (- maxDepth (+ depth minDepth))) |
| 18:08 | Raynes | brehaut: It's a sneaky little thing that nobody would ever care about until it actually works for them and then they love it. |
| 18:08 | brehaut | thats the plan |
| 18:08 | amalloy | yeah |
| 18:14 | User | interesting page nickik |
| 18:14 | nickik | page? |
| 18:14 | spewn | &(+ 1 2 3 |
| 18:14 | User | clojure is quite slow especially when problem size isn't huge |
| 18:14 | sexpbot | ⟹ 6 ; Adjusted to (+ 1 2 3) |
| 18:14 | spewn | I love it! |
| 18:14 | phenom_ | anyone have cake working with clojure 1.3 ? |
| 18:14 | User | the shootout nickik |
| 18:15 | phenom_ | [org.clojure/clojure "1.3.0-master-SNAPSHOT"] as a dependency isn't working for me in project.clj |
| 18:15 | nickik | User, yeah im doing a project for school and i want to have the binarytree working with 1.3 alpha |
| 18:15 | User | for huge huge problem size of 2^20 it's only 3 times slower than java but for 2^12 which is a huge binary tree nonetheless it's like 15 times slower than java |
| 18:16 | User | (most of my programs use lists and vectors of size around 10 and there clojure is around 40 times slower than java) |
| 18:21 | User | wow for binary trees of size 4096 nodes, clojure is the slowest language |
| 18:21 | nickik | Mhh the bitshift does not seam to work with longs |
| 18:22 | nickik | call to shiftLeft can't be resolved. |
| 18:22 | nickik | (its a reflection warning) |
| 18:23 | nickik | User, why do you think that is? |
| 18:23 | User | yeah and that code uses unchecked ops everywhere |
| 18:24 | User | no idea |
| 18:24 | User | immutable data and checked arithmetrics are usually the biggest slowness |
| 18:24 | User | notice that lisp does much better |
| 18:25 | raek | boxing is very bad for performance too |
| 18:25 | User | because it allows mutation and it uses imperative programming |
| 18:25 | User | yes |
| 18:25 | User | this code uses (int x) and such a lot though |
| 18:25 | User | http://shootout.alioth.debian.org/u64/benchmark.php?test=binarytrees&lang=clojure |
| 18:26 | nickik | in 1.2 you cant box if you have a function call right? |
| 18:26 | User | I don't see how it can be improved |
| 18:26 | nickik | her is my take: https://github.com/nickik/IDPA-Programmiersprachen-Benchmarken/blob/master/clojure/src/clojure/binarytrees_me.clj |
| 18:26 | User | I mean even LUA is faster :D |
| 18:26 | User | and python :P |
| 18:27 | raek | nickik: you can't pass primitives over function boundaries, yes |
| 18:27 | raek | ...in 1.2 |
| 18:27 | User | and erlang |
| 18:27 | User | and ruby :D |
| 18:28 | nickik | reak, the version i linked is 1.3 |
| 18:28 | User | seems to me that JVM also limits clojure performance in some ways, it just wasn't made for this |
| 18:28 | nickik | that should speed things up |
| 18:28 | User | LISP compilers have free hands |
| 18:28 | nickik | the code for this example is almost one to one translation from java |
| 18:29 | User | I know |
| 18:29 | User | it's quite non-idiomatic too |
| 18:30 | User | nobody actually writes clojure like that imo |
| 18:30 | nickik | does not matter its a benchmark |
| 18:31 | nickik | Was a stupid idea to use benchmarking for a school project |
| 18:31 | nickik | its way to hard and does not look impressiv |
| 18:32 | User | indeed |
| 18:32 | User | I'm just saying, it's an annoying thing with clojure |
| 18:32 | nickik | should of just have implemented some parallel code in clojure and java and show how clojure is better |
| 18:32 | User | you have to write differently than normal if you don't want some huge performance hits |
| 18:33 | User | in java I just write normal code and it usually doesn't run much slower than hand optimized |
| 18:33 | User | with clojure difference is quite significant |
| 18:34 | User | with all those unchecked-add, I think it woudl be easier to just rebind + to unchecked-add :P |
| 18:34 | nickik | 2^(maxdepth-depth + mindepth) should work to right, then i could throw away bit-shift |
| 18:35 | nickik | whats the function for 2^ in clojure? |
| 18:35 | User | bit shift is quite a bit faster than power |
| 18:35 | nickik | but it needs to use reflection |
| 18:35 | User | clojure generally uses Math/pow from java |
| 18:35 | User | for all you power needs |
| 18:36 | nickik | i have to find out whats faster later |
| 18:36 | User | or (apply * (repeat 2 n)) |
| 18:36 | amalloy | clojure.math/expt |
| 18:36 | User | both are slot :D |
| 18:36 | User | slow |
| 18:36 | clojurebot | Gabh mo leithscéal? |
| 18:36 | amalloy | User: i disagree with your claim about map/pow |
| 18:36 | amalloy | s/map/Math |
| 18:36 | sexpbot | <amalloy> User: i disagree with your claim about Math/pow |
| 18:37 | User | why |
| 18:37 | amalloy | it only deals with Double, and for example there's clojure.math/expt that handles all of clojure's numeric data types |
| 18:38 | User | yeah well in any case any implementation does as many multiplications as the exponent is |
| 18:38 | User | while bitshift is like a single add |
| 18:39 | amalloy | User: half an hour ago you were telling everyone that << wasn't worth the obfuscation |
| 18:39 | User | generally |
| 18:40 | User | in any case it's unfortunate that default numeric data in clojure is that slow...considering 99% of the time I modify numeric data it's "count++" type of code and the variable is well inside int range |
| 18:41 | User | thus I rarely get to use the benefits (automatic promotion of type) |
| 18:41 | brehaut | User: really? you increment counters a lot in your clojure code? |
| 18:41 | amalloy | hah, good catch there brehaut |
| 18:41 | User | not that much |
| 18:42 | User | usually when I use recur |
| 18:42 | User | but it sure comes up more often than anything else |
| 18:42 | User | any other numeric manipulation |
| 18:42 | amalloy | User: i rarely wind up needing to use recur either. just let the lazy seqs flow |
| 18:43 | amalloy | less performant but more reusable |
| 18:43 | User | and how do you generate these seqs |
| 18:43 | amalloy | and more readable |
| 18:43 | User | usually there's some variable that changes |
| 18:43 | brehaut | &(apropos "-indexed") |
| 18:43 | sexpbot | java.lang.Exception: Unable to resolve symbol: apropos in this context |
| 18:43 | brehaut | &(use 'clojure.repl) |
| 18:43 | sexpbot | ⟹ nil |
| 18:43 | amalloy | map-indexed |
| 18:43 | User | in any case it's SLOOOOOW |
| 18:43 | brehaut | &(apropos "-indexed") |
| 18:43 | sexpbot | ⟹ (keep-indexed map-indexed) |
| 18:44 | User | that just hides inc calls |
| 18:44 | amalloy | but brehaut, those use lazy seqs under the covers. it's so slow! |
| 18:44 | User | they still happen and they are still slow |
| 18:44 | amalloy | User: actually it's using (range), bet you a million dollars. (range hides the incs, of course) |
| 18:44 | User | :D:D:D:D |
| 18:44 | User | always comes down to inc :D |
| 18:45 | tomoj | don't bet |
| 18:45 | User | s/inc/inc calls/ |
| 18:45 | sexpbot | <User> always comes down to inc calls :D |
| 18:45 | tomoj | neither use range in 1.2 |
| 18:45 | amalloy | tomoj: if i'm wrong i'll just claim by "dollars" i meant something else |
| 18:45 | tomoj | ok :) |
| 18:45 | brehaut | tomoj: they do use primative ints for counters though |
| 18:46 | brehaut | (which is to say: agreeing) |
| 18:46 | phenom_ | ,(deftype Test [] clojure.lang.IPersistentVector (length [this])) |
| 18:46 | tomoj | really? I dno't see that |
| 18:46 | clojurebot | sandbox.Test |
| 18:46 | phenom_ | ,(Test.) |
| 18:46 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.AbstractMethodError> |
| 18:46 | brehaut | 'size (int (count c))" hmm, maybe just for the size |
| 18:47 | tomoj | I see a letfn with lazy-seq that calls itself |
| 18:47 | tomoj | in 1.2 I don't see how this could possibly be primitive |
| 18:47 | brehaut | the inner most let |
| 18:47 | tomoj | ah, right |
| 18:48 | brehaut | it would boxed up again though wouldnt it |
| 18:50 | User | I doubt core functions use primitive ints for anything |
| 18:50 | User | because most of those functions are supposed to work for infinite sequences and stuff like that |
| 18:51 | User | in any case look at that language shootout page |
| 18:51 | brehaut | i see no reason that there could not be a polymorphic implementation that uses primatives till it overflows and then slowints to the rest of infinity |
| 18:52 | User | even though clojure beats a lot of languages such as ruby, lua and stuff at binary trees with size of 1 mil, it's the slowest language with small trees size 4000, which is majority of data |
| 18:52 | User | I ever use |
| 18:52 | tomoj | slower than ruby is hard to believe |
| 18:54 | User | look at it yourself |
| 18:54 | dnolen | User: JVM startup time. |
| 18:54 | tomoj | I don't mean that I don't believe those are the current results, I mean that those results aren't _right_ :) |
| 18:56 | dnolen | User: has nothing to do w/ small trees. A warm JVM will be eat Python and Ruby for breakfast. |
| 18:56 | User | I think jvm startup time doesn't count |
| 18:56 | User | look at java stats |
| 18:56 | User | it beats most languages |
| 18:56 | User | clojure none |
| 18:56 | ossareh | morning 'all |
| 18:57 | ossareh | s/'// |
| 18:57 | sexpbot | <ossareh> morning all |
| 18:57 | dnolen | User: I don't know the details of how those example are run, if they are AOT etc. Doesn't matter, Clojure is not slow on small trees, makes no sense. |
| 18:57 | tomoj | saying "java beats most languages" or "clojure beats none" seems a bit misleading. as if the results give facts about the languages |
| 18:58 | ossareh | clojure beats everything I've ever used in terms of expressiveness. |
| 18:58 | tomoj | that in this example clojure loses to ruby suggests very strongly to me that these results aren't about the language at all |
| 18:59 | User | see tomoj you are arguing with no data either |
| 18:59 | User | against what you call flawed data |
| 19:00 | brehaut | one sample point is not a basis for an argument either |
| 19:00 | User | from dropdown you can select other samples |
| 19:00 | joshua__ | link to what your talking about |
| 19:00 | joshua__ | ? |
| 19:00 | User | but that's beside the point |
| 19:01 | User | joshua__: http://shootout.alioth.debian.org/u64/benchmark.php?test=binarytrees&lang=clojure |
| 19:01 | tomoj | presumably running with the larger tree sizes gives larger runtimes |
| 19:01 | User | it does |
| 19:01 | tomoj | I wonder if that is the only way the jvm startup time becomes less dominant, and the only way hotspot is allowed to wake up? |
| 19:02 | User | no idea |
| 19:02 | tomoj | still, slower than ruby baffles me unless the runtime for that size is very short |
| 19:02 | User | in any case you can compare java and clojure if you want |
| 19:02 | User | my java code is usually 3 - 200 times faster |
| 19:02 | User | most often in 10-40 range |
| 19:04 | User | this usually comes from ArrayList - clojure vector difference and arithmetics |
| 19:06 | joshua__ | http://shootout.alioth.debian.org/u64/performance.php?test=binarytrees&sort=elapsed |
| 19:06 | joshua__ | isn't that saying Clojure is ahead, not behind? Or am I missing something? |
| 19:07 | dnolen | User: not surprising. Writing fast Clojure takes some experience. Clojure generates a lot of classes, even w/ AOT I imagine that adversely affects startup time. |
| 19:08 | nickik | Ah it works know with 1.3, know i only have to find out if its going to be fast than 1.2 |
| 19:09 | amalloy | joshua__: you must be reading it wrong |
| 19:09 | mec | my paredit has quit working. It was working perfectly yesterday, and I havn't changed anything since. Anyone know what might be wrong, or how to find out? |
| 19:10 | User | joshua__ that is N=20 --> million elements tree, try N=12 4000 elements tree |
| 19:10 | tomoj | mec: elaborate? |
| 19:10 | User | dnolen: saying that writing fast programs reuqires special knowledge doesn't do it any favors |
| 19:11 | mec | tomoj: the commands to move parenthesis around do nothing, and while typing ( produces () deleting the opening parenthesis does not remove the closing one at the repl. In a *.clj file it doesnt appear to work at all |
| 19:12 | amalloy | mec: the repl is generally not in paredit mode. mine isn't, anyway |
| 19:12 | tomoj | mec: and you still see "Paredit" in the modeline for a clj file? |
| 19:12 | dnolen | User: eh? that's the case for pretty much every PL I ever used for any non-trivial program. |
| 19:12 | mec | tomoj: no, there is a Paredit on the repl line |
| 19:13 | tomoj | I'd be surprised if that didn't cause trouble |
| 19:13 | tomoj | but if you don't see it in the modeline for a clj file, it's not on |
| 19:13 | dnolen | User: in fact, Alioth benchmarks is proof of that. |
| 19:14 | mec | tomoj: the lines are still in my .emacs to enable it |
| 19:14 | tomoj | a clojure-mode-hook? |
| 19:14 | brehaut | dnolen: you can write fast small programs in c without specialist knowledge |
| 19:15 | amalloy | i set my repl to use paredit mode once. it was a disaster, for reasons i don't remember |
| 19:15 | dnolen | brehaut: non-trivial means moving memory around, then you have start getting clever. |
| 19:15 | mec | it looks like it adds it to anything that is a -mode-hook and specifically after that to slime-repl-mode-hook |
| 19:15 | brehaut | dnolen: sure, it gets hard very fast |
| 19:16 | ldh | any compojure folks? i'm trying to set the content-type header in my handler response. I've seen it documented like this, but I get "unsuppored binding form: :headers |
| 19:16 | ldh | (GET "/" [{:headers {"Content-type" "text/plain"}} "Response text"] |
| 19:16 | tomoj | clj files aren't in slime-repl-mode |
| 19:16 | tomoj | and I don't think you want paredit turning on in every mode hook... |
| 19:16 | mec | oh sorry its just '(emacs-lisp lisp inferior-lisp slime) |
| 19:16 | tomoj | perhaps you should add clojure? ..do you use clojure-mode? |
| 19:17 | mec | yes let me add it and see if that fixes it |
| 19:17 | nickik | https://github.com/nickik/IDPA-Programmiersprachen-Benchmarken/blob/master/clojure/src/clojure/binarytrees_me.clj |
| 19:18 | brehaut | ldh: you might find #compojure more helpful? |
| 19:18 | nickik | Can somebody help me I keep getting "Exception in thread "main" clojure.lang.ArityException: Wrong number of args (2) passed to: core$number-QMARK-" |
| 19:18 | ldh | brehaut: ah, of course. thanks. |
| 19:18 | brehaut | ldh: sorry i cant help more, i mainly use moustache |
| 19:18 | mec | I get a "File mode specification error: (error "Unmatched bracket or quote")" when I open a .clj, could that be the case? |
| 19:18 | mec | r/case/cause/ |
| 19:19 | User | dnolen: I can do very fast java programs without any special care |
| 19:19 | nickik | Hard to understand whats going on if you don't even get a linenumber. |
| 19:19 | tomoj | mec: you lost me, sorry. good luck |
| 19:20 | dnolen | User: would you say your Java knowledge is about equal to your Clojure knowledge? |
| 19:20 | tomoj | amalloy: |
| 19:21 | ldh | brehaut: no worries. a bit of struggle is part of the process of learning a new language/paradigm I suppose ;) |
| 19:21 | tomoj | er. amalloy: I heard durendal can make paredit work in the repl. haven't tried it yet |
| 19:21 | brehaut | ldh: perceiver though, clojure's web ecosystem is developing very nicely |
| 19:22 | nickik | dnolen, i think its true because in java you mostly just use plain old imperativ code witch is just fast than in clojure (plus its mutch easier to get primitv types working) |
| 19:22 | ldh | brehaut: indeed. seems like a pretty exciting time to be writing webapps in clojure |
| 19:22 | brehaut | ldh: definately is |
| 19:23 | User | dnolen: no, but in java I at least don't need to change operators in every function and wrap all in additional casts to get performance |
| 19:24 | tomoj | nickik: condp passes two args to each pred, number? and string? take only one arg |
| 19:25 | tomoj | er, ignore that |
| 19:25 | tomoj | but that's where your problem is :) |
| 19:25 | User | here's java optimization: unroll a loop somewhere, take a calculated variable and take it out of a loop |
| 19:26 | dnolen | User: I'm certainly not saying all in the Clojure world is wine and roses. < I agree 1.2 required too much expertise. Those are known pain points - 1.3.0 addresses some of the more problematic one. |
| 19:26 | joshua__ | I just tried to implement a html to markdown converter. My attempt can be seen here: https://gist.github.com/868546 It was created by trying to translate this SO answer to Clojure: http://stackoverflow.com/questions/59557/html-to-markdown-with-java |
| 19:26 | User | here's clojure optimization: every trick of java optimization PLUS you need to replace all calls to * + - etc with unchecked, all numeric variables with (int x) and arguments with type hints |
| 19:26 | joshua__ | It doesn't work. I don't know enough about what I'm doing to know why. |
| 19:26 | User | a LOT more work, also makes code super ugly |
| 19:27 | dnolen | User: and it would great for higher order operations to work on collections of Java primitives. Work is being done on this stuff. |
| 19:28 | nickik | you can rebind *unckecked-math* or something to avoid the hole unckecked stuff right? (in 1.3) |
| 19:28 | tomoj | nickik: right, so it's evaluating (apply number? args). I guess you're passing two args? |
| 19:29 | tomoj | ..those will never be numbers anyway, will they? |
| 19:30 | nickik | tomoj, true i will replace it with something else |
| 19:31 | mec | wow so apparently an errant close paren somewhere in the source killed Paredit from loading at all |
| 19:33 | nickik | tomoj, i dont think its that. I use the same -main in a other namespace and it works there |
| 19:33 | tomoj | there, how many args do you pass? |
| 19:34 | Derander | serial-port is relevant to my interests |
| 19:34 | dnolen | User: for a lang that's three years old to be butting up against CL and Racket on Alioth is remarkable, I have high hopes for continued improvements to Clojure performance and regaining some lost expressivity. |
| 19:35 | nickik | tomoj, only one. |
| 19:35 | tomoj | nickik: gotta go. if you're passing one arg to that one, and two args here, maybe you can see the problem? |
| 19:37 | User | what expressivity was lost? |
| 19:38 | User | dnolen:scala isn't any older (I think?) and is 3 times faster |
| 19:39 | amalloy | ugh. unless you have to write any code in scala. that should slow you down |
| 19:39 | dnolen | User: Scala is 2003. |
| 19:39 | brehaut | Scala is much older than clojure: wikipedia lists its first appearance as 2003 |
| 19:39 | Derander | doesn't clojure also stand to gain massively from java 7? |
| 19:40 | dnolen | Derander: I don't think so. |
| 19:40 | nickik | mmh not really |
| 19:40 | Derander | okay |
| 19:40 | Derander | nevermind then :-) |
| 19:40 | nickik | maybe a little but not like ruby |
| 19:40 | amalloy_ | Derander: it looks that way to me, but people who know better than i say no |
| 19:40 | User | besides clojure isn't butting up to CL and Racket for small lists |
| 19:40 | Derander | okay. I'm also watching from a ruby perspective so perhaps I crossed the channels |
| 19:40 | nickik | the forkjoin stuff and the closures will be helpfull |
| 19:41 | dnolen | User: Alioth doesn't bench small lists in long running programs. |
| 19:47 | User | 4000 elements is still quite big |
| 19:48 | User | try putting 10 elements into a vector...then 10 elements into an arraylist, then run this in a million iteration loop, so hotspot isn;t an issue |
| 19:48 | User | staggering difference |
| 19:49 | nickik | dnolen, did you look into that logic programming language you mention on your blog (that so much faster then prolog). I didn't have time to look into. |
| 19:54 | dnolen | User: Try changing an ArrayList and getting the old version of the ArrayList before the change. staggering difference. Anyways sorry but this conversation isn't going anywhere for me. |
| 19:54 | dnolen | nickik: ? what are you referring to? |
| 19:56 | nickik | dnolen, The Mercury Programming Language |
| 19:59 | dnolen | nickik: I've only looked into it a little. Seems interesting, performance is very impressive. Lack of REPL is a turnoff for me tho. |
| 20:12 | amalloy | technomancy: that is an adorable thing for your kid to do |
| 20:13 | User | I knew you;'d say that |
| 20:15 | User | too bad immutability doesn't do anything when vector doesn't leave the fn |
| 20:34 | fliebel | dnolen: Which of your posts mentions Mercury? I think that paper you sent me also mentions it. |
| 20:34 | dnolen | fliebel: I only mentioned it in passing as something interesting to look at. Enjoying the paper? |
| 20:36 | fliebel | dnolen: So far… meh. It contains a lot of stuff I already read in TRS, but I assume it's only the beginning, and even there it has a few interesting insights. |
| 20:38 | dnolen | fliebel: yeah it picks up when it covers the implementation. |
| 20:38 | fliebel | I skipped forward to the arithmetic part, and they explained why it is so much more complicated that one would think at first, thinking of it as a recursive full-adder. They stress determinism(is that a valid word?) much more than the book. |
| 20:40 | fliebel | I think they mentioned Mercury for its ability to use regular functions in unifications, deferring their action untill all values are grounded, but deny this approach because it can not be said to terminate. |
| 20:40 | fliebel | This is kind of what project does, right? |
| 20:43 | dnolen | fliebel: project is for getting a logic vars value so you can use regular (non-relational) operations on them. For example you might know that a logic var is bound to a Clojure set, and you really just want to use conj etc on it's value. |
| 20:45 | fliebel | dnolen: Oh, yea, I mixed up a few terms, I need to sleep. See ya. |
| 20:47 | brehaut | dnolen: is project equiv to m-lift for logos ? |
| 20:48 | dnolen | brehaut: sadly my monad fu is significantly less than my logic fu, and honestly both are quite low :) what does m-lift do? lift a value out of a monad? |
| 20:48 | brehaut | it lifts a function into the monad |
| 20:49 | dnolen | brehaut: ah, it takes a regular function and allows it be used w/in a monad? |
| 20:49 | brehaut | yeah thats a better way of putting it |
| 20:54 | brehaut | my monad fu is pretty low too, but im interested in the correspondence between alternative models of evaluation and the monadic operations |
| 20:54 | dnolen | interesting, it does sound related. But the issue is different. Many useful operations are hard (impossible?) to define efficiently in a relational way (where inputs/outputs are interchangeable). So instead of struggling to define everything relationally, project is bit of an escape hatch for solving common problems with the downside that you can no longer infer inputs from outputs. |
| 20:55 | brehaut | ah right |
| 20:56 | brehaut | that input/output interchangability is where ive hit a roadblock trying to slowly evolve a logical variation of the monkey and banana from a naive functional variation |
| 20:57 | dnolen | brehaut: in Prolog? |
| 20:57 | brehaut | in clojure |
| 20:58 | brehaut | taken from the bratko book |
| 20:58 | brehaut | its trivial in prolog :) |
| 21:01 | brehaut | dnolen: even using fogus's unifier i still have to be fairly explicit about the solving steps |
| 21:01 | brehaut | dnolen: https://github.com/brehaut/monkey-and-banana if you are interested |
| 21:02 | brehaut | i want to have a crack at getting a logos version done too |
| 21:02 | dnolen | brehaut: have you looked at logicT ? |
| 21:02 | brehaut | dnolen: nope? what is it |
| 21:03 | brehaut | logic monad transformer? |
| 21:03 | dnolen | brehaut: yeah, Oleg's implementation in Haskell of miniKanren's core ideas. |
| 21:03 | brehaut | huh. thats definatly something i need to read up on |
| 21:04 | dnolen | brehaut: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.84.6597&rep=rep1&type=pdf |
| 21:05 | brehaut | dnolen: great, thanks! |
| 21:05 | dnolen | brehaut: if you implement anything like that in Clojure I'd love to see that and compare :) |
| 21:06 | brehaut | dnolen: i'll have to understand it first :P |
| 21:06 | brehaut | but it soudns like something worth doing |
| 21:15 | amalloy | brehaut: writing code is a lot less adventurous if you understand it first |
| 21:15 | brehaut | amalloy: thats not true if monads are involved :P |
| 21:16 | brehaut | also the paper is by oleg, they man has a brain the size of a small galaxy |
| 21:17 | brehaut | it dawns on me that thus far none of my experiements in logic programming with clojure have included any notion of a logical variable |
| 21:44 | fmw | http://paste.pocoo.org/show/353261/ for some reason an if-not block seems to be executing there, even if it shouldn't. Any idea what I'm doing wrong there? |
| 21:45 | amalloy | fmw: ((println |
| 21:45 | amalloy | i don't think that is your *actual* problem (yet), but it will cause you pain eventually |
| 21:46 | fmw | amalloy: the whole 3 lines (both println's and (. vintage ...) are supposed to be part of the same block |
| 21:46 | fmw | the println's are only for debugging though |
| 21:46 | amalloy | there are two ways to fix this problem |
| 21:47 | amalloy | well. i guess that depends where the .add is supposed to go. your indentation makes this really hard to read |
| 21:47 | fmw | the .add is outside of the if (its added anyway) |
| 21:48 | amalloy | okay. so you have two issues here |
| 21:48 | amalloy | one is that you've stuck an if-not inside of a doto form where it doesn't realy belong |
| 21:48 | amalloy | this is expanding into (if-not document (nil? ...) ((println ...)) (.vintage ...)) |
| 21:50 | amalloy | the other is that you don't group expressions by wrapping them with more parens: ((println x) (println y)) doesn't mean "print x, then y", it means "print x, then treat the return value of that print as a function and call it with argument y" |
| 21:50 | amalloy | you're looking for (do (println x) (println y)) |
| 21:51 | fmw | amalloy: ok, thanks, that fixes it |
| 21:51 | fmw | that as in moving it out of the doto/wrapping the println's in a do |
| 21:52 | amalloy | good good |
| 21:53 | fmw | amalloy: as to the indentation, is it still objectable with http://paste.pocoo.org/show/353264/ ? if so, why? I suppose indentation is very personal, but I'd like to get used to an idiomatic identation style because I'm just starting out with Clojure anyway |
| 21:54 | amalloy | fmw: that's much better |
| 21:54 | amalloy | i wouldn't put a newline after the [ in let, but i'm pretty sure there are people who would side with you |
| 21:55 | fmw | amalloy: allright. yes, I was debating that with myself when I put it there |
| 21:56 | amalloy | btw, you know you don't *have* to type-hint those variables, right? i mean, feel free if you need performance or like it as self-documenting code, but it's not required |
| 21:56 | tomoj | (if-not x (do y z)) == (when-not x y z) |
| 21:56 | fmw | amalloy: aye, I know, but I was like: why not? |
| 21:57 | amalloy | sure |
| 21:57 | tomoj | but, (when-not (nil? x)) seems strange |
| 21:57 | tomoj | why not (when x) ? |
| 21:57 | amalloy | tomoj: yeah. i wanted to emphasize "what do does" rather than "how i would write the code" which actually sidesteps the problem he was having |
| 21:58 | tomoj | sorry, I just got here |
| 21:58 | tomoj | did you already make the . point? |
| 21:58 | amalloy | no |
| 21:58 | amalloy | i just fixed his problem. i haven't addressed ways to make his code better in general |
| 21:59 | fmw | so, whats the . point? ;) |
| 21:59 | tomoj | whether you asked for it or not: (. age setIntValue x) is less idiomatic than (.setIntValue age x) |
| 22:00 | tomoj | I got excited when I saw lucene, then unexcited at couchdb :( |
| 22:00 | fmw | tomoj: aww, whats wrong with couchdb? |
| 22:00 | amalloy | before any of yours, i would (let [{:keys [distillery title bottler ...]} (:value json-item)] ...) |
| 22:00 | amalloy | then you can stop messing around with json maps and just have a bunch of local bindings for the stuff you're interested in |
| 22:01 | tomoj | fmw: nothing, I like it quite a lot, I'm just not using it right now |
| 22:01 | fmw | tomoj: ok :) |
| 22:02 | tomoj | I think there is a beautiful clojure library for solr/lucene that hasn't been written yet |
| 22:02 | tomoj | I tried and failed miserably |
| 22:02 | amalloy | tomoj: ninjudd and/or lancepantz were at least starting to work on that |
| 22:02 | tomoj | it's abstract classes all the way down |
| 22:03 | brehaut | i think abstract classes go up rather than down |
| 22:03 | amalloy | anyway fmw does my suggestion make sense? i think tomoj will agree that it's more interesting than his suggestions :), so if not let me know |
| 22:04 | fmw | amalloy: the :keys suggestion? |
| 22:04 | amalloy | right |
| 22:04 | tomoj | brehaut: maybe solr's got me standing on my head |
| 22:04 | brehaut | tomoj: entirely possible |
| 22:04 | fmw | amalloy: yes, I'm trying to implement it atm actually |
| 22:04 | amalloy | great |
| 22:04 | tomoj | amalloy: agreed |
| 22:05 | brehaut | tomoj: one of my friends wrote his own in memory clj text index because it was simplier than trying to grok lucene et al |
| 22:14 | amalloy | fmw: if you don't mind, i've rewritten this to remove most of the duplicated code i could find: https://gist.github.com/868661 |
| 22:14 | amalloy | but since i don't have lucene/couch handy, i don't even know if it compiles, so test with care before including :P |
| 22:15 | fmw | amalloy: cool, I think I fully understand the code, even :) |
| 22:15 | fmw | cheers |
| 22:15 | amalloy | fmw: that's the idea! write each idea exactly once :) |
| 22:16 | fmw | amalloy: yes, I get the point and see why this is idiomatic |
| 22:17 | amalloy | oh, i bet my change from (Integer.) to (int) broke things, though. don't use that :P |
| 22:18 | fmw | amalloy: ok, that was one of the things I was wondering about |
| 22:18 | amalloy | a brief attack of amnesia |
| 22:18 | amalloy | nothing more |
| 22:18 | fmw | amalloy: also, why the when instead of if? AFAIK it does exactly the same, but when is more idiomatic because it implies a do? |
| 22:19 | amalloy | fmw: that is one of the two reasons |
| 22:19 | joshua__ | Anyone here familiar with XSLT? |
| 22:19 | amalloy | the other is that, after doing this for a while, seeing an if without an else will make you dizzy: you will never leave one out on purpose |
| 22:19 | amalloy | er, on accident |
| 22:19 | amalloy | joshua__: it's been like four years but i used to be pretty solid on them |
| 22:19 | fmw | amalloy: ok :) |
| 22:19 | fmw | point taken |
| 22:20 | joshua__ | I just tried to implement a html to markdown converter. My attempt can be seen here: https://gist.github.com/868546 It was created by trying to translate this SO answer to Clojure: http://stackoverflow.com/questions/59557/html-to-markdown-with-java |
| 22:21 | Derander | Is it possible to use java.nio.file's api to watch files for changes w/o polling in java 6? is there an alternate api for java 6? I can't believe polling has been the way to track files forever |
| 22:21 | brehaut | joshua__: have considered enlive instead of xslt ? |
| 22:21 | joshua__ | brehaut, enlive has an html to markdown function!?! |
| 22:21 | brehaut | joshua__: no, but it has general html scrapping functions |
| 22:21 | brehaut | and its selector based |
| 22:22 | joshua__ | brehaut, I'm already using it for the scraping. See: http://173.255.212.42/item?id=1589257 |
| 22:23 | joshua__ | I just don't want it to look ugly, so I'm planning to select only the part of the comment I want with enlive, convert that to html, convert that html into markdown, and than have the backend of comments be markdown |
| 22:25 | wooby | Derander: not that i've seen, if you really needed to you could dip into the host api w/ JNA |
| 22:25 | wooby | (or jni) |
| 22:26 | Derander | wooby: seems unbelievably goofy to me, but okay :-/ |
| 22:27 | tomoj | I think I managed to get a stupid example with jnotify working reasonably easily once |
| 22:28 | wooby | possible someone's already done the goofiness for you, i haven't looked in awhile |
| 22:30 | amalloy | wooby: impossible. there is a limitless supply of goofiness to be done |
| 22:39 | fmw | amalloy: hmm, thats giving an error for me http://paste.pocoo.org/show/353276/ |
| 22:40 | amalloy | fmw: missing a ~ in ~document at line 11, sorry |
| 22:41 | fmw | amalloy: meh, in hindsight I should've spotted that! |
| 22:41 | fmw | thanks though |
| 22:41 | amalloy | fmw: i left it in intentionally, to give you practice reading compiler stacktraces....... |
| 22:41 | fmw | amalloy: hehe :) |
| 22:46 | fmw | amalloy: this one is really inexplicable for me: http://paste.pocoo.org/show/353278/ says java.lang.ClassCastException: java.lang.String cannot be cast to org.apache.lucene.document.Fieldable |
| 22:46 | fmw | on the (doto document line, even |
| 22:47 | tomoj | is there a reason for add-field to be a macro? |
| 22:47 | amalloy | tomoj: i wanted to get the string version of the symbol |
| 22:48 | tomoj | ah, I see |
| 22:48 | fmw | the error occurs regardless of using a macro or not |
| 22:48 | amalloy | since he's doing (Field. "title" title) |
| 22:48 | fmw | (if I remember correctly) |
| 22:49 | amalloy | oh |
| 22:49 | amalloy | er hm |
| 22:50 | amalloy | fmw: sure? the easiest explanation would be that my macro is wrong somewhere |
| 22:50 | tomoj | presumably age and vintage are strings from the json? |
| 22:50 | tomoj | .add on a Document expects a Fieldable |
| 22:50 | amalloy | oh |
| 22:50 | fmw | tomoj: ah yes they are. |
| 22:50 | amalloy | yes thanks |
| 22:51 | fmw | its not being used for vintage/age though |
| 22:51 | fmw | the macro |
| 22:51 | amalloy | fmw: see the last two lines |
| 22:51 | amalloy | you mean age-field, not age |
| 22:51 | fmw | amalloy: ah yes |
| 22:52 | fmw | I corrected that in the let, but copied your code without thinking elsewhere. |
| 22:52 | tomoj | does using the name of the local binding for the field name not seem a bit strange? very terse and pretty, but.. |
| 22:52 | fmw | I don't like the stack traces yet, really, so hard to see where you're going wrong exactly |
| 22:53 | amalloy | tomoj: i wouldn't object if you called it gross |
| 22:54 | amalloy | if you wanted to make it into a function and pass the string manually i guess that would be okay with me |
| 22:55 | amalloy | better i guess would be to create a function version, and wrap it in a macro that uses the local binding |
| 22:56 | tomoj | dunno that it's bad, just strange and different |
| 22:57 | amalloy | tomoj: part of my campaign to never type the same symbol twice in any program |
| 22:58 | tomoj | my analogous code just took a map of keywords for field names to values |
| 22:58 | tomoj | but solr took care of all the per-field properties |
| 22:58 | amalloy | tomoj: i have a keywordize macro i use occasionally: (keywordize [a b c]) expands to {:a a :b b :c c} |
| 22:59 | amalloy | it's pretty common that N different functions refer to some stuff by the same names, and want to pass around data in a map |
| 23:00 | tomoj | then again, do the per-field properties really belong in create-document? |
| 23:00 | tomoj | nevermind, it's 30 lines of code :) |
| 23:01 | amalloy | the dude wants code to add some fields to a thing? he gets code to add fields to a thing |
| 23:01 | fmw | heh |
| 23:01 | tomoj | is lucene schemaless? |
| 23:01 | tomoj | never used it except through solr |
| 23:02 | fmw | tomoj: as in that it doesn't require all fields for every document? |
| 23:02 | tomoj | I mean, you could add whatever fields with whatever names/properties you wanted? |
| 23:03 | fmw | tomoj: yes |
| 23:04 | amalloy | hey ossareh, were you at the clojure meetup? nobody ever said "hey i'm ossareh" |
| 23:09 | tomoj | amalloy: I think it's that it blurs the distinction between code and data in a way I just haven't really seen before |
| 23:10 | tomoj | but the more I think about it, the more it seems like that might be a good thing |
| 23:10 | amalloy | tomoj: well, glad to have opened your mind, i guess, whether or not you decide you like it |
| 23:12 | tomoj | :) |
| 23:13 | tomoj | being without keywordize when you need it is certainly ugly |
| 23:14 | amalloy | heh |
| 23:15 | amalloy | needing it is usually a bad smell anyway |
| 23:16 | phenom_ | does clojure have a sort of circular linked list or ring-like data structure ? |
| 23:17 | tomoj | for what? |
| 23:17 | brehaut | &(take 10 (cycle [:a :b :c]) |
| 23:17 | sexpbot | ⟹ (:a :b :c :a :b :c :a :b :c :a) ; Adjusted to (take 10 (cycle [:a :b :c])) |
| 23:18 | phenom_ | well, i've got a list but id like to read the first element, then rotate left (so the head goes to the end and everything shift over 1) |
| 23:18 | brehaut | phenom_: cons pairs are you easiest route to cycles |
| 23:19 | phenom_ | cons pairs ? |
| 23:19 | brehaut | ,(cons 1 ()) |
| 23:19 | clojurebot | (1) |
| 23:19 | brehaut | ,(cons 2 (cons 1 ()) |
| 23:19 | clojurebot | EOF while reading |
| 23:19 | brehaut | that'll teach me to use clojurebot |
| 23:19 | tomoj | guess the question is, do you need to edit it during these read/rotates? |
| 23:20 | brehaut | tomoj wins for best question |
| 23:20 | phenom_ | tomoj, well, other threads may edit it |
| 23:20 | tomoj | then it's an interesting problem |
| 23:20 | tomoj | :( |
| 23:20 | phenom_ | i was using a [index, content] pair |
| 23:21 | phenom_ | "head" was (nth content index) |
| 23:22 | amalloy | ken wesson implemented a ringbuffer on the mailing list a while ago |
| 23:22 | brehaut | phenom_: can you back up a step and explain what you are trying to solve? |
| 23:23 | amalloy | but in general i like brehaut's answer better. instead of asking for a data structure to solve a problem (which you've usually created for yourself), look for a better approach to the problem |
| 23:24 | phenom_ | well, i've got a list of items, i need to get the first element, then rotate the list ... other threads might be adding elements to the end of the list or removing elements from anywhere within the list |
| 23:24 | amalloy | phenom_: what do you mean, get the first element then rotate the list? "rotating the list" sounds like an artifact of your implementation, not your requirements |
| 23:25 | phenom_ | i want to cycle through the list |
| 23:25 | amalloy | ie, it sounds like you're really looking for a bounded-size queue |
| 23:25 | amalloy | and you want to let other threads *delete* things from the list while you're doing that? prefer suicide |
| 23:25 | phenom_ | well, using refs :P |
| 23:26 | amalloy | that's not going to make it less confusing |
| 23:28 | phenom_ | amalloy ... let's say you've got a list of email addresses and a system that receives requests to send out email ... everytime you get an email, you cycle through the list of addresses, send it to exactly one, then rotate the list |
| 23:29 | phenom_ | so: list = a@a.com, b@b.com, c@c.com ... request one get's mailed to a@a.com, then the next request to b@b.com etc. |
| 23:29 | amalloy | why would my system do that? i can't imagine a real-life scenario where i would say "here is an email, please send it to someone on this list but i'm not sure who" |
| 23:29 | phenom_ | that's beside the point |
| 23:30 | brehaut | phenom_: what requirement forces you to remove from anywhere in the list? |
| 23:30 | amalloy | i don't think it is. refs or no, if you introduce concurrency to this model your performance will be basically random |
| 23:31 | amalloy | like, i was thinking "maybe he's doing load-balancing for a set of servers" |
| 23:31 | amalloy | but you might as well just assign randomly in that case, it will all work out on average |
| 23:31 | brehaut | phenom_: is it some sort of priority requirement? |
| 23:31 | phenom_ | no priority |
| 23:31 | phenom_ | just round-robin |
| 23:32 | brehaut | its not round robin if you take randomly |
| 23:32 | phenom_ | well, server 4 may go down |
| 23:33 | amalloy | phenom_: so? keep an unordered set of servers and assign randomly to any that are still working. no reason to futz with keeping an ordered list |
| 23:34 | phenom_ | amalloy: the requirement is to do sequentially in the order they were added to the list |
| 23:35 | brehaut | phenom_: it sounds like you want a clojure.lang.PersistentQueue in some reference type |
| 23:35 | brehaut | or alternatively to restructure your program to run in an agent |
| 23:36 | brehaut | your third option is to not use a persistent queue type and switch to a java concurrent queue which is blocking |
| 23:36 | tomoj | wouldn't you need a dequeue? |
| 23:36 | phenom_ | brehaut: but how do i get the round-robin behaviour? dequeue then requeue ? |
| 23:37 | tomoj | er, deque |
| 23:37 | brehaut | phenom_: round robin is the consumeres taking turns |
| 23:37 | brehaut | im not sure how thats a data concern |
| 23:38 | tomoj | yyy ju'i nai |
| 23:38 | phenom_ | brehaut: the logic to forward requests to the appropriate server ... how would that be done in round-robin then ? |
| 23:38 | phenom_ | given a list of servers |
| 23:39 | brehaut | cycle your list of servers, send a message to each server to to get work, server requests work? |
| 23:43 | phenom_ | brehaut: the problem with that is given list [s1 s2 s3], when the first request comes it it should be sent to s1, when the second comes in (possibly in a different thread), it needs to go to s2 |
| 23:44 | phenom_ | meaning, the system doesn't know up front all the requests ... it's done as it's picked up off the network |
| 23:47 | amalloy | phenom_: how can it be a "requirement" that servers be assigned to strictly in order, when you have to be tolerant to them disappearing at any time? |
| 23:47 | brehaut | phenom_: i think we are talking passed each other now. i have no idea what you want that i havent mentioned previously |
| 23:47 | brehaut | i know that if i had n servers and 1 work queue, i would just use a blocking work queue |
| 23:48 | brehaut | and make the workers request items off it as fast as they could |
| 23:48 | brehaut | and not owrry about trying to implement some addition round robin scheduling |
| 23:48 | phenom_ | okay, maybe load balancing is the wrong anaolgy |
| 23:49 | phenom_ | how about a message queue ... you have n subscribers but you want an incoming message in a queue to be sent to exactly one and only one ... so you use a round robin system |
| 23:49 | brehaut | phenom_: i wouldnt. i would us a blocking queue |
| 23:50 | amalloy | indeed |
| 23:50 | brehaut | phenom_: the blocking queue ensures all the concurrency semantics around dequeueing one item to each requester, in order, and such that if there is no work to do, nobody spins |
| 23:50 | amalloy | what if one message were really long? or one server were really slow? round-robin makes no sense |
| 23:51 | phenom_ | subscribers are passive ... the messages need to be pushed over the network |
| 23:52 | amalloy | that's even more nuts. how will you find out if a subscriber crashes? |
| 23:52 | phenom_ | ack/nack expiry |
| 23:53 | amalloy | in the meantime you've wasted time sending him N requests he never got, and you've had to remember them so you can reassign them to someone else |
| 23:53 | amalloy | just make the subscribers ask you for data like brehaut says |
| 23:53 | phenom_ | assume the other :P |
| 23:53 | phenom_ | the problem is the cycling |
| 23:53 | amalloy | anyway apparently my being opinionated isn't solving your problem, and i don't have real ideas. afk |