#clojure log - Jan 27 2011

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

1:19 no_mind: anyone has a working example of JSON being returned from a clojure program ? I am trying this https://github.com/sivajag/Address-Book but no luck

2:07 amalloy: LauJensen, you around?

3:00 LauJensen: amalloy: yea

3:00 Just got in

3:00 amalloy: nm, i decided to bug you in #clojureql instead

3:00 LauJensen: :)

4:12 mrSpec: Hello! I have problem with (eval (read)) in my program. I have: (defn -main [& args] (while (= 1 1) (print "REPL> ") (eval (read)))) but Instead of "REPL>" I have empty line. When user writes something, "REPL>" is printed and after that the result. What am I doing wrong? Can I force Clojure to print "REPL>" before evaling what user write?

4:14 opqdonut: try flushing *out*

4:14 zmila: did you tryed (println "") instead of (print )?

4:34 mrSpec: thanks! (flush) solve this problem :)

4:40 solar_sea: Is the joy of clojure book ready for reading or it's still a work in progress ? (I'm wondering wether I should get the "meap" subscription for it or wait for a final release)

4:44 clgv: solar_sea: I heard that it is already completed and you can buy it from Amazon or Manning

4:56 LauJensen: solar_sea: http://joyofclojure.com/buy

4:56 clgv: how do I tell leiningen about local dependencies? I have a java implementation in a jar file I want to use.

6:43 edoloughlin: For a simple cache, a map of maps keyed by id & shared by multiple threads: is it best to use an atom or ref?

6:44 companion_cube: i'd say a ref, because to keep the cache consistent you would modify the map in a transaction

6:47 ejackson: agreed - if more than one thread is writing to the cache, then you need to coordinate it

6:48 if only one writes, and the others read, then I'd argue an atom is better as it doesn't need to be coordinated.

6:49 edoloughlin: If all I'm doing it adding (and periodically removing/cleaning) entries to a map, then can't an atom provide a sufficient level of locking? There's only one variable involved...

6:50 companion_cube: if two threads read the atom, add something to the cache, and put the new value in the atom, one of the changes will be lost

6:51 edoloughlin: What if the atom _is_ the cache? (def cache (atom {}))

6:51 clgv: there is a memoize implementation that uses only atoms: http://kotka.de/blog/2010/03/memoize_done_right.html

6:51 maybe that might help you

6:53 ejackson: it depends what you are storing in the cache. if every call needs to be recorded then i think you need a ref

6:53 companion_cube: oh, right, there is a kind of compare-and-swap in atoms

6:53 so you can spot concurrent updates

6:53 edoloughlin: clgv: Looks interesting. This is my first venture into concurrency in Clojure. I'm trying not to to the noob thing of throwing everything at it.

6:54 raek: atoms are fins as long as you don't need to coordinate the change with some other change

6:54 ejackson: companion_cube: i did not know that. seems that in that case you would want a ref though, to take care of the concurrency collisions, no ?

6:54 clgv: edoloughlin: I learned a lot reading that post. I think the decisions are well explained there.

6:54 edoloughlin: Will read. Thanks.

6:54 ejackson: raek is exactly right. coordination is the differentiator.

6:55 and you need to coordinate if >1 thread can alter data, and depend on another's value. such as an incrementer, say. at least i think so :)

6:55 raek: in memoize, the atom never leaves the function, so you know it will never have to be coordinated with someone else's changes

6:56 ejackson: if you (swap! atom-on-int inc) from two threads together, you will be one count short.

6:56 clgv: but multiple threads can use the function and the cache shall be share like explained in the post

6:56 raek: no, atoms are thread safe

6:56 ejackson: bollocks :)

6:57 oops, as in not you're talking bollocks, but bollocks i'm wrong again.

6:57 raek: but if you want to change multiple atoms or one atom in multiple steps, then you can't do it atomically

6:57 that's what refs add

6:57 clojurebot: Titim gan éirí ort.

6:58 ejackson: ah yes... that's it.

6:59 raek: my rule of thumb is: if you are not sure someone else might want to use your atom/ref in a multi-step or multi-ref change, use refs

7:00 companion_cube: i think you can do it with atoms, but refs (with STM) are much simpler to keep state consistent

7:44 qoja: I'm trying to reify a java.io.FilenameFilter with: (reify FilenameFilter (accept [_ name] (.endsWith name ".sql"))) and I get Can't define method not in interfaces: accept--what am I doing wrong?

7:46 clgv: qoja: I am not 100% sure, but shouldnt you use proxy instead of reify since reify is only intended for protocols?

7:46 qoja: aren't protocols interfaces actually ?

7:48 clgv: well, they are clojure constructs compiled to java interfaces and you are trying to implement a java interface. so there is a semantic difference here.

7:49 companion_cube: it's a bit of static typing, right ?

7:49 clgv: if you got the method-signature right and reify doesnt work I would definitely try proxy instead

7:49 I used it for TreeCellRender...

7:52 companion_cube: the blog entry on memoization is really interesting

7:56 qoja: oh what a silly mistake. forgot this-variable as first parameter!

7:57 raek: for interfaces, both proxy and reify can be used

7:57 clgv: raek: ah, good to know

7:57 raek: but reify is designed to be clojure-ish

7:58 so you can't do subclassing with it, for instance

8:02 ejackson: and i believe is much faster

8:03 raek: it is.

8:03 proxy also allows you to update the methods at run time

8:03 (which I haven't used myself...)

8:17 * raek just realized that you can dowload the whole API docs at https://github.com/clojure/clojure/tree/gh-pages

8:19 ejackson: raek: i've played that trick through deftype. Its fantastic from the repl.

8:48 zippy314: Hey, guys, I know this isn't strictly a clojure question, but since I'm hanging out here and using it for colure dev... It's an emacs customization question. I've used technomancy's starter emacs repo, and it calls for removing my .emacs file and using .emacs.d. Where in that directory should I be putting my own cusomizations?

8:50 arbscht: zippy314: ~/.emacs.d/init.el is a reasonable choice. it is documented in greater detail at http://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html

8:52 zippy314: tx!

8:55 fliebel: Hrm, I wonder if Logos, and logic programming in general could solve blue eyes. I guess it can, if you define the problem correctly.

8:55 ejackson: a hesitate to ask..... what is blue eyes ?

8:55 fliebel: http://xkcd.com/blue_eyes.html

8:56 I have set it as my home page until I solve it :)

8:57 zippy314: fliebel: nice1

8:58 (s/1/!/) correction: fliebel: nice!

8:58 ejackson: eep

8:59 fliebel: I have made a few assertions, but solved nothing yet...

9:00 zippy314: If you'd have typed that regex without the cruft, sexpbot would have xxx it for you ;)

9:00 s/xxx/replaced

9:00 sexpbot: <fliebel> zippy314: If you'd have typed that regex without the cruft, sexpbot would have replaced it for you ;)

9:01 zippy314: text

9:01 (s/x/s/) correction: test

9:01 hmm what cruft?

9:01 I just typed "s/x/s/"

9:01 ejackson: s/ee/EEEEEEEEEEEEEE/

9:01 sexpbot: <ejackson> EEEEEEEEEEEEEEp

9:02 zippy314: Could it be my client?

9:02 ejackson: no you typed "correction:....." after the regex

9:03 fliebel: probably.

9:03 zippy314: nope, I didn't I think my irc client must be doing that or something...

9:03 ejackson: haha, its like a macro. your client got it before sexpbot did :)

9:03 fliebel: $sed -zippy314 s/'t/'t,/

9:03 sexpbot: <zippy314> nope, I didn't, I think my irc client must be doing that or something...

9:04 zippy314: I'm using Colloquy (OS x)

9:04 fliebel: $sed -zippy314 s/x/X/

9:04 sexpbot: <zippy314> I'm using Colloquy (OS X)

9:04 zippy314: :-)

9:04 fliebel: Okay, I'll to annoying people...

9:05 s/to/stop/

9:05 sexpbot: <fliebel> Okay, I'll stop annoying people...

9:05 zippy314: is anybody else here using technomancy's emacs starter kit?

9:07 raek: I do.

9:08 zippy314: raek: where do you add your own emacs customizations?

9:11 clgv: fliebel: seems to be a proof by induction ;)

9:12 incandenza: zippy314: I use ~/.emacs.d/username.el

9:12 fliebel: clgv: uh?

9:13 clgv: fliebel: the blue eyes puzzle ;)

9:13 fliebel: clgv: the proof by induction ;)

9:13 zippy314: Looks like ~/.emacs.d/custom.el is also autoloaded for this purpose...

9:14 incandenza: that is actually used for M-x customize

9:14 you probably shouldn't put stuff in there

9:14 zippy314: BTW if any body else is on a Mac and is annoyed by the default scrolling behavior of Carbon emacs, here's something that fixes it: http://www.emacswiki.org/emacs/SmoothScrolling

9:14 neilcj: zippy314: i throw any code in custom.el and it works, donno if that's ok :P

9:15 clgv: fliebel: you dont know the term, or what?

9:15 fliebel: clgv: I'm reading wikipedia now ;)

9:15 zippy314: incandenza: hmm, what's M-x customize for?

9:15 clgv: fliebel: ok^^

9:15 raek: zippy314: ~/.emacs.d/raek.el and ~/.emacs.d/raek/<oher files>.el

9:15 incandenza: zippy314: it's a way of setting configuration variables with a menu system

9:17 raek: "First, the user-specific-config file is the file named after your user with the extension ".el". In addition, if a directory named after your user exists, it will be added to the load-path, and any elisp files in it will be loaded."

9:17 from https://github.com/technomancy/emacs-starter-kit

9:17 incandenza: ^ yeah, follow that :)

9:17 neilcj: yeah, just moved stuff I'd added from custom.el to neilcj.el and everything worked: do that, zippy

9:42 markskilbeck: Anybody know of a trick in emacs to mimic aquamacs's ability to click a previously entered expression in the REPL to have it evaluated again?

9:44 neilcj: middle clicking an expression inserts it after the REPL prompt, if that helps

9:54 raek: hitting <ret> after a previous expression copies it to the bottom, iirc

9:54 M-p can be useful too

9:58 markskilbeck: neilcj, raek: thanks

10:14 zippy314: raek: what do you do with M-p?

10:16 semperos_: go up one entry in REPL history in Emacs

10:17 zippy314: oh sweet! I need the slime repl cheat sheet.

10:18 looks like there is one: http://www.pchristensen.com/slimecommands.pdf

10:25 raek: the slime commands listed here are really useful: https://github.com/technomancy/swank-clojure

10:31 hoggarth: do you have an easy way to convert a string to a list of characters?

10:33 ejackson: ,(map identity "Hello, world!")

10:33 clojurebot: (\H \e \l \l \o \, \space \w \o \r ...)

10:33 hoggarth: nice

10:33 Chousuke: ,(seq "hello world")

10:33 clojurebot: (\h \e \l \l \o \space \w \o \r \l ...)

10:33 Chousuke: use that :P

10:33 ejackson: nicer !

10:34 Chousuke: actually, since most seq-expecting things call seq on their argument anyway, you can often just pass in plain strings

10:34 hoggarth: i'll keep that in mind

10:35 Chousuke: ,(first "foo") for example

10:35 clojurebot: \f

10:35 hoggarth: thanks guys

10:51 Kruppe: Is there any way of finding out what slots are in a class (short of using inspect or reading the source)?

10:52 ejackson: Kruppe: I usually use show from repl-utils

10:53 Kruppe: ejackson: I'll take a look at it, thanks :)

10:53 ejackson: although you should be careful with my advice, I haven't been correct yet today ;)

10:53 Kruppe: ejackson: these things happen

11:20 Luyt: My solution for Euler #1, http://clojure.pastebin.com/rw9zgSyt , I guess I could use some range that counts to 1000 and filter it on multiplep(3) OR multiplep(5). Would that be more elegant?

11:24 chouser: I like what you've got.

11:25 * chouser checks his own solution

11:25 chouser: hm, essentially identical, though I started my ranges as 0

11:25 at 0

11:27 Luyt: Somehow expanding two lists, concatenating them, then making the numbers in it unique using 'set', seems like a detour to me.

11:28 I'd rather have one seq which counts from 0 to 1000, selects only the multiples of 3 and 5 from them, and sums those.

