#clojure log - May 12 2008

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

12:05 abrooks: rhickey: I keep waiting for Yegge to realize that Clojure's the language he's looking for. I know he thinks the paren issue is too much for the genral population. I'm not quite sure. BTW, did you really post 15 minutes after Yegge posted his article?

12:24 rhickey: abrooks: Yegge seems most interested in JavaScript, having resigned himself to the language limits at Google. I've realized as people trot out the Lisp-has-had-its-day argument that I need to highlight how Clojure is, IMO, much cleaner looking and approachable than CL/Scheme, a combination of fewer parens in let et al and the vector and map literals.

12:25 abrooks: I think I was much later than 15 minutes...

13:06 Chouser: I wonder if it'd be worth coding up a couple of relatively attrocious CL examples and show them with Clojure equivalents.

13:09 rhickey: Chouser: I think it's more important to go head-to-head with JRuby/Groovy/Jython, as those developers might not realize Lisp might not be the parens-infested nightmare they imagine. CL devs have already come to grips with parens, knowing the power of macros enabled by them...

13:11 Chouser: hm. ok. tougher sell, but ok. :-)

13:12 I've got a friend who, after seeing some of your videos, has decided Clojure is the right way to go, if only he can create a C-like syntax on top of it.

13:12 rhickey: Oh no!!

13:13 I attended many of the dynamic language sessions (Groovy/JRuby/Jython) at JavaOne. Clojure looks pretty decent by comparison, considering all the syntactic sugar they have, and is actually less complex due to the lack of it.

13:14 Chouser: I won't tell him you said that. I'm encouraging him to try, since the more closely you look at the problem (and spend time reading/writing s-expressions), the more better s-exprs look.

13:15 rhickey: Yeah, it's an inevitable part of learning Lisp...

13:17 Chouser: And for my part, I wouldn't mind if he succeeded. He's hardly the first to try, so I'm not too hopeful, but I'm sure there is a set of programmers who could be hooked if they had a more familiar syntax to start with.

13:24 rhickey: Clojure is no more different from Python than Python is from C/Java, syntactically, except no infix ops, say. Given the climate of people learning new language that exists today, I'm hopeful Clojure is directly approachable. Personally, Ruby/Scala etc syntax gives me a headache. The longer people avoid code-as-data the longer until they 'get' Clojure/Lisp.

13:26 mfredrickson: i think the statement vs. expression distinction is a larger impediment to Lisps than code vs data (though certainly an important concept)

13:27 rhickey: mfredrickson: interesting... Ruby is all expressions, Python too?

13:28 mfredrickson: rhickey: ruby (of which I am more familiar) skates a line between statemtents and expression

13:28 for example, I can write a function like def foo; 3; end

13:28 it evaluates to 3 and returns that value

13:29 i can also write def foo; if something; return 12; end 3 end

13:29 rhickey: the return is needed?

13:29 mfredrickson: in the second foo, that first "if" is a statement (as in, no return value), but the 3 (if reached) is an expression

13:29 not strictly

13:30 thus the duality of the language

13:30 ozzilee: Hey all, is there a way to load in a .java file from the REPL? It's not in my classpath.

13:30 rhickey: yuck

13:30 ozzilee: .java is source, do you mean .class?

13:30 mfredrickson: rhickey: yeah. it's weird. i'm writing some Rails code write now, and I keep switching back and forth between expression and statement style. I'm schizo

13:31 ozzilee: rhickey: No, actually .java. I'd be interested to hear of a way to do .class files as well though.

13:32 rhickey: General question for those that know Ruby/Python/Groovy - do you find Clojure to be simpler/smaller or more complex/larger?

13:33 ozzilee: no, you must compile with javac and get the class file on the classpath, or use something like Janino from Clojure.

13:34 ozzilee: rhickey: So, in general, if I download a java library (be it a .java, .class, or .jar file), I'm going to need to restart my REPL before I can play with it?

13:35 rhickey: ozzilee: a Java library will most likely be in a .jar. I'm looking at adding support for dynamic loading of jars.

13:35 ozzilee: Ok, that would be cool.

13:36 mfredrickson: I might be wrong, but I'm pretty sure that "if" statement returns a value regardless. I haven't used ruby in a few months, though.

