#clojure log - Jun 23 2008

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

4:08 jmbr: hi

4:09 jgrant: hi

7:24 spacebat_: I think I'm missing something basic about clojure

7:24 (def x 1) says I've bound #'user/x

7:24 I can evaluate it with x

7:24 and get 1

7:24 drewr: spacebat_: You're in the user namespace by default.

7:25 spacebat_: yup

7:25 like common lisp

7:25 but there is no setf

7:25 drewr: :-)

7:25 spacebat_: (set! x 2) doesn't work

7:25 (set! user/x 2) doesn't work

7:26 drewr: Clojure doesn't let you set a value that easily.

7:26 It's a feature.

7:26 spacebat_: nor (set #'user/x 2) nor (var-set x 2)

7:26 drewr: x is a Var, which are immutable.

7:26 spacebat_: but in a few places they say that Vars are mutable (thread locally)

7:27 "While Vars ensure safe use of mutable mutable storage locations via thread isolation..." (http://clojure.org/refs)

7:28 drewr: You have to wrap it in a BINDING form, which is thread-local.

7:28 spacebat_: each time I update it?

7:28 but when I leave the binding that change is gone

7:29 drewr: What problem are you tring solve?

7:29 trying

7:29 spacebat_: I have a recursive function

7:29 I thought I could close over a variable to count the number of invokations

7:30 like I can in common lisp

7:30 drewr: There's an idiom for that in Clojure. Likely you'll want LOOP..RECUR.

7:31 Something like (loop [ct 0] ... (recur (inc ct))).

7:31 spacebat_: pjb3 mentioned that this morning, but I'm not getting far with the docs I'm afraid

7:31 it seems on the one hand I don't know enough lisp to understand some things

7:32 but I know enough common lisp to go about things the wrong way :)

7:32 drewr: You probably write imperative CL, which won't help.

7:32 You need to think more functionally (which Clojure forces you into).

7:33 spacebat_: yes I'm not used to being forced

7:33 so loop..recur operats on refs

7:34 drewr: They operate on whatever arguments you give them.

7:34 Not Ref-specific.

7:34 spacebat_: and can go anywhere - its not like a loop construct is like a foor or while in imperative languages

7:34 ok

7:34 drewr: Look through boot.clj to get some examples.

7:34 spacebat_: thanks drewr I will

7:35 looking at clojure I thought, I should learn some CL in order to 'get' it

7:35 but it seems clojure is different enough that I should just focus on it

7:37 drewr: I agree.

8:10 cgrand: spacebat_, can you paste your code? http://paste.lisp.org/new/clojure

8:13 lisppaste8: spacebat_ pasted "trivial recursive function" at http://paste.lisp.org/display/62714

8:15 spacebat_: the paste is of the function before I tried loop...recur

8:15 because I have no idea how to use it in a recursive context

8:16 cgrand: well loop...recur is here to work around the lack of TCO on the jvm. Since your function is not tail recursive you can't use loop...recur to write it

8:18 spacebat_: is there a way to count how many times fib is called?

8:19 cgrand: as said before, with binding and set!, let me annotate your paste

8:20 spacebat_: right, I couldn't see how to keep the value of the binding after I'd left the scope

8:20 or can the binding wrap the function...

8:23 lisppaste8: cgrand annotated #62714 with "counting fibs invocations" at http://paste.lisp.org/display/62714#1

8:25 spacebat_: right, so (def fib-count) is 'unbound' because there is no initial value, it looks up and finds the binding

8:26 cgrand: you can provide a default (root) value but you are unable to alter it with set!

8:26 spacebat_: I tried using def and set! but when I threw in binding as well, put it in the wrong place

8:26 ok

8:26 but binding allows it

8:27 so this is imperative style, but binding limits the scope

8:28 cgrand: and the only way to change the root value is to re-def. Yup, binding sets a value for the var and allows you to alter it

8:29 spacebat_: thanks a lot, that brings some pieces together

8:30 cgrand: yw

8:30 spacebat_: now to find out how to get command line args

8:30 someone posted a patch to the group but I assume its been integrated by now

8:31 cgrand: don't forget to put -- before your args

10:27 rhickey: Hello, could clojure.lang.Numbers.compare be exposed? (as <=> or whatever please you) Without it an unsuspecting user (eg me) may write comparators using substraction and get overflows on the return value of the Comprator :-(

10:28 rhickey: ok

10:29 cgrand: thanks!

10:32 rhickey: Although I heard <=> referred to as the "spaceship operator" at a Java One talk and instantly developed an aversion to it...

10:35 cgrand: it reminds me of text-mode breakout games but it was the only one (with cmp) to come to my mind.

10:36 signum ?

10:37 rhickey: ah

10:37 but that is a unary op

10:38 cgrand: you're right :-(

10:38 rhickey: one I want to add

10:45 cgrand: or AFn.compare could be changed to not use intValue

10:57 rhickey: cgrand: what would that solve?

10:58 compare is defined to return int in Comparator

11:11 StartsWithK: why there is no (char-array) and #^chars hint?

11:12 rhickey: StartsWithK: haven't gotten to it - first pass was for numerics

11:13 cgrand: rhickey: By changing AFn.compare to not use Number.intValue, I mean replacing the call to Number.intValue by something signum-like. It would make use of fns as comparators more foolproof: a comparator fn would then be able to return any number without caring whether it firs into an int or not.

11:13 s/firs/fits/

11:14 rhickey: seems like double work

11:37 ok - I've added compare, and based sorts on compare:

11:37 user=> (sort [19 3M 9.0 2 7 nil 4])

11:37 (nil 2 3M 4 7 9.0 19)

11:40 cgrand: thanks!

13:00 StartsWithK: how do i create array of bytes (not java.lang.Byte)?

13:01 rhickey: (make-array Byte/TYPE 100)

13:02 or (make-array (. Byte TYPE) 100) if you are not on SVN

13:03 the names of the classes corresponding to the primitives are static members of their respective boxed types, all called TYPE

13:04 StartsWithK: rhickey, this works perfectly, thanks

13:33 Lau_of_DK: rhickey: In the concurrency talk you mentioned some theory on log(n) calc times (or O(n)) and similar things, which were important in regards to obtaining near constant time. Do you have some links for some background reading on these issues?

14:49 abrooks: Chouser: What was the last version of Clojure SVN you had working with Enclojure?

14:49 rhickey: Lau_of_DK: you can find some info by googling bagwell hash tries

14:50 abrooks: Lau_of_DK: This wikipedia page has two good links: http://en.wikipedia.org/wiki/Hash_array_mapped_trie

14:55 Lau_of_DK: Thanks to both of you

16:25 arbscht: does clojure have trouble handling class names containing .? I can't access java.awt.geom.Point2D.Double for example (ClassNotFoundException)

16:26 rhickey: the real name of that nested class is: java.awt.geom.Point2D$Double

16:26 arbscht: I see

16:27 thanks

16:27 rhickey: sure

16:37 jgrant: hey everyone, i have a question about var scope

16:38 I've defined a global var *x* in a specific package 'mypackage

16:38 now after calling the load-file function I'd like to access this variable and update it

16:39 it seems the loaded file has it's own scope if i do a (def *x*) it seems to be a copy ?

16:40 rhickey: are you still in the same package?

16:40 namespace

16:40 jgrant: yes

16:41 rhickey: what makes it feel like a copy?

16:44 jgrant: it doesn't have the value assigned in the parent file

16:45 thanks for bearing with me i'm still figuring my way around clojure's idioms

16:45 rhickey: if in the defining file you say (def *x* 42), then after loading *x* should be 42, no?

16:45 jgrant: yea i agree it should i must be doing something wrong

16:46 rhickey: are you def'ing it again somewhere?

16:48 jgrant: yes in the loaded file

16:48 rhickey: 2x in the same file?

16:48 jgrant: once

16:49 once in the parent and once in the loaded file

16:49 rhickey: I don't understand what you mean by parent then

16:50 foo.clj defs x and loads bar.clj that defs x?

16:50 jgrant: clojure loads file1 (which defs var *x*) which loads file2 (which also defs var *x*)

16:50 yes

16:50 rhickey: both in same ns?

16:50 jgrant: yes

16:51 rhickey: they both have in-ns explicitly?

16:51 jgrant: bar.clj has same (in-ns ...) as foo.clj

16:51 yes it's explicit

16:51 rhickey: last def should win

16:52 jgrant: should foo.clj see the update made to *x* by bar ?

16:53 rhickey: exprs happen in order, latter see former

16:54 jgrant: ok it's working now , not sure what i fixed

16:54 another related question

16:54 bar.clj will be updating *x* in a thread

16:54 rhickey: oh

16:54 jgrant: would (dosync (def *serve-count* (inc *serve-count*))) be valid ?

16:55 rhickey: updating by def?

16:55 jgrant: yea

16:55 rhickey: then *x* should be a ref and you shouldn't be re-def-ing it

16:55 (def *cnt* (ref 0))

16:56 (dosync (commute *cnt* inc))

16:56 jgrant: ah i see !

17:00 I'm getting 'Unable to resolve symbol: *x*' when i try that ?

17:02 rhickey: are you launching your threads in bar prior to the def in foo?

17:02 jgrant: not at all

17:02 (def *cnt* (ref 0))

17:02 is one of the first lines in foo.clj

17:03 uggh, you are right

17:03 i was not !

17:06 thx rich

17:06 rhickey: sure

17:21 jgrant: mmmm, (println *x*) doesn't seem to report the right value

17:21 rhickey: @*x*

17:22 jgrant: um yea that's what i mean

17:22 rhickey: you want the value in the ref, not the ref itself

17:22 jgrant: it seems to do with how many threads are trying to update *x*

17:22 if i run a few at a time i see the value inc

17:22 if i run a lot it seems to stay at 0

17:26 aha

17:29 calling (dosync (commute *cnt* inc))

17:29 has to be in the enclosing function used by the thread

17:29 if it's in another function called by the thread then it does not work

17:38 (or maybe it requires the dosync to be in foo.clj)

17:39 having it in bar.clj doesn't seem to work

17:52 The dosync doesn't work if it's in a function that exists also in foo.clj

17:52 seems like it needs to be in the same function

17:52 that is used as the thread

18:00 rich : nevermind another one of my own bugs, it works exactly as you described

23:33 why does not work in clojure ?

23:34 (map (fn [fname]

23:34 (load-file (str (. (File. ".") getCanonicalPath) "/src/" fname))) '("file1.clj" "file2.clj" "file3.clj"))

Logging service provided by n01se.net