#clojure logs

2008-09-08

10:42Chouserwhat percentage of a struct-map has to be nil before it's less efficient than a sparse hash map (roughly speaking, on average).
10:43rhickeyChouser: less efficient in what way?
10:44ChouserI was thinking space.
10:44Chousermemory
10:45ChouserRelative lookup performance between the two would be roughly the same regardless the size, wouldn't it?
10:45rhickeyyes
10:46rhickeynot a percentage thing, really. absolute sizes matter
10:47Chouseroh, ok.
10:47ChouserIn 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:48rhickeywould the keys be in the hash-map or not?
10:48rhickeykey set to nil value and no key are different
10:48Chouseroh, right, in the hash-map they'd be half empty. In the struct-map they'd be half nil.
10:49ChouserIn this case I don't need to differentiate.
10:50rhickeystruct-map is likely to be smaller, but you'd have to look at the implementation or measure to know
10:51Chouseris there an easy to way to ask a collection for its size in bytes?
10:51Chouserprobably a Java question, I guess.
10:51rhickeyno
10:51rhickeybut another key question is - how many instances of the same struct?
10:52Chouserone per XML node. So... *shrug*
10:52Chouserlikely hundreds. Maybe thousands.
10:53rhickeythen the shared keys will win
10:54Chouserok, thanks.
10:54rhickeyno substitute for profilng - speaking of which, I wonder if cemerick had any luck with profilers?
10:56cemerickrhickey: 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:57cemerickobviously, 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:58rhickeycemerick: by 'work fine' do you mean you can collective meaningful data on Clojure fn calls etc, not just Clojure's Java runtime?
10:59cemerickrhickey: well, clojure fns and such appear on their own as distinct call sites, if that's what you're getting at.
10:59rhickeyyes, that, getting number of calls, time spent in, time spent in children etc
11:00cemerickyeah, 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:01rhickeycool
11:01cemerickYourkit is very nice, although being able to use NB would be great.
11:01rhickeyagreed
11:02rhickeyI guess VisualVM is in same boat as NB
11:02cemerickHow to isolate its problem is entirely unclear to me...
11:03cemerickHrm, hadn't come across VisualVM before, thanks.
11:03cemerickBut yeah, being on NB, I would expect it to have the same hang-ups.
11:17blackdogrhickey, http://lambda-the-ultimate.org/node/2978
11:17rhickeyblackdog: saw that, thanks
11:17blackdogk
11:18rhickeyno controversy, so everyone must agree :)
11:18blackdog:) waiting for the fireworks
11:20ChouserLtU 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:20cemerick"...its target focus is concurrency..." Funny, as we've not really touched the concurrency stuff at all.
11:21cemerickLtU has been pretty balanced over the years, IMO.
11:21Chouserok. I read it, but must admit to understanding a pretty small fraction of the issues that are brought up.
11:27rhickeyChouser: 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:29rhickeycemerick: yeah, FP is good for concurrency but not only that. Few people understand how their mutable state effects everything
11:31Chouser"Let's make a programming language!" on LtU -- haha! so doomed!
11:31rhickeyI'm happy for the coverage and the nice writeup
11:31cemerickWhile 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:33rhickeycemerick: 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:33rhickeya broader audience for Clojure is desired :)
11:34cemerickrhickey: 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:34ChouserThat's a demure Rich Hickey form of Torvald's goal of taking over the world.
11:35rhickeyClojure will always be for discriminating tastes, but I'd like to saturate that market
11:36ChouserRuby 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:39cemerickI'm deeply pessimistic about the ability of a non-curly-brace language becoming widespread anytime soon (outside of those with "discriminating tastes" , perhaps ;-))
11:39pjstadigclojure's way of dealing with concurrency is what caught my attention
11:39rhickeyClojure has curly braces!
11:40cemerick:-P
11:40pjstadigdon'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:41ChouserI'm here (originally) because of Java libs + macros.
11:41rhickeyChouser: so how have you found the functional programming side?
11:41Chouseroh, and dynamic types too, I guess.
11:41pjstadigyeah (in my short time getting acquainted with clojure) there are lots of selling points to clojure
11:42Chouserrhickey: yummy.
11:42rhickeyThat'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:43rhickeyas FP langs go Clojure is IMO the most approachable
11:43pjstadigi don't know ML or Haskell, but i've tried to get acquainted
11:43pjstadigand Clojure is more approachable IMO
11:43rhickeybut I don't think people are looking for FP, just suffering from OO mess...
11:44ChouserI 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:44pjstadigthe blip vids are great though
11:45pjstadigsomeone passed them along to my Ruby Users Group
11:46ChouserAnd 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:46Chouser)
11:46rhickeyChouser: they're working on it:http://www.codecommit.com/blog/scala/more-persistent-vectors-performance-analysis :)
11:46cemerickyeah, I came by way of Scala too
11:48ChouserI got to Scala by way of Rhino. :-)
11:50rhickeyChouser: so with ClojureScript you'll get back to Rhino?
11:51Chouserheh. no.
11:52ChouserI 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:55Chouseralthough I suppose testing ClojureScript by running the results on Rhino might be handy.
11:56blackdogwhat is clojurescript a clj to js translator then? does code exist?
12:12Chouseryes, that's what it would be. There is some very preliminary code, but I don't think anyone's actively advancing it.
12:13blackdogis that in contrib ?
12:13Chouserblackdog: no. Let me see if I can find a link.
12:17Chouserblackdog: http://groups.google.com/group/clojure/msg/73fdae1e56ffae71
12:17blackdogthanks
12:19pjstadigdumb question
12:19pjstadigwhat is the best way to exit the REPL
12:19pjstadig(quit) (exit) don't seem to work
12:19pjstadig^C?
12:19Chouser^D
12:20pjstadigthanks
12:20ChouserOr (System/exit 0)
12:21pjstadigyou mean (. System exit 0)?
12:21pjstadig(System/exit 0)
12:21pjstadigjava.lang.Exception: No such namespace: System
12:21Chousercgrand: hi! Any recent changes to your Javascript HTML templating stuff?
12:22Chouserpjstadig: Yeah, if you've got an older Clojure. In oldest to newest:
12:22Chouser(. System exit 0) (.exit System 0) (System/exit 0)
12:22pjstadigoh ok
12:23pjstadigi've got the download snapshot
12:23pjstadigfrom june i think
12:23Chousersorry, I rapidly lose track of which changes were made how recently.
13:50albinoHas clojure chosen a convention for word separation in variable names? camelCase or under_scores ?
13:51rhickeydashes-please
13:51albinooh duh, lisp
13:52albinonext newbie question, how do I do else if
13:52Chouser(if <test> <then-clause> <else-clause>)
13:53albinoI'm lookinng for something like (if <test> <body> elif <test> <body> else <body>)
13:54rhickeyalbino: cond
13:55albinorhickey: thanks
14:02rhickeyhttp://www.reddit.com/r/programming/comments/7031x/maybe_building_a_new_language_on_a_homemade_vm/
14:09Chouseryour willingness to read and respond to reddit comments demonstrates impressive patience.
14:10rhickeyChouser: it's interesting to see the level of animosity towards the JVM
14:14pjstadigwell there's that, and people also seem to be missing the thrust of the argument
14:14rhickeypjstadig: yes, that's frustrating
14:14pjstadigwhich is not necessarily that the JVM is The Way (TM), just that it may be smarter to not start from scratch
14:21Chouserdoes anyone agree with zzzeek's comment that many Java libraries are sub-par in some way compared to libraries for other languages?
14:22ChouserI guess poor API doesn't bother me much since slapping a pretty Clojure API on top usually requires only a little code.
14:22ChouserBut having had fairly little experience with Java, I don't know if I should be worried about buggy or poorly-performing libs.
14:23blackdogcertainly clojure gets round all my issues with the java infrastructure(barring egregious memory use)
14:24rhickeyChouser: any such blanket comment is suspect, I doubt all Java libs are bad nor all Python libs good
14:24blackdogi think it's the extra scaffolding required of java that people hate, and that disappears with clojure
14:25blackdogi.e. it's not really the libraries
14:25rhickeyalso he did some EJB, which is particularly painful, and SOAP
14:25ChouserI 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:26rhickeyI 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:26ChouserIf 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:27rhickeyWhat's the Python alternative to JMS?
14:27blackdogyou can use the stomp protocol from various clients inc python
14:27blackdogapachemq supports it
14:28rhickeyblackdog: yeah, apache activemq is Java/JMS
14:30blackdogif you mean a python like implementation of a jms server then i don't know
14:34blackdogactually maybe twisted python has some protcol
14:34Chouseravoid twisted.
14:34Chousertwisted is actually what I was specifically thinking of when I said "not all Python libs are good" :-)
14:34blackdog:) i use it for a chat server
14:38rhickeyI 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:38rhickeyThese are not toys
14:41blackdogi think for anyone considering clojure for commercial work
14:41blackdogthe jvm is a terrific choice
14:41blackdogit's an easy sell to customers
14:41blackdogfor academic work etc, purity maybe not
14:42rhickeyblackdog: what do you mean by purity?
14:43blackdogwell people on that thread seemed a bit academic to me, there was a particualr quote
14:43blackdogwhich made me say purity there
14:45blackdogfor example, people talking about the abstraction is java underneath
14:46blackdogand then talk of assembler being the ultimate abstraction
14:46blackdogetc
14:52Chouserthe i86 instruction set doesn't support TCO either, does it?
14:53rhickeyChouser: everything is manual at that level.
14:54rhickeyturtles 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:55ChouserI'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:56blackdogor me, that was my point, the other stuff is academic argument while we get to write code now
14:59rhickeyChouser: you would be defining your own calling convention and could easily (manually) do TCO, just clear stack before jumping
15:01Chouserah, you can't jump into a Java function? you must call?
15:03rhickeyChouser: yeah, that's all abstracted away, the instructions are high-level, like invokeVirtual
15:03rhickeyyou can't fudge the stack at all
15:03Chouserthere's goto, but only within a function?
15:04rhickeyChouser: right
15:04pjstadigis there a preference between 'clj' and 'clojure' when naming libraries, executables, etc.?
15:04pjstadigclojure-extra vs. clj-extra
15:05rhickeypjstadig: unless you are planning a contribution to Clojure, you should avoid using it to avoid conflict with the base libs
15:06pjstadigi mean just a project name
15:06pjstadigon github you see projects like clojure-mcp, clj-cont, etc.
15:08rhickeyI guess clj- is like the J all java libs prepend, but you should avoid Clojure, reserved for the language itself.
15:09pjstadigyeah or i was thinking maybe clj- is the equivalent of cl- for common lisp
15:09pjstadigjust curious
15:09rhickeyalso now there is a package/namespace unification, so com.pjstadig.libname
15:10pjstadigoh
15:10pjstadigcool
15:10abrooksrhickey: Is that documented on the main website or only in the Google Group? :)
15:11rhickeyabrooks: 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:12abrooksrhickey: Cool. BTW, I just noticed the "Recent Changes" link on the website. Good idea. Is there an RSS feed for website changes?
15:13abrooksOh, I see that the RSS feed for the changes page is the website changes.
15:13StartsWithK_rhickey: is there maven repository or something similar with clojure.jar from current trunk?
15:14rhickeyStartsWithK_: not from me, but probably
15:15abrooksSorry, should have looked first. Maybe that could be a discrete link (currently it's only provided via the linkrel).
15:15abrooks(changes RSS--^)
15:18rhickeyabrooks: I don't know, this just falls out of the Wiki software, maybe tomhickey knows...
15:18rhickeyabrooks: in any case, between releases the changes are mostly doc bug-fixes, not tracking SVN
15:18albino(doseq i "hello" (if (= i "h") (println "match"))) Why doesn't that print match?
15:19Chouseralbino: a string is a sequence of characters
15:19Chouserbut "h" is a string
15:19Chousertry \h instead
15:19albinoahh, characters are different from strings, thanks
15:20ChouserYep. (class "hi") ==> java.lang.String
15:20Chouser(class \h) ==> java.lang.Character
15:21leafwis there any reason why the following fails: (pop (seq (double-array 10)))
15:22leafwjava.lang.ClassCastException: clojure.lang.ArraySeq$ArraySeq_double cannot be cast to clojure.lang.IPersistentStack
15:23abrooksrhickey: 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:23Chouserleafw: any reason not to use "rest" instead of "pop"?
15:23leafwno reason. Just testing
15:24leafwI would like to understand how is pop different than rest.
15:24leafwpeek also fails in the same situaton.
15:25Chousersure. peek and pop operate on IPersistentStack
15:25leafwthat is evident from the cast error.
15:25ChouserArraySeq extends ASeq, but not IPersistentStack
15:25leafwbut what do you mean?
15:26leafwperhaps my question ought to be reformulated: why should there be different treatment of sequences?
15:26Chouseryeah, that's a deep enough "why" that I don't think I can help you. :-)
15:27ChouserWith persistent collections, is there ever any different between peek/pop and first/rest?
15:27leafwif by persistent you mean immutable, no, they both return a new collection anyway.
15:28ChouserAnd yet rhickey implemented IPersistentStack, so I must be missing something.
15:28Chouseroh, wait, I figured this out once...
15:29Chouser(pop [1 2 3]) ==> [1 2] (rest [1 2 3]) ==> (2 3)
15:30Chousernot the same
15:30leafwhum
15:31leafwweird. So vectors are treated differently.
15:31Chouserso peek/pop don't operate on seqs in general, but on specific data structures that support it.
15:31Chouser...while all collections support first/rest
15:31leafwyeah, like a java.lang.Vector (or whatever it is that Cloujure uses in replacement)
15:32leafwso vectors are more like linked lists then
15:32leafwlike cons cells chained.
15:32Chouservectors 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:33leafwArraySeq is new to me.
15:34leafwthanks Chouser, you did cast some light.
15:34Chouserthere's actually lots of little seq classes to implement seqs around various underlying data structures.
15:37rhickeyChouser: all coolections support seq, which in turn supports first/rest
15:38rhickeyleafw: no, vectors are most like arrays/arraylists, not chained, fast indexed access
15:38rhickeypeek/pop work on the same end as conj
15:38rhickeyfirst/rest always at front
15:38rhickeyconj on lists is at front, on vectors at end
15:38Chouserwell... first/rest (the clojure functions) call seq on their arg, right?
15:39rhickeyright, but the collection only need implement seq
15:39Chouserok
15:39rhickeyfirst/rest are provided by the seq, while peek/pop are provided by the collection
15:40rhickeypeek/pop return the same type of collection, first/rest always return seqs
15:40rhickeyso, many differences
15:40albinoIf 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:41rhickeyalbino: def returns the var, not the value
15:42rhickeyat top level (def b 0) (def a b)
15:42rhickeyin a fn (let [b 0 a b] ...)
15:43albinorhickey: thanks
15:46albinois there a nice way to read from stdin, or do I just follow the same way that java would?
15:49Chouseryou might look at slurp
15:49Chouseroh, nm.
15:49Chouseryou want line-at-a-time, the whole stdin to EOF, or what?
15:50albinoyes, read one line at a time from stdin
15:50albinoIn python I would say for line in sys.stdin: print line
15:51albinoI'm looking for the equivalent
15:51kotarakMaybe line-seq, but you need a BufferedReader
15:52albinokotarak: that should work, thanks
15:52kotarakThat 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:53rhickeykotarak: enough is read to find the split point
15:54kotarakrhickey: Hmm.. Ok. Thanks.
15:54Chouser(require '[clojure.contrib.duck-streams :as ds])
15:55Chouser(doseq line (line-seq (ds/reader System/in)) (println line))
15:56Chouseryeah, it causes a bunch of Java io pain to evaporate.
16:00Chouserwell, I finally checked in clojure.contrib.lazy-xml
16:01Chouserplease hold your applause until the end of the show. ;-)
16:01abrooksChouser: Cool. Has it changed significantly since X months ago?
16:01Chouserabrooks: it works now, but otherwise no.
16:02ChouserIt'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:03abrooksOh the original parser was greedy, right?
16:03ChouserEither way, the API is the same and you end up with a clojure.xml compatible tree of hashes and lazy-seqs.
16:03Chouserabrooks: yep
16:03abrooksThis one is sort of lazy it sounds.
16:04Chouserthe only other API difference (so far) is that emit doesn't add extra newlines unless you ask it to.
16:05abrooksChouser: Is with_pull.clj the lazy pull parser?
16:05abrooksOh, no. It's just a wrapper.
16:05ChouserI 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:06Chouseryeah, I didn't write my own parser.
16:06abrooksChouser: By compact you mean terser for readability concerns that you and I've discussed or something else?
16:07Chousera single vector (or lazy-cons) per element instead of a hash and a vector.
16:08ChouserIt 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:11meredyddOoh, wow. defonce is in SVN? Lovely.
16:15meredyddWhat'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:18rhickeymeredydd: what do you want that jdbc doesn't do?
16:18meredyddWell, pool connections
16:19meredyddBut, generally speaking, I'm looking for a Clojure-idiomatic way of doing things
16:19rhickeyresultset-seq
16:19meredyddIf there's nothing already out there, then I'll get on with writing my own wrappers
16:19meredyddWhere does that live?
16:20rhickeyboot.clj
16:21meredyddExcellent. Thank-you.
16:23rhickeymeredydd: http://commons.apache.org/dbcp/
16:31meredyddGah. Dodgy wireless routers suck.
16:31meredyddrhickey: Did you say anything else since you recommended dbcp?
16:31rhickeynope
16:32rhickeynot a recommendation, just a pointer. I presume you're not in Tomcat or another app server with connection pooling
16:32blackdoganother good one is http://proxool.sourceforge.net/
16:33meredyddRight now, I'm in Compojure
16:35meredydd(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:36blackdogtry proxool, it's transparent
16:37Chousermeredydd: that's your proof that it's not a toy
16:37blackdoga special jdbc:proxool url with yout db of choice
16:37meredyddChouser: *Really* don't get me started.
16:37meredyddOne of the nastier experiences of the last two months was starting a new project, and moving from Apache XML-RPC v2 to v3.
16:39blackdoghttp://proxool.sourceforge.net/quickStart.html
16:40meredyddThank-you, blackdog.
16:46wwmorganrhickey: the print method in clojure.lang.RT ought to check whether its argument is a Pattern and emit such forms like #"foo"
16:57albinoHow 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:58Chouserclose. Just add clojure.lang.Repl between .jar and .clj
16:58Chouseror clojure.lang.Script if you don't want to drop to a Repl when the .clj is done.
16:59albinoChouser: thanks
16:59Chouserhttp://en.wikibooks.org/wiki/Clojure_Programming#Installation_from_Source
17:00Chouserare you on a unix?
17:01albinogentoo linux
17:01Chouserrhickey: someone wrote a defmulti version of print, didn't they? Is that planned for inclujion?
17:01abrooksChouser: If only we knew some Gentoo devs who could get Clojure into portage....
17:02albinohas someone already packaged it?
17:02Chouseralbino: in that case you may be interested in http://en.wikibooks.org/wiki/Clojure_Programming#Shebang_Scripting_in_Clojure as well
17:02albinoChouser: thank you
17:02albinoI'll be using that for sure
17:02abrooksalbino: Oh, it wouldn't be hard. I think I even started an ebuild at some point.
17:03abrooksI think I'd block it on having a better shell wrapper. The current one is... not so good.
17:03Chouserabrooks: you don't like rlwrap?
17:04abrooksChouser: Oh, rlwrap is okay. I still want a context sensative REPL but that's neither here nor there.
17:04albinoabrooks: you a gentoo dev?
17:05abrooksalbino: 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:06albinoabrooks: nice
17:06albinoIn that case I volunteer abrooks before myself for packaging clojure
17:06albinothat was easy enough
17:06abrooksI hang out with a number of Gentoo/ex-Gentoo devs on- and off-line.
17:07Chousermostly ex- now
17:07pjstadigwhat about debian?
17:08abrooksI'll wait for the next release since that seems imminent.
17:08pjstadiganyone have enough experience to build a .deb?
17:08abrooksChouser: I think it's still more current than ex- but I could be wrong.
17:09albinoI'm sure if I took some time I could build a deb, these days I'm supposed to be getting good at rpms
17:11albinoabrooks: cause they're brain dead, or what?
17:11abrooksI suppose one can be "good at potato sack racing"...
17:12abrooksalbino: :)
17:29albinoIf anyone wants to make fun of some clojure code I wrote, I'm looking for feedback http://paste.lisp.org/display/66505
17:33meredyddOkay...
17:33meredyddYour big issue here is that you keep wanting to use mutable variables.
17:34albinomeredydd: teach me
17:34meredyddWhat you wrote is more or less a Clojure transliteration of what you'd do in a (pardon me) 'normal' programming language.
17:35meredyddA good start would be to completely eliminate all (def)s from that code.
17:35albinohow would I fit immutability in with solving this problem?
17:35meredyddThey (re)define global variables
17:35meredyddIn my experience, there are two uses of this kind of thing.
17:35albinobut making them local, still isn't the right way, right?
17:36meredyddOne, 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:36meredyddThere's no need to define a global variable to do that - you can just use (let). So:
17:37meredydd(let [stdin (...big long hairy expression here)]
17:37meredydd...carry on and work with stdin here... )
17:37albinothe gain being that I'm not defining another global variable?
17:38Chouserthat's not the moste terrible use of def, though. The ones inside doseq is much worse.
17:38meredyddthe 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:39Chousersorry for the snipe -- gotta go. :-/
17:39meredyddcya, Chouser
17:40meredyddNow, as Chouser says, the real issue is that you're using (def) to create a variable whose value changes
17:41meredyddwhich is something that's deliberately ugly in clojure, because it's so un-clojure-ish.
17:41meredyddalbino: Still with me?
17:42albinomeredydd: yes
17:43meredyddOkay. In the functional world, we think of recursive solutions as much as possible, rather than iteratively changing things.
17:43meredyddLet's start with a much more simple example - the classic factorial one.
17:44meredydd(1! = 1, 2! = 2 * 1, 3! = 3 * 2 * 1, 4! = 4 * 3 * 2 * 1, ...)
17:44meredyddNow, if you were doing that in Java, you might do something like:
17:44meredyddvoid fact(int n) {
17:44meredyddint val=1;
17:45meredyddfor(; n>=1; n--) { val = val * n; }
17:45meredydd}
17:45meredyddYes?
17:45albinoyes
17:46meredyddNow, in Clojure, we would do something more like:
17:46meredydd(defn fact [n]
17:47meredydd(if (= n 1)
17:47meredydd1
17:47meredydd(* n (fact (dec n)))))
17:48meredyddDo you understand how that works?
17:56albinoyeah, uses recursion
17:58meredyddright
17:58meredyddThe point is that, instead of changing the value of 'n'
17:58meredyddwhat you do is go into a new frame, with 'n' having a different value.
17:59meredyddNow, 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:00albinoare frames cheaper in functional languages and that's why that approach is chosen more often?
18:01meredyddNot 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:01meredydd(let alone if you're doing something like multithreading)
18:01meredyddso, the fact that functional runtimes often use tricks to keep stack frame usage low is a consequence of that philosophical approach
18:02meredyddClojure has (recur), which is a special form.
18:04meredyddoh, blast.
18:04meredyddI'm sorry - I have to go now.
18:04albinonp
18:04albinothanks for the info
18:04albinomuch appreciated
18:04meredyddTry looking for an "introduction to functional programming" article
18:05rhickeyalbino: here are some more tips:
18:05rhickeysplit your function into 2 - one that calculates a result and another that prints it. Combining the two will always make a mess
18:06rhickeygive the value-calculating function a good name so we know what you are trying to do
18:07albinookay, that's easy enough
18:07albinodidn't figure it was worth it for such a short problem
18:07rhickeymake sure both functions take args (i.e. don't hardwire your global name)
18:08rhickeyalbino: functions will make it easier to do the right thing, but not longer in the end
18:09wwmorganalbino: 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:09wwmorgan*eg
18:16wwmorganrhickey: the print method in clojure.lang.RT ought to check whether its argument is a Pattern and emit such forms like #"foo"
18:22fyuryuif anybody is interested in a processing wrapper, here's one: http://bit.ly/3ZT3ZG
18:24fyuryuI wanted to push it to github but git+ssh+windows apparently don't get get along
18:42meredyddfyuryu: I think the best thing might be to post a link to the Google Group
18:45fyuryumeredydd: yeah, I'm doing it now