#clojure log - Jun 06 2011

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

0:02 Raynes: I'm going to have to start going door to door and sharing the gospel of cake.

0:03 zakwilson: apache commons-email is fantastic.

0:03 zakwilson: After going through all the Clojure libraries, none are all that satisfactory, and commons-email is fantastic at one thing: sending email.

0:05 zakwilson: Raynes: five minutes of playing with Postal is starting to convince me of that. I don't have very sophisticated needs, but this seems to be unable to handle encrypted smtp.

0:06 Why do so many Java libraries make you create an object and use setters instead of passing the values for the fields to the constructor?

0:07 offby1: mutation is the Way and the Light™

0:07 Raynes: zakwilson: Postal wraps command-line tools for mail stuff, and I'm not convinced that calling out to an external application is a very good thing.

0:07 lawfulfalafel: I keep seeing people mentioning marmalade on posts about clojure, but I don't really get what it is

0:07 and googling for it isn't really helping me understand it any better

0:08 Raynes: zakwilson: However, since it calls out to msmtp and such, chances are you can configure that to do whatever you want. I'd much rather there just be a java-mail wrapper or something though.

0:08 technomancy: lawfulfalafel: it's clojars for elisp

0:08 Raynes: lawfulfalafel: Marmalade is an elisp package server. It's just a public place where people can upload their elisp packages for use with ELPA.

0:09 zakwilson: Raynes: postal claims to be a javamail wrapper, but it seems unable to authenticate with gmail so it sucks.

0:09 lawfulfalafel: ah, thank you

0:10 Raynes: zakwilson: I seem to recall needing something that it didn't support on the javamail side.

0:11 zakwilson: Raynes: then javamail is not very complete.

0:11 technomancy: lawfulfalafel: while elpa.gnu.org is more like maven central

0:12 Raynes: zakwilson: Actually, it was the other way around. Postal just didn't support doing whatever it was. It doesn't really seem to wrap javamail very thorougly.

0:13 zakwilson: Raynes: a brief glance at the source of Postal has me agreeing with you. It looks very bare bones. I'll take your word for it about apache commons.

0:13 Raynes: zakwilson: I don't know if it supports encrypted stmp, but it's certainly easy to use.

0:15 zakwilson: Raynes: the docs suggest that it does.

0:16 lawfulfalafel: okay, I installed cake, but I don't get how to run it

0:16 I've never used ruby or gems before

