2009-07-10
| 02:03 | thearthur | (partition dropps partial blocks at the end. I need one that doesn't do that |
| 02:03 | thearthur | is this in contirb somewhere? |
| 02:04 | thearthur | ???? (partition 4 [1 2 3 4 5 6 7]) => ((1 2 3 4)) |
| 02:05 | thearthur | (my-partition 4 [1 2 3 4 5 6 7]) => ((1 2 3 4) (5 6 7)) |
| 02:10 | thearthur | nm found that partition can do this with its pas arg |
| 02:10 | thearthur | (partition 4 4 () [1 2 3 4 5 6 7]) |
| 02:24 | Raynes | Is there a predicate to check whether or not a sequence is empty? |
| 02:24 | arbscht_ | ,(empty? []) |
| 02:24 | clojurebot | true |
| 02:24 | Raynes | Thank you. :) |
| 02:27 | thearthur | (push and pop mention working on queues. how do i create a clojure.lang.PersistentQueue |
| 02:33 | mrpika | there doesn't appear to be a clojure wrapper for it |
| 02:34 | mrpika | you'd have to use it via java interop |
| 02:35 | mrpika | or conj |
| 02:35 | mrpika | http://markmail.org/message/brvozelsgmr5a3ba |
| 04:01 | thearthur | how do i undefine a var from the repl? |
| 04:01 | thearthur | dont want to reaload everything |
| 04:06 | Chousuke | ns-unmap should help |
| 04:12 | Raynes | Why would you need to undefine a var from the REPL? |
| 07:55 | Holcxjo` | 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:02 | Holcxjo` | 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:03 | Holcxjo` | I can do (import '(com.evernote.edam.userstore.UserStore)) but anything after that fails... |
| 08:03 | Holcxjo` | com.evernote.edam.userstore.UserStore/Client (. com.evernote.edam.userstore.UserStore Client) (com.evernote.edam.userstore.UserStore/Client. <some arg>) ... |
| 08:04 | Holcxjo` | Any ideas? |
| 08:04 | liebke | Holcxjo`: you access inner classes with $, e.g. Class$InnerClass |
| 08:04 | Holcxjo` | Oh! |
| 08:04 | liebke | yeah, not really obvious :) |
| 08:04 | Holcxjo` | Also not in the book I believe... |
| 08:05 | Holcxjo` | It's on http://clojure.org/java_interop if you know what the correct term (inner class) is... |
| 08:05 | Holcxjo` | thanks! |
| 08:06 | liebke | no problem :) |
| 09:52 | Raynes | I accidentially wrote a faster (apply max ..) :o |
| 10:08 | Chouser | I think they're making fun of us. http://lambda-the-ultimate.org/node/3488 |
| 10:15 | Chousuke | nah :) |
| 10:16 | cemerick | Chouser: I think they were aiming at NewLisp |
| 10:16 | Chouser | ah |
| 10:17 | liebke | yeah it doesn't look like it's aimed at clojure, read the paper (pdf) http://jfm3.org/phosphorous.pdf |
| 10:18 | Chouser | I guess it was the JVM comments that made me wonder |
| 10:18 | Chousuke | I like how their CamelCase convention extends to the paper as well. |
| 10:25 | cemerick | Chouser: JVM:lispers :: Microsoft:free-software-advocates |
| 10:25 | Chouser | heh |
| 10:37 | Raynes | Like parent's tell their children. "Don't mind them, they are only upset because you're so special!" |
| 10:41 | Chouser | does anyone have a link to the little outline about new-new plans? |
| 10:42 | cgrand | Chouser: http://www.assembla.com/wiki/show/clojure/New_new ? |
| 10:42 | Chouser | ah, yes. thanks! |
| 10:44 | achim` | oh, the NewLisp presentation has a nice font selection |
| 10:45 | achim` | does anybody happen to know the monospaced font? :) |
| 10:49 | lisppaste8 | ceninan pasted "macro/seq practice "dsl"" at http://paste.lisp.org/display/83369 |
| 10:49 | ceninan | I thought I'd learn some macro-fu by doing something that changes lisp semantics, and not just simple syntax "prettification" |
| 10:49 | ceninan | so I "designed" (lol) something that I thought would be interesting to implement |
| 10:50 | ceninan | anyone familiar with the Icon language? |
| 10:52 | cemerick | seems like assert should take an optional failure-msg arg |
| 10:52 | Chouser | cemerick: you're playing with assert? Have you seen the new pre/post conditions? |
| 10:52 | Chouser | ceninan: not me, sorry. |
| 10:54 | cemerick | Chouser: oh, no -- someone mentioned them to me, but I'd forgotten |
| 10:54 | cemerick | we're on v1.0 + patches for a while, though |
| 10:55 | Chouser | oh, ok. |
| 10:56 | cemerick | I suppose aggressively tracking head might be a good idea, but that'd take some CI work. |
| 10:57 | Chouser | I'm using 1.0 at work myself, but I also haven't touched our .clj code in a while. |
| 10:57 | cemerick | it's the only reasonable way to do things atm, but I do certainly loathe upgrade cycles. |
| 10:58 | lisppaste8 | ceninan annotated #83369 "untitled" at http://paste.lisp.org/display/83369#1 |
| 11:00 | Chouser | ceninan: it looks like you're mutating !tries in the middle there |
| 11:00 | ceninan | Chouser: that part isn't really correct |
| 11:01 | ceninan | the :! should have an optional let form |
| 11:01 | Chouser | ceninan: and some minor adjustments to your proposed syntax would make it much easier to implement |
| 11:01 | ceninan | I'm all ears :) |
| 11:01 | Chouser | looks like an interesting experiment |
| 11:01 | Chouser | well, macros are applied at compile time when the compiler sees a (macro-name ...) form |
| 11:03 | Chouser | so 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:03 | ceninan | is it possible to do a macro macro generator? |
| 11:03 | Chouser | ceninan: yes |
| 11:03 | ceninan | then there could be some sort of "def" for these types of "functions" |
| 11:04 | ceninan | correct? |
| 11:04 | Chouser | both the options I described are possible, but neither is particularly simple |
| 11:04 | Chouser | yes |
| 11:04 | Chouser | but writing such a macro is several steps removed from accomplishing your goal -- unless this specific syntax is your goal, I suppose. |
| 11:05 | ceninan | not really stuck on the syntax, no |
| 11:05 | ceninan | do you have a simpler proposal? |
| 11:05 | Chouser | if you instead wrapped another layer, maybe... (icon-step (integer? (read-line)) :<- ... :! ...) |
| 11:05 | Chouser | then you could define a single macro 'icon-step' that did your heavy-lifting. |
| 11:06 | ceninan | hmm, yes - that does sound like a more practical approach |
| 11:06 | Chouser | and 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:07 | ceninan | right :) |
| 11:07 | ceninan | thanks, hadn't thought of that |
| 11:07 | Chouser | as 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:08 | ceninan | and that leads to my next question :) |
| 11:08 | mccraig | Chouser: are pre/post conds described/exampled anywhere ? |
| 11:08 | ceninan | what would be a good structure for the "seq"? |
| 11:10 | mccraig | found a description : http://github.com/richhickey/clojure/commit/0ac482878a1dd520cbee2faa0f5f6ab1082ffa76 |
| 11:10 | Chouser | mccraig: sure! in the commit message. :-) |
| 11:10 | Chouser | there ya go |
| 11:13 | Chouser | ceninan: not sure -- seems like figuring that out is the task you've chosen for yourself. :-) |
| 11:14 | ceninan | well, that's true ;p |
| 11:14 | ceninan | thanks a lot for the help! |
| 11:15 | Chouser | I'm not quite sure I grok your syntax, but if you get stuck feel free to ask more. |
| 11:16 | ceninan | I'll try to figure it out without dealing with the syntax first :) |
| 11:16 | ceninan | thanks again |
| 11:18 | ceninan | (btw, they allow you to react to failure conditions; failure can have different causes, eg '=' have the fail conditions '>' and '<') |
| 11:18 | ceninan | (tbh, I don't really grok it myself yet ;)) |
| 11:19 | Chouser | ah! hm. |
| 11:20 | Chouser | that makes it sound more like a sort of cond applied to each element of the seq |
| 11:24 | ceninan | I'm entirely sure that I follow; the "fail conditions" primary purpose is to produce side effects or change local bindings |
| 11:25 | ceninan | they shouldn't escape to a parent operation |
| 11:25 | ceninan | but like some sort of (loop (cond)), yes |
| 11:26 | Chouser | I'll be fascinated to see what you come up with. :-) |
| 11:26 | ceninan | thanks :) |
| 11:28 | ozzilee | Chouser: 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:29 | Chouser | lazy-xml hasn't changed in ages |
| 11:29 | Chouser | ozzilee: you're talking about when emitting? |
| 11:30 | ozzilee | Chouser: Yeah. Something like {:tag :foo :content [5]} throws an NPE. |
| 11:31 | Chouser | ah. I don't think I'd noticed that. A contrib ticket and patch for that would be welcome. |
| 11:33 | ozzilee | Chouser: 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:34 | Chouser | a ticket without a patch would be fine too |
| 11:35 | ozzilee | Any recommendations on that front, btw? As far as a testing framework. Fact maybe? It's hard to keep up. |
| 11:35 | hiredman | test-is got moved into core |
| 11:35 | ozzilee | Chouser: Ok, I'll do a ticket now. |
| 11:43 | ozzilee | hiredman: That looks like it will work. Do you use it? |
| 11:43 | ozzilee | Chouser: Ticket submitted. |
| 11:43 | Chouser | ozzilee: thanks! |
| 11:44 | hiredman | ozzilee: nope |
| 11:45 | hiredman | I guess I could write tests for clojurebot |
| 11:45 | hiredman | bleh |
| 11:45 | Raynes | I wish I knew Java. :\ I might understand what this :state stuff is all about. |
| 11:45 | hiredman | Raynes: it creates a field where you can store state information |
| 11:46 | hiredman | generally a ref or a atom |
| 11:46 | Raynes | Oh, like a field in Java. |
| 11:46 | ozzilee | Raynes: Except you only get one per proxy object. |
| 11:46 | hiredman | eh? |
| 11:46 | hiredman | proxy has a .state? |
| 11:46 | Chouser | one per gen-class instance |
| 11:47 | Raynes | Works for me. :D |
| 11:47 | hiredman | yeah |
| 11:47 | ozzilee | Er, gen-class. Yeah. That's what I meant. |
| 12:34 | eyeris | When 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:38 | hiredman | (let [{:keys [a]} {:a 1}] a) |
| 12:38 | hiredman | ,(let [{:keys [a]} {:a 1}] a) |
| 12:38 | clojurebot | 1 |
| 12:41 | eyeris | Thanks |
| 13:26 | ataggart | does anyone have a clear sense of which datastructure manipulation functions are meta-data preserving? |
| 13:27 | ataggart | e.g., conj is, but drop isn't |
| 13:27 | Chouser | hm |
| 13:27 | Chouser | I'm under the impression that everything on vectors and maps is supposed to preserve metadata |
| 13:27 | ataggart | I 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:29 | Chouser | lists and seqs ... well I guess I'm not sure |
| 13:30 | Chouser | it 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:31 | ataggart | also depends on the undelrying type |
| 13:31 | ataggart | ,(:foo (meta (conj (with-meta '(1 2 3) {:foo "bar"}) 4))) |
| 13:31 | clojurebot | "bar" |
| 13:31 | ataggart | ,(:foo (meta (conj (with-meta [1 2 3] {:foo "bar"}) 4))) |
| 13:31 | clojurebot | nil |
| 13:31 | Chouser | I 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:31 | ataggart | but drop does take a seq |
| 13:31 | ataggart | or am I totally bonkers |
| 13:32 | Chouser | well, it *can* take a seq, but it can also take any other collection |
| 13:32 | Chouser | ,(drop [1 2 3]) |
| 13:32 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: core$drop |
| 13:32 | Chouser | ,(drop 2 [1 2 3]) |
| 13:32 | clojurebot | (3) |
| 13:32 | Chouser | vector in, seq out. I'd be pretty surprised if metadata came through that. |
| 13:34 | ataggart | though conj is preserrving, depending on the original type |
| 13:34 | Chouser | on 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:34 | Chouser | ataggart: right |
| 13:34 | Chouser | I 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:35 | ataggart | heh this is funny: |
| 13:35 | ataggart | (:foo (meta (conj (with-meta (seq [1 2 3]) {:foo "bar"}) 4))) |
| 13:35 | ataggart | ,(:foo (meta (conj (with-meta (seq [1 2 3]) {:foo "bar"}) 4))) |
| 13:35 | clojurebot | nil |
| 13:35 | Chouser | vs. 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:35 | ataggart | ,(:foo (meta (conj (with-meta (seq '(1 2 3)) {:foo "bar"}) 4))) |
| 13:35 | clojurebot | "bar" |
| 13:35 | ataggart | though you can with-meta a seq |
| 13:35 | ataggart | as above |
| 13:35 | Chouser | hmph. |
| 13:36 | ataggart | which makes sense in the idealized abstract ... thing |
| 13:36 | ataggart | where functions might only care about seqiness |
| 13:37 | ataggart | maybe this is just an area for improvement ;) |
| 13:37 | Chouser | ,^(next (cons 1 '#^{:my :meta} (2 3 4))) |
| 13:37 | clojurebot | {:my :meta} |
| 13:37 | Chouser | there metadata is kept on the individual cell of the persistentlist |
| 13:37 | ataggart | aha! I was lookig for that with-meta reader macro |
| 13:38 | Chouser | it's not exactly the same as with-meta |
| 13:38 | ataggart | orly? |
| 13:38 | Chouser | it applies metadata to the form read by the reader and passed to the compiler |
| 13:39 | Chouser | with-meta happens at runtime and applies to the collection at that point |
| 13:40 | Chouser | ,(meta #^{:my :meta} (conj [1 2] 3)) |
| 13:40 | clojurebot | nil |
| 13:40 | Chouser | ,(meta (with-meta (conj [1 2] 3) {:my :meta})) |
| 13:40 | clojurebot | {:my :meta} |
| 13:40 | ataggart | hm, still not grokking why that's different |
| 13:41 | Chouser | in 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:41 | ataggart | oh is that first one appplying the metadata to the conj, and not the result of the conj? |
| 13:41 | Chouser | right |
| 13:41 | ataggart | excellent |
| 13:42 | Chouser | ,(meta #^{:my :meta} [1 2 3]) |
| 13:42 | clojurebot | {:my :meta} |
| 13:42 | ataggart | ,^(next (cons 1 '#^{:my :meta} [2 3 4])) |
| 13:42 | clojurebot | nil |
| 13:42 | Chouser | but in the case of a literal collection like this, the compiler transfers the metadata from the read form onto the resulting collection |
| 13:43 | ataggart | ,^(next (cons 1 '#^{:my :meta} (seq [2 3 4]))) |
| 13:43 | clojurebot | {:my :meta} |
| 13:43 | Chouser | right! because 'next' on a vector returns a seq -- a different thing |
| 13:44 | Chouser | but next on a seq returns a list returns a list, and the metadata is kept per-cell on a list |
| 13:44 | Chouser | but next on a list returns a list, and the metadata is kept per-cell on a list |
| 13:46 | Chouser | but 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:47 | ataggart | letting this all marinade |
| 13:47 | Chouser | hm |
| 13:47 | Chouser | actually, list in general is a bit confusing |
| 13:48 | Chouser | conj on a list preserves metadata, cons does not? |
| 13:48 | Chouser | oh, cons on a list returns a Cons not a PersistentList |
| 13:49 | danlarkin | +1 for metadata review |
| 13:49 | ataggart | ,^(conj '#^{:my :meta} '(1 2 3) 4) |
| 13:49 | clojurebot | {:my :meta} |
| 13:49 | ataggart | ,^(butlast '#^{:my :meta} '(1 2 3) ) |
| 13:49 | clojurebot | nil |
| 13:49 | ataggart | I'm guessing butlast has the same issue drop does |
| 13:51 | ataggart | this 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:51 | ataggart | using butlast |
| 13:51 | Chouser | I use PersistentLists so rarely for data in Clojure. |
| 13:53 | ataggart | this is the problem I have: |
| 13:53 | Chouser | gah. pop on vector also loses metadata |
| 13:53 | Chouser | that can't be right |
| 13:53 | ataggart | ^(butlast (with-meta (re-split #"/" "foo/bar/baz") {:my :meta})) |
| 13:54 | ataggart | ,^(butlast (with-meta (re-split #"/" "foo/bar/baz") {:my :meta})) |
| 13:54 | clojurebot | java.lang.Exception: Unable to resolve symbol: re-split in this context |
| 13:54 | ataggart | d'oh |
| 13:54 | ataggart | well that woudl output nil |
| 13:54 | Chouser | yeah, I'm with you |
| 13:54 | Chouser | I don't know if butlast or drop-last should preserve metadata or not |
| 13:55 | ataggart | so I've been doing stuff like (with-meta (butlast orig-seq) {meta orig-seq)) |
| 13:55 | Chouser | but I would be shocked if pop losing metadata on vectors is intentional |
| 13:55 | ataggart | pop is next, right? |
| 13:55 | Chouser | no |
| 13:55 | ataggart | oh |
| 13:55 | ataggart | ioening the src |
| 13:55 | Chouser | it is for lists, but for vectors and queues it pops off the right |
| 13:55 | ataggart | *opening |
| 13:55 | ataggart | ah yeah |
| 13:55 | Chouser | ,(pop [1 2 3 4]) |
| 13:55 | clojurebot | [1 2 3] |
| 13:56 | Chouser | so that would be ideal for you case |
| 13:56 | Chouser | a thing the naturally grows and shrinks on the right |
| 13:56 | Chouser | but is walked left-to-right |
| 13:56 | ataggart | ,(pop (take 3 (iterate inc 1))) |
| 13:56 | clojurebot | java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IPersistentStack |
| 13:56 | Chouser | it's a vector. And most modifications to a vector preserve metadata (conj, assoc) |
| 13:57 | ataggart | so I'd need to turn the seq from re-split into a vector... |
| 13:57 | ataggart | smells funny |
| 13:57 | Chouser | nah, that's common |
| 13:57 | Chouser | re-split doesn't know what you're going to do. And it can be lazy (though I don't think it is). |
| 13:57 | Chouser | so a seq is a natural return type |
| 13:58 | Chouser | but you don't care about lazy and want to treat it as a vector. that's exactly what 'vec' is for |
| 13:58 | ataggart | hmm fair point |
| 13:58 | Chouser | *but* the only way I know to drop an item off the end of a vector is 'pop' |
| 13:58 | Chouser | and that still loses your metadata. :-P |
| 13:58 | ataggart | butlast works fine except for the losing of metadata |
| 13:58 | ataggart | heh |
| 13:59 | Chouser | right, but butlast is O(n) and more importantly an argument could be made that it should not preserve metadata. |
| 13:59 | Chouser | maybe. I dunno. |
| 14:00 | ataggart | the O(n) is a good point |
| 14:00 | ataggart | ya, swithcing to vectors |
| 14:00 | Chouser | vec is O(n) but it would happen once and then you can pop/conj in O(1) as needed |
| 14:00 | ataggart | regardless of the metadata issue |
| 14:00 | ataggart | right |
| 14:01 | Chouser | and I'm haveing a very hard time imagining the argument for dropping metadata on vector pop |
| 14:01 | ataggart | maybe Rich can clarify the rules for when manipulation functions should be meta-data preserving |
| 14:01 | Chouser | unless there's some other fn for dropping off the last item of a vector. I can't think of one. |
| 14:01 | ataggart | pop sounds right |
| 14:02 | Chouser | huh |
| 14:02 | Chouser | oh |
| 14:03 | ataggart | this 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:03 | ataggart | REST, not '(rest ) :) |
| 14:04 | Chouser | :-) |
| 14:04 | Chouser | ,^(pop (with-meta (conj [1 2 3] 4) {:my :meta})) |
| 14:04 | clojurebot | {:my :meta} |
| 14:04 | Chouser | ,^(pop (with-meta [1 2 3 4] {:my :meta})) |
| 14:04 | clojurebot | nil |
| 14:04 | Chouser | it's a bug |
| 14:04 | Chouser | ,(class (with-meta [1 2 3 4] {:my :meta})) |
| 14:04 | clojurebot | clojure.lang.LazilyPersistentVector |
| 14:05 | ataggart | ah finally a good excuse to register with assembla |
| 14:05 | Chouser | the metadata gets lost in the transition from LazilyPersistentVector to PersistentVector |
| 14:10 | ataggart | do we need to send in a CA in order to be able to post tickets in assembla? |
| 14:11 | ataggart | well, sicne I'd also want to try writing a patch, I guess so. nvm |
| 14:13 | Chousuke | you can use the "support" thing to report a bug I think. |
| 14:14 | Chousuke | but you need to be a project member to have full access to the ticket system, and that requires a CA |
| 14:14 | ataggart | yup, I'll do the CA thing once I have access to a printer |
| 14:14 | ataggart | and stamps |
| 14:21 | ataggart | chouser: btw thanks for the help |
| 14:22 | Chouser | ataggart: sure. I'd still be pleased to have a high-level description from rhickey about when metadata should be preserved vs. not |
| 14:24 | cemerick | shouldn't all objects be able to support metadata in JDK7? |
| 14:24 | cemerick | (totally orthogonal to the preservation issue) |
| 14:24 | Chouser | cemerick: how? got a link? |
| 14:24 | cemerick | Chouser: well, invokedynamic allows for method injection, or so I thought. |
| 14:25 | Chouser | huh. like add a method to Integer that ... closes over a variable that points to the metadata? |
| 14:26 | technomancy | that's the first I've heard of invokedynamic supporting something like that |
| 14:26 | cemerick | right...totally naievely, I'd think with-meta would just swap out another meta method |
| 14:26 | technomancy | Rich seemed to imply that it's mostly for supporting dynamic OOP on the JVM |
| 14:27 | danlarkin | I think it's to aid in languages where foo.bar might mean "get instance variable bar" or "call instance method var"... or something |
| 14:27 | danlarkin | s/var/bar |
| 14:27 | cemerick | sorry, the terminology is "interface injection": http://challenge.openjdk.org/projects/mlvm/subprojects.html |
| 14:27 | cemerick | not technically part of invokedynamic, but still part of JSR292 |
| 14:29 | Chouser | seems like a stretch to me |
| 14:29 | Chouser | doesn't sound like it would let you change the class of an existing object |
| 14:29 | Chouser | hm |
| 14:29 | cemerick | Chouser: no need to change the class -- just adding the IMeta interface is enough. |
| 14:30 | Chouser | no, you need a place to store the meta value |
| 14:30 | cemerick | right, so the method that is injected along with the interface would just be a thunk that closed over the meta value |
| 14:31 | Chouser | but now you're talking about a new method per instance |
| 14:31 | technomancy | cemerick: that's pretty awesome |
| 14:31 | cemerick | *shrug* Better than not having any metadata on java.lang.Objects at all. |
| 14:31 | Chouser | and classes like Integer are final -- could you still inject a method? |
| 14:32 | cemerick | that 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:33 | cemerick | alternatively, 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:33 | hiredman | cemerick: if that was true then you could just use the asm library to generate your own bytecode that ignores final |
| 14:33 | ataggart | yes final is for the compiler, and hotspot |
| 14:34 | ataggart | thats why you can change final fields via reflection |
| 14:34 | hiredman | final means different things in different places |
| 14:34 | cemerick | hiredman: I'm always on shaky ground w.r.t. final and bytecode issues. |
| 14:34 | Chouser | you could use WeakHashMap today |
| 14:35 | Chouser | just have meta and with-meta fns use that instead of (or in addition to) .meta() and .withMeta() methods. |
| 14:35 | cemerick | Chouser: right, but I presume Rich wouldn't put a big honking switch in the meta fn. |
| 14:36 | Chouser | I think his resistance would actually be more toward the WeakHashMap -- he's actually got plenty of bit switches. |
| 14:37 | cemerick | well, who knows, maybe pushing a new method into an object on every with-meta will end up being cheap :-) |
| 14:37 | Chouser | we can hope! |
| 14:38 | hiredman | that would be rather down the line I imagine |
| 14:38 | Chousuke | http://blogs.sun.com/jrose/entry/interface_injection_in_the_vm reading this, it seems it would be done for classes, not objects. |
| 14:38 | hiredman | (since clojure targets java 5) |
| 14:39 | cemerick | hiredman: 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:39 | Chouser | Chousuke: anything about field injection there? :-) |
| 14:40 | hiredman | cemerick: I remain skeptical |
| 14:40 | Chouser | bifurcation of .. the clojure sources? |
| 14:40 | cemerick | Chouser: no, just different code paths for invokedynamic |
| 14:40 | Chouser | oh |
| 14:42 | cemerick | Chouser: John Rose indicates that traits are a core use case for interface injection, so yeah, injecting fields is on the table |
| 14:42 | cemerick | e.g. an IMeta trait |
| 14:42 | cemerick | (which carries a meta field) |
| 14:43 | Chouser | clojure.test confuses me |
| 14:43 | Chouser | oh... |
| 14:50 | ataggart | is there a way to add doc to a defstruct? |
| 14:56 | Chouser | (defstruct #^{:doc "this is foo"} foo :a :b) |
| 14:57 | Chousuke | Maybe I should bookmark this JRose blog :) |
| 14:57 | Chousuke | fun stuff |
| 14:58 | Chousuke | Also, the JVM apparently has an interesting method to check for null pointer derefs. |
| 14:59 | eyeris | Is there a standard function in the api for flattening a list? |
| 15:00 | Chousuke | basically, 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:00 | hiredman | cute |
| 15:00 | Chousuke | +and |
| 15:00 | Chousuke | eyeris: there is flatten in contrib |
| 15:01 | eyeris | Thanks |
| 15:03 | cemerick | Chousuke: yeah, I've subscribed jrose's blog :-) |
| 15:04 | cemerick | Let's hope he stays hale, hearty, and healthy. Quite a positive voice in the jvm circus. |
| 15:05 | ataggart | chouser: yup that did it. thanks. |
| 15:06 | Chouser | ataggart: so you're planning on filing a bug, sending in a CA, and writing a patch, right? |
| 15:07 | ataggart | I woudl but it'll take me a few days to get to a printer. feel free to open it in the meantime. |
| 15:07 | Chousuke | hmm |
| 15:08 | Chousuke | ,(remove coll? (tree-seq coll? seq [[1] {1 2} [2 [5 4]] 3])) |
| 15:08 | clojurebot | (1 1 2 2 5 4 3) |
| 15:08 | Chouser | ataggart: I wouldn't want reduce your incentive to register and contribute. :-)_ |
| 15:08 | Chouser | Chousuke: nice! |
| 15:09 | ataggart | hehe fair enough, just didn't want to hold you up. |
| 15:11 | Chouser | ataggart: you don't need a CA to file an assembla ticket, though. Just use the Support tab |
| 15:11 | ataggart | ah excellent. doing it now. |
| 15:14 | Chousuke | I have to say, searchable menu entries in OS X Cocoa apps are sheer genius. |
| 15:14 | fffej | with 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:15 | Chouser | fffej: you're doing (use 'clojure.contrib.zip-filter) ? |
| 15:15 | Chousuke | I 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:15 | fffej | chouser: I'm doing (ns mynamespace (:use [clojure.contrib.zip-filter])) |
| 15:16 | Chouser | Try (:require [clojure.contrib.zip-filter :as zf]), then use zf/descendents or whatever |
| 15:16 | cemerick | Chousuke: whoa, I had *no* idea Mail could consume RSS! |
| 15:16 | Chousuke | cemerick: heh |
| 15:17 | fffej | chouser: thanks, that works |
| 15:17 | texodus | How can I determine if a something is an array? |
| 15:18 | Chouser | texodus: 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:18 | texodus | yes, im positive - im writing a specific Writer proxy that needs to dispatch differently on byte arrays |
| 15:19 | ozzilee | Chouser: Submitted a patch for lazy-xml. Pretty simple, unless I missed something. |
| 15:19 | texodus | so, proxy to a defmulti - but then how to determine an array ... |
| 15:19 | texodus | ,(class (to-array [1 2 3])) |
| 15:19 | clojurebot | [Ljava.lang.Object; |
| 15:20 | texodus | ,(= (class (to-array [1 2 3])) [Ljava.lang.Object) |
| 15:20 | clojurebot | Unmatched delimiter: ) |
| 15:20 | texodus | clearly doesnt work |
| 15:20 | ataggart | ,(Class/isArray (class (to-array [1 2 3]))) |
| 15:20 | clojurebot | java.lang.IllegalArgumentException: No matching method: isArray |
| 15:20 | Chouser | ,(some #{(byte 2)} (into-array Byte/TYPE (map byte [1 2 3]))) |
| 15:20 | clojurebot | 2 |
| 15:20 | ataggart | hmm |
| 15:21 | ataggart | ,(.isArray (class (to-array [1 2 3]))) |
| 15:21 | clojurebot | true |
| 15:21 | hiredman | ! |
| 15:21 | clojurebot | CLABANGO! |
| 15:21 | hiredman | beat me to it |
| 15:21 | ataggart | lol |
| 15:21 | texodus | ,(. (class (to-array [1 2 3])) isArray) |
| 15:21 | clojurebot | true |
| 15:21 | texodus | bingo |
| 15:21 | texodus | thanks alot |
| 15:22 | Chouser | wow, I completely misread the question |
| 15:22 | eyeris | I 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:23 | hiredman | vec |
| 15:23 | Chouser | I had an extra "in" in there. "if a something is in an array" |
| 15:23 | ataggart | ,(vec (seq [1 2 3[)) |
| 15:23 | clojurebot | Unmatched delimiter: ) |
| 15:23 | ataggart | ,(vec (seq [1 2 3])) |
| 15:23 | clojurebot | [1 2 3] |
| 15:23 | hiredman | or just pass a vector |
| 15:23 | hiredman | like most other bindings |
| 15:25 | Chouser | ozzilee: thanks! BTW, issues have moved to assembla, and code to github. See http://clojure.org/patches |
| 15:26 | ozzilee | Chouser: Oh, contrib too? Neato. |
| 15:26 | Chouser | yep. We're trying to create as long a list of out-of-date project hosting services as possible |
| 15:26 | ozzilee | Chouser: Heh no kidding :-) |
| 15:27 | eyeris | Is %1 valid inside (fn) as it is inside #()? |
| 15:27 | Chouser | eyeris: no |
| 15:27 | Chousuke | ,((fn [] %1)) |
| 15:27 | clojurebot | arg literal not in #() |
| 15:27 | Chousuke | ,((fn [] %)) |
| 15:27 | clojurebot | arg literal not in #() |
| 15:27 | Chouser | although the error case has changed a bit recently |
| 15:28 | Chousuke | hmm |
| 15:28 | Chousuke | old clojure? :P |
| 15:28 | Chousuke | should simply be an unresolved symbol. |
| 15:28 | Chouser | right, to support :post |
| 15:28 | eyeris | Is there a compliment for (keyword)? |
| 15:29 | hiredman | :post? |
| 15:29 | hiredman | eyeris: name |
| 15:30 | ataggart | ,*clojure-version* |
| 15:30 | clojurebot | {:interim true, :major 1, :minor 1, :incremental 0, :qualifier "alpha"} |
| 15:30 | Chouser | hiredman: ((fn [] {:post [(= % 5)]} 6)) ==> java.lang.Exception: Assert failed: (= % 5) |
| 15:30 | Chouser | wow, that's a whole lot of parens |
| 15:31 | hiredman | Chouser: oooooo |
| 15:31 | Chouser | and various other grouping chars |
| 15:31 | hiredman | no :pre yet? |
| 15:31 | Chouser | :pre is there too, but doesn't need % |
| 15:31 | hiredman | ah |
| 15:38 | eyeris | Is :as not allowed in the defn arg list? |
| 15:38 | Chouser | right. |
| 15:40 | Chouser | ,(let [foo (fn [& [a b :as all]] [a b all])] (foo 1 2 3)) |
| 15:40 | clojurebot | [1 2 (1 2 3)] |
| 15:40 | Chouser | but you can do that, I suppose |
| 15:41 | eyeris | Yeah, I've been using it in let/ |
| 15:42 | Chouser | sure, but you see I'm doing it in fn args there, just destructuring the "rest" part |
| 15:42 | eyeris | Oh, you mean I could do (def foo (fn... and use the destructuring there |
| 15:42 | Chouser | or just (defn foo [& [a b :as all]] [a b all]) |
| 15:45 | eyeris | I see. I tried that, but I was doing it wrong :/ |
| 15:45 | Chouser | nested destructuring can get a bit convoluted |
| 15:46 | eyeris | I am using it with a nested map, so I was trying (defn foo [& {{:keys [a b]} :sub-map} :as my-map] ...) |
| 15:46 | eyeris | But it shoudl be (defn foo [& {{:keys [a b]} :sub-map :as my-map}] ...) |
| 15:50 | zakwilson | I'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:04 | ataggart | chouser: what clojure implementation code were you looking at when we were talking about pop and meta-data? |
| 16:04 | ataggart | I haven't quite grokked how to get from clj function defs in clojure.core over to clojure java |
| 16:05 | hiredman | ataggart: when you see a java method call |
| 16:05 | ataggart | I'm referring to clojure's java implementation |
| 16:05 | ataggart | e.g., where pop, conj, etc are implemented |
| 16:06 | hiredman | yeah |
| 16:06 | hiredman | ~def pop |
| 16:06 | hiredman | so you look at the pop method in the RT class |
| 16:07 | hiredman | ~def c.l.RT |
| 16:07 | ataggart | yes, but chris was referring to something earlier andni'm trying to find out exactly what he was looking at |
| 16:08 | ataggart | in order to write a bugfix patch |
| 16:08 | hiredman | oh |
| 16:08 | hiredman | pardon |
| 16:08 | ataggart | np, I should have been more clear |
| 16:10 | guille_ | hi there |
| 16:18 | ataggart | how does one add further comments on a ticket in assembla? |
| 16:19 | ataggart | hmm must be because I'm not CA'd yet |
| 16:20 | guille_ | 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:24 | ataggart | chouser: 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:25 | ataggart | ,(meta (pop (conj (with-meta '(1 2 3) {:my :meta}) 4))) |
| 16:25 | clojurebot | {:my :meta} |
| 16:27 | ataggart | ,(meta (pop (with-meta '(1 2 3) {:my :meta}))) |
| 16:27 | clojurebot | nil |
| 16:27 | ataggart | because (meta '(1 2)) is nil |
| 16:28 | ataggart | so ticket #149 should probably be marked as invalid |
| 16:42 | eyeris | Will someone here help me figure out where I am going wrong with this macro? http://pastebin.ca/1491100 |
| 16:44 | eyeris | If I load it into the repl and use macroexpand, it just prints out the input, without any expansion. |
| 16:44 | eyeris | That must be a sign that I've used defmacro incorrectly, but I can't figure out how |
| 16:46 | Chousuke | hm |
| 16:47 | eyeris | The (one) and (two) in the example usage are incorrect, but that isn't what the exception refers to. |
| 16:49 | Chousuke | you can't pass runtime values to a macro |
| 16:49 | Chousuke | you need to call it as (with-map-bindings {:one 1 :two 2} (+ one two)) |
| 16:50 | eyeris | I see. |
| 16:51 | eyeris | Is 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:51 | Chousuke | a 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:51 | Chousuke | that would require eval I think. |
| 16:52 | Chousuke | but... are you sure you need to do that at all? |
| 16:52 | eyeris | I don't *need* to, but I'd sure like to. |
| 16:52 | eyeris | I have a map that has 6 keys, my function uses all of them. |
| 16:52 | Chousuke | in which case would you need to pass a binding vector to let at runtime? |
| 16:53 | eyeris | I could use :keys [...], but that just feels overly verbose when I am binding them all |
| 16:53 | Chousuke | hmm |
| 16:53 | eyeris | It also is misleading to me, because when I see :keys [...] I instinctively look at what *isn't* bound from the map |
| 16:54 | Chousuke | will simple-map be static? |
| 16:54 | eyeris | No |
| 16:54 | Chousuke | hm. |
| 16:55 | Chousuke | I still don't get your use case though. :/ |
| 16:56 | Chousuke | you can't bind locals based on runtime values, unless you also generate the code at runtime and use eval |
| 16:56 | Chousuke | and that's not what you want to do. |
| 16:57 | eyeris | Oh, wait. |
| 16:57 | eyeris | The keys in my map will be static. |
| 16:57 | eyeris | The values will change though. |
| 16:57 | Chousuke | in that case there's no problem |
| 16:59 | eyeris | I 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:00 | Chousuke | just write (defmacro defspecialfn [& body] `(let [{:keys ~'[your keys here]} *the-global-map*] ~@body)) |
| 17:00 | Chousuke | assuming *the-global-map* will be bound with (binding ...) here. |
| 17:01 | Chousuke | otherwise, it *would* be static and the values would not be changing :) |
| 17:02 | eyeris | Okay |
| 17:02 | eyeris | I think I understand that. |
| 17:02 | Chousuke | alternatively, it could be a ref |
| 17:02 | Chousuke | in which case you'd want to do: |
| 17:02 | Chousuke | just write (defmacro defspecialfn [& body] `(let [{:keys ~'[your keys here]} (deref *the-global-map*)] ~@body)) |
| 17:03 | Chousuke | forgot to remove the just write. |
| 17:04 | Chousuke | note the funky ~' unquote thing there. that needs to be used so that let won't complain about binding to qualified names. |
| 17:04 | Chousuke | it also serves as documentation to the reader that the macro introduces local names implicitly. |
| 17:05 | eyeris | I think this is one step removed from what I want to do. |
| 17:05 | eyeris | The map I am using is always passed into the function. I don't rebind the global symbol to update the values. |
| 17:07 | Chousuke | well, in that case you can add the map name as a parameter to the defspecialfn macro |
| 17:08 | eyeris | And, inside the function, that would be a local symbol just like a normal function parameter? |
| 17:08 | Chousuke | (defmacro defspecialblock [mname & body] `(let [{:keys ~'[your keys here]} ~mname] ~@body)) |
| 17:08 | Chousuke | then (defspecialblock *global-map* (do-stuff using your keys)) |
| 17:08 | eyeris | http://pastebin.ca/1491131 |
| 17:09 | eyeris | That is what I am doing |
| 17:09 | eyeris | (dispatcher) returns the next function to pass the state map into |
| 17:10 | eyeris | that function returns the next map to bind to the state symbol |
| 17:10 | eyeris | repeat |
| 17:11 | Chousuke | investigate the macroexpansions of these functions, you'll see what kind of code they produce :) |
| 17:16 | eyeris | Where does the name of the special block go? |
| 17:16 | Chousuke | well, that above thing doesn't actually define a function. |
| 17:16 | Chousuke | just a let block |
| 17:16 | Chousuke | but you could easily extend it to a defn |
| 17:19 | eyeris | This 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:20 | eyeris | can't call it = can't call the special fn defined by the macro |
| 17:20 | Chousuke | it doesn't define a fn :P |
| 17:21 | eyeris | if does if I make if (defspecialfn [fname mname & body] (defn fname `(let ... |
| 17:22 | eyeris | Wait a minute |
| 17:22 | eyeris | I think I got something |
| 17:23 | Chousuke | the ` should go before defn, not let. |
| 17:25 | Chousuke | http://pastebin.ca/1491144 |
| 17:25 | Chousuke | I used [] around map-name because giving the binding in a vector to the macro is more idiomatic |
| 17:30 | eyeris | I want the map symbol inside the generated fn to always be the same |
| 17:31 | eyeris | Removing map-name from the defmacro parameters and then removing the ~ from before each use of it yields an exception though |
| 17:32 | Chousuke | well, of course. |
| 17:32 | eyeris | Why? |
| 17:32 | Chousuke | because it's passed to defn as the parameter name |
| 17:32 | Chousuke | and inside ` it becomes qualified, and qualified names can't be used to bind to. |
| 17:33 | Chousuke | if you want to force the name, do ~'whatever |
| 17:34 | eyeris | This whole "the macro language is the language" is bs |
| 17:34 | Chousuke | hm? |
| 17:34 | Chousuke | no it's not. |
| 17:34 | Chousuke | a macro must return a data structure. |
| 17:34 | Chousuke | which is clojure code. |
| 17:34 | eyeris | but it must do so using different evaluation rules |
| 17:35 | Chousuke | not really. the only differing thing is that macro parameters are not evaluated |
| 17:35 | Chousuke | otherwise a macro is a normal function |
| 17:35 | Chousuke | it may look different because of `(foo bar whatever |
| 17:36 | Chousuke | but syntax-quote is not restricted to macros |
| 17:36 | Chousuke | ,(let [x 1] `(foo bar x ~x)) |
| 17:36 | clojurebot | (sandbox/foo sandbox/bar sandbox/x 1) |
| 17:37 | Chousuke | you could write every macro without syntax quoting |
| 17:38 | eyeris | http://pastebin.ca/1491155 |
| 17:38 | eyeris | Why is that wrong? |
| 17:38 | Chousuke | (defmacro [x] (list 'clojure.core/+ x x)) <- equivalent to (defmacro [x] `(+ ~x ~x)) |
| 17:39 | hiredman | eyeris: map-name is not specified anywhere |
| 17:39 | eyeris | Right, so I have to use 'map-name |
| 17:40 | Chousuke | ~'map-name |
| 17:40 | clojurebot | map is *LAZY* |
| 17:40 | Chousuke | :P |
| 17:40 | eyeris | Chousuke so what does ~'map-name evaluate to? |
| 17:40 | Chousuke | if you do 'map-name, you will see (quote user/map-name) in the expansion |
| 17:40 | hiredman | eyeris: 'map-name |
| 17:40 | Chousuke | eyeris: just the symbol map-name |
| 17:40 | hiredman | ~ is unsyntax quote and ' is quote |
| 17:40 | clojurebot | Alles klar |
| 17:41 | hiredman | erp |
| 17:41 | Chousuke | eyeris: in other lisps, you'd just write "map-name" without the unquote-quote thing. |
| 17:41 | Chousuke | eyeris: but in clojure, map-name will be qualified in that case, and you can't bind to qualified names |
| 17:41 | ataggart | eyeris: are you just trying to reimplement (binding [...] ...)? |
| 17:42 | Chousuke | to get around this, you unquote a quoted, plain symbol. thus the result is the plain symbol |
| 17:43 | Chousuke | compare: |
| 17:43 | Chousuke | ,`sym |
| 17:43 | clojurebot | sandbox/sym |
| 17:43 | Chousuke | ,`~sym |
| 17:43 | clojurebot | java.lang.Exception: Unable to resolve symbol: sym in this context |
| 17:43 | Chousuke | ,`~'sym |
| 17:43 | clojurebot | sym |
| 17:43 | eyeris | I get that part |
| 17:44 | eyeris | but you syntax quote the macro to prevent evaluation, right? |
| 17:44 | Chousuke | no |
| 17:44 | Chousuke | the evaluation is already prevented by the macro expansion. |
| 17:44 | hiredman | Chousuke: you kinda do |
| 17:45 | Chousuke | well, hm. |
| 17:46 | hiredman | you quote the form the form you want to be the result of the macro |
| 17:46 | hiredman | and you use syntax quote because you want all its snazzy features |
| 17:47 | eyeris | Yeah, but that form is unevaluated until it is called |
| 17:47 | hiredman | … |
| 17:47 | eyeris | e.g. the defn isn't evaluated before defmacro returns |
| 17:47 | Chousuke | eyeris: no. |
| 17:48 | Chousuke | well, in a way yes. |
| 17:48 | Chousuke | but there's a more fundamental point. |
| 17:48 | Chousuke | eyeris: the macro, when called, *returns* the defn form |
| 17:48 | Chousuke | as a value |
| 17:48 | Chousuke | and then the compiler calls eval on it. |
| 17:48 | eyeris | Right |
| 17:49 | eyeris | Normally, to prevent the evaluation of a symbol, you quote it, right? |
| 17:49 | eyeris | (let [x 1] 'x) returns the symbol x |
| 17:49 | eyeris | but (let [x 1] x) returns 1 |
| 17:50 | eyeris | s/returns/evaluates to/ |
| 17:50 | Chousuke | you 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:51 | Chousuke | the former will print 2 and return 2, the latter will print (+ 1 1) and return 2 |
| 17:51 | Chousuke | (because of the implicit eval) |
| 17:52 | eyeris | Right, but inside defmacro, x is not resolved when it is an argument to println |
| 17:52 | Chousuke | after that, you can try using syntax-quote on x in both the macro and the function |
| 17:52 | eyeris | whereas outside defmacro, it would be |
| 17:53 | Chousuke | yes it is resolved. |
| 17:53 | Chousuke | it's just that its value is '(+ 1 1) |
| 17:53 | Chousuke | not 2, like in the function |
| 17:53 | eyeris | erm |
| 17:54 | eyeris | I misspoke |
| 17:54 | eyeris | it is not evaluated |
| 17:55 | Chousuke | yes. |
| 17:56 | Chousuke | or 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:57 | Chousuke | in 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:58 | eyeris | Okay |
| 17:59 | eyeris | So |
| 17:59 | eyeris | So 'x in a fn evals to the symbols x. |
| 18:00 | Chousuke | yes. |
| 18:00 | eyeris | So what does 'x eval to inside a macro? |
| 18:00 | Chousuke | the same as in a function. |
| 18:00 | Chousuke | to the symbol x |
| 18:01 | eyeris | So the syntax-quote function is doing the namespace resolution? |
| 18:01 | Chousuke | yes. |
| 18:01 | eyeris | Why? What problem does that solve? |
| 18:01 | Chousuke | hygiene |
| 18:02 | Chousuke | it's more difficult to accidentally introduce names |
| 18:02 | Chousuke | that could shadow names in other code. |
| 18:02 | Chousuke | very useful for macros, which is why ` is very popular when writing them |
| 18:02 | Chousuke | but ` is not restricted to macros |
| 18:03 | Chousuke | ,((fn [x] `(x :is ~x :unqualified ~'x)) 5) |
| 18:03 | clojurebot | (sandbox/x :is 5 :unqualified x) |
| 18:04 | eyeris | So I can write macros without `? |
| 18:04 | Chousuke | sure. |
| 18:05 | Chousuke | (defmacro add-to-y [x] (list '+ x 'y)) |
| 18:05 | Chousuke | next (def y 3); (add-to-y 4) -> 7 |
| 18:06 | Chousuke | because the macro will return '(+ 4 y) which is 7 when evaluated in that context |
| 18:09 | Chousuke | the 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:10 | Chousuke | however, if you do (list 'let `[y 5] ...), you will get an exception |
| 18:10 | Chousuke | because y is qualified and let does not like that. |
| 18:11 | Chousuke | so you won't mistakenly override names in the context. |
| 18:12 | eyeris | Is there a contrib that function as syntax quote without the ns resolution? |
| 18:12 | Chousuke | no. |
| 18:13 | Chousuke | but as show, you can override syntax-quote's ns resolution by prefixing the symbol you want to be bare with ~' |
| 18:13 | eyeris | I get that. |
| 18:13 | eyeris | That is just plain not intuitive for me. |
| 18:14 | Chousuke | well, it's not supposed to be :) |
| 18:14 | eyeris | ' = quote |
| 18:14 | eyeris | ~ = unquote |
| 18:14 | clojurebot | Excuse me? |
| 18:14 | Chousuke | yeah |
| 18:14 | eyeris | reversing something should yield the same thing |
| 18:14 | eyeris | erm |
| 18:14 | Chousuke | and when you quote a symbol, and unquote it, you get the symbol back. |
| 18:14 | eyeris | (inc (dec 1)) == 1 |
| 18:15 | Chousuke | but see |
| 18:15 | Chousuke | ,`'y |
| 18:15 | clojurebot | (quote sandbox/y) |
| 18:15 | eyeris | Right, but if ~'x evaluates to x, why doesn't it get resolved? |
| 18:15 | Chousuke | hmm |
| 18:15 | Chousuke | ,`~'y |
| 18:15 | clojurebot | y |
| 18:15 | eyeris | See |
| 18:15 | eyeris | it's different |
| 18:16 | Chousuke | ,`~'sandbox/y |
| 18:16 | clojurebot | sandbox/y |
| 18:16 | Chousuke | (quote sandbox/y) |
| 18:16 | Chousuke | ,(quote sandbox/y) |
| 18:16 | clojurebot | sandbox/y |
| 18:17 | Chousuke | well, you can just take this behaviour for granted now :) |
| 18:17 | Chousuke | it's useful. |
| 18:18 | Chousuke | it *is* a bit funky though. |
| 18:18 | clojurebot | 0 |
| 18:19 | Chousuke | but you can think of it as unquoting a quoted form yielding the same form. |
| 18:20 | eyeris | It seems to me that syntax-quote must do resolution before any evaluation and simply doesn't recurse into an unquote form |
| 18:21 | Chousuke | possibly. |
| 18:21 | Chousuke | syntax-quote is a special thing implemented in java, after all |
| 18:21 | Chousuke | it has some special semantics. |
| 18:22 | Chousuke | but it's undeniably useful, and not at all that difficult after you understand how it works. |
| 18:22 | eyeris | For Symbols, syntax-quote resolves the symbol in the current context, yielding a fully-qualified symbol (i.e. namespace/name or fully.qualified.Classname). |
| 18:23 | eyeris | That should be followed by "except when preceded by ~'" or something more complete. |
| 18:24 | eyeris | Thanks for your help |
| 18:24 | eyeris | I'll need a lot more practice, but it's a start |
| 18:28 | ataggart | rule 1 of macros: don't write macros. |
| 18:29 | Chouser | such a good rule. |
| 19:09 | ataggart | chouser: did you see my comments from earlier regarding pop? |
| 19:17 | Chouser | I hadn't. But yes, I guess I was failing to describe it. |
| 19:17 | Chouser | glad you figured it out anyway, though. |
| 20:34 | newbie | hi, 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:35 | hiredman | newbie: use for |
| 20:37 | newbie | but how can i create a vector and add on it like in loop? |
| 20:38 | hiredman | vectors can be created with the literal [] or the function vec, or vector |
| 20:40 | newbie | yeah but vector is not persisted between iterations so i can add on it |
| 20:41 | hiredman | if you are looping, you can rebind names in the loop |
| 20:42 | hiredman | ,(loop [foo 0 r []] (if (= foo 5) r (recur (inc foo) (conj r foo)))) |
| 20:42 | clojurebot | [0 1 2 3 4] |
| 20:42 | newbie | no thats why i am asking is there a way to achive the same effect while using doseq |
| 20:42 | hiredman | doseq is for side effects |
| 20:44 | newbie | so loop inside loop is my only choice? to iterate x,y coordinates? |
| 20:45 | hiredman | for |
| 20:46 | hiredman | ,(vec (for [x (range 10) y (range 10)] [x y])) |
| 20:46 | clojurebot | [[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:56 | newbie | thanks that solved it. |
| 21:11 | Raynes | hiredman: 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:11 | hiredman | Raynes: it generally is a ref |
| 21:12 | Raynes | I know, but what is the point of it? I'm not really sure why it's needed. |
| 21:12 | hiredman | the key point is the is a state per instance |
| 21:13 | Raynes | So it's primarily for Clojure classes that will be instantiated by Java classes? |
| 21:13 | Raynes | Well, clojure-generated classes. |
| 21:13 | hiredman | yes |
| 21:14 | Raynes | I'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:14 | Raynes | Thanks. |
| 21:37 | Knekk | I 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:37 | Knekk | thanks |
| 21:42 | gnuvince | Knekk: SICP? |
| 21:42 | Knekk | http://mitpress.mit.edu/sicp/? |
| 21:43 | gnuvince | Aye |
| 21:43 | hiredman | clojurebot: delicious |
| 21:43 | clojurebot | delicious is http://delicious.com/clojurebot |
| 21:43 | Knekk | nice, didn't know about it. Thanks :) |
| 21:44 | gnuvince | Knekk: as far as CS books go, this one is way high up there. |
| 21:44 | Knekk | $114 at amazon, free on the site. Yay |
| 21:44 | Knekk | hiredman: thanks |
| 23:43 | flying_spaghetti | anyone can help with a noob question? |
| 23:46 | fUD | Greets |
| 23:47 | flying_spaghetti | hail |
| 23:50 | flying_spaghetti | i seek a clue |
| 23:52 | Chouser | go |
| 23:54 | flying_spaghetti | well, 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:54 | flying_spaghetti | because 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:55 | flying_spaghetti | and then convert the resulting list back into a colour structure |
| 23:55 | flying_spaghetti | i am wondering if there is a generic means to do that |
| 23:56 | texodus | ,(into {} (map (fn [[_ v]] (+ 1 v)) [1 2 3]) |
| 23:56 | clojurebot | EOF while reading |
| 23:57 | texodus | ,(into {} (map (fn [[_ v]] (+ 1 v)) [1 2 3])) |
| 23:57 | clojurebot | java.lang.RuntimeException: java.lang.UnsupportedOperationException: nth not supported on this type: Integer |
| 23:58 | flying_spaghetti | oh great thx i will try |
| 23:58 | texodus | oh right, struct |
| 23:58 | texodus | (into {} (map (fn [[_ v]] (+ 1 v)) {:1 1 :2 2 :3 3}) |
| 23:58 | texodus | ,(into {} (map (fn [[_ v]] (+ 1 v)) {:1 1 :2 2 :3 3}) |
| 23:58 | clojurebot | EOF while reading |
| 23:59 | texodus | ,(into {} (map (fn [[_ v]] (+ 1 v)) {:1 1 :2 2 :3 3})) |
| 23:59 | clojurebot | java.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer |