#clojure logs

2008-10-17

01:23Lau_of_DKTop of the morning gents
02:12Lau_of_DKanybody else caught this? :) http://robert.zubek.net/blog/2008/04/26/clojure-web-server/
02:15arbschtthat made the rounds some months ago. very nice though
02:17Lau_of_DKYea pretty cool
02:18Lau_of_DKOur company is considering launching a new development division next year, and Im really considering pushing hard for it to be clojure based. Any thoughts?
02:19arbschtexclusively clojure based?
02:20Lau_of_DKNo, Im thinking 80% clojure, 20% php/perl/c. But that will also reflect the demands from our customers
02:23arbschtif it's suitable for the job, that may be worthwhile. I presume php/perl/c are the only alternatives
02:24arbschtbut then I'm not one to give useful advice on these things :) in my work, it's more like 10% among 10 different language systems
02:24Lau_of_DKYes that seems to be the case
02:24Lau_of_DKOk
02:24Lau_of_DKMy only hang-up is, that Im wondering if Clojure is not enterprise ready in all areas. That we might hit dead ends
02:25tWipYou can always work around in Java or patch Clojure... is that really a critical issue?
02:25arbschtcan you try to prototype first?
02:26arbschtearly failure can be cheap
02:26tWipand also... what does "enterprise ready" even mean? seems like buzzwords
02:26Lau_of_DKtWip, it can potentially be a big issue
02:27Lau_of_DKarbscht a prototype is difficult, because initially we will need to find 4 Lispers, which is a pretty big investment
02:27Lau_of_DKtWip, by Enterprise ready, I just mean that its solid enough to build larger project on, without something breaking
02:28arbschtI'm curious, why are 4 necessary?
02:29Lau_of_DKIts an estimate, that with current order-flow thats what we'll need to be prepared to handle the coming workload. We dont want to reject/postpone certain contracts, because the division is not fully operational
02:30Lau_of_DK(brb, afk)
02:32tWipI completely trust that Clojure is enterprise ready (in the sense you mean)
02:47Lau_of_DKK - Thanks alot for your input
03:03johnwaynerPupeno: regarding indention issues. I had some problems and it turns out there are at least two clojure-mode's floating around. I had more luck with this one: http://github.com/jochu/clojure-mode/tree/master . You may want to check which you are using.
05:08Lau_of_DKAny of you sitting with some good Clojure links ? blogs, tutorials, etc.
05:51Lau_of_DKAny of you sitting with some good Clojure links ? blogs, tutorials, etc.
06:29blackdogLau_of_DK: http://blog.thinkrelevance.com/2008/9/25/pcl-clojure-chapter-16
06:30Lau_of_DKThanks Big Dawg
06:32hoeckLau_of_DK: http://www.loufranco.com/blog/files/20-Days-of-Clojure-Day-7.html (clojure vector implementation explained)
06:37Lau_of_DKThanks Hoeck :)
06:55dmileswild.. a channel
07:26emacsendmiles, yes, wild...
07:31dmilesclojure comes closer to having def-java-class from jLinker than abcl huh?
07:34dmilesi been implementing as much of the jLinker (allegro docs) in my javalisp .. but thinking i ought to use clojure classgening for letting lisp subclass exisitng java objects
07:37dmileshas anyone tried a classloading class transformer to instrument preexisting java classes to allow lisp to redefine methods? .. pretty much just adding in a redefined?callClojureInstead
07:38rhickeydmiles: interesting
07:38rhickeybut is there much demand for that?
07:38dmilesi did this a while ago for beansell .. but i forgot alot of things since then
07:40dmilesrhickey, i cant say there has been alot of use cases needing this.. but i am thinking there is sometimes this has to be done to catch exceptions and things
07:40dmilesor to make legitimate subclasses
07:41dmileslegitimate subclass .. trying to figure out a better explaination
07:43dmilesoh i remember.. allowing objects to get created by third parties before and after clojure.. the classes are preinjected (classload transformer) with supporting allowing redefinations
07:44dmilesmainly its for the cases when clojure wasnt able to manage the creation of objects
07:46rhickeydmiles: I'm still not quite clear - genclassed classes can get instantiated separately but have their methods redefined - or is this just an init-order thing?
07:48dmilesgened classes have power to redefine their methods runtime right?
07:48rhickeyyes
07:51dmileswell what made me think i needed this was when i wanted to catch an exception that was thrown as a result of something i did and cliamed to handle.. yet in the object doing something with my method wasnt letting me handle it... i really should come up with a clearer explainaion ;P
07:52dmilesi wanted to make the handler catch an exception .. yet the code that caused the exception was from a class i didnt write.. but was preloaded
07:53dmilesso i was supposed to return a result that wasnt null.. but was bad and returned null.. causing the user class to get a npe
07:54dmilesi sorta wished that user class was calling 'thru' some safety wrapper of mine that calls the orignal code
07:55dmilesthen i could let lisp handle the NPE and not java
07:56dmilesso really what this is all about is having a higher resolution into call stacks
07:57dmileseven though i am sure .. at some point i'd been looking for even a higher resolution into the calls than per-method :P
07:59dmilesi guess the main idea.. is nothing in un-redefinable
07:59rhickeyI know bytecode injection/transformation is all the rage, but I'm concerned about the composability of these techniques
08:01dmilestoday i really wanted to been able to change java.lang.reflect.Array.* to be able to work with lisp sequences and lisp arrays
08:03dmilesi wanted a class that i didnt write that used Array.* methods.. to use my lisp array instead of its member
08:04rhickeyClojure goes pretty far in complying with Java interfaces for interop, but something like that is out-of-scope - maybe AspectJ?
08:06dmilesmight look into aspectJ for satisifying the class definition needs i think i have.. but .. yeah i havent proved to myself i need this yet ;P
08:08dmilescan clojure subclass something like java.util.Date ?
08:09dmileserm sorry of course it can.. and override any members overridable
08:09rhickeyas long as it's not final
08:14dmilesforgive the naive question, how hard would it be to make clojure switch in the middle of execution to a full CL mode levearging ABCL when that need arises?
08:15dmilesi almost thinking about trying to see if i can make ABCL switch to a clojure mode to leverage things that cojure might do more optimally
08:16rhickeydmiles: to the extent ABCL exposes itself as a Java library, it should be easy to interop.
08:17emacsenrhickey, is there a canonical documentation source?
08:18emacsenthe pages on the site seem somewhat spartan
08:18rhickey(doc fnname) is canonical, prose docs at http://clojure.org
08:18rhickeyThe site is a reference, and has shortcomings as a tutorial
08:18emacsenthe reference pages are fine for a lisper. They suck as something to point a java person at
08:19emacsenmaybe I should just point them to the PCL port
08:20rhickeyThe best start for non-lisper Java programmers would be these talks: http://blip.tv/file/982823 http://blip.tv/file/982957
08:21emacsenyeah the java ones?
08:21rhickeyyes
08:21emacsenI'm just about to send a friend those but want to say "Okay, so once you're convinced, this is what you should be reading"
08:23emacsenit's clear in that talk you were pressed for time (even though it's 3 hours) you only didn't even get much into even the concurency model
08:23emacsenwhich reminds me, I don't see anything on the reference site about this... does clojure have a conditionals system ala CL?
08:23emacsenerm conditions, not conditionals
08:23rhickeyemacsen: there a separate 3 hr concurrency talk, also very much directed at Java programmers
08:23emacsenah, sorry, didn't see that one yet
08:25rhickeyIt's a challenge to get all the docs needed to get a Java programmer up to speed - the first focus was on documenting what Clojure does
08:25rhickeybut then there are fundamental Lisp and FP concepts
08:25karmazillarhickey: that's the one where you wave jcip at the audience, more or less implying they can't call themselves professional if they haven't read it?
08:25emacsensure. I guess the book will solve some of that too
08:25emacsenas will the book ports
08:25emacsenoh, and here's one that I know is covered somewhere
08:25emacsenwhat's the term for a clojure user
08:25emacsenclojist?
08:26rhickeykarmazilla: I don't think I questioned anyone's professionalism :)
08:26emacsenAs in "The Little _____"
08:26rhickeyClojurian seems to be catching on
08:26karmazillarhickey: maybe I remember it like that :)
08:26emacsenThe Little Clojurian...
08:29dmileslistening/watching theblip.tv intros i am coming from a jvm lisp.. so this is great
08:29AWizzArdindeed, sounds like one of the best ideas I've heard in the past few years
08:30dmilesand not vapourware
08:32AWizzArdIf you want to get famous put work into Clojure ;-)
08:34dmilesi am hoping to see if we can compile the CYC sublisp (which is a .lisp 2 .java) into maybe a (.lisp 2 .clj)
08:36dmilessometimes the .java step tricks us into doing some suboptimal that maybe a .clj lets us leave soemthing that might been bad the why we do the .java .. will let us make the .clj to .class be smarter than us
08:36dmiles bad the why we do the .java/ bad the way we do the .java
08:38dmilesbut some questions still up in the air.. how hard will it be to make a .lisp->.clj
08:38dmilestranslator
08:39dmilesand will clojure runtime performance exceed Cyc's javalisp
08:39H4nsdmiles: i don't think it is feasible to automatically convert from lisps with mutable data structures to clojure.
08:39rhickeyIt's easy once you have an imperative->functional translator
08:39rhickey;)
08:40H4nsrhickey: i'm not used to be the pessimist! :)
08:40AWizzArdThe question that longtime lispers should ask is *why* they want to translate CL into CLJ.
08:40AWizzArdMaybe it's the few libs that Java offers...
08:41dmileswe have a sublisp2c and sublisp2java ... the 2java is faster than the 2c.. i didnt write the translators.. bu ti can hack our translators to producing other languages.. like c#.. but maybe even .clj
08:41rhickeyMore broadly, and back to emacsen's documentation qs, some sort of 'how do I transform this imperative xxx' guide would be quite useful
08:46arnfredis there any function in clojure returning true if a char is in a string or if an atom is in a list? like haskells 'elem'?
08:48wlrrhickey: that guide would be good in tandem with "how to think/design/program in terms of rhickey's State and Identity essay"
08:50jdzwhat's the way to find out wheather a value is an array?
08:52rhickeywlr: I think the most success comes from understanding the problems Clojure is trying to address. Anyone who's built large OO systems with mutable objects knows the problem, add threads, and knows the pain
08:52jdzoh, it's vector?
08:54wlrrhickey: sure. but i thought the general topic was "help for the rest of us..."
08:55karmazillajdz: how about (defn in? [x xs] (reduce #(or %1 (= %2 x)) false xs))
08:55rhickeywlr: I think this describes the complexity problem well: http://web.mac.com/ben_moseley/frp/paper-v1_01.pdf
08:56jdzkarmazilla: not "in" array, but "an" array :)
08:56rhickeywlr: not specific to the state and identity concept
08:56karmazillaoh
08:56karmazillasilly me
08:56jdzbut my bad on the terminology. in clojure they are called vectors.
08:57rhickey(some #{\a \c} "abacab")
08:57dmilesso a vector is the impl of a clojure array?
08:57arnfrednevermind, I made one myself: (defn elem [x list] (reduce (fn [z w] (or z w)) (map (fn [y] (= y x)) list)))
08:57rhickeyarnfred: see some above
08:58rhickey(some #{4} [1 2 3 4 5 6])
08:58dmilesso a vector is the impl of a clojure array? a prexisting java array like char[] returned from a 3rd party lib to closure is called a what?
08:58arnfredoh, right, that's a lot neater
08:58arnfredthanks
08:58dmilesoops didnt mean to repeat my question
08:59rhickeydmiles: vector is Clojure's indexed sequential thing, we reserve the term array for Java arrays
09:00AWizzArdI expect from Clojures vectors a +/- constant access time for random elements
09:01arnfredrhickey, what does the "#{4}" mean in "(some #{4} [1 2 3 4 5 6])"?
09:01rhickeyarnfred: It's a set literal - sets are functions of their elements - (#{1 2 3 4} 3) -> 3
09:02karmazillacallable collections is still a rather new concept to me
09:02parth_m(instance? (class [1]) [1 2 3]) => true, while (instance? (class []) [1 2 3]) => false.
09:02arnfredthat's way cool!
09:02parth_mrhickey: Is this expected?
09:02AWizzArdarnfred: http://clojure.org/data_structures
09:03parth_mI see one is PersistentVector while the other is LazyPersistentVector
09:03rhickeyso the (some set ...) technique works for every thing except nil and false, for which you have nil? and false? predicates
09:04rhickeyparth_m: you can't depend on any specific concrete classes, use the interfaces
09:05rhickeyhttp://clojure.googlegroups.com/web/chart.png
09:05parth_mok. I was thinking of jdz's question on how to check if something is a vector.
09:05parth_mWhat would be a good way.
09:05jdzparth_m: i already found my answer :) it's the function vector?
09:05rhickey(vector? x)
09:06parth_mAh ... :) Thanks.
09:06rhickeythe chart above is nice, shows the interfaces and the predicate if any
09:07parth_mNice.
09:07rhickeyIBlahs are safe to use with instance?, as well as Associative, Reversible, Sorted, Sequential - all of which have predicates
09:08parth_mThanks for the clarificaiton. I understand this much better now.
09:08karmazillanot everything is an IObj I see. so what is an IObj?
09:08arnfredis there a function to append one list to another? like ++ from haskell?
09:09rhickeykarmazilla: IObjs have metadata
09:09karmazillaah
09:09rhickeyarnfred: concat and lazy-cat
09:10arnfredthanks a lot
09:15AWizzArdarnfred: the documentation is also helpful: http://clojure.org/sequences
09:17arnfredAWizzArd, I know, I've been reading through it repeatedly all day :)
09:18AWizzArdexcellent
09:36blackdogChouser: how did you implement your repl in Clojurescript without the clojure compiler, or are you running that in an applet?
09:37blackdogi didn't investigate further than the svn log :P
09:45Chouserblackdog: it uses ajax-like techniques to have a jvm somewhere do the compiling.
09:46emacsenDoes anyone have a recommendation for a web framework for use with Clojure. I have a very simple web site idea. I could do it in, I dunno, a day or two in Django, but thinking this may be a good time to learn.
09:46blackdogChouser: ok
09:46Chouseremacsen: you might want to look at Compojure -- haven't really used it myself yet, but I know others are.
09:47Chouserblackdog: you can try it if you want. Be gentle: http://chouser.n01se.net/clojurescript/
09:48blackdogemacsen: i have a nice servlet utility for jetty, where you can do (defn x[] (isServlet "text/json" .... and print to the output
09:48blackdogthe emphasis is on simple
09:48blackdognot a framework
09:49emacsenblackdog, I'm thinking I may stick with what I know because the site is /so simple/ - or I think it is :)
09:56lisppaste8blackdog pasted "a jetty servlet " at http://paste.lisp.org/display/68682
10:02H4nsblackdog: i don't understand the use of make-array and aset in createHandler. wouldnt a [resourceHandler servletHandler] in the call to .setHandlers do?
10:02blackdogpossibly :) it works though, i didn't investigate all the possibilities
10:03blackdogthere could be better ways,
10:03H4nsblackdog: ok - so take it as a suggestion. looks less imperative that way :)
10:04blackdogyea, i'm new to all the functional lispish goodness so suggestions welcome
10:06H4nsblackdog: don't place closing parens on lines by themselves, and use an editor that does the indentation correctly
10:06H4nsblackdog: (correctly and, most importantly, automatically)
10:07blackdogoh, well that was me, i was fighting the emacs all the way :) when i was moving over from js java i felt more comfortable with the indentation, but I'm beginning to write more regular stuff now
10:09blackdogactually that array stuff was commentet out, i did find a better way
10:11H4nsblackdog: C-M-q on the opening paren reindents an s-expression. I use that, and C-M-k to kill s-expresssions all the time when refactoring code.
10:11H4nsblackdog: then there is paredit, but i've not gotten used to that.
10:12blackdogok, thanks!
10:12lisppaste8blackdog pasted "servlet usage" at http://paste.lisp.org/display/68684
10:13blackdogif you'er interested
10:13H4nslooks nice! :)
10:14blackdogto me it's a lot easier than using the appservers, i can just upload a dir and run, and jetty is awsome
10:32blackdoghow does one make a pin on Graham Fawcett's google map, I seem to be missing the obviousl
10:33H4nspress "edit" then choose the placemark icon on top of the map
10:33blackdogha
10:37blackdogok i'm not completely daft, edit wasn't visible in epiphany browser, but ok in firefox
10:39karmazillais there a website for compojure more official than the github repo page?
11:37Lau_of_DKGood afternoon gents
11:37Chouserhi
11:38emacsennot quite yet afternoon here
11:41asbjxrnIt's about time for bed here.
11:42tWipit's about time for some friday night activities here
11:43Lau_of_DKhehe
11:43Lau_of_DKOkay guys - What I meant was, good to see you all again
11:44scottjLau_of_DK: you were talking earlier about enterprise apps. What type of apps does your copany specialize in?
11:45Lau_of_DKscottj, I got some good input in the discussion earlier, but someone regretting asking the question in a channel that has public logs. So I think I'll park the subject if thats okay with you
11:46Lau_of_DK(someone = somewhat regrettet)
11:47scottjunderstood
11:47Lau_of_DK:)
11:53Lau_of_DKIs there any difference between a regular 'set', and then a persistanthashset, in the way the respond to conj and contains?
11:53karmazillayour from denmark?
11:53Chouser(class (set [])) ==> #=clojure.lang.PersistentHashSet
11:54Lau_of_DKThanks
11:54Lau_of_DKSo the shorthand #{} will work fine
11:55nicknullhow do i try-catch?
11:56Chouserhttp://clojure.org/special_forms#try
11:57Chouserhm, that doesn't actually work. Anyway, search that page for "catch"
11:58drewrnicknull:
11:58drewrhttp://clojure.org/special_forms#toc12
12:02ChouserI'm surprised merge doesn't act like set/union
12:03lisppaste8q pasted "a" at http://paste.lisp.org/display/68692
12:04nicknullhttp://paste.lisp.org/display/68692
12:05nicknull^^ there it came, im using tyr-catch there but it isnt working, what is the correct use? an example in the documentation would help
12:05Chouser(try (/ 5 0) (catch ArithmeticException e 0.5))
12:05drewrnicknull: Let me guess. You're getting a ClassCastException because 0.5 isn't a fn?
12:05drewrAh, and the binding form for the exception object...
12:05Chouseralso was missing the local to bind to the exception (in my example "e")
12:13nicknullit works now thanks
12:13nicknullwhat is e?
12:13drewrArbitrary. Call it whatever you want.
12:13nicknullarithmeticexception e
12:13nicknullok
12:14drewrIt's a symbol that the exception object gets bound to. You can inspect it, print stacktrace, etc.
12:15drewrIn Python, that would be: except FooError, e: ...
12:15drewrSame concept.
12:15nicknullah i see
14:29Chousercould re-find and friends call str on their second argument, since strings are the only thing that regexes work on?
14:31albinoIs str ascii or how does that fit with unecode?
14:31drewrWhy would they want a String when they need a Pattern?
14:32Chouserfor example, this currently throws an exception: (re-find #"foo" 'foo)
14:33drewrOh, sorry the second *argument*.
14:33ChouserI'm just wondering if it'd be reasonable for it to behave like (re-find #"foo" (str 'foo)) automatically.
14:33drewrRight, that seems reasonable.
14:33danlarkinChouser: I think it would be unreasonable
14:33drewrdanlarkin: I what scenario would the magic there be confusing?
14:34Chouseralbino: str returns a Java string, which is unicode.
14:35danlarkinwell regexes work on strings, so you pass it a string or you get an exception... which is good. and if you considered this case you can either call (str 'foo) yourself or catch the exception and deal with it
14:36rhickey_Chouser: I think there are many functions taking a logical 'name' or designator, for which taking either strings or symbols would be ok, I don't know that this falls into that category, but arbitrary (str x) seems like a bit much
14:38Chouserok
15:21ozzileeMacros hurt my brain. I'm trying to write a macro combinations such that (combinations [1 2 3] [4 5 6]) expands to (for [a [1 2 3] b [4 5 6]] [a b]). Help?
15:22ozzileecombinations may take any number of vectors
15:33drewrYou sure you need a macro for that?
15:41ozzileedrewr: If you can show me a way without a macro I'm all ears.
15:41Chouserto use "for", I think you need a macro. There might be a better way than using "for", though.
15:41lisppaste8Chouser pasted "combination macro etc." at http://paste.lisp.org/display/68701
15:43ozzileeChouser: Ah, hmm. Might take me a bit to absorb that, thanks.
15:45Chouserbuild two vectors and stick them in a "for", right?
15:45ozzilee"(vec (apply concat (partition 1 2" just says "take every other one", correct?
15:45ozzilee"and make a vector out of them"
15:45Chouserright!
15:46Chouserhm, shoulda used take-nth
15:49ozzileeYeah. Also interleave would work for v, I think.
15:49ozzileeBut I get the meaning, no matter.
15:50ozzileeI tried writing the v and o inline with the for and got myself horribly confused, this is much cleaner, thanks.
15:50Chouserah, sure.
15:50Chouserbut since the inputs to combinations are all regular eval'ed values, it doesn't need to be a macro.
15:51Chouserif it were a regular function than things like "apply" can work on it, which could be useful.
15:53ozzileeChouser: Yeah, that's true, I just wasn't sure of the right algorithm, and for was so nice and handy...
15:53Chouseryep
15:55ozzileePerhaps I'll look up how for works later. Thanks for the help.
15:57lisppaste8Chouser annotated #68701 with "combination fn" at http://paste.lisp.org/display/68701#1
15:59Chouseryeah, that one's a stretch for me.
16:02lisppaste8Chouser annotated #68701 with "better combinations macro" at http://paste.lisp.org/display/68701#2
17:04PupenoHello.
17:04Chouserhi!
17:04PupenoSo, to distribute a Clojure program you just distribute the source files in a jar and a little java class/program that gets it started?
17:05Chouserif you put something in user.clj in the classpath, clojure.jar will start it for you
17:06PupenoOk... but still putting the source code in plain view? Right?
17:06Chouseryessir
17:06AWizzArdcurrently yes
17:07AWizzArdbut if you don't think only shortterm, then I think we can assume this will go away
17:09lisppaste8Chouser annotated #68701 with "combinations, lazy fn" at http://paste.lisp.org/display/68701#3
17:18Chouseroh, nevermind -- annotation 1 is lazy too.
18:00mmcgranaHi all, I have some question about loading other Java and clojure code from a clojure script.
18:01mmcgranaFirst, what is the best way to load up eg clojure-contrib for use in a one-off script?
18:02wwmorgan_mmcgrana: (doc ns)
18:03blackdogmmcgrana: e.g. (ns user (:require
18:03blackdog [clojure.contrib.duck-streams :as ds]))
18:04blackdogand add the root of contrib to your classpath
18:04mmcgranartm, right. but for example if I just do (ns my-ns (:require (clojure.contrib str-utils))) it clearly won't find that resource. so presumably it needs to go in the classpath, so then how does one get it in a jar etc?
18:04mmcgranasorry if this sounds noobish...
18:05blackdogyou can jar up contrib then add a -cp contrib.jar
18:05mmcgranaok so ant from clojure-contrib/ builds a jar, then put that in classpath
18:05blackdogyes
18:06blackdoganother good one is -Djava.ext.dirs=$LIBDIR where you can have a dir full of jars
18:06blackdogand add them all at once
18:07AWizzArdWhat does Paul Grahams accumulator look like in Clojure? (defun foo (n) (lambda (i) (incf n i)))
18:07mmcgranaah nice thanks
18:09AWizzArdnot that I need it, I just would like to know the trick how to go around the immutable state
18:10Chouser(defn foo [n] (fn [i] (+ n i))) ?
18:10mmcgranahttp://www.paulgraham.com/accgen.html
18:10AWizzArdthis is not an accumulator Chouser
18:10AWizzArd(def bar (foo 3))
18:10mmcgranai think the praham one has state, so the result changes with successive calls
18:10AWizzArd(bar 5) ==> 8.. (bar 1) ==> 4
18:11jerrykIs anybody out there interested in, or already working on, an interval artithmetic package for Clojure?
18:11AWizzArdit should be 9
18:11Chousersorry, gotta run
18:11AWizzArdmmcgrana: right
18:11wwmorgan_AWizzArd: you might use refs to get that behavior
18:12AWizzArdthis is what I supposed, but as I discovered Clojure only yesterday I don't know how that would look like
18:15blackdogAWizzArd: this guide is good, and it had somewhere a good example of an accumaltor but I can't find it now http://blog.thinkrelevance.com/2008/9/16/pcl-clojure
18:15blackdoghttp://blog.thinkrelevance.com/2008/9/16/pcl-clojure-chapter-6 there it is
18:15blackdogcounter example
18:15blackdogif that's what I think you're looking for
18:16wwmorgan_AWizzard: Here's one way to do it http://paste.lisp.org/display/68712
18:19AWizzArdthanks you two
18:21mmcgranaSo I have the clojure-contrib.jar all set and in /jars within the project root. But I also have a "clj" script in usr/local/bin that calls java with clojure and jline in the classpath. Does anyone have any practical advice on how to invoke clojure with extra stuff in the classpath (like jars/clojure-contrib.jar) without having to type java -cp .... etc directly, ie using something like a "clj" script but that is aware of
18:23mmcgranahas anyone tried something like this: http://github.com/dudleyf/clojure-bin/tree/master/clojure ?
18:24wwmorgan_mmcgrana: add-classpath may do what you want
18:26mmcgranahmm interesting. Do people generally load additional resources from within a single root resource (like one would in Ruby with "require") or all at the beginning (like one might with -cp in a java invokation) ?
18:27mmcgranaanother related one: if I have several clojure files to load from an inital boot file, would clojure/load-file be right for that or is something else preferred?
18:31wwmorgan_I use enclojure which figures out all the classpath stuff automagically. From the command line I invoke java with -cp to my source root and the ns macro in each file does everything else
18:39mmcgranaok thanks for the thoughts blackdog and wwmorgan_, I going to try re-reading clojure/ns and friends, then see if I can put together an example project that does all these various things
18:40dmilesso clojure doesnt have a rplacd ?
18:41mmcgrananot really, its in a very functional style
18:41mmcgranamutating state should be managed by refs, agents, or vars
18:42dmilesah and setting it up via transactions?
18:43mmcgranayeah for refs. clojure's mvcc is very cool, you should investigate
18:43dmilesif someone really felt they needed lisp conses mutable.. they could write a series of macros that implment mutable conses?
18:44mmcgranaactually i don't think that clojure provides a means of mutating non ref,var,agent state from within clojure code, you would have to drop into java i think. not sure though
18:44Chouserdmiles: yeah, but don't do that. :-)
18:46ChouserClojure interacts with mutable Java objects all the time, so you could write your own mutable cons cell in Java, built on arrays or something, or in Clojure built on refs.
18:46dmilesoh right
18:47ChouserThe latter might be slightly preferrable as it would be thread safe (refs can only be mutated inside transaction), but either way you'd be doing a lot of work to fight the language.
18:48dmilesi am trying to see if it will be worth translation of pre-existing lisp code to clojure code
18:48Chousermechanical translation?
18:48dmilesthe lisp runtime is written in java.. it is pretty fast.. but wondering if it translates to cljure if it might be faster
18:49dmilesmechanical prefered there is over 6 million lines of lisp code
18:50walters_wow
18:50Chouserwould you expect to maintain it in clojure then, or maintain it in lisp and re-translate every time you update?
18:50dmilesits the codebase to CYC
18:50dmilesthinking it should be option for people to maintain their code in clojure
18:51Chousercan the existing lisp code be called from Java?
18:51dmilesas long as we can also debug clojure from the lispworks runtime at some points since they cant always have a jvm
18:52dmilesyes, the RTL has a java port.. so it can be leveraged from 3rd party libs
18:52dmilesso an application written in java can use hte javalisp features now.. but thinking if it possible to ever swap out javalisp for cojure runtime
18:53Chouserif you want to keep the imperative, mutable model, I would guess a better use of your time would be to improve the lisp runtime with ideas from Clojure.
18:53dmileslisp code is currently interpetd unless the user use the lisp2java translator and then compiles
18:53ChouserThe Clojure compiler isn't terribly large.
18:54ChouserI think it would be pretty hard to translate from existing lisp code to idomatic Clojure.
18:54dmileshow about java2clojure?
18:55meredyddDitto.
18:55dmilesi guess thats just syntax
18:55meredyddIt would be fairly hard to replicate Java's mutable local variables
18:56meredyddYou'd need to wrap all locals in a ref or something unpleasant like that, at a guess.
18:56dmilesi guess even if you emulated those, i wonder if you ever gain.. but hrrm yeah i guess it should be sposible
18:56meredyddAlthough Clojure can call into and out of Java very nicely, the language itself is structured quite differently.
18:57dmilesdoes clojure use a try/finally to implment (let ... ... ) ?
18:57meredyddWhy do you need try/finally for (let)?
18:58dmilesto allow symbol shadowing
18:58meredyddThere's no need for that - you can figure out which binding a symbol refers to statically, at compile time.
18:58dmileserm well a view of letted values
18:58meredyddIt's all lexically scoped.
18:59meredydd(let [a :foo] (prn a) (let [a :bar] (prn a))) is completely unambiguous.
18:59dmiles (let [a :foo] (prn a) (let [a :bar] (prn a)) (prn a) ) ?
19:00dmiles:foo :bar :foo ?
19:00meredyddyep
19:00meredyddGet away from the idea that 'a is a local variable that "let" is modifying - it's not.
19:00dmilesso the middle a is not the same a.. its a copy?
19:01meredydd'a, the symbol, is bound to a particular variable. The binding we call 'a inside that inner (let) has nothing to do with the binding we call 'a *outside* that (let)
19:01meredyddIt's a completely new creature.
19:01dmilesoh .. it wouldnt even need to be 'copy' its a new thing?
19:01dmilesright
19:01meredyddyep.
19:02dmiles (let [a :foo] (prn a) (let [a a] (prn a)) (prn a) ) ?
19:02meredyddit's like you said (let [a1 :foo] (prn a) (let [a2 :bar] (prn b)))
19:03meredyddThat corresponds to: (let [a1 :foo] (prn a1) (let [a2 a1] (prn a2)))
19:03dmilesthe global mutables like *standard-output*.. is there lexical bindingings of them?
19:04meredyddThose are different. (let)-ed variables are fundamentally different to (def)-ed variables.
19:04meredyddYou can do two things:
19:04meredydd1. (def a :foo) (let [a :bar] (prn a))
19:05meredyddwhich is equivalent to (def a :foo) (let [a1 :bar] (prn a1))
19:05meredydd2. (def a :foo) (binding [a :bar] (prn a))
19:06AWizzArdbtw, I just read you were talking about compilers 10 minutes ago.. did Rich mention that he wants to implement Clojure fully in Clojure one day?
19:06dmilesthe operator 'binding' is new to me
19:07meredyddThat's using dynamic rather than lexical binding - any time between the *time* execution enters that (binding) block and the *time* that execution exits that block, anyone reading that global variable 'a sees :foo.
19:07mmcgranaactually I think he mentioned somewhere that he wasn't particularly interested
19:07AWizzArdI mean, it was bootstrapped in Assemb... Java, so now it's there and in principle could get rid of all Java, no?
19:07meredydd(Actually, it's stricter than that - it's any code running *in the same thread* as the (binding) block)
19:07AWizzArdic
19:08meredyddAWizzArd: The runtime is still in Java. Theoretically you could rewrite the runtime using a couple of primitives in raw Java ASM, then build the rest in Clojure.
19:08mmcgranaAWizzArd: i think it was in one of the clojure videos on http://clojure.blip.tv/ where he mentioned this
19:09dmilesso (binding [*standard-output* myfile] (prn :foo)) might write to my file assuming *standard-output* was used by prn?
19:09meredyddAside, on the "programmatic translation of Java to Clojure" idea - you could probably more-or-less emulate local variables using (binding)s and (set!). Definitely counts under "creative abuse of the language", though...
19:10meredydddmiles: Correct.
19:10AWizzArdmmcgrana: I've seen yesterday one vid there where he mentioned that tons of stuff is done in CLJ itself. What I mean is an implementation which is written 100% in CLJ, without even a single line of Java.
19:10AWizzArdAlthough the time is not ready for this yet.. the language is still getting more and more mature and there are several things to do first.
19:11mmcgranayeah i think he explains in another one why he wasn't particularly excited about it: something like the compiler works fine as is, the data structures need a lot of java features that would otherwise need to be added to clojure, and as you said most of the user-facing aspects of the language are already defined in boot.clj and friends
19:11AWizzArdFor example currently you need to distribute your source code with your programs, and your programs get every time compiled before execution. The concept of a .fasl is still missing.
19:12mmcgranathat reminds me, there's been talk of AOT compilation - is this recompiling like .pyc files or something else?
19:12dmilesmeredydd: yeah .. sounds like a good excersize gfor me to try :)
19:13meredydddmiles: Honestly, I'd recommend against it.
19:13meredyddNot because it wouldn't be fun, but because it would be really difficult to do right before you have a good solid grasp of how to use Clojure "right".
19:14meredydd(Creative abuse tends to require a feel for what you're abusing)
19:17dmilesmore and more often i question exactly what programs i need to write for myself
19:19dmilesi have a few i need to write and a few i have written that integratiomn with java libs are needed.. so sometimes thinking of porting
19:20meredyddmmcgrana: The compiler generates Java bytecode, one top-level S-expression at a time, then executes.
19:21mmcgranathats what it does now, right?
19:21meredyddmmcgrana: There's no theoretical reason why AOT compilation isn't possible, but ISTR there are some unpleasant corners rhickey has expressed himself not-particularly-enthusiastic about working around for now.
19:21dmilesand there usually a pretty clear S-epression->.class
19:22mmcgranaoic. yeah i was just curious, i don't have any problems with the current compiler.
19:22meredyddRight now, if you generate a .class with (gen-and-save-class), it's just a shim that (load-resource)s an appropriately-named Clojure source file.
19:22dmilesi wonder how much AOT can be done on the .clj soure to .clj source
19:22meredydddmiles: Explain?
19:23dmilesmeredydd, i guess method hints could get annotated in?
19:23dmilesbut that'd happen in the compilling anyways
19:24meredydddmiles: Why bother? It's not like that would pick up anything the type-inference stuff wouldn't figure out during actual compilation.
19:24ChouserI think AOT compilation is coming Really Soon Now.
19:25ChouserBut that's not the same as rewriting the remaining Java pieces in Clojure. I don't ever really expect that.
19:25meredyddChouser: That would be Really Sweet(tm).
19:26dmilesmeredydd: yeah i am wondering what AOT means really.. is it a database or transformations to do on S-Expressions?
19:26dmilesor/for
19:26Chouserhe had a version checked in a couple days ago that compiled all forms to .class files, then read them back off the disk to execute.
19:26meredyddIs there a realistic prospect of then packaging a limited version of the runtime that doesn't include any custom classloaders?
19:26Chousermeredydd: yes
19:26meredyddExcellent. Android may yet become easier to live with :D
19:26Chouserpossibly no custom classloader, no Compiler, and no ASM lib.
19:26Chousermeredydd: exactly.
19:27meredydddmiles: Compilation right the way down to .class files you can call from any other Java runtime.
19:27meredyddChouser: Of course, GC's still going to bite, hard. (The GC lag on that thing is not-fun). But if he can get the RTL footprint down far enough, I'd be a very happy chappy.
19:28ChouserClojureScript works roughly the same way, except it produces .js instead of .class files.
19:28Chousermeredydd: GC on Android is poor?
19:29meredyddChouser: The SDK docs all warn loudly about it. I may be mistaken, but the implication I got was that they might even have a naive mark-and-sweep like some of the early J2ME runtimes
19:29Chouseroh. ow.
19:30meredydd(early SDK documents, unreliable memory, blah blah. But yes - "Ouch" is the impression I distinctly remember.)
19:30ChouserRich has stated before that Clojure depends on well-performing ephemeral GC.
19:30meredydd(They were warning you to avoid using Iterators at all, ever, for example.)
19:30dmilesmeredydd: i see
19:30meredyddWell, duh. Persistent data structures don't work without one :)
19:30Chouserright
19:31dmilesmeredydd: yeah this AOT/Whole program optimization.. may as well be farmed out to a 4th party lib like Soot
19:31meredydddmiles: Why? rhickey's already written a full compiler capable of generating .class files.
19:33dmilesmeredydd: oh in refering to: <meredydd> mmcgrana: There's no theoretical reason why AOT compilation isn't possible, but ISTR there are some unpleasant corners rhickey has expressed himself not-particularly-enthusiastic about working around for now.
19:34meredydddmiles: Oh, right. Well, for starters, that was out of date (from what Chouser's saying). But I think the corners were to do with (def)s and similar, and other things that are far easier to deal with within the compiler than in an external library.
19:35meredyddChouser: I'm googling now - "dalvik garbage collection" doesn't bring up much. It's possible they do use a generational collector, but it's definitely stop-the-world, which isn't fun if you're trying to do a fluid user interface.
19:36dmilesmeredydd: ah i see
19:37AWizzArdIn principle I think we don't need to care much about AOT and WPO. As long Clojure compiles to bytecode which is then seen by the jvm we can just wait for them to implement a AI system which will do the right stuff.
19:37dmiles(possible (re)def(s) can happen arbitrarily and such)
19:38AWizzArdwhat I find more interesting is: what will happen when tail call optimization will come into the jvm?
19:40AWizzArdat the moment we need to do TCO manually, right?
19:41AWizzArdthat is, providing some intermediate parameters to recursive functions
19:46mmcgranai'm sure what you mean by that last but, but yeah you have to use "recur"
19:50AWizzArdmmcgrana: yes, but now let's say Sun introduces tco into the jvm. Recur is no longer needed
19:50AWizzArdWill it stay for backwards-compatibility? Or go away? If the jvm supported tco today then recur would never have found its way into Clojure in the first place, would it?
19:51walters_AWizzArd: remember that OpenJDK exists now *you* (or anyone) can add TCO into the JVM =)
19:52AWizzArdI will better concentrate on adding other things to Clojure. But what do you think will happen with recur? What should happen?
19:58pjb3If I do (defn foo [] "foo"), why can't I call that with ((symbol "foo"))?
19:59AWizzArdbecause your function foo takes no arguments
19:59AWizzArdnevermind
20:00pjb3I'm not clear as to how (foo) and ((symbol "foo")) are different
20:02AWizzArdah, I see what you mean
20:02AWizzArdyes, good question
20:02mmcgrana(class foo) vs (class (symbol "foo"))
20:02mmcgrana((resolve (symbol "foo")))
20:03pjb3mmcgrana: ok, right
20:03pjb3Is there an easier way to call a function if I have the name of a function in a string?
20:04mmcgranahmm not sure
20:09AWizzArdhas anyone of you tested already writing programs for your mobile phone in Clojure?
20:13dmilesis there some syntax char to make (class (symbol "foo")) act like (class foo) .. like (class ~(symbol "foo")) .. but doesnt supose it's in backquote?
20:14lisppaste8pjb3 pasted "calling a function from a string" at http://paste.lisp.org/display/68718
20:18dmilesfrom watching the talk on CJ for java progrtammers.. since you can add metadata to any object like [1 2 3] .. i almost wonder why one shouldnt be able to (def 666 ..as a function..) and call 666
20:19dmilesi mean any value could be def fnable
20:19AWizzArd(def 13 4)
20:19AWizzArd(+ 13 2) ==> ?
20:20dmilesjust that only doing that to symbols seems for sanity sakes only
20:20AWizzArdyou don't want that :-)
20:21dmilesAWizzArd, good example
20:21AWizzArdalso http://clojure.org/special_forms#toc1 explicitly says that the first argument to def has to be a symbol (and not an object)
20:22dmilesbut maybe i want (def say-person :say-joe-sixpackfn) (say-person) (def say-person :say-joe-plimber) (say-pesron)
20:23dmilesbut right i can always use ((say-person))
20:24dmilesmainly looking for auto-dereferencing of symbols
20:24dmilesso you keep drefing an object until it has a function value
20:26dmilesdunno .. not important.. if it was the way i said.. then it wouldnt vbe the same programming language
20:27dmilesbut (+ 13 2) => 15 but (+ (13) 2) => 5
20:27dmileserm 6
20:29dmilesor (+ @13 2) => 6
20:30dmilesCool, watching Clojure for Lisp Programmers
20:33AWizzArdI just don't see a place where it would be useful to be able to say (13) ==> 4
20:34AWizzArdand why should one only be able to bind a function object to 13 and not other objects, that is, why only: (def 13 #(4)) and not (def 13 4)?
20:35dmilesi was thinking it be ok to bind functions to anything
20:36dmilesquestion is (class "foo") ok?
20:36dmiles"foo" being a class differnt from 'foo though
20:37AWizzArdobviouslj
20:37AWizzArd"foo" is a string object
20:37dmiles(class 13) ?
20:38AWizzArdIt's an int
20:38ChouserI don't know which result is most likely, but I for one would vote to keep recur, even if the JVM had TCO.
20:39AWizzArdChouser: fair enough.. only that no one would use it anymore
20:39ChouserI would use it. I think it makes code clearer.
20:39ChouserWhen you use recur explicitly, the compiler checks to make sure it's in the tail position -- you can have condfidence you're not threatening the stack.
20:39abrooksChouser: re: recur -- I concur.
20:39AWizzArdI think having the name of the function there and no loop is more clear
20:40ChouserI really don't know how Rich would come down on this, but I think use of recur (when possible) should remain the preferred idiom.
20:40AWizzArdno loop+recur looks more like pseudo code and math, while now it looks like a helping construction to protect from stack overflows
20:41Chouseryou don't need loop -- you can use recur with a fn and no loop.
20:45AWizzArdokay, this makes it better then imo
20:47mmcgranaso I have a public java class com.mmcgrana.HelloWorld with a public static method sayHello. I can compile and jar fine, then load with (add-classpath "file:jars/hello.jar"), use (:import com.mmcgrana HelloWorld) in the ns macro, but then when I try (. HelloWorld sayHello) it gives me: ava.lang.IllegalAccessError: tried to access class com.mmcgrana.HelloWorld from class user.eval__2550 (NO_SOURCE_FILE:0)
20:48mmcgrana*(:import (com.mmcgrana HelloWorld))
20:48mmcgranashouldn't I be able to access the public method?
20:50pjb3mmcgrana: You call static methods with (HelloWorld/sayHello)
20:50mmcgranaeg a public static method in clojure: (. clojure.lang.RT (var "clojure" "map"))
20:50pjb3or if it's not imported, (com.mmcgrana.HelloWorld/sayHello)
20:51mmcgrana(. HelloWorld sayHello) (HelloWorld/sayHello) and (com.mmcgrana.HelloWorld/sayHello) all give the same error. I must be doing something really basic wrong.
20:52mmcgranaok figured it out needed *public* class HelloWorld. Sorry guys.
20:52mmcgrana<= java noob
20:53rottcoddshould I be using (seq ...) where I would use (values ...) in Common Lisp?
20:54pjb3I guess the (.staticMethod org.whatever.Class arg1 arg2) syntax does till work, I thought that was going away
20:55mmcgranaso (org.whatever.Class/staticMethod arg1 arg2) is now preferred right?
20:55pjb3I think so
20:56pjb3Has something to so with the way classes work
20:56pjb3for example this doesn't work, but you would think that is would
20:56pjb3(let [m java.lang.Math] (.floor m 4.5))
20:58Chouserrottcodd: sorry, don't know CL well enough. You want just the values from a hash-map? or something else?
20:58AWizzArdmmcgrana: I have the same problem like you, don't know the Java lib well enough
20:58mmcgranapjb3 found this in the group: http://groups.google.com/group/clojure/browse_thread/thread/91c715364604a3a4/d825a71aa23d5953?lnk=gst&amp;q=static+method#d825a71aa23d5953
20:59mmcgranaseveral others here if you're curious: http://groups.google.com/group/clojure/search?group=clojure&amp;q=static+method&amp;qt_g=Search+this+group
21:00AWizzArdrottcodd: seq returns a fresh sequence... it does not make your function return multiple values
21:00AWizzArdso no, don't replace values with seq
21:01Chouseroh, is that related to multiple return binding?
21:01mmcgranaYeah, for me its no so much the Java lib as it is the Java environment, especially code loading. I've been spoiled by python and ruby where you just point it to the next file to load
21:02pjb3mmcgrana: Right, so the reason (let [m java.lang.Math] (.floor m 4.5)) doesn't work is because that is like saying Math.getClass().floor(4.5) in Java
21:02pjb3which doesn't work in Java because Java is stupid :)
21:02mmcgranaclasses aren't quite first-class, right?
21:03AWizzArdthey are I think
21:03pjb3mmcgrana: right, not like they are in Ruby, for example
21:04rottcoddChouser: yes, I want to return multiple values, what is the clojure idiom?
21:05AWizzArdI think Clojure has no multiple return values, so just return a set of things
21:05Chouserrottcodd: clojure uses java calling conventions, so you can only return one thing. But destructuring make returning a vector fairly pleasant.
21:05mmcgranarottcodd: probably returning a vector of values and then using destructuring in the reciever
21:05AWizzArdyes, returning a list, vector or just a set
21:05Chouser(defn a [] [20 30]) (let [[x y] (a)] ...)
21:05AWizzArdit is trivial on the caller side to unpack these things
21:06mmcgranabtw related questions: would you suggest using lists or vectors for this purpose?
21:06AWizzArdwhy not just a set?
21:06walters_pjb3: that'd require reflection in general
21:06mmcgranawell a set is unordered the semantics are different
21:06ChouserAWizzArd: how would you use a set? they're unordered
21:06AWizzArdokay, then I understood it not right, thx
21:07rottcoddwouldn't a seq be better, since it is lazy
21:07Chouseryou could return a hash-map or something, that can be powerful.
21:08Chouser(defn b [] {:ra 7 :rb 8 :rc 9}) (let [{:keys [ra rc] (b)] (prn ra rc))
21:09rottcoddthat's really nice
21:09Chouserrottcodd: sure, if computing the second value is expensive enough to bother skipping, and many callers will only take the first item, returning a lazy-seq might make sense.
21:11Chouserbah, missing a } up there.
21:22pjb3What is the difference between defn and defn- ?
21:22pjb3"same as defn, yielding non-public def"
21:23pjb3?
21:23mmcgranaas in "private"
21:23mmcgranai think that means not visible outside of the namespace
21:23pjb3ah
21:23Chouserit marks the def'ed var as private, so it isn't pulled in by "refer"
21:23mmcgranaits used e.g. for helper functions that are not exposed to library users
21:33AWizzArdCan one have multiple multimethods in Clojure? Example: I want to have a multimethod foo that takes a sequence and returns 0 if the sequence contains 3 elements and which returns 1 if the sequence contains 4 elements. Easy so far. But now I want another foo which returns 2 if the first element of the sequence is a 100.
21:34Chousersure
21:34AWizzArdWould that work? Or don't we want that because of the disambiguity, as [100 200 300 400] contains 4 elements (thus should return a 1) but also begins with 100, so it must return a 2
21:34AWizzArd(defmulti foo (fn [c] (count c)))
21:34AWizzArd(defmethod foo 3 [arg] 0)
21:34AWizzArd(defmethod foo 4 [arg] 1)
21:35AWizzArdbut how do I get the "is-first-arg=100-thingy" into the game?
21:35ChouserAWizzArd: http://groups.google.com/group/clojure/browse_thread/thread/7abeb31b2c34980/ee9179ca679b0a27
21:36Chouserfor multi-line pastes, please use http://paste.lisp.org/new/clojure
21:36AWizzArdChouser: yes, thx
21:37ChouserAWizzArd: you'd have to set up your dispatch function(s), and it'd end up being unambiguous.
21:40AWizzArdChouser: this sounds a bit like manual dispatching again
21:40AWizzArdfor example in that thread you posted I see Stuart giving an answer where he is doing kind of a manual dispatch with his if
21:41Chousersure, and Rich later recommends against that.
21:43Chouserthe more specific your dispatch requirements, the more manual it's going to feel, I would imagine.
21:44AWizzArdI am comparing the generality of this concept against pattern matching
21:52lisppaste8Chouser pasted "more nested multimethods" at http://paste.lisp.org/display/68722
21:56AWizzArdYes, good idea
21:56AWizzArdI will see if it makes sense to define pattern matching on top of that, with some kind of (defpattern foo ...)
21:56Chousernot quite as general as pattern matching of course, but not tons of overhead and no ambiguity.
21:58AWizzArdyes, it's okay, but I still don't see why *not* having pattern matching when already defining a new lisp
21:59Chousersome of Rich's comments on pattern matching: http://groups.google.com/group/clojure/msg/0d01874b383f7bdd
21:59AWizzArdCLs multimethods are a big step forward over single dispatch as in C#, Ruby, Java, Python, ...
22:00AWizzArdClojures multimethods seem even more general right now, I am not sure yet. But again, stopping at half the way to general expressibility
22:02scgilardido you have some generality in particular in mind that's missing?
22:08AWizzArdWell, that is tricky, as whatever I name can be solved in a turing complete language like Clojure.
22:08AWizzArdbut pattern matching would give an easy an clean solution to the situation I just mentioned
22:09AWizzArdChouser showed a nice way how to do it
22:09AWizzArdbut this also makes things a bit harder to follow... in the end it probably makes most sense to have both constructs side by side
22:11scgilardiit did seem nice. I may have missed part of the conversation, but did you/could you post how it would look with pattern matching in place? (I did look at Chouser's paste)
22:12AWizzArdthere are several different pattern matching implementations in different languages, and we can make it look like we want, well yes, let me come up with something
22:14scgilardiChouser: Thanks very much for the irc log. Would changing the update interval to something shorter (say 15 minutes) increase the load it makes on your system(s) to an uncomfortable level?
22:15Chouserscgilardi: hm, probably not. It's doing more work per run than it should.
22:16pjb3If I want to have a cond with a default case, is the way to do it by using an or?
22:16pjb3(defn foo [x] (or (cond (> x 0) "positive" (< x 0) "negative") "whatever"))
22:16lisppaste8AWizzArd pasted "Pattern matching" at http://paste.lisp.org/display/68724
22:16ChouserI have plans (though don't hold your breath) to provide an atom feed with hourly entries.
22:17Chouserpjb3: (cond (> x 0) "positive" (< x 0) "negative" :else "whatever")
22:17walters_pjb3: that'd require reflection in general
22:17walters_oops, mt
22:17pjb3Chouser: else, thanks
22:18walters_(typing alt-tab + up + return quickly can be hazardous)
22:18Chouserpjb3: nothing special about :else, it's just a non-false value used by convention.
22:18pjb3cond :else isn't in the docs, maybe that should get added
22:19pjb3ah, I get it
22:19pjb3so I should replace it with true or :whatever
22:19pjb3^could
22:20Chouseryep, you sure could. :else is a nice choice though. :-)
22:21scgilardithanks, AWizzArd. I'm looking at it. It seems that we have all the plumbing in place to do those tasks. defpattern would be more about a clear, compact representation. does that sound right?
22:21Chouserjust make sure you put it at the end.
22:25AWizzArdscgilardi: of course it can be implemented.. in probably 2-7 days. There are seveal pattern matchers available for Lisp. But having one specific one in Clojure would mean that everyone would use it. And defpattern is indeed a way to represent some problems very well. Although it is "static" in the sense of: not extensible as defmethod. But why not having both? And in principle one could always allow to add new clauses to a pattern.
22:25AWizzArdin fact, it could be a list/vector of patterns, and one could dynamically add/remove some
22:25ChouserAWizzArd: in the first example, how does it know "n" is to be bound and not to be evaluated?
22:26AWizzArdyeah, I forgot to put n into the argument list
22:28AWizzArdthis fibonacci thing would have to be compiled into something that uses recur
22:29AWizzArdI am still thinking about a way for adding currying to Clojure
22:30AWizzArdthe #(...) notation could be a great way to implement it
22:30Chouserdoesn't #() make currying largely unnecessary?
22:30Chouserthere's also (partial)
22:30AWizzArdhmm, is #(...) === (fn [] ...) ?
22:31Chouseralmost. #(...) == (fn [...] (...))
22:31Chouser#() takes as many args as are mentioned: #(+ %1 %2) take 2 args
22:32AWizzArdah okay, then I must think if this is what I meant
22:32AWizzArdbut I would really prefer #(+) more here
22:33AWizzArdif we ignore for a moment functions that take any number of arguments
22:33Chouseryou can even do #(apply + %&) for var-args
22:33AWizzArdlet's look for a moment at stuff that takes a specific number of arguments
22:34Chouserok
22:34AWizzArdfor example a function RGB that returns a RGB object
22:34AWizzArdthen I would like to make something that is very red in any case, but not decided how green/blue it is: #(rgb 255)
22:35AWizzArd(def reddish #(rgb 255))
22:35AWizzArd(def greenish #(rgb _ 255))
22:35Chouser#() does not, in itself, curry.
22:35pjb3Chouser: Thank you for not making / a character than has to be escaped in regexs
22:35Chouser(def reddish #(rgb 255 %1 %2)) (def greenish #(rgb %1 255 %2))
22:35pjb3You were right, that's paying off for me right now :)
22:36AWizzArdyes Chouser, this comes close
22:36Chouserpjb3: you're welcome!
22:36AWizzArdbut what I want is to use the underscore for anonymous args on that position
22:36ChouserAWizzArd: but that means you can't use the same arg twice, right?
22:36AWizzArdwe keep the %x thing to be able to do this
22:37AWizzArdbut in 90% of the cases we will not reuse an arg
22:37AWizzArdwe have: (filter #(< 5) ...) or things like that
22:37AWizzArdI don't want to give any %num or _ after the last specific arg has been given
22:37Chouser(filter #(< 5 %) ...)
22:38AWizzArdyes, it comes close and I could live with that
22:38AWizzArdalthough I find my approach nicer
22:38ChouserAWizzArd: yeah, I know that's what currying is. Personally I kinda like the explicitness of %, and it only costs me 2 keystrokes.
22:39Chouserplus hooks me directly into a mechanism that allows splitting args (like #(rgn %1 255 %2)), etc.
22:39AWizzArdyes, this is definitly better than CLs explicit (lambda (args) ...) thing
22:39AWizzArdwhat do you mean by splitting?
22:39Chouserbut you could certainly write a macro (curry rgb _ 255 _)
22:40AWizzArdsure, but I don't want to say curry
22:40Chouseroh, by splitting I just mean currying into positions other than the last arg.
22:40AWizzArd#(rgb _ _ 50) ; a bit blue
22:41AWizzArdand #(rgb 10) == #(rgb 10 _) == #(rgb 10 _ _) == #(rgb 10 %1) == #(rgb 10 %1 %2) == #(rgb 10 _ %2)
22:42AWizzArdalthough, I must admit, that my solution needs some extra care for functions that take any number of arguments
22:42AWizzArdwe don't know if #(+) is either: (apply + args) or (+) which would evaluate to 0
22:43Chouserthat's a little different from fully automatic currying seen in some languages -- I do like the explicit # you're proposing better.
22:43AWizzArdI want the #
22:43AWizzArdI don't want implicit currying
22:43Chouserwe agree on that.
22:44AWizzArdbut with the # it is damn close to implicit currying, but gives the eye an extra mark that tells the reader for what he needs to care
22:44AWizzArdso, the easiest extension would be to allow any number of underscores instead of %1 %2 and so on
22:44AWizzArd#(rgb 0 _ _)
22:44AWizzArdbecause it really does not matter which the first arg is, and which the seconde one is
22:45AWizzArdbut the %1 %2 stuff does not go away.. if we really want (def square #(* %1 %1)) we should be able to do it
22:46Chouserto make a case for this, you'll want to write it up and send to the google group. Rich isn't here at the moment so likely won't see this.
22:46AWizzArdright
22:46AWizzArdI need to think if we get any problems with functions that take any number of args
22:46Chouser_ is a currently a valid symbol
22:47AWizzArdyes
22:47scgilardi(defn a [b _ _ c] b) is legal now (which makes sense now that I think about it). (a 1 2 3 4) yields 1.
22:48pjb3Is there a way to do a mutlimethod that takes one arg, and if that are is a map I do one thing, regexp I do another, and then have a default case?
22:48AWizzArd(defn foo [a a a a] (list a a)) and then (foo 1 2 3 4) ==> (4 4)
22:48pjb3but have the map part work for all map types?
22:49rottcoddhow about changing things so #(f % %) == #(f %1 %2) instead of #(f %1 %1)
22:49scgilardipjb3: the multimethod's dispatch function can be "class" which could accomplish that
22:49AWizzArdI personally think that the % is not so nice for the eyes
22:50pjb3scgilardi: but class returns PersistentHashMap on {}
22:50AWizzArdthis is the problem.. as soon a language begins to add syntax (as Clojure does) people begin to care about it :-)
22:50Chouserpjb3: http://clojure.googlegroups.com/web/chart.png
22:50AWizzArdin Common Lisp we don't have that problem as there is far less syntax
22:50Chouserpjb3: so you probably want clojure.lang.IPersistentMap
22:50AWizzArdbut I think losing the underscore as a valid symbol is no real loss
22:51AWizzArdwho in the world names his parameters with underscores and would miss them if he couldn't do that anymore?
22:51pjb3Chouser: sure, but what method can I call on a map to have it return that interface?
22:51Chouserpjb3: use (defmulti foo class) -- the result of that will be compared using "isa?"
22:51pjb3I think I have to invent a method that returns the "base" type for an object
22:51scgilardiunderscore is currently being used in Clojure as an argument that should be ignored.
22:52pjb3Chouser: oh, it uses isa? for checking the method
22:52pjb3that should work then
22:52AWizzArdscgilardi: are you sure? Is this documented somewhere?
22:53ChouserI agree with scgilardi that's currently a convention (though not a particularly deeply ingrained one, I would say)
22:53pjb3AWizzArd: underscore is used as the "I don't case about this value" param
22:53AWizzArdokay
22:53AWizzArdso that is great
22:53AWizzArdit means: the underscore alread is not a valid symbol anymore, in the sense that a var could be bound to it
22:54AWizzArdI would like to extend it's use to the #(...) macro
22:54scgilardisymbols are independent of "places" (vars) in Clojure
22:54AWizzArdbecause there it also should mean: I don't care.. there will be some argument, but for my function definition it doesn't matter
22:55AWizzArdscgilardi: I understood your example first like (defn foo [a a a] ...). And this even works, although I don't think it is a good idea.
22:57scgilardiI think it's a fine idea if (as is the case in the uses of _ I've seen so far) you don't care about/won't use the value.
22:57scgilardi
22:58AWizzArdyou mean it is good that (defn foo [a a a] ...) is possible and does not produce an error or at least a warning?
22:58AWizzArdI think the underscore in the parameter vector of defn makes sense and is a fine thing.
22:58AWizzArdBut being able to repeat parameter names?
23:00scgilardirepetitions are allowed because nothing checks for them and precludes them. Repeating a name allows one to repeat _ which I think is a good thing. (currently _ gets no special treatment)
23:01AWizzArdI think there should be check for repetitions of symbols that are not _ and produce at least a warning
23:02scgilardi_ as "don't care" isn't documented anywhere that I know of. It is used once in boot.clj. A pretty cool implementation of drop_last. I've seen it in other cases where there needs to be an argument, but its value doesn't matter.
23:02scgilardiThat sounds like a fine warning to me.
23:03AWizzArdyes, the _ is fine, I agree. Nice thing
23:03AWizzArdI just think it makes sense that anything else in the argument lis.. vector should not repeat
23:07AWizzArdis there something like (remove element collection) or should one say (filter #(not= element %1) collection)?
23:08scgilardiremove was added yesterday, but it takes a predicate. to remove an element you can use a set as the predicate #{element} matches element and nothing else.
23:09AWizzArd:-)
23:15rottcoddsearching the clojure source and contribs, looks like every occurance of %1 and %2 are in order
23:15AWizzArdthis makes mostly sense
23:16AWizzArdotherwise it would be highly confusing
23:17AWizzArd( #(/ %2 %1) 10 2) ==> 1/5 and not 5
23:17rottcoddand no usage of %1 and %1, so perhaps #(f % %) => #(f %1 %2) would be a better default
23:17AWizzArdI suggest that we say #(f) instead
23:18scgilardi#(f) to mean what?
23:18AWizzArd(apply f %&)
23:18scgilardi#(...) puts the name and the body of the function between the parentheses
23:18AWizzArdyes
23:19AWizzArdforget my (apply f %&)
23:19AWizzArdI mean: #(f) returns a function that takes any number of arguments and then calls apply like I said
23:19scgilardiscratch my last... #(...) is anonymous and contains the body of the function between the parentheses
23:19AWizzArdso #(f) == #(f % %)
23:20AWizzArdI want to be able to omit all underscores or %1 %2 thingies as soon all specific curried arguments were given
23:21Chouserno you were right the first time: #(apply f %&) which === f
23:21AWizzArdof course currying makes no sense if you won't give any argument, because then one could do what Chouser just said, simply providing f
23:22AWizzArdbut for a function that takes 11 args where I want to give only the third I wish to say: #(f _ _ 100)
23:22AWizzArdand not #(f _ _ 100 _ _ _ _ _ _ _ _) or even #(f %1 %2 100 %3 %4 %5 %6 %7 %8 %9 %10 %11)
23:23AWizzArdif the #(..) macro sees underscores it first replaces them with the percent/number thing, as in #(f _ _ 100) becomes #(f %1 %2 100)
23:24Chouser#(apply f %1 %2 100 %&)
23:24scgilardicurrently you would still need to match one of the defined arities of f
23:24AWizzArdand then it returns a function that takes any number of args and is... exactly Chouser
23:25Chouseryou could name your new curry macro just _ and then call it like (_ f _ _ 100) instead of #(f _ _ 100)
23:25scgilardiChouser: that wouldn't work with an 11 arg f, would it?
23:25AWizzArdit would work with 11 args
23:25Chouserscgilardi: why not?
23:26AWizzArdand yes, having a single character macro could be a way, but I would still prefer something readable.. in Common Lisp I did it with brackets, as in [f _ _ 100]
23:27ChouserAWizzArd: that looks like arc
23:27AWizzArdbut as they are already used for vectors and also {} are in use and <> don't look good I would like #(...) most
23:27Chouserexcept in arc that syntax always takes exactly one arg I think, so your example would mean (fn [x] (f x x 100))
23:29scgilardiChouser: are you talking about calling #(apply f %1 %2 100 %&) with 11 subesequent arguments? If so, then I understand and it would work.
23:29scgilardi(#(apply...) a b c d e f g h i j k) would work
23:29AWizzArdYes
23:30AWizzArdbut we want to curry these arguments away
23:30AWizzArd(filter #(< 5) sequence)
23:30Chouserwhich is what #(apply ...) does today.
23:30AWizzArdexactly
23:31AWizzArdscgilardi: #(...) is a reader macro which returns a function object
23:31AWizzArdit already is doing it today
23:31scgilardiyes, I understand that
23:31AWizzArdand not too bad, I did not even know about it before Chouser mentioned it
23:32AWizzArd(because I found Clojure only yesterday)
23:32scgilardi:-)
23:32AWizzArdWhat I suggest is to extend #(...) a little bit
23:32ChouserI'm not sure I like the idea of _ meaning different values in the same scope.
23:33AWizzArdit means: for my abstraction I don't care what these are as soon I want to evaluate them
23:34AWizzArdIt say: yep, there is something, but whatever it is, in #(rgb _ _ 20) I want to make a function that creates something which is only a little bit blue
23:34scgilardiAWizzArd: are you thinking to extend it by giving meaning to something between the parens that is currently meaningless or by changing something that already has a meaning?
23:34ChouserAWizzArd: but the first time it means the first arg, second the second ... that's very unusual for a word.
23:34AWizzArdscgilardi: I want to be able to use the underscore, so that I can say #(rgb _ _ 20) instead of #(rgb %1 %2 20)
23:36AWizzArdin (defn [a b _ _ e f] ...) the first underscore means also: don't care for the 3rd arg and only a second later it means "don't care for the 4th arg"
23:36Chouserit would also mean that *all* #() constructs would take any number of args.
23:36AWizzArdright, so that is an efficiency hit?
23:36Chouserdunno.
23:36AWizzArdapply must always be a bit slower I guess than a direct call
23:37Chouserit is in clojurescript :-) not sure about clojure.
23:37AWizzArdwhat is clojurescript?
23:37scgilardiin a microbenchmark today, apply was being as fast as reduce in an application where they were equivalent. fwiw.
23:38ChouserAWizzArd: a partially complete clojure-to-javascript compiler.
23:38AWizzArdChouser: oh nice, didn't know that
23:38walters_Chouser: wouldn't it be easier to use applets?
23:39AWizzArdwalters_: why making html at all? Let the whole website be an applet :-)
23:39AWizzArdi think much more users turned java off in their browsers, but leave Javascript turned on
23:39Chouserwalters_: if an applet works in a given context, by all means use it.
23:40Chousercurrently applets must be signed to work, which throws up a security dialog (this may change with AOT compilation)
23:41Chouserapplets also require Java which is not quite as wide-spread in browsers as JavaScript.
23:41walters_hm...sounds like it shouldn't be that hard to fix
23:42AWizzArdapropos.. do you know if one could run ons Clojure programs on mobile phones?
23:43AWizzArdin principle j2me is also jvm
23:45Chouserwalters_: it has to do with clojure currently using a custom classloader. dunno if that would be a problem for j2me or not.
23:46pjb3(some #(even? %) [1 2 3 4]) returns true, shouldn't it return 2?
23:47Chouserno, some returns the value returned by the predicate
23:47Chouseryou may want filter
23:47walters_also, (some even? [1 2 3 4]) seems shorter =)
23:47pjb3"Returns the first logical true value of (pred x) for any x in coll, else nil."
23:47Chouserpjb3: right, and (even? 2) return true, so some returns true.
23:48pjb3I interpreted that mean the value, not the value of the pred
23:48pjb3yeah, I guess now that I re-read it
23:48Chouser(some #(when (even? %) %) [1 2 3 4])
23:48pjb3I want something that stops at the first logical true value, and returns the value
23:48AWizzArdwell, in principle 2 also stands for something true: (if 2 1 0)
23:49Chouserpjb3: I've stumbled on that a couple times.
23:49AWizzArdpjb3: you need to implement your own some
23:49Chouserfirst (filter even? [1 2 3 4]))
23:49pjb3Anything based on filter will go through the whole seq, right?
23:50Chouserfilter is lazy, so with (first) around it, you'll only do the required work.
23:50Chouser(first (filter even? (iterate inc 1))) works fine even though (iterate ...) is an infinite seq.
23:51pjb3ah, wow, lazy seq FTW
23:52AWizzArdChouser: I am still thinking about this apply thing, if apply costs performance
23:54pjb3So I assume (first (filter (< % 1) (iterate inc 1))) should just go forever, never terminate?
23:54AWizzArdin principle the jvm can optimize stuff if it knows that we have a (fn [a1 a2 a3 a4 a5... a11] (f a1 a2 a3 100 a4 a5... a11)) instead of a (fn [a1 a2 a3 & more] (apply f a1 a2 a3 100 more))
23:55AWizzArdpjb3: if you are brave paste your code to the repl :-)
23:56ChouserAWizzArd: you might want to take a peek at the implementation of apply. Or just ask rhickey.
23:56AWizzArdyes, I will ask him
23:56pjb3yup, just goes forever
23:57AWizzArdif it makes no practical difference, even when we have to map over billions of objects, then I will propose my changes to #(...)