#clojure log - Sep 08 2008

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

10:42 Chouser: what percentage of a struct-map has to be nil before it's less efficient than a sparse hash map (roughly speaking, on average).

10:43 rhickey: Chouser: less efficient in what way?

10:44 Chouser: I was thinking space.

10:44 memory

10:45 Relative lookup performance between the two would be roughly the same regardless the size, wouldn't it?

10:45 rhickey: yes

10:46 not a percentage thing, really. absolute sizes matter

10:47 Chouser: oh, ok.

10:47 In this particular case I've got a total of about 6 or 7 keys, but for any one instance I'd expect about half of them to be nil

10:48 rhickey: would the keys be in the hash-map or not?

10:48 key set to nil value and no key are different

10:48 Chouser: oh, right, in the hash-map they'd be half empty. In the struct-map they'd be half nil.

10:49 In this case I don't need to differentiate.

10:50 rhickey: struct-map is likely to be smaller, but you'd have to look at the implementation or measure to know

10:51 Chouser: is there an easy to way to ask a collection for its size in bytes?

10:51 probably a Java question, I guess.

10:51 rhickey: no

10:51 but another key question is - how many instances of the same struct?

10:52 Chouser: one per XML node. So... *shrug*

10:52 likely hundreds. Maybe thousands.

10:53 rhickey: then the shared keys will win

10:54 Chouser: ok, thanks.

10:54 rhickey: no substitute for profilng - speaking of which, I wonder if cemerick had any luck with profilers?

10:56 cemerick: rhickey: yourkit and good ol' hprof work fine; netbeans chokes when attempting to profile our largest project that has some clojure in it, although it does fine on a toy project that uses clojure (and on our largest project from before we started using clojure).

10:57 obviously, I'd like to use NB exclusively, but I've not been able to come up with a simple way to replicate the problem so as to report a bug

10:58 rhickey: cemerick: by 'work fine' do you mean you can collective meaningful data on Clojure fn calls etc, not just Clojure's Java runtime?

10:59 cemerick: rhickey: well, clojure fns and such appear on their own as distinct call sites, if that's what you're getting at.

10:59 rhickey: yes, that, getting number of calls, time spent in, time spent in children etc

11:00 cemerick: yeah, the clojure fns are identified nicely, as far as I've seen. Obviously, the names aren't as spiffy (my-fn is labelled myfn_1234 or whatever), but it's definitely usable.

11:01 rhickey: cool

11:01 * rhickey needs to try yourkit

11:01 cemerick: Yourkit is very nice, although being able to use NB would be great.

11:01 rhickey: agreed

11:02 I guess VisualVM is in same boat as NB

11:02 cemerick: How to isolate its problem is entirely unclear to me...

11:03 Hrm, hadn't come across VisualVM before, thanks.

11:03 But yeah, being on NB, I would expect it to have the same hang-ups.

11:17 blackdog: rhickey, http://lambda-the-ultimate.org/node/2978

11:17 rhickey: blackdog: saw that, thanks

11:17 blackdog: k

11:18 rhickey: no controversy, so everyone must agree :)

11:18 blackdog: :) waiting for the fireworks

11:20 Chouser: LtU is a bit slanted toward static typing, isn't it? Gives them more problems to solve and might make Clojure too boring to cause controversy.

11:20 cemerick: "...its target focus is concurrency..." Funny, as we've not really touched the concurrency stuff at all.

11:21 LtU has been pretty balanced over the years, IMO.

11:21 Chouser: ok. I read it, but must admit to understanding a pretty small fraction of the issues that are brought up.

11:27 rhickey: Chouser: yes, LtU has lots of category theory etc, Lisp is very old school for them, although they did cover PLT Scheme's move to immutable cons cells: http://lambda-the-ultimate.org/node/2631 :)

11:29 cemerick: yeah, FP is good for concurrency but not only that. Few people understand how their mutable state effects everything

11:31 Chouser: "Let's make a programming language!" on LtU -- haha! so doomed!

11:31 rhickey: I'm happy for the coverage and the nice writeup

11:31 cemerick: While concurrency safety is a Good Thing, it might be worthwhile to ensure that clojure isn't pigeonholed as "only" being useful for concurrent programming. Of course, that sort of PR and expectations management is only important if a broader audience for clojure is desired.

