#clojure log - Jul 06 2008

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

0:22 Nafai: Yay, just wrote my first real working Clojure code

0:25 http://paste.lisp.org/display/63330

0:26 Any critiques would be welcome :)

0:48 wa

0:48 Whoops

1:11 slava: hey nafai

1:13 Nafai: Hi

1:14 slava: i heard you moved away from austin

1:14 Nafai: Yeah, moved back to Utah.

1:15 Got a pretty good job and I have more friends here

1:55 arbscht: Nafai: fwiw: http://paste.lisp.org/display/63330#1

1:55 Nafai: I make no assurance that it is in any way better, but maybe it gives you some ideas :)

1:58 * Nafai reads

1:58 Nafai: Thanks arbscht

2:01 How do I assign a variable at the REPL?

2:01 let won't work because the scope is over once you close the )

2:02 jgrant: (def varname value)

2:03 arbscht: the value is optional, too

2:07 Nafai: How do I find out what type objects in a seq are? I'm trying to print the sequence and I keep getting class-cast exceptions

2:12 Ah, it's happening earlier

2:19 slava: Nafai: look who's here

2:19 Nafai: Hi erg

2:20 erg: hi Nafai

2:20 how's the codez?

2:21 Nafai: Not bad

2:21 Thought I'd pick a little Clojure to see if I like it

2:33 Any ideas on how I would do this?

2:33 I want to have a data file that has a vector per line

2:33 Like: [1 2 3]

2:33 I want to be able to use the reader and process each vector

2:34 Maybe it's just I can't figure out the proper thing to do with loop and recur but I can't figure it out

2:51 arbscht: Nafai: if you wrap the contents of your file in [] you will get a vector of vectors when you (load-file)

2:53 Nafai: Oooo

8:48 ballzack3: l

8:49 hello

8:56 StartsWithK: how can i create instance of nested class?

8:56 blackdog: class$nested

8:58 StartsWithK: Unable to resolve classname: Ellipse2D$Float