13:36 mfredrickson: ozzilee: it returns nil

13:37 ozzilee: according to the IRB session i have open anyway

13:37 ozzilee: mfredrickson: Hrm you're right.

13:38 No, the repl just gets confused.

13:39 a = if 1; "foo"; end;

13:39 a is "foo"

13:39 It still returns a value.

13:41 mfredrickson: ozzilee: if the REPL is confused, how am I supposed to know what's going on? ;-)

13:42 ozzilee: Heh. Lines with colons in them just don't show their return values in the REPL, apparently.

13:42 1; 2; 3; // No return values.

13:42 Chouser: rhickey: I posted a pure-clojure hack for dynamic loading of .jars the other day.

13:42 mfredrickson: i would still argue that because of it favors the OO/mutal state model Ruby is more of a statement style language

13:43 though I do appreciate using expressions in it

13:43 Chouser: python has distinction between statements and expressions (unlike ruby). ...and it hurts.

13:43 ozzilee: Chouser: Yeah, I think I found that.

13:44 http://paste.lisp.org/display/60512 ?

13:44 rhickey: Chouser: yes, thanks, just trying to avoid the setAccessible call

13:44 Chouser: rhickey: heh. yes. good idea.

13:45 for example, python has "lambda", but only allows it to include a single expression. But "if" is a statement, so you can't use it in a lambda body.

13:45 rhickey: Chouser: looking at making DynamicClassLoader derive from URLClassLoader

13:46 mfredrickson: Chouser: my brain hurts already. and here I was thinking I should learn python to give significant whitespace a try

13:46 ozzilee: Chouser: Yeah, Python deliberately discourages anonymous funcitons. I believe I heard it said that he wanted to take lambda out all together.

13:46 (can't think of his name right now)

13:47 Chouser: mfredrickson: every language has warts, and Python certainly has merits.

13:47 rhickey: I'm trying to find the web page where the guy wrote Lisp code, then used progressively lighter fonts for the parens until it looked like Python, to demonstrate what happens after a while - the parens disappear for a Lisp programmer, but can't find it right now :(

13:47 mfredrickson: Chouser: I'm being dramatic. I'm sure I'd learn a thing or two from picking up python

13:48 Chouser: ozzilee: yeah, but Guido van Rossum's swimming up-stream. Python's picking up a lot of functional contructs -- to its benefit, I think.

13:48 ozzilee: Guido, that's his name :-)

13:49 I don't think he's anti-functional. Just anti-lambda.

13:49 rhickey: Chouser: I thought GVR was pro-iteration and against more functional style?

13:49 ozzilee: Are list comprehensions considered functional?

13:50 rhickey: not really, fancy iteration

13:50 map/reduce/apply etc

13:50 ozzilee: Hmm. Well they're pretty slick, anyway.

13:50 Yeah, Python has those.

13:50 Chouser: well, but comprehensions generally accept a value and return a value without side-effects. ...more functional than many alternatives for the same functionality.

13:50 mfredrickson: rhickey: it's not the disappearing parens, but I've keeping my eye on "readable s-expression"

13:50 http://www.dwheeler.com/readable/

13:51 i keep meaning to write a little Lisp to try them out

13:51 Chouser: rhickey: That's my impression of GVR as well, but he has a community that he doesn't entirely ignore. :-)

13:52 rhickey: keeping lambda limited reduces the utility of map/reduce etc

13:52 * rhickey is not totally on top of Python developments

13:52 ozzilee: Yeah, it sure does. Python's just got different goals, readability high on the list.

13:53 I'm certainly not saying it's better than lisp. It is pleasant, though.

13:53 rhickey: Anything Pythons list comprehensions do that Clojure's don't?

13:53 ozzilee: Heh I doubt it. No idea, though, haven't look at Clojure's.

13:56 Chouser: I don't think so. But the syntax is all backwards -- you start with the returning expression and then the bindings, and finally the test

13:57 rhickey: That's the Haskell way

13:58 which makes somewhat more sense when your lists are built up using infix cons (::)

13:58 ozzilee: Speaking of list comprehensions, what's a good way to get a lazy infinite list of random values?

13:59 Or even a finite list.

13:59 I think I ended up on (for [x (range 10)] (rand)), but I don't really like that.

14:00 I'd like something like (take 10 (repeat (rand))); which obviously doesn't work.

14:01 rhickey: (defn randoms [] (lazy-cons (rand) (randoms)))

14:01 (take 10 (randoms))

14:03 ozzilee: Blech :-)

14:03 rhickey: you don't like it?

14:03 ozzilee: How does fnseq work? (take 10 (fnseq (rand) rand)) doesn't do what I'd expect.

14:04 It's fine, I was just looking for something more general, like (take 10 (repeat-fn rand)) or something.

14:04 (which I'm I could write, but if it's built-in...)

14:05 rhickey: ozzilee: fnseq's second arg must be a fn that returns a seq

14:06 ozzilee: yeah, I also occasionally want a repeatedly macro, (repeatedly (rand))

14:07 ozzilee: Yeah, that would work.

14:09 Sorry to sidetrack the conversation, just feeling my way around the language.

14:11 rhickey: (defmacro repeatedly [e]

14:11 `((fn rec# []

14:11 (lazy-cons ~e (rec#)))))

14:12 ozzilee: And there it is :-)

14:15 Chouser: I've got a new format for the #clojure logs up at: http://clojure-log.n01se.net/

14:15 Let me know if it looks broken in your favorite browser.

14:16 rhickey: Chouser: looks fine here Camino OS/X 10.4.11

14:17 ozzilee: Chouser: Long usernames get screwed up on FF/Linux.

14:18 mfredrickson, for example.

14:18 By "screwed up" I mean cut off.

14:19 Chouser: hm. indeed -- text piling up.

14:20 ozzilee: Heh changing the margin-left on b elements fixes it, but that's not really a solution.

14:20 Chouser: yeah, because then you run into the timestamps.

14:21 b { overflow: hidden } also solves it sorta-but-not-really.

14:24 mfredrickson: i win. I broke chouser's design.

14:24 Chouser: :-)

14:24 ozzilee: Heh.

14:26 Tables?

14:26 Chouser: Yeah, the old design used tables. http://n01se.net/chouser/clojure-log/2008-05-12.html

14:27 ozzilee: Yeah, I don't see any way around tables as long as you stick with that general layout.

14:28 Something like username<br>message could be done in css, but bleh.

14:28 Chouser: I don't mind clipping ridiculously long nicks (sorry, mfredrickson!) client-side if it looks good, but I'm not sure if it's worth the trouble.

14:28 ozzilee: Of course, that would stop really long usernames from shoving everything to the right...

14:29 Chouser: The benefit of no tables is it's easier for the browser to show the top of the page soon while still loading the bottom of the page.

14:29 oh well. I can't work on it now anyway. I'll poke at it again some other time.

14:38 hoeck: chouser: long usernames look bad too on opera 9.02/linux

14:44 ozzilee: Is there anything set up to collect Clojure libraries? For example, if I were to write a JSON library...

14:46 Chouser: ozzilee: http://sourceforge.net/projects/clojure-contrib/

14:57 ozzilee: Chouser: Thanks.

15:21 abrooks: rhickey: Going back to this mornings context of Yegge's post -- Yes. My experience with Clojure is that it's really crossed a cleanliness / expressiveness barrier that other Lisps handn't been able to do (for me). I've sat down and gotten myself workably proficient with various CL implementationts four times in the past but never got to the point where I felt like the language was a natural way to express things. Clojure ...

15:21 ... crossed that barrier in the first hour of me using it. I've found myself very comfortable in Clojure and belive the small ammounts of additional map, set and vector literals and general expressiveness really bridge that gap for me.

15:21 Chouser, rhickey: The friend who likes Clojure but doesn't like parens isn't looking for C syntax. It's more of a Pythonic indent based syntax that he's looing for.

15:22 * rhickey is still looking for that site with the disappearing parens...

15:22 abrooks: He gets annoyed at the duplicated expression of nesting (both in s-expressions and in indentation).

15:23 Disappearing parens? I should read all of the backlog. I was in meetings and am just catching up now.

15:23 ozzilee: Does anything besides emacs do decent s-expr indentation? Eclipse?

15:23 abrooks: Have you tried Scheme, out of curiousity?

15:24 abrooks: rhickey: Are you talking about sweet-expressions?

15:24 http://www.dwheeler.com/readable/retort-lisp-can-be-readable.html

15:24 The parens bugged me too... up until Clojure. Then I just didn't care any more.

15:24 rhickey: no, not really disappearing, just an example of how they effectively disappear

15:25 not in favor of sweet-expressions

15:26 abrooks: I'm not either. There was a time I thought that idea was nifty. Like I said, it doesn't bother me any more.

15:26 I should really try to identify why it bugged me and why that

15:26 I should really try to identify why it bugged me and why that's not an issue to me.

15:27 rhickey: right, the trick is to convey that effect to newcomers, since invariably anyone who sticks with it soon no longer cares

15:27 abrooks: rhickey: I do think one important thing that eventually happened over my previous Lisp forrays is learing to format Lisply instead of Cishly.

15:27 Formatting properly is a big part of not having to read the parens.

15:27 rhickey: yes, indentation is as important as, well everywhere else

15:28 abrooks: Perhaps all intro to Lisp tutorials should start with a reformat your thinking about formatting.

15:29 i.e. This is how you format and read code in Lisp (or in our case, Clojure).

15:31 ozzilee: What do you guys use for an editor?

15:31 abrooks: I'm using Vim for now. I want more out of it but its working well enough.

15:32 leadnose: I'm quite a newbie to lisp, but the parentheses never really bugged me because a proper editor should handle it just as easily as any else

15:32 I've been using emacs with slime

15:33 ozzilee: Heh. Why is it that anytime the phrase "proper editor" comes up, it's emacs?

15:33 </rhetorical>

15:33 leadnose: I didn't say it is the only one :)

15:34 but I think that the editor should handle most of the formatting in any language

15:34 mostly indenting though

15:34 ozzilee: Yeah, it should, but a lot of editors don't deal with s-exprs very well. Textmate, for one. IDK about Eclipse, haven't tried it.

15:35 It's too bad about Clojure removing parens from cond. It doesn't indent properly without a special rule now...

15:35 Chouser: I'm working on getting jVi to work with enclojure in NetBeans. ...still don't have it right yet.

15:36 I'm headed home. ...later...

15:36 ozzilee: later

15:37 abrooks: ozzilee: Didn't see your question until now -- no, I've never written Scheme though I've read chunks of SICP.

15:38 Actually, I guess I did a really small amount of Guile.

15:38 ...And librep but that's neither here nor there.

15:39 ozzilee: abrooks: It's a lot cleaner than CL. I don't much like CL either.

15:40 Might be worth checking out. I think Clojure's going to end up being more practical for a lot of things.

15:40 I'd recommend Chicken Scheme myself.

15:41 er, "more practical for a lot of things, though."

15:50 rhickey: I've added repeatedly and add-classpath:

15:50 (add-classpath "file:/Users/rich/dev/colt/lib/colt.jar")

15:51 (take 10 (repeatedly rand))

15:52 ozzilee: rhickey: Wow, you're intense :-)

15:53 (repeatedly rand) or (repeatedly (rand)) ?

15:53 rhickey: note repeatedly is a function, not a macro like I showed before

15:53 ozzilee: Ok, that was my question :-)

15:53 rhickey: so (repeatedly rand)

15:55 ozzilee: Very cool, I'm going to have to switch to trunk for add-classpath, that will be nice.

15:56 Maybe just on my Mac at home though, I always feel like I'm working with boxing gloves on in Linux...

15:57 rhickey: Do you work on Clojure full-time?

16:00 rhickey: ozzilee: no

16:01 abrooks: It just might appear that way but Clojure has allowed rhickey to open a spacetime portal and have TWO full time jobs.

16:02 ozzilee: abrooks: I see. Is that macro in SVN trunk? I might have to upgrade for that...

16:03 abrooks: ozzilee: I've been trying to use it but I find it flaky. It must be something in rhickey's environment that I don't have. I wind up having half the time I had before I found Clojure. ;-)

16:04 ozzilee: heh

16:04 abrooks: Maybe I'm using the wrong JDK. Like one without quantum entanglement.

16:04 rhickey: abrooks: as long as you get twice as much done with the Clojure half...

16:06 abrooks: It's not quite there. I still have a lot of Java learning before I can just go in a straight line without zagging to check various Java resources. The clojure part is pretty smooth aside from the moments of confusion followed by epiphany. :)

16:06 ozzilee: abrooks: What languages are you coming from, if you don't mind me asking?

16:08 abrooks: C, C++, Python, Ruby, Haskell, et al.. I did some Java stuff ages ago but don't really count it.

16:09 I mostly do C, Python and Bash at my current Job.

16:09 The C is mostly Linux kernel. Most userspace is a mix of Bash and Python with some small parts in C.

16:11 ozzilee: Nice. So a decent mess of stuff :-)

16:11 abrooks: Oh, and GNU Make. =-O

16:11 ozzilee: Yes, all the horrors of the programming language universe. :-)

16:12 We actually use Lisp inhouse for our DMA engine compiler and some internal network analysis tools but that's not my domain.

16:12 SBCL is the Lisp we use.

16:12 ozzilee: Interesting that Clojure seems to be pulling in a lot of people with no other interest in the JVM.

16:13 I don't think Scala or Groovy could say the same thing.

16:14 abrooks: Yes. I only had ill feelings for the Java universe. (I didn't mind the JVM so much as certain language misfeatures and the warped Sun mindset that Java is a self sufficient universe that doesn't need to acknowledge anything outside.)

16:15 I think the things happening with GNU Classpath and IceTea are exciting. Hopefully opensource will truly come to JavaLand.

16:16 rhickey: One nice take-away from Java One was that the JVM is truly detached from Java - lots of support for non-Java langs etc.

16:16 abrooks: ozzilee: I do think it's interesting that the number of JVM languages appears to be growing. Java 7 has dynamic language support -- something that Sun would have never done 5 years ago as it does nothing for Java.

16:16 rhickey: Exactly. --^

16:18 ozzilee: It will certainly be interesting to follow for the next few years.

16:19 rhickey: I think the JVM is going to see very much increased use

16:19 So much free infrastructure

16:20 great tech (HotSpot)

16:20 open source

16:20 ozzilee: I'm curious to see if Apple changes their attitude on it. They seem pretty lukewarm towards it lately.

16:20 abrooks: Yep. And one thing I have been impressed with are the tools that Sun has provided for debuging and profiling.

16:21 rhickey: that was a stunning disconnect at the show. In the sessions I attended, Macs were used by 90% of the presenters...

16:21 But some of the JavaFX stuff is still not supported on Mac, so they were running in VMs

16:21 Sun and Apple have to get this together

16:24 ozzilee: They really do. Heh I just googled "iphone jvm" and found a bunch of articles talking about how the lack of Java was going to bury the iPhone. Not so much...

16:25 drewr: I'm not sure I understand how Java and the JVM can be disconnected. Could you write a language for hosting on the JVM in something other than Java?

16:26 abrooks: drewr: If you bootstrapped you could.

16:26 I'm not sure you'd want to, I guess.

16:26 drewr: What's Java written in?

16:26 rhickey: You could write one today in Clojure

16:27 abrooks: Also, you'd lose all of the libraries if you were to entirely purge Java. I'm not sure you'd want that either.

16:27 drewr: C++ IIRC.

16:28 rhickey: Java is really a good infrastructure language. I hope they stop changing it. But you need something like it, just not for all applications

16:28 drewr: So could you write a Scheme hosted on the JVM that's properly tail-recursive?

16:29 rhickey: the disconnection is that you don't need to program in Java in order to leverage it and the JVM

16:29 abrooks: drewr: Java sources, now that you distracted me. ;-) http://hg.openjdk.java.net/

16:29 ozzilee: drewr: Kawa is tail-recursive, I believe.

16:29 rhickey: only in a special slow mode

16:29 drewr: I guess I don't understand how VM architecture works (Gemstone, Hot Spot, et al).

16:30 abrooks: The bytecode instructions are stack based.

16:30 rhickey: an interpreter could be tail recursive, see SISC

16:30 drewr: Kawa and SISC are written in Java though, aren't they?

16:30 rhickey: and Sun could make the JVM native calling do TCO, in which case Clojure would immediately do the same

16:31 abrooks: It goes all the way down to the instructions but with the changes happening for dynamic languages in Java 7 I wonder if you could get an efficient tail recursion instruction set added.

16:31 rhickey: drewr: there is a spec for the bytecode, and many ways to generate that

16:31 drewr: Ah, OK.

16:31 rhickey: abrooks: TCO is not on the short list for JDK 7 AFAIK

16:32 abrooks: rhickey: No.

16:32 rhickey: I meant theoretically the project might be ammenable to accepting it in a future release if you could demonstrate the demand.

16:32 rhickey: The JDK7 dynamic languages stuff benefits languages like JRuby and Jython more than Clojure

16:33 abrooks: Right. I've looked at the changes.

16:33 They excite me but do nothing that I can tell for Clojure.

16:33 Hm. Is there any benefit that Clojure could extract from the dynamic language changes?

16:33 rhickey: --^

16:34 rhickey: abrooks: That emphasis (JRuby/Jython) is not a good one IMO. Trying to make ported interpreted languages without great semantics run well, vs languages written for the JVM (Clojure/Scala/Groovy)

16:34 For Clojure I would like TCO and tagged references

16:35 abrooks: What would tagged references buy you?

16:35 rhickey: no boxed numbers

16:35 * abrooks renders a blank look

16:35 abrooks: boxed numbers?

16:36 rhickey: http://blogs.sun.com/jrose/entry/fixnums_in_the_vm

16:36 abrooks: Ah!

16:36 rhickey: would greatly speed up math and use of numbers

16:36 abrooks: Okay.

16:36 Efficient "cut-through" objects without the objects, right?

16:37 rhickey: Other than that Clojure is pretty well satisfied by what currently exists, since type hints get rid of the need for all the reflection optimizations, and Clojure's native calling is very fast right now.

16:37 abrooks: I just didn't recognize the term.

16:38 rhickey: abrooks: no boxing means no allocations, no blowing cache to follow references to numbers in random memory locations etc

16:38 abrooks: Yep.

16:38 rhickey: It's my #1 feature request, but the importance of it is not recognized by some of the other dynamic lang devs

16:39 http://groups.google.com/group/jvm-languages/browse_frm/thread/ac9308ae74da9b7e

16:40 By building for the existing JVM, with a pragmatic approach, Clojure is doing quite well, vs langs that inherited a design they have to make work on the JVM, especially one that started out as an interpreter.

16:41 off to my second full-time job :)

16:41 bpattison: has anyone had any problems using enclojure in netbeans 6.1 under windows? namely <alt-enter> doesn't seem to be committing my expression to REPL -- plus shift-ctl-L doesn't seem to work

17:09 ozzilee: What? Clojure doesn't have fold??

17:10 Oh, I guess I can just cons the starting value onto the front of the sequence and use reduce...

17:25 lisppaste8: ozzilee pasted "I love lisp." at http://paste.lisp.org/display/60648

18:58 esquesque_: what does a metadata map for a map look like?

18:59 is it just the type of the value?

19:00 #^String {:key "value"}

19:01 rhickey: no, metadata is an optional map that can be attached to some objects - collections and symbols. If you hadn't added metadata to a map there would be none:

19:01 user=> (def m {:a 1 :b 2})

19:01 #'user/m

19:01 user=> (meta m)

19:01 nil

19:02 esquesque_: you can't attach metadata to a map?

19:02 rhickey: yes you can

19:02 there is no metadata unless you put some on it

19:04 esquesque_: erm... metadata for a function looks like #^Type (defn ...) because a function evaluates to only one value

19:04 but a map has two - key and value

19:04 i was wondering if the metadata for a map had a constraint for the key and value or just the value

19:05 rhickey: metadata is always a map, no matter what it is attached to

19:05 esquesque_: i'm talking about conveying types to the compiler

19:06 rhickey: there is read/print shorthand for metadata when the only entry in the map is :tag, in which case it prints like #^Tag

19:07 when you convey types to the compiler you do so by attaching metadata to symbols usually. Metadata is also available for arbitrary program use

19:08 user=> (def m #^{:x 1 :y 2} {:a 1 :b 2})

19:08 #'user/m

19:08 user=> m

19:08 {:a 1, :b 2}

19:08 user=> (meta m)

19:08 {:x 1, :y 2}

19:11 esquesque_: okay, thanks

19:11 i was thinking you could apply :tag to maps

Logging service provided by n01se.net