11:33 rhickey: cemerick: it's pretty easy to show someone how mutable objects make concurrency hard, much more subtle to have them understand the complexity issues of state raised by 'Out of the Tar Pit'.

11:33 a broader audience for Clojure is desired :)

11:34 cemerick: rhickey: I wouldn't deign to assume something like that, especially since Clojure's interoperability with Java could enable it to fly under the radar in perpetuity. :-)

11:34 Chouser: That's a demure Rich Hickey form of Torvald's goal of taking over the world.

11:35 rhickey: Clojure will always be for discriminating tastes, but I'd like to saturate that market

11:36 Chouser: Ruby was relatively unknown until Rails. I think it's just a matter of time until there are one or two analogous "killer apps" for Clojure to catch people's attention.

11:39 cemerick: I'm deeply pessimistic about the ability of a non-curly-brace language becoming widespread anytime soon (outside of those with "discriminating tastes" , perhaps ;-))

11:39 pjstadig: clojure's way of dealing with concurrency is what caught my attention

11:39 rhickey: Clojure has curly braces!

11:40 cemerick: :-P

11:40 pjstadig: don't know if that will translate into a "killer app", but with multi-core procs and the complete inability of most other languages to deal with concurrency, it might

11:41 Chouser: I'm here (originally) because of Java libs + macros.

11:41 rhickey: Chouser: so how have you found the functional programming side?

11:41 Chouser: oh, and dynamic types too, I guess.

11:41 pjstadig: yeah (in my short time getting acquainted with clojure) there are lots of selling points to clojure

11:42 Chouser: rhickey: yummy.

11:42 rhickey: That's what I hope for Clojure, but it's hard to sell - FP will make your code better, easier to understand, easier to test, easier to change

11:43 as FP langs go Clojure is IMO the most approachable

11:43 pjstadig: i don't know ML or Haskell, but i've tried to get acquainted

11:43 and Clojure is more approachable IMO

11:43 rhickey: but I don't think people are looking for FP, just suffering from OO mess...

11:44 Chouser: I think I cut the necessary immutable programming neural pathways in Scala (solving projecteuler problems), but had to use mutable structures pretty often for performance.

11:44 pjstadig: the blip vids are great though

11:45 someone passed them along to my Ruby Users Group

11:46 Chouser: And Scala's static typing annoyed me deeply as soon as I tried to do anything real. In Clojure, the types stay out of your way and there's really deep and rich support for immutable programming (collections, library of functions, idioms, etc.

11:46 )

11:46 rhickey: Chouser: they're working on it:http://www.codecommit.com/blog/scala/more-persistent-vectors-performance-analysis :)

11:46 cemerick: yeah, I came by way of Scala too

11:48 Chouser: I got to Scala by way of Rhino. :-)

11:50 rhickey: Chouser: so with ClojureScript you'll get back to Rhino?

11:51 Chouser: heh. no.

11:52 I was in Rhino because of Yegge (of course) -- a year or so ago, I agreed with nearly everything he said. But that was before I realized he's not promoting JavaScript, but rather his own new language based vaguely on JavaScript and built on top of Rhino.

11:55 although I suppose testing ClojureScript by running the results on Rhino might be handy.

11:56 blackdog: what is clojurescript a clj to js translator then? does code exist?

12:12 Chouser: yes, that's what it would be. There is some very preliminary code, but I don't think anyone's actively advancing it.

12:13 blackdog: is that in contrib ?

12:13 Chouser: blackdog: no. Let me see if I can find a link.

12:17 blackdog: http://groups.google.com/group/clojure/msg/73fdae1e56ffae71

12:17 blackdog: thanks

12:19 pjstadig: dumb question

12:19 what is the best way to exit the REPL

12:19 (quit) (exit) don't seem to work

12:19 ^C?

12:19 Chouser: ^D

12:20 pjstadig: thanks

12:20 Chouser: Or (System/exit 0)

12:21 pjstadig: you mean (. System exit 0)?

12:21 (System/exit 0)

12:21 java.lang.Exception: No such namespace: System

12:21 Chouser: cgrand: hi! Any recent changes to your Javascript HTML templating stuff?

12:22 pjstadig: Yeah, if you've got an older Clojure. In oldest to newest:

12:22 (. System exit 0) (.exit System 0) (System/exit 0)

12:22 pjstadig: oh ok

12:23 i've got the download snapshot

12:23 from june i think

12:23 Chouser: sorry, I rapidly lose track of which changes were made how recently.

