2008-09-08
| 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 | Chouser | memory |
| 10:45 | Chouser | Relative lookup performance between the two would be roughly the same regardless the size, wouldn't it? |
| 10:45 | rhickey | yes |
| 10:46 | rhickey | not a percentage thing, really. absolute sizes matter |
| 10:47 | Chouser | oh, ok. |
| 10:47 | Chouser | 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 | rhickey | 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 | Chouser | 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 | Chouser | probably a Java question, I guess. |
| 10:51 | rhickey | no |
| 10:51 | rhickey | but another key question is - how many instances of the same struct? |
| 10:52 | Chouser | one per XML node. So... *shrug* |
| 10:52 | Chouser | 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 | cemerick | 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 | cemerick | Yourkit is very nice, although being able to use NB would be great. |
| 11:01 | rhickey | agreed |
| 11:02 | rhickey | I guess VisualVM is in same boat as NB |
| 11:02 | cemerick | How to isolate its problem is entirely unclear to me... |
| 11:03 | cemerick | Hrm, hadn't come across VisualVM before, thanks. |
| 11:03 | cemerick | 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 | cemerick | 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 | rhickey | 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 | rhickey | 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 | rhickey | 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 | pjstadig | 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 | pjstadig | 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 | Chouser | ) |
| 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 | Chouser | 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 | Chouser | 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 | Chouser | blackdog: http://groups.google.com/group/clojure/msg/73fdae1e56ffae71 |
| 12:17 | blackdog | thanks |
| 12:19 | pjstadig | dumb question |
| 12:19 | pjstadig | what is the best way to exit the REPL |
| 12:19 | pjstadig | (quit) (exit) don't seem to work |
| 12:19 | pjstadig | ^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 | pjstadig | (System/exit 0) |
| 12:21 | pjstadig | java.lang.Exception: No such namespace: System |
| 12:21 | Chouser | cgrand: hi! Any recent changes to your Javascript HTML templating stuff? |
| 12:22 | Chouser | pjstadig: Yeah, if you've got an older Clojure. In oldest to newest: |
| 12:22 | Chouser | (. System exit 0) (.exit System 0) (System/exit 0) |
| 12:22 | pjstadig | oh ok |
| 12:23 | pjstadig | i've got the download snapshot |
| 12:23 | pjstadig | 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 | albino | 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 | Chouser | 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 | Chouser | 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 | blackdog | 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 | blackdog | 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 | blackdog | actually maybe twisted python has some protcol |
| 14:34 | Chouser | avoid twisted. |
| 14:34 | Chouser | 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 | rhickey | These are not toys |
| 14:41 | blackdog | i think for anyone considering clojure for commercial work |
| 14:41 | blackdog | the jvm is a terrific choice |
| 14:41 | blackdog | it's an easy sell to customers |
| 14:41 | blackdog | 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 | blackdog | which made me say purity there |
| 14:45 | blackdog | for example, people talking about the abstraction is java underneath |
| 14:46 | blackdog | and then talk of assembler being the ultimate abstraction |
| 14:46 | blackdog | 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 | rhickey | 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 | rhickey | 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 | pjstadig | 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 | pjstadig | 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 | pjstadig | just curious |
| 15:09 | rhickey | also now there is a package/namespace unification, so com.pjstadig.libname |
| 15:10 | pjstadig | oh |
| 15:10 | pjstadig | 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 | abrooks | 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 | abrooks | (changes RSS--^) |
| 15:18 | rhickey | abrooks: I don't know, this just falls out of the Wiki software, maybe tomhickey knows... |
| 15:18 | rhickey | 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 | Chouser | but "h" is a string |
| 15:19 | Chouser | try \h instead |
| 15:19 | albino | ahh, characters are different from strings, thanks |
| 15:20 | Chouser | Yep. (class "hi") ==> java.lang.String |
| 15:20 | Chouser | (class \h) ==> java.lang.Character |
| 15:21 | leafw | is there any reason why the following fails: (pop (seq (double-array 10))) |
| 15:22 | leafw | 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 | leafw | I would like to understand how is pop different than rest. |
| 15:24 | leafw | 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 | leafw | 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 | Chouser | 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 | Chouser | oh, wait, I figured this out once... |
| 15:29 | Chouser | (pop [1 2 3]) ==> [1 2] (rest [1 2 3]) ==> (2 3) |
| 15:30 | Chouser | not the same |
| 15:30 | leafw | hum |
| 15:31 | leafw | 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 | Chouser | ...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 | leafw | so vectors are more like linked lists then |
| 15:32 | leafw | 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 | leafw | 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 | rhickey | leafw: no, vectors are most like arrays/arraylists, not chained, fast indexed access |
| 15:38 | rhickey | peek/pop work on the same end as conj |
| 15:38 | rhickey | first/rest always at front |
| 15:38 | rhickey | 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 | rhickey | peek/pop return the same type of collection, first/rest always return seqs |
| 15:40 | rhickey | 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 | rhickey | at top level (def b 0) (def a b) |
| 15:42 | rhickey | in a fn (let [b 0 a b] ...) |
| 15:43 | albino | rhickey: thanks |
| 15:46 | albino | 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 | Chouser | oh, nm. |
| 15:49 | Chouser | 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 | albino | In python I would say for line in sys.stdin: print line |
| 15:51 | albino | I'm looking for the equivalent |
| 15:51 | kotarak | Maybe line-seq, but you need a BufferedReader |
| 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 | Chouser | (doseq line (line-seq (ds/reader System/in)) (println line)) |
| 15:56 | Chouser | yeah, it causes a bunch of Java io pain to evaporate. |
| 16:00 | Chouser | well, I finally checked in clojure.contrib.lazy-xml |
| 16:01 | Chouser | 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 | Chouser | 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 | Chouser | 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 | abrooks | 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 | Chouser | 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 | Chouser | 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 | meredydd | 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 | meredydd | 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 | meredydd | 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 | meredydd | rhickey: Did you say anything else since you recommended dbcp? |
| 16:31 | rhickey | nope |
| 16:32 | rhickey | 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 | meredydd | (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 | blackdog | a special jdbc:proxool url with yout db of choice |
| 16:37 | meredydd | Chouser: *Really* don't get me started. |
| 16:37 | meredydd | 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 | Chouser | 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 | Chouser | 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 | albino | 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 | abrooks | 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 | albino | In that case I volunteer abrooks before myself for packaging clojure |
| 17:06 | albino | 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 | albino | abrooks: cause they're brain dead, or what? |
| 17:11 | abrooks | I suppose one can be "good at potato sack racing"... |
| 17:12 | abrooks | 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 | meredydd | 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 | meredydd | 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 | meredydd | 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 | meredydd | There's no need to define a global variable to do that - you can just use (let). So: |
| 17:37 | meredydd | (let [stdin (...big long hairy expression here)] |
| 17:37 | meredydd | ...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 | meredydd | Now, as Chouser says, the real issue is that you're using (def) to create a variable whose value changes |
| 17:41 | meredydd | which is something that's deliberately ugly in clojure, because it's so un-clojure-ish. |
| 17:41 | meredydd | 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 | meredydd | Let's start with a much more simple example - the classic factorial one. |
| 17:44 | meredydd | (1! = 1, 2! = 2 * 1, 3! = 3 * 2 * 1, 4! = 4 * 3 * 2 * 1, ...) |
| 17:44 | meredydd | Now, if you were doing that in Java, you might do something like: |
| 17:44 | meredydd | void fact(int n) { |
| 17:44 | meredydd | int val=1; |
| 17:45 | meredydd | for(; n>=1; n--) { val = val * n; } |
| 17:45 | meredydd | } |
| 17:45 | meredydd | Yes? |
| 17:45 | albino | yes |
| 17:46 | meredydd | Now, in Clojure, we would do something more like: |
| 17:46 | meredydd | (defn fact [n] |
| 17:47 | meredydd | (if (= n 1) |
| 17:47 | meredydd | 1 |
| 17:47 | meredydd | (* n (fact (dec n))))) |
| 17:48 | meredydd | Do you understand how that works? |
| 17:56 | albino | yeah, uses recursion |
| 17:58 | meredydd | right |
| 17:58 | meredydd | The point is that, instead of changing the value of 'n' |
| 17:58 | meredydd | what you do is go into a new frame, with 'n' having a different value. |
| 17:59 | meredydd | 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 | meredydd | (let alone if you're doing something like multithreading) |
| 18:01 | meredydd | so, the fact that functional runtimes often use tricks to keep stack frame usage low is a consequence of that philosophical approach |
| 18:02 | meredydd | Clojure has (recur), which is a special form. |
| 18:04 | meredydd | oh, blast. |
| 18:04 | meredydd | I'm sorry - I have to go now. |
| 18:04 | albino | np |
| 18:04 | albino | thanks for the info |
| 18:04 | albino | 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 | rhickey | 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 | rhickey | 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 | albino | 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 | rhickey | 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 | wwmorgan | *eg |
| 18:16 | wwmorgan | 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 | fyuryu | 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 |