#clojure log - Mar 13 2011

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

1:18 waxrose: >.>

1:19 scottj: I'm not very good at reading ascii art

1:21 waxrose: why's that?

1:23 scottj: lack of imagination I suppose

1:24 waxrose: What are you up to tonight?

1: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

1:26 waxrose: I've never had a chance to read that one.

1:26 Between class and doing every thing else.

1:30 scottj: reading's overrated

1:32 waxrose: how so?

1:33 I find reading the only way to progress outside of pure experience.

1:34 scottj: I find reading uninspired by experience produces poor comprehension and short retention

1:35 I'm skeptical of the value of reading not motivated by problem solving

1:39 waxrose: mmhmm

1:40 But then again, not every one reacts to stimulus the same way.

3:44 hiredman: ~search for rhickey

8:42 pyr: hi

9:02 nawk: gud morning

9:24 raek: CompilerException java.lang.NoSuchMethodError: clojure.lang.RestFn.<init>(I)V (autodoc.clj:1)

9:24 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 :(

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 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 or was renamed, so you'd have to read through the docs to see what's changed

13:19 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 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 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 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 ,(let [x 1] (meta ^{:foo x} [1 x 3]))

14:10 clojurebot: {:foo 1}

14:11 raek: but

14:11 ,(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 ,(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 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 *3

14:15 avdi: raek: gotcha. Makes sense.

14:16 raek: that is, the thing that is sent to the compiler

14:17 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 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 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 *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 ,((juxt str pr-str) (range 5))

15:48 * angerman rubs his eyes.

15:48 clojurebot: ["clojure.lang.LazySeq@1b554e1" "(0 1 2 3 4)"]

15:48 angerman: what for is clojure.string/join?

15:48 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 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 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 both of them take sep coll

15:54 angerman: amalloy: ahh, multi arity

15:54 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 I generally extend the soap client with a class of my own

16:44 jaley: @User ; (.getEvents *service*)

16:44 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 *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 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 &(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 *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 (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 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 http://groups.google.com/group/enlive-clj/browse_thread/thread/45e0e64f51ec6bdb?pli=1

16:58 look at cgrand's answer

16:58 first code snippet

16:59 brehaut: User: {:input :br} selects (inclusively) everything between an input and br

16:59 User: oh

16:59 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 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 thats from the readme

17:10 under 'syntax'

17:11 roughly parenthisis basicly (which CSS doesnt have)

17:13 User: so set is used for OR

17:13 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 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 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 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 but i think you are right that it is actually an and in this case

17:20 * brehaut regrets discussing precise things before coffee

17:20 User: that's what confused me immensely

17:21 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 got to test this

17:22 brehaut: amalloy: oh crap

17:22 User: good plan

17:25 User: http://pastebin.com/5AfExvj5

17:25 look at this

17:26 the difference between [:ul :.content] [:body :.content] and [[:ul :.content]]

17:26 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 notices are supposed to be lower-impact than regular messages, not higher

17:38 tufflax: oh, is that so :P

17:39 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 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 A more sophisticated ripoff, but a ripoff nonetheless.

17:46 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 amalloy: Don't we have a contributor list that isn't on my blog? Like, in the README?

17:51 If so, we should add brehaut to that. I never intended to edit that blog post every time someone committed to sexpbot.

17:52 I'll check and do that in a moment. Got to get my environment going.

17:56 brehaut: But yes, Android is awesome. :>

17:56 brehaut: ha

18:01 nickik: What does this mean in java

18:01 int iterations = 1 << (maxDepth - depth + minDepth);

18:02 amalloy: << is left-bit-shift

18:02 User: it's a retarded shift trick

18:02 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 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 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 (most of my programs use lists and vectors of size around 10 and there clojure is around 40 times slower than java)

18:21 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 call to shiftLeft can't be resolved.

18:22 (its a reflection warning)

18:23 User, why do you think that is?

18:23 User: yeah and that code uses unchecked ops everywhere

18:24 no idea

18:24 immutable data and checked arithmetrics are usually the biggest slowness

18:24 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 yes

18:25 this code uses (int x) and such a lot though

18:25 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 and python :P

18:27 raek: nickik: you can't pass primitives over function boundaries, yes

18:27 ...in 1.2

18:27 User: and erlang

18:27 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 it's quite non-idiomatic too

18:30 nobody actually writes clojure like that imo

18:30 nickik: does not matter its a benchmark

18:31 Was a stupid idea to use benchmarking for a school project

18:31 its way to hard and does not look impressiv

18:32 User: indeed

18:32 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 in java I just write normal code and it usually doesn't run much slower than hand optimized

18:33 with clojure difference is quite significant

18:34 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 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 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 slow

18:36 clojurebot: Gabh mo leithscéal?

18:36 amalloy: User: i disagree with your claim about map/pow

18:36 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 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 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 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 usually when I use recur

18:42 but it sure comes up more often than anything else

18:42 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 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 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 (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 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 because most of those functions are supposed to work for infinite sequences and stuff like that

18:51 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 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 look at java stats

18:56 it beats most languages

18:56 clojure none

18:56 ossareh: morning 'all

18:57 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 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 ?

19:00 User: but that's beside the point

19:01 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 my java code is usually 3 - 200 times faster

19:02 most often in 10-40 range

19:04 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 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 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 (GET "/" [{:headers {"Content-type" "text/plain"}} "Response text"]

19:16 tomoj: clj files aren't in slime-repl-mode

19:16 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 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 er, ignore that

19:25 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 ..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 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 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 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 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 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 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 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 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 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 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 taken from the bratko book

20:58 its trivial in prolog :)

21:01 dnolen: even using fogus's unifier i still have to be fairly explicit about the solving steps

21:01 dnolen: https://github.com/brehaut/monkey-and-banana if you are interested

21:02 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 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=

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 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 also the paper is by oleg, they man has a brain the size of a small galaxy

21:17 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:18 * brehaut has too many projects

21:20 * __name__ finishes too little projects

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 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 the println's are only for debugging though

21:46 amalloy: there are two ways to fix this problem

21:47 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 one is that you've stuck an if-not inside of a doto form where it doesn't realy belong

21:48 this is expanding into (if-not document (nil? ...) ((println ...)) (.vintage ...))

21:50 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 you're looking for (do (println x) (println y))

21:51 fmw: amalloy: ok, thanks, that fixes it

21:51 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 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 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 did you already make the . point?

21:58 amalloy: no

21:58 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 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 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 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 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 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 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 er, on accident

22:19 joshua__: it's been like four years but i used to be pretty solid on them

22:19 fmw: amalloy: ok :)

22:19 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 and its selector based

22:22 joshua__: brehaut, I'm already using it for the scraping. See:

22:23 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 (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 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 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 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 er hm

22:50 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 .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 the macro

22:51 amalloy: fmw: see the last two lines

22:51 you mean age-field, not age

22:51 fmw: amalloy: ah yes

22:52 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 if you wanted to make it into a function and pass the string manually i guess that would be okay with me

22:55 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 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 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 nevermind, it's 30 lines of code :)

23:00 * amalloy is blissfully unaware of all this lucene stuff

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 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 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 being without keywordize when you need it is certainly ugly

23:14 amalloy: heh

23:15 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 :(

23:20 phenom_: i was using a [index, content] pair

23:21 "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 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 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 like, i was thinking "maybe he's doing load-balancing for a set of servers"

23:31 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 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 or alternatively to restructure your program to run in an agent

23:36 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 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 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 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 i know that if i had n servers and 1 work queue, i would just use a blocking work queue

23:48 and make the workers request items off it as fast as they could

23:48 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 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 just make the subscribers ask you for data like brehaut says

23:53 phenom_: assume the other :P

23:53 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

Logging service provided by n01se.net