13:50 albino: Has clojure chosen a convention for word separation in variable names? camelCase or under_scores ?

13:51 rhickey: dashes-please

13:51 albino: oh duh, lisp

13:52 next newbie question, how do I do else if

13:52 Chouser: (if <test> <then-clause> <else-clause>)

13:53 albino: I'm lookinng for something like (if <test> <body> elif <test> <body> else <body>)

13:54 rhickey: albino: cond

13:55 albino: rhickey: thanks

14:02 rhickey: http://www.reddit.com/r/programming/comments/7031x/maybe_building_a_new_language_on_a_homemade_vm/

14:09 Chouser: your willingness to read and respond to reddit comments demonstrates impressive patience.

14:10 rhickey: Chouser: it's interesting to see the level of animosity towards the JVM

14:14 pjstadig: well there's that, and people also seem to be missing the thrust of the argument

14:14 rhickey: pjstadig: yes, that's frustrating

14:14 pjstadig: which is not necessarily that the JVM is The Way (TM), just that it may be smarter to not start from scratch

14:21 Chouser: does anyone agree with zzzeek's comment that many Java libraries are sub-par in some way compared to libraries for other languages?

14:22 I guess poor API doesn't bother me much since slapping a pretty Clojure API on top usually requires only a little code.

14:22 But having had fairly little experience with Java, I don't know if I should be worried about buggy or poorly-performing libs.

14:23 blackdog: certainly clojure gets round all my issues with the java infrastructure(barring egregious memory use)

14:24 rhickey: Chouser: any such blanket comment is suspect, I doubt all Java libs are bad nor all Python libs good

14:24 blackdog: i think it's the extra scaffolding required of java that people hate, and that disappears with clojure

14:25 i.e. it's not really the libraries

14:25 rhickey: also he did some EJB, which is particularly painful, and SOAP

14:25 Chouser: I know from experience that not all Python libs are good, but those that are bundled with Python are generally sufficient and generally very trustworthy.

14:26 rhickey: I did some playing (in Clojure) with JMS and OpenMQ and it was awesome, easy, fun and vert fast, with pro level docs from Sun

14:26 Chouser: If SAX weren't standard, available in most platforms, and just as bad in all of them, then the nastyness of SAX in Java would worry me more.

14:27 rhickey: What's the Python alternative to JMS?

14:27 blackdog: you can use the stomp protocol from various clients inc python

14:27 apachemq supports it

14:28 rhickey: blackdog: yeah, apache activemq is Java/JMS

14:30 blackdog: if you mean a python like implementation of a jms server then i don't know

14:34 actually maybe twisted python has some protcol

14:34 Chouser: avoid twisted.

14:34 twisted is actually what I was specifically thinking of when I said "not all Python libs are good" :-)

14:34 blackdog: :) i use it for a chat server

14:38 rhickey: I don't wan't to beat up on Python, just to highlight JMS and Servlets say, as great examples of Java APIs that are simple, general, and most important support many implementations: JMS has OpenMQ/ActiveMQ/JORAM, servlets: Tomcat/Jetty/Glassfish/Resin, all free, + many commercial

14:38 These are not toys

14:41 blackdog: i think for anyone considering clojure for commercial work

14:41 the jvm is a terrific choice

14:41 it's an easy sell to customers

14:41 for academic work etc, purity maybe not

14:42 rhickey: blackdog: what do you mean by purity?

14:43 blackdog: well people on that thread seemed a bit academic to me, there was a particualr quote

14:43 which made me say purity there

14:45 for example, people talking about the abstraction is java underneath

14:46 and then talk of assembler being the ultimate abstraction

14:46 etc

14:52 Chouser: the i86 instruction set doesn't support TCO either, does it?

14:53 rhickey: Chouser: everything is manual at that level.

14:54 turtles all the way down matters when you are writing the whole stack. But Clojure isn't writing its own GC, so the fact that the JVM guys use Java/C/ASM doesn't matter to me

14:55 Chouser: I'm probably betraying vast ignorance here, but if you were to emit i86 asm, you could use the processor's own call stack but then you wouldn't get TCO.

14:56 blackdog: or me, that was my point, the other stuff is academic argument while we get to write code now

14:59 rhickey: Chouser: you would be defining your own calling convention and could easily (manually) do TCO, just clear stack before jumping

15:01 Chouser: ah, you can't jump into a Java function? you must call?

15:03 rhickey: Chouser: yeah, that's all abstracted away, the instructions are high-level, like invokeVirtual

15:03 you can't fudge the stack at all

15:03 Chouser: there's goto, but only within a function?

15:04 rhickey: Chouser: right

15:04 pjstadig: is there a preference between 'clj' and 'clojure' when naming libraries, executables, etc.?

15:04 clojure-extra vs. clj-extra

15:05 rhickey: pjstadig: unless you are planning a contribution to Clojure, you should avoid using it to avoid conflict with the base libs

15:06 pjstadig: i mean just a project name

15:06 on github you see projects like clojure-mcp, clj-cont, etc.

15:08 rhickey: I guess clj- is like the J all java libs prepend, but you should avoid Clojure, reserved for the language itself.

15:09 pjstadig: yeah or i was thinking maybe clj- is the equivalent of cl- for common lisp

15:09 just curious

15:09 rhickey: also now there is a package/namespace unification, so com.pjstadig.libname

15:10 pjstadig: oh

15:10 cool

15:10 abrooks: rhickey: Is that documented on the main website or only in the Google Group? :)

15:11 rhickey: abrooks: it's been evolving on the group and here, but I hope to cut a release now that it has settled down, with docs on the web

15:12 abrooks: rhickey: Cool. BTW, I just noticed the "Recent Changes" link on the website. Good idea. Is there an RSS feed for website changes?

15:13 Oh, I see that the RSS feed for the changes page is the website changes.

15:13 StartsWithK_: rhickey: is there maven repository or something similar with clojure.jar from current trunk?

15:14 rhickey: StartsWithK_: not from me, but probably

15:15 abrooks: Sorry, should have looked first. Maybe that could be a discrete link (currently it's only provided via the linkrel).

15:15 (changes RSS--^)

15:18 rhickey: abrooks: I don't know, this just falls out of the Wiki software, maybe tomhickey knows...

15:18 abrooks: in any case, between releases the changes are mostly doc bug-fixes, not tracking SVN

15:18 albino: (doseq i "hello" (if (= i "h") (println "match"))) Why doesn't that print match?

15:19 Chouser: albino: a string is a sequence of characters

15:19 but "h" is a string

15:19 try \h instead

15:19 albino: ahh, characters are different from strings, thanks

15:20 Chouser: Yep. (class "hi") ==> java.lang.String

15:20 (class \h) ==> java.lang.Character

15:21 leafw: is there any reason why the following fails: (pop (seq (double-array 10)))

15:22 java.lang.ClassCastException: clojure.lang.ArraySeq$ArraySeq_double cannot be cast to clojure.lang.IPersistentStack

15:23 abrooks: rhickey: Oh, I know. I'm interested in generally tracking website changes too. Had I been subscribed to the recent changes feed I would have seen that the link to the recent changes page was added on 8/9. Hm. That's a little chicken-and-eggy isn't it...

15:23 Chouser: leafw: any reason not to use "rest" instead of "pop"?

15:23 leafw: no reason. Just testing

15:24 I would like to understand how is pop different than rest.

15:24 peek also fails in the same situaton.

15:25 Chouser: sure. peek and pop operate on IPersistentStack

15:25 leafw: that is evident from the cast error.

15:25 Chouser: ArraySeq extends ASeq, but not IPersistentStack

15:25 leafw: but what do you mean?

15:26 perhaps my question ought to be reformulated: why should there be different treatment of sequences?

15:26 Chouser: yeah, that's a deep enough "why" that I don't think I can help you. :-)

15:27 With persistent collections, is there ever any different between peek/pop and first/rest?

15:27 leafw: if by persistent you mean immutable, no, they both return a new collection anyway.

15:28 Chouser: And yet rhickey implemented IPersistentStack, so I must be missing something.

15:28 oh, wait, I figured this out once...

15:29 * leafw awaits enlightement. This is puzzling.

15:29 Chouser: (pop [1 2 3]) ==> [1 2] (rest [1 2 3]) ==> (2 3)

15:30 not the same

15:30 leafw: hum

15:31 weird. So vectors are treated differently.

15:31 Chouser: so peek/pop don't operate on seqs in general, but on specific data structures that support it.

15:31 ...while all collections support first/rest

15:31 leafw: yeah, like a java.lang.Vector (or whatever it is that Cloujure uses in replacement)

15:32 so vectors are more like linked lists then

15:32 like cons cells chained.

15:32 Chouser: vectors support peek/pop in the opposite direction as first/rest. lists support them in the same direction. maps and ArraySeqs don't support them at all.

15:33 leafw: ArraySeq is new to me.

15:34 thanks Chouser, you did cast some light.

15:34 Chouser: there's actually lots of little seq classes to implement seqs around various underlying data structures.

15:37 rhickey: Chouser: all coolections support seq, which in turn supports first/rest

15:38 leafw: no, vectors are most like arrays/arraylists, not chained, fast indexed access

15:38 peek/pop work on the same end as conj

15:38 first/rest always at front

15:38 conj on lists is at front, on vectors at end

15:38 Chouser: well... first/rest (the clojure functions) call seq on their arg, right?

15:39 rhickey: right, but the collection only need implement seq

15:39 Chouser: ok

15:39 rhickey: first/rest are provided by the seq, while peek/pop are provided by the collection

15:40 peek/pop return the same type of collection, first/rest always return seqs

15:40 so, many differences

15:40 albino: If you wanted to the equivalent of a = b = 0 from a C like language. I tried this, but it doesn't seem to work (def a (def b 0))

15:41 rhickey: albino: def returns the var, not the value

15:42 at top level (def b 0) (def a b)

15:42 in a fn (let [b 0 a b] ...)

15:43 albino: rhickey: thanks

15:46 is there a nice way to read from stdin, or do I just follow the same way that java would?

15:49 Chouser: you might look at slurp

15:49 oh, nm.

15:49 you want line-at-a-time, the whole stdin to EOF, or what?

15:50 albino: yes, read one line at a time from stdin

15:50 In python I would say for line in sys.stdin: print line

15:51 I'm looking for the equivalent

15:51 kotarak: Maybe line-seq, but you need a BufferedReader

15:51 * albino goes to look at line-seq

15:52 albino: kotarak: that should work, thanks

15:52 kotarak: That leads me to another question: If I use line-seq with split-with. Are the lines read into memory? Or is this done only, when a access the two seq I get back?

15:53 rhickey: kotarak: enough is read to find the split point

15:54 kotarak: rhickey: Hmm.. Ok. Thanks.

15:54 Chouser: (require '[clojure.contrib.duck-streams :as ds])

15:55 (doseq line (line-seq (ds/reader System/in)) (println line))

15:55 * kotarak has to have a look at duckstreams, it seems.

15:56 Chouser: yeah, it causes a bunch of Java io pain to evaporate.

16:00 well, I finally checked in clojure.contrib.lazy-xml

16:01 please hold your applause until the end of the show. ;-)

16:01 abrooks: Chouser: Cool. Has it changed significantly since X months ago?

16:01 Chouser: abrooks: it works now, but otherwise no.

16:02 It'll use a pull parser if it's in the classpath, otherwise it does some ugly threading and weakreference stuff to tame the built-in SAX parser (or any SAX parser you hand it).

16:03 abrooks: Oh the original parser was greedy, right?

16:03 Chouser: Either way, the API is the same and you end up with a clojure.xml compatible tree of hashes and lazy-seqs.

16:03 abrooks: yep

16:03 abrooks: This one is sort of lazy it sounds.

16:04 Chouser: the only other API difference (so far) is that emit doesn't add extra newlines unless you ask it to.

16:05 abrooks: Chouser: Is with_pull.clj the lazy pull parser?

16:05 Oh, no. It's just a wrapper.

16:05 Chouser: I want to add more complete namespace support and maybe a more compact data structure (as has been discussed), but I wanted to make sure I got at least this much out there.

16:06 yeah, I didn't write my own parser.

16:06 abrooks: Chouser: By compact you mean terser for readability concerns that you and I've discussed or something else?

16:07 Chouser: a single vector (or lazy-cons) per element instead of a hash and a vector.

16:08 It would also help with readability, but I now think that's secondary -- providing converters that may or may not be triggered automatically may be sufficient.

16:11 meredydd: Ooh, wow. defonce is in SVN? Lovely.

16:15 What's the current status of SQL in clojure? Is contrib's sql module the latest word, or is something else being mooted/cooked up elsewhere?

16:18 rhickey: meredydd: what do you want that jdbc doesn't do?

16:18 meredydd: Well, pool connections

16:19 But, generally speaking, I'm looking for a Clojure-idiomatic way of doing things

