#clojure log - Dec 16 2008

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

0:07 arohner: is the github mirror of clojure contrib working for anyone else?

0:07 it says the last commit is dec 7

2:38 Lau_of_DK: Top of the morning gents

3:07 slangan: http://www.computersight.com/Programming/Five-Strangest-Programming-Languages.397205

3:07 LOLCODE ^^ so friggin funny

3:07 http://www.computersight.com/Programming/Five-Strangest-Programming-Languages.397205

3:07 replaca: yeah, that was a big reddit today

3:08 slangan: oops


3:08 HAI




3:08 replaca: yeah, but it needs a graphics subsystem that shows pics of your LOLCATs while the prog runs

3:12 zakwilson: lolcode was on reddit months ago.

3:15 ivan: slangan: http://www.esolangs.org/wiki/Language_list

4:02 AWizzArd: When I have a string filled with xml, how can I parse it?

4:02 Lau_of_DK: See Zip-filter

4:03 AWizzArd: in the clojure.xml package?

4:03 Lau_of_DK: (xml-> (xml/Parse "xml-file.xml") :root :child [:element "Custom search"])

4:03 AWizzArd: well yes, but (clojure.xml/parse ...) does not work on strings

4:04 it wants a file or a url

4:05 Lau_of_DK: Thats where Zip-filter comes in

4:05 (zip/xml-zip (xml/parse "file.xml"))

4:05 AWizzArd: in what package can I find it?

4:05 Lau_of_DK: Contrib somewhere, Chouser wrote it

4:05 AWizzArd: yeah, only that I don't have a file

4:05 Lau_of_DK: huh?

4:06 AWizzArd: I have a string filled with xml.

4:06 If it were a file or a url I would use clojure.xml/parse

4:06 Lau_of_DK: As I recall there's also a func which takes a string

4:07 AWizzArd: this is what I am looking for :-)

4:07 Lau_of_DK: infact, doesnt (zip/xml-zip ) do that?

4:07 AWizzArd: it takes a string s, but only returns [s nil]

4:08 Lau_of_DK: (defn parse-str [s]

4:08 (zip/xml-zip (xml/parse (new org.xml.sax.InputSource

4:08 (new java.io.StringReader s)))))

4:09 albino: parse-str sounds like it parses a string :)

4:09 AWizzArd: yes

4:09 but it's not included I guess?

4:10 Lau_of_DK: Im not sure :)

4:10 AWizzArd: I mean, you just wrote it yourself, right?

4:10 Lau_of_DK: No I found it in the bottom of zip-filter.clj, under examples, commented out :)

4:10 I think its a little helper Chouser wrote

4:11 AWizzArd: ic

4:17 good, works, thanks

4:22 wipewindows: Can I haz purpose with life K thanks?

4:27 jdz: slangan: such purposes are hard to find. and they are not in this channel. kthnxbye.

5:39 hiredman: clojurebot: sicp?

5:39 clojurebot: sicp is http://www.codepoetics.com/wiki/index.php?title=Topics:SICP_in_other_languages:Clojure:Chapter_1

5:40 hiredman: clojurebot: sicp is also <reply>those guys are such dorks

5:40 clojurebot: Ik begrijp

5:56 AWizzArd: clojurebot: max users?

5:56 clojurebot: No entiendo

5:56 AWizzArd: sehr gut

5:59 hiredman: clojurebot: max people

5:59 clojurebot: max people is 116

6:03 AWizzArd: is that number (user-) overwritable?

6:03 hiredman: yes

6:03 AWizzArd: closurebot: max people is 4

6:04 hiredman: nice try :P

6:04 AWizzArd: Can you please lock this?

6:05 hiredman: why?

6:05 AWizzArd: to be able to trust this number (because it inherits trust in you)

6:08 jdz: what is max people and why would anybody want to trast such a number?

6:08 *trust

6:09 hiredman: jdz: it stores the max people clojurebot has seen in the channel

6:09 I dunno why someone would trash it, and I am not sure that I care if they do

6:11 jdz: max as in "highest number of people present at one time" or "how many [different] people have visited the channel"? (i assume it counts stats for this channel ;)

6:11 hiredman: it doesn't really do stats

6:11 AWizzArd: at the same time

6:11 hiredman: jdz: max at any one time

6:12 jdz: well, i don't see much use of this number if it does not reset daily or weekly

6:12 and if it does not store the history

6:12 hiredman: *shrug*

