#clojure logs

2009-07-10

02:03thearthur(partition dropps partial blocks at the end. I need one that doesn't do that
02:03thearthuris this in contirb somewhere?
02:04thearthur???? (partition 4 [1 2 3 4 5 6 7]) => ((1 2 3 4))
02:05thearthur(my-partition 4 [1 2 3 4 5 6 7]) => ((1 2 3 4) (5 6 7))
02:10thearthurnm found that partition can do this with its pas arg
02:10thearthur(partition 4 4 () [1 2 3 4 5 6 7])
02:24RaynesIs there a predicate to check whether or not a sequence is empty?
02:24arbscht_,(empty? [])
02:24clojurebottrue
02:24RaynesThank you. :)
02:27thearthur(push and pop mention working on queues. how do i create a clojure.lang.PersistentQueue
02:33mrpikathere doesn't appear to be a clojure wrapper for it
02:34mrpikayou'd have to use it via java interop
02:35mrpikaor conj
02:35mrpikahttp://markmail.org/message/brvozelsgmr5a3ba
04:01thearthurhow do i undefine a var from the repl?
04:01thearthurdont want to reaload everything
04:06Chousukens-unmap should help
04:12RaynesWhy would you need to undefine a var from the REPL?
07:55Holcxjo`I am lost with Java interop. I have a class that has a static class as its member. How do I instantiate that inner class?
08:02Holcxjo`To be specific: I am trying out the Evernote API. The Java demo does: import com.evernote.edam.userstore.*; ... UserStore.Client userStore = new UserStore.Client(...args..)
08:03Holcxjo`I can do (import '(com.evernote.edam.userstore.UserStore)) but anything after that fails...
08:03Holcxjo`com.evernote.edam.userstore.UserStore/Client (. com.evernote.edam.userstore.UserStore Client) (com.evernote.edam.userstore.UserStore/Client. <some arg>) ...
08:04Holcxjo`Any ideas?
08:04liebkeHolcxjo`: you access inner classes with $, e.g. Class$InnerClass
08:04Holcxjo`Oh!
08:04liebkeyeah, not really obvious :)
08:04Holcxjo`Also not in the book I believe...
08:05Holcxjo`It's on http://clojure.org/java_interop if you know what the correct term (inner class) is...
08:05Holcxjo`thanks!
08:06liebkeno problem :)
09:52RaynesI accidentially wrote a faster (apply max ..) :o
10:08ChouserI think they're making fun of us. http://lambda-the-ultimate.org/node/3488
10:15Chousukenah :)
10:16cemerickChouser: I think they were aiming at NewLisp
10:16Chouserah
10:17liebkeyeah it doesn't look like it's aimed at clojure, read the paper (pdf) http://jfm3.org/phosphorous.pdf
10:18ChouserI guess it was the JVM comments that made me wonder
10:18ChousukeI like how their CamelCase convention extends to the paper as well.
10:25cemerickChouser: JVM:lispers :: Microsoft:free-software-advocates
10:25Chouserheh
10:37RaynesLike parent's tell their children. "Don't mind them, they are only upset because you're so special!"
10:41Chouserdoes anyone have a link to the little outline about new-new plans?
10:42cgrandChouser: http://www.assembla.com/wiki/show/clojure/New_new ?
10:42Chouserah, yes. thanks!
10:44achim`oh, the NewLisp presentation has a nice font selection
10:45achim`does anybody happen to know the monospaced font? :)
10:49lisppaste8ceninan pasted "macro/seq practice "dsl"" at http://paste.lisp.org/display/83369
10:49ceninanI thought I'd learn some macro-fu by doing something that changes lisp semantics, and not just simple syntax "prettification"
10:49ceninanso I "designed" (lol) something that I thought would be interesting to implement
10:50ceninananyone familiar with the Icon language?
10:52cemerickseems like assert should take an optional failure-msg arg
10:52Chousercemerick: you're playing with assert? Have you seen the new pre/post conditions?
10:52Chouserceninan: not me, sorry.
10:54cemerickChouser: oh, no -- someone mentioned them to me, but I'd forgotten
10:54cemerickwe're on v1.0 + patches for a while, though
10:55Chouseroh, ok.
10:56cemerickI suppose aggressively tracking head might be a good idea, but that'd take some CI work.
10:57ChouserI'm using 1.0 at work myself, but I also haven't touched our .clj code in a while.
10:57cemerickit's the only reasonable way to do things atm, but I do certainly loathe upgrade cycles.
10:58lisppaste8ceninan annotated #83369 "untitled" at http://paste.lisp.org/display/83369#1
11:00Chouserceninan: it looks like you're mutating !tries in the middle there
11:00ceninanChouser: that part isn't really correct
11:01ceninanthe :! should have an optional let form
11:01Chouserceninan: and some minor adjustments to your proposed syntax would make it much easier to implement
11:01ceninanI'm all ears :)
11:01Chouserlooks like an interesting experiment
11:01Chouserwell, macros are applied at compile time when the compiler sees a (macro-name ...) form
11:03Chouserso with your proposed syntax, you either need to define 'integer?', 'between?' and '=' as macros, or wrap the whole thing in a macro call that will walk the tree looking for your :! :<- annotations
11:03ceninanis it possible to do a macro macro generator?
11:03Chouserceninan: yes
11:03ceninanthen there could be some sort of "def" for these types of "functions"
11:04ceninancorrect?
11:04Chouserboth the options I described are possible, but neither is particularly simple
11:04Chouseryes
11:04Chouserbut writing such a macro is several steps removed from accomplishing your goal -- unless this specific syntax is your goal, I suppose.
11:05ceninannot really stuck on the syntax, no
11:05ceninando you have a simpler proposal?
11:05Chouserif you instead wrapped another layer, maybe... (icon-step (integer? (read-line)) :<- ... :! ...)
11:05Chouserthen you could define a single macro 'icon-step' that did your heavy-lifting.
11:06ceninanhmm, yes - that does sound like a more practical approach
11:06Chouserand actually, if you got that working and still wanted to write a 'def-icon-fn' macro, it could produce macros that expand to 'icon-step' forms and your life would be more pleasant. :-)
11:07ceninanright :)
11:07ceninanthanks, hadn't thought of that
11:07Chouseras with any macro, I'd highly recommend writing out code the code you want your example to expand to before you start trying to write the macro
11:08ceninanand that leads to my next question :)
11:08mccraigChouser: are pre/post conds described/exampled anywhere ?
11:08ceninanwhat would be a good structure for the "seq"?
11:10mccraigfound a description : http://github.com/richhickey/clojure/commit/0ac482878a1dd520cbee2faa0f5f6ab1082ffa76
11:10Chousermccraig: sure! in the commit message. :-)
11:10Chouserthere ya go
11:13Chouserceninan: not sure -- seems like figuring that out is the task you've chosen for yourself. :-)
11:14ceninanwell, that's true ;p
11:14ceninanthanks a lot for the help!
11:15ChouserI'm not quite sure I grok your syntax, but if you get stuck feel free to ask more.
11:16ceninanI'll try to figure it out without dealing with the syntax first :)
11:16ceninanthanks again
11:18ceninan(btw, they allow you to react to failure conditions; failure can have different causes, eg '=' have the fail conditions '>' and '<')
11:18ceninan(tbh, I don't really grok it myself yet ;))
11:19Chouserah! hm.
11:20Chouserthat makes it sound more like a sort of cond applied to each element of the seq
11:24ceninanI'm entirely sure that I follow; the "fail conditions" primary purpose is to produce side effects or change local bindings
11:25ceninanthey shouldn't escape to a parent operation
11:25ceninanbut like some sort of (loop (cond)), yes
11:26ChouserI'll be fascinated to see what you come up with. :-)
11:26ceninanthanks :)
11:28ozzileeChouser: Forgive me for not just trying it or digging through the changelogs, but... the lazy-xml I have doesn't automatically convert tag contents to strings, instead throwing NPEs. Has that changed?
11:29Chouserlazy-xml hasn't changed in ages
11:29Chouserozzilee: you're talking about when emitting?
11:30ozzileeChouser: Yeah. Something like {:tag :foo :content [5]} throws an NPE.
11:31Chouserah. I don't think I'd noticed that. A contrib ticket and patch for that would be welcome.
11:33ozzileeChouser: Okay, will do. Probably. At some point :-) I need to work on getting some tests going on this mess before I start updating dependencies.
11:34Chousera ticket without a patch would be fine too
11:35ozzileeAny recommendations on that front, btw? As far as a testing framework. Fact maybe? It's hard to keep up.
11:35hiredmantest-is got moved into core
11:35ozzileeChouser: Ok, I'll do a ticket now.
11:43ozzileehiredman: That looks like it will work. Do you use it?
11:43ozzileeChouser: Ticket submitted.
11:43Chouserozzilee: thanks!
11:44hiredmanozzilee: nope
11:45hiredmanI guess I could write tests for clojurebot
11:45hiredmanbleh
11:45RaynesI wish I knew Java. :\ I might understand what this :state stuff is all about.
11:45hiredmanRaynes: it creates a field where you can store state information
11:46hiredmangenerally a ref or a atom
11:46RaynesOh, like a field in Java.
11:46ozzileeRaynes: Except you only get one per proxy object.
11:46hiredmaneh?
11:46hiredmanproxy has a .state?
11:46Chouserone per gen-class instance
11:47RaynesWorks for me. :D
11:47hiredmanyeah
11:47ozzileeEr, gen-class. Yeah. That's what I meant.
12:34eyerisWhen I want to use destructuring to bind a symbol to a map key of the same name, e.g. (let [{k :k} my-map] (...)), is there an abbreviated form of `a :a` that assumes the same name?
12:38hiredman(let [{:keys [a]} {:a 1}] a)
12:38hiredman,(let [{:keys [a]} {:a 1}] a)
12:38clojurebot1
12:41eyerisThanks
13:26ataggartdoes anyone have a clear sense of which datastructure manipulation functions are meta-data preserving?
13:27ataggarte.g., conj is, but drop isn't
13:27Chouserhm
13:27ChouserI'm under the impression that everything on vectors and maps is supposed to preserve metadata
13:27ataggartI know I can just look it up, but I thought there might have been some intention behind the choices that I wasn't aware of
13:29Chouserlists and seqs ... well I guess I'm not sure
13:30Chouserit does seem a bit odd that conj, pop, and next on a PersistentList all return PersistentLists, and conj keeps metadata but pop and next do not
13:31ataggartalso depends on the undelrying type
13:31ataggart,(:foo (meta (conj (with-meta '(1 2 3) {:foo "bar"}) 4)))
13:31clojurebot"bar"
13:31ataggart,(:foo (meta (conj (with-meta [1 2 3] {:foo "bar"}) 4)))
13:31clojurebotnil
13:31ChouserI wouldn't expect fns that take a non-seq and return a seq (like drop) would transfer metadata from the coll to the seq
13:31ataggartbut drop does take a seq
13:31ataggartor am I totally bonkers
13:32Chouserwell, it *can* take a seq, but it can also take any other collection
13:32Chouser,(drop [1 2 3])
13:32clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: core$drop
13:32Chouser,(drop 2 [1 2 3])
13:32clojurebot(3)
13:32Chouservector in, seq out. I'd be pretty surprised if metadata came through that.
13:34ataggartthough conj is preserrving, depending on the original type
13:34Chouseron the other hand, I'm surprised that pop on a PersistentList loses the metadata. PL in, PL out, just like conj. I wonder if pop's behavior there is intentional.
13:34Chouserataggart: right
13:34ChouserI don't know if this is valid, but I tend to think of a seq as a series of things, and wouldn't expect the same metadata on all elements
13:35ataggartheh this is funny:
13:35ataggart(:foo (meta (conj (with-meta (seq [1 2 3]) {:foo "bar"}) 4)))
13:35ataggart,(:foo (meta (conj (with-meta (seq [1 2 3]) {:foo "bar"}) 4)))
13:35clojurebotnil
13:35Chouservs. collections like map, vector, and PersistentList where I tend to think of the collection as stable and the metadata applying to the whole thing
13:35ataggart,(:foo (meta (conj (with-meta (seq '(1 2 3)) {:foo "bar"}) 4)))
13:35clojurebot"bar"
13:35ataggartthough you can with-meta a seq
13:35ataggartas above
13:35Chouserhmph.
13:36ataggartwhich makes sense in the idealized abstract ... thing
13:36ataggartwhere functions might only care about seqiness
13:37ataggartmaybe this is just an area for improvement ;)
13:37Chouser,^(next (cons 1 '#^{:my :meta} (2 3 4)))
13:37clojurebot{:my :meta}
13:37Chouserthere metadata is kept on the individual cell of the persistentlist
13:37ataggartaha! I was lookig for that with-meta reader macro
13:38Chouserit's not exactly the same as with-meta
13:38ataggartorly?
13:38Chouserit applies metadata to the form read by the reader and passed to the compiler
13:39Chouserwith-meta happens at runtime and applies to the collection at that point
13:40Chouser,(meta #^{:my :meta} (conj [1 2] 3))
13:40clojurebotnil
13:40Chouser,(meta (with-meta (conj [1 2] 3) {:my :meta}))
13:40clojurebot{:my :meta}
13:40ataggarthm, still not grokking why that's different
13:41Chouserin the first example, the *form* (conj ...) has metadata. Could provide a line number, type hint, etc. In this case, the compiler doesn't know what to do with :my and it gets thrown away
13:41ataggartoh is that first one appplying the metadata to the conj, and not the result of the conj?
13:41Chouserright
13:41ataggartexcellent
13:42Chouser,(meta #^{:my :meta} [1 2 3])
13:42clojurebot{:my :meta}
13:42ataggart,^(next (cons 1 '#^{:my :meta} [2 3 4]))
13:42clojurebotnil
13:42Chouserbut in the case of a literal collection like this, the compiler transfers the metadata from the read form onto the resulting collection
13:43ataggart,^(next (cons 1 '#^{:my :meta} (seq [2 3 4])))
13:43clojurebot{:my :meta}
13:43Chouserright! because 'next' on a vector returns a seq -- a different thing
13:44Chouserbut next on a seq returns a list returns a list, and the metadata is kept per-cell on a list
13:44Chouserbut next on a list returns a list, and the metadata is kept per-cell on a list
13:46Chouserbut the mental model I'm defending here doesn't explain pop (or next) on a list, so either there's a bug or I'm just wrong.
13:47ataggartletting this all marinade
13:47Chouserhm
13:47Chouseractually, list in general is a bit confusing
13:48Chouserconj on a list preserves metadata, cons does not?
13:48Chouseroh, cons on a list returns a Cons not a PersistentList
13:49danlarkin+1 for metadata review
13:49ataggart,^(conj '#^{:my :meta} '(1 2 3) 4)
13:49clojurebot{:my :meta}
13:49ataggart,^(butlast '#^{:my :meta} '(1 2 3) )
13:49clojurebotnil
13:49ataggartI'm guessing butlast has the same issue drop does
13:51ataggartthis is coming up for me because I''m splitting a url up into its segments via re-split, then adding meta-data to that seq, but the later manipulating that seq
13:51ataggartusing butlast
13:51ChouserI use PersistentLists so rarely for data in Clojure.
13:53ataggartthis is the problem I have:
13:53Chousergah. pop on vector also loses metadata
13:53Chouserthat can't be right
13:53ataggart^(butlast (with-meta (re-split #"/" "foo/bar/baz") {:my :meta}))
13:54ataggart,^(butlast (with-meta (re-split #"/" "foo/bar/baz") {:my :meta}))
13:54clojurebotjava.lang.Exception: Unable to resolve symbol: re-split in this context
13:54ataggartd'oh
13:54ataggartwell that woudl output nil
13:54Chouseryeah, I'm with you
13:54ChouserI don't know if butlast or drop-last should preserve metadata or not
13:55ataggartso I've been doing stuff like (with-meta (butlast orig-seq) {meta orig-seq))
13:55Chouserbut I would be shocked if pop losing metadata on vectors is intentional
13:55ataggartpop is next, right?
13:55Chouserno
13:55ataggartoh
13:55ataggartioening the src
13:55Chouserit is for lists, but for vectors and queues it pops off the right
13:55ataggart*opening
13:55ataggartah yeah
13:55Chouser,(pop [1 2 3 4])
13:55clojurebot[1 2 3]
13:56Chouserso that would be ideal for you case
13:56Chousera thing the naturally grows and shrinks on the right
13:56Chouserbut is walked left-to-right
13:56ataggart,(pop (take 3 (iterate inc 1)))
13:56clojurebotjava.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IPersistentStack
13:56Chouserit's a vector. And most modifications to a vector preserve metadata (conj, assoc)
13:57ataggartso I'd need to turn the seq from re-split into a vector...
13:57ataggartsmells funny
13:57Chousernah, that's common
13:57Chouserre-split doesn't know what you're going to do. And it can be lazy (though I don't think it is).
13:57Chouserso a seq is a natural return type
13:58Chouserbut you don't care about lazy and want to treat it as a vector. that's exactly what 'vec' is for
13:58ataggarthmm fair point
13:58Chouser*but* the only way I know to drop an item off the end of a vector is 'pop'
13:58Chouserand that still loses your metadata. :-P
13:58ataggartbutlast works fine except for the losing of metadata
13:58ataggartheh
13:59Chouserright, but butlast is O(n) and more importantly an argument could be made that it should not preserve metadata.
13:59Chousermaybe. I dunno.
14:00ataggartthe O(n) is a good point
14:00ataggartya, swithcing to vectors
14:00Chouservec is O(n) but it would happen once and then you can pop/conj in O(1) as needed
14:00ataggartregardless of the metadata issue
14:00ataggartright
14:01Chouserand I'm haveing a very hard time imagining the argument for dropping metadata on vector pop
14:01ataggartmaybe Rich can clarify the rules for when manipulation functions should be meta-data preserving
14:01Chouserunless there's some other fn for dropping off the last item of a vector. I can't think of one.
14:01ataggartpop sounds right
14:02Chouserhuh
14:02Chouseroh
14:03ataggartthis is all coming up because I'm porting (sort-of) a rest framework I originally wrote in java. got tired of just toying with clojure.
14:03ataggartREST, not '(rest ) :)
14:04Chouser:-)
14:04Chouser,^(pop (with-meta (conj [1 2 3] 4) {:my :meta}))
14:04clojurebot{:my :meta}
14:04Chouser,^(pop (with-meta [1 2 3 4] {:my :meta}))
14:04clojurebotnil
14:04Chouserit's a bug
14:04Chouser,(class (with-meta [1 2 3 4] {:my :meta}))
14:04clojurebotclojure.lang.LazilyPersistentVector
14:05ataggartah finally a good excuse to register with assembla
14:05Chouserthe metadata gets lost in the transition from LazilyPersistentVector to PersistentVector
14:10ataggartdo we need to send in a CA in order to be able to post tickets in assembla?
14:11ataggartwell, sicne I'd also want to try writing a patch, I guess so. nvm
14:13Chousukeyou can use the "support" thing to report a bug I think.
14:14Chousukebut you need to be a project member to have full access to the ticket system, and that requires a CA
14:14ataggartyup, I'll do the CA thing once I have access to a printer
14:14ataggartand stamps
14:21ataggartchouser: btw thanks for the help
14:22Chouserataggart: sure. I'd still be pleased to have a high-level description from rhickey about when metadata should be preserved vs. not
14:24cemerickshouldn't all objects be able to support metadata in JDK7?
14:24cemerick(totally orthogonal to the preservation issue)
14:24Chousercemerick: how? got a link?
14:24cemerickChouser: well, invokedynamic allows for method injection, or so I thought.
14:25Chouserhuh. like add a method to Integer that ... closes over a variable that points to the metadata?
14:26technomancythat's the first I've heard of invokedynamic supporting something like that
14:26cemerickright...totally naievely, I'd think with-meta would just swap out another meta method
14:26technomancyRich seemed to imply that it's mostly for supporting dynamic OOP on the JVM
14:27danlarkinI think it's to aid in languages where foo.bar might mean "get instance variable bar" or "call instance method var"... or something
14:27danlarkins/var/bar
14:27cemericksorry, the terminology is "interface injection": http://challenge.openjdk.org/projects/mlvm/subprojects.html
14:27cemericknot technically part of invokedynamic, but still part of JSR292
14:29Chouserseems like a stretch to me
14:29Chouserdoesn't sound like it would let you change the class of an existing object
14:29Chouserhm
14:29cemerickChouser: no need to change the class -- just adding the IMeta interface is enough.
14:30Chouserno, you need a place to store the meta value
14:30cemerickright, so the method that is injected along with the interface would just be a thunk that closed over the meta value
14:31Chouserbut now you're talking about a new method per instance
14:31technomancycemerick: that's pretty awesome
14:31cemerick*shrug* Better than not having any metadata on java.lang.Objects at all.
14:31Chouserand classes like Integer are final -- could you still inject a method?
14:32cemerickthat I don't know. I *think* so, as I don't think there's anything special about a final class (e.g. the final keyword is for javac's benefit...?)
14:33cemerickalternatively, there could be a single meta() method that looked up the meta value in a global WeakHashMap (if you were worried about creating a meta method per instance)
14:33hiredmancemerick: if that was true then you could just use the asm library to generate your own bytecode that ignores final
14:33ataggartyes final is for the compiler, and hotspot
14:34ataggartthats why you can change final fields via reflection
14:34hiredmanfinal means different things in different places
14:34cemerickhiredman: I'm always on shaky ground w.r.t. final and bytecode issues.
14:34Chouseryou could use WeakHashMap today
14:35Chouserjust have meta and with-meta fns use that instead of (or in addition to) .meta() and .withMeta() methods.
14:35cemerickChouser: right, but I presume Rich wouldn't put a big honking switch in the meta fn.
14:36ChouserI think his resistance would actually be more toward the WeakHashMap -- he's actually got plenty of bit switches.
14:37cemerickwell, who knows, maybe pushing a new method into an object on every with-meta will end up being cheap :-)
14:37Chouserwe can hope!
14:38hiredmanthat would be rather down the line I imagine
14:38Chousukehttp://blogs.sun.com/jrose/entry/interface_injection_in_the_vm reading this, it seems it would be done for classes, not objects.
14:38hiredman(since clojure targets java 5)
14:39cemerickhiredman: I think we're going to see some conditional execution macros and a lot of bifurcation as soon as invokedynamic is available (perhaps as an option in a JDK 6 update)
14:39ChouserChousuke: anything about field injection there? :-)
14:40hiredmancemerick: I remain skeptical
14:40Chouserbifurcation of .. the clojure sources?
14:40cemerickChouser: no, just different code paths for invokedynamic
14:40Chouseroh
14:42cemerickChouser: John Rose indicates that traits are a core use case for interface injection, so yeah, injecting fields is on the table
14:42cemericke.g. an IMeta trait
14:42cemerick(which carries a meta field)
14:43Chouserclojure.test confuses me
14:43Chouseroh...
14:50ataggartis there a way to add doc to a defstruct?
14:56Chouser(defstruct #^{:doc "this is foo"} foo :a :b)
14:57ChousukeMaybe I should bookmark this JRose blog :)
14:57Chousukefun stuff
14:58ChousukeAlso, the JVM apparently has an interesting method to check for null pointer derefs.
14:59eyerisIs there a standard function in the api for flattening a list?
15:00Chousukebasically, it assumes that they don't happen doesn't do any checking (probably not true for some cases, but anyway). Instead, it traps them when they happen, recovers, and recompiles the code at runtime to include a null check :P
15:00hiredmancute
15:00Chousuke+and
15:00Chousukeeyeris: there is flatten in contrib
15:01eyerisThanks
15:03cemerickChousuke: yeah, I've subscribed jrose's blog :-)
15:04cemerickLet's hope he stays hale, hearty, and healthy. Quite a positive voice in the jvm circus.
15:05ataggartchouser: yup that did it. thanks.
15:06Chouserataggart: so you're planning on filing a bug, sending in a CA, and writing a patch, right?
15:07ataggartI woudl but it'll take me a few days to get to a printer. feel free to open it in the meantime.
15:07Chousukehmm
15:08Chousuke,(remove coll? (tree-seq coll? seq [[1] {1 2} [2 [5 4]] 3]))
15:08clojurebot(1 1 2 2 5 4 3)
15:08Chouserataggart: I wouldn't want reduce your incentive to register and contribute. :-)_
15:08ChouserChousuke: nice!
15:09ataggarthehe fair enough, just didn't want to hold you up.
15:11Chouserataggart: you don't need a CA to file an assembla ticket, though. Just use the Support tab
15:11ataggartah excellent. doing it now.
15:14ChousukeI have to say, searchable menu entries in OS X Cocoa apps are sheer genius.
15:14fffejwith the latest release, i'm having a little problem using zip_filter.clj. I get this message "descendants already refers to: #'clojure.core/descendants in namespace" - any ideas? I see in the source it is excluding descendants, so I'm a little confused
15:15Chouserfffej: you're doing (use 'clojure.contrib.zip-filter) ?
15:15ChousukeI wasn't able to find the menu item for adding an RSS feed in mail but then I remembered the help system, wrote "add rss" into it and it instantly showed me what I wanted <3
15:15fffejchouser: I'm doing (ns mynamespace (:use [clojure.contrib.zip-filter]))
15:16ChouserTry (:require [clojure.contrib.zip-filter :as zf]), then use zf/descendents or whatever
15:16cemerickChousuke: whoa, I had *no* idea Mail could consume RSS!
15:16Chousukecemerick: heh
15:17fffejchouser: thanks, that works
15:17texodusHow can I determine if a something is an array?
15:18Chousertexodus: are you sure you want to be using an array? If you're trying to determine membership, usually a set or map works better.
15:18texodusyes, im positive - im writing a specific Writer proxy that needs to dispatch differently on byte arrays
15:19ozzileeChouser: Submitted a patch for lazy-xml. Pretty simple, unless I missed something.
15:19texodusso, proxy to a defmulti - but then how to determine an array ...
15:19texodus,(class (to-array [1 2 3]))
15:19clojurebot[Ljava.lang.Object;
15:20texodus,(= (class (to-array [1 2 3])) [Ljava.lang.Object)
15:20clojurebotUnmatched delimiter: )
15:20texodusclearly doesnt work
15:20ataggart,(Class/isArray (class (to-array [1 2 3])))
15:20clojurebotjava.lang.IllegalArgumentException: No matching method: isArray
15:20Chouser,(some #{(byte 2)} (into-array Byte/TYPE (map byte [1 2 3])))
15:20clojurebot2
15:20ataggarthmm
15:21ataggart,(.isArray (class (to-array [1 2 3])))
15:21clojurebottrue
15:21hiredman!
15:21clojurebotCLABANGO!
15:21hiredmanbeat me to it
15:21ataggartlol
15:21texodus,(. (class (to-array [1 2 3])) isArray)
15:21clojurebottrue
15:21texodusbingo
15:21texodusthanks alot
15:22Chouserwow, I completely misread the question
15:22eyerisI am taking a first stab at writing a macro. I have a seq of bindings I want, but (let) wants a vector. How can I create a vector from that seq?
15:23hiredmanvec
15:23ChouserI had an extra "in" in there. "if a something is in an array"
15:23ataggart,(vec (seq [1 2 3[))
15:23clojurebotUnmatched delimiter: )
15:23ataggart,(vec (seq [1 2 3]))
15:23clojurebot[1 2 3]
15:23hiredmanor just pass a vector
15:23hiredmanlike most other bindings
15:25Chouserozzilee: thanks! BTW, issues have moved to assembla, and code to github. See http://clojure.org/patches
15:26ozzileeChouser: Oh, contrib too? Neato.
15:26Chouseryep. We're trying to create as long a list of out-of-date project hosting services as possible
15:26ozzileeChouser: Heh no kidding :-)
15:27eyerisIs %1 valid inside (fn) as it is inside #()?
15:27Chousereyeris: no
15:27Chousuke,((fn [] %1))
15:27clojurebotarg literal not in #()
15:27Chousuke,((fn [] %))
15:27clojurebotarg literal not in #()
15:27Chouseralthough the error case has changed a bit recently
15:28Chousukehmm
15:28Chousukeold clojure? :P
15:28Chousukeshould simply be an unresolved symbol.
15:28Chouserright, to support :post
15:28eyerisIs there a compliment for (keyword)?
15:29hiredman:post?
15:29hiredmaneyeris: name
15:30ataggart,*clojure-version*
15:30clojurebot{:interim true, :major 1, :minor 1, :incremental 0, :qualifier "alpha"}
15:30Chouserhiredman: ((fn [] {:post [(= % 5)]} 6)) ==> java.lang.Exception: Assert failed: (= % 5)
15:30Chouserwow, that's a whole lot of parens
15:31hiredmanChouser: oooooo
15:31Chouserand various other grouping chars
15:31hiredmanno :pre yet?
15:31Chouser:pre is there too, but doesn't need %
15:31hiredmanah
15:38eyerisIs :as not allowed in the defn arg list?
15:38Chouserright.
15:40Chouser,(let [foo (fn [& [a b :as all]] [a b all])] (foo 1 2 3))
15:40clojurebot[1 2 (1 2 3)]
15:40Chouserbut you can do that, I suppose
15:41eyerisYeah, I've been using it in let/
15:42Chousersure, but you see I'm doing it in fn args there, just destructuring the "rest" part
15:42eyerisOh, you mean I could do (def foo (fn... and use the destructuring there
15:42Chouseror just (defn foo [& [a b :as all]] [a b all])
15:45eyerisI see. I tried that, but I was doing it wrong :/
15:45Chousernested destructuring can get a bit convoluted
15:46eyerisI am using it with a nested map, so I was trying (defn foo [& {{:keys [a b]} :sub-map} :as my-map] ...)
15:46eyerisBut it shoudl be (defn foo [& {{:keys [a b]} :sub-map :as my-map}] ...)
15:50zakwilsonI'm trying to decide between Haskell and Clojure for a project. I know Clojure better, but Haskell seems like it will make FRP easier and I intend to make fairly heavy use of that.
16:04ataggartchouser: what clojure implementation code were you looking at when we were talking about pop and meta-data?
16:04ataggartI haven't quite grokked how to get from clj function defs in clojure.core over to clojure java
16:05hiredmanataggart: when you see a java method call
16:05ataggartI'm referring to clojure's java implementation
16:05ataggarte.g., where pop, conj, etc are implemented
16:06hiredmanyeah
16:06hiredman~def pop
16:06hiredmanso you look at the pop method in the RT class
16:07hiredman~def c.l.RT
16:07ataggartyes, but chris was referring to something earlier andni'm trying to find out exactly what he was looking at
16:08ataggartin order to write a bugfix patch
16:08hiredmanoh
16:08hiredmanpardon
16:08ataggartnp, I should have been more clear
16:10guille_hi there
16:18ataggarthow does one add further comments on a ticket in assembla?
16:19ataggarthmm must be because I'm not CA'd yet
16:20guille_if i'm implementing a interface in a single file, should I use the last name of the namespace (using same convention as java), that's the interface name, or the whole package name in :name too?
16:24ataggartchouser: I figured it out. pop is meta-data preserving, but it's just that we see the meta-data associated with that sublist, which in the example is nil.
16:25ataggart,(meta (pop (conj (with-meta '(1 2 3) {:my :meta}) 4)))
16:25clojurebot{:my :meta}
16:27ataggart,(meta (pop (with-meta '(1 2 3) {:my :meta})))
16:27clojurebotnil
16:27ataggartbecause (meta '(1 2)) is nil
16:28ataggartso ticket #149 should probably be marked as invalid
16:42eyerisWill someone here help me figure out where I am going wrong with this macro? http://pastebin.ca/1491100
16:44eyerisIf I load it into the repl and use macroexpand, it just prints out the input, without any expansion.
16:44eyerisThat must be a sign that I've used defmacro incorrectly, but I can't figure out how
16:46Chousukehm
16:47eyerisThe (one) and (two) in the example usage are incorrect, but that isn't what the exception refers to.
16:49Chousukeyou can't pass runtime values to a macro
16:49Chousukeyou need to call it as (with-map-bindings {:one 1 :two 2} (+ one two))
16:50eyerisI see.
16:51eyerisIs there a way to pass a runtime vector to let instead of a literal vector, so that I could write that macro as a fn?
16:51Chousukea macro is a function that takes clojure code as its parameters, and does not evaluate them; so, in your example, you're passing it a plain symbol :)
16:51Chousukethat would require eval I think.
16:52Chousukebut... are you sure you need to do that at all?
16:52eyerisI don't *need* to, but I'd sure like to.
16:52eyerisI have a map that has 6 keys, my function uses all of them.
16:52Chousukein which case would you need to pass a binding vector to let at runtime?
16:53eyerisI could use :keys [...], but that just feels overly verbose when I am binding them all
16:53Chousukehmm
16:53eyerisIt also is misleading to me, because when I see :keys [...] I instinctively look at what *isn't* bound from the map
16:54Chousukewill simple-map be static?
16:54eyerisNo
16:54Chousukehm.
16:55ChousukeI still don't get your use case though. :/
16:56Chousukeyou can't bind locals based on runtime values, unless you also generate the code at runtime and use eval
16:56Chousukeand that's not what you want to do.
16:57eyerisOh, wait.
16:57eyerisThe keys in my map will be static.
16:57eyerisThe values will change though.
16:57Chousukein that case there's no problem
16:59eyerisI just have to use this map in a lot of functions, so I'd like to write a function or macro that binds the keys to local symbols so that I don't have to write out the destructuring for every function
17:00Chousukejust write (defmacro defspecialfn [& body] `(let [{:keys ~'[your keys here]} *the-global-map*] ~@body))
17:00Chousukeassuming *the-global-map* will be bound with (binding ...) here.
17:01Chousukeotherwise, it *would* be static and the values would not be changing :)
17:02eyerisOkay
17:02eyerisI think I understand that.
17:02Chousukealternatively, it could be a ref
17:02Chousukein which case you'd want to do:
17:02Chousukejust write (defmacro defspecialfn [& body] `(let [{:keys ~'[your keys here]} (deref *the-global-map*)] ~@body))
17:03Chousukeforgot to remove the just write.
17:04Chousukenote the funky ~' unquote thing there. that needs to be used so that let won't complain about binding to qualified names.
17:04Chousukeit also serves as documentation to the reader that the macro introduces local names implicitly.
17:05eyerisI think this is one step removed from what I want to do.
17:05eyerisThe map I am using is always passed into the function. I don't rebind the global symbol to update the values.
17:07Chousukewell, in that case you can add the map name as a parameter to the defspecialfn macro
17:08eyerisAnd, inside the function, that would be a local symbol just like a normal function parameter?
17:08Chousuke(defmacro defspecialblock [mname & body] `(let [{:keys ~'[your keys here]} ~mname] ~@body))
17:08Chousukethen (defspecialblock *global-map* (do-stuff using your keys))
17:08eyerishttp://pastebin.ca/1491131
17:09eyerisThat is what I am doing
17:09eyeris(dispatcher) returns the next function to pass the state map into
17:10eyeristhat function returns the next map to bind to the state symbol
17:10eyerisrepeat
17:11Chousukeinvestigate the macroexpansions of these functions, you'll see what kind of code they produce :)
17:16eyerisWhere does the name of the special block go?
17:16Chousukewell, that above thing doesn't actually define a function.
17:16Chousukejust a let block
17:16Chousukebut you could easily extend it to a defn
17:19eyerisThis still doesn't make sense, because I can't call it from inside my state loop, because I don't have a symbol for the map outside the state loop
17:20eyeriscan't call it = can't call the special fn defined by the macro
17:20Chousukeit doesn't define a fn :P
17:21eyerisif does if I make if (defspecialfn [fname mname & body] (defn fname `(let ...
17:22eyerisWait a minute
17:22eyerisI think I got something
17:23Chousukethe ` should go before defn, not let.
17:25Chousukehttp://pastebin.ca/1491144
17:25ChousukeI used [] around map-name because giving the binding in a vector to the macro is more idiomatic
17:30eyerisI want the map symbol inside the generated fn to always be the same
17:31eyerisRemoving map-name from the defmacro parameters and then removing the ~ from before each use of it yields an exception though
17:32Chousukewell, of course.
17:32eyerisWhy?
17:32Chousukebecause it's passed to defn as the parameter name
17:32Chousukeand inside ` it becomes qualified, and qualified names can't be used to bind to.
17:33Chousukeif you want to force the name, do ~'whatever
17:34eyerisThis whole "the macro language is the language" is bs
17:34Chousukehm?
17:34Chousukeno it's not.
17:34Chousukea macro must return a data structure.
17:34Chousukewhich is clojure code.
17:34eyerisbut it must do so using different evaluation rules
17:35Chousukenot really. the only differing thing is that macro parameters are not evaluated
17:35Chousukeotherwise a macro is a normal function
17:35Chousukeit may look different because of `(foo bar whatever
17:36Chousukebut syntax-quote is not restricted to macros
17:36Chousuke,(let [x 1] `(foo bar x ~x))
17:36clojurebot(sandbox/foo sandbox/bar sandbox/x 1)
17:37Chousukeyou could write every macro without syntax quoting
17:38eyerishttp://pastebin.ca/1491155
17:38eyerisWhy is that wrong?
17:38Chousuke(defmacro [x] (list 'clojure.core/+ x x)) <- equivalent to (defmacro [x] `(+ ~x ~x))
17:39hiredmaneyeris: map-name is not specified anywhere
17:39eyerisRight, so I have to use 'map-name
17:40Chousuke~'map-name
17:40clojurebotmap is *LAZY*
17:40Chousuke:P
17:40eyerisChousuke so what does ~'map-name evaluate to?
17:40Chousukeif you do 'map-name, you will see (quote user/map-name) in the expansion
17:40hiredmaneyeris: 'map-name
17:40Chousukeeyeris: just the symbol map-name
17:40hiredman~ is unsyntax quote and ' is quote
17:40clojurebotAlles klar
17:41hiredmanerp
17:41Chousukeeyeris: in other lisps, you'd just write "map-name" without the unquote-quote thing.
17:41Chousukeeyeris: but in clojure, map-name will be qualified in that case, and you can't bind to qualified names
17:41ataggarteyeris: are you just trying to reimplement (binding [...] ...)?
17:42Chousuketo get around this, you unquote a quoted, plain symbol. thus the result is the plain symbol
17:43Chousukecompare:
17:43Chousuke,`sym
17:43clojurebotsandbox/sym
17:43Chousuke,`~sym
17:43clojurebotjava.lang.Exception: Unable to resolve symbol: sym in this context
17:43Chousuke,`~'sym
17:43clojurebotsym
17:43eyerisI get that part
17:44eyerisbut you syntax quote the macro to prevent evaluation, right?
17:44Chousukeno
17:44Chousukethe evaluation is already prevented by the macro expansion.
17:44hiredmanChousuke: you kinda do
17:45Chousukewell, hm.
17:46hiredmanyou quote the form the form you want to be the result of the macro
17:46hiredmanand you use syntax quote because you want all its snazzy features
17:47eyerisYeah, but that form is unevaluated until it is called
17:47hiredman
17:47eyerise.g. the defn isn't evaluated before defmacro returns
17:47Chousukeeyeris: no.
17:48Chousukewell, in a way yes.
17:48Chousukebut there's a more fundamental point.
17:48Chousukeeyeris: the macro, when called, *returns* the defn form
17:48Chousukeas a value
17:48Chousukeand then the compiler calls eval on it.
17:48eyerisRight
17:49eyerisNormally, to prevent the evaluation of a symbol, you quote it, right?
17:49eyeris(let [x 1] 'x) returns the symbol x
17:49eyerisbut (let [x 1] x) returns 1
17:50eyeriss/returns/evaluates to/
17:50Chousukeyou can also try the following in a repl: (defn f [x] (println x) x) (defmacro m [x] (println x) x) and try (f (+ 1 1)) (m (+ 1 1))
17:51Chousukethe former will print 2 and return 2, the latter will print (+ 1 1) and return 2
17:51Chousuke(because of the implicit eval)
17:52eyerisRight, but inside defmacro, x is not resolved when it is an argument to println
17:52Chousukeafter that, you can try using syntax-quote on x in both the macro and the function
17:52eyeriswhereas outside defmacro, it would be
17:53Chousukeyes it is resolved.
17:53Chousukeit's just that its value is '(+ 1 1)
17:53Chousukenot 2, like in the function
17:53eyeriserm
17:54eyerisI misspoke
17:54eyerisit is not evaluated
17:55Chousukeyes.
17:56Chousukeor to make it painfully clear, x is evaluated inside the macro, but when you pass in arguments to the macro, the arguments are not evaluated, and thus the value of x becomes the literal list '(+ 1 1)
17:57Chousukein a similar way, the local x is evaluated inside a function, but also the arguments you pass to the function are evaluated; and (+ 1 1) evaluates to 2, so the value of x becomes 2
17:58eyerisOkay
17:59eyerisSo
17:59eyerisSo 'x in a fn evals to the symbols x.
18:00Chousukeyes.
18:00eyerisSo what does 'x eval to inside a macro?
18:00Chousukethe same as in a function.
18:00Chousuketo the symbol x
18:01eyerisSo the syntax-quote function is doing the namespace resolution?
18:01Chousukeyes.
18:01eyerisWhy? What problem does that solve?
18:01Chousukehygiene
18:02Chousukeit's more difficult to accidentally introduce names
18:02Chousukethat could shadow names in other code.
18:02Chousukevery useful for macros, which is why ` is very popular when writing them
18:02Chousukebut ` is not restricted to macros
18:03Chousuke,((fn [x] `(x :is ~x :unqualified ~'x)) 5)
18:03clojurebot(sandbox/x :is 5 :unqualified x)
18:04eyerisSo I can write macros without `?
18:04Chousukesure.
18:05Chousuke(defmacro add-to-y [x] (list '+ x 'y))
18:05Chousukenext (def y 3); (add-to-y 4) -> 7
18:06Chousukebecause the macro will return '(+ 4 y) which is 7 when evaluated in that context
18:09Chousukethe problem comes when you do something like : (defmacro eval-with-y [code] (list 'let '[y 5] code)); (def y 1) (eval-with-y (+ y 10)) -> 15
18:10Chousukehowever, if you do (list 'let `[y 5] ...), you will get an exception
18:10Chousukebecause y is qualified and let does not like that.
18:11Chousukeso you won't mistakenly override names in the context.
18:12eyerisIs there a contrib that function as syntax quote without the ns resolution?
18:12Chousukeno.
18:13Chousukebut as show, you can override syntax-quote's ns resolution by prefixing the symbol you want to be bare with ~'
18:13eyerisI get that.
18:13eyerisThat is just plain not intuitive for me.
18:14Chousukewell, it's not supposed to be :)
18:14eyeris' = quote
18:14eyeris~ = unquote
18:14clojurebotExcuse me?
18:14Chousukeyeah
18:14eyerisreversing something should yield the same thing
18:14eyeriserm
18:14Chousukeand when you quote a symbol, and unquote it, you get the symbol back.
18:14eyeris(inc (dec 1)) == 1
18:15Chousukebut see
18:15Chousuke,`'y
18:15clojurebot(quote sandbox/y)
18:15eyerisRight, but if ~'x evaluates to x, why doesn't it get resolved?
18:15Chousukehmm
18:15Chousuke,`~'y
18:15clojureboty
18:15eyerisSee
18:15eyerisit's different
18:16Chousuke,`~'sandbox/y
18:16clojurebotsandbox/y
18:16Chousuke(quote sandbox/y)
18:16Chousuke,(quote sandbox/y)
18:16clojurebotsandbox/y
18:17Chousukewell, you can just take this behaviour for granted now :)
18:17Chousukeit's useful.
18:18Chousukeit *is* a bit funky though.
18:18clojurebot0
18:19Chousukebut you can think of it as unquoting a quoted form yielding the same form.
18:20eyerisIt seems to me that syntax-quote must do resolution before any evaluation and simply doesn't recurse into an unquote form
18:21Chousukepossibly.
18:21Chousukesyntax-quote is a special thing implemented in java, after all
18:21Chousukeit has some special semantics.
18:22Chousukebut it's undeniably useful, and not at all that difficult after you understand how it works.
18:22eyerisFor Symbols, syntax-quote resolves the symbol in the current context, yielding a fully-qualified symbol (i.e. namespace/name or fully.qualified.Classname).
18:23eyerisThat should be followed by "except when preceded by ~'" or something more complete.
18:24eyerisThanks for your help
18:24eyerisI'll need a lot more practice, but it's a start
18:28ataggartrule 1 of macros: don't write macros.
18:29Chousersuch a good rule.
19:09ataggartchouser: did you see my comments from earlier regarding pop?
19:17ChouserI hadn't. But yes, I guess I was failing to describe it.
19:17Chouserglad you figured it out anyway, though.
20:34newbiehi, i am iterating pixels on the screen using 2 doseq loops one for x one for y then i cam doing some calculations on the pixels i end up with some valid pixels how can i return a vector of pixels?
20:35hiredmannewbie: use for
20:37newbiebut how can i create a vector and add on it like in loop?
20:38hiredmanvectors can be created with the literal [] or the function vec, or vector
20:40newbieyeah but vector is not persisted between iterations so i can add on it
20:41hiredmanif you are looping, you can rebind names in the loop
20:42hiredman,(loop [foo 0 r []] (if (= foo 5) r (recur (inc foo) (conj r foo))))
20:42clojurebot[0 1 2 3 4]
20:42newbieno thats why i am asking is there a way to achive the same effect while using doseq
20:42hiredmandoseq is for side effects
20:44newbieso loop inside loop is my only choice? to iterate x,y coordinates?
20:45hiredmanfor
20:46hiredman,(vec (for [x (range 10) y (range 10)] [x y]))
20:46clojurebot[[0 0] [0 1] [0 2] [0 3] [0 4] [0 5] [0 6] [0 7] [0 8] [0 9] [1 0] [1 1] [1 2] [1 3] [1 4] [1 5] [1 6] [1 7] [1 8] [1 9] [2 0] [2 1] [2 2] [2 3] [2 4] [2 5] [2 6] [2 7] [2 8] [2 9] [3 0] [3 1] [3 2] [3 3] [3 4] [3 5] [3 6] [3 7] [3 8] [3 9] [4 0] [4 1] [4 2] [4 3] [4 4] [4 5] [4 6] [4 7] [4 8] [4 9] [5 0] [5 1] [5 2] [5 3] [5 4] [5 5] [5 6] [5 7] [5 8] [5 9] [6 0] [6 1] [6 2] [6 3] [6 4] [6 5] [6 6] [6 7] [6 8] [6 9] [7 0
20:56newbiethanks that solved it.
21:11Rayneshiredman: Why is :state necessary? The only times I've seen it used are by clojure-generated classes that extend Java classes. http://www.fatvat.co.uk/2009/05/clojure-and-robocode.html being one example. It looks to me like :state could be replaced with any ol' ref.
21:11hiredmanRaynes: it generally is a ref
21:12RaynesI know, but what is the point of it? I'm not really sure why it's needed.
21:12hiredmanthe key point is the is a state per instance
21:13RaynesSo it's primarily for Clojure classes that will be instantiated by Java classes?
21:13RaynesWell, clojure-generated classes.
21:13hiredmanyes
21:14RaynesI've noticed that Stuart's example in Programming Clojure instantiated a Clojure-generated class inside the same Clojure-generated class. That blew my mind for a few minutes. :p
21:14RaynesThanks.
21:37KnekkI am looking for something new to read, related to CS/Programming, in case anyone wants to recommend something they've found enlightening or interesting.
21:37Knekkthanks
21:42gnuvinceKnekk: SICP?
21:42Knekkhttp://mitpress.mit.edu/sicp/?
21:43gnuvinceAye
21:43hiredmanclojurebot: delicious
21:43clojurebotdelicious is http://delicious.com/clojurebot
21:43Knekknice, didn't know about it. Thanks :)
21:44gnuvinceKnekk: as far as CS books go, this one is way high up there.
21:44Knekk$114 at amazon, free on the site. Yay
21:44Knekkhiredman: thanks
23:43flying_spaghettianyone can help with a noob question?
23:46fUDGreets
23:47flying_spaghettihail
23:50flying_spaghettii seek a clue
23:52Chousergo
23:54flying_spaghettiwell, i am learning clojure, writing a raytracer.. i want to know, is there an easy way to get a list representation of the content of a struct or vise versa
23:54flying_spaghettibecause i have, e.g. colour structures with members r, g, b, and sometimes it would be nice to apply the same operation to all of them using map
23:55flying_spaghettiand then convert the resulting list back into a colour structure
23:55flying_spaghettii am wondering if there is a generic means to do that
23:56texodus,(into {} (map (fn [[_ v]] (+ 1 v)) [1 2 3])
23:56clojurebotEOF while reading
23:57texodus,(into {} (map (fn [[_ v]] (+ 1 v)) [1 2 3]))
23:57clojurebotjava.lang.RuntimeException: java.lang.UnsupportedOperationException: nth not supported on this type: Integer
23:58flying_spaghettioh great thx i will try
23:58texodusoh right, struct
23:58texodus(into {} (map (fn [[_ v]] (+ 1 v)) {:1 1 :2 2 :3 3})
23:58texodus,(into {} (map (fn [[_ v]] (+ 1 v)) {:1 1 :2 2 :3 3})
23:58clojurebotEOF while reading
23:59texodus,(into {} (map (fn [[_ v]] (+ 1 v)) {:1 1 :2 2 :3 3}))
23:59clojurebotjava.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer