#clojure log - Jun 07 2008

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

2:01 sohail: hey, I don't know scheme but I know enough of CL to keep me dangerous. Is reading the reference enough for me or do I need to be a scheme geek to use clojure?

8:42 cgrand: Lau_of_DK: if you are still interested in a primes seq: http://clj-me.blogspot.com/2008/06/primes.html

8:42 Lau_of_DK: Oh I am :) Thanks

8:43 Is that your own blog?

8:51 cgrand, that is an amazing prime routine - probably the best Ive ever seen

8:52 takes 2500 primes in 0.033582 msecs

8:52 cgrand: thanks, that's what I thought when I see the haskell version (I lost the url)

8:54 Lau_of_DK: insane, takes 5000 primes in 0.03---

8:54 cgrand: the primes are cached

8:54 Lau_of_DK: I have to study it more closely soon as Im done with the task Im on - Look forward to some questions :)

9:03 cgrand: I can't guarantee I'll be there the whole afternoon

9:08 Lau_of_DK: Its ok, dont hang around for my sake, it'll be hours before I can sit down and focus on Clojure - But thanks alot for the link, its really helpful

9:11 cgrand: btw when you do (time (take 2500 primes)) you don't compute 2500 primes (laziness is a virtue :-)) (time (dorun (take 2500 primes))) will force computation

9:11 Lau_of_DK: But it outputs something that looks like 2500 numbers to the screen - they must have been computed

9:17 cgrand: if it outputs them then yes their are computed (or retrieved from cache). Here (time (take 2500 primes)) "Elapsed time: 0.038832 msecs" but outputs only "(". While (time (dorun (take 2500 primes))) "Elapsed time: 136.393034 msecs"

9:36 blackdog: hi, can someone shed some light on these comments for me, rhickey: using (JThis. ...) makes that pretty declarative too

9:36 13:08 Chouse1: Yeah I converted all my (new...)s to (JFoo. ...)s this morning. I'm still pretty ambivalent.

9:37 what's this syntax for java objects?

9:45 hoeck: blackdog: (JFoo. ..) means (new JFoo ..)

9:46 blackdog: http://clojure-log.n01se.net/date/2008-06-03.html (search for "(new Foo)")

10:10 slava: rhickey: does all mutable state in clojure go through stm?

10:46 rhickey: slava: no, there are 3 kinds of references that can change - one is transactional, one is atomic (actor-like) and one is thread-local

14:40 Lau_of_DK: cgrand, you here?

15:00 Gents, is clojure.org the only place that I can get documentation for this language?

15:07 JamesIry: Besides miscellaneous blog posts, that's about it.

15:08 Lau_of_DK: I've had a few instances now where I couldnt find documentation on function, like recur, where is it documented?

15:20 Anybody here got some informative links that arent found from clojure.org? (regarding clojure that is)

15:27 JamesIry: Sorry, I had to step away for awhile. Here's where recur is documented. http://clojure.sourceforge.net/reference/special_forms.html

15:28 Lau_of_DK: No need to appologize, but thank you for the link :)

15:29 I dont know if Im alone with this, but I have a little bit of a hard time adjusting my mutatable mind to functional programming- How did you guys embrace is? Do I need to take a trip down Haskell lane ?

15:29 JamesIry: Lau_of_DK: I have the advantage of having learned Scheme and then Haskell first.

15:30 Lau_of_DK: Yea thats gotta be an advantage

15:30 JamesIry: I don't think it's absolutely necessary to learn Haskell first, but it does have the advantage of pretty much forcing you to jump in head first

15:30 Lau_of_DK: I think Ive solved about 20% of all Euler challenge in single (loop) statements, so this is a change of mindset^3

15:30 k

15:36 JamesIry: Lau_of_DK: But another alternative is to work through excercises in SICP but use Clojure. 90% or more of the book avoids mutation.

15:48 Lau_of_DK: Yea, its just that I just did that in SBCL, so its a daunting task

15:48 JamesIry, do you know of any tutorials on how to get started with fn programming?

15:49 JamesIry: If you did SICP in SBCL then you should be covered

15:49 Lau_of_DK: maybe, but I dont feel covered. My first instinct is always to jump into some with sideeffects :)

15:52 rsynnott: Lau_of_DK: use erlang or something for a bit; it sorta forces the issue :)

15:52 JamesIry: Well, I really liked "Haskell: The Craft of Functional Programming" http://www.cs.kent.ac.uk/people/staff/sjt/craft2e/. I wasn't quite as impressed by "The Haskell School of Expression."

15:53 Lau_of_DK: gah :) Maybe I'll take my own advice and try to form some sort of tutorial. I quite like the example where some guy ported Practical Common Lisp Chpt 3 to Clojure

15:53 Ok, thanks JamesIry, I'll check it out

15:53 JamesIry: There ya go. Somebody else ported "The Reasoned Schemer" to Clojure

15:53 If you do that you learn both functional and logic paradigms.

15:56 Lau_of_DK: Sounds good

16:09 user> (nth primes 5)

16:09 11

16:09 user> (take 5 primes)

16:09 (1 2 3 5 7)

16:09 Is this done on purpose?

16:14 wybiral: Think about indexing it, from 0

16:15 vs taking 5 actual objects

16:15 Lau_of_DK: But by that logic it should return 5, not 11 ?

16:15 Its gone to index + 1, not zero-index

16:17 Chouser: I would recommend doing projecteuler problems, perhaps from the beginning, in clojure.

16:18 Lau_of_DK: Chouser, Im already on it - though I didnt quite go back to the beginning

16:18 wybiral: Lau, I don't get what you mean... 1 would be the 0th object

16:21 Lau_of_DK: nevermind, its the coffee talking :(

16:21 You're right, its just the zero-index thing

17:59 user> tst

17:59 [:sum 1061897 :offset 5]

17:59 how do I access the 2 values in tst ?

18:03 Chouser: (:sum (apply hash-map tst))

18:04 (nth tst 3) ; ==> 5

18:05 (second tst) ; ==> 1061897

18:05 Lau_of_DK: Thanks Chouser, thats exactly what I needed - In addition: #1 clue that you've spent to much time in Emacs: I wrote "th" and tabbed, expecting it to complete to "thanks" .. hehe :)

18:06 Chouser: ;-)

18:06 (let [{:keys [sum offset]} (apply hash-map tst)] [sum offset]) ; => [1061897 5]

18:25 hm, I thought take-ns would be in boot.clj by now.

19:04 Lau_of_DK: What is [_] compared to [] ?

19:38 I have a sequence of ints, which I need to compare numerically to a value, how do I cast the seq to int ? (similar to SBCLs parse-integer)

19:41 JamesIry: Does't parse-integer attempt to parse a string to an integer?

19:41 Lau_of_DK: yea

19:41 (def roofseq

19:41 (fn [s roof]

19:41 (loop [next 1]

19:41 (if (> (apply int (first s)) roof)

19:41 (rest s)

19:41 (recur (conj s (nth s (inc next))))))))

19:41 Its the (if) that I need to get working

19:45 JamesIry: I'm still not following. s is a sequence of ints, right?

19:45 Lau_of_DK: Yes, I want to say that I want all the primes below 1000 with (roofseq primes 1000)

19:47 JamesIry: So you need two sequences. One is the sequence you're looking through and the other is the sequence that has passed the test so far.

19:47 Lau_of_DK: yea, the idea was just to take the nth, start with 1 and move up, once I exceed the roof I'll return the _rest_

19:48 thats why Im conj'ing on the next value

19:48 JamesIry: Taking the nth can be an expensive operation depending on the type of sequence

19:48 Lau_of_DK: How would you go about it?

19:49 I tried (filter (fn [x] (> x 5)) fibs)... but that of course doesn't figure out that it should break on the first false value, so it keeps going