6:13 jdz: except for entertainment reasons

6:15 AWizzArd: Hi black

6:15 blackdog_: hi

6:52 slangan: how do you use databases in clojure?

6:52 blackdog_: clojure.contrib.sql is a good place to start

7:07 AWizzArd: slangan: you have your own namespace, such as (ns com.slangan (:require (clojure.contrib [sql :as sql]))) and then in that namespace you can say (sql/with-connection ...) and so on.

8:05 wipewindows: how do I pull contrib?

8:18 aperotte: wipewindows: contrib is hosted on sourceforge, are you asking for the svn address?

8:20 has anyone noticed that you get different behavior when using (load-file ...) versus calling each form in a file yourself in a repl?

8:33 clojurebot: svn rev 1161; refactored Comparator into superclass of functions only

9:19 svn rev 1162; EPL in header

10:03 aperotte: hello all, can anyone think of why some of the forms in a file might not be evaluated when using (load-file ...). If I load the file into emacs, select the contents and evaluate region, they all get evaluated.

10:05 Chouser: none of them get evaluated with load-file?

10:06 aperotte: no, all of the def's get evaluated

10:06 and the defn's

10:06 but then I call a few of the defined functions

10:06 they don't get run for some reason

10:07 Chouser: can you trim it down to a single defn and a single call?

10:07 aperotte: I'll try, give me a few

10:11 slangan: how do I install contrib? do I just place it in some folder and then import it?

10:13 hoeck: slangan: yes, or you build a jar with ant

10:13 and import that

10:14 rhickey: svnsync-ing Clojure to Google Code - taking forever

10:17 aperotte: Chouser: It's going to take me some time to trim it down, I'll come back once I can isolate the problem

10:18 Chouser: aperotte: ok. for what it's worth, the only thing I can think of is that the namespace var *ns* may get pushed/popped for a load-file

10:18 ...but I can't think of how that would break anything in your case

10:25 shoover`: rhickey: whoa, never saw lisp/clojure.lisp before

10:26 aperotte: Chouser: hmm ... ok, I'll keep that in mind while testing

10:27 rhickey: shoover`: doing some archaeology?

10:27 shoover`: when I went to the google project, that's how far along the sync was

10:27 rhickey: ah

10:28 taking only slightly less time to sync than to write from scratch...

10:29 shoover`: thinking in Common Lisp, Clojure, .NET and JVM simultaneously must've been fun

10:29 rhickey: shoover`: yeah

10:30 Chousuke: hm

10:31 I guess teh move to google code means I'll have to reclone clojure... I hope GC will at least be faster than sourceforge :P

10:32 Chouser: browsing svn via the web is much faster at google code. fast enough to be usable even.

10:32 * Chouser looks forward to answering questions by posting links to the source.

10:34 Chousuke: google code is definitely superior to sourceforge.

10:35 still, I keep wishing there was an official mirror using some DVCS :)

10:35 rhickey: Chouser: yes, everything about gc's web interface is so much faster

10:36 ... rev 370 ... fourth restart ...

10:36 Chousuke: I wonder if there is a way to get check-in notifications for the SVN repo in google code via some google api.

10:36 that way you could have an automatically updated git/mercurial/whatever clone of it.

10:37 RSS might be good enough.

10:39 Chouser: why push when you can poll, right? :-P

10:40 rhickey: Looks like I can setup an address for commits and one for issue changes

11:06 http://groups.google.com/group/clojure-commits

11:06 Chouser: ah, nice idea.

12:14 rhickey: 200 revs left ...

12:14 RSchulz: The full commit history is being replicated at the GC repo?

12:14 rhickey: I hope so

12:21 Chouser: it looks that way

12:26 RSchulz: When you say "it looks that way" are you seeing the commits on the feed at the foregoing link? 'Cause I'm not.

12:26 rhickey: RSchulz: they're not new commits, so I wouldn't expect them there

12:26 RSchulz: They have a special "import an existing SVN repository" capability?

12:27 rhickey: RSchulz: yes, a one-shot thing

12:27 RSchulz: Cool.

12:27 triddell: I can see the various revisions and view the diffs etc.

12:27 rhickey: one multi-hour extravaganza apparently

12:28 triddell: at 1055 and climbing

12:28 rhickey: maybe we shouldn't fiddle around in there too much until it finishes?

12:28 Chouser: right, not at the feed, but by examining the browsable svn repo I can see old versions of files.

12:28 triddell: np :-) ... that's exactly how I'd feel

12:29 rhickey: final lap...

12:36 RSchulz: On the lighter side, here's an IM I just sent to a Lisp programmer buddy of mine: Clojure keeps getting cooler. I can sense where this is headed. I'm going to end up in a state where writing Java makes me feel dirty.

12:37 rsynnott: irritated is more common than dirty, I suspect

12:45 zakwilson: I feel dirty when I have to use some Java library that requires a lot of mutation (e.g. constructors that don't take reasonable args, requiring the use of setters)

12:47 rhickey: svn checkout http://clojure.googlecode.com/svn/trunk/ clojure

12:47 have at it

12:48 rsynnott: yay! Non-incredibly-slow svn :)

12:48 rhickey: http://code.google.com/p/clojure/source/browse/

12:49 http://code.google.com/p/clojure/source/list

12:51 gnuvince: You changed the license?

12:53 rhickey: gnuvince: yes, to EPL a couple of days ago, to facilitate this move - successor to CPL

13:00 Chousuke: heh

13:00 git cloning the new repo now. it's still low, but way faster than sourceforge :P

13:00 slow*

13:04 zakwilson: clojurebot: svn?

13:04 clojurebot: svn is https://clojure.svn.sourceforge.net/svnroot/clojure/

13:05 zakwilson: clojurebot: svn is http://code.google.com/p/clojure/source/checkout

13:05 clojurebot: Ik begrijp

13:05 Chousuke: five minutes and already half done. this is not so bad after all

13:10 alphazero: clojurebot: svn is http://clojure.googlecode.com/svn/trunk/

13:10 clojurebot: Roger.

13:11 alphazero: URL: http://clojure.googlecode.com/svn/trunk

13:11 Repository Root: http://clojure.googlecode.com/svn

13:11 Repository UUID: a41a16f3-9855-0410-b325-31a011a03e7c

13:11 Revision: 1162

13:11 Node Kind: directory

13:11 Schedule: normal

13:11 Last Changed Author: rhickey

13:11 Last Changed Rev: 1162

13:11 Last Changed Date: 2008-12-16 09:10:56 -0500 (Tue, 16 Dec 2008)

13:13 Chouser: Chousuke: surely there's a way to use my existing git repo and just retarget the upstream one.

13:14 duck1123_: Chouser: I would think that git-svn wouldn't like that unless they were actually the same repository, just moved

13:15 Chousuke: Chouser: probably, but... my reclone just finished :)

13:15 if you have local modifications I guess you need to export them as patches :/

13:23 RSchulz: Well, for us readers-only, that was completely painless. I did a little switcharoo with directories after the check-out, copied over my src/Clojure.iml (not to be confused with Rich's clojure.iml!) and voila! Even IDEA didn't mind.

13:39 rsynnott: rfgpfeiffer_: they differ only by capitalisation?

13:39 sorry, RSchulz

13:39 RSchulz: I was unaware of Rich's when I set up my IDEA module. But mine's also in the src/ subdirectory while Rich's is at the top.

13:39 Not that it matters, mine's never going to leave my system.

13:47 Is Clojure-Contrib migrating to GC, too?

13:48 Chouser: I think it will, but I suppose it has to be compeletely switched over to EPL first.

13:51 Lau_of_DK: Good evening good folk

13:56 zakwilson: Good day, Lau_of_DK.

13:57 If you'll recall that file format we were talking about a few days ago, it's even more bizzare than I thought.

13:57 Lau_of_DK: I remember, what did you find ?

13:59 zakwilson: The official editor software generates files that make sense (parameter_id in one file matches parameter_id in the other), but the nearly 400 device files supplied as a downloadable package do not.

14:00 The official editor and the lighting controller can read and use these files.

14:00 Lau_of_DK: Sounds a little unintuitive, isnt this documented somewhere?

14:01 zakwilson: So I can make a working editor that will produce working files, but I cannot edit the files provided by the vendor.

14:02 Documented? Ha!

14:02 Lau_of_DK: Is the two-way thing important in your situation ? I remeber you want to provide a single-format solution to light-shows?

14:05 zakwilson: It's not important for that goal, but I want to start by making an editor for a single file format, and it would be nice if it's fully functional.

14:06 Lau_of_DK: Maybe you'll be the guy who writes the one Lamp to rule them all! :)

14:06 zakwilson: I actually have the controller in question and the provided device editor is horrible. It's slow, unstable and only runs on Windows.

14:06 I intend to release the replacement editor as open source, and use it as the basis for me one editor to rule them all.

14:07 Lau_of_DK: Sounds charming, but its good that you get some RE experience, thats always fun

14:08 zakwilson: I'm not sure I want to glorify it by calling it reverse-engineering. Figuring out what labled fields in a CSV file mean isn't that hard.

14:09 Figuring out that some fields are generated by adding/multiplying other fields is a little harder... as is discovering that overflow of a signed int is part of the design.

14:09 rsynnott: zakwilson: on a machine of some particular word size, I assume? :)

14:10 Lau_of_DK: I read your previous statement as you wanting to dive into the controllers driver? The one you said was slow and unstable

14:10 sohail: zakwilson, maybe the thing to do is create your own format :-)

14:12 zakwilson: Getting in to the controller's software is beyond me right now.

14:12 I intend to create my own format, but that needs to be translated in to formats various controllers can read.

14:13 deklund: quick question: 'use' is not transative? (does not appear to be). I just want to verify... i.e. if I use on a ns, I don't get the libraries/namespaces that the used namespace references?

14:13 zakwilson: rsynnott: yes

14:13 it seems to be 32-bit

14:14 which means I should be able to rely on overflowing ints with Clojure's unchecked arithmetic.

14:14 RSchulz: deklund: I'd hope not! But seriously, no.

14:15 * zakwilson is curious as to how the supplied device builder software would work on a 64-bit machine.

14:15 deklund: :) thanks

14:15 rsynnott: it'd probably work in 32bit mode on a 64bit machine

14:15 but if you had the source and built it 64bit, it would probably NOT work

14:15 RSchulz: zakwilson: In the x86_64 world, at least, 32-bit programs run just fine as is. They need their usual complement of dependent libraries in 32-bit form, but the hardware for x86_64 is a superset at the user level.

14:16 rsynnott: same with Ultrasparc, I think; when running a 32bit app overflows happen as you'd expect

14:17 zakwilson: That makes sense. I don't have an x86_64 machine yet. Oddly enough, I do have an Ultrasparc.

14:19 rsynnott: 32bit software running on an x86_64 just sees an ordinary x86

14:19 no extra registers or anything :)

15:03 Lau_of_DK: (doc emit)

15:03 clojurebot: It's greek to me.

15:04 hiredman: only clojure.core

15:16 actions sent to agents happen in order right?

15:18 RSchulz: hiredman: According to http://clojure.org/agents they do.

15:18 "Actions dispatched to an agent from another single agent or thread will occur in the order they were sent, potentially interleaved with actions dispatched to the same agent from other sources."

15:21 hiredman: excellent

15:24 RSchulz: hiredman: Is this the first you're using Agents? I wrote my first code for them yesterday and I gotta' say, I think they're very cool.

15:25 But I really wish I could figure out how to keep them from hindering shutdown via CTRL-D at the REPL.

15:25 Registering them as a JVM shutdown hook doesn't seem to work.

15:26 I should say, registering an execution of (shutdown-agents) via the JVM shutdown hook doesn't work.

16:47 Lau_of_DK: In which revision did doseq change to vector bindings?

16:50 RSchulz: Lau_of_DK: Since it's meant to mimic (for ...), it seems natural. Anyway, I never encountered it in another form.

16:51 Lau_of_DK: Mr. Schulz, it seems that the change was made after 1089

16:52 RSchulz: What binding form did it take before then? A list?

16:52 Lau_of_DK: (doseq i (range 10)

16:53 (println i))

16:53 1

16:53 2

16:53 3

16:53 ...

16:54 RSchulz: Ah. Much more limited than (for ...)'s capabilities, then?

16:54 Lau_of_DK: The purpose of the change was to allow for :when :while keywords

16:59 SimonAdameit: hi

16:59 How do I measure the size (length) of a collection?

17:00 hiredman: (count ...)

17:00 SimonAdameit: thanks!

17:00 I obviously searched for length :)

17:02 RSchulz: Keep in mind that doing so will force a lazy collection and will never terminate for an unbounded one.

17:02 Chouser: but is constant-time for a PersistentList

17:05 RSchulz: Chouser: All of them?

17:06 Chouser: all instances of PersistentList? yes.

17:07 RSchulz: I meant all subtypes, but I see it has none. Other implementations of IPersistentList do not have constant-time (count ...) behavior, do they?

17:10 Chouser: I don't think it's guaranteed, but right now the only other implementor of IPersistentList is APersistentVector, which also should be ableo to do count in constant time.

17:14 dmiles: was DotLisp and clojure expected to be almost the same syntax?

17:15 http://code.google.com/p/opensim4opencog/source/browse/trunk/bin/test.lisp

17:15 hiredman: dmiles: http://dotlisp.sourceforge.net/dotlisp.htm <-- explains why the syntax might be similar

17:15 dmiles: oh cool

17:17 RSchulz: Chouser: I posted to the list, but I guess I could / should have just mentioned it here, but Atoms are missing from the type chart.

17:17 Chouser: RSchulz: hm! thanks.

17:25 gnuvince_: If send-off immediately returns, how come doing a send-off of 20 elements takes nearly 10 seconds?

17:26 Chouser: gnuvince_: because you're doing something else in your loop that takes nearly a half-second?

17:27 RSchulz: Or because as soon as you send a task off the thread assigned to the receiving Agent becomes active and runnable?

17:32 gnuvince_: Chouser: The loop just does the send-offs

17:35 net.gnuvince.comics> (time (doseq [[comic a] comic-agents] (send-off a conj (try (fetch-comic comic) (catch Exception e nil)))))

17:35 "Elapsed time: 23271.9988 msecs"

17:36 Chouser: gnuvince_: nope, that's a common mistake. send-off takes a function not a block of code.

17:36 gnuvince_: Chouser: that's what I do

17:37 (send-off a conj (...))

17:37 Chouser: ooh, maybe send and send-off should assert their arg is a IFn

17:37 gnuvince_: ah, good point.

17:38 gnuvince_: Unless the try/catch is executed before the send-off

17:38 Chouser: but you're still evaluating the arg (fetch-comic) before passing its return value to send-off

17:38 right

17:38 gnuvince_: Which would actually make sense

17:38 Chouser: right

17:38 gnuvince_: ok

17:38 Thanks

17:38 I'll see what I can do

17:38 Well

17:39 While I'm here

17:39 Here's the problem I want to solve: I want to fire up a bunch of threads and accumulate their results in a single ref

17:43 hiredman: make it a thunk, arg to the func you send to the agent

17:44 clojurebot: haskell?

17:44 clojurebot: Yo dawg, I heard you like Haskell, so I put a lazy thunk inside a lazy thunk so you don't have to compute while you compute.

17:45 danm_: heh

19:26 aperotte: Chouser: I asked this morning about (load-file ...) versus evaluating each expression in a file at the repl. Are there concurrency issues that might lead to differences in how things might be evaluated in those two settings?

19:29 RSchulz: aperotte: I think it's a virtual certainty that what you're seeing is not about concurrency unless you're evaluating forms that directly or indirectly trigger threaded execution (Agents, e.g.)

19:31 Chouser: aperotte: does the problem go away when you trim it down?

19:32 aperotte: It's hard for me to trim it down because I have a bunch of definitions that build on one another

19:33 I'm not using agents ... only refs

19:34 Chouser: I tried toy examples, but I didn't have the same problem

19:35 RSchulz: ok, even if I'm using a java library deals with threads and might lock?

19:35 RSchulz: The more so!

19:36 The bottom line is that logically (with sequential execution assumptions) there's no difference between (load-file ...) and one-by-one evaluating the forms in the loaded file.

19:37 The fact that you're seeing a difference and that you know you're (indirectly) executing explicitly threaded code strongly suggests that that code is not entirely thread-safe.

19:37 Chouser: aperotte: can you sprinkle println's through the file?

19:37 RSchulz: Is the pattern of execution (or the difference between the two modes of evaluation) repeatable? Or unpredictable / variable?

19:38 Chouser: Heisenbug territory!

19:38 Chouser: yep

19:38 aperotte: I haven't tried println's through the file because I know it gets to the last statement

19:38 But it is completely repeatable

19:38 Chouser: I understand -- I'm curious if the first println's would execute or if none of them would.

19:39 aperotte: ok, I'll give it a try

19:40 Chouser: RSchulz: I'm not sure exactly what to do with atom in the graph

19:41 RSchulz: I don't know how it fits into the type structure. What's the problem?

19:41 aperotte: Are you running on a multi-CPU or multi-core system?

19:42 Chouser: when you use 'atom' it creates an instance of clojure.proxy.java.util.concurrent.atomic.AtomicReference$IRef

19:42 aperotte: RSchulz: I'm running on a single cpu, single core system

19:42 Chouser: I can add that to the graph, but AtomicReference$IRef doesn't strike me as a particularly useful name

19:43 aperotte: Chouser: all of the (println ...) statements sprinkled through my code work

19:43 RSchulz: What I did when I first started playing with your chart generator code was to add a predicate of my own to detect Obj / IObj, which had not been accommodated at that time in your code.

19:43 Then I associated that with the others in your big map of type predicates.

19:44 So even though there was no (obj? ...) in Clojure, my modification to your generator acted as if there was and the graph was generated accordingly.

19:44 The same should be possible with Atoms.

19:44 aperotte: Chouser: however, between two of the println statements I sprinkled exists some code that should take about 20 seconds to run, and the println's happen within 4 seconds of one another ... I'm very confused why there's a difference at all

20:02 Chouser: aperotte: wow.

20:03 RSchulz: it's not a problem of the code, it's how the chart should look

20:03 I suppose I could use the word 'atom' in lowercase and leave out the cryptic class name entirely

20:03 RSchulz: Yes, but the point is that you can influce that by faking a pair in the map between labels and type predicates.

20:04 ...influence...

20:04 Actually, the only "faking" is of an (atom? ...) predicate.

20:05 gnuvince_: paste

20:05 lisppaste8: paste

20:05 hiredman: lisppaste8: url

20:05 gnuvince_: lisppaste8: paste?

20:05 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

20:05 gnuvince pasted "Looks okay?" at http://paste.lisp.org/display/72271

20:06 gnuvince_: Chouser: how does that look?

20:09 Chouser: gnuvince_: well, does it work? :-)

20:09 gnuvince_: any particular reason you don't use the value from *comics* as the agent's state?

20:10 gnuvince_: It works

20:10 Chouser: I don't really need the state of an agent

20:10 I'm merely using them to launch new threads

20:11 Chouser: do you really want the fetch-comic call to re-run if there's contention on the ref?

20:11 gnuvince_: no

20:11 I guess having fetching the value once is enough.

20:11 s/having//

20:13 So I'd better move out the try/catch out of the dosync?

20:13 Chouser: right. I think that will also lead you to a more "functional" definition fetch-comic.

20:14 gotta run -- I'll be back later.

20:14 gnuvince_: See ya

21:35 RSchulz: Chouser: Perhaps the funkiness surrouding Atoms comes from the fact that they're Clojure proxies. See (defn atom) in .../core_proxy.clj

21:42 Chouser: RSchulz: yes

21:43 RSchulz: I don't know how that helps, but perhaps it points the way. Still, the use of a user-supplied (you're the user) atom? predicate seems like a workable hook.

21:43 You could also ask Rich for an atom? predicate in the Clojure core.

21:44 Chouser: no, I don't need anything like that.

21:45 this is just about how to label the graph

21:45 RSchulz: Then I think my technique will work.

21:45 Chouser: all the other classes we care about have names. Ref, Symbol, etc.

21:46 But what name should I give this thing? There is logical class that could be named Atom, but because it's a proxy class its name is not terribly useful.

21:47 I'm looking now at adding "constructor" function names to the graph

21:47 that would add things like 'hash-map', 'sorted-set' and such to the appropriate ovals. Then adding 'atom' to this new one would be consistent.

21:51 RSchulz: The name should just be Atom. The membership criteria would (for now) be (loosely speaking) (and AtomicReference IRef).

21:52 Chouser: no, there is no thing called Atom

21:54 RSchulz: (defn atom? [thing] (and (instance? clojure.lang.IRef thing) (instance? java.util.concurrent.atomic.AtomicReference thing)))

21:54 I know, but people will understand what an Atom (or "atom") is in the context of the graph.

21:56 Regardless, you should probably consult Rich about this so you can depict the class structure accurately.

21:57 Chouser: you don't think they'll be surprised when they write try to write an 'instance?' test and find there's no clojure.lang.Atom class?

21:58 RSchulz: Well, that's why there should be type-discriminating predicates for every distinct kind of entity in the core!

22:20 deklund: hi all... what am I missing here? (let [ #^{ :a 1 :b 2} x [1]]

22:20 (meta x))

22:21 returns nil

22:25 Chouser: deklund: the #^ reader syntax attaches meta to the symbol x at reader time.

22:25 I think.

22:26 you might want: (let [x (with-meta [1] {:a 1 :b 2})] (meta x))

22:27 deklund: chouser: thanks. I guess I need to stretch my mind about that 'read' time distinction... i am not yet getting it.. ( I am guessing this is something fundamental)

22:28 Chouser: perhaps -- I'm not sure I quite get it yet.

22:28 deklund: :) good to know

22:30 Chouser: deklund: http://groups.google.com/group/clojure/msg/919455504c57659e

22:32 deklund: I was just reading that... I guess the distinction is that the #^ reader macro assigns to a 'form' object

22:32 with-meta is more for runtime 'user' objects

22:32 sound plausible? warmer?

22:35 Chouser: maybe, but 'form' objects and 'user' objects aren't very different

22:36 when read, your first example creates a symbol x with the meta-data you gave.

22:37 the compiler looks in that hash for a :tag key for type hints. Macros could use that metadata.

22:37 (I'm thinking this through out loud -- makes more sense to me each time I try)

22:38 deklund: :)

22:38 Chouser: once compiled, I don't think you can get to that symbol x anymore, though.

22:39 deklund: inherently, you are using it, though... so how would it be lost

22:39 ?

22:39 Chouser: no, the compiler used it to produce bytecode. In the bytecode it's probably just a java local, not a Symbol object anymore.

22:40 hiredman: clojurebot: you in?

22:40 clojurebot: Gabh mo leithsc�al?

22:40 Chouser: rhicky's not here to correct me when I wander off the true path. :-/

22:40 deklund: so ... in that case, (let [ x #^{ :a 1 :b 2} [1]]

22:40 x)

22:41 is the second x a new symbol?

22:41 i thought they got interned... and x was not lost

22:43 Chouser: symbols are not interned in Clojure

22:45 (identical? (symbol "x") (symbol "x")) ==> false

22:45 deklund: ahh... so the second x is considered a new form symbol

22:45 ok... neat (def #^{ :a 1 :b 2} x [1])

22:45 (meta x) returns => nil

22:45 but

22:46 (meta #'x) => {:file "NO_SOURCE_FILE", :b 2, :line 1, :a 1, :ns #<Namespace user>, :name x}

22:46 Chouser: right, in that case the meta is attached to the Var as well -- I'm trying to find where that happens.

22:47 of course you can also (def x #^{:foo :bar} [1])

22:48 deklund: I get a compiler error on that one

22:48 Chouser: hm!?

22:48 deklund: i tried that switcheroo with the let form and got a compiler error too

22:49 java.lang.NoClassDefFoundError: clojure/lang/Compiler$MetaExpr (NO_SOURCE_FILE:1)

22:49 [Thrown class clojure.lang.Compiler$CompilerException]

22:49 Chouser: you build from svn?

22:49 deklund: last week

22:49 Chouser: did you "ant clean" before "ant"?

22:49 hiredman: both works here

22:50 deklund: i'll try the ant clean

22:50 and an svn up

22:52 yup.. mea culpa. I needed to do an "ant clean"

22:52 Chouser: I think this is where the code is produced to copy the metadata from the symbol to the var: http://code.google.com/p/clojure/source/browse/trunk/src/jvm/clojure/lang/Compiler.java#327

22:55 deklund: just to be sure... the metadata is being copied to var or to the value of the var?

22:57 I'm going to have study the java in depth..

22:57 Chouser: to the Var itself

22:59 deklund: ok. now that I got rid of the compiler problem

22:59 (let [ x #^{ :a 1 :b 2} [1]]

22:59 (meta x))

22:59 returns {:a 1, :b 2}

23:00 the switcheroo works...

23:01 in that case I could make this argument:

23:02 (let [ x #^{ :a 1 :b 2} [1]] (meta x)) returns ---> {:A 1, :b 2}

23:02 (let [ #^{ :a 1 :b 2} x [1]] (meta x)) returns ---> nil

23:02 (let [ #^{ :a 1 :b 2} x [1]] (meta 'x)) returns ----> nil

23:02 hiredman: correct

23:02 deklund: in the first case, the metadata is associated with object itself

23:02 hiredman: yes

23:02 deklund: in the second it's associated with the symbol x

23:03 but not it's evaluated object

23:03 hiredman: not the symbol

23:03 the var

23:03 deklund: and in the THIRD... the second x is a new sybol

23:03 Chouser: hiredman: nope, no Var here

23:03 hiredman: but

23:03 fine

23:03 deklund: var?

23:03 hiredman: I lose

23:03 deklund: ok

23:03 Chouser: :-)

23:03 hiredman: clojurebot: hiredman?

23:03 clojurebot: hiredman is a three-toed sloth

23:04 deklund: does this THIRD scenario seem plausible?

23:04 you said symbols are not interned, so that could explain the nil return

23:04 Chouser: hiredman: Vars are created by 'def', 'intern', 'with-local-vars', but not by 'let'

23:05 deklund: I think so

23:05 but we should be able to ask for the meta of the same symbol...

23:05 deklund: i would think so too

23:06 but as you said... (identical? (symbol "x") (symbol "x")) returns false

23:06 so there might be no way to get the same symbol

23:06 Chouser: right, but I mean the *same* symbol, not just a symbol with the same name...

23:07 deklund: yes

23:07 Chouser: yeah, I'm not getting it. still trying...

23:07 deklund: i think I'm closer

23:07 Chouser: (let [z 0] (meta '#^{:a :b} z))

23:08 the ' quotes the meta and symbol together. Like:

23:08 (let [z 0] (meta (quote #^{:a :b} z)))

23:09 deklund: oh goodness. :) now I'm more confused

23:09 Chouser: no no, stay with me!

23:10 deklund: i'll try

23:10 Chouser: we're using meta to ask for the meta of a quote symbol

23:10 quoted symbol

23:11 deklund: ok.. i think i see where you're going

23:11 first off... i thought quote only worked on the form right next to it

23:11 Chouser: so the meta of the symbol itself, not of the value or of some other symbol with the same name

23:11 deklund: yes

23:12 Chouser: deklund: that's right, except the reader takes the #^ metadata annotation and the following symbol together

23:12 deklund: i see that... and the fact that the quote works on the 'form right next to it implies the metadata is part of the next form

23:12 Chouser: deklund: in other words, #^ is the one exception to ' ... I think.

23:12 exactly

23:12 deklund: read time... it's becoming clearer

23:13 ok... i see what you did there.

23:13 Chouser: (macroexpand '(let [z 0] (meta '#^{:a :b} z)))

23:13 the ' quotes the z which just happens to have had metadata attached to it already.

23:14 deklund: as attached by the reader

23:14 yes

23:14 Chouser: (binding [*print-meta* true] (prn '(let [z 0] (meta '#^{:a :b} z))))

23:15 deklund: i think i see the path to clarity

23:16 i wonder if there is a way to get to that symbol later

23:18 Chouser: you can get to it in a macro, but after that I doubt it.

23:18 deklund: chouser: excellent.. thanks for walking through that with me

23:19 Chouser: and thank you! I understand it much better now.

23:20 (defmacro pm [x] (println x "has meta" (meta x)) x)

23:20 let [z 0] (pm #^{:a :b} z))

23:20 with, of course, a leading (

23:22 deklund: i see, we're in a different evaluative mode with macros

23:22 Chouser: right, the parameter x in pm is the actual symbol that the reader is handing us -- the instance of Symbol with the metadata that the reader attached.

23:23 of course that's still a different z symbol than the one in let's vector.

23:23 deklund: yes

23:24 but there was still that var issue...

23:24 Chouser: what is that?

23:25 deklund: (def #^{:foo :bar} x [1])

23:25 (meta #'x)

23:25 i think the _value_ of the var is getting the metadata

23:25 is that not what the #' reader macro does?

23:25 Chouser: ah, no.

23:26 if you (def x), then later when you say just x it does the dereference and gives you the current value there.

23:26 ...because in normal programs, that's what you want.

23:26 saying #'x or (var x) is sorta preventing the deref and giving you the Var object.

23:27 deklund: ahh i misread the api... that makes sense

23:27 Chouser: you can call the 'get' method of the Var object to get it's current value.

23:27 (.get (var x))

23:27 deklund: or (var-get) apparently

23:28 Chouser: well sure, if you want to use the "documented" and "supported" API

23:28 :-)

23:28 deklund: :)

23:28 so as a Var object is interned, we can get at its metadata later

23:28 Chouser: yes!

23:28 deklund: not so with symbols

23:28 ok

23:28 por fin!

23:28 again thanks...

23:29 time to hit the sack and have meta dreams

23:29 Chouser: same here. good night

Logging service provided by n01se.net