2009-10-11
| 00:04 | technomancy | I wonder if it should/could be made more obvious somehow |
| 00:05 | technomancy | I guess it could write it automatically with the customize feature, but many people don't appreciate that. |
| 00:07 | jaiganesh | hi |
| 00:07 | jaiganesh | can anyone explain whats happening in this piece of code (for [x (range 100 1000) y (range x 1000)] (* x y)) |
| 00:09 | tomoj | x goes from 100 to 1000, and each time y goes from x to 1000 |
| 00:11 | tomoj | er, except 999 instead of 1000 |
| 00:11 | tomoj | ,(for [x (range 0 4) y (range x 4)] [x y]) |
| 00:11 | clojurebot | ([0 0] [0 1] [0 2] [0 3] [1 1] [1 2] [1 3] [2 2] [2 3] [3 3]) |
| 00:11 | jaiganesh | yeah thks |
| 00:12 | jaiganesh | is this called List comprehension? can i produce similar list in a different way in clojure? |
| 00:14 | tomoj | it's list comprehension, yes |
| 00:17 | tomoj | ,(mapcat (fn [i] (map (fn [j] [i j]) (range i 4))) (range 0 4)) |
| 00:17 | clojurebot | ([0 0] [0 1] [0 2] [0 3] [1 1] [1 2] [1 3] [2 2] [2 3] [3 3]) |
| 00:17 | tomoj | maybe there is a prettier way to do it besides using for |
| 00:17 | tomoj | but why don't you want to use for? :) |
| 00:21 | tomoj | for is faster, too |
| 00:21 | jaiganesh | k |
| 00:21 | tomoj | going from 0 to 1000, the for version above is over 3 times faster than the mapcat version |
| 00:22 | jaiganesh | hmm interesting |
| 00:22 | tomoj | it uses chunked seqs, maybe other optimizations as well |
| 00:28 | solussd | what is the difference between binding and let? |
| 00:28 | hiredman | let is lexical |
| 00:28 | twee | is there an easy way to get the namespace of a function parameter? |
| 00:28 | hiredman | binding is dynamic, and it only works if the names have already been created via def |
| 00:29 | hiredman | twee: what do you mean? |
| 00:29 | hiredman | (fn [x] x) x is a local name, there is no namespace |
| 00:29 | twee | at runtime i guess.. when you can the fn |
| 00:29 | twee | call the fn |
| 00:30 | solussd | I see- So, binding will mask a defined value, but not define a new one? |
| 00:30 | hiredman | more or less |
| 00:30 | tomoj | all the code called from within the body of the binding will see the new value, as well ("dynamic") |
| 00:30 | hiredman | twee: what doe you mean by get the namespace of a function parameter? |
| 00:30 | hiredman | binding is also thread local |
| 00:31 | solussd | isn't 'let' thread local? |
| 00:31 | hiredman | let is lexical |
| 00:31 | hiredman | (let [x 1] (future (prn x))) |
| 00:32 | hiredman | (def x 0) (binding [x 1] (future (prn x))) |
| 00:32 | tomoj | (def *foo* 3), (defn foo [] *foo*), then compare (binding [*foo* 10] (foo)) to (let [*foo* 10] (foo)) |
| 00:34 | twee | something like what the namespace function does, except for arbitrary things i guess |
| 00:34 | twee | (doc namespace) |
| 00:34 | clojurebot | "([x]); Returns the namespace String of a symbol or keyword, or nil if not present." |
| 00:34 | hiredman | arbitrary things don't have namespaces |
| 00:35 | solussd | I see. Thanks |
| 00:35 | twee | let's say i pass in (namespace map) i'd like it to say 'clojure.core' |
| 00:35 | hiredman | namespaces are a space for names, so the only things that have/exist in namepsaces are names like keywords and symbols |
| 00:36 | hiredman | (def foo (Object.)) |
| 00:36 | hiredman | the Object is not in a namespace, the name bound to the Object is |
| 00:37 | tomoj | hmm |
| 00:37 | tomoj | ,#'map |
| 00:37 | clojurebot | #'clojure.core/map |
| 00:37 | tomoj | how do you pull that out? maybe that's what twee is asking? |
| 00:37 | twee | yup it is |
| 00:38 | hiredman | you want to resolve a symbol to the var it is bound to |
| 00:38 | hiredman | ,(doc resolve) |
| 00:38 | clojurebot | "([sym]); same as (ns-resolve *ns* symbol)" |
| 00:38 | tomoj | does resolve have an inverse, though? |
| 00:40 | tomoj | ,(.ns #'map) |
| 00:40 | clojurebot | #<Namespace clojure.core> |
| 00:41 | twee | ah thank you, that's what i was looking for |
| 00:41 | tomoj | I dunno if you're supposed to use that |
| 00:41 | tomoj | may be subject to change, I dunno |
| 00:42 | twee | i see |
| 00:42 | hiredman | what are you doing? |
| 00:42 | twee | some java interop stuff |
| 00:43 | hiredman | and what does that have to do with namespaces? |
| 00:46 | twee | have some stuff where it dynamically resolves the workflows to run, where workflow is passed in from cmdline, but for test-is code, i just don't want to deal with it. but if it doesn't work out, i'll just pass it in explicitly |
| 00:46 | hiredman | if you don't want to say, you can just say that |
| 01:03 | hiredman | http://weblogs.java.net/blog/forax/archive/2009/10/06/jdk7-do-escape-analysis-default |
| 02:31 | arussel | I got some newbee question before I start learning clojure. How mature is the eclipse plugin ? |
| 02:32 | slashus2 | arussel: Try netbeans with enclojure |
| 02:32 | arussel | (in term of debuggin, autocomplete, code browsing) |
| 02:33 | arussel | slashus2: I never used netbeans ... Then between emacs and netbean plugin, which one would you recommend ? |
| 02:33 | slashus2 | I don't use emacs because I have never given it an honest try, so I can't really weigh those. |
| 02:34 | arussel | does the netbeans plugin has autocomplete, debugging and code browsing ? |
| 02:37 | slashus2 | arussel: Yes. |
| 02:39 | arussel | nice. Apart from compojure, is there any other web framework known to run on GAE ? |
| 03:43 | gonzojive | does anybody have emacs configured for both Common Lisp and Clojure? right now I can only do one or the other |
| 03:44 | tomoj | I have both |
| 03:44 | tomoj | but I still have a bit of trouble using both at the same time |
| 03:44 | tomoj | gonzojive: http://gist.github.com/28a01c699b8afecc0750 |
| 04:10 | G0SUB | what should be the clojure type hint for a Future<Object> object? |
| 04:10 | G0SUB | will #^Future<object> work? or should it be #^Future ? |
| 04:11 | LauJensen | Depends on what you're passing it to I suppose - I never had to type hint a future, why do you ? |
| 04:11 | G0SUB | LauJensen: I was just thinking. I am trying to use the spymemcached lib. |
| 04:21 | ambient | arussel neither netbeans nor eclipse plugins are something i'd call "mature" |
| 04:21 | ambient | they work, but that's about it |
| 04:21 | ambient | plenty of rough edges |
| 04:38 | Chousuke | G0SUB: typehinting Object is pointless, and if you want to tell the compiler it's a Future, just use #^Future |
| 04:38 | Chousuke | or at least, I hope typehinting Object is pointless, since all classes are supposed to be Objects ;P |
| 04:39 | G0SUB | Chousuke: OK. |
| 04:39 | Chousuke | if you still need to do the hinting, you'll need to do it when you dereference the future |
| 04:39 | Chousuke | eg. #^Object @future |
| 04:39 | clojurebot | Chousuke: the fn created by future (like all fns) doesn't close over dynamicly scoped stuff |
| 04:44 | hiredman | ~botsnack |
| 04:44 | clojurebot | thanks; that was delicious. (nom nom nom) |
| 04:53 | arussel | ambient: do you know where to get the sources ( hg clone https://counterclockwise.googlecode.com/hg/ counterclockwise is empty |
| 04:58 | ambient | arussel might be a problem with googlecode |
| 04:58 | ambient | they juse changed how their repos work iirc |
| 05:00 | hiredman | ~ccw |
| 05:00 | clojurebot | Counterclockwise aka ccw at http://code.google.com/p/counterclockwise/ |
| 05:01 | ambient | hiredman if you browse she source from there, you will notice it is empty |
| 05:05 | hiredman | I was just checking |
| 05:05 | hiredman | I know, uh, the guy that does the ccw stuff just stuffed a mess of urls into clojurebot the other day |
| 05:06 | kyromancer | arussel, http://github.com/laurentpetit/ccw |
| 05:06 | cgrand | ~ccw is http://github.com/laurentpetit/ccw |
| 05:06 | clojurebot | Ack. Ack. |
| 05:06 | cgrand | ccw |
| 05:06 | cgrand | ~ccw |
| 05:06 | clojurebot | ccw is http://github.com/laurentpetit/ccw |
| 05:06 | hiredman | I think he was the one that set it to the google code url |
| 05:07 | kyromancer | github is just where the source is maintained, issues and wiki is on google code |
| 05:07 | hiredman | 2009:Oct:08:15:37:53 lpetit : clojurebot: ccw is <reply> Counterclockwise aka ccw at http://code.google.com/p/counterclockwise/ |
| 05:07 | arussel | fatal: http://github.com/laurentpetit/ccw/info/refs not found: did you run git update-server-info on the server? |
| 05:07 | hiredman | oh |
| 05:08 | hiredman | interesting |
| 05:09 | kyromancer | the clone url is different |
| 05:09 | kyromancer | git://github.com/laurentpetit/ccw.git |
| 05:10 | arussel | got it, thanks |
| 05:13 | arussel | I am not much of an eclipse coder, but it seams that the name of the folder in which we put the compiled class is hardcoded. |
| 05:14 | kyromancer | let me check |
| 05:15 | kyromancer | indeed, ClojureBuilder.java:124 |
| 05:16 | arussel | I would like to be able to have them also in a war/WEB-INF/classes folder. |
| 05:18 | arussel | or to change the folder to war/WEB-INF/classes. |
| 05:22 | kyromancer | hmm thats gonna be a problem... |
| 05:22 | kyromancer | you try linking classes to war/WEB-INF/classes |
| 05:23 | kyromancer | *could |
| 05:24 | kyromancer | it's a workaround at least if your OS supports it |
| 05:31 | arussel | that looks like an ok workaround :-) |
| 05:52 | G0SUB | OK, so I have written a wrapper on top of spymemcached, and I need to write some tests. what's the best way to temporarily bind some vars just for testing purposes? (I need to bind the client obj to some var). |
| 06:25 | arussel | kyromancer: what action would compile a file into the "classes" folder. It seems I can manage to do once and that's it. If I clean the project, classes just becomes empty, and nothing is compiled into it anymore |
| 06:25 | kyromancer | yeah that is a bit of an issue atm |
| 06:25 | kyromancer | compilation needs the REPL to run |
| 06:26 | kyromancer | since that is where to compilation is performed |
| 06:26 | kyromancer | try starting it |
| 06:27 | kyromancer | then CTRL+ALT+K in the editor |
| 06:27 | kyromancer | (Clojure->Compile...) |
| 06:28 | kyromancer | arussel: I am currently working on ways to improve compilation and Java interop |
| 06:29 | kyromancer | The other day I was trying to mash up wicket and clojure using ccw, and it was quite difficult |
| 06:29 | kyromancer | Eclipse was spitting out errros about not being able to clean the classes folder because the REPL was running |
| 06:30 | kyromancer | so I stopped the REPL and did a "Clean" |
| 06:30 | kyromancer | that of course deleted all the classes generated from clj |
| 06:31 | kyromancer | so I restarted REPL, compiled, stopped repl, refreshed project... |
| 06:31 | kyromancer | Maybe theres a better way |
| 06:31 | kyromancer | ..but I haven't found it yet |
| 06:54 | Chousuke | G0SUB: (binding [thing someotherthing] ...)? |
| 06:54 | Chousuke | G0SUB: you need to be careful if threading is involved, though. |
| 06:55 | G0SUB | hmm |
| 06:56 | G0SUB | Chousuke: I wanted to know if clojure.test provided a similar but more sugared construct. |
| 06:59 | G0SUB | Chousuke: I need to write a function/macro similar to memoize which caches the return vals in memcached. any tips on how to write something like that? |
| 07:04 | Chousuke | G0SUB: well, clojure.test also has fixtures but I'm not sure how to use those |
| 07:05 | Chousuke | G0SUB: isn't memoize enough? :) |
| 07:06 | Chousuke | anyway, one way to do it would be to have the function close over an atom for example. |
| 07:06 | G0SUB | Chousuke: memoize, is not enough :) Really need to use memcached. |
| 07:07 | Chousuke | ah, I guess I misunderstood your question |
| 07:08 | G0SUB | Chousuke: so instead of storing the ret val in an atom, I store it in memcached. |
| 07:08 | Chousuke | that might work. |
| 07:09 | G0SUB | Chousuke: OK. What's the best way to convert a function's name to a string? I am using (str (val f)) right now. |
| 07:09 | G0SUB | (var f) |
| 07:09 | G0SUB | not val. |
| 07:10 | Chousuke | I think that's just fine |
| 07:10 | Chousuke | hmm |
| 07:10 | Chousuke | ,(.toString +) |
| 07:10 | clojurebot | "clojure.core$_PLUS___4443@1fce83e" |
| 07:10 | G0SUB | hmm |
| 07:10 | Chousuke | if you're going to use it as a memcached id or something, you might want to use that, too. it'll work for any function |
| 07:11 | G0SUB | yeah, for the memcached key |
| 07:19 | G0SUB | I am always getting confused with the syntax of :use inside the :ns macro. |
| 07:19 | G0SUB | (:use [clojure.contrib seq-utils :only (str-join)]) |
| 07:19 | G0SUB | what's wrong wit that? |
| 07:19 | G0SUB | with |
| 07:21 | Chousuke | it's (:use (clojure.contrib [seq-utils :only (str-join)])) |
| 07:22 | G0SUB | ah |
| 07:23 | Chousuke | it takes a prefix list, which is a list containing the prefix and any number of library specifications (either plain symbols or vectors) |
| 07:24 | G0SUB | Chousuke: there seems to be a problem with var |
| 07:24 | G0SUB | (defn var-test |
| 07:24 | G0SUB | [f] |
| 07:24 | G0SUB | (str (var f))) |
| 07:24 | G0SUB | this gives an error. |
| 07:25 | Chousuke | that's because f is a local, and thus f names no var :) |
| 07:25 | G0SUB | dang |
| 07:26 | G0SUB | how do I get the name of the function then? |
| 07:26 | Chousuke | the function might not even have a name |
| 07:26 | Chousuke | but try the toString approach |
| 07:26 | G0SUB | right |
| 07:26 | G0SUB | ok |
| 07:27 | G0SUB | Chousuke: one concern is that the toString fn returns some extra stuff after the name of the function. I think it refers to the memory location or something. |
| 07:28 | G0SUB | as a result, it might not be the same for two different VMs running the same code. |
| 07:28 | Chousuke | hmm, yeah |
| 07:28 | Chousuke | it won't be :P |
| 07:28 | G0SUB | may be I can split the str at two underscores |
| 07:29 | Chousuke | how general do you need this memcache thing to be? |
| 07:29 | G0SUB | Chousuke: not a lot, really. but it should generate the same key for different VMs given the same fn and args |
| 07:30 | Chousuke | maybe the easiest solution would be to leave selecting a proper key to the user |
| 07:30 | G0SUB | Chousuke: hmm, you are right, I think. |
| 07:30 | Chousuke | so they could do (def memcached-foo (memcache "the.ns.foo" foo)) |
| 07:34 | G0SUB | Chousuke: makes sense. thanks for the tip. |
| 08:37 | mrBliss | I've got a question about zippers |
| 08:39 | mrBliss | suppose you want to represent a graph as a zipper |
| 08:39 | mrBliss | much like http://projecteuler.net/index.php?section=problems&id=18 |
| 08:40 | mrBliss | I only see a way to store values in the leaves, not in the branches |
| 11:04 | kyromancer | A question: Is there a particular reason that all the VARs in RT are static? |
| 11:05 | kyromancer | This makes cleanly separating independent clojure instances pretty hard... |
| 11:06 | kyromancer | Groovy and JRuby for example offer a runtime object that encapsulates the state so multiple instances don't step on each other's toes |
| 12:58 | raek | is there any difference between .. and -> besides that .. "adds dots" to the functions/methods? |
| 13:20 | chouser | raek: nope. if you look at their definitions in core.clj you'll see there are very similar. |
| 14:46 | itistoday | i'm looking through the code for compojure and I came across this: |
| 14:46 | itistoday | (fn [param-map, #^DiskFileItem item] |
| 14:46 | itistoday | what is that ',' doing there? |
| 14:47 | hoeck1 | itistoday: commas are whitespace in clojure |
| 14:47 | itistoday | hoeck1: thanks |
| 14:47 | itistoday | do you happen to know why they were added? |
| 14:48 | hoeck1 | maybe to enhance readability in this arglist |
| 14:49 | itistoday | oh i mean in general |
| 14:49 | hoeck1 | when printing maps, clojure puts commas between key-value pairs |
| 14:49 | tomoj | ,{1 2 3 4 5 6 7 8 9 10} |
| 14:49 | clojurebot | {1 2, 3 4, 5 6, 7 8, 9 10} |
| 14:49 | itistoday | ah i see |
| 14:49 | tomoj | much harder to read without commas |
| 14:50 | itistoday | so it's so that can be read back in? |
| 14:51 | Chousuke | nah, just for humans :) |
| 14:51 | Chousuke | the reader thinks commas are whitespace |
| 14:51 | itistoday | ah k, thanks |
| 14:52 | Chousuke | it's possible to abuse though :P |
| 14:52 | hoeck1 | but it would be nice to have one more reader-macro character, |
| 14:53 | Chousuke | what for? |
| 14:53 | hoeck1 | don't know (yet) |
| 14:53 | hoeck1 | maybe for arrays? |
| 14:54 | itistoday | personally i hope clojure doesn't stray any further away from its lisp roots than it has... |
| 14:54 | itistoday | syntax is the enemy ;-) |
| 14:56 | prishvin | Hello, I have netbeans repl saying "Unable to resolve classname: Color" when I have (import '(java.awt Color ) done, |
| 14:56 | prishvin | what might be the reason? |
| 15:07 | prishvin | any ideas? :) |
| 15:12 | chouser | prishvin: seems unlikely, doesn't it. |
| 15:13 | chouser | You're sure the file's getting saved and reloaded the way you think it is? No other errors? |
| 15:17 | prishvin | yes chouser, the file is saved and reloaded. it works if i use the full name like java.awt.Color |
| 15:17 | prishvin | like if import does not work |
| 15:30 | LauJensen | prishvin, netbeans and vim have been replaced by something called Emacs - everything works in there :) |
| 15:31 | prishvin | LauJensen, :) I am not the emacs guy, btw do you have function browser/list in there? |
| 15:31 | prishvin | I've had function browser when I used emacs for a while writing CL |
| 15:31 | LauJensen | yea sure, you mean by way of reflection for java stuff? |
| 15:33 | prishvin | no sorry, I must have said it wrong, I mean a list of functions, which are in the open source file, "source browser" |
| 15:34 | LauJensen | I think somebody made a speedbar integration, but Ive never looked into it |
| 15:34 | prishvin | well, netbeans has it, + its the best java ide, imo |
| 15:35 | LauJensen | k |
| 15:35 | prishvin | all works like a charm, except for (import...) |
| 15:38 | LauJensen | How about those JVM Summit videos, are they up yet ? |
| 15:39 | itistoday | rhickey: take a look at newlisp's documentation: http://www.newlisp.org/downloads/manual_frame.html |
| 15:40 | itistoday | rhickey: can be auto-generated using newlispdoc command: http://www.newlisp.org/downloads/newLISPdoc.html |
| 15:42 | Chousuke | I wonder where the clojure-contrib doc generator is being hosted :/ |
| 15:43 | itistoday | one other thing that i think clojure should borrow from newlisp is its strings ({}, [text][/text]) |
| 15:43 | itistoday | does clojure have escape-proof strings? |
| 15:43 | Chousuke | escape-proof? |
| 15:43 | itistoday | I.e. in newlisp this is a valid string: {hello "fool", I'm so "cool"} |
| 15:43 | Chousuke | they're java Strings |
| 15:43 | clojurebot | ☕ |
| 15:43 | itistoday | instead of: "hello \"fool\", I'm so \"cool\"" |
| 15:44 | Chousuke | no such thing |
| 15:44 | itistoday | it would be *great* if it did... |
| 15:44 | Chousuke | it's a neat feature, yeah. |
| 15:44 | Chousuke | but what do you propose as the syntax? |
| 15:45 | itistoday | it's a problem for clojure to use {} of course |
| 15:45 | itistoday | or [] |
| 15:45 | itistoday | or () |
| 15:45 | itistoday | so... i'm not sure |
| 15:45 | itistoday | how about <> |
| 15:45 | itistoday | i don't think those are being used for anything right? |
| 15:45 | itistoday | it would be best for it to be one-character, whatever the delimiter ends up being |
| 15:45 | Chousuke | other than being valid in symbols, no ;/ |
| 15:46 | Chousuke | how do you suppose we'd deal with (< 1 2 3)? :/ |
| 15:46 | itistoday | good question |
| 15:46 | LauJensen | <> is xml property |
| 15:46 | itistoday | clojure might not be able to do it with only one char... |
| 15:46 | itistoday | perhaps something like /* */ :-p |
| 15:46 | Chousuke | :P |
| 15:47 | LauJensen | How about #"" ? |
| 15:47 | itistoday | that's already used |
| 15:47 | itistoday | for regex's |
| 15:47 | itistoday | but good idea |
| 15:47 | LauJensen | yea, but for something as useless as regex |
| 15:47 | LauJensen | so scrap that |
| 15:47 | Chousuke | :P |
| 15:47 | LauJensen | Who would miss regex? |
| 15:47 | itistoday | lots of people :P |
| 15:47 | LauJensen | ~regex |
| 15:47 | clojurebot | Sometimes people have a problem, and decide to solve it with regular expressions. Now they have two problems. |
| 15:47 | LauJensen | See... :) |
| 15:47 | itistoday | haha |
| 15:48 | LauJensen | According to my last blogpost, regex is for dweebs :) We have to go by that |
| 15:48 | itistoday | i like the idea though |
| 15:48 | itistoday | some other char though |
| 15:48 | itistoday | and we can't use " |
| 15:48 | itistoday | it can't be #"" b/c we can't use # or " |
| 15:48 | itistoday | and it can't be #{} because that's already used too |
| 15:49 | itistoday | so how about #[] ? |
| 15:49 | Chousuke | I'd rather save that for some data structure |
| 15:49 | itistoday | k... |
| 15:50 | Chousuke | something like #rDfooD where D is the delimiter wouldn't be too bad |
| 15:50 | itistoday | well whatever it ends up being another constraint is that it has to play nice with regex's |
| 15:50 | itistoday | in newlisp {} are used all the time for regex's |
| 15:51 | itistoday | so that you don't have to do extra escaping |
| 15:51 | Chousuke | the regex literals have different escaping rules from plain strings |
| 15:52 | itistoday | right, but it's handy nonetheless, as it does let you avoid escaping a bunch of stuff |
| 15:53 | itistoday | [t]my text[/t] ? |
| 15:53 | Chousuke | [t] is a vector :P |
| 15:53 | LauJensen | Still looks good though |
| 15:54 | itistoday | running out of symbols |
| 15:54 | itistoday | s/symbols/characters/ |
| 15:55 | itistoday | s{my "escaped" string?} |
| 15:55 | Chousuke | needs the # prefix |
| 15:55 | itistoday | can't have it |
| 15:55 | itistoday | that's a set |
| 15:55 | Chousuke | no, I mean #s{...} |
| 15:55 | itistoday | oh |
| 15:55 | Chousuke | as I suggested earlier :) |
| 15:56 | Chousuke | though a bit more general |
| 15:56 | itistoday | :-) |
| 15:56 | itistoday | so #s{blah..} is good? |
| 15:56 | itistoday | it seems to fit clojure's use of # |
| 15:57 | Chousuke | that would be easy to implement and wouldn't reserve any very important characters. |
| 15:57 | itistoday | where should I send the recommendation? |
| 15:57 | itistoday | bzr-dev? |
| 15:57 | itistoday | (list) |
| 15:57 | itistoday | errr |
| 15:57 | itistoday | lol |
| 15:57 | Chousuke | the list, yeah. :P |
| 15:57 | itistoday | clojure-dev list |
| 15:58 | Chousuke | not the developer list though. the public list :) |
| 15:58 | itistoday | just wondering, but why? |
| 15:58 | itistoday | isn't this a dev decision? |
| 15:59 | Chousuke | the dev list is for discussing the implementation mostly |
| 16:00 | itistoday | rhickey: when you get back, check out the discussion above on #s{ ... } |
| 16:00 | Chousuke | a raw string reader macro would be quite useful for docstrings |
| 16:00 | Chousuke | which often contain bits of code |
| 16:00 | itistoday | that's true |
| 16:01 | itistoday | that way you could easily include sample code, something that the docs desperately need |
| 16:01 | Chousuke | you can include it now, too, but writing strings is a bit ugly. |
| 16:02 | itistoday | btw, can i join the clojure group without a gmail account? |
| 16:02 | itistoday | (if so, how?) |
| 16:03 | Chousuke | you need a google account I think |
| 16:04 | itistoday | not cool google... |
| 16:04 | Chousuke | hmm, I can send invitations it seems |
| 16:04 | Chousuke | I don't know what that actually does, but give me your email address and I'll send you one :P |
| 16:04 | rlb | itistoday: you don't have to have a gmail account, just a google account -- though I agree, still unfortunate for a list. |
| 16:05 | itistoday | rlb: the invitation should work? |
| 16:05 | itistoday | Chousuke: pm sent |
| 16:05 | Chousuke | I have no idea if the invitation does anything special |
| 16:05 | Chousuke | or if it's just a "plz join" spam message :P |
| 16:06 | Chousuke | but sent it anyway |
| 16:06 | rlb | itistoday: you don't need an invitation -- you can create an account for this purpose yourself. |
| 16:07 | itistoday | Chousuke: i got the invite, thanks, it contained a link, i seem to have been subscribed, might take a bit to see if it actually worked though |
| 16:07 | Chousuke | itistoday: I wonder if you'll be able to post without a google account though :/ |
| 16:08 | itistoday | Chousuke: have you noticed anyone on the list without one? |
| 16:08 | itistoday | i seem to recall on another list people doing so |
| 16:08 | itistoday | so i think it's possible |
| 16:09 | Chousuke | itistoday: http://groups.google.com/support/bin/answer.py?hl=en&answer=46438 |
| 16:10 | hiredman | it's not actually mailing list, it is a google group, which needs a google account, you just have the option of using it via email |
| 16:11 | Chousuke | you can post by sending mail to clojure@googlegroups.com apparently |
| 16:11 | itistoday | cool, thanks |
| 16:11 | itistoday | although i was expecting an email to arrive saying "you've joined! here's what you can do:..." |
| 16:12 | itistoday | someone should post to the group though and i should get the email though, if that doesn't happen within 4 hours i'll just sign on via gmail |
| 16:13 | hiredman | the first message to the group requires a moderator to sign off on it |
| 16:14 | itistoday | hiredman: that doesn't affect receiving emails though right? |
| 17:39 | itistoday | fyi i've sent an email to the clojure group regarding the #s{ ... } construct, hopefully a mod will approve it soon |
| 17:40 | spaceman_stu | I'd like write a macro that would generate a few helper functions. defn'ing them from within the macro seems problematic - what's the right approach there? maybe return a hash with the funcs as keys? |
| 17:42 | Chousuke | keys? you mean values? :P |
| 17:42 | spaceman_stu | details =] |
| 17:43 | spaceman_stu | but yeah, so would something along those lines be the preferred appraoch? |
| 17:43 | Chousuke | do you need to generate these functions at runtime? |
| 17:43 | spaceman_stu | no |
| 17:44 | spaceman_stu | I know them beforehand |
| 17:44 | Chousuke | then I guess macros might be a better choice |
| 17:45 | Chousuke | you can have a (defmacro gen-funcs [some params] (list 'do `(defn firstone ..) `(defn secondone ...)) |
| 17:45 | Chousuke | the (list 'do ..) because nesting ` is a bit icky :) |
| 17:45 | spaceman_stu | hm, yeah, that could the reason it's not working now |
| 17:54 | itistoday | ~seen rhickey |
| 17:54 | clojurebot | rhickey was last seen joining #clojure, 623 minutes ago |
| 17:54 | itistoday | ,(/ 623 60) |
| 17:54 | clojurebot | 623/60 |
| 17:54 | itistoday | ... |
| 17:54 | itistoday | ,(int (/ 623 60)) |
| 17:54 | clojurebot | 10 |
| 17:55 | itistoday | ,(float (/ 623 60)) |
| 17:55 | clojurebot | 10.383333 |
| 18:03 | itistoday | how do i check if a symbol is bound? |
| 18:03 | itistoday | i.e. (def x) |
| 18:03 | itistoday | then what to check if it's bound? |
| 18:04 | itistoday | (as that will leave it unbound) |
| 18:04 | Chousuke | (try x 'BOUND (catch SomeException e 'UNBOUND)) :P |
| 18:05 | itistoday | ok, then i should change my question as that's not the solution i'm looking for |
| 18:06 | itistoday | how do you create a closure that increments a counter? |
| 18:06 | itistoday | i.e. (defn counter ... ) |
| 18:06 | itistoday | (counter) => 1 |
| 18:06 | itistoday | (counter) => 2 |
| 18:06 | itistoday | etc. |
| 18:06 | Chousuke | that's bad style :) |
| 18:06 | itistoday | that's a common thing to do |
| 18:07 | Chousuke | not in clojure though |
| 18:07 | itistoday | can clojure not do it? |
| 18:07 | Chousuke | but, (let [ctr (atom 0)] (defn counter [] (swap! counter inc))) |
| 18:07 | Chousuke | you're strongly encouraged not to do this though :P |
| 18:07 | clojurebot | this is not a bug |
| 18:08 | Chousuke | rather, have the counter in an atom or a ref and increment it explicitly :) |
| 18:08 | itistoday | k... but what is that code doing..? |
| 18:08 | itistoday | where is ctr used? |
| 18:09 | Chousuke | whoops |
| 18:09 | Chousuke | the first argument to swap! should be ctr |
| 18:10 | Chousuke | ,(let [a (atom 0) b (fn [] (swap! a inc)] [(b) (b) (b)]) |
| 18:10 | clojurebot | Unmatched delimiter: ] |
| 18:10 | Chousuke | ,(let [a (atom 0) b (fn [] (swap! a inc))] [(b) (b) (b)]) |
| 18:10 | clojurebot | [1 2 3] |
| 18:11 | itistoday | ok cool, thanks |
| 18:11 | itistoday | and why an atom and not a var? |
| 18:11 | Chousuke | a var is usually not intended to be changed |
| 18:11 | Chousuke | locally rebound, perhaps, but not changed |
| 18:12 | itistoday | hmm.. thanks, i'll wrap my head around this soon... |
| 18:13 | itistoday | how does one create a local var? |
| 18:13 | Chousuke | (doc with-local-vars) |
| 18:13 | clojurebot | "([name-vals-vec & body]); varbinding=> symbol init-expr Executes the exprs in a context in which the symbols are bound to vars with per-thread bindings to the init-exprs. The symbols refer to the var objects themselves, and must be accessed with var-get and var-set" |
| 18:13 | Chousuke | but that's almost never used. |
| 18:13 | Chousuke | in fact, I can't think of any good use for it :P |
| 18:14 | itistoday | well, i was looking at the docs on var |
| 18:14 | itistoday | http://clojure.org/vars |
| 18:14 | itistoday | and it says that set! can't be used to change a root binding |
| 18:14 | itistoday | so how do i create a var that is not in the root binding? |
| 18:14 | Chousuke | you don't. :) |
| 18:15 | Chousuke | you use the binding macro to rebind it locally |
| 18:15 | itistoday | so when is set! used? |
| 18:15 | itistoday | is it used often? |
| 18:16 | Chousuke | within a dynamic scope where a var has been thread-locally bound |
| 18:16 | Chousuke | eg, (binding [*someglobal* 4] (foo)) |
| 18:16 | Chousuke | now foo can be a function that uses set! on *someglobal* |
| 18:17 | itistoday | that seems like it would be a very rare thing to do |
| 18:17 | itistoday | or at least in poor taste |
| 18:17 | itistoday | i.e. foo would require that it be run inside the binding macro and nowhere else |
| 18:17 | itistoday | right? |
| 18:17 | Chousuke | well, using set! is fairly rare, but binding stuff like that isn't |
| 18:17 | Chousuke | set! is thread-safe though. :) |
| 18:17 | Chousuke | because var bindings are thread-local |
| 18:18 | Chousuke | the root binding isn't, so that's why you can't use set! on it. |
| 18:18 | itistoday | is 'binding' used often? |
| 18:18 | itistoday | i can't imagine a situation where i'd want to use it |
| 18:18 | Chousuke | pretty often I think. |
| 18:19 | itistoday | can you give an example? sorry if i'm asking too many questions btw |
| 18:20 | Chousuke | itistoday: well, you could have some code that depends on a database being specified, and you could use a global *db* that is initially unbound, but when you actually call the database functions, you bind it with (binding ...) |
| 18:20 | Chousuke | usually wrapped with some macro magic so that you can use (with-database-connection conn (some-db-stuff) (more-db-stuff))) |
| 18:20 | itistoday | does that mean you'd have to establish a db connection each time you want to do something? |
| 18:21 | Chousuke | itistoday: no, you can establish the db connection beforehand |
| 18:21 | Chousuke | and just bind *db* to that whenever you use the db functions |
| 18:21 | itistoday | why not have the *db* always bound? |
| 18:22 | Chousuke | will you always have a connection? :) |
| 18:22 | Chousuke | you might also want to have multiple connections |
| 18:23 | itistoday | ok, so you're saying that functions can reference *db* and just require they be called in a binding on *db* |
| 18:23 | itistoday | where is the actual connection stored though? |
| 18:23 | Chousuke | yes. |
| 18:23 | itistoday | on another var? |
| 18:23 | itistoday | or an atom? |
| 18:23 | Chousuke | wherever you like |
| 18:23 | raek | when is var-quote useful? |
| 18:24 | raek | in (send *agent* #'do-stuff) ? |
| 18:25 | itistoday | actually, that's another question i had, what is the purpose of #'blah |
| 18:26 | itistoday | i.e. the var function? |
| 18:26 | itistoday | ,(doc var) |
| 18:26 | clojurebot | Titim gan éirí ort. |
| 18:26 | itistoday | wtf |
| 18:27 | raek | that's var-quote |
| 18:27 | itistoday | ,(doc var-quote) |
| 18:27 | clojurebot | No entiendo |
| 18:27 | Chousuke | ,'#'foo |
| 18:27 | clojurebot | (var foo) |
| 18:27 | raek | it gives you the var bound to the symbol |
| 18:27 | Chousuke | itistoday: var is a special form, no doc string for it :) |
| 18:28 | Chousuke | #'foo is identical to (var foo) |
| 18:28 | raek | so, when should one use var-quotes? |
| 18:29 | raek | do they force a lookup when they are evaluated? |
| 18:29 | Chousuke | when you want the var named by a symbol :/ |
| 18:29 | Chousuke | which does happen sometimes |
| 18:29 | Chousuke | itistoday: http://gist.github.com/207927 |
| 18:30 | Chousuke | whoops |
| 18:30 | Chousuke | typo in comment. |
| 18:30 | Chousuke | the first one of course results in 15 :P |
| 18:31 | itistoday | thanks |
| 18:31 | itistoday | i see that now |
| 18:31 | itistoday | i'm trying to reconcile my existing knowledge with clojure |
| 18:31 | itistoday | and it's hurting |
| 18:31 | itistoday | heh |
| 18:31 | Chousuke | dynamic scope is a bit weird :) |
| 18:31 | itistoday | well i know dynamic scope |
| 18:32 | raek | if I run (send-off some-agent some-fn), will some-fn be looked up only once? |
| 18:32 | itistoday | i'm trying to figure out how to do lexical scope to create a counting function |
| 18:32 | raek | *if I run .. from "some-agent" |
| 18:32 | itistoday | and i take it that i need to use an atom, but if i'd rather use a var |
| 18:33 | raek | that is, do I have to use var-quote if I want to be able to "monkey patch" the code? |
| 18:33 | Chousuke | raek: hm, I'm not sure about that actually. |
| 18:33 | Chousuke | try it and see :) |
| 18:34 | raek | it looks like #'some-fn and some-fn doesn't make any difference |
| 18:34 | Chousuke | it sometimes does though IIRC. |
| 18:34 | Chousuke | maybe only if you're storing it in a data structure. |
| 18:35 | itistoday | Chousuke: how do i make a correct version of this: (defn new-counter [] (binding [x 0] (fn [] (set! x (+ 1 x)) x))) |
| 18:35 | itistoday | i'm pretty sure that i'm using binding incorrectly |
| 18:35 | itistoday | but all i want is a variable with that closure |
| 18:35 | itistoday | that the function can manipulate |
| 18:35 | itistoday | or is that not possible in clojure? |
| 18:36 | Chousuke | itistoday: you need an atom |
| 18:36 | Chousuke | or a ref, or an agent, but an atom is simpler |
| 18:37 | itistoday | (defn new-counter [] (let [x (atom 0)] (fn [] (swap! x inc) x))) ? |
| 18:37 | itistoday | that seems to work |
| 18:37 | Chousuke | yeah, it closes over the atom |
| 18:37 | Chousuke | the x at the end is redundant though |
| 18:37 | itistoday | oh, didn't know |
| 18:37 | Chousuke | actually, it's wrong. you meant @x :) |
| 18:38 | Chousuke | x is the atom, @x is its value |
| 18:38 | itistoday | gotcha |
| 18:38 | itistoday | getting the hang of this... thanks :-) |
| 18:38 | Chousuke | but in any case, (swap! x inc) returns the new value |
| 18:38 | itistoday | right |
| 18:39 | itistoday | is there anything in clojure that is not thread-safe? |
| 18:39 | Chousuke | java interop :P |
| 18:39 | itistoday | gotcha, so using a value from a java object could be unsafe? |
| 18:40 | Chousuke | in clojure parlance, a "value" is an immutable things. |
| 18:40 | Chousuke | -s |
| 18:40 | Chousuke | but Java objects are not necessarily values |
| 18:40 | Chousuke | they might change, thus rendering them unsafe. |
| 18:40 | itistoday | a java object that has a public int x; using that x is unsafe right? and uh... what do i call that x if not a value? |
| 18:40 | itistoday | or a variable? |
| 18:41 | Chousuke | x is a variable I suppose, but the int is its value |
| 18:41 | Chousuke | an int is immutable |
| 18:41 | Chousuke | 5 is 5, no matter what you do :) |
| 18:42 | itistoday | right, ok, i'll learn to use the terms correctly too ;-) |
| 18:42 | itistoday | but the *variable* is unsafe? |
| 18:42 | Chousuke | yeah. |
| 18:42 | itistoday | what do people do about that? |
| 18:43 | Chousuke | you could do (def foo (YourObject.)), and depending on what happens, (.x foo) may return different values |
| 18:43 | Chousuke | so foo is not a value |
| 18:43 | Chousuke | itistoday: usually, people are very careful when dealing with mutable java things :) |
| 18:44 | Chousuke | immutable java things are safe of course, so not all interop is dangerous |
| 18:44 | itistoday | well i mean say they have a java object written to by multiple threads, do they wrap it in a clojure actor? |
| 18:44 | Chousuke | that's one way I guess. |
| 18:44 | itistoday | with my limited knowledge of clojure, that's what i'd do. ;-) |
| 18:45 | Chousuke | there's also the locking macro, but that's pretty rare :/ |
| 18:45 | Chousuke | I don't think I've ever seen it used :P |
| 18:45 | itistoday | it's like a mutex lock? |
| 18:45 | Chousuke | ~def locking |
| 18:46 | itistoday | pretty much a mutex i guess |
| 18:46 | Chousuke | I guess it's whatever the java synchronisation system uses |
| 18:46 | itistoday | monitors are similar to mutex locks no? |
| 18:47 | itistoday | `(let [lockee# ~x] |
| 18:47 | itistoday | is that # on the end doing anything special? |
| 18:47 | Chousuke | yes. it's an autogensym |
| 18:47 | itistoday | or is that just some bizarre naming convention |
| 18:48 | itistoday | ah, gotcha |
| 18:48 | itistoday | so that's how they're used |
| 18:48 | Chousuke | it can be used to avoid multiple evaluations of x |
| 18:48 | itistoday | i thought it was used to prevent name clashes? |
| 18:48 | Chousuke | that, too |
| 18:48 | itistoday | gotcha |
| 18:48 | itistoday | well, i think i've used up enough of your time :-p |
| 18:48 | itistoday | thanks for all your help |
| 18:49 | Chousuke | (let [x '(some-expensive-computation)] `(let [x x#] [x# x# x# ~x ~x ~x])) |
| 18:49 | Chousuke | ,(let [x '(some-expensive-computation)] `(let [x x#] [x# x# x# ~x ~x ~x])) |
| 18:49 | clojurebot | (clojure.core/let [sandbox/x x__4470__auto__] [x__4470__auto__ x__4470__auto__ x__4470__auto__ (some-expensive-computation) (some-expensive-computation) (some-expensive-computation)]) |
| 18:49 | Chousuke | oops |
| 18:49 | Chousuke | forgot to unquote the first x |
| 18:49 | Chousuke | and got them the wrong way around too |
| 18:49 | Chousuke | ... I guess I shoudl go to sleep :) |
| 18:49 | Chousuke | anyway, you get the idea. |
| 18:50 | Chousuke | ,(let [x '(some-expensive-computation)] `(let [x# ~x] [x# x# ~x ~x])) |
| 18:50 | clojurebot | (clojure.core/let [x__4474__auto__ (some-expensive-computation)] [x__4474__auto__ x__4474__auto__ (some-expensive-computation) (some-expensive-computation)]) |
| 18:50 | itistoday | yeah, i originally thought it was to be used the way you had it the first way around |
| 18:50 | itistoday | because I thought it was like (gensym) |
| 18:51 | itistoday | so, (let [x (gensym)] ... ) |
| 18:51 | itistoday | i figured it'd be (let [x x#] ... ) , or something like that |
| 18:51 | itistoday | but that wouldn't make sense |
| 18:51 | Chousuke | autogensyms are so much nicer than using gensym directly though |
| 18:52 | Chousuke | in the cases that you can use them, which is most of the time. |
| 18:52 | itistoday | right, i thought it was nifty when i saw it, and seeing it used now makes sense, i just never would have thought that code would work because i'd thought calling x# multiple times the way it does there could create multiple symbols |
| 18:53 | itistoday | somehow it doesn't though |
| 18:53 | Chousuke | ` contains a lot of magic |
| 18:54 | itistoday | ,`(let [#x 0] (println #x)) |
| 18:54 | clojurebot | No dispatch macro for: x |
| 18:54 | itistoday | why fail? |
| 18:54 | Chousuke | huh |
| 18:54 | Chousuke | ah |
| 18:54 | Chousuke | x#, not #x :D |
| 18:55 | itistoday | ,`(let [x# 0] (println x#)) |
| 18:55 | clojurebot | (clojure.core/let [x__4478__auto__ 0] (clojure.core/println x__4478__auto__)) |
| 18:55 | itistoday | lol |
| 18:55 | itistoday | hehe |
| 18:55 | Chousuke | if you want to see sq implemented in clojure, search http://github.com/Chousuke/clojure/blob/sq-macro/src/clj/clojure/core.clj for syntax-quote |
| 18:56 | itistoday | k, think that's too advanced for me right now though |
| 18:56 | itistoday | btw, how do i get that thing to print 0? |
| 18:56 | itistoday | ,`(let [x# 0] (println x#)) |
| 18:56 | clojurebot | (clojure.core/let [x__4482__auto__ 0] (clojure.core/println x__4482__auto__)) |
| 18:56 | itistoday | instead of that |
| 18:56 | Chousuke | eval it :) |
| 18:57 | Chousuke | macros in the end are just functions that produce data structures just like that. |
| 18:57 | Chousuke | the compiler just runs eval on it afterwards |
| 18:57 | itistoday | ,(eval `(let [x# 0] (println x#))) |
| 18:57 | clojurebot | DENIED |
| 18:57 | Chousuke | heh ;( |
| 18:57 | itistoday | that would have worked though right? |
| 18:57 | Chousuke | yes. |
| 18:57 | itistoday | k |
| 18:58 | Chousuke | it was a small epiphany for me when I finally understood macros. |
| 18:58 | itistoday | that happened to me as well, but that was a year ago when i was learning scheme |
| 18:59 | Chousuke | when I tried to learn CL I saw the backquote as some kind of magic that's macro only :/ |
| 18:59 | itistoday | since them i've forgotten about them because i've been using newlisp's fexprs |
| 18:59 | itistoday | that's about the stage that i'm back at right now too ;-) |
| 18:59 | Chousuke | heh. |
| 19:00 | Chousuke | but it really helps to realise that the backquote is just a convenience tool to replace a lot of manual calls to list and quote :P |
| 19:00 | itistoday | right |
| 19:00 | itistoday | i'm going to go back to that scheme tutorial and read about it, it had an excellent explanation |
| 19:01 | itistoday | http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z-H-10.html#node_chap_8 |
| 19:01 | itistoday | btw, i love clojure's logo, i just noticed the yin-yang in it |
| 19:02 | Chousuke | yeah, it's great |
| 19:03 | itistoday | ah, looks like my suggestion for #s{ ... } made it into the clojure list |
| 19:07 | kmurph79 | is there a function that returns true/false based on whether a regex matches a string; like: (re-match #"(9)" "298") => true |
| 19:07 | Chousuke | (doc re-match) |
| 19:07 | clojurebot | excusez-moi |
| 19:07 | Chousuke | hmm |
| 19:07 | Chousuke | ,(re-matches #"foo" "bar") |
| 19:07 | clojurebot | nil |
| 19:08 | Chousuke | ,(re-matches #"foo" "foo") |
| 19:08 | clojurebot | "foo" |
| 19:08 | Chousuke | maybe that's good enough? |
| 19:08 | kmurph79 | yeah |
| 19:08 | itistoday | ,(if (re-matches #"foo" "foo") "yes" "no") |
| 19:08 | clojurebot | "yes" |
| 19:08 | itistoday | ,(if (re-matches #"foo" "fzo") "yes" "no") |
| 19:08 | clojurebot | "no" |
| 19:08 | itistoday | yay |
| 19:08 | raek | ,(boolean (re-matches #"foo" "foo")) |
| 19:08 | clojurebot | true |
| 19:09 | raek | if you don't want to "leak" any details |
| 19:09 | kmurph79 | thanks |
| 19:13 | raek | is (doseq [x xs y ys] (fn-with-side-effects x y)) the same as (dorun (for [x xs y ys] (fn-with-side-effects x y))) ? |
| 19:31 | kmurph79 | what does the _ symbol do? |
| 19:32 | dreish | raek: They expand to different code, but as far as I know they're effectively the same thing. |
| 19:32 | kmurph79 | nm i think i got it |
| 19:33 | raek | (try (foo) (catch SomeException _ (bar))) |
| 19:34 | raek | in that case, you are not interested in the value that would have been assigned to the symbol in the place of _ |
| 19:34 | raek | (defn foo [_] (bar)) |
| 19:35 | raek | a function that takes one argument and discards it |
| 21:00 | steiger | hey guys. i'm trying to create my own data structure in clojure by using :gen-class and extending clojure.lang.ASeq (like StringSeq does). but, how should I call the superclass (ASeq) in the -init method? |
| 21:03 | arbscht | steiger: -init returns a vector including arguments for the superclass constructor, and your own state. the superclass constructor is called automatically with those args |
| 21:04 | arbscht | if you want to call any other overridden methods, use :exposes-methods |
| 21:05 | steiger | arbscht: oh, i see |
| 21:06 | steiger | arbscht: thank you |
| 21:18 | zaphar_ps | why does recur not work in an if expression? |
| 21:18 | zaphar_ps | it's still a tail call but if I put the tail call in an if expression it doesn't work |
| 21:19 | chouser | ,(loop [a 1] (if (< a 10) (recur (inc a)) a)) |
| 21:19 | clojurebot | 10 |
| 21:19 | chouser | works fine |
| 21:20 | zaphar_ps | hrmmm must have a paren out of place then :-) |
| 21:20 | itistoday | zaphar_ps: i hear it needs to be in the "right place" |
| 21:21 | itistoday | i.e., near the end |
| 21:21 | zaphar_ps | heh |
| 21:21 | zaphar_ps | found it |
| 21:21 | zaphar_ps | I hate it when you lose track of one. It's such a pain to track it down again |
| 21:31 | ynniv | hiredman: Does the XMPP code in clojurebot currently work? I'm having some trouble. |
| 21:35 | steiger | is it possible (if so, what is the best way) to implement a map structure that has different behavior on (first) (rest) and (seq), returning something like: (first {1 2 3 4}) -> {1 2} instead of [1 2] ? |
| 21:39 | ynniv | I don't know the answer to your question, but your question seems odd. Why would you want a dictionary from (first)? |
| 21:40 | itistoday | i think it makes sense, he wants the first key/value pair |
| 21:40 | itistoday | oh wait |
| 21:40 | itistoday | no, it is odd |
| 21:40 | ynniv | heh |
| 21:40 | itistoday | he's getting that already |
| 21:40 | itistoday | hehe |
| 21:42 | steiger | ynniv: i'm just experimenting |
| 21:42 | hiredman | ,(key (first {:a 1})) |
| 21:42 | clojurebot | :a |
| 21:42 | hiredman | ,(val (first {:a 1})) |
| 21:42 | clojurebot | 1 |
| 21:42 | ynniv | you're probably looking for "(apply hash-map (first { 1 2 3 4 }))" |
| 21:42 | steiger | hiredman: i'm aware you can do that |
| 21:43 | ynniv | is the goal to make a new data type that has an alternate definition of #'seq? |
| 21:43 | steiger | the focus of my question is: how to create a custom data structure with a custom (first) and (rest) semantics |
| 21:43 | steiger | ynniv: something like that, yes |
| 21:45 | steiger | think of the string data type: (seq str) returns a StringSeq, which is a string of chars |
| 21:45 | steiger | ,(type (seq "abc")) |
| 21:45 | clojurebot | clojure.lang.StringSeq |
| 21:46 | steiger | and (first "abc") returns \a |
| 22:17 | ynniv | steiger: that seems surprisingly difficult to accomplish. maybe I'm following the wrong trail? |
| 22:17 | ynniv | but I'm knee deep in Java, and not seeing a clear path out |
| 22:21 | ynniv | seq seems to operate on ISeq, which is a java interface that has more methods than I expected (through inheritence) |
| 22:43 | ynniv | steiger: (defn make-data [d] (proxy [clojure.lang.ISeq] [] (first [] (apply hash-map (first d))) (next [] (next d)) (more [] (rest d)) (cons [o] (cons d o)) (count [] (count d)) (empty [] (empty d)) (equiv [a] (= d a)) (seq [] (seq d)))) |
| 22:44 | ynniv | I only modified "first" to return a map |
| 22:46 | ynniv | actually, this might do it: |
| 22:46 | ynniv | (defn make-data [d] (proxy [clojure.lang.ISeq] [] (first [] (apply hash-map (first d))) (next [] (make-data (next d))) (more [] (make-data (rest d))) (cons [o] (cons d o)) (count [] (count d)) (empty [] (empty d)) (equiv [a] (= d a)) (seq [] (map #(apply hash-map %) (seq d))))) |
| 22:47 | ynniv | which would look really snazzy in a paste, but i'm tired |
| 22:47 | ynniv | answering questions like this one is a great way to learn a new system, tho |
| 23:01 | steiger | ynniv: sorry for the delay |
| 23:01 | ynniv | i used the time to format my code to be clojurebot friendly: |
| 23:01 | ynniv | ,(let [make-data (fn [d] (proxy [clojure.lang.ISeq] [] (first [] (apply hash-map (first d))) (next [] (recur (next d))) (more [] (recur (rest d))) (cons [o] (cons d o)) (count [] (count d)) (empty [] (empty d)) (equiv [a] (= d a)) (seq [] (map #(apply hash-map %) (seq d)))))] (seq (make-data { 'a 1 'b 2 }))) |
| 23:01 | clojurebot | ({a 1} {b 2}) |
| 23:01 | ynniv | and use #'recur for the first time |
| 23:02 | steiger | ynniv: thank you, that's what i wanted. i was trying to extend ASeq, but implementing ISeq really seems to be cleaner |
| 23:03 | ynniv | only because you can use convenient clojure funcs like "rest" instead of trying to bridge to java :) |
| 23:03 | ynniv | I am continually impressed by the design and implementation of clojure |
| 23:04 | steiger | indeed :] |