16:19 rhickey: resultset-seq

16:19 meredydd: If there's nothing already out there, then I'll get on with writing my own wrappers

16:19 Where does that live?

16:20 rhickey: boot.clj

16:21 meredydd: Excellent. Thank-you.

16:23 rhickey: meredydd: http://commons.apache.org/dbcp/

16:31 meredydd: Gah. Dodgy wireless routers suck.

16:31 rhickey: Did you say anything else since you recommended dbcp?

16:31 rhickey: nope

16:32 not a recommendation, just a pointer. I presume you're not in Tomcat or another app server with connection pooling

16:32 blackdog: another good one is http://proxool.sourceforge.net/

16:33 meredydd: Right now, I'm in Compojure

16:35 (Aiee. It's an Apache Commons project, all right. The basic version of the setup involves factory methods, registration, and all sorts of dependency injection - and the "easier way" is 28 lines of extremely verbose XML.

16:36 blackdog: try proxool, it's transparent

16:37 Chouser: meredydd: that's your proof that it's not a toy

16:37 * Chouser ducks

16:37 blackdog: a special jdbc:proxool url with yout db of choice

16:37 meredydd: Chouser: *Really* don't get me started.

16:37 One of the nastier experiences of the last two months was starting a new project, and moving from Apache XML-RPC v2 to v3.

16:39 blackdog: http://proxool.sourceforge.net/quickStart.html

16:40 meredydd: Thank-you, blackdog.

16:46 wwmorgan: rhickey: the print method in clojure.lang.RT ought to check whether its argument is a Pattern and emit such forms like #"foo"

16:57 albino: How do I invoke a some clojure code outside of the repl? I was hoping to do java -cp /path/to/clojure.jar /path/to/code.clj

16:58 Chouser: close. Just add clojure.lang.Repl between .jar and .clj

16:58 or clojure.lang.Script if you don't want to drop to a Repl when the .clj is done.

16:59 albino: Chouser: thanks

16:59 Chouser: http://en.wikibooks.org/wiki/Clojure_Programming#Installation_from_Source

17:00 are you on a unix?

17:01 albino: gentoo linux

17:01 Chouser: rhickey: someone wrote a defmulti version of print, didn't they? Is that planned for inclujion?

17:01 abrooks: Chouser: If only we knew some Gentoo devs who could get Clojure into portage....

17:02 albino: has someone already packaged it?

17:02 Chouser: albino: in that case you may be interested in http://en.wikibooks.org/wiki/Clojure_Programming#Shebang_Scripting_in_Clojure as well

17:02 albino: Chouser: thank you

17:02 I'll be using that for sure

17:02 abrooks: albino: Oh, it wouldn't be hard. I think I even started an ebuild at some point.

17:03 I think I'd block it on having a better shell wrapper. The current one is... not so good.

17:03 Chouser: abrooks: you don't like rlwrap?

17:04 abrooks: Chouser: Oh, rlwrap is okay. I still want a context sensative REPL but that's neither here nor there.

17:04 albino: abrooks: you a gentoo dev?

17:05 abrooks: albino: No. I've been dangerously close at times. I work for a company that use Gentoo as a meta distribution (and also have been using Gentoo since who-knows-when).

17:06 albino: abrooks: nice

17:06 In that case I volunteer abrooks before myself for packaging clojure

17:06 that was easy enough

17:06 abrooks: I hang out with a number of Gentoo/ex-Gentoo devs on- and off-line.

17:07 Chouser: mostly ex- now

17:07 pjstadig: what about debian?

17:08 abrooks: I'll wait for the next release since that seems imminent.

17:08 pjstadig: anyone have enough experience to build a .deb?

17:08 abrooks: Chouser: I think it's still more current than ex- but I could be wrong.

17:09 albino: I'm sure if I took some time I could build a deb, these days I'm supposed to be getting good at rpms

17:11 * abrooks is confused by the concept "good at rpms"

17:11 albino: abrooks: cause they're brain dead, or what?

17:11 abrooks: I suppose one can be "good at potato sack racing"...

17:12 albino: :)

17:29 albino: If anyone wants to make fun of some clojure code I wrote, I'm looking for feedback http://paste.lisp.org/display/66505

17:33 meredydd: Okay...

17:33 Your big issue here is that you keep wanting to use mutable variables.

17:34 albino: meredydd: teach me

