#clojure logs

2009-10-11

00:04technomancyI wonder if it should/could be made more obvious somehow
00:05technomancyI guess it could write it automatically with the customize feature, but many people don't appreciate that.
00:07jaiganeshhi
00:07jaiganeshcan anyone explain whats happening in this piece of code (for [x (range 100 1000) y (range x 1000)] (* x y))
00:09tomojx goes from 100 to 1000, and each time y goes from x to 1000
00:11tomojer, except 999 instead of 1000
00:11tomoj,(for [x (range 0 4) y (range x 4)] [x y])
00:11clojurebot([0 0] [0 1] [0 2] [0 3] [1 1] [1 2] [1 3] [2 2] [2 3] [3 3])
00:11jaiganeshyeah thks
00:12jaiganeshis this called List comprehension? can i produce similar list in a different way in clojure?
00:14tomojit's list comprehension, yes
00:17tomoj,(mapcat (fn [i] (map (fn [j] [i j]) (range i 4))) (range 0 4))
00:17clojurebot([0 0] [0 1] [0 2] [0 3] [1 1] [1 2] [1 3] [2 2] [2 3] [3 3])
00:17tomojmaybe there is a prettier way to do it besides using for
00:17tomojbut why don't you want to use for? :)
00:21tomojfor is faster, too
00:21jaiganeshk
00:21tomojgoing from 0 to 1000, the for version above is over 3 times faster than the mapcat version
00:22jaiganeshhmm interesting
00:22tomojit uses chunked seqs, maybe other optimizations as well
00:28solussdwhat is the difference between binding and let?
00:28hiredmanlet is lexical
00:28tweeis there an easy way to get the namespace of a function parameter?
00:28hiredmanbinding is dynamic, and it only works if the names have already been created via def
00:29hiredmantwee: what do you mean?
00:29hiredman(fn [x] x) x is a local name, there is no namespace
00:29tweeat runtime i guess.. when you can the fn
00:29tweecall the fn
00:30solussdI see- So, binding will mask a defined value, but not define a new one?
00:30hiredmanmore or less
00:30tomojall the code called from within the body of the binding will see the new value, as well ("dynamic")
00:30hiredmantwee: what doe you mean by get the namespace of a function parameter?
00:30hiredmanbinding is also thread local
00:31solussdisn't 'let' thread local?
00:31hiredmanlet is lexical
00:31hiredman(let [x 1] (future (prn x)))
00:32hiredman(def x 0) (binding [x 1] (future (prn x)))
00:32tomoj(def *foo* 3), (defn foo [] *foo*), then compare (binding [*foo* 10] (foo)) to (let [*foo* 10] (foo))
00:34tweesomething like what the namespace function does, except for arbitrary things i guess
00:34twee(doc namespace)
00:34clojurebot"([x]); Returns the namespace String of a symbol or keyword, or nil if not present."
00:34hiredmanarbitrary things don't have namespaces
00:35solussdI see. Thanks
00:35tweelet's say i pass in (namespace map) i'd like it to say 'clojure.core'
00:35hiredmannamespaces are a space for names, so the only things that have/exist in namepsaces are names like keywords and symbols
00:36hiredman(def foo (Object.))
00:36hiredmanthe Object is not in a namespace, the name bound to the Object is
00:37tomojhmm
00:37tomoj,#'map
00:37clojurebot#'clojure.core/map
00:37tomojhow do you pull that out? maybe that's what twee is asking?
00:37tweeyup it is
00:38hiredmanyou want to resolve a symbol to the var it is bound to
00:38hiredman,(doc resolve)
00:38clojurebot"([sym]); same as (ns-resolve *ns* symbol)"
00:38tomojdoes resolve have an inverse, though?
00:40tomoj,(.ns #'map)
00:40clojurebot#<Namespace clojure.core>
00:41tweeah thank you, that's what i was looking for
00:41tomojI dunno if you're supposed to use that
00:41tomojmay be subject to change, I dunno
00:42tweei see
00:42hiredmanwhat are you doing?
00:42tweesome java interop stuff
00:43hiredmanand what does that have to do with namespaces?
00:46tweehave some stuff where it dynamically resolves the workflows to run, where workflow is passed in from cmdline, but for test-is code, i just don't want to deal with it. but if it doesn't work out, i'll just pass it in explicitly
00:46hiredmanif you don't want to say, you can just say that
01:03hiredmanhttp://weblogs.java.net/blog/forax/archive/2009/10/06/jdk7-do-escape-analysis-default
02:31arusselI got some newbee question before I start learning clojure. How mature is the eclipse plugin ?
02:32slashus2arussel: Try netbeans with enclojure
02:32arussel(in term of debuggin, autocomplete, code browsing)
02:33arusselslashus2: I never used netbeans ... Then between emacs and netbean plugin, which one would you recommend ?
02:33slashus2I don't use emacs because I have never given it an honest try, so I can't really weigh those.
02:34arusseldoes the netbeans plugin has autocomplete, debugging and code browsing ?
02:37slashus2arussel: Yes.
02:39arusselnice. Apart from compojure, is there any other web framework known to run on GAE ?
03:43gonzojivedoes anybody have emacs configured for both Common Lisp and Clojure? right now I can only do one or the other
03:44tomojI have both
03:44tomojbut I still have a bit of trouble using both at the same time
03:44tomojgonzojive: http://gist.github.com/28a01c699b8afecc0750
04:10G0SUBwhat should be the clojure type hint for a Future<Object> object?
04:10G0SUBwill #^Future<object> work? or should it be #^Future ?
04:11LauJensenDepends on what you're passing it to I suppose - I never had to type hint a future, why do you ?
04:11G0SUBLauJensen: I was just thinking. I am trying to use the spymemcached lib.
04:21ambientarussel neither netbeans nor eclipse plugins are something i'd call "mature"
04:21ambientthey work, but that's about it
04:21ambientplenty of rough edges
04:38ChousukeG0SUB: typehinting Object is pointless, and if you want to tell the compiler it's a Future, just use #^Future
04:38Chousukeor at least, I hope typehinting Object is pointless, since all classes are supposed to be Objects ;P
04:39G0SUBChousuke: OK.
04:39Chousukeif you still need to do the hinting, you'll need to do it when you dereference the future
04:39Chousukeeg. #^Object @future
04:39clojurebotChousuke: the fn created by future (like all fns) doesn't close over dynamicly scoped stuff
04:44hiredman~botsnack
04:44clojurebotthanks; that was delicious. (nom nom nom)
04:53arusselambient: do you know where to get the sources ( hg clone https://counterclockwise.googlecode.com/hg/ counterclockwise is empty
04:58ambientarussel might be a problem with googlecode
04:58ambientthey juse changed how their repos work iirc
05:00hiredman~ccw
05:00clojurebotCounterclockwise aka ccw at http://code.google.com/p/counterclockwise/
05:01ambienthiredman if you browse she source from there, you will notice it is empty
05:05hiredmanI was just checking
05:05hiredmanI know, uh, the guy that does the ccw stuff just stuffed a mess of urls into clojurebot the other day
05:06kyromancerarussel, http://github.com/laurentpetit/ccw
05:06cgrand~ccw is http://github.com/laurentpetit/ccw
05:06clojurebotAck. Ack.
05:06cgrandccw
05:06cgrand~ccw
05:06clojurebotccw is http://github.com/laurentpetit/ccw
05:06hiredmanI think he was the one that set it to the google code url
05:07kyromancergithub is just where the source is maintained, issues and wiki is on google code
05:07hiredman2009:Oct:08:15:37:53 lpetit : clojurebot: ccw is <reply> Counterclockwise aka ccw at http://code.google.com/p/counterclockwise/
05:07arusselfatal: http://github.com/laurentpetit/ccw/info/refs not found: did you run git update-server-info on the server?
05:07hiredmanoh
05:08hiredmaninteresting
05:09kyromancerthe clone url is different
05:09kyromancergit://github.com/laurentpetit/ccw.git
05:10arusselgot it, thanks
05:13arusselI am not much of an eclipse coder, but it seams that the name of the folder in which we put the compiled class is hardcoded.
05:14kyromancerlet me check
05:15kyromancerindeed, ClojureBuilder.java:124
05:16arusselI would like to be able to have them also in a war/WEB-INF/classes folder.
05:18arusselor to change the folder to war/WEB-INF/classes.
05:22kyromancerhmm thats gonna be a problem...
05:22kyromanceryou try linking classes to war/WEB-INF/classes
05:23kyromancer*could
05:24kyromancerit's a workaround at least if your OS supports it
05:31arusselthat looks like an ok workaround :-)
05:52G0SUBOK, so I have written a wrapper on top of spymemcached, and I need to write some tests. what's the best way to temporarily bind some vars just for testing purposes? (I need to bind the client obj to some var).
06:25arusselkyromancer: what action would compile a file into the "classes" folder. It seems I can manage to do once and that's it. If I clean the project, classes just becomes empty, and nothing is compiled into it anymore
06:25kyromanceryeah that is a bit of an issue atm
06:25kyromancercompilation needs the REPL to run
06:26kyromancersince that is where to compilation is performed
06:26kyromancertry starting it
06:27kyromancerthen CTRL+ALT+K in the editor
06:27kyromancer(Clojure->Compile...)
06:28kyromancerarussel: I am currently working on ways to improve compilation and Java interop
06:29kyromancerThe other day I was trying to mash up wicket and clojure using ccw, and it was quite difficult
06:29kyromancerEclipse was spitting out errros about not being able to clean the classes folder because the REPL was running
06:30kyromancerso I stopped the REPL and did a "Clean"
06:30kyromancerthat of course deleted all the classes generated from clj
06:31kyromancerso I restarted REPL, compiled, stopped repl, refreshed project...
06:31kyromancerMaybe theres a better way
06:31kyromancer..but I haven't found it yet
06:54ChousukeG0SUB: (binding [thing someotherthing] ...)?
06:54ChousukeG0SUB: you need to be careful if threading is involved, though.
06:55G0SUBhmm
06:56G0SUBChousuke: I wanted to know if clojure.test provided a similar but more sugared construct.
06:59G0SUBChousuke: I need to write a function/macro similar to memoize which caches the return vals in memcached. any tips on how to write something like that?
07:04ChousukeG0SUB: well, clojure.test also has fixtures but I'm not sure how to use those
07:05ChousukeG0SUB: isn't memoize enough? :)
07:06Chousukeanyway, one way to do it would be to have the function close over an atom for example.
07:06G0SUBChousuke: memoize, is not enough :) Really need to use memcached.
07:07Chousukeah, I guess I misunderstood your question
07:08G0SUBChousuke: so instead of storing the ret val in an atom, I store it in memcached.
07:08Chousukethat might work.
07:09G0SUBChousuke: OK. What's the best way to convert a function's name to a string? I am using (str (val f)) right now.
07:09G0SUB(var f)
07:09G0SUBnot val.
07:10ChousukeI think that's just fine
07:10Chousukehmm
07:10Chousuke,(.toString +)
07:10clojurebot"clojure.core$_PLUS___4443@1fce83e"
07:10G0SUBhmm
07:10Chousukeif you're going to use it as a memcached id or something, you might want to use that, too. it'll work for any function
07:11G0SUByeah, for the memcached key
07:19G0SUBI am always getting confused with the syntax of :use inside the :ns macro.
07:19G0SUB(:use [clojure.contrib seq-utils :only (str-join)])
07:19G0SUBwhat's wrong wit that?
07:19G0SUBwith
07:21Chousukeit's (:use (clojure.contrib [seq-utils :only (str-join)]))
07:22G0SUBah
07:23Chousukeit takes a prefix list, which is a list containing the prefix and any number of library specifications (either plain symbols or vectors)
07:24G0SUBChousuke: there seems to be a problem with var
07:24G0SUB(defn var-test
07:24G0SUB [f]
07:24G0SUB (str (var f)))
07:24G0SUBthis gives an error.
07:25Chousukethat's because f is a local, and thus f names no var :)
07:25G0SUBdang
07:26G0SUBhow do I get the name of the function then?
07:26Chousukethe function might not even have a name
07:26Chousukebut try the toString approach
07:26G0SUBright
07:26G0SUBok
07:27G0SUBChousuke: one concern is that the toString fn returns some extra stuff after the name of the function. I think it refers to the memory location or something.
07:28G0SUBas a result, it might not be the same for two different VMs running the same code.
07:28Chousukehmm, yeah
07:28Chousukeit won't be :P
07:28G0SUBmay be I can split the str at two underscores
07:29Chousukehow general do you need this memcache thing to be?
07:29G0SUBChousuke: not a lot, really. but it should generate the same key for different VMs given the same fn and args
07:30Chousukemaybe the easiest solution would be to leave selecting a proper key to the user
07:30G0SUBChousuke: hmm, you are right, I think.
07:30Chousukeso they could do (def memcached-foo (memcache "the.ns.foo" foo))
07:34G0SUBChousuke: makes sense. thanks for the tip.
08:37mrBlissI've got a question about zippers
08:39mrBlisssuppose you want to represent a graph as a zipper
08:39mrBlissmuch like http://projecteuler.net/index.php?section=problems&amp;id=18
08:40mrBlissI only see a way to store values in the leaves, not in the branches
11:04kyromancerA question: Is there a particular reason that all the VARs in RT are static?
11:05kyromancerThis makes cleanly separating independent clojure instances pretty hard...
11:06kyromancerGroovy and JRuby for example offer a runtime object that encapsulates the state so multiple instances don't step on each other's toes
12:58raekis there any difference between .. and -> besides that .. "adds dots" to the functions/methods?
13:20chouserraek: nope. if you look at their definitions in core.clj you'll see there are very similar.
14:46itistodayi'm looking through the code for compojure and I came across this:
14:46itistoday (fn [param-map, #^DiskFileItem item]
14:46itistodaywhat is that ',' doing there?
14:47hoeck1itistoday: commas are whitespace in clojure
14:47itistodayhoeck1: thanks
14:47itistodaydo you happen to know why they were added?
14:48hoeck1maybe to enhance readability in this arglist
14:49itistodayoh i mean in general
14:49hoeck1when printing maps, clojure puts commas between key-value pairs
14:49tomoj,{1 2 3 4 5 6 7 8 9 10}
14:49clojurebot{1 2, 3 4, 5 6, 7 8, 9 10}
14:49itistodayah i see
14:49tomojmuch harder to read without commas
14:50itistodayso it's so that can be read back in?
14:51Chousukenah, just for humans :)
14:51Chousukethe reader thinks commas are whitespace
14:51itistodayah k, thanks
14:52Chousukeit's possible to abuse though :P
14:52hoeck1but it would be nice to have one more reader-macro character,
14:53Chousukewhat for?
14:53hoeck1don't know (yet)
14:53hoeck1maybe for arrays?
14:54itistodaypersonally i hope clojure doesn't stray any further away from its lisp roots than it has...
14:54itistodaysyntax is the enemy ;-)
14:56prishvinHello, I have netbeans repl saying "Unable to resolve classname: Color" when I have (import '(java.awt Color ) done,
14:56prishvinwhat might be the reason?
15:07prishvinany ideas? :)
15:12chouserprishvin: seems unlikely, doesn't it.
15:13chouserYou're sure the file's getting saved and reloaded the way you think it is? No other errors?
15:17prishvinyes chouser, the file is saved and reloaded. it works if i use the full name like java.awt.Color
15:17prishvinlike if import does not work
15:30LauJensenprishvin, netbeans and vim have been replaced by something called Emacs - everything works in there :)
15:31prishvinLauJensen, :) I am not the emacs guy, btw do you have function browser/list in there?
15:31prishvinI've had function browser when I used emacs for a while writing CL
15:31LauJensenyea sure, you mean by way of reflection for java stuff?
15:33prishvinno sorry, I must have said it wrong, I mean a list of functions, which are in the open source file, "source browser"
15:34LauJensenI think somebody made a speedbar integration, but Ive never looked into it
15:34prishvinwell, netbeans has it, + its the best java ide, imo
15:35LauJensenk
15:35prishvinall works like a charm, except for (import...)
15:38LauJensenHow about those JVM Summit videos, are they up yet ?
15:39itistodayrhickey: take a look at newlisp's documentation: http://www.newlisp.org/downloads/manual_frame.html
15:40itistodayrhickey: can be auto-generated using newlispdoc command: http://www.newlisp.org/downloads/newLISPdoc.html
15:42ChousukeI wonder where the clojure-contrib doc generator is being hosted :/
15:43itistodayone other thing that i think clojure should borrow from newlisp is its strings ({}, [text][/text])
15:43itistodaydoes clojure have escape-proof strings?
15:43Chousukeescape-proof?
15:43itistodayI.e. in newlisp this is a valid string: {hello "fool", I'm so "cool"}
15:43Chousukethey're java Strings
15:43clojurebot
15:43itistodayinstead of: "hello \"fool\", I'm so \"cool\""
15:44Chousukeno such thing
15:44itistodayit would be *great* if it did...
15:44Chousukeit's a neat feature, yeah.
15:44Chousukebut what do you propose as the syntax?
15:45itistodayit's a problem for clojure to use {} of course
15:45itistodayor []
15:45itistodayor ()
15:45itistodayso... i'm not sure
15:45itistodayhow about <>
15:45itistodayi don't think those are being used for anything right?
15:45itistodayit would be best for it to be one-character, whatever the delimiter ends up being
15:45Chousukeother than being valid in symbols, no ;/
15:46Chousukehow do you suppose we'd deal with (< 1 2 3)? :/
15:46itistodaygood question
15:46LauJensen<> is xml property
15:46itistodayclojure might not be able to do it with only one char...
15:46itistodayperhaps something like /* */ :-p
15:46Chousuke:P
15:47LauJensenHow about #"" ?
15:47itistodaythat's already used
15:47itistodayfor regex's
15:47itistodaybut good idea
15:47LauJensenyea, but for something as useless as regex
15:47LauJensenso scrap that
15:47Chousuke:P
15:47LauJensenWho would miss regex?
15:47itistodaylots of people :P
15:47LauJensen~regex
15:47clojurebotSometimes people have a problem, and decide to solve it with regular expressions. Now they have two problems.
15:47LauJensenSee... :)
15:47itistodayhaha
15:48LauJensenAccording to my last blogpost, regex is for dweebs :) We have to go by that
15:48itistodayi like the idea though
15:48itistodaysome other char though
15:48itistodayand we can't use "
15:48itistodayit can't be #"" b/c we can't use # or "
15:48itistodayand it can't be #{} because that's already used too
15:49itistodayso how about #[] ?
15:49ChousukeI'd rather save that for some data structure
15:49itistodayk...
15:50Chousukesomething like #rDfooD where D is the delimiter wouldn't be too bad
15:50itistodaywell whatever it ends up being another constraint is that it has to play nice with regex's
15:50itistodayin newlisp {} are used all the time for regex's
15:51itistodayso that you don't have to do extra escaping
15:51Chousukethe regex literals have different escaping rules from plain strings
15:52itistodayright, but it's handy nonetheless, as it does let you avoid escaping a bunch of stuff
15:53itistoday[t]my text[/t] ?
15:53Chousuke[t] is a vector :P
15:53LauJensenStill looks good though
15:54itistodayrunning out of symbols
15:54itistodays/symbols/characters/
15:55itistodays{my "escaped" string?}
15:55Chousukeneeds the # prefix
15:55itistodaycan't have it
15:55itistodaythat's a set
15:55Chousukeno, I mean #s{...}
15:55itistodayoh
15:55Chousukeas I suggested earlier :)
15:56Chousukethough a bit more general
15:56itistoday:-)
15:56itistodayso #s{blah..} is good?
15:56itistodayit seems to fit clojure's use of #
15:57Chousukethat would be easy to implement and wouldn't reserve any very important characters.
15:57itistodaywhere should I send the recommendation?
15:57itistodaybzr-dev?
15:57itistoday(list)
15:57itistodayerrr
15:57itistodaylol
15:57Chousukethe list, yeah. :P
15:57itistodayclojure-dev list
15:58Chousukenot the developer list though. the public list :)
15:58itistodayjust wondering, but why?
15:58itistodayisn't this a dev decision?
15:59Chousukethe dev list is for discussing the implementation mostly
16:00itistodayrhickey: when you get back, check out the discussion above on #s{ ... }
16:00Chousukea raw string reader macro would be quite useful for docstrings
16:00Chousukewhich often contain bits of code
16:00itistodaythat's true
16:01itistodaythat way you could easily include sample code, something that the docs desperately need
16:01Chousukeyou can include it now, too, but writing strings is a bit ugly.
16:02itistodaybtw, can i join the clojure group without a gmail account?
16:02itistoday(if so, how?)
16:03Chousukeyou need a google account I think
16:04itistodaynot cool google...
16:04Chousukehmm, I can send invitations it seems
16:04ChousukeI don't know what that actually does, but give me your email address and I'll send you one :P
16:04rlbitistoday: you don't have to have a gmail account, just a google account -- though I agree, still unfortunate for a list.
16:05itistodayrlb: the invitation should work?
16:05itistodayChousuke: pm sent
16:05ChousukeI have no idea if the invitation does anything special
16:05Chousukeor if it's just a "plz join" spam message :P
16:06Chousukebut sent it anyway
16:06rlbitistoday: you don't need an invitation -- you can create an account for this purpose yourself.
16:07itistodayChousuke: i got the invite, thanks, it contained a link, i seem to have been subscribed, might take a bit to see if it actually worked though
16:07Chousukeitistoday: I wonder if you'll be able to post without a google account though :/
16:08itistodayChousuke: have you noticed anyone on the list without one?
16:08itistodayi seem to recall on another list people doing so
16:08itistodayso i think it's possible
16:09Chousukeitistoday: http://groups.google.com/support/bin/answer.py?hl=en&amp;answer=46438
16:10hiredmanit's not actually mailing list, it is a google group, which needs a google account, you just have the option of using it via email
16:11Chousukeyou can post by sending mail to clojure@googlegroups.com apparently
16:11itistodaycool, thanks
16:11itistodayalthough i was expecting an email to arrive saying "you've joined! here's what you can do:..."
16:12itistodaysomeone should post to the group though and i should get the email though, if that doesn't happen within 4 hours i'll just sign on via gmail
16:13hiredmanthe first message to the group requires a moderator to sign off on it
16:14itistodayhiredman: that doesn't affect receiving emails though right?
17:39itistodayfyi i've sent an email to the clojure group regarding the #s{ ... } construct, hopefully a mod will approve it soon
17:40spaceman_stuI'd like write a macro that would generate a few helper functions. defn'ing them from within the macro seems problematic - what's the right approach there? maybe return a hash with the funcs as keys?
17:42Chousukekeys? you mean values? :P
17:42spaceman_studetails =]
17:43spaceman_stubut yeah, so would something along those lines be the preferred appraoch?
17:43Chousukedo you need to generate these functions at runtime?
17:43spaceman_stuno
17:44spaceman_stuI know them beforehand
17:44Chousukethen I guess macros might be a better choice
17:45Chousukeyou can have a (defmacro gen-funcs [some params] (list 'do `(defn firstone ..) `(defn secondone ...))
17:45Chousukethe (list 'do ..) because nesting ` is a bit icky :)
17:45spaceman_stuhm, yeah, that could the reason it's not working now
17:54itistoday~seen rhickey
17:54clojurebotrhickey was last seen joining #clojure, 623 minutes ago
17:54itistoday,(/ 623 60)
17:54clojurebot623/60
17:54itistoday...
17:54itistoday,(int (/ 623 60))
17:54clojurebot10
17:55itistoday,(float (/ 623 60))
17:55clojurebot10.383333
18:03itistodayhow do i check if a symbol is bound?
18:03itistodayi.e. (def x)
18:03itistodaythen what to check if it's bound?
18:04itistoday(as that will leave it unbound)
18:04Chousuke(try x 'BOUND (catch SomeException e 'UNBOUND)) :P
18:05itistodayok, then i should change my question as that's not the solution i'm looking for
18:06itistodayhow do you create a closure that increments a counter?
18:06itistodayi.e. (defn counter ... )
18:06itistoday(counter) => 1
18:06itistoday(counter) => 2
18:06itistodayetc.
18:06Chousukethat's bad style :)
18:06itistodaythat's a common thing to do
18:07Chousukenot in clojure though
18:07itistodaycan clojure not do it?
18:07Chousukebut, (let [ctr (atom 0)] (defn counter [] (swap! counter inc)))
18:07Chousukeyou're strongly encouraged not to do this though :P
18:07clojurebotthis is not a bug
18:08Chousukerather, have the counter in an atom or a ref and increment it explicitly :)
18:08itistodayk... but what is that code doing..?
18:08itistodaywhere is ctr used?
18:09Chousukewhoops
18:09Chousukethe first argument to swap! should be ctr
18:10Chousuke,(let [a (atom 0) b (fn [] (swap! a inc)] [(b) (b) (b)])
18:10clojurebotUnmatched delimiter: ]
18:10Chousuke,(let [a (atom 0) b (fn [] (swap! a inc))] [(b) (b) (b)])
18:10clojurebot[1 2 3]
18:11itistodayok cool, thanks
18:11itistodayand why an atom and not a var?
18:11Chousukea var is usually not intended to be changed
18:11Chousukelocally rebound, perhaps, but not changed
18:12itistodayhmm.. thanks, i'll wrap my head around this soon...
18:13itistodayhow does one create a local var?
18:13Chousuke(doc with-local-vars)
18:13clojurebot"([name-vals-vec & body]); varbinding=> symbol init-expr Executes the exprs in a context in which the symbols are bound to vars with per-thread bindings to the init-exprs. The symbols refer to the var objects themselves, and must be accessed with var-get and var-set"
18:13Chousukebut that's almost never used.
18:13Chousukein fact, I can't think of any good use for it :P
18:14itistodaywell, i was looking at the docs on var
18:14itistodayhttp://clojure.org/vars
18:14itistodayand it says that set! can't be used to change a root binding
18:14itistodayso how do i create a var that is not in the root binding?
18:14Chousukeyou don't. :)
18:15Chousukeyou use the binding macro to rebind it locally
18:15itistodayso when is set! used?
18:15itistodayis it used often?
18:16Chousukewithin a dynamic scope where a var has been thread-locally bound
18:16Chousukeeg, (binding [*someglobal* 4] (foo))
18:16Chousukenow foo can be a function that uses set! on *someglobal*
18:17itistodaythat seems like it would be a very rare thing to do
18:17itistodayor at least in poor taste
18:17itistodayi.e. foo would require that it be run inside the binding macro and nowhere else
18:17itistodayright?
18:17Chousukewell, using set! is fairly rare, but binding stuff like that isn't
18:17Chousukeset! is thread-safe though. :)
18:17Chousukebecause var bindings are thread-local
18:18Chousukethe root binding isn't, so that's why you can't use set! on it.
18:18itistodayis 'binding' used often?
18:18itistodayi can't imagine a situation where i'd want to use it
18:18Chousukepretty often I think.
18:19itistodaycan you give an example? sorry if i'm asking too many questions btw
18:20Chousukeitistoday: well, you could have some code that depends on a database being specified, and you could use a global *db* that is initially unbound, but when you actually call the database functions, you bind it with (binding ...)
18:20Chousukeusually wrapped with some macro magic so that you can use (with-database-connection conn (some-db-stuff) (more-db-stuff)))
18:20itistodaydoes that mean you'd have to establish a db connection each time you want to do something?
18:21Chousukeitistoday: no, you can establish the db connection beforehand
18:21Chousukeand just bind *db* to that whenever you use the db functions
18:21itistodaywhy not have the *db* always bound?
18:22Chousukewill you always have a connection? :)
18:22Chousukeyou might also want to have multiple connections
18:23itistodayok, so you're saying that functions can reference *db* and just require they be called in a binding on *db*
18:23itistodaywhere is the actual connection stored though?
18:23Chousukeyes.
18:23itistodayon another var?
18:23itistodayor an atom?
18:23Chousukewherever you like
18:23raekwhen is var-quote useful?
18:24raekin (send *agent* #'do-stuff) ?
18:25itistodayactually, that's another question i had, what is the purpose of #'blah
18:26itistodayi.e. the var function?
18:26itistoday,(doc var)
18:26clojurebotTitim gan éirí ort.
18:26itistodaywtf
18:27raekthat's var-quote
18:27itistoday,(doc var-quote)
18:27clojurebotNo entiendo
18:27Chousuke,'#'foo
18:27clojurebot(var foo)
18:27raekit gives you the var bound to the symbol
18:27Chousukeitistoday: var is a special form, no doc string for it :)
18:28Chousuke#'foo is identical to (var foo)
18:28raekso, when should one use var-quotes?
18:29raekdo they force a lookup when they are evaluated?
18:29Chousukewhen you want the var named by a symbol :/
18:29Chousukewhich does happen sometimes
18:29Chousukeitistoday: http://gist.github.com/207927
18:30Chousukewhoops
18:30Chousuketypo in comment.
18:30Chousukethe first one of course results in 15 :P
18:31itistodaythanks
18:31itistodayi see that now
18:31itistodayi'm trying to reconcile my existing knowledge with clojure
18:31itistodayand it's hurting
18:31itistodayheh
18:31Chousukedynamic scope is a bit weird :)
18:31itistodaywell i know dynamic scope
18:32raekif I run (send-off some-agent some-fn), will some-fn be looked up only once?
18:32itistodayi'm trying to figure out how to do lexical scope to create a counting function
18:32raek*if I run .. from "some-agent"
18:32itistodayand i take it that i need to use an atom, but if i'd rather use a var
18:33raekthat is, do I have to use var-quote if I want to be able to "monkey patch" the code?
18:33Chousukeraek: hm, I'm not sure about that actually.
18:33Chousuketry it and see :)
18:34raekit looks like #'some-fn and some-fn doesn't make any difference
18:34Chousukeit sometimes does though IIRC.
18:34Chousukemaybe only if you're storing it in a data structure.
18:35itistodayChousuke: how do i make a correct version of this: (defn new-counter [] (binding [x 0] (fn [] (set! x (+ 1 x)) x)))
18:35itistodayi'm pretty sure that i'm using binding incorrectly
18:35itistodaybut all i want is a variable with that closure
18:35itistodaythat the function can manipulate
18:35itistodayor is that not possible in clojure?
18:36Chousukeitistoday: you need an atom
18:36Chousukeor a ref, or an agent, but an atom is simpler
18:37itistoday(defn new-counter [] (let [x (atom 0)] (fn [] (swap! x inc) x))) ?
18:37itistodaythat seems to work
18:37Chousukeyeah, it closes over the atom
18:37Chousukethe x at the end is redundant though
18:37itistodayoh, didn't know
18:37Chousukeactually, it's wrong. you meant @x :)
18:38Chousukex is the atom, @x is its value
18:38itistodaygotcha
18:38itistodaygetting the hang of this... thanks :-)
18:38Chousukebut in any case, (swap! x inc) returns the new value
18:38itistodayright
18:39itistodayis there anything in clojure that is not thread-safe?
18:39Chousukejava interop :P
18:39itistodaygotcha, so using a value from a java object could be unsafe?
18:40Chousukein clojure parlance, a "value" is an immutable things.
18:40Chousuke-s
18:40Chousukebut Java objects are not necessarily values
18:40Chousukethey might change, thus rendering them unsafe.
18:40itistodaya java object that has a public int x; using that x is unsafe right? and uh... what do i call that x if not a value?
18:40itistodayor a variable?
18:41Chousukex is a variable I suppose, but the int is its value
18:41Chousukean int is immutable
18:41Chousuke5 is 5, no matter what you do :)
18:42itistodayright, ok, i'll learn to use the terms correctly too ;-)
18:42itistodaybut the *variable* is unsafe?
18:42Chousukeyeah.
18:42itistodaywhat do people do about that?
18:43Chousukeyou could do (def foo (YourObject.)), and depending on what happens, (.x foo) may return different values
18:43Chousukeso foo is not a value
18:43Chousukeitistoday: usually, people are very careful when dealing with mutable java things :)
18:44Chousukeimmutable java things are safe of course, so not all interop is dangerous
18:44itistodaywell i mean say they have a java object written to by multiple threads, do they wrap it in a clojure actor?
18:44Chousukethat's one way I guess.
18:44itistodaywith my limited knowledge of clojure, that's what i'd do. ;-)
18:45Chousukethere's also the locking macro, but that's pretty rare :/
18:45ChousukeI don't think I've ever seen it used :P
18:45itistodayit's like a mutex lock?
18:45Chousuke~def locking
18:46itistodaypretty much a mutex i guess
18:46ChousukeI guess it's whatever the java synchronisation system uses
18:46itistodaymonitors are similar to mutex locks no?
18:47itistoday `(let [lockee# ~x]
18:47itistodayis that # on the end doing anything special?
18:47Chousukeyes. it's an autogensym
18:47itistodayor is that just some bizarre naming convention
18:48itistodayah, gotcha
18:48itistodayso that's how they're used
18:48Chousukeit can be used to avoid multiple evaluations of x
18:48itistodayi thought it was used to prevent name clashes?
18:48Chousukethat, too
18:48itistodaygotcha
18:48itistodaywell, i think i've used up enough of your time :-p
18:48itistodaythanks for all your help
18:49Chousuke(let [x '(some-expensive-computation)] `(let [x x#] [x# x# x# ~x ~x ~x]))
18:49Chousuke,(let [x '(some-expensive-computation)] `(let [x x#] [x# x# x# ~x ~x ~x]))
18:49clojurebot(clojure.core/let [sandbox/x x__4470__auto__] [x__4470__auto__ x__4470__auto__ x__4470__auto__ (some-expensive-computation) (some-expensive-computation) (some-expensive-computation)])
18:49Chousukeoops
18:49Chousukeforgot to unquote the first x
18:49Chousukeand got them the wrong way around too
18:49Chousuke... I guess I shoudl go to sleep :)
18:49Chousukeanyway, you get the idea.
18:50Chousuke,(let [x '(some-expensive-computation)] `(let [x# ~x] [x# x# ~x ~x]))
18:50clojurebot(clojure.core/let [x__4474__auto__ (some-expensive-computation)] [x__4474__auto__ x__4474__auto__ (some-expensive-computation) (some-expensive-computation)])
18:50itistodayyeah, i originally thought it was to be used the way you had it the first way around
18:50itistodaybecause I thought it was like (gensym)
18:51itistodayso, (let [x (gensym)] ... )
18:51itistodayi figured it'd be (let [x x#] ... ) , or something like that
18:51itistodaybut that wouldn't make sense
18:51Chousukeautogensyms are so much nicer than using gensym directly though
18:52Chousukein the cases that you can use them, which is most of the time.
18:52itistodayright, i thought it was nifty when i saw it, and seeing it used now makes sense, i just never would have thought that code would work because i'd thought calling x# multiple times the way it does there could create multiple symbols
18:53itistodaysomehow it doesn't though
18:53Chousuke` contains a lot of magic
18:54itistoday,`(let [#x 0] (println #x))
18:54clojurebotNo dispatch macro for: x
18:54itistodaywhy fail?
18:54Chousukehuh
18:54Chousukeah
18:54Chousukex#, not #x :D
18:55itistoday,`(let [x# 0] (println x#))
18:55clojurebot(clojure.core/let [x__4478__auto__ 0] (clojure.core/println x__4478__auto__))
18:55itistodaylol
18:55itistodayhehe
18:55Chousukeif you want to see sq implemented in clojure, search http://github.com/Chousuke/clojure/blob/sq-macro/src/clj/clojure/core.clj for syntax-quote
18:56itistodayk, think that's too advanced for me right now though
18:56itistodaybtw, how do i get that thing to print 0?
18:56itistoday,`(let [x# 0] (println x#))
18:56clojurebot(clojure.core/let [x__4482__auto__ 0] (clojure.core/println x__4482__auto__))
18:56itistodayinstead of that
18:56Chousukeeval it :)
18:57Chousukemacros in the end are just functions that produce data structures just like that.
18:57Chousukethe compiler just runs eval on it afterwards
18:57itistoday,(eval `(let [x# 0] (println x#)))
18:57clojurebotDENIED
18:57Chousukeheh ;(
18:57itistodaythat would have worked though right?
18:57Chousukeyes.
18:57itistodayk
18:58Chousukeit was a small epiphany for me when I finally understood macros.
18:58itistodaythat happened to me as well, but that was a year ago when i was learning scheme
18:59Chousukewhen I tried to learn CL I saw the backquote as some kind of magic that's macro only :/
18:59itistodaysince them i've forgotten about them because i've been using newlisp's fexprs
18:59itistodaythat's about the stage that i'm back at right now too ;-)
18:59Chousukeheh.
19:00Chousukebut it really helps to realise that the backquote is just a convenience tool to replace a lot of manual calls to list and quote :P
19:00itistodayright
19:00itistodayi'm going to go back to that scheme tutorial and read about it, it had an excellent explanation
19:01itistodayhttp://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z-H-10.html#node_chap_8
19:01itistodaybtw, i love clojure's logo, i just noticed the yin-yang in it
19:02Chousukeyeah, it's great
19:03itistodayah, looks like my suggestion for #s{ ... } made it into the clojure list
19:07kmurph79is there a function that returns true/false based on whether a regex matches a string; like: (re-match #"(9)" "298") => true
19:07Chousuke(doc re-match)
19:07clojurebotexcusez-moi
19:07Chousukehmm
19:07Chousuke,(re-matches #"foo" "bar")
19:07clojurebotnil
19:08Chousuke,(re-matches #"foo" "foo")
19:08clojurebot"foo"
19:08Chousukemaybe that's good enough?
19:08kmurph79yeah
19:08itistoday,(if (re-matches #"foo" "foo") "yes" "no")
19:08clojurebot"yes"
19:08itistoday,(if (re-matches #"foo" "fzo") "yes" "no")
19:08clojurebot"no"
19:08itistodayyay
19:08raek,(boolean (re-matches #"foo" "foo"))
19:08clojurebottrue
19:09raekif you don't want to "leak" any details
19:09kmurph79thanks
19:13raekis (doseq [x xs y ys] (fn-with-side-effects x y)) the same as (dorun (for [x xs y ys] (fn-with-side-effects x y))) ?
19:31kmurph79what does the _ symbol do?
19:32dreishraek: They expand to different code, but as far as I know they're effectively the same thing.
19:32kmurph79nm i think i got it
19:33raek(try (foo) (catch SomeException _ (bar)))
19:34raekin that case, you are not interested in the value that would have been assigned to the symbol in the place of _
19:34raek(defn foo [_] (bar))
19:35raeka function that takes one argument and discards it
21:00steigerhey guys. i'm trying to create my own data structure in clojure by using :gen-class and extending clojure.lang.ASeq (like StringSeq does). but, how should I call the superclass (ASeq) in the -init method?
21:03arbschtsteiger: -init returns a vector including arguments for the superclass constructor, and your own state. the superclass constructor is called automatically with those args
21:04arbschtif you want to call any other overridden methods, use :exposes-methods
21:05steigerarbscht: oh, i see
21:06steigerarbscht: thank you
21:18zaphar_pswhy does recur not work in an if expression?
21:18zaphar_psit's still a tail call but if I put the tail call in an if expression it doesn't work
21:19chouser,(loop [a 1] (if (< a 10) (recur (inc a)) a))
21:19clojurebot10
21:19chouserworks fine
21:20zaphar_pshrmmm must have a paren out of place then :-)
21:20itistodayzaphar_ps: i hear it needs to be in the "right place"
21:21itistodayi.e., near the end
21:21zaphar_psheh
21:21zaphar_psfound it
21:21zaphar_psI hate it when you lose track of one. It's such a pain to track it down again
21:31ynnivhiredman: Does the XMPP code in clojurebot currently work? I'm having some trouble.
21:35steigeris it possible (if so, what is the best way) to implement a map structure that has different behavior on (first) (rest) and (seq), returning something like: (first {1 2 3 4}) -> {1 2} instead of [1 2] ?
21:39ynnivI don't know the answer to your question, but your question seems odd. Why would you want a dictionary from (first)?
21:40itistodayi think it makes sense, he wants the first key/value pair
21:40itistodayoh wait
21:40itistodayno, it is odd
21:40ynnivheh
21:40itistodayhe's getting that already
21:40itistodayhehe
21:42steigerynniv: i'm just experimenting
21:42hiredman,(key (first {:a 1}))
21:42clojurebot:a
21:42hiredman,(val (first {:a 1}))
21:42clojurebot1
21:42ynnivyou're probably looking for "(apply hash-map (first { 1 2 3 4 }))"
21:42steigerhiredman: i'm aware you can do that
21:43ynnivis the goal to make a new data type that has an alternate definition of #'seq?
21:43steigerthe focus of my question is: how to create a custom data structure with a custom (first) and (rest) semantics
21:43steigerynniv: something like that, yes
21:45steigerthink of the string data type: (seq str) returns a StringSeq, which is a string of chars
21:45steiger,(type (seq "abc"))
21:45clojurebotclojure.lang.StringSeq
21:46steigerand (first "abc") returns \a
22:17ynnivsteiger: that seems surprisingly difficult to accomplish. maybe I'm following the wrong trail?
22:17ynnivbut I'm knee deep in Java, and not seeing a clear path out
22:21ynnivseq seems to operate on ISeq, which is a java interface that has more methods than I expected (through inheritence)
22:43ynnivsteiger: (defn make-data [d] (proxy [clojure.lang.ISeq] [] (first [] (apply hash-map (first d))) (next [] (next d)) (more [] (rest d)) (cons [o] (cons d o)) (count [] (count d)) (empty [] (empty d)) (equiv [a] (= d a)) (seq [] (seq d))))
22:44ynnivI only modified "first" to return a map
22:46ynnivactually, this might do it:
22:46ynniv(defn make-data [d] (proxy [clojure.lang.ISeq] [] (first [] (apply hash-map (first d))) (next [] (make-data (next d))) (more [] (make-data (rest d))) (cons [o] (cons d o)) (count [] (count d)) (empty [] (empty d)) (equiv [a] (= d a)) (seq [] (map #(apply hash-map %) (seq d)))))
22:47ynnivwhich would look really snazzy in a paste, but i'm tired
22:47ynnivanswering questions like this one is a great way to learn a new system, tho
23:01steigerynniv: sorry for the delay
23:01ynnivi used the time to format my code to be clojurebot friendly:
23:01ynniv,(let [make-data (fn [d] (proxy [clojure.lang.ISeq] [] (first [] (apply hash-map (first d))) (next [] (recur (next d))) (more [] (recur (rest d))) (cons [o] (cons d o)) (count [] (count d)) (empty [] (empty d)) (equiv [a] (= d a)) (seq [] (map #(apply hash-map %) (seq d)))))] (seq (make-data { 'a 1 'b 2 })))
23:01clojurebot({a 1} {b 2})
23:01ynnivand use #'recur for the first time
23:02steigerynniv: thank you, that's what i wanted. i was trying to extend ASeq, but implementing ISeq really seems to be cleaner
23:03ynnivonly because you can use convenient clojure funcs like "rest" instead of trying to bridge to java :)
23:03ynnivI am continually impressed by the design and implementation of clojure
23:04steigerindeed :]