0:16 zakwilson: Raynes: what do I put in my project.clj to make lein or cake download it from wherever they get things? (so far, I'm treating things that interact with Maven as magic)

0:17 Raynes: zakwilson: [org.apache.commons/commons-email "1.2"]

0:17 lawfulfalafel: but I know it's at /var/lib/gems/1.8/bin/cake

0:17 Raynes: lawfulfalafel: The command is 'cake'.

0:17 zakwilson: Raynes: Thanks. My guess was so close, yet so far.

0:17 Raynes: If that doesn't work, then put /var/lib/gems/1.8/bin on your PATH

0:18 lawfulfalafel: uh, could you perhaps remind me how to do that?

0:18 I know $PATH=/blah/blah/blah sets it

0:18 but I forget how to append to it

0:18 Raynes: On Linux?

0:18 lawfulfalafel: yup

0:18 Raynes: Do you have a ~/.bashrc file?

0:19 lawfulfalafel: yes, but it's been automatically generated

0:19 at least I don't remember touching it

0:19 Raynes: Put this in it: export PATH=/var/lib/gems/1.8/bin:$PATH

0:20 Then restart your terminal (to restart bash) or run this: . ~/.bashrc

0:22 lawfulfalafel: Raynes: I tried that and got "bash: /home/kirby/.bashrc: Permission denied"

0:23 so I just typed "bash" again to just launch another one, but for some reason it still can't find cake

0:23 Raynes: lawfulfalafel: echo $PATH

0:24 lawfulfalafel: /var/liv/gems/1.8/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

0:24 devn: /var/liv

0:24 Raynes: Typo.

0:24 lawfulfalafel: lol

0:25 thank you devn

0:25 thank you Raynes, it works now

0:26 just out of curiosity, does cake support syntax hilighting?

0:26 Raynes: No problem. We also have a channel specifically for cake if you have any other problems. #cake.clj

0:26 devn: now go forth and write clojure with great ferocity

0:27 Raynes: cake's REPL supports more than most, but it doesn't support syntax highlighting. For that, you want an editor. Emacs or any of the IDEs (Eclipse + Counterclockwise, Netbeans + Enclojure, etc).

0:27 devn: or you can print your code on paper and get a few colored highlighters

0:27 Raynes: devn: Or M-x print-buffer

0:28 devn: 1up

0:28 lawfulfalafel: well thanks again guys

0:28 gn

0:28 devn: im going to bed also

0:28 good night all

0:58 korny: anyone know if there's some way to run "lein midje" so it automatically re-runs tests on file changes?

1:00 - mostly, I'm trying to avoid the startup time; it's a slow process re-running manually

1:06 technomancy: korny: that's what lein interactive is for

1:07 well, really that's what lein swank is for; lein interactive is just for folks who don't use swank for whatever reason.

1:07 korny: cool - so "lein interactive" will let you run 'midje' repeatedly.

1:07 technomancy: yup

1:08 korny: I'm not using swank for now - I keep meaning to re-learn emacs, but somehow I keep failing.

1:08 technomancy: sure; one step at a time

1:08 korny: I was a big emacs used in the '90s, but somehow these days I'm an IDE junky. Especially when jumping from language to language.

1:08 technomancy: midje should make it easy to run its tests from the repl too

1:08 korny: s/used/user

1:08 sexpbot: <korny> I was a big emacs user in the '90s, but somehow these days I'm an IDE junky. Especially when jumping from language to language.

1:09 technomancy: with clojure.test you can just do (run-tests) in the repl; hopefully midje has an equivalent

1:11 korny: just running 'midje' in lein interactive is working. thanks!

1:11 technomancy: cool

1:15 korny: hmm - nope, 'midje' works the first time, the second time I get "Couldn't connect".

1:16 technomancy: hm; it could be the midje plugin for leiningen exits

1:17 perhaps the author of midge didn't realize that the task needs to return an integer rather than calling System/exit directly

1:22 korny: the source is short - I'll ave a look.

1:27 hmm - got part way there but other stuff is screwing up. This is getting beyond me - might ask the midje author.

1:29 technomancy: bzzzt--do not want: https://github.com/marick/Midje/blob/master/leiningen/midje.clj#L61

1:32 actually with subprocesses it's a bit more tricky, but there's a flag you can check to see if you need to exit; I'll open an issue on midje

2:57 void_: hi this is my second day with clojure

2:57 why does this (.getName String) throw this: #<NoSuchFieldException java.lang.NoSuchFieldException: getName>

3:01 justinlilly: void_: is it possible that String doesn't refer to what you thought?

3:02 ,(.getName String)

3:02 clojurebot: "java.lang.String"

3:02 justinlilly: should work.

3:02 ,(.. System (getProperties) (get "os.name"))

3:02 clojurebot: java.security.AccessControlException: access denied (java.util.PropertyPermission * read,write)

3:19 xkb: hi

3:20 void_: so there's something wrong with my local installation

3:21 xkb: I'm trying to solve this telephone number mnemonics puzzle in Clojure. Goal is to find a word (or as an extension, words) for a given number. I implemented it like so: https://gist.github.com/1009867 and that works. However loading the whole dictionary into the map takes ages. Any ways to improve this code?

3:47 fliebel: xkb: Do you have an explaination about the problem?

3:54 xkb: fliebel: yes

3:54 say your telephone number is 111, then the solution would be aaa or aAa

3:55 if aaa or aAa would be words

3:55 other example: "530189010363" ["adenogenesis"]

3:55 fliebel: xkb: So basically you try to form words from the chars on the phone keys?

3:56 xkb: correct

3:56 like T9 on the old nokia's

3:56 fliebel: so, like 1-800-my-apple ;)

3:56 bpr: then how does 1 => a and 5 => a ?

3:56 fliebel: xkb: Yea, your table looks weird.

3:57 Why is it like { 0 "e" 1 "jnq" 2 "rwx" 3 "dsy" 4 "ft" 5 "am" 6 "civ" 7 "bku" 8 "lop" 9 "ghz"} and not {1 "abc ...} like normal phones over here do?

3:58 xkb: fliebel: ah, that was just parameterisation

3:58 over here it's a "" 2 "abc" for example

3:58 bpr: still, on what phone does 1 and 5 both have a?

3:58 xkb: so app. it's region specific

3:59 I meant 1 "" 2 "abc" btw

3:59 fliebel: xkb: Ah, okay. Have you looked a tries? A nice one using assoc-in: http://stackoverflow.com/questions/1452680/clojure-how-to-generate-a-trie

3:59 xkb: yup

4:00 but as I understand it maps are implemented as trees anyways

4:00 so just inserting number word tuples should work just as well

4:00 emphasis on the should ;)

4:01 bpr: trie =/= tree

4:01 fliebel: xkb: But with a trie you get to take advantage of the alphabet ;)

4:01 bpr: tries are built from trees, but their a special purpose data structure

4:01 they're*

4:01 ^

4:03 xkb: I started out with something very similar to the SO code, but changed it back to a simple map

4:03 I'm wondering why it takes so long to build the {number [word]} map

4:04 fliebel: xkb: You mean, you are generating all possible words for all possible numbers? :-o

4:05 xkb: fliebel: other way around

4:05 I generate numbers for all words in the dict

4:05 that compact it to all words for the numbers generated

4:06 and theres 234936 words

4:07 fliebel: Ah, I see. I'll have some breakfast and have a look at it.

4:07 xkb: cool :)

4:07 maybe I should try the Trie meanwhile ;)

4:40 fliebel: xkb: How long does yours take?

4:41 xkb: for the full dict it takes more time then I care to wait for :)

4:42 and that's just the convert/compact function

4:42 reading the dict and transforming it to number/word pairs is fast

4:43 or rather parts of it are lazy oc :)

4:44 fliebel: xkb: so, all you're doing there is combining word with the same number, right?

4:44 xkb: correct

4:45 I recurse over all the numbers, recombining words if the number is already in the target map

4:46 I use get-in to find numbers in the new map, and assoc to update an existing number [word] pair

4:46 fliebel: xkb: I'd use merge-with

4:46 * xkb does (doc merge-with)

4:47 xkb: ah

4:48 fliebel: I run out of memory before I even v=created the full map, btw :(

4:48 xkb: :(

4:49 bpr: so, you'll need to store a trie on disk

4:49 xkb: the problem is you cant even use integers as key: telephonenumbers might start with a 0

4:56 merge-with is quite nice :)

4:59 40k words is still doable

6:05 fliebel: xkb: I got something trie based, how are you doing?

6:10 xkb: had to do some real work in the mean-time

6:10 fliebel: https://gist.github.com/1010027

6:10 xkb: rewrote it to just use merge-with

6:10 but that doesnt really help

6:11 fliebel: xkb: Mine is fast enough for me, only it does not include all words for a give number.

6:11 If I did that, I ran out of memory, and it took much longer.

6:11 xkb: ah, I had the same with my first Trie based attempt

6:12 hmm why doesnt your build-trie function blow stack?

6:13 with the recursion there

6:17 fliebel: xkb: because the recursion depth is only max word length.

6:19 xkb: ah now I see, not that familiar with the use of comp

7:14 msappler: hello

7:15 what is the best way for a macro that does some assertions and then expands to another function call to store the other function?

7:15 I mean this function from my blog: http://resatori.com/advanced-keyword-function#comments

7:16 when i let the macro expand to the function I get an ExceptionInitializerError

7:17 so basically I just want to convert this macro: https://gist.github.com/999256

7:18 so that it runs its checks at compile-time ...

7:46 hoeck: msappler: checking at compile-time works only in those cases where the arguments are known at compile time

7:46 eg. when you call such a function directly (keyfn :arg1 'value)

7:48 and does not work when you pass the function around: (map keyfn args)

7:50 msappler: yes i do that always

7:50 calling it directly

10:05 ilyak: hi *

10:06 Suppose I have a class, CSVReader ^^

10:06 What's the best way to implement seq protocol for it? I can't touch the class itself

10:09 stuartsierra: Unfortunately, seq is not a protocol. It's just an interface.

10:09 All you can do is write a function that takes a CSVReader and returns a seq.

10:11 ilyak: stuartsierra: How does clojure do it for, e.g., String?

10:11 stuartsierra: Conditionals for each special case in the implementation of seq.

10:11 All that stuff predates the introduction of protocols.

10:12 Probably someday it will be replaced by protocols.

10:16 chouser: so all you need to do is provide a new function that returns a seq for your CSVReader

10:21 cemerick: ilyak: see iterator-seq and enumerator-seq for examples of fns that return seqs over mutable things

10:21 if your CSVReader is returning rows via an iterator, then you actually have no work to do

10:26 stuartsierra: I think we lost him, guys.

10:30 ilyak: cemerick: I just did (repeatedly #(.readNext csv-reader))

10:30 Yet to actually try

10:30 How would I access enum values of nested enum belonging to some class?

10:31 SqlUtils/Columns/ALL doesn't work

10:31 and no idea how to import it

10:32 cemerick: that'll work, though you'll need to handle the EOF condition, and use take-while (or some equivalent) to keep only the useful data.

10:33 SqlUtils$Columns/ALL?

10:33 SqlUtils$Columns is the class you'd import

10:34 ilyak: Okay, figured it out, thanks

11:18 timvisher: hey all

11:18 what would be the easiest way to compare 2 sequences in a position independent manner

11:18 ?

11:19 so that (= [1 2 3 4] [4 3 2 1]) would return true

11:19 stuartsierra: Turn them both into sets.

11:19 manutter: ,(= (into #{} [1 2 3 4]) (into #{} [4 3 2 1])

11:19 clojurebot: EOF while reading

11:20 manutter: ,(= (into #{} [1 2 3 4]) (into #{} [4 3 2 1]))

11:20 clojurebot: true

11:20 timvisher: which should only break if there are duplicates

11:20 and if there are never duplicates then maybe they should always be sets...

11:20 * timvisher thinks

11:21 manutter: Maybe you could also map the seqs into hashmaps, with the count as the value

11:21 [1 2 3 2 1] => {1 2, 2 2, 3 1}

11:21 timvisher: it's only a vector because i'm used to the `[` seq literal

11:21 there's really no reason it shouldn't be set

11:21 I don't want duplicate entries

11:22 manutter: sure, that'll make things easier for you then

11:22 timvisher: so that's probably a good idea

11:22 manutter: sure

11:22 timvisher: ya'll rock :)

11:26 cemerick: timvisher: just keep in mind that your literals can't have dupes in them already…

11:26 ,#{3 2 3}

11:26 clojurebot: Duplicate key: 3

11:26 timvisher: cemerick: indeed

11:26 none of them do

11:26 i'm really falling victim to what I always do in java

11:26 cemerick: That wasn't the case a long time ago.

11:26 timvisher: i default to List there without really thinking about the data structure

11:27 edw`: Hey, think I found a bug in clojure's swank support: evaling "(keys [0 1 2])" gives an elisp error while evaling "(keys 42)" throws one into the slime debugger.

11:27 timvisher: or rather, the data that I'm trying to structure

11:27 cemerick: Each time I get tagged by it (mostly by not paying attention), I wonder why dupe checking is being done at all.

11:27 timvisher: and then i realize way down the line that it really should have been a map or a set or whatever and i have to got through a huge refactoring exercise

11:30 stuartsierra: cemerick: It used to be possible to create literal array maps with duplicate keys, rather unexpectedly.

11:32 cemerick: Yeah, I remember that as well. I can see the utility of both behaviours, especially w/ fns that destructure kw args.

11:33 chouser: it was possible to have innocent-looking code that produced collections that were internally broken and would behave weiredly at much later times

11:33 hard to debug

11:35 cemerick: Sure, that's bad.

11:58 stuartsierra: that BIGINT notation is…unfortunate

11:58 stuartsierra: yes

11:58 I'm hoping it ends up temporary.

12:01 cemerick: As in, remove the notation entirely? I don't see the downside to using #<BigInteger 1234>, either.

12:02 All big ops will return BigInts anyway; you really need to try to get a BigInteger.

12:03 stuartsierra: Either remove 1234BIGINT or replace it with 1234BIGINTEGER

12:03 cemerick: Besides, two notations for functionally equivalent (ex. interop) concrete types. Bleh.

12:37 renamecontains: ,(println "Testing 123")

12:37 clojurebot: Testing 123

12:38 renamecontains: &(println "Testing 321")

12:38 sexpbot: ⟹ Testing 321 nil

12:39 offby1: I took Testing 201 but changed my major to English Lit after that

13:15 `fogus: dnolen: Jekyll sound like a good way to start

13:18 dnolen: `fogus: cool! I'll try to create the gh-pages branch later today.

13:20 `fogus: dnolen: Do you know if I have commit rights?

13:20 * `fogus hasn't tried yet

13:20 dnolen: `fogus: I thought all clojure org devs automatically have commit rights.

13:21 `fogus: dnolen: I'm sorry, I meant admin rights. It appears I do not... and that's probably not needed anyway

13:22 dnolen: `fogus: oh yeah, I don't have admin rights either.

13:22 `fogus: dnolen: I think there is a quick way to create a gh-pages branch, but it requires admin

13:23 dnolen: `fogus: yeah I'm pretty sure there is, perhaps we can get someone to do that for us?

13:23 stuartsierra: just branch and push

13:24 `fogus: stuartsierra: That's it? Cool!

13:24 stuartsierra: It's an ordinary Git branch like any other.

13:24 dnolen: `fogus: if you want to setup the branch, that's fine by me.

13:25 `fogus: stuartsierra: With some special config files I imagine

13:25 (jekyll config files that is)

13:26 Oh I see now. My Potion repo has a gh-pages branch

13:26 stuartsierra: I don't know much about Jekyll.

13:28 `fogus: http://fogus.github.com/potion/

13:28 Jekyll seems pretty nice on 10 minutes of investigation (but what doesnt)

13:29 stuartsierra: From what I've seen at Relevance, it's good for very small sites (5-10 pages) but gets cumbersome for larger sites.

13:30 `fogus: Well, we can migrate to Enterprise Jekyll when we cross that threshold :p

13:30 stuartsierra: ha

13:31 You mean Service-Oriented Enterprise JekyllBeans Professional.

13:32 `fogus: Oh great! Another certification for me!

13:32 * `fogus checks Learning Tree

13:32 stuartsierra: :)

13:35 * `fogus back to work

14:16 Krato`: imagine I have something like (defn fib [n] (if (< n 2) n (+ (fib (dec n)) (fib (dec (dec n))))))

14:16 I can speed this up with

14:17 (def fib (memoize (fn [n] (if (< n 2) n (+ (fib (dec n)) (fib (dec (dec n))))))))

14:17 is there any other way to insert memoize like this

14:18 for instance in this case I don't have metadata like parameter list on the resulting function

14:22 stuartsierra: Memoize works on any function. You don't need to know the arguments.

14:23 hiredman: stuartsierra: sure, but he wants to preserve the doc string and args and other metadata you get when using defn

14:23 Krato`: you can define the function using defn and then alter-var-root to memoize

14:24 but memoize doesn't actually work for self calling fns created with defn

14:24 Krato`: it does

14:25 the one I listed works

14:25 hiredman: it doesn't

14:25 Krato`: lol

14:25 manutter: does it work as memoized, or does it just work as if unmemoized

14:25 hiredman: becuase (defn foo [x] ...) expands to (def foo (fn foo [x] ...))

14:26 which means calls to foo in the function body won't go through the var, but use the lexical binding

14:26 so if you memoize the function in var it doesn't matter

14:26 manutter: but you can explicitly call the var in your function, and then it will work

14:26 Krato`: the one case I listed works

14:27 hiredman: Krato`: doesn't

14:27 manutter: (def fib (memoize (fn [n] (if (< n 2) n (+ (#'fib (dec n)) (#'fib dec (dec n))))))))

14:27 Krato`: it does, enter both listed into the repl and time them

14:27 pjstadig: does too ∞ +1

14:27 manutter: Assuming I remembered the correct reader macro for calling a var

14:27 pjstadig: Krato`: were you entering as (def ...) or (defn ...)

14:28 hiredman: Krato`: pardon me, I assumed you meant the case you mentioned rewritten using defn

14:28 manutter: that will work

14:28 Krato`: first one I listed take 13000 msec to calculate fib 38 and second one takes 0.14 msec

14:28 pjstadig: hiredman is saying that (defn ...) wouldn't work

14:28 hiredman: this is a particular interaction between defn and memoize

14:28 def and fn is fine

14:28 unfornately defn is the only easy way to get all the cool metadata

14:29 technomancy: hiredman: do you know if there's a good reason for that?

14:29 manutter: if you use #'fib in your defn for memoize, that's a workaround, isn't it?

14:29 hiredman: manutter: it will make your fib slow

14:29 technomancy: I opened an issue about fn not having arg/docstring meta; no idea if it's by design

14:30 Krato`: well 2 things bother me with my solution

14:30 hiredman: the whole metadata on fn situation seems very iffy

14:30 Krato`: 1. lack of metadata

14:30 2. I don;t understand why def + fn works

14:30 I mean the variable doesn't exist at the time of function evalution or something?

14:31 scgilardi: I recall reading that fogus is on the case for a helper to help making defn-like macros easier to write by getting all the metadata, optional-doc-string, etc. right behind an API.

14:32 Krato`: need to make defmemofn macro :P

14:32 pjstadig: yeah `fogus_away how's that coming??? :)

14:32 hiredman: Krato`: the compiler creates #'fib before compiling the function setting the value of the var to the function

14:32 Krato`: so basically it's (define, then fn then assign to var

14:33 mrBliss`: http://clojuredocs.org/clojure_contrib/clojure.contrib.def/defn-memo

14:33 scgilardi: yeah that. :)

14:34 Krato`: o nice

14:34 hiredman: mrBliss`: that has the problem I just described

14:34 Krato`: gotta learn what contrib has to offer

14:34 hiredman: if you look at the source it expands to defn + alter-var-root

14:34 mrBliss`: hiredman: sorry, I didn't follow the whole conversation

14:34 hiredman: which means that self calling functions will not be properly memoized

14:35 * hiredman won't add a comment since he doesn't want to figure out how to login to clojuredocs

14:36 Krato`: memoizing recursive stupid O(2^n) implementations is the best thing to memoize :)

14:38 preserves clarity of the original definition of the problem and evaluates with same speed as iterative implementation :)

14:46 `fogus_away: scgilardi: You mean this? https://github.com/clojure/tools.macro/blob/master/src/main/clojure/clojure/tools/macro.clj#L273

14:48 scgilardi: `fogus_away: looks right. what I saw was an exchange between you and stuart halloway about it. looks like it's done. :)

14:48 `fogus_away: scgilardi: Recommendations welcomed. :-)

14:49 hiredman: something should be done about broken memoize+defn

14:49 scgilardi: hiredman: would a fixed defn-memo do the trick? it seems feasible.

14:50 hiredman: possibly, I wonder if rich would re-evaluate the need to lexically bind the function now that vars are not dynamic

14:51 scgilardi: (although the caching policy on a naked memoize is such that I suspect defn-memo has little chance of getting pulled into clojure)

14:52 pjstadig: hiredman: yeah but i'm not sure how that would work since the var doesn't exist when the fn is compiled

14:52 perhaps there's a way around it

14:52 scgilardi: hiredman: is the alternative to compile to var references? maybe only in the case where the fn has no name of its own?

14:52 hiredman: pjstadig: oh, the comopiler already takes care of that

14:52 defn didn't always expand that way

14:53 pjstadig: ah

14:53 hiredman: the way a def is compiled allows the body of the value to refer to the var that is created

14:53 pjstadig: fixed point combinator? :)

14:54 hiredman: compilation just generates the code to def the var, it doesn't deref it, so the var can exist and be empty

14:54 which is effectively what the compilation of def does

14:55 Krato`: btw I did the Euler Project problem 15 with this memoize trick.

14:55 you have to count the number of paths down a 20x20 grid going only down and right

14:56 using naive implementation which forks at each node I couldn't get result even though I ran it 6 hours

14:56 added memoize and it got solved in 0.something ms

14:57 the problem is of size "choose n out of 2n" which is something around squrt(n) * 2^2n-1

14:58 so around O(4^n)

14:59 pjstadig: http://en.wikipedia.org/wiki/Dynamic_programming

14:59 hiredman: you should do it as a grid of agents

15:05 Krato`: hehe grid of agents

15:07 to be fair I haven't yet grasped how agents and futures work and when I should use one or the other

15:08 also pmap was behaving weirdly, only doubling performance on 8 cores

15:18 hiredman: Krato`: well, linear performance grow is the dream, but with coordination overhead, etc, it can heardly be expected

15:19 Krato`: I expected it not to be exactly 8

15:19 but 2? cmon

15:19 I recall it was only using 25% CPU

15:19 in task manager

15:20 so looks like pmap only utilized 2 cores

15:29 http://clojuredocs.org/clojure_contrib/clojure.contrib.apply-macro/apply-macro

15:29 why is this in contrib if it's evil?

15:30 technomancy: because contrib doesn't have high standards

15:30 or didn't, I guess

15:30 hiredman: because contrib is also evil

15:30 ohpauleez: technomancy: right, I would say old contrib is that way

15:30 but I'm sure apply-macro exists for composition

15:34 Krato`: let's say I have this: I have a function that returns a function that returns a function etc... and I have a vector of arguments which I would like to apply to each of these 1 argument per function

15:34 how would I do that

15:35 gfrlog: (reduce #(%1 %2) f args)

15:35 is my guess

15:36 ,(let [f (partial partial +)] (reduce #(%1 %2) f (range 10)))

15:36 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

15:37 gfrlog: yeah that didn't do what I wanted it to :(

15:37 I mean the previous code is probably still fine, but (partial partial +) is not a function like the one you described

15:37 so I don't have an easy idea for testing it

15:57 TimMc: ,(((partial partial +) 3) 5)

15:57 clojurebot: 8

15:57 TimMc: ,((((partial partial partial +) 3) 5) 10)

15:57 clojurebot: 18

15:58 TimMc: ,(let [f (nth (iterate partial +) 10)] (reduce #(%1 %2) f (range 10)))

15:58 clojurebot: java.lang.RuntimeException: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$partial

15:59 TimMc: Ah, not quite.

15:59 Need a comp and apply or something.

16:02 Krato`: here's why

16:02 vectors maps and sets are also functions

16:02 TimMc: ,(let [n 10, f ((apply comp (take n (repeat partial))) +)] (reduce #(%1 %2) f (range n)))

16:02 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$partial

16:02 TimMc: meh

16:02 Krato`: so using this and a sequence of indexes and keys would allow one to work with nested collections

16:03 gfrlog: Krato`: you know about get-in right?

16:04 surely the functional nature of a set is little help in this situation

16:06 TimMc: ,(let [n 10, f (apply partial (concat (take (dec n) (repeat partial)) [+]))] (reduce #(%1 %2) f (range n)))

16:06 clojurebot: 45

16:06 TimMc: \o/

16:07 gfrlog: TimMc: try writing it where f does not depend on n, and to get the final value you call the last function with no args

16:07 TimMc: point

16:07 gfrlog: point?

16:07 clojurebot: the point of moby dick is "be yourself"

16:08 TimMc: gfrlog: that is, "you have a good point"

16:08 gfrlog: ah okay

16:12 I was thinking maybe you could achieve that with some inherent property of partial (that's what I was going for on my first try), but now I'm thinking you'd need an (if), or two different method bodies :(

16:12 ,(partial +)

16:12 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$partial

16:12 gfrlog: yeah; I was thinking maybe that would return 0

16:13 which would be strange.

16:16 TimMc: Hmm, I don't see why (partial f) should throw.

16:16 It is not ill-defined -- just return f.

16:16 gfrlog: right

16:17 I agree that would seem better

16:17 TimMc: &(source partial)

16:17 sexpbot: java.lang.Exception: Unable to resolve symbol: source in this context

16:17 TimMc: $source partial

16:17 sexpbot: partial is http://is.gd/zZxzDD

16:17 hiredman: I think you could argue either way, but the sort of person who uses partial is most likely to argue it should not throw

16:18 TimMc: The case where I see this happening is (apply partial f args)

16:18 hiredman: args is nil

16:18 TimMc: yeah

16:32 gfrlog: ,(map #(-> 10 range % class) [seq sequence])

16:32 clojurebot: (clojure.lang.ChunkedCons clojure.lang.LazySeq)

16:41 TimMc: ,(doc sequence)

16:41 clojurebot: "([coll]); Coerces coll to a (possibly empty) sequence, if it is not already one. Will not force a lazy seq. (sequence nil) yields ()"

16:42 gfrlog: TimMc: will we ever know all of the clojure.core functions?

16:42 TimMc: ,(map (juxt seq sequence) [nil () [1]])

16:42 clojurebot: ([nil ()] [nil ()] [(1) (1)])

16:55 void_: what database (sql or nosql) do you use for your clojure projects?

16:57 gfrlog: void_: I have used MySQL and Couch

16:57 technomancy: lucene

16:57 void_: so this REST API of couch, that sounds to me like something annoying

16:57 technomancy: I've only used couch from elisp, but it was very pleasant there.

16:58 gfrlog: void_: if you have a good wrapper library then it's fine. It's quite convenient if you're going to call it from client-side JS

16:58 void_: well I think I'm gonna compare clojure wrappers and see which one is most popular

16:58 gfrlog: void_: clutch was good I think. I didn't use it too extensively.

16:59 void_: gfrlog: well, I'm not. I want to build a JS app, but use WebSocket instead. (For fun, you know ;))

16:59 gfrlog: but the couch API is decently simple, so clutch probably does a good job

17:00 void_: my opinion is that if you're not planning on ever using couch in a big cluster, then it's probably not worth it. It'll be fine if your data model is real simple, but it sacrifices a lot of functionality to get the scalability

17:00 void_: well thanks guys

17:00 gfrlog: yep

17:01 void_: is there any web app example built with clojure?

17:02 cemerick: gfrlog: The basics of the couch api are simple, but it gets pretty arcane (and ill-documented) as you wade into the more recent stuff.

17:02 gfrlog: cemerick: I think there are some things it could do better, like url rewrites

17:02 cemerick: (this coming from a contributor to clutch, FWIW)

17:03 gfrlog: cemerick: now that I think about it more, I don't mind couch so much as I do couch-apps

17:03 cemerick: ah

17:03 the couchapp stuff is insane IMO

17:04 gfrlog: I tried building a couch app or two and there were way too many times where the answer to "how can I do X?" was "nope."

17:04 Krato`: so insane in what way?

17:05 cemerick: That's what happens when you nail yourself up with javascript.

17:05 * cemerick is trolling a bit :-P

17:05 gfrlog: cemerick: javascript is an orthogonal issue, which is remedied a bit with coffeescript

17:05 cemerick: if couch ran only clojure, I'd still have the same complaints

17:05 technomancy: cemerick: I can see a sweet spot there if you got users to run couch locally

17:05 hiredman: gfrlog: syntax

17:06 technomancy: which all new ubuntu installs do

17:06 hiredman: gfrlog: the runtime cannot be fixed by a preprocessor

17:06 gfrlog: hiredman: right, thus "a bit"

17:06 cemerick: Krato`: Writing anything besides DOM glue with javascript is pretty tortuous.

17:06 gfrlog: technomancy: that turns into a security headache

17:07 technomancy: gfrlog: you could still do plenty of useful stuff only listening on

17:07 gfrlog: technomancy: At least if you don't have a bijection between users and couch instances

17:07 technomancy: oh, for multiuser boxes; sure.

17:08 cemerick: gfrlog: true enough. The app model's quasi-political objectives get in the way of my building useful things.

17:10 VT_entity: hey all

17:10 gfrlog: hey

17:10 VT_entity: I'm having trouble installing Clojure

17:11 gfrlog: have you tried leiningen?

17:11 VT_entity: no

17:11 that was going to be my last resort- I usually don't like running other people's install scripts on my box

17:12 gfrlog: ah okay then; so what do you mean by "install"?

17:12 VT_entity: I tried to use counterclockwise from Eclipse

17:12 it's giving me problems whenever I try to :use a library

17:12 aaand then I tried to install with git

17:13 gfrlog: if you want to use Eclipse, I can't help. If you just want to run clojure any way possible, you shouldn't need anything other than the jar (and java installed)

17:13 VT_entity: but I would also need clojure-contrib.jar, right?

17:13 gfrlog: if you want to use some of those libraries, yes

17:13 VT_entity: don't I have to add both to my classpath somehow before I (:use (clojure.contrib...))

17:14 gfrlog: yeah

17:14 VT_entity: see, this is where I'm getting all screwed up

17:14 cemerick: VT_entity: what was your particular problem with counterclockwise?

17:14 gfrlog: do you know how to set up the classpath when executing the java command?

17:14 VT_entity: java -cp

17:14 gfrlog: so

17:14 java -cp clojure.jar:clojure-contrib.jar clojure.main

17:14 should work

17:15 VT_entity: I can't import libraries while using counterclockwise

17:15 lol, I did something wrong, I'm just not sure where

17:15 cemerick: VT_entity: did you add the relevant jars to your project's set of libraries?

17:15 VT_entity: do any of you install the git way?

17:16 cemerick: "git way"?

17:16 VT_entity: how do I do that cemerick?

17:16 you mean the :use command?

17:17 cemerick: VT_entity: right-click on your project (usually in the "Project Explorer" view), and choose properties. Select "Java Build Path", and you'll see a listing of the project's libraries, to which you can add jars and such.

17:17 VT_entity: when I try to download from git, there isn't even a clojure-contrib.jar in the directory, just a series of .clj files

17:17 cemerick: (that all assumes you're not using maven)

17:17 VT_entity: I've tried both ways, neither has really worked for me, I screwed something up.

17:17 oooooooh no way

17:18 cemerick, I never thought to look under build path

17:18 I'm going to try that right now

17:19 cemerick: VT_entity: yeah, it's a snap once you're on the right panel; you probably want "add external jar" — browse, select, then run your REPL, etc.

17:38 gfrlog: Java doesn't have any nice library for english noun pluralization like ActiveSupport does it?

17:44 technomancy: jruby =)

17:50 jmatt: gfrlog: check out inflections - http://r0man.github.com/inflections-clj/

17:53 mtrelinsomething: hi there, how do i call this in clojure? public <T extends java.rmi.Remote> T getService(AdWordsService service) ?

17:54 it's expecting a "T"

17:59 gfrlog: jmatt: thanks

17:59 Krato`: hm hm.... I see c.contrib.string/replace-by doesn't allow to replace just certain groups

18:01 gfrlog: Krato`: maybe something like regex backreferences would do what you want? I'm not too familiar with java's regex support...

18:01 woah

18:01 s/backreferences/lookahead-and-lookbehind

18:01 Krato`: I actually have the needed corde in java

18:01 no those are not useful for replacing

18:02 gfrlog: I meant for not capturing the part you don't want to replace

18:02 Krato`: I know what you meant

18:02 when you specify replace string in java

18:02 you can say $1 or something like that

18:02 and the matched group 1 is inserted into replacement string at that position

18:03 however that prevents you from behing able to replace a group with the result of a function

18:04 gfrlog: doesn't replace-by give you enough info to assemble whatever you need?

18:04 Krato`: it does in some way

18:04 it would require the user to piece together the replacement string themselves

18:05 especially difficult when groups are nested

18:05 (a(b(c)))

18:05 you wanna replace just c

18:06 you need to append a minus c with the replacement for c

18:06 it can get arbitrarily complicated

18:06 gfrlog: yep. I think that's when people start building parsers :)

18:09 Krato`: http://pastebin.com/SSj9JTD9

18:10 little something I've made that replaces groups with the replacements, null elements meaning group doesn't get replaced

18:11 this is a part of a larger framework for working with java reg exp and the replacements in this case are results of match groups run though a bunch of functions

18:12 when I say functions I mean IFn-like interface instances

18:40 Krato``: hmmm

18:40 (defn string-sum [s]

18:40 (reduce #(+ %1 (- (.numericValue ^Character %2) (.numericValue \A))) 0 s))

18:40 why does this make 2 reflection warnings, both for numericValue

18:41 I've typehinted one and the constant can't be typehinted

18:42 oh

18:42 never mind

Logging service provided by n01se.net