19:50 JamesIry: Plus, it's the opposite meaning

19:51 Lau_of_DK: details, details

19:51 JamesIry: :)

19:51 Lau_of_DK: But can you help me workout the rootseq?

19:51 JamesIry: Just a sec

19:51 I wanted to see if clojure had an equivalent to Haskell's takeWhile

19:52 The gist is that you have a function that takes a sequence and a predicate (a function that returns true or false when given an element). Internally it calls a second recursive function with the sequence as the first argument and an empty sequence as the second.

19:53 Lau_of_DK: ok :)

19:55 JamesIry: The recursive function examines the first element of the first sequence which I'll call candidate. If candidate passes the predicate the function recurses on itself with the rest of the first sequence as the first argument plus candidate conjed onto the second argument as the new second argument. If candidate does not pass then the result is the second argument reversed.

19:55 In other words it shrinks one sequence while building up the other.

19:55 Lau_of_DK: k

19:56 JamesIry: The base case is when it finds the first element that doesn't match the predicate

19:57 Oh yeah, second base case when the first argument is an empty sequence :-)

19:58 Lau_of_DK: ok

20:01 oh wait... isnt (rest) lazy ?

20:01 (first fibs)

20:01 0

20:01 (rest fibs)

20:01 java heap space exhausted...

20:01 ??

20:04 JamesIry: That's a bit surprising

20:04 Lau_of_DK: yea - I know my stream lib in SBCL would have handled it differently

20:04 (which is not a sign of quality :))

20:04 JamesIry: I just thought of a better way to write takeWhile in clojure :-)

20:04 Lau_of_DK: Go go go! :)

20:06 JamesIry: Hmmm...my clojure is pretty weak

20:06 Lau_of_DK: That makes 2 of us

20:07 Why does this simple loop crash?

20:07 (def roofseq

20:07 (fn [s roof]

20:07 (loop [offset 1]

20:07 (if (> (first (take offset s)) roof)

20:07 (take offset s)

20:07 (recur (inc offset))))))

20:09 JamesIry: I'm struggling to write the clojure (I'm learning I'm learning) but the possibly better takeWhile than what I wrote before is to mimic Haskell's exactly...

20:09 takeWhile takes a predicate and a sequence. Base cases are empty sequence or candidate that doesn't match predicate. For the base case it returns an empty sequence.

20:10 For the non base case it returns a lazy stream consisting of the candidate as the head and (takeWhile p (rest s)) as the tail

20:10 p is the predicate argument, s is the stream argument

20:12 Lau_of_DK: sounds good

20:14 JamesIry: LOL, or just use take-while. http://clojure.sourceforge.net/reference/sequences.html

20:14 Lau_of_DK: ARGH

20:14 :D

20:15 and I just got mine working

20:15 Just replace (first ) with (last ) ... man

20:15 Why do I do this to myself, coding after midnight :(

20:18 JamesIry: And here's the impl, which is what I was describing.... (defn take-while [pred coll] (when (and (seq coll) (pred (first coll))) (lazy-cons (first coll) (take-while pred (rest coll)))))

20:19 Lau_of_DK: sounds easy enough - wonder why I couldnt do that

20:19 JamesIry: The only thing I would be tempted to do differently is add a let to bind (first col) once

20:22 Lau_of_DK: why would you do that?

20:23 JamesIry: Because it's used twice in the function

20:23 Plus adding a let helps self document

20:23 Lau_of_DK: ah ok

20:23 good practice probably

20:37 Great, I've solved the first 3 Eulers in Clojure and learned a few tips and tricks doing it. Thanks for all your help JamesIry and Chouser

20:37 JamesIry: NP

20:48 rhickey: Chouser: for take-ns, see partition

20:54 JamesIry: rhickey: have you seen this - http://openjdk.java.net/projects/mlvm/jvmlangsummit/

23:35 Chouser: rhickey: partition is a much better name, thanks.

Logging service provided by n01se.net