11:29 incandenza: Luyt: you could do it like this: (reduce + (filter #(or (= 0 (mod % 3)) (= 0 (mod % 5))) (range 3 1000)))

11:29 Luyt: Aha, that looks more like it

11:31 chouser: Luyt: well, that means calling mod at least once on every number under 1000

11:32 incandenza: yes, it is slower, I noticed

11:32 chouser: what you've got now only touches numbers that will be included in the set

11:32 Luyt: Indeed ;-)

11:33 chouser: and remember both ranges and concat are lazy, so it's not really expanding two lists before building the set

11:33 Luyt: Oh? I didn't know that.

11:35 chouser: the set is what forces the realization of the lazy seqs in that expression, so really only one chunk of input numbers exists at any one time while the set is being built up

11:37 symuyn: Hey, is reverse on a lazy seq linear or constant?

11:38 chouser: linear. reverse itself isn't lazy and realizes the whole input seq

11:38 as it of course must

11:38 Luyt: Hmmm when I run it on a range of 3000000 Incandenza's seems to be a lot quicker. How could you easily measure it?

11:39 incandenza: I just used 'time'

11:39 semperos_: $doc time

11:39 guess that only works for source...

11:39 Luyt: Ah, I'll try.

11:39 symuyn: chouser: Is it the same for reversing vectors?

11:39 Luyt: ,(doc time)

11:39 clojurebot: "([expr]); Evaluates expr and prints the time it took. Returns the value of expr."

11:40 chouser: be careful doing micro benchmarks -- the JVM is complex and will give widely varying times, especially the first several times you run a particular chunk of code

11:40 symuyn: yes, but don't use reverse on a vector, use rseq

11:40 symuyn: Oh dear

11:40 Thanks

11:41 Luyt: Incandenza's code is quicker, at least on my machine. 588 msec vs. 3700 msec.

11:42 incandenza: probably the mod is cheaper than the set membership test, in the long run

11:42 Luyt: Yeah, because with smaller sets my code is slightly quicker

11:43 incandenza: and I guess the set itself can't be lazy

11:43 Luyt: Well, that's an interesting side effect ;-) On to problem 2...

11:47 chouser: set can't be lazy, but two sorted lazy seqs could be merged lazily, and adjacent dups could be removed lazily

12:16 Luyt: I added a solution to problem 1 at the bottom of http://clojure-euler.wikispaces.com/Problem+001 if you're interested.

12:18 Luyt: Interesting to see all these solutions

12:18 1000 ways to skin a cat

12:20 I see many people used the reduce, set, concat thing.

12:21 chouser: Luyt: they all either used a set, distinct (which uses a set internally), or subtracted the duplicate sum afterward

12:22 that's what I thought it might be interesting to have the merge solution there -- it's the only one that skips the dups instead of subtracting them, but without building a full set

12:23 Luyt: Right now I noticed by homebrewn fibonacci routine is dog slow, and my jaw drops when looking at http://en.wikibooks.org/wiki/Clojure_Programming/Examples/Lazy_Fibonacci ;-)

12:23 chouser: I'm not saying it's better, just different. Ends up being a lot of code for such a simple problem. :-P

12:25 symuyn: If I want to make an empty collection as a base case for a sequence-returning function, should I use the empty list or the empty vector?

12:26 chouser: symuyn: well, are you building a vector, a list, or a lazy-seq?

12:27 symuyn: A lazy seq

12:27 chouser: you don't want nil for the base case/

12:27 ?

12:27 pdk: ok dumb q

12:28 symuyn: chouser: Oh, of course. Silly me

12:28 pdk: what out of the box function would i use to append an item to a seq

12:28 i see there's cons to prepend but i figured i could append in one step too

12:29 chouser: pdk: lazily without forcing it? a single item, or will it end up being many?

12:29 pdk: one item at a time

12:29 it can be lazy

12:30 let me guess it involves wrapping the item in () then doing lazy-cat :p

12:30 chouser: well, concat then, but if you're doing it a lot that's rather inefficient

12:30 pdk: what would you suggest to optimize it or change the strategy

12:30 mattmitchell: could someone recommend a lib for dealing with command line args?

12:31 chouser: pdk: use a vector instead of a lazy seq -- you can efficiently add to the right

12:32 pdk: or use lazy-seq directly

12:35 pdk: yeah i was thinking a vector though i didnt find anything right away to append to them

12:35 semperos_: conj

12:35 chouser: conj appends to vectors. very very fast

12:35 pdk: could always use lazy-concat in place of concat too

12:35 hm here i was using conj on sets

12:35 er lazy-cat

12:36 semperos_: conj is the cons of vectors

12:36 and vectors efficiently add items to the right

12:36 while lists to the left (head)

12:36 chouser: conj works on everything: sets, maps, vectors, lazy seqs, cons, ...

12:39 Luyt: Is there a pastebin/codepad somewhere which will execute clojure code?

12:39 pkinney: is it ok to paste a one-liner piece of code here?

12:39 tonyl: pkinney, one-liners are fine

12:39 pkinney: tonyl: thanks

12:40 (map #(bit-xor (int (get %1 %2)) (int (get %1 (- 1 %2)))) lock (iterate inc 0))

12:40 semperos_: put & at the beginning

12:40 tonyl: Luyt maybe try-clojure but don't think it would return a paste url

12:40 Luyt: ,(map #(bit-xor (int (get %1 %2)) (int (get %1 (- 1 %2)))) lock (iterate inc 0))

12:40 clojurebot: java.lang.Exception: Unable to resolve symbol: lock in this context

12:40 pkinney: lock is a string

12:40 Luyt: tonyl: I'll check.

12:41 Argh... "The service is not available. Please try again later." http://tryclj.licenser.net/

12:41 tonyl: try this http://www.try-clojure.org/

12:41 pkinney: ,(map #(bit-xor (int (get %1 %2)) (int (get %1 (- 1 %2)))) "testing" (iterate inc 0))

12:41 clojurebot: java.lang.NullPointerException

12:42 pkinney: I think its throwing the error because the int is getting a nil on the last iteration

12:42 tonyl: there is no last iteration

12:42 is a lazy sequence

12:42 pkinney: (sorry the 1st)

12:42 Luyt: tonyl: Thanks, that site is alive, however it won't accept opening parentheses. Could be a Konqueror issue ;-)

12:42 tonyl: &(take 100 (iterate inc 0))

12:42 sexpbot: ⟹ (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99)

12:43 Luyt: quick! What't the sum of that? (Gauss)

12:43 tonyl: the map function to apply to the items only takes 1 argument though

12:44 Luyt: crap forgot that, 5015?

12:44 Luyt: N=100, N/2 * 100 - N

12:44 tonyl: &(get 0 1)

12:44 sexpbot: ⟹ nil

12:44 chouser: &(get 0 1 :lunchtime)

12:44 pkinney: tonyl: I thought if u gave the map more args they run in parallel

12:44 sexpbot: ⟹ :lunchtime

12:45 Luyt: Gauss solved that in a few seconds when he was a little boy (his schoolmaster gave him the silly assignment of adding the numbers 1 through 100 just to keep him busy)

12:45 tonyl: pkinney: if you give it more then 1 collection ##(map vector (range 0 10) (range 11 20))

12:45 sexpbot: ⟹ ([0 11] [1 12] [2 13] [3 14] [4 15] [5 16] [6 17] [7 18] [8 19])

12:48 pkinney: yeah

12:48 tonyl: Luyt: found this in my delicious http://ideone.com/ I knew I saw a service like that somewhere

12:48 pkinney: my bad, I forgot about the string there

12:48 pkinney: I thought I could use the other coll (from iterate) as an index

12:49 Luyt: tonyl: Looks very good, thanks.

12:49 tonyl: it seems that the error might be in 1 of those gets

12:49 &(map vector "testing" (range))

12:49 sexpbot: ⟹ ([\t 0] [\e 1] [\s 2] [\t 3] [\i 4] [\n 5] [\g 6])

12:50 pkinney: oh, does range work that way too, lol

12:50 thats cool

12:51 tonyl: yeah i use it for shortcut

12:51 tomoj: &(map-indexed vector "testing")

12:51 sexpbot: ⟹ ([0 \t] [1 \e] [2 \s] [3 \t] [4 \i] [5 \n] [6 \g])

12:51 amalloy: do you really want (- 1 %2)? in infix that's 1 - %2

12:51 pkinney: yeah

12:52 tonyl: (dec %2)

12:52 sexpbot: ⟹ -1

12:52 tonyl: &(dec %2)

12:52 sexpbot: java.lang.Exception: Unable to resolve symbol: %2 in this context

12:52 amalloy: lol

12:52 tonyl: lol

12:52 pkinney: its xoring the letter together

12:52 amalloy: tonyl: you activated the karma plugin

12:52 tonyl: yeah

12:52 wonder who is %2

12:52 amalloy: tonyl: nobody

12:52 tonyl: &(map (fn [[x y]] [(int (get x y)) (int (get x (dec y))]) "testing" (range))

12:52 sexpbot: java.lang.Exception: Unmatched delimiter: ]

12:52 amalloy: but just in case he signs on

12:53 pkinney: eg. t ^ e = 3... 3 ^ s... etc (3 is made-up)

12:54 amalloy: pkinney: and you have negative numbers as keys in the maps?

12:54 pkinney: oh, i'm wrong sorry... t ^ e, e ^ s...

12:54 tonyl: &(map (fn [[x y]] [(int (get x y)) (int (get x (dec y)))]) "testing" (range))

12:54 sexpbot: java.lang.IllegalArgumentException: Wrong number of args (2) passed to: sandbox17750$eval19737$fn

12:55 pkinney: amalloy: what do you mean?

12:55 amalloy: &(- 1 5)

12:55 sexpbot: ⟹ -4

12:56 amalloy: my point is that (- 1 x) will be negative for any x larger than 1

12:56 Luyt: Well, my solution for Euler #2. It contains some suckage...

12:56 amalloy: and you're using the result of as a key in your maps

12:56 Luyt: http://ideone.com/iCCOS

12:56 pkinney: aaah

12:56 tonyl: &(int (get \t 0)

12:56 sexpbot: java.lang.Exception: EOF while reading

12:56 tonyl: &(int (get \t 0))

12:56 sexpbot: java.lang.NullPointerException

12:57 tonyl: &(int (get \t 1))

12:57 sexpbot: java.lang.NullPointerException

12:57 tonyl: pkinney: that might be your problem

12:57 pkinney: yeah, thats it

12:58 (need to find a way outa that

12:58 amalloy: pkinney: ##(dec 5)

12:58 sexpbot: ⟹ 4

12:59 pkinney: It'll strill try and get the -1 index though

13:00 tonyl: i am guessing because of (dec 0)

13:00 pkinney: ,(map #(bit-xor (int (get %1 %2)) (int (get %1 (dec %2)))) "testing" (iterate inc 0))

13:00 clojurebot: java.lang.NullPointerException

13:00 pkinney: yup

13:00 Luyt: I think these Project Euler problems focus too much on math and not on real world problems

13:01 pkinney: is there a quick way to get it to give a 0 if the index doesn't exist

13:01 tonyl: that is why is called Euler :P

13:01 qoja: is there some short macro, to merge metadata (and not replece, like with-meta does) ?

13:01 Luyt: I mean, to write a web app you don;t have to solve the sum of the first 10001 primes who are amicable

13:01 amalloy: Luyt: so don't solve them

13:01 tonyl: qoja metadata is map and there is a merge fn for maps

13:02 amalloy: pkinney: ##(get {} -1 0)

13:02 sexpbot: ⟹ 0

13:02 Luyt: amalloy: Excellent idea!

13:02 tonyl: Luyt: it even says you can do them in paper

13:02 qoja: tonyl: but what with (with-meta (fn .... ) (merge ??? { :my 'metadata }))

13:02 tonyl: the not-found arg I always forget it too

13:02 qoja: i could of course write a fun for that, but isn't there one standard already?

13:03 Luyt: tonyl: My dad studied math and he solved some problems by just analysing them... while I pull out my fav language and go bruteforce it ;-)

13:03 * pkinney faceslaps himself

13:03 pkinney: thanks

13:03 tonyl: Luyt: I wish I could do that like your dad, but I like bruteforcing every now and then

13:04 qoja: as far as I know there isn't

13:04 raek: qoja: vary-meta

13:04 ,(doc meta)

13:04 Luyt: tonyl: Yup. But not in all cases bruteforcing is even remotely possible.

13:04 clojurebot: "([obj]); Returns the metadata of obj, returns nil if there is no metadata."

13:04 raek: ,(doc vary-meta)

13:04 clojurebot: "([obj f & args]); Returns an object of the same type and value as obj, with (apply f (meta obj) args) as its metadata."

13:04 qoja: tonyl: ok thanks, i thought it maybe is present int contrib. it seems to be a common scenario

13:05 tonyl: yeah and raek's suggestion might help

13:05 qoja: raek: that's what i need

13:05 thx

13:06 amalloy: &(vary-meta #'first (comp merge meta) #'comment)

13:06 sexpbot: java.lang.IllegalArgumentException: Wrong number of args (2) passed to: core$meta

13:06 amalloy: oh duh

13:07 &(vary-meta #'first merge (meta #'comment))

13:07 sexpbot: java.lang.ClassCastException: clojure.lang.Var cannot be cast to clojure.lang.IObj

13:07 tonyl: what's up with var's private meta? what is it used for?

13:09 raek: it stops people from making functions that use those vars outside the namespace they live in

13:10 tonyl: ok thanks raek

13:11 raek: ,clojure.core/array

13:11 clojurebot: java.lang.IllegalStateException: var: clojure.core/array is not public

13:11 raek: ...or from even using it from the outside of the namespace

13:11 ,@#'clojure.core/array ; with exceptions... :-)

13:11 clojurebot: #<core$array clojure.core$array@1479a6b>

13:12 symuyn: &(seq? nil)

13:12 sexpbot: ⟹ false

13:13 pdk: ,(Integer/parseInt "3")

13:13 clojurebot: 3

13:13 pdk: ,(Integer/parseInt 3)

13:13 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

13:26 mattmitchell: how can i check if a variable exists?

13:28 i guess i mean, how can i check if a var exists?

13:28 raek: ,(doc resolve)

13:28 clojurebot: "([sym]); same as (ns-resolve *ns* symbol)"

13:28 kumarshantanu: mattmitchell: the compiler checks that for you :-p

13:28 raek: maybe this

13:28 mattmitchell: interesting

13:29 raek: you very rarely need to use it though...

13:29 mattmitchell: makes me think i might be handling this bit of code incorrectly then :)

13:38 bendlas: key folks!

13:38 /s/key/hey/

13:39 fun clojure quirk of the day

13:39 ,(loop [x 5]

13:39 (when (pos? x)

13:39 (try

13:39 clojurebot: EOF while reading

13:39 bendlas: (recur (dec x))

13:39 (finally (print x)))))

13:39 ,(loop [x 5] (when (pos? x) (try (recur (dec x)) (finally (print x)))))

13:39 clojurebot: bendlas: No entiendo

13:40 * bendlas scratches head

13:40 chouser: the bots don't like you using try/catch

13:40 bendlas: OIC

13:41 chouser: they could be used to prevent killing of runaway exprs and such.

13:41 bendlas: guessed that

13:41 anyways, the expression compiles, but the finally is silently discarded

13:41 due to the recur

13:42 hiredman: bendlas: thats a bug, the latest clojure won't compile the expression

13:42 raek: ,((fn f [x] (when (pos? x) (try (f (dec x)) (finally (print x))))) 5)

13:42 clojurebot: raek: Huh?

13:42 hiredman: recur is not allowed across try/binding

13:42 raek: right. the catch form.

13:43 bendlas: hiredman: so it's on the radar already, good

13:45 hiredman: bendlas: recuring across a dynamic context like try or binding is a buggy way of thinking, the compiler was just loose in allowing you to shoot your foot off

13:49 bendlas: actually, I need a variation of (binding ) that works on #'var s, with each binding expression in a try

13:49 but using recur there smelled fishy right away, so i checked first

13:49 luckily

13:51 hiredman: sounds icky

13:52 bendlas: it does

13:53 and of course there is a simpler way, which i've just realized

13:55 pkinney: is there an easy way to add an item to the beginning of a coll? like a reversed conj?

13:55 bendlas: (cons item collection)

13:55 chouser: pkinney: conj on a list adds items to the left

13:55 hiredman: conj add items in the most effecient way

13:55 ,(conj [1] 2)

13:55 clojurebot: [1 2]

13:55 chouser: ,(conj '(b c d) a)

13:55 clojurebot: java.lang.Exception: Unable to resolve symbol: a in this context

13:55 chouser: ,(conj '(b c d) 'a)

13:55 hiredman: ,(conj '(1) 2)

13:55 clojurebot: (a b c d)

13:55 chouser: sigh

13:55 clojurebot: (2 1)

13:55 chouser: sorry

13:56 pkinney: chouser: ah rite, thanks :)

13:58 (how didn't I notice that? heh)

14:12 gaaah, I'm still stuck in the mold (of OOP)

14:14 amalloy: pkinney: OOP backwards is POO. keep that in mind

14:15 pkinney: hehe

14:15 I just think the overall design of my functions are wrong

14:17 https://gist.github.com/799022

14:17 amalloy: could be. everything's a learning experience

14:17 pkinney: my ugly function

14:17 I'm abusing let

14:18 amalloy: pkinney: fwiw (list* s) should be the same as just plain s, unless you want to coerce some other sequence to be specifically a list

14:19 pkinney: Oh

14:19 amalloy: and there's nothing wrong with using let to label intermediate results, although you might want to pick names that mean something :P

14:20 pkinney: heh, yeah a to d isn't good for variable names

14:20 amalloy: if you just want to reduce the nesting factor of your intermediate results, you can use -> or ->> instead

14:21 pkinney: I've seen other code snippets about using -> and ->>, thought they were interesting, but haven't got my head round them enough to using them

14:21 amalloy: (->> (count lock) (reduce some-fn) (conj (map other-fn other-data)) (map nibble-swap) (map char) (apply str))

14:21 pkinney: does it just push the result onto the next...

14:21 aah

14:22 amalloy: &(macroexpand-all '(->> (range) (filter even?) (drop 100) (take 100) (reduce +)))

14:22 sexpbot: ⟹ (reduce + (take 100 (drop 100 (filter even? (range)))))

14:22 pkinney: could take out the let altogether then?

14:22 zippy314: I'm trying to remove an item from a ref to a vector. I can't figure out why this doesn't work: ##(def x (ref [1 2 3 4])) (dosync (alter x remove [#{2}]))

14:22 sexpbot: java.lang.SecurityException: You tripped the alarm! def is bad!

14:22 zippy314: oops

14:23 amalloy: zippy314: #{2}, not [#{2}]

14:23 chouser: zippy314: x bevomes the first arg to remove, which is probably not what you want

14:23 amalloy: oh, or chouser is so right

14:24 pkinney: amalloy: thanks, thats gave me some food for thought

14:24 amalloy: pkinney: welcome, and enjoy it. i'm off

14:24 pkinney: me too ^_^ thanks again

14:25 zippy314: amalloy: that doesn't work either: ##(let [x (ref [1 2 3 4])] (dosync (alter x remove #{2})) @x)

14:25 sexpbot: ⟹ ()

14:27 zippy314: so, I'm trying to figure out what's the proper way to remove an item from a ref to a vector?

14:28 amalloy_: zippy314: chouse [as usual] has the right answer

14:28 (alter x #(remove #{2} %))

14:29 chouser: zippy314: removing items from a vector is suspect in the first place. you're sure you don't want a set instead?

14:29 tonyl: the way alter is calling is like (remove @x #{2})

14:29 shortlord: is directly using an (immutable) var in a function without passing the var as an argument considered to be impure?

14:29 tonyl: yes, but you can still do it

14:29 zippy314: Well, the thing is I care about the order.

14:29 hiredman: :(

14:29 zippy314: is there and ordered set?

14:29 chouser: there's a sorted set

14:29 hiredman: (alter x (partial remove #{2}))

14:31 zippy314: yah baby! that's what I really want, sorted-set. Cool.

14:31 jweiss_: can someone point me to a typical dir structure for a project with java and clojure source? (/src/java, /src/clj)? (java/src, clojure/src)? etc

14:31 chouser: note that remove will return a lazy seq, not a vector, and because it's lazy has the potential to stack calls when later realized

14:32 zippy314: but how do you define the sort algorithm?

14:32 shortlord: tonyl: but using other functions directly would not be considered impure, right?

14:32 chouser: zippy314: see sorted-set-by, but be aware that if your fn says two things are equal, only one will be stored in the set

14:32 jweiss_: clojure itself uses src/clj and src/jvm, oddly

14:33 chouser: jweiss_: the maven standard is something like src/main/clojure and src/main/java

14:33 tonyl: shortlord: what do you mean directly

14:33 technomancy: jweiss_: consider why you feel that Java code needs to be in a separate dir

14:33 chouser: ...and there's the non-maven voice. :-)

14:34 jweiss_: technomancy: i suppose that was a false assumption that it DOES have to be separate?

14:34 chouser: jweiss_: it'll depend on your tools.

14:34 shortlord: tonyl: well, where's the difference between using vars or functions in another function without passing them as arguments? using built-in functions like map is not considered to make a function impure, so why is using an immutable var?

14:34 technomancy: jweiss_: maybe you have a good reason, but I don't think most people do

14:34 worth some thought =)

14:34 jweiss_: i'm using leiningen to build, so i assume if the creator of lein says its ok then lein won't complain either

14:34 :)

14:35 i suppose that if it doesn't work out, separating the two types of files won't be hard.

14:38 tonyl: the functions you pass to map won't change anything, it would just create a new value and map would save those values in a seq

14:38 vars are global objects

14:38 technomancy: jweiss: for the record I haven't actually tried that; I have noticed that it hasn't been a problem to keep JS files in src.

14:38 tonyl: I think I might be missing something here

14:39 chouser: does lein know how to compile .java files?

14:39 technomancy: chouser: yeah, added in the latest version

14:39 jweiss_: technomancy: as long as lein will still know to compile java, and put the class files in the jar, along with the clj files, i'll be happy

14:39 shortlord: tonyl: no, I mean using 'map' inside one of your functions without passing the map function as an argument. (quite theoretical, I know). Just using clojure's core functions is conceptually not different to using your own functions without passing them as arguments

14:40 tonyl: and since vars could be functions or anything else but are in any case immutable, I don't see why just using them in a function without passing them as an argument makes the function impure

14:41 tonyl: shortlord: oh that is a good question about the purity or functional langs. in the strictest of meanings that is impure

14:43 shortlord: but as you say you would need some impurity to use the language functionalities. I would say AFAIK in clojure you can use global functions inside your functions, but when it comes to other values in vars, depend less on those.

14:43 but that is my opinion

14:43 shortlord: I ask about that quite theoretical thing, because I still have problems determining how pure any particular function in my code should be. For small problems it's quite easy to stay very pure, but in a larger project all the functions seem to require more an more arguments to stay pure

14:45 tonyl: good question, but if you want to stay really pure then you can only use the special forms that clojure comes with, which I think are about 12.

14:46 that would be a tedious language to use, instead of using of the available library functions like the seq, maps, vectors, etc ... functions

14:47 shortlord: tonyl: I am not very interested in staying pure for the sake of staying pure, but I have the feeling that I'm often still doing things too imperatively. Whenever I try to actively write pure code, it's very hard to determine when to pass which things as arguments and when to use something directly

14:48 is there any good resource on software development using functional programming that is largely language agnostic and goes beyond explaining the functional concepts in terms of isolated 5 - 50 lines examples?

14:49 tonyl: shortlord: I battle with that thinking sometimes. but I haven't stumble upon a source like that. I have just started reading the SCIP book and it seems quite good in functional concepts, although it uses scheme to illustrate

14:50 I have just started with functional programming with clojure

14:50 technomancy: scheme is as close to language-neutral as you can get

14:51 tonyl: technomancy: yeah, I can understand about 80% of what the code means. maybe because I have some clojure exposure

14:51 shortlord: I've already heard quite a few good things about SICP, I guess I should really put it on my to-read list

14:52 thx for the suggestion :)

14:53 edw: shortlord: And watch the H-P lectures from the '80s by Sussman & Abelson.

14:53 benreesman: what is the idiomatic way in clojure to assoc a key that's nested in a map, perhaps several levels in?

14:53 semperos: assoc-in, I think

14:54 ,(doc assoc-in)

14:54 clojurebot: "([m [k & ks] v]); Associates a value in a nested associative structure, where ks is a sequence of keys and v is the new value and returns a new nested structure. If any levels do not exist, hash-map...

14:54 shortlord: benreesman: if you simply want to assoc it, use assoc-in, otherwise update-in can operate on it using a function

14:54 benreesman: thank you!

14:57 is there a way to have it add the keys if not present as maps?

14:58 semperos: part of the docs for assoc-in

14:58 "If any levels do not exist, hash-maps will be created"

14:59 that what you meant?

15:01 benreesman: definitely

15:02 brilliant, works like a charm

15:16 sritchie: hey all -- I'm looking to work with a java function that takes a byte array as a parameter and fills it with data. this sort of goes against the clojure way, as data structures are supposed to be immutable -- also, when I pass in the symbol for my array (defined with (def array (byte-array (* 1200 1200)))), it doesn't change

15:17 what's the most idiomatic way to deal with a java method like this?

15:19 tonyl: i don't think that java fn would know how to change the value of a binding to the var that is holding the array

15:20 brehaut: tonyl: by the byte array itself is a mutable block of memory

15:20 tonyl: mmm... I haven't done anything like this, but maybe somebody here hve

15:20 brehaut: s/by/but/

15:20 sexpbot: <brehaut> tonyl: but the butte array itself is a mutable block of memory

15:20 sritchie: got it, so it's modifying the array, but can't switch the binding over

15:21 brehaut: sexpbot, that wasnt a general regexp. why did you apply it twice?

15:21 sritchie: no

15:21 tonyl: thankr brehaut, I clearly need more knowledge about this then :)

15:22 sritchie: the other option is a method that returns a DirectByteBuffer

15:22 brehaut: as i understand it, all array types are mutable, and largely exist for interop (and speed)

15:22 tonyl: I can see that in the code now

15:23 brehaut: i think something else is going wrong to cause sritchie's array to not be modified

15:24 sritchie: also idiomatically, i think you would try to isolate the code that worries about mutation as much as reasonably possible.

15:24 ie keep it internal to one function

15:25 amalloy_: brehaut: sexpbot does a global replace. he's not perl, awk, or sed, he's just looking for s/foo/bar (optional trailing slash)

15:25 sritchie: brehaut: I'm reading MODIS tiles from nasa, enclosed in these dataset objects -- reading this byte array is the last step before I can free myself from mutable arrays

15:26 brehaut: sritchie: thats fine then. java interop is 'first class' code in clojure

15:26 amalloy: apparently so :P

15:27 tonyl: sritchie: you can use java structures in clojure functions too

15:28 sritchie: well, looks like my first step is figuring out why that byte array isn't being modified

15:29 tonyl: maybe the java function is not actually changing it?

15:30 brehaut: sritchie: does you java function have some api docs (or better source) on the internet?

15:30 and can you paste your snippit somewhere?

15:30 sritchie: yeah, here's the doc -- http://gdal.org/java/org/gdal/gdal/Band.html#ReadRaster_Direct(int, int, int, int)

15:30 brehaut: pardon, here it is -- http://gdal.org/java/org/gdal/gdal/Band.html

15:32 https://gist.github.com/799187

15:32 that's how I was calling it

15:33 I'm going to go verify that the Band has good data in it

15:33 brehaut: sritchie: thats a good idea.

15:33 tonyl: that method needs a ByteBuffer object

15:34 brehaut: tonyl: its heavily overloaded

15:34 sritchie: tonyl: yeah, check the example at the very top, it just needs a byte array

15:34 tonyl: yeah I scrolled further more

15:34 i see the method signature now

15:35 maybe type hinting would help resolve which method is being choose to operate

15:36 sritchie: tonyl: looks like the method is returning CE_None, which shows that all went well -- I'm going to try this with a different dataset, and see what happens

15:36 tonyl: ok

15:36 sritchie: but the fact that the method can modify a byte[] created with byte-array is great

15:36 that simplifies this application quite a bit

15:37 brehaut: sritchie: are any exceptions being raised about finding methods?

15:38 im presuming not, otherwise you probably would have mentioned them before now?

15:38 sritchie: brehaut: no, the application finds the method, and returns 0, which is CE_None (meaning no failure), but the byte array returned the same value from the REPL

15:39 I assumed that it hadn't been modified, since (take 100 gdal-bytes) resulted in 0s, but based on these answers and the CE_None, I'm worried that I chose an empty band

15:42 brehaut: sritchie: use (some (complement zero?) gdal-bytes)

15:42 it will return true if there is a non zero value and nil otherwise

15:43 instead of take 100

15:44 sritchie: yeah, I do get true

15:44 brehaut: 100 bytes out of 1400000 is not a very reliable sample

15:44 amalloy: or (not-every? zero? bytes)

15:44 brehaut: amalloy cleans up my mess again :P

15:44 amalloy: i think that exists. maybe not. ##(doc not-every?)

15:44 sexpbot: ⟹ "([pred coll]); Returns false if (pred x) is logical true for every x in coll, else true."

15:44 amalloy: whew

15:45 brehaut: amalloy: and it works right too

15:45 tonyl: lol not-every is just (comp not every?) oh i love it, so simple

15:46 sritchie: hey, great, this --

15:46 (some #(if (or (zero? %) (neg? %)) nil %) my-bytes)

15:46 returns 30

15:46 tonyl: so there are values

15:46 sritchie: yup, looks like all's well

15:46 tonyl: :) I learned from this one too

15:47 sritchie: so! the lessons of today are -- byte arrays are mutable, and don't use (take 100 array) to investigate a 1200 x 1200 array

15:47 brehaut: tonyl: i learnt from tutoring at university that helping other people is always the best way to learn

15:48 tonyl: brehaut: so true

15:48 brehaut: sritchie: you next lesson is to take that test case, and write a deftest for it

15:49 sritchie: brehaut: sounds like a plan, that's a great idea

15:49 brehaut: which reminds me that i want to look into midje more

15:49 sritchie: thank you guys for the help, the clojure community's been fantastic

15:57 brehaut: it is definately time for a pot of tea

15:57 amalloy: brehaut: make some for sritchie too

15:58 sritchie: btw that #(if ...) thing you did earlier is a complicated version of when-not

16:00 brehaut: i would pay money for a good A3 cheatsheat/quickref poster

16:00 amalloy: &(when-not (zero? 0) 10)

16:00 sexpbot: ⟹ nil

16:01 sritchie: amalloy: does when-not return the value that it stops at?

16:01 amalloy: no, when-not is just a tweaked version of if, not of some

16:01 sritchie: gotcha

16:01 amalloy: you might also look at (first (filter #(when-not ...)))

16:01 brehaut: sritchie: there is a large family of if and when functions

16:02 amalloy: or i guess (first (filter pos? coll))

16:02 now that i've actually read your or expression :P

16:03 sritchie: hey, I like that better

16:03 amalloy: if you didn't, i'd suggest getting your head examined :)

16:05 sritchie: especially since my test was sort of meaningless, just meant to reassure me that this damned data exists, I can (take 10 (filter pos? coll)) to my heart's content

16:06 amalloy: &(->> (range) (filter even?) (filter odd?) first)

16:07 my favoritest infinite loop

16:07 sexpbot: Execution Timed Out!

16:07 brehaut: huh. so it is

16:07 amalloy: find me the first odd even number, plz

16:08 sritchie: very nice

16:09 tonyl: wouldn't that be just 0

16:10 * tonyl hates that math fades away from his brain at an exponential speed, maybe faster

16:12 brehaut: ,[(odd? 0) (even? 0)]

16:12 clojurebot: [false true]

16:13 amalloy: one that's a little sneakier is (->> (range) (map (partial * 2)) (filter odd?))

16:16 sritchie: One quick question -- for that particular method we discussed, is it preferable to convert the java array into a vector, after the mutation?

16:16 tonyl: I guess I meant mathematically speaking

16:17 sritchie: to use it in clojure world?

16:17 sritchie: yeah, with incanter -- I need to cut the array up and form 2d time series arrays

16:17 brehaut: tonyl: ok. how about this. Oddness is defined in terms of evenness. Evenness is defined as devisible by 2 with no remainder

16:17 oddness is the complement of evenness

16:18 tonyl: so 0 can't be use as a value if it is the pivot used to test evenness

16:19 raek: sritchie: the functions in clojure's sequence library will call seq on the argument, so to use arrays with map, filter, reduce, et.c. you donät have to do anything

16:19 tonyl: but we need practicality in programming so that would suffice :P

16:19 raek: *don't

16:19 brehaut: tonyl: i dont understand?

16:19 sritchie: raek: but is it preferable to convert to vector to get immutability?

16:20 brehaut: sritchie: someone has to go out of their way to mutate the array

16:20 using (frinstance) aset

16:20 or passing it to some java

16:20 sritchie: brehaut: got it, and since I'm writing the code, (vector ... ) would just be an extra operation

16:20 brehaut: yes, although you'd use vec

16:21 tonyl: I mean we are using 0 in the implementation of even? to test if 0 is even or not

16:22 raek: if you can't know whether the other code in your progam (or the libraries it uses) will respect your wish for it to remain constant, then I guess you need to create a immutable version of it

16:22 brehaut: tonyl: in what sense? (defn even? [n] (= 0 (mod n 2))) would be my first guess at the imp

16:23 raek: if it never escapes your function in array form, there's no need to worry

16:23 sritchie: raek: got it, makes sense

16:23 raek: you could just call seq on it to hide the fact that the data is in a vector

16:23 tonyl: brehaut: but you are trying to find the evenness of 0 by testing an operation (mod) against 0

16:24 brehaut: thats fine

16:24 surely

16:24 tonyl: yeah it is

16:25 I am just saying that I was thought in math classes that 0 can be even or odd and positive or negative

16:25 brehaut: im not sure i understand how that invalidates the 0 as a part of the series of even numbers though

16:26 hiredman: http://en.wikipedia.org/wiki/Parity_of_zero

16:26 tonyl: that is not true

16:27 brehaut: hiredman: huh, scales make the meaning even particular intuitive

16:28 tonyl: hiredman brehaut: thanks for the info. I am going to have to send a very angry letter to my math professors now

16:29 brehaut: that would be a funny letter :P

16:29 hiredman: please do, be sure to also complain if you were taught that multiplication is repeated addition

16:30 tonyl: a quote from the wiki page 'For them the question exemplifies "common knowledge ... that any well-educated adult should have"'

16:31 i guess i am not an adult yet then

16:31 hiredman: yeah they did that too

16:31 pdk: ,(Math/pow 2 50)

16:31 clojurebot: 1.125899906842624E15

16:31 pdk: great

16:31 hiredman: http://scienceblogs.com/goodmath/2008/07/teaching_multiplication_is_it.php

16:32 brehaut: obligatory xkcd http://xkcd.com/123/

16:33 hiredman: that is a good one, I'd not seen it before

16:34 brehaut: it was footnoted in the most recent one

16:34 i had forgotten about it

16:34 (being bad at both physics and bond films)

16:40 pdk: ,(Math/pow 2 25)

16:40 clojurebot: 3.3554432E7

16:58 sritchie: hey guys, is it preferable to typehint on java interop as a matter of course (for a third party API, say), or is it best to do it only on performance bottlenecks, as the clojure documentation suggests?

17:03 tonyl: performance bottlenecks except for swing, swing doesn't like reflection

17:03 Raynes: Swing doesn't like humanity.

17:07 joly: ,(doc gcd)

17:08 clojurebot: Gabh mo leithscéal?

17:08 ossareh: is there a tool that does the reverse of hiccup? i.e. reads some html and gives me a bunch of vectors?

17:08 brehaut: ossareh: enlive

17:08 ossareh: brehaut: of course!

17:09 bendlas: only it gives you {:tag :html :attrs {} :body []}

17:09 raek: enlive<->hiccup https://gist.github.com/633049 :-)

17:10 brehaut: raek: nice :)

17:10 raek: there are other wrapping libs than Enlive that use Tagsoup for parsing

17:11 some of them output data in hiccup style

17:11 ossareh: That is awesome

17:12 So, while we're on this - my app has the need to create html - which I was hoping to later on postwalk to replace certain things in the tree - i.e. if it see <r:user:name> it knows to replace it with (:name user). Is there such a thing already?

17:13 raek: enlive can match and replace elements

17:13 ossareh: awesome

17:13 raek: it is often used as a html templating engine

17:13 that's the thing it does besides the parsing

17:14 bendlas: indeed and it's the winningest html templating engine i know of, btw

17:14 konr: I've got a package "foo" with a global *bar* and many different function sets operating on it so that there are namespaces foo.fun1, foo.fun2 etc. Where should I put *bar*? In a new namespace like foo.variables? Or I can :use foo.core on foo.fun1 etc and vice versa?

17:14 raek: example for a guestbook: https://github.com/raek/lcug-guestbook/blob/master/src/se/raek/lcug/guestbook/view.clj

17:15 ossareh: huh - I've been using hiccup for the past 2 or so months. Is enlive significantly better suited to this type of thing? (i.e. is it worth the time to convert)

17:15 raek: running server: (beware of retro 90's html, your eyes might hurt a bit) http://services.raek.se/guestbook/

17:16 ossareh: It is very likely that much more of my application will have the html created in something like TinyMCE and data just "slotted in".

17:16 raek: AFAIC, hiccup only does clojure data to html conversion

17:16 tonyl: konr: I am guessing you are refering to namespace foo not package "foo"

17:16 konr: tonyl: yes, indeed

17:16 tonyl: konr: usually if it is a global var it goes in the core

17:16 like foo.core/*bar*

17:17 or just the base like foo/*bar*

17:17 raek: konr: namespaces cannot have cyclic dependencies

17:17 ossareh: raek: in that example deftemplate is reading that html, throwing it into a var and then what are the forms after that? Perhaps replacing the content of those entries with the output of the form?

17:18 raek: yes, those forms describe what html elements to match and what to do with them

17:18 you use CSS-style selectors

17:19 ossareh: right

17:19 I do like that. A lot in fact.

17:19 deftemplate seems to be reading from the filesystem - that could come from anywhere I hope?

17:19 raek: the right hand side is a function that takes the subtree and returns a (potentially) altered one

17:20 bendlas: ossareh: enlive is especially worth it, when you have html from other sources. generating new html based on existing html is the thing enlive does.

17:20 raek: yes, it's just one of the convenience macros, iirc

17:20 LauJensen has written about enlive in his blog

17:20 LauJensen: many times :)

17:21 ossareh: raek, bendlas: awesome - thanks. I'm going to spend some quality time with it.

17:22 pdk: ,(apply +)

17:22 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$apply

17:22 pdk: hmm

17:22 brehaut: ,(apply + [])

17:22 clojurebot: 0

17:23 brehaut: apply needs a fn and a seq minimum

17:24 pdk: i was looking for an equivalent to funcall but hey

17:24 guess wrapping the function i generate in extra parens will work

17:24 brehaut: ,(+)

17:24 clojurebot: 0

17:24 pdk: ,(Math/pow 2 13)

17:24 clojurebot: 8192.0

17:24 raek: yes, the first thing in the list just has to evaluate to something that implements IFn. no funcall is needed.

17:25 bendlas: ,(.invoke + 1 2)

17:25 raek: like in Scheme

17:25 clojurebot: 3

17:25 bendlas: ,(.invoke +)

17:25 clojurebot: 0

17:26 raek: ,(* (+ (*) (*)) (+ (*) (*) (*)) (+ (*) (*) (*) (*) (*) (*) (*)))

17:26 clojurebot: 42

17:27 brehaut: haha awesome

17:27 bendlas: wow

17:27 just wow

17:27 brehaut: real simple

17:27 the identity of multiplication is 1

17:28 ossareh: LauJensen: so bestinclass is built with the manly sounding CMS you eluded to close to new year?

17:28 brehaut: if you think of * as reducing its arguments, you'd have (reduce binary_mult 1 seq)

17:29 so you can use (*) as weird-hand for 1, and the rest is basic math

17:34 huh

17:35 the implementation of + is actually really close to that, jsut with some explicity arities and an inline

17:35 s/+/*/

17:36 tonyl: but + with zero args returns 0

17:36 bendlas: yeah, rich knows his algebra

17:37 brehaut: tonyl: yes, 0 is the identity for addition

17:37 tonyl: yup

17:38 mattmitchell: how can i test a files existence in clojure?

17:39 bendlas: see java.io.File

17:40 with convenience fns from clojure.java.io

17:40 mattmitchell: bendlas: excellent thanks!

17:43 bendlas: clojurebot: do you do javadoc?

17:43 clojurebot: Pardon?

17:43 bendlas: ,(javadoc java.io.File)

17:43 clojurebot: java.lang.Exception: Unable to resolve symbol: javadoc in this context

17:43 bendlas: clojurebot: google java.io.File

17:43 clojurebot: First, out of 535000 results is:

17:43 File (Java 2 Platform SE v1.4.2)

17:43 http://download.oracle.com/javase/1.4.2/docs/api/java/io/File.html

17:48 * dnolen is blown away by bookmark+ for Emacs

17:50 zanes_: dnolen: Why?

17:50 Raynes: mattmitchell: (.exists (java.io.File. "/home/matt/somefile"))

17:51 mattmitchell: Raynes: That's exactly what I'm looking for thanks!

17:51 raek: (also consider using clojure.java.io/file for joining path segments in a platform independent way)

17:54 dnolen: zanes: seems like a fantastic way to annotate code w/o cluttering it up with comments while under heavy development. also seems like a great way to annotate other people's code while you're figuring it out.

17:54 raek: interesting

17:55 especially the second usage

17:55 mattmitchell: I have a condition setup, where if the test is true, I'd like to print a message and then call (System/exit 0)

17:55 but the (System/exit 0) part is never executed.

17:55 only the printing of the message

17:56 semperos: you capturing the actions in a do block?

17:56 tonyl: (when true (println "message) (System/exit 0))

17:56 &(when true (println "message) (System/exit 0))

17:56 sexpbot: java.lang.Exception: EOF while reading string

17:56 mattmitchell: no

17:56 tonyl: &(when true (println "message") (System/exit 0))

17:56 sexpbot: java.security.AccessControlException: access denied (java.lang.RuntimePermission exitVM.0)

17:56 semperos: if you're using an if expression, the second form is the 'else' statement

17:57 i.e. the second form after the condition

17:57 mattmitchell: semperos: ok i see

17:57 tonyl: &(if true (do (prn "message") (System/exit 0)))

17:57 sexpbot: java.security.AccessControlException: access denied (java.lang.RuntimePermission exitVM.0)

17:57 semperos: yep

17:57 mattmitchell: tonyl semperos thanks!

17:58 brehaut: mattmitchell: do look at the flow control section of http://clojuredocs.org/quickref/Clojure%20Core

17:58 there are a lot of short hand forms that will make your life easier

18:05 mattmitchell: brehaut: awesome thanks

18:06 brehaut: very helpful indeed

18:06 pdk: ,(Math/pow 2 20)

18:06 clojurebot: 1048576.0

18:11 jweiss_: i know this is only tangentially related to clojure, but somebody here probably knows the answer: when i run 'lein deps', the deps that are SNAPSHOT versions do not get updated from the remote repository, it just copies the existing snapshot from the local repo. is there a way to change this behavior?

18:13 dakrone: jweiss_: lein will check once a day for an update to snapshots

18:13 jweiss_: dakrone: is there a way to get it to check every time?

18:13 technomancy: if you need more than that you should probably use checkout dependencies

18:14 dakrone: jweiss_: you can remove it from your ~/.m2 dir

18:14 technomancy: jweiss_: I attempted to implement that, but the Maven API call to force it to check every time seemed to be a no-op.

18:14 could be I was doing something wrong, but checkout deps are generally a better solution for most cases

18:14 jweiss_: hm. maybe i can run mvn -U ?

18:14 technomancy: that works too

18:14 jweiss_: i suppose rm -rf will work just as well

18:15 ok thanks

18:23 ossareh: so, with enlive, when I deftemplate name file - what are the lookup semantics for where that file is? I'm getting an NPE with all sorts of different path attempts

18:25 brehaut: ossareh: your classpath i believe

18:26 oh, maybe source path

18:28 ossareh: brehaut: cool - looks like you're right (just stepping through the enlive code now) clojure.lang.RT/baseLoader

18:28 brehaut: ossareh: ok cool, i'm making pigs out of the sausage of my own sites implementation

18:29 in lein i have :source-path defined as "src", and inside src i have templates/….html and my deftemplates are qualified with respect to src

18:31 ossareh: aha - when you package up with lein war is everything kept sane?

18:31 brehaut: haha no i use ductape and string :P

18:31 im sure most sane people will chastise me for my deployment strategy

18:32 ossareh: brehaut: I think we're in the same camp - so not chastening from me =)

18:32 brehaut: i git pull on the live site, lein uberjar, kill the old process, java -server -jar ... & disown

18:32 ossareh: heh - pretty much similar except I scp the uberjar from my local machine

18:33 brehaut: ah right. i have all my media resources served by nginx on a subdomain

18:33 andi just point it at the git repo

18:33 technomancy: as long as it's not production code...

18:33 brehaut: technomancy: what do you mean by production ?

18:33 technomancy: live users; your job on the line, etc

18:33 brehaut: oh right

18:33 nope

18:34 technomancy: ok, carry on =)

18:34 brehaut: if it was my job to run my blog, i'd have a lot more time to get the deployment sorted, and i'd earn a lot less :P

18:35 ossareh: technomancy: if I specify resources-path is that imported into a jar / uberjar ?

18:35 technomancy: ossareh: yeah. you don't have to specify it; if you have a resources/ directory, then it will be included in the jar

18:35 ossareh: oh, OK.

18:35 thanks :)

18:36 technomancy: sure

18:37 brehaut: ossareh: theres a bunch of different lein plugins for different automated deployment tools/strategies these days.

18:37 realistically i should put aside half a day to learn one

18:38 ossareh: brehaut: blog about it :)

18:38 brehaut: haha

18:38 no doubt

18:39 __name__: brehaut: would you mind giving me the url to your blog?

18:39 brehaut: http://brehaut.net/

18:39 __name__: does not load for me

18:39 brehaut: comments about the colors can be redirected to /dev/null/

18:40 ;)

18:40 __name__: brehaut: i do not get any meaningful page with chromium

18:40 echo "my eyes!" > /dev/null

18:41 brehaut: hmm. it looks fine in both safari and webkit for me

18:41 and http://www.downforeveryoneorjustme.com/brehaut.net says its up

18:41 __name__: brehaut: i do get /something/.

18:42 * ossareh is trying really hard to say something about something other than the colours on that page....

18:42 ossareh: ;)

18:42 brehaut: ossareh: OMG monads WTF is reasonable

18:42 ossareh: technomancy & brehaut - thanks - I now have my deftemplates working =)

18:43 brehaut: no worries

19:04 joshua__: I'm using duck-streams write-lines method to write a file on a Linux OS which is than read by a C++ program on a Window's OS.

19:05 The program doesn't run as expected. When you open up the file in Notepad there is an invisible char directly before line breaks.

19:05 I get that this is some sort of new lines are different based on operating system thing, but how do I fix this?

19:06 brehaut: the basic newline differences would go the other way

19:06 unix uses \n and windows uses \n\r (i think that way round)

19:07 start with opening the file in a hex editor or something

19:07 joshua__: So what is my actual problem?

19:07 brehaut: you need to look at the files byte contents, rather than a text editors interpretation

19:07 text file encoding is a broad and subtle field for erros

19:08 joshua__: brehaut, how do I view the byte contents?

19:08 brehaut: hex editor or something

19:09 joshua__: http://ubuntuforums.org/showpost.php?p=277111&postcount=2 for linux

19:09 joshua__: thanks

19:09 brehaut: a good hex editor wil lshow you line number, bytes as hex pairs, then the ascii output

19:10 http://stackoverflow.com/questions/10426/what-is-a-good-windows-hex-editor-viewer for windows

19:11 also, check the very first two bytes in the file

19:12 thats where a byte order mark appears if it has been included (common for UCS and some UTF encodings)

19:12 http://en.wikipedia.org/wiki/Byte_order_mark

19:20 joshua__: brehaut, thanks for pointing me in the right direction. If I dig into hex to fix a bug I'm allowed to call myself Mel, right?

19:21 brehaut: only if you rewrite your duckstream to take into account of drum timings to control program flow.

19:21 using a hex editor to fix a bug is just unlucky

19:40 ossareh: OK. enlive rocks.

19:41 brehaut: totally eh

19:42 one really nice property is that you can work on the design by just editing the template without any other webserver or anything in between.

21:00 pdk: (doc bindings)

21:00 clojurebot: Excuse me?

21:00 pdk: (doc binding)

21:00 clojurebot: "([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before. The new bindings are made in parallel (unlike let); all init-exprs are evaluated before the vars are bound to their new values."

21:10 pdk: ,(let [myfn (fn [[arg]] arg)] (myfn))

21:10 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (0) passed to: sandbox$eval930$myfn

21:10 pdk: ,(let [myfn (fn [& [arg]] arg)] (myfn))

21:10 clojurebot: nil

21:13 tonyl: &((fn [& [x y & more]] [x y more]) 1 2 3 4 5 6)

21:13 sexpbot: ⟹ [1 2 (3 4 5 6)]

21:16 brehaut: $source destructure

21:16 sexpbot: destructure is http://is.gd/ub7pAw

21:17 brehaut: well, thats a bunch longer than i was expecting

21:18 tonyl: it's magically longer

21:20 hiredman: maniacally

21:21 brehaut: pretty sure a lot of tea was involved

21:23 tonyl: aaah, i need to extend my nested closure tolerance

21:23 * tonyl forcing himself to read that code to understand every detail

21:26 brehaut: tonyl: have you played about with it? it helps to know what its doing

21:27 pdk: i am officially concurrent programming wizard

21:27 brehaut: offically?

21:27 pdk: apparently trying to optimize an AI tree search algo by making it spawn a new thread for each branch in the tree unchecked is not wise


21:28 brehaut: tonyl: its rewriting a destructuring bind into a bunch of calls to nth etc

21:29 ,(destructure ['a 1])

21:29 clojurebot: [a 1]

21:29 tonyl: brehaut: I figure it creates new symbols based on the destructuring norms that are passed

21:29 brehaut: ,(destructure ['[a b] [1 2]])

21:29 clojurebot: [vec__948 [1 2] a (clojure.core/nth vec__948 0 nil) b (clojure.core/nth vec__948 1 nil)]

21:30 tonyl: yup

21:30 hiredman: that is the tamest sort of destructuring

21:30 brehaut: the output is surprisingly simple compared to the work that goes into producing it

21:31 hiredman: ,(destructure ['{{[x y z] :b} :a} {:a {:b [1 2 3}}])

21:31 clojurebot: Unmatched delimiter: }

21:31 hiredman: ,(destructure ['{{[x y z] :b} :a} {:a {:b [1 2 3]}}])

21:31 clojurebot: [map__951 {:a {:b [1 2 3]}} map__951 (if (clojure.core/seq? map__951) (clojure.core/apply clojure.core/hash-map map__951) map__951) map__952 (clojure.core/get map__951 :a) map__952 (if (clojure.core/...

21:31 pdk: } truly is the best in the land clojurebot

21:33 hiredman: [{:keys [bytes} {:keys [x y z] :as args} :foo :as everything}] ;;ran into something like this in production code today

21:33 danlarkin: a travesty

21:34 brehaut: oh my

21:34 hiredman: danlarkin: right, well joe and I took some steps

21:34 tonyl: [bytes doesn't look like a valid symbol

21:34 danlarkin: good, abominations like that should not stand

21:35 hiredman: the [bytes} should be [bytes]

21:36 then he complained about something like (let [a … b …] (.delete a) b)

21:36 tonyl: haha

21:36 sounds like somebody had code amnesia

21:37 hiredman: so I suggested (let [a …] ((fn [b] (.delete a) b) …)) so he yelled at me for a bit

21:37 danlarkin: oh god

21:37 hiredman: yeah, just like that

21:38 tonyl: wow, did you show him his own code?

21:38 hiredman: oh the destructuring thing was code I had written too

21:42 brehaut: the frightening thing about those snippets is that they are pretty decent in the context of the wider industry

21:43 hiredman: what is the difference between (let [a 1] a) and ((fn [a] a) 1) ?

21:43 no_mind: what is the difference between defn and defn- ?

21:44 hiredman: let can bind primitives to names and fn creates a recur point

21:44 danlarkin: no_mind: defn is ok to use and defn- is wrong

21:44 brehaut: no_mind: defn creates a ns private var

21:44 no_mind: danlarkin: amny clojure libs are using defn-

21:44 brehaut: no_mind: many projects are using C++; doesnt make it right

21:44 danlarkin: if they jumped off a bridge would you too?

21:45 BAM! Mothered

21:45 hiredman: danlarkin is something of a luddite, he complains if I use letfn

21:45 no_mind: well i want to know what is defn- and why not to use it ?

21:45 brehaut: hiredman: its not his fault, he came from python

21:45 hiredman: no_mind: have you read the doc string?

21:45 no_mind: no

21:45 tonyl: &(doc defn-)

21:45 sexpbot: ⟹ "Macro ([name & decls]); same as defn, yielding non-public def"

21:45 brehaut: no_mind: you dont want to use because someone will come along later and curse you that the fn they need is private and now tey need to copy and waste

21:46 hiredman: it is infact very easy to get access to a private var

21:46 brehaut: hiredman: oh real? that would be handy

22:04 technomancy: private is more about reducing the surface area of your API than actually hiding anything

22:04 brehaut: interesting

22:04 technomancy: why should foo.mylib.<TAB> complete to a bunch of internal junk you don't ever need to call?

22:04 brehaut: sure that makes sense

22:05 time for the stupid question: emacs clojure mode supports that?

22:05 technomancy: no, you need swank

22:05 brehaut: ah

22:06 pass on that for a while then

22:07 technomancy: suit yrself

22:08 brehaut: yup :) while it would be handy i am still pretty bad at emacs

22:12 Raynes: technomancy: Have you ever done any gnus stuff?

22:15 * Raynes withdraws the question he intended to ask, because he realizes how little he actually cares about making gnus work properly. :>

22:17 zippy314: Hi, I'm wanting to regex replace on strings and a google search yields re-gsub in clojure-contrib.str-utils. and also re-replace in clojure.contrib.strings What's the difference and which should I use?

22:17 hiredman: you should check the .replaceAll method on String and see if it doesn't do what you want

22:18 zippy314: I also what lower-casing and capitalization. Should I just use java methods?

22:18 hiredman: yes

22:20 zippy314: ,(.replaceAll "fish bonk" #"\w")

22:20 clojurebot: java.lang.IllegalArgumentException: No matching method found: replaceAll for class java.lang.String

22:21 zippy314: ?

22:21 hiredman: zippy314: when I said check I meant "read the javadoc"

22:21 zippy314: it's there.

22:21 hiredman: read the javadoc

22:21 zippy314: http://download.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#replaceAll(java.lang.String,%20java.lang.String)

22:21 oh (blush)

22:21 ,(.replaceAll "fish bonk" #"\w" _)

22:21 clojurebot: java.lang.Exception: Unable to resolve symbol: _ in this context

22:22 zippy314: ,(.replaceAll "fish bonk" #"\w" "_")

22:22 clojurebot: java.lang.ClassCastException: java.util.regex.Pattern cannot be cast to java.lang.String

22:22 hiredman: you still haven't read the doc

22:22 infact you haven't even read the link you just posted

22:22 zippy314: yah. sorry.

22:24 ok. but please explain why I should be using this instead of the contrib libs.

22:24 brehaut: zippy314: its right there in the javadoc

22:25 hiredman: because dependence on contrib, given the dubious quality of lots of contrib is bad

22:25 zippy314: (.replaceAll "fish bonk" "\\W" "_")

22:25 ,(.replaceAll "fish bonk" "\\W" "_")

22:25 clojurebot: "fish_bonk"

22:26 zippy314: Hmmm. I'm not so keen about regexs encoded as strings. It's a pain to have to escape the escapes and so on..

22:27 brehaut: hiredman: in this instance, the fns in question have moved from contrib to clojure itself havent they?

22:27 jimbostrudel: you could store them in a file and read them in

22:27 brehaut: http://clojure.github.com/clojure/clojure.string-api.html

22:28 hiredman: brehaut: *shrug*

22:44 zippy314: brehaut: from that url it says to use: (:require '[clojure.string :as str]) But when I do that, I get "java.lang.Exception: lib names inside prefix lists must not contain periods" any idea what gives?

22:45 brehaut: is that part of your ns definition?

22:45 tonyl: (:require doesn't need the apostrophe

22:46 brehaut: zippy314: ie do you have (ns my.ns (:require …))

22:46 technomancy: Raynes: it's been a while since I had a really tuned gnus

22:46 Raynes: technomancy: It was fairly easy getting it to fetch my mail. The problem is that there are no mail groups. INBOX doesn't exist.

22:47 It's bizarre.

22:47 <3 thunderbird

22:47 scottj: you mean you can't subscribe to inbox?

22:49 Raynes: scottj: Yes. It claims that it doesn't exist.

22:50 scottj: but you can see the maildir/whatever file(s)?

22:51 Raynes: The only thing it's actually showing me is the default help group.

22:51 zippy314: brehaut: yes I was. The trick was what tonyl said.

22:51 brehaut: zippy314: ok cool.

22:51 zippy314: tx

22:52 scottj: Raynes: have you consulted the manual?

22:52 Raynes: Yes, and at least 4 different step-by-step tutorials. It doesn't look like anybody else has ever encountered this problem.

22:52 It isn't a huge deal. I'll ask in #emacs eventually.

22:53 scottj: what select method are you using?

22:53 anyway, email clients that only show one message at a time are lame.

22:54 Raynes: nnml

Logging service provided by n01se.net