17:34 meredydd: What you wrote is more or less a Clojure transliteration of what you'd do in a (pardon me) 'normal' programming language.

17:35 A good start would be to completely eliminate all (def)s from that code.

17:35 albino: how would I fit immutability in with solving this problem?

17:35 meredydd: They (re)define global variables

17:35 In my experience, there are two uses of this kind of thing.

17:35 albino: but making them local, still isn't the right way, right?

17:36 meredydd: One, you do right at the top, there - you use a def to assign a name (stdin) to the result of a big hairy expression

17:36 There's no need to define a global variable to do that - you can just use (let). So:

17:37 (let [stdin (...big long hairy expression here)]

17:37 ...carry on and work with stdin here... )

17:37 albino: the gain being that I'm not defining another global variable?

17:38 Chouser: that's not the moste terrible use of def, though. The ones inside doseq is much worse.

17:38 meredydd: the gain being that you're recognising that 'stdin' is an immutable name for something, and that it's locally scoped. (let) has those characteristics.

17:39 Chouser: sorry for the snipe -- gotta go. :-/

17:39 meredydd: cya, Chouser

17:40 Now, as Chouser says, the real issue is that you're using (def) to create a variable whose value changes

17:41 which is something that's deliberately ugly in clojure, because it's so un-clojure-ish.

17:41 albino: Still with me?

17:42 albino: meredydd: yes

17:43 meredydd: Okay. In the functional world, we think of recursive solutions as much as possible, rather than iteratively changing things.

17:43 Let's start with a much more simple example - the classic factorial one.

17:44 (1! = 1, 2! = 2 * 1, 3! = 3 * 2 * 1, 4! = 4 * 3 * 2 * 1, ...)

17:44 Now, if you were doing that in Java, you might do something like:

17:44 void fact(int n) {

17:44 int val=1;

17:45 for(; n>=1; n--) { val = val * n; }

17:45 }

17:45 Yes?

17:45 albino: yes

17:46 meredydd: Now, in Clojure, we would do something more like:

17:46 (defn fact [n]

17:47 (if (= n 1)

17:47 1

17:47 (* n (fact (dec n)))))

17:48 Do you understand how that works?

17:56 albino: yeah, uses recursion

17:58 meredydd: right

17:58 The point is that, instead of changing the value of 'n'

17:58 what you do is go into a new frame, with 'n' having a different value.

17:59 Now, in practice you'll use a bit of a cheat to account for the fact that you can't have an infinite number of stack frames

18:00 albino: are frames cheaper in functional languages and that's why that approach is chosen more often?

18:01 meredydd: Not so much. It's actually a conceptual choice - when writing large programs, it very quickly gets a hell of a lot easier to use functional techniques than standard mutable state

18:01 (let alone if you're doing something like multithreading)

18:01 so, the fact that functional runtimes often use tricks to keep stack frame usage low is a consequence of that philosophical approach

18:02 Clojure has (recur), which is a special form.

18:04 oh, blast.

18:04 I'm sorry - I have to go now.

18:04 albino: np

18:04 thanks for the info

18:04 much appreciated

18:04 meredydd: Try looking for an "introduction to functional programming" article

18:05 rhickey: albino: here are some more tips:

18:05 split your function into 2 - one that calculates a result and another that prints it. Combining the two will always make a mess

18:06 give the value-calculating function a good name so we know what you are trying to do

18:07 albino: okay, that's easy enough

18:07 didn't figure it was worth it for such a short problem

18:07 rhickey: make sure both functions take args (i.e. don't hardwire your global name)

18:08 albino: functions will make it easier to do the right thing, but not longer in the end

18:09 wwmorgan: albino: if you had a function that took a string and produced a sequence of nesting levels for each character in the string, ie "(((a)))" yielded (1 2 3 3 2 1 0), then your problem becomes easy: for each line, paren-count is the last element in that sequence, and paren-depth is the max element

18:09 *eg

18:16 rhickey: the print method in clojure.lang.RT ought to check whether its argument is a Pattern and emit such forms like #"foo"

18:22 fyuryu: if anybody is interested in a processing wrapper, here's one: http://bit.ly/3ZT3ZG

18:24 I wanted to push it to github but git+ssh+windows apparently don't get get along

18:42 meredydd: fyuryu: I think the best thing might be to post a link to the Google Group

18:45 fyuryu: meredydd: yeah, I'm doing it now

Logging service provided by n01se.net