8:58 i have (import '(java.awt.geom Ellipse2D))

9:01 blackdog: try Ellipse2D$Float

9:01 try import Ellipse2D$Float

9:05 StartsWithK: blackdog, that worked, thanks

9:06 blackdog: cool,

9:24 kotarak: Is it possible to have a lazy map like lazy-cons? ie. the value is only evaluated when I access the key.

11:23 Chouser: kotarak: I was just discussing that with abrooks.

11:24 kotarak: I think you could use proxy to implement an IPersistenHash that has that behavior, but as far as I know there's no way as easy as lazy-cons

11:25 ...and unless you're going to assoc onto it, y really might just be talking about a memoized function.

11:28 kotarak: the use would be in the return type of a function, where certain things must be done lazily. One could of course return a lazy list, but the gets ugly when the return value changes

11:40 Chouser: you could return a memoized function, right? That would cover your use case?

11:42 kotarak: I would like to just get the value, w/o having to call a function.

11:43 ie. the funcll would be transparw

11:43 oops

11:43 the funcall would be transparent to the program

11:45 ktne: hello

11:45 is clojure the best lisp for jvm?

11:48 kotarak: there is also a scheme, but don't remember the name.

11:49 ktne: is that a standard scheme?

11:50 kotarak: I think so, R5RS IIRC.

11:50 ktne: i see

11:50 i was thinking about something more experimental

11:50 not just a standard implementation

12:12 mac_: ktne: experimental in what way? clojure is made to easily support concurrent and functional programming

12:12 ktne: i mean, not just standard scheme implementation

12:14 mac_: It's definetly not a standard scheme. I'm pretty new to lisp and clojure myself so I can't tell you what the differences are exactly but it should be on the web page I think

12:15 there we go: http://clojure.org/lisps

12:15 ktne: thanks

12:18 Chouser: kotarak: if it were a hash, you'd still need to call something to get a value (get foo :key) or (foo :key) or (:key foo), right?

12:19 if it's a memoized function called foo, you could call it with (foo :key) -- same syntax

12:19 kotarak: hmm... ok. That makes sense.

12:51 Chouser: hm, and there's a nice memoize already in clojure-contrib.

12:55 meredydd: Hey all.

12:55 Chouser: hi, meredydd.

12:55 meredydd: Is there an idiomatic way of modifying the value stored to a particular key in a map?

12:56 Chouser: can't modify anything. ;-)

12:56 meredydd: Chouser: Well, that's the problem. Because an in-place modify is fetch->modify

12:56 whereas with immutability you have to do fetch->modify->writeback

12:56 and 'fetch' and 'writeback' have quite a lot of redundancy.

12:56 Chouser: user=> (def m {:a 1 :b 2})

12:56 #'user/m

12:56 user=> (assoc m :a 9)

12:56 {:b 2, :a 9}

12:57 oh.

12:57 meredydd: I'm doing a lot of:

12:57 (alter map-ref assoc key (do-something-complicated-to (@map-ref key))

12:58 Was just going to knock up a macro to do the round-tripping for me (based on the "alter" idea - give it a map, a key, and a fn to apply to the value, and it'll give you the new map)

12:58 but it strikes me as the kind of thing there might be something in the API fo

12:58 r

13:00 kotarak: Maybe clojure wants you to do it differently? A lot of hassle is often a sign, that you work against the system.

13:00 meredydd: Indeed. Which is why I'm running it past here before doing that.

13:01 On the other hand, I can't really think of another way around it - I need to store a set of Xs for each Y

13:02 kotarak: Maybe you should pass it on to a function instead of storing it somewhere?

13:02 meredydd: so unless you can think of a better option than an immutable map of Ys to immutable sets of Xs, you're going to have to do something

13:02 kotarak: I'm familiar with the basics of functional programming. This is one of this program's three pieces of state.

13:06 (In fact, one piece of state. But it needs to be looked up from several directions, so it ends up being in several maps.)

13:10 Chouser: meredydd: I think you're doing it right, although you if you think you can get away with commute instead of alter, that would be better.

13:11 the pattern you described shows up a couple times in ants.clj

13:11 meredydd: Chouser: Commute would be good - unfortunately, there's some conditional logic in there and I think I'd be whacking a hornet's nest if I let multiple invocations on the same value of Y intersect.

13:11 (defn alter-map-val

13:11 [map-val key alter-fn & args]

13:11 (assoc map-val key (apply alter-fn (get map-val key) args)))

13:12 Chouser: meredydd: yeah, ok, as long as you're thinking about it. I've not done enough different things with refs of hashes to think easily about when I would need alter vs. commute.

13:12 meredydd: Seems nice to me.

13:13 Okay, that just made the whole statement fit on one line. That's promising.

13:14 Chouser: meredydd: can you paste an example usage?

13:14 you'll use ref-set now instead of alter?

13:14 meredydd: {:test #(assert= (alter-value {:a 4 :b 5} :b #(+ %1 %2) 1) {:a 4 :b 6})}

13:15 Usage goes:

13:15 (alter user-roles-by-component (alter-map-val victim #(disj % [user, role])))

13:15 (where the #(disj...) stuff is the application-specific stuff - removing something from taht set)

13:16 aaand I have to go.

13:16 bbl, might discuss this further if you're around, Ch

13:16 *chouser

13:17 Chouser: Hm! I think it looks good!

14:53 meredydd: I know you're not here, but that's not quite right

14:55 meredydd: ?

14:56 Chouser?

14:56 Chouser: oh, hi.

14:56 alter's second arg is a fn, so either alter-map-val needs to return a fn, or something else needs to be different

15:08 (defn alter-map-val [m key alter-fn & args] (alter m assoc key (alter-fn (@m key))))

15:08 (dosync (alter-map-val victim :a #(disj % [user, role])))

15:11 You could have a commute-map-val too, I suppose

15:58 Lau_of_DK: public class MyClass implements JButton {} -- How is this done in Clojure?

15:59 Chouser: gen-class or proxy

16:00 Lau_of_DK: got a brief example?

16:01 Chouser: (proxy [JButton] []) will create a new instance of a class derived from JButton.

16:02 xml.clj includes an example of proxy

16:04 Lau_of_DK: Thanks, exactly what I needed to know

16:05 Chouser - Maybe you should look through the documentation on Clojure.com? I find it somewhat lacking in a few various areas

16:06 Chouser: proxy is documented on the java-interop page

16:11 scgilardi: I noticed your memoize in clojure-contrib today. Thanks for that!

16:12 scgilardi: you're welcome! I noticed the discussion earlier about alter. does memoize show how to do something similar more simply?

16:14 Chouser: I don't think so. There was a conversation about a lazy-cons for hashes, and I was saying that for some use cases, memoize might be sufficient (since we don't currently have a lazy-cons for hashes).

16:15 scgilardi: ok, I haven't worked through it all yet, but it seems like "assoc" when used in a "commute" fills the role of "alter-map-val". I've been pleased with how "conj" and "assoc" have been all I've needed when commuting.

16:16 Chouser: yeah, the alter stuff was an different topic.

16:16 scgilardi: "commute" -> "alter"

16:16 ok cool

16:17 Chouser: I don't think alter-map-val is necessary, but without it you often end up repeating the name of the map ref and the key -- once for the lookup and once for the assoc or conj.

16:17 alter-map-val or something like it just reduces the repetition.

16:18 scgilardi: alter returns the new value. is it to try to capture the previous value?

16:18 (actually I haven't yet used alter... I'm familiar with commute)

16:19 Chouser: both alter and commut pass in the old value, but if your ref is of a hash you still need to look up the key you want to change.

16:20 ...and the thing you need to return from your alter or commute func is the whole hash, not just the new val. that's where alter-map-val would help.

16:22 scgilardi: interesting ok. I'll work through an example to understand it.

16:24 Chouser: (def m (ref {:a 1}))

16:25 (dosync (commute m assoc :a (inc (m :a))))

16:25 m and :a are each mentioned twice

16:26 (dosync (alter-map-val m :a inc))

16:26 with the alter-map-val I gave above, m and a are only mentioned once each.

16:27 scgilardi: ok I see now, thanks

16:28 Chouser: but as you said, commute would be good too, so maybe it would be useful to also have commute-map-val

16:28 scgilardi: or to make alter or commute an argument rather than part of the function name

16:28 Chouser: sure

17:37 meredydd: Yo, Chouser

17:37 You said you had a bug in my map-alter fn

17:53 Chouser: yep -- did you actually try your version?

17:55 meredydd: http://clojure-log.n01se.net/date/2008-07-06.html#14:56b

17:56 meredydd: Chouser: Not yet, tes

17:56 *not yet

17:58 Chouser: Hmm. Comp crashed, and I've lost that file. Hold on...

17:58 Oh, yes, you're right.

17:58 (alter user-roles-by-component (alter-map-val victim #(disj % [user, role]))) is wrong

17:59 (alter user-roles-by-component alter-map-val victim #(disj % [user, role]))

17:59 That's right.

18:06 Chouser: oh!

18:06 very well then.. that way you can use commute without needed a commut-map-val

18:09 meredydd: Chouser: ha!

18:09 I just read that log, and was about to make the same point.

18:09 "alter" was the wrong name to give this fn.

18:09 It should be "replace-map-val"

18:09 (or, in fact, "replace-assoc-val", but that's really quite long)

18:10 I named it after "alter" because I was thinking about how you can do this:

18:10 (alter x + 1)

18:10 or (alter x assoc :key :value)

18:11 You can now thread this some distance:

18:11 (alter user-roles-by-component alter-map-val victim disj [user, role])

18:12 Chouser: yikes

18:12 meredydd: (kinda a reverse "->")

18:13 (which, again, is one of those things that first made me go "yikes", then after an hour of using it, made me appreciate rhickey even more than before)

18:14 Chouser: :-)

18:19 well, it's very hard for me to think through how that works, but it's hard to argue with the brevity.

18:19 I suppose it wouldn't take long to get used to the pattern.

21:46 arohner: has anyone here played with compojure?

Logging service provided by n01se.net