#clojure log - Aug 28 2008

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

10:10 ozzilee: Could anyone tell me why using a recur within a map would cause clojure to go into an infinite loop?

10:11 Chouser: care to paste an example?

10:12 lisppaste8: ozzilee pasted "recur within map" at http://paste.lisp.org/display/66008

10:13 Chouser: ah. recur goes back to nearest containing loop or fn.

10:14 ozzilee: Ah. Hm.

10:14 Recur will go back to a fn rather than a loop? Neat.

10:14 Chouser: yep

10:15 I can't really tell what you're trying to do there, but recur's not going to help you escape from a map early.

10:15 ozzilee: Not sure if it does me any good, but neat. I'm try to recursively convert a json structure represented as HashMaps and Arrays into maps and vectors. Maybe I should try a zipper?

10:15 Chouser: you might try (for ... :while)

10:15 oh, scratch that.

10:15 ozzilee: Oh no, I'm not trying to escape, I just want to recursively convert the map entries.

10:15 drewr: ozzilee: Hey! I was doing the converse of that the other day.

10:16 ozzilee: drewr: Heh, for Jetty bychance?

10:16 drewr: No, loading JDBC ResultSets into CouchDB.

10:17 The process is entirely too fragile IMHO.

10:17 Chouser: ozzilee: for something like that you can probably use a fn instead of loop, and call it by name from inside your map fn.

10:17 you know, just regular recursion.

10:17 ozzilee: Chouser: Right, but that'll eat the stack, correct?

10:18 Chouser: yes, it'll up the stack proportionally to the depth of the JSON structure you're walking. Chances are that'll be ok.

10:18 * ozzilee has no idea how big the JVM stack would be

10:18 ozzilee: Chouser: Ok, maybe I'll just go that route for now.

10:18 drewr: What did you end up doing?

10:19 Chouser: What you'd be doing is much less dangerous than if you're iterating, and using up stack frames for each iteration.

10:20 if you want to be extra-careful (and get other benefits) you can set it up to work lazily.

10:20 drewr: ozzilee: Creating a recursive mess.

10:20 (But it worked.)

10:21 ozzilee: All right. Plain ol' recursion it is. Thanks guys.

12:29 rhickey: hoeck: got your CA

13:30 hoeck: rhickey: okay, cool

14:19 rhickey: I'm thinking about going with the mk-get/assoc defined here: http://groups.google.com/group/clojure/msg/ec91ef45b017db68

14:20 any comments/suggestions for names?

14:31 alternatives: get->, assoc->, get* assoc* (there's also an mk-update)

14:41 Chouser: what's the mk- meant to imply?

14:44 hoeck: I would vote for get* and assoc*, but I doubt that I'm going to use that feature

14:51 rhickey: mk == multi-key

14:52 hoeck: why wouldn't you use it, if you had nested structure?

14:52 Chouser: ah. not short for "make"

14:56 If it's going to take a vector, I'd vote get* and assoc*

14:57 well, I'd just prefer not get->. get* or get-nested or something.

14:59 parth_m: rhickey: I kind of like get* and assoc* more than mk-get and mk-assoc. mk- sort of sounds like make- convention of CL.

15:02 How about get+ and assoc+ ... + indicating 1 or more?

15:02 hoeck: rhickey: just toying around with relational algebra and trying to avoid hierachical data-access paths

15:03 rhickey: hoeck: ok, FYI I'm looking into adding some sort of Datalog/rule engine which will do recursive queries

15:04 get-in, assoc-in, update-in ?

15:05 parth_m: rhickey: -in sounds good to me. Intuitive.

15:05 Chouser: -in is fine. what's update? :-)

15:06 rhickey: Chouser: takes a fn a la alter/commute - replaces value with function of current value

15:09 lisppaste8: rhickey pasted "get-in, assoc-in, update-in" at http://paste.lisp.org/display/66030

15:10 Chouser: ah, right. very good.

15:11 parth_m: Ah. I am already seeing my lines of code going down with update-in :-)

15:13 Had a general question triggered by point 2 in this thread: http://groups.google.com/group/clojure/msg/52491a246b648067

15:14 Probably a noob question. What exactly do we think of items like "String" "Exception" etc. in Clojure? Do we think of these as symbols?

15:14 (def s String) shows s as java.lang.String but (new s "abc") fails.

15:15 Chouser: new is a special form, and it doesn't evaluate the class symbol.

15:15 rhickey: parth_m: new and . are not reflective (i.e. they don't take Class instances)

15:17 parth_m: So apart from symbols and keywords, Clojure has a third category "class" i.e. items like String. right?

15:17 And (def s String) makes s and instance of String?

15:18 rhickey: parth_m: you need to distinguish between the data returned by the reader and its interpretation, when read, String is a symbol

15:19 after . and new, String is interpreted as a class scope (. and new are special forms as Chouser said)

15:19 in normal evaluation contexts, String designates the Class instance String

15:20 so (def s String) makes s the Class String

15:21 user=> (def s String)

15:21 #'user/s

15:21 user=> (class s)

15:21 java.lang.Class

15:21 Chouser: which is a big long way of saying that aliasing classes for use in . and new is non-trivial. :-)

15:22 parth_m: I think I get it now.

15:22 So for normal evaluation s would be ok but . and new being special forms do things a little differently

15:22 rhickey: Chouser: I wouldn't say that, but it is not important, and perhaps an anti-feature

15:23 Chouser: hm.

15:24 parth_m: I don't see a need for aliasing classes, I just wanted to improve my understanding of how it all worked. Thanks for the clarifications.

15:24 kotarak: (eval `(new ~s)) does work, no? But it probably supports the anti-feature thesis.

15:25 rhickey: kotarak: right

15:35 lisppaste8: rhickey pasted "proposed lib usage" at http://paste.lisp.org/display/66034

15:38 Chouser: ooh.

15:38 * drewr likey

15:39 * cemerick drools :-)

15:39 Chouser: is :requires doing an alias, or can I say (ns foo (:requires (clojure.contrib sql :as sql sql.tests :as sql.tests))

15:39 cemerick: I assume the aliasing options are available/

15:40 (what Chouser said)

15:40 rhickey: same stuff as in lib, I think it requires some []s

15:40 [very-long-thing :as vlt]

15:40 cemerick: Looks fantastic.

15:42 I don't remember if this has been brought up elsewhere before, but on a related note, it'd be really wonderful if class names could be aliased as well (which would simply be some reader magic, I'd think).

15:42 rhickey: cemerick: we were just discussing that, I think it's an anti-feature

15:42 cemerick: (i.e. (ns foo (:imports (java.util [Date :as JDate]) (com.foo [Date :as FDate]))))

15:44 rhickey: anti-feature as in, bad practice, or as in, doable with macros already?

15:44 rhickey: more likely I'd extend namespace aliasing to Java packages: juitl/Date foo/date

15:44 cemerick: bad in proactice - makes code harder to understand, tougher for tools etc

15:45 foo/Date above

15:45 cemerick: yeah, the namespace aliasing would scratch my itch

15:45 s/namespace/package

15:48 kotarak: this is awesome. Nice to experience this "live", so to say. Normally when I learn a new language it's around 15 years old. :]

15:49 Chouser: kotarak: yeah, it's exciting isn't it? expecially when you start to get the sense that people may actually still be learning it in 15 years.

15:49 Because, you know, they need to in order to get a job anywhere. :-)

15:50 parth_m: Regarding (:requires ...). Can this clause be used to load clj files in a multifile app/library? or should we use load-file(s) in the sources?

15:51 rhickey: parth_m: requires does the loading

15:51 the library itself handles its multiple files if any

15:51 parth_m: Thats nice :-)

15:52 kotarak: Chouser: hehe, and you can tell your kids "Look, that Chouser in the IRC log of ye Olden dayes, that was me! Right from the beginning!" ;)

15:52 Chouser: kotarak: :-)

15:53 parth_m: Might be a silly question. Whats the different between :requires and :uses?

15:54 rhickey: uses refers automatically

15:54 parth_m: Ah. Nice.

15:55 kotarak: :imports, :requires and :uses translates to the similar named functions of clojure.contrib.lib

15:55 ok, :requires and :uses actually...

15:56 parth_m: kotarak: Will look at clojure.contrib.lib. Thanks for the pointer.

15:56 kotarak: parth_m: you did not, up to now? Hurry up. That's a really must-have!

15:57 parth_m: :-)

16:08 tomhickey: rhickey: i like the -in examples, feels nice

16:57 kotarak: I added a section for clojure.contrib.lib on the wiki. But well parth_m has already left...

16:57 rhickey: lib is now integrated!

16:57 This works:

16:57 (ns foo

16:57 (:requires [clojure.parallel :as par])

16:57 (:uses (clojure inspector))

16:57 (:imports (java.util Date Timer Random)

16:57 (java.sql Connection Statement)))

16:58 kotarak: Ok. I'll adapt the wiki entry.

16:58 Chouser: woohoo!

16:59 rhickey: also added a defonce, plus format and printf

17:01 Chouser: :-) printf lives on...

17:03 kotarak: rhickey: does (:require bar.baz) also work? w/o []?

17:04 rhickey: kotarak: yes, []s are only needed if using flags like :as

17:05 kotarak: rhickey: ok. Just asking. Don't want to write something wrong on the wiki. :)

17:06 rhickey: kotarak: best to read the embedded docs, which are quite detailed, before you restate them - (doc require)

17:10 * Chouser can't figure out how to do :uses and :exclude

17:13 rhickey: (ns foo

17:13 (:requires [clojure.parallel :as par])

17:13 (:uses [clojure.inspector :exclude (inspect-tree)])

17:13 (:imports (java.util Date Timer Random)

17:13 (java.sql Connection Statement)))

17:16 kotarak: How do I do load-libs now?

17:16 Chouser: (ns foo (:uses [clojure :exclude (slurp load-file)]))

17:16 java.io.FileNotFoundException: Could not locate Clojure resource on classpath: clojure/clojure.clj

17:17 (ns foo (:uses (clojure :exclude (slurp load-file)))) ==> java.lang.IllegalArgumentException: Don't know how to create ISeq from: Keyword

17:18 (ns foo (:uses ([clojure :exclude (slurp load-file)]))) ==> nil, but then: foo=> (def slurp "oops") ==> java.lang.Exception: Name conflict, can't def slurp because namespace: foo refers to:#'clojure/slurp

17:19 gotta go, I'll pick this up again later tonight.

17:19 kotarak: This is happened already before.

17:19 So it's not from the new code, I suppose.

17:23 Chouser: oh, this is because the new ns macro does a (refer 'clojure) for us automatically.

17:23 That was mentioned (and even documented) but I forgot. If I want to exclude some clojure, I'll have to do something before calling ns.

17:24 kotarak: Ok? Hmmm, but I'm sure I had this "exclude but complain anyway" phenomenon also in a previous version.

17:25 And I still miss load-libs...

17:26 drewr: Excellent: http://is.gd/219Y

17:27 kotarak: Ah. Maybe load-resources does the job!

17:28 Chouser: ok, really going now...

18:30 hoeck: wow, built in lib is superb

18:33 pmf: /j vim

20:14 cemerick: I'm pretty sure the answer is currently 'no', but: is there any way to obtain a partial fn from a java object's method?

20:14 Chouser: you can use the #() syntax to build one pretty easily

20:15 cemerick: gawd, yes

20:15 it's been a long week :-)

20:20 Chouser: :-)

21:42 jamii_: Um ...

21:42 user=> (. Integer (getName))

21:42 java.lang.IllegalArgumentException: No matching method: getName

21:42 Chouser: there's no static method getName in the Integer class.

21:43 jamii: Oh. Of course. I want the non-static method of the class object Integer

21:43 Chouser: right. (. (identity Integer) (getName))

21:43 or (. (class 5) (getName))

21:44 jamii: I'm confused. Why does the former work?

21:45 user=> (= (identity Integer) Integer)

21:45 true

21:46 Chouser: . is a special form (not a function). It checks its first arg to see if its a literal class name, in order to provide access to static methods and fields.

21:46 If the first arg to . is anything else, it gets evaluated to get an object instance (an instance of Class in these cases).

21:47 jamii: Ok. I can see that that would rarely cause problems.

21:47 Thanks

21:47 Chouser: In most other contexts, class names evaluate to their instance of Class, which is why your = did what it did.

21:48 yep, I certainly have stumbled on it a few times.

21:54 lisppaste8: jamii pasted "slots" at http://paste.lisp.org/display/66041

21:54 jamii: My first clojure module

21:56 Chouser: cool!

21:56 jamii: the seeds of a scriptable notetaking app

21:58 has clojure yet evolved a common indentation style?

21:58 Chouser: pretty common, I think. Borrows a lot from Common Lisp of course.

22:00 your paste looks pretty good. Indent the contents of let

22:02 jamii: cool. thanks for the help.

22:06 Chouser: sure

22:08 hey, if you update to the latest clojure svn, you can replace your first two lines with just (ns slots)

23:28 arohner: has anyone tried (ns foo (:require ..))?

23:29 (ns foo (:require 'clojure.contrib.sql)) gives me java.lang.Exception: Unable to resolve symbol: requir in this context

23:29 but (ns foo) (require 'clojure.contrib.sql) works fine

23:30 Chouser: heh

23:37 yep, I see that.

23:38 oh, you need :requires -- note the "s"

23:40 arohner: ah, thanks

23:40 having alias in the (ns) block would be nice

23:40 I notice I tend to use alias right after require

23:47 Chouser: (ns foo (:requires [clojure.parallel :as par]))

23:48 arohner: oh, nice

23:48 maybe I should read the docs fully?

23:48 :-)

23:48 Chouser: :-)

23:49 well, now you may have to. I'm off to bed.

23:49 arohner: thanks for the help

Logging service provided by n01se.net