2009-09-30
| 00:45 | thedoor | wow |
| 00:45 | thedoor | a lot of people at this channel :P |
| 00:45 | arbscht | it is growing :) |
| 00:46 | thedoor | a work friend talk to me about clojure today, now im installing the nescessary thing to star :) |
| 00:46 | thedoor | start* |
| 00:51 | Raynes | thedoor: And it's the middle of the night for a lot of people. We get new people in here all the time. |
| 00:52 | Raynes | thedoor: I hope you have lots of fun with Clojure. :) |
| 00:52 | thedoor | here is 02:00 am :) |
| 00:53 | thedoor | i need to sleep but i need to star this :P |
| 00:53 | thedoor | start* |
| 00:53 | thedoor | sorry my bad english :( |
| 01:44 | hiredman | clojurebot: ping? |
| 01:44 | clojurebot | PONG! |
| 02:56 | yason | re |
| 03:06 | vy | Reading the Agents documentation... What does "dispatch" in "If during the function execution any other dispatches are made (directly or indirectly), they will be held until after the state of the Agent has been changed." expression? |
| 03:07 | hiredman | send or send-off |
| 03:08 | vy | Thanks. |
| 03:11 | vy | Dispatches on an agent are placed in a queue that are consumed by a thread pool? Right? If so, assuming mutation of the agent is serialized, what's the necessity/role of a thread pool in here? Wouldn't it be more simple to dedicate a single thread for an agent and its dispatch queue? |
| 03:13 | vy | Hrm... Or that "thread pool" is dedicated to "whole available agents"? |
| 03:14 | hiredman | send sends to a fixed size threadpool (I think it as 2+core count last I checked) |
| 03:14 | hiredman | send-off sends to a non-fixed size threadpool |
| 03:15 | hiredman | well, have 200 threads try to run on a 2 core machine is kind of, well, not entirely optimal |
| 03:16 | jdz | hiredman: optimal for what? |
| 03:17 | jdz | when i look in the process browser on my machine, there are 261 threads running currently |
| 03:17 | hiredman | thats a lie |
| 03:17 | vy | Hrm... Yeah, that's for sure. What I now realize is that: 1) There is a single (actually 2, one for "send" and another one for "send-off") dedicated thread pool and mutations to a single Agent is serialized. 2) No more than one thread tries to write to the same Agent at a time in the pool. |
| 03:17 | jdz | hiredman: says who? |
| 03:18 | hiredman | the processor is switching back and forth between 261 processes |
| 03:18 | hiredman | jdz: I just did (according to my logs) |
| 03:18 | jdz | well, then by your logic, what's the point of having 2+core count threads? why 2 more? |
| 03:19 | jdz | and JVM starts with how many threads? |
| 03:19 | hiredman | jdz: because threads might block for io or whatever |
| 03:19 | jdz | so, the original question stands... |
| 03:19 | vy | Sun Java System Application Server 9.1 Performance Tuning Guide > Thread Count [http://docs.sun.com/app/docs/doc/819-3681/6n5srlhod?a=view] |
| 03:26 | jdz | vy: that's about very specific purpose |
| 03:27 | jdz | vy: namely HTTP request handling |
| 03:27 | hiredman | everyone has some heuristic |
| 03:28 | hiredman | I've seen 1+core count, 2+core count, 5*core count |
| 03:28 | hiredman | there was a paper in acm like eight years ago that did some real math on the subject |
| 03:28 | jdz | lol, "real math" |
| 03:29 | hiredman | well, more than multiplication and addition |
| 03:33 | Fossi | hi |
| 03:38 | Fossi | cgrand: sorry to bother you, but you seem to be involved into hashmap development: is there a chance to make it serializable? |
| 03:52 | cgrand | Fossi: personally I don't care about java serialization so I won't push for it. Plus other clojure data structures doesn't implement serializable either. |
| 03:54 | Fossi | cgrand: well, at least in my clojure PersistenHashMap implements Serializable, but BitmapIndexedNode prevents it from actually being it |
| 03:54 | cgrand | hmm let me check |
| 03:55 | Fossi | and it's a pita to serialize a deep map (for memcache/jcache in this case) either way through serializable (because of maps and keywords) and through the reader because of 'custo,m' java classes that we can't read back |
| 03:56 | Fossi | so wanting to cache an object graph, we're stuck with walking it and transforming or such |
| 03:56 | hiredman | Fossi: you know about print-dup and #=()? |
| 03:56 | Fossi | hiredman: what does #=() do? |
| 03:56 | hiredman | #=() allows for limited read time evaluation |
| 03:56 | Fossi | i've tried print-dup and we couldn't get the things to read back in |
| 03:57 | hiredman | so you hook a custom method into, uh, I think it's called print-method |
| 03:57 | hiredman | ,(doc print-method) |
| 03:57 | clojurebot | "; " |
| 03:57 | hiredman | how useful |
| 03:57 | Fossi | ;D |
| 03:57 | hiredman | which prn uses |
| 03:57 | Fossi | yeah, i get that part, but how do i read it back in? |
| 03:58 | hiredman | it emits a some thing like "#=(java.util.ArrayList (1 3 4 5))" |
| 03:58 | hiredman | ,#=(java.util.ArrayList (1 3 4 5)) |
| 03:58 | clojurebot | Can't resolve java.util.ArrayList |
| 03:58 | hiredman | ,#=(java.utils.ArrayList (1 3 4 5)) |
| 03:58 | clojurebot | java.utils.ArrayList |
| 03:58 | hiredman | bah |
| 03:58 | hiredman | ,#=(java.utils.ArrayList. (1 3 4 5)) |
| 03:58 | clojurebot | java.utils.ArrayList |
| 03:58 | Fossi | ok, that should prolly work |
| 03:59 | hiredman | ,#=(java.util.ArrayList. '(1 3 4 5)) |
| 03:59 | clojurebot | #<ArrayList [quote, (1 3 4 5)]> |
| 03:59 | hiredman | ,#=(java.util.ArrayList. (1 3 4 5)) |
| 03:59 | clojurebot | #<ArrayList [1, 3, 4, 5]> |
| 03:59 | hiredman | gah |
| 03:59 | hiredman | read time arraylist |
| 04:01 | Fossi | hiredman: i'll try and snoop around some more in the read and print code |
| 04:05 | cgrand | Fossi, for the record, PersistentHashMap implements Serializable through AFn and AFn was marked Serializable in commit "cleanup for findbugs" http://github.com/cgrand/clojure/commit/7cd3b285328e7e7e71b23080303d66640e0f21e8#diff-0 |
| 04:14 | LauJensen | Morning cgrand |
| 04:14 | cgrand | morning LauJensen |
| 04:24 | Fossi | cgrand: ok, so i guess that's a smallish 'bug' then |
| 04:24 | Fossi | since a lot of stuff is marked serializabel since a lot of things implement ifn :) |
| 04:24 | cgrand | ,(ancestors (class #(42))) |
| 04:24 | clojurebot | #{clojure.lang.IMeta clojure.lang.IFn clojure.lang.IObj java.lang.Object clojure.lang.Fn clojure.lang.Obj java.util.Comparator java.util.concurrent.Callable java.lang.Runnable :clojure.contrib.generic/any java.io.Serializable clojure.lang.AFunction clojure.lang.AFn} |
| 04:26 | Fossi | also a bit weird to have something callable marked as serializable :) |
| 04:36 | serp_ | ,(funcall) |
| 04:36 | clojurebot | java.lang.Exception: Unable to resolve symbol: funcall in this context |
| 04:37 | serp_ | ,(#(42)) |
| 04:37 | clojurebot | java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn |
| 04:37 | serp_ | ,#(42) |
| 04:37 | clojurebot | #<sandbox$eval__4764$fn__4766 sandbox$eval__4764$fn__4766@1324de2> |
| 04:37 | serp_ | I don't get it =( |
| 04:37 | serp_ | why would the second one work. |
| 04:39 | funkenblatt | well i think a better question is why the first one didn't work |
| 04:39 | funkenblatt | the second one is supposed to work |
| 04:41 | serp_ | I'm talking about ,(#(42)) |
| 04:41 | funkenblatt | oh |
| 04:41 | serp_ | shouldn't #(42) return a lambda function that simply returns 42, and is later evaluated |
| 04:43 | Fossi | ,(macroexpand-1 '(#(42))) |
| 04:43 | clojurebot | ((fn* [] (42))) |
| 04:44 | serp_ | oh I see... |
| 04:44 | Fossi | a smallish annoyance and source of common confusion |
| 04:44 | Fossi | but better than having to type #(( all the time |
| 04:45 | serp_ | I don't know... seems like magic to me... makes the language harder to understand |
| 04:45 | opqdonut | you can always use #(int 42) ;) |
| 04:45 | serp_ | unless... |
| 04:45 | serp_ | ,(macroexpand-1 '#42) |
| 04:45 | clojurebot | No dispatch macro for: 4 |
| 04:46 | serp_ | ,#42 |
| 04:46 | clojurebot | No dispatch macro for: 4 |
| 04:46 | serp_ | nope |
| 04:46 | Fossi | # is not the reader macro #( is |
| 04:46 | opqdonut | anyways, (constantly 42) is better |
| 04:46 | Fossi | sind # is used for a lot of things |
| 04:46 | Fossi | *since |
| 04:46 | opqdonut | , ((constantly 42) 0) |
| 04:46 | clojurebot | 42 |
| 04:47 | serp_ | so a construct with #( has an implied function call in it |
| 04:47 | Fossi | otherwise you would have to type #((some-fn %)) all the time |
| 04:48 | serp_ | sure, but then it is very clear what's going on =) |
| 04:51 | jdz | no, if just don't use the #() construct at all |
| 04:51 | jdz | then it's very clear what's going on |
| 04:57 | Chousuke | #() is a very useful shortcut sometimes, but it's not intended to replace fn |
| 04:58 | Chousuke | you can think of # as transforming a single expression into a function, if you want :P |
| 04:59 | Chousuke | (and that expression must be a list form) |
| 05:27 | Fossi | sometimes i miss #([(:a %) (:b %)]), but destructuring works better anyway |
| 05:41 | Chousuke | Fossi: or the new juxt |
| 05:41 | Chousuke | ,((juxt :a :b) {:a 1 :b 2 :c 3}) |
| 05:41 | clojurebot | java.lang.Exception: Unable to resolve symbol: juxt in this context |
| 05:41 | Chousuke | hm |
| 05:42 | Chousuke | clojurebot: you're old :( |
| 05:42 | clojurebot | No entiendo |
| 05:43 | Chousuke | Fossi: well, anyway, a new function was added recently, and #(vector (:a %) (:b %)) = (juxt :a :b) |
| 05:44 | cgrand | ,(#(map % [:a :b]) {:a 1 :b 2 :c 3}) ; not a vector though -- and juxt is better |
| 05:44 | clojurebot | (1 2) |
| 05:44 | serp_ | ,(#(list % %) 1 2) |
| 05:44 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--4786$fn |
| 05:44 | cgrand | (#(list %1 %2) 1 2) |
| 05:45 | serp_ | what does just % mean? |
| 05:45 | Chousuke | same as %1 |
| 05:45 | serp_ | oh |
| 07:42 | Drakeson | how can I use incanter on a headless machine? incanter imports processing.PApplet, which apparently asks for a graphical environment. Is there a standard way to deal with graphical packages when you run on a headless machine and don't need them but they are imported in the package? |
| 07:46 | dliebke | Drakeson: I shouldn't import PApplet in incanter.core, I'll try and remedy that today |
| 07:47 | Drakeson | thanks |
| 07:49 | Drakeson | one more thing, incanter places the dependencies in the git repos. maybe what compojure does is a bit better. compojure zips and puts the deps in github using the `upload' feature, and just places a link in the main repo. |
| 07:50 | dliebke | Drakeson: there has been discussion about using Maven to manage dependencies |
| 07:52 | Drakeson | that would be cool :) (I often follow discussions about package managers, and dependency resolvers). |
| 08:38 | Fossi | i'm getting a "Caused by: java.lang.NoSuchMethodError: clojure.lang.Namespace.importClass(Ljava/lang/Class;)Ljava/lang/Class;" when building from ant, but not from emacs using the same clojure.jar |
| 08:39 | Fossi | it's behaving really weird |
| 09:00 | ar1 | It's so quiet. |
| 09:16 | Fossi | ar1: so? |
| 09:16 | Fossi | btw: my problem was solved by running ant clean and thus deleting our target dir. no idea what went wrong inbetween |
| 09:38 | AWizzArd | Is there an easier way to do (.toString (.format (java.text.SimpleDateFormat. "yyyy-MM-dd_HH-mm-ss-SSS") (java.util.Date.) (StringBuffer.) (java.text.FieldPosition. 0)))? |
| 09:38 | AWizzArd | ,(.toString (.format (java.text.SimpleDateFormat. "yyyy-MM-dd_HH-mm-ss-SSS") (java.util.Date.) (StringBuffer.) (java.text.FieldPosition. 0))) |
| 09:38 | clojurebot | "2009-09-30_06-43-03-925" |
| 09:39 | rsynnott | heheh, poor clojure hasn't quite escaped the terrifying Java date classes, then? :) |
| 09:39 | rsynnott | someone should write a nice wrapper |
| 09:39 | chouser | someone did |
| 09:39 | chouser | they got shouted down for not just using JediDate or whatever it's called |
| 09:40 | chouser | ,(.format (java.text.SimpleDateFormat. "yyyy-MM-dd_HH-mm-ss-SSS") (java.util.Date.)) |
| 09:40 | clojurebot | "2009-09-30_06-45-36-693" |
| 09:41 | rsynnott | (presumably there on the basis that the world might arbitrarily start using a different calendar) |
| 09:41 | AWizzArd | chouser: oh good, this is much nicer |
| 09:42 | AWizzArd | strange i didn't see this on the api page of SimpleDateFormat |
| 09:44 | manic12 | this may sound like backward steps to clojurites, but it is true that ordinary single-object dispatch (smalltalk/flavors style) is quite useful to engineers... |
| 09:45 | chouser | manic12: sure. Clojure uses it all the time. |
| 09:45 | manic12 | I haven't learned enough clojure to do that in clojure |
| 09:45 | chouser | because the JVM can do it *fast*, mostly. |
| 09:46 | manic12 | and I also haven't learned how to create generative style extensions to that |
| 09:47 | chouser | conj is single-dispatch on the type of the first arg |
| 09:48 | chouser | for example |
| 09:50 | manic12 | another thing, I haven't learned how to write declaratively in clojure, just functional with procedural aspects mostly talking to java libs |
| 09:52 | Fossi | re serialization: now we have some trouble serializing structs. it seems that they are treated as an persistentMap and that has a "create" method, but the structs don't |
| 09:53 | Fossi | so naturally, things break |
| 09:57 | manic12 | I would like to create an 'object' which behaves a bit like a map, that instead of simply fetching the value, it calls a function on itself to compute and memoize the value, seems a bit anti-immutable |
| 09:59 | manic12 | but maybe that's ok, because it would be easier to implement 'undo' |
| 09:59 | manic12 | anybody there? |
| 10:00 | chouser | did you ask a question? |
| 10:00 | manic12 | i am asking how to do that sort of thing with clojure |
| 10:01 | chouser | one way would be to implement clojure.lang.IPersistentMap using proxy |
| 10:01 | manic12 | what about just deriving a actual java class? |
| 10:03 | chouser | ,(let [m (proxy [clojure.lang.APersistentMap] [] (valAt [_] 5) (seq [] nil))] [(get m :foo) (:bar m) (seq m)]) |
| 10:03 | clojurebot | [5 5 nil] |
| 10:04 | tmountain | chouser: that's pretty nifty |
| 10:06 | jdz | why the hell does slurp declare the f parameter as String? |
| 10:07 | tmountain | jdz: it takes a string pointing to the file |
| 10:07 | jdz | and why does it care if i pass it an instance of java.io.File? |
| 10:07 | tmountain | $ echo "foo" > /tmp/foo.txt |
| 10:08 | tmountain | (slurp "/tmp/foo.txt") |
| 10:08 | tmountain | "foo\n" |
| 10:09 | jdz | tmountain: and notice that (slurp (new java.io.File "/tmp/foo.txt")) does not work :/ |
| 10:10 | tmountain | jdz: yeah, looking at its implementation, slurp creates a FileInputStream in the background with f as it's argument |
| 10:10 | jdz | despite the fact that java.io.FileInputStream accepts java.io.File in the constructor |
| 10:10 | tmountain | jdz: yeah, that does sort of limit it's utility |
| 10:13 | tmountain | jdz: slurp uses the two argument form for the FileInputStream constructor |
| 10:14 | tmountain | jdz: to allow specification of encoding |
| 10:14 | jdz | tmountain: your point being? |
| 10:14 | jdz | tmountain: it uses it anyway even when passed only one parameter |
| 10:15 | tmountain | jdz: point being, you'd need another declaration to make it work with both a File and String |
| 10:15 | jdz | no |
| 10:16 | jdz | just drop the #^String thing |
| 10:16 | jdz | easy as that |
| 10:16 | manic12 | chouser: how do I access the proxy object if valAt is being defined in the proxy definition? |
| 10:17 | manic12 | i need the keys to be able to reference other keys |
| 10:17 | tmountain | jdz: my mistake, I see it's the InputStreamReader that takes the encoding argument |
| 10:18 | jdz | tmountain: my gripe with this is that somebody added the declaration although it does no good. |
| 10:18 | jdz | tmountain: same for the encoding |
| 10:19 | tmountain | jdz: yeah, you're right, I removed the type hint, and it works with a File as well |
| 10:20 | Chousuke | I suppose the type hint gives no measurable performance gain. :P |
| 10:21 | Chousuke | so it'd be better to remove it. |
| 10:21 | tmountain | yeah, I'd imagine there's miniscule difference in performance |
| 10:22 | Chousuke | if you wanted performance you wouldn't use slurp anyway |
| 10:22 | Chousuke | it's wasteful ;P |
| 10:22 | tmountain | using string builder |
| 10:22 | Chousuke | str uses a string builder internally. I mean storing an entire file in a string |
| 10:23 | tmountain | wasteful memory wise |
| 10:24 | manic12 | chouser: if you're there I want to post something |
| 10:28 | AWizzArd | Compojure users: anyone here who handles json requests? |
| 10:36 | manic12 | i would like to use clojure in a practical application, is there anyone here who can discuss how i might be able to satisfy some of the requirements with clojure? |
| 10:38 | manic12 | is anyone here at all? |
| 10:39 | rsynnott | hiding :) |
| 10:40 | manic12 | must be a coffee break |
| 10:44 | cemerick | we're all working :-P |
| 10:44 | arbscht | manic12: state your question and anyone who can answer it may... |
| 10:46 | manic12 | clojurebot: lisppaste |
| 10:46 | clojurebot | It's greek to me. |
| 10:46 | manic12 | is there a specific lisppaste for this irc channel? |
| 10:47 | ambient | M-x package-install lisppaste ;) |
| 10:47 | manic12 | tehe |
| 10:49 | Fossi | lisppaste8: url |
| 10:49 | lisppaste8 | To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste. |
| 10:50 | Fossi | manic12: there you go |
| 10:51 | lisppaste8 | manic12 pasted "how to do in clojure?" at http://paste.lisp.org/display/87950 |
| 10:51 | manic12 | thx |
| 10:58 | raek | how do I add my own directory to the CLASSPATH and still have the library paths in it? |
| 10:58 | raek | or -- how do I find my system default CLASSPATH? |
| 10:59 | raek | I ran "find /usr -name \*.jar -print" to find the jars in my system |
| 10:59 | raek | but they're evererywhere! |
| 11:05 | liwp | raek: on unix with bash: export CLASSPATH=path/to/foo.jar:path/to/classes:$CLASSPATH |
| 11:05 | raek | yes, I know |
| 11:06 | raek | but I sort of found a solution to my problem |
| 11:06 | liwp | ok, so what's the problem exactly |
| 11:06 | liwp | ok |
| 11:06 | raek | I specified the path to my own clj files with the -cp option to java |
| 11:06 | liwp | raek: that'll work |
| 11:06 | raek | but then I also had to add the path to the system jar files |
| 11:07 | liwp | you shouldn't have to do that. What do you mean with system jar files? |
| 11:08 | raek | I'm trying to get compojure running |
| 11:08 | raek | but it turned that I missed a dependency |
| 11:09 | raek | java.lang.ClassNotFoundException: org.mortbay.jetty.servlet.Context (jetty.clj:0) |
| 11:09 | raek | this is what I get when evaluating (use 'compojure) |
| 11:10 | raek | oh wait |
| 11:10 | raek | forgot to put the jar files produced by "ant deps" into my classpath |
| 11:11 | raek | you may ignore my previous 10 lines |
| 11:12 | liwp | heh |
| 11:12 | raek | java.lang.SecurityException: sealing violation: package org.mortbay.jetty.servlet is sealed (jetty.clj:0) |
| 11:13 | raek | ok, what have I done now? |
| 11:21 | raek | ok, working now |
| 11:22 | raek | removed jetty and firends with my package manager and used the jars supplied by compojure |
| 11:29 | kunjan | Is Clojure dynamically scoped in some cases? |
| 11:36 | yason | kunjan: I'm not an expert by any means but IIRC no. You could probably simulate dynamic scope with vars and (binding ...) |
| 11:40 | raek | (let) in clojure introduces lexically scoped variables |
| 11:40 | raek | and (binding) dynamically scoped ones |
| 11:44 | rhickey | raek: they aren't dynamically scoped, just dynamically bound. If you do (defn foo [] (use-some free-var)) it will fail at compile time if free-var isn't in scope, vs true dynamic scope where someone could establish free-var then call foo and have it find it |
| 11:45 | sproingie | http://onclojure.com/2009/05/06/simulating-dynamic-scoping/ |
| 11:46 | raek | ah, please bear with me. i've only used clojure for a week |
| 11:46 | sproingie | doesn't look like a general solution tho |
| 11:47 | raek | :rhickey ah, I see. |
| 11:49 | raek | these things are new to me, as I come from languages that doesn't have these things |
| 11:49 | raek | or I wasn't aware of them |
| 11:53 | raek | is it un-ideomatic to use variables with dynamic bindings as a way to not have to pass a certain arg to function? |
| 11:53 | raek | i'm coding some things that calculates the width and height of texts that will be drawn |
| 11:53 | raek | and these things depends on the Metrics of the font in use |
| 11:54 | rhickey | raek: if you are just starting out you should avoid dynamic binding |
| 11:54 | yason | raek: so what you want is an easy way to pass on state? |
| 11:55 | stuartsierra | I think it's idiomatic, but subject to a number of tricky bit when laziness & concurrency are involved |
| 11:55 | raek | (binging [metrics (.. label .getFont .getMetrics)]] (calculate-width "text")) |
| 11:56 | raek | and (calculate-width) then uses metrics |
| 11:57 | raek | but as the width is a function of both the text and the metrics, maybe I should pass along metrics as an arg |
| 11:58 | raek | that is the way I do it now |
| 12:04 | manic12_ | are object systems in general anti-clojure philosophy? |
| 12:05 | rhickey | manic12_: http://clojure.org/state |
| 12:05 | Makoryu | manic12_: Stateful objects are the bane of both concurrency and common sense. |
| 12:06 | rhickey | I don't know that anyone has reconciled OO with the problems enumerated there, but I don't think it is impossible. Whether the result would be considered OO anymore is another question |
| 12:07 | rhickey | OO includes a lot of things that Clojure delivers a la carte, like polymorphism and hierarchy |
| 12:07 | manic12__ | sorry my internet connection dropped, i think the router was rebooted |
| 12:08 | Makoryu | manic12__: http://clojure-log.n01se.net/ <- You can always use this to see what you missed. |
| 12:08 | manic12__ | thanks |
| 12:08 | Makoryu | Or, er, not, I suppose |
| 12:08 | Makoryu | I thought it updated more frequently |
| 12:09 | chouser | every 15 minutes right now |
| 12:09 | chouser | 20 minutes |
| 12:10 | Makoryu | manic12__: Anyway... https://gist.github.com/61e9ffb761b574428cc4 |
| 12:10 | manic12__ | i've got a declarative DSL built into clos, and i am interested in doing the same things with clojure |
| 12:11 | sproingie | might try spinoza or categories. not tried either myself so i couldnt say how good they are |
| 12:12 | sproingie | dammit.. |
| 12:12 | sproingie | manic12__: ^^^ |
| 12:13 | manic12__ | are those on github or somewhere? |
| 12:13 | sproingie | google code i think |
| 12:13 | sproingie | teh googelz knows :) |
| 12:13 | Draggor | Are there any lexers for Clojure? Something like cl-yacc? |
| 12:13 | manic12__ | oh wow |
| 12:14 | sproingie | neither spinoza nor categories defines a call-next-method tho, let alone a formal MRO |
| 12:15 | manic12__ | i actually don't need call-next-method because it makes no sense in the DSL |
| 12:16 | manic12__ | so categories is a drinking game |
| 12:16 | sproingie | hard to reconcile with the predicate dispatch of multifn's anyway |
| 12:16 | stuartsierra | Draggor: you could use ANTLR or JavaCC to generate a lexer |
| 12:17 | sproingie | manic12__: categories is at http://code.google.com/p/explorersguild/ |
| 12:17 | sproingie | somewhere in the source |
| 12:17 | Draggor | stuartsierra: the JavaCC site appears to be down. Does one have any particular features over the other? |
| 12:18 | cemerick | wasn't cgrand working on a slick clojure DSL for grammars? |
| 12:18 | sproingie | antlr has oodles of features. also a vertical learning curve, and some annoying conventions around lexer/parser distinctions |
| 12:20 | cgrand | cemerick: still working |
| 12:22 | cemerick | cgrand: just giving you the intro to do some promotion :-) |
| 12:22 | stuartsierra | Draggor: ANTLR is generally considered easier to use, but it requires a runtime library to run your parser. ANTLR generates recursive-descent parsers, JavaCC generates (I think) bottom-up parsers |
| 12:23 | cemerick | I got tired of javacc and antlr years and years ago. |
| 12:23 | stuartsierra | For very simple grammars (e.g., Lisp) they're overkill. |
| 12:23 | stuartsierra | But essential for parsing something like C. |
| 12:25 | manic12__ | cannot each change to an object be a new structure entirely? |
| 12:25 | Draggor | I'm just having fun and writing a parser for a die roller, something like [5d6] or [[1d6]d6] |
| 12:26 | Draggor | And then put math operations in it too |
| 12:26 | rsynnott | stuartsierra: quite a few C compilers have awful hand-made parsers |
| 12:27 | Draggor | Really it's just a calculator with another operator d and using [] for grouping instead of () |
| 12:27 | sproingie | isn't g++'s new parser a hand-rolled recdescent parser? |
| 12:28 | stuartsierra | rsynnott: really? ugh |
| 12:32 | manic12__ | i don't understand the difference between altering a ref and mutating state |
| 12:34 | sproingie | they are state |
| 12:34 | sproingie | but you can only change them in a transaction |
| 12:34 | manic12__ | it says that is "identity" |
| 12:34 | manic12__ | it doesn't matter if it's transactional |
| 12:35 | sproingie | clojure doesn't lack state completely, it just shoves it into some well-defined areas |
| 12:36 | manic12__ | that statement should be put on the clojure.org/state webpage |
| 12:39 | sproingie | that page gets a little overly focused on identity. refs are essentially first-class slots, just not necessarily "owned" by some structure. |
| 12:39 | manic12__ | ok |
| 12:40 | manic12__ | but oo is a bad idea? |
| 12:40 | sproingie | hardly |
| 12:41 | sproingie | oo doesn't even necessarily have to throw around uncoordinated mutable state |
| 12:41 | sproingie | it's just that most oo languages have few alternatives to doing so |
| 12:42 | sproingie | java has some immutable collections in libraries that are pretty efficient, but most people don't use them |
| 12:42 | sproingie | C++ STL is pretty much hopeless |
| 12:43 | sproingie | scala's the only oo language i can think of that has seriously decent functional objects |
| 12:43 | manic12__ | I'm looking at the "memoize" example and thinking about declarative oop |
| 12:45 | arohner | manic12__: in clojure, refs, atoms etc are a way to cleanly declare and isolate when & how state changes happen |
| 12:45 | manic12__ | not absolute declarative like prolog though, declarative where it makes sense to do so: storing knowledge |
| 12:45 | arohner | yes, they're all state changes, but clojure has much stricter guarantees about how they happen |
| 12:46 | sproingie | clojure has all the state of any imperative language, but everything stateful in clojure has some kind of synchronization primitive baked into it |
| 12:46 | sproingie | refs are transactional, agents have asynchronicity, and atoms are, well, atomic |
| 12:46 | sproingie | clojure has all kinds of state, it just doesn't have "naked state" |
| 12:46 | manic12__ | i haven't determined the difference yet |
| 12:47 | manic12__ | that's good |
| 12:47 | manic12__ | because it will make it easier to implement undo |
| 12:48 | sproingie | you could easily write a clojure program in completely imperative style, it's just that clojure steers toward a functional style |
| 12:48 | sproingie | by using immutable collections and so forth |
| 12:49 | rhickey_ | a point of Clojure is to separate identity, state and value |
| 12:49 | manic12__ | so clojure needs some object systems |
| 12:49 | rhickey_ | people throw around the term state without considering its meaning |
| 12:50 | manic12__ | i read the clojure.org/state page, and i'm one of those people apparently |
| 12:50 | sproingie | most people who aren't FP geeks will conflate them somewhat :) |
| 12:51 | sproingie | "pure" fp geeks don't even go in for the concept of "identity" |
| 12:51 | sproingie | insofar as being distinguishable from value that is |
| 12:51 | manic12__ | fp=functional programming? |
| 12:51 | sproingie | yep |
| 12:51 | milep | Hello, is there a good/standard way to use structmaps with sorted-set? Or should I create custom compare function and use that with normal set? |
| 12:51 | dnolen | sproingle: being the creator of spinoza, I would say don't bother. I haven't touched that project in ages :) it's best to just dive into fp style programming. |
| 12:51 | rhickey_ | by being atomic, and pointing to immutable composites, Clojure's reference types ensure transitions from value to value, and you can grab one of those values without getting trounced by future state transitions |
| 12:52 | rhickey_ | contrast that with objects that change in your hands |
| 12:52 | sproingie | dnolen: aw. i rather liked the idea of first-class protocols. |
| 12:52 | rhickey_ | those objects don't have obtainable state at all |
| 12:52 | dnolen | sproingie: yes, I think mikel's generic functions project is less half-baked tho. |
| 12:53 | sproingie | dnolen: is that the categories thing in explorersguild? |
| 12:53 | manic12__ | so if one thread grabs the state from the ref, it won't change on it underneath if another thread grabs it next |
| 12:53 | dnolen | sproingie: yes |
| 12:53 | rhickey_ | a state is a value at a point in time, being a value it can't change |
| 12:53 | rhickey_ | references just manage time |
| 12:54 | rhickey_ | objects typically conflate all three and become impossible to reason about |
| 12:54 | manic12__ | the most unfortunate thing about my code is that i use a huge c++ library! |
| 12:56 | manic12__ | but is my statement correct? about the state not changing from under a function in one thread because it's immutable? |
| 12:57 | rhickey_ | manic12__: state of what? values don't have state. If you get a value from a ref you are done with state |
| 12:57 | manic12__ | ok, so yes |
| 12:58 | manic12__ | the state doesn't change because it's not a state in the first place it's an immutable value |
| 12:59 | rhickey_ | manic12__: there is a thing with state (the reference). When you dereference it, you obtain its value at a point in time. That value is an immutable thing and has no state/time at all |
| 12:59 | manic12__ | i understand now |
| 13:00 | rhickey_ | I don't mean to be pedantic, but I am on a mission to clarify this I guess. So tired of OO muddle... |
| 13:01 | manic12__ | the c++ library suffers from exactly this stuff clojure is intended to solve |
| 13:01 | rhickey_ | Clojure disassembles OO and delivers it in orthogonal pieces |
| 13:01 | manic12__ | that's fine, i get it |
| 13:03 | manic12__ | but to do what I have coded in clos will require implementing some constructs i didn't have to before, that's what i was wondering |
| 13:03 | rhickey_ | the prize is obtainable values and the fact that you can write pure functions that work with them, completely independent of things relating to state. In most OO values are relegated to primitives |
| 13:03 | manic12__ | i should say meta programming in clos |
| 13:04 | rhickey_ | manic12__: porting from CLOS will require looking at how it is being used, what's stateful, what's inheritance driven etc. It is a rich polymorphism system for sure |
| 13:04 | manic12__ | it uses memoization heavily |
| 13:06 | manic12__ | i don't want to introduce uses of 'state' just because that's the way clos does it |
| 13:08 | manic12__ | the C++ code often destroys objects you pass into functions and you have to explicitly copy them first if you want to keep it |
| 13:10 | manic12__ | so it will be a challenge to make it appear like native code |
| 13:11 | chouser | "Take an old man's word; there's nothing worse than a muddle in all the world. It is easy to face Death and Fate, and the things that sound so dreadful. It is on my muddles that I look back with horror--on the things that I might have avoided." -- http://tinyurl.com/ychwqfp |
| 13:18 | rhickey_ | Chouser: love it! |
| 13:18 | Draggor | Anyone tried http://kotka.de/projects/clojure/parser.html ? |
| 13:19 | chouser | rhickey_: I'm not sure he was talking about identity-value conflation, but it'll do. |
| 13:30 | drewr | ,(#{false} [true false]) |
| 13:30 | clojurebot | nil |
| 13:30 | drewr | shouldn't that be false? |
| 13:31 | chouser | ,(#{false} true false) |
| 13:31 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: PersistentHashSet |
| 13:31 | chouser | hm |
| 13:31 | stuartsierra | ,(#{false} false) |
| 13:31 | clojurebot | false |
| 13:32 | chouser | drewr: sets return the matching value, else nil. |
| 13:32 | stuartsierra | ,(#{:a} :a) |
| 13:32 | clojurebot | :a |
| 13:32 | stuartsierra | ,(#{:a} [:a]) |
| 13:32 | clojurebot | nil |
| 13:33 | stuartsierra | ,(some #{false} [true false]) |
| 13:33 | clojurebot | nil |
| 13:33 | stuartsierra | ,(some #{:a} [:b :a]) |
| 13:33 | clojurebot | :a |
| 13:35 | drewr | chouser: isn't false the matching value though? |
| 13:36 | chouser | #{false} does not contain the vector [true false] |
| 13:36 | chouser | ,(#{:foo [true false] :bar} [true false]) |
| 13:36 | clojurebot | [true false] |
| 13:42 | hiredman | (#{false} false) |
| 13:42 | hiredman | ,(#{false} false) |
| 13:42 | clojurebot | false |
| 13:42 | hiredman | ,(#{nil} nil) |
| 13:42 | clojurebot | nil |
| 13:42 | hiredman | :( |
| 13:43 | chouser | ,(#{'spam} 'spam) |
| 13:43 | clojurebot | spam |
| 14:02 | drewr | chouser: oh, ok; I thought it wanted a coll there |
| 14:02 | drewr | which is what stuartsierra was demonstrating :-) |
| 14:04 | drewr | which makes sense when the set is callable there |
| 14:09 | bitbckt | Anybody have an easy way of taking an Array of N^2 items and splitting it into an NxN matrix? |
| 14:11 | ambient | x+y*width |
| 14:11 | chouser | ,(partition 4 (range 16)) |
| 14:11 | clojurebot | ((0 1 2 3) (4 5 6 7) (8 9 10 11) (12 13 14 15)) |
| 14:11 | bitbckt | chouser: That's what I was looking for. Thanks. |
| 14:16 | tmountain | has anyone seen this before? http://pleac.sourceforge.net/ |
| 14:17 | tmountain | it's a website featuring recipes from the perl cookbook implemented in a variety of programming languages |
| 14:17 | tmountain | good resource for finding out how to do something quickly in a given language |
| 14:18 | tmountain | I was thinking of starting a clojure module if anyone else is interested |
| 14:19 | tmountain | I contributed the ruby section on directories, and it was pretty fun |
| 14:20 | sproingie | pleac is pretty nifty |
| 14:20 | sproingie | good way to compare expressiveness |
| 14:20 | sproingie | adding clojure would be awesome |
| 14:21 | tmountain | sweet, I'll contact the project admin and see about getting it added |
| 14:35 | drewr | stuartsierra: your some example was also confusing me |
| 14:36 | stuartsierra | which one? |
| 14:36 | drewr | ,(some #{:foo} [:foo false true]) |
| 14:36 | clojurebot | :foo |
| 14:36 | drewr | ,(some #{false} [:foo false true]) |
| 14:36 | clojurebot | nil |
| 14:36 | stuartsierra | That happens because "some" tests the result of applying the predicate to an element in the sequence. "false" tests false! |
| 14:37 | drewr | that seems like a bug |
| 14:37 | stuartsierra | Not a bug, I think, but certainly an edge case. |
| 14:38 | stuartsierra | ,(some #(false? %) [:foo false true]) |
| 14:38 | clojurebot | true |
| 14:38 | chouser | you just have to be careful dealing with collections that might contain nil or false |
| 14:46 | drewr | kotarak: how's ClojureCheck coming? |
| 14:47 | kotarak | drewr: uhweuhm oehmm... |
| 14:47 | kotarak | drewr: falling off the spare time clip at the moment, I'm afraid. |
| 14:48 | kotarak | Although I'd really like to work on it.... I have to cut done my projects... |
| 14:49 | drewr | what's it lack? |
| 14:49 | kotarak | drewr: The TAP part is more or less complete, but the QuickCheck clone is a mess. I'd really like to clean that up. |
| 14:51 | drewr | k |
| 14:51 | kotarak | .. and make it work, actually... |
| 14:52 | drewr | a coworker started working on his own and didn't know whether to tell him to use yours :-) |
| 14:53 | kotarak | drewr: -.- I have to win in the lottery, so that I can quit my day job and start working full time on fun projects. ) |
| 14:53 | kotarak | :) |
| 14:54 | drewr | yep |
| 14:55 | kotarak | the job cuts away 43h (effectively 48h) per week, with the recently grown family and soon to be bought apartment the prospects are rather depressing from the clojure project point of view. (Although the last two points have higher priority than clojure... :)) |
| 14:57 | drewr | please put your family before clojure :-) |
| 14:58 | kotarak | Of course! :D |
| 14:59 | kotarak | drewr: but now that you asked, I will probably invest some time to drive CC a bit more. VimClojure ate a lot of time lately, too... |
| 16:08 | ngoc | Why "Logging str" is output 5 times in the example at http://clojure.org/concurrent_programming? |
| 16:10 | kotarak | ngoc: What do you expect? Have you had a look at the implementation of str? |
| 16:10 | arohner | lisppaste8: url |
| 16:10 | lisppaste8 | To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste. |
| 16:11 | kotarak | ngoc: http://groups.google.com/group/clojure/browse_frm/thread/9f8b14cd7cdf9f4d/90158571284ac1ef?q=loves+ethel+lucy+group:clojure for details |
| 16:12 | lisppaste8 | arohner pasted "get the value of a local at runtime?" at http://paste.lisp.org/display/87966 |
| 16:13 | arohner | is there any way to get the value of a local at runtime? and is there any way to implement value-of in a way that doesn't use eval? |
| 16:14 | hiredman | uh |
| 16:14 | kotarak | arohner: the only way I see is just returning expr from my-fun. |
| 16:14 | arohner | is there a way to edit the paste? |
| 16:14 | kotarak | you can annotate it |
| 16:14 | hiredman | there is no value at runtime |
| 16:14 | hiredman | err |
| 16:14 | hiredman | at compile time |
| 16:15 | lisppaste8 | arohner annotated #87966 "untitled" at http://paste.lisp.org/display/87966#1 |
| 16:15 | hiredman | when is when macro expansion happens |
| 16:15 | hiredman | there is just a datastructure |
| 16:15 | kotarak | arohner: that's not possible, as hiredman says. |
| 16:16 | arohner | the macro turns into code that calls (my-fun 'foo) |
| 16:16 | arohner | my-fun is run at runtime |
| 16:16 | arohner | ah, the paste is missing a ` |
| 16:17 | kotarak | And a quote on the expr. |
| 16:17 | lisppaste8 | arohner annotated #87966 "untitled" at http://paste.lisp.org/display/87966#2 |
| 16:17 | kotarak | But here expr gets evaluated. |
| 16:17 | manic12__ | i implemented a "destructive" assoc for structmaps which obviously doesn't destroy anything but does allow for undo and redo, you have to pack the structmap in another map and make a ref to it and pretend the ref is the structmap |
| 16:18 | arohner | sorry for the mistakes. I'm trying to create a simplified example. obviously I'm making mistakes in the translation |
| 16:18 | arohner | `(my-fun expr) |
| 16:18 | hiredman | manic12__: sounds horrible |
| 16:18 | manic12__ | that would have been a pain in CL because you need to copy the objects yourself |
| 16:18 | lisppaste8 | kotarak annotated #87966 "quoted expr" at http://paste.lisp.org/display/87966#3 |
| 16:19 | manic12__ | hiredman: why? |
| 16:19 | hiredman | manic12__: because then you are going to have a lot of little "mutable" structmaps |
| 16:20 | manic12__ | but you can undo them |
| 16:20 | arohner | interesting kotarak. is it possible to do the work in my-fun? |
| 16:20 | kotarak | arohner: which work? |
| 16:20 | tomoj | being able to undo doesn't make mutable state a good thing :) |
| 16:20 | hiredman | while controled mutation is better than uncontroled, immutability is better still |
| 16:20 | arohner | getting the value of expr. doing it in the macro rather than the function would make my code a lot more complicated |
| 16:20 | arohner | (or maybe my design is just wrong) |
| 16:21 | kotarak | arohner: well you do the work in the function. The macro just wraps everything up in a thunk, which is (maybe) called in the function to obtain the value. |
| 16:22 | manic12__ | i want to be able for the user of the DSL to def to the ref and keep a constant ref to an dynamic object |
| 16:23 | hiredman | :( |
| 16:23 | manic12__ | for animation and changing inputs/attributes |
| 16:25 | Chousuke | wouldn't a simple ref for the input do? |
| 16:25 | Chousuke | or inputs. |
| 16:26 | manic12__ | how do you synchronize the state of the object to acheive the undo/redo? |
| 16:26 | lisppaste8 | arohner annotated #87966 "untitled" at http://paste.lisp.org/display/87966#4 |
| 16:26 | Chousuke | hm. |
| 16:27 | Chousuke | I'm not quite sure what it is that you are doing now |
| 16:27 | Chousuke | how does your scheme allow for undo/redo? :/ |
| 16:27 | wavis | manic12__: instead of using a ref, just create and undo function that returns the previous map, which you had originally used assoc on |
| 16:28 | manic12__ | and even if the struct map gets really big I don't think clojure's copying of it would slow it down compared to the fact that the object may need to recompute all of it's values |
| 16:28 | kotarak | arohner: that cannot work, you can't eval an expression passed to a function (at least not in general) |
| 16:28 | manic12__ | generators? |
| 16:28 | manic12__ | wavis |
| 16:28 | Chousuke | no, really, I have no idea what you're thinking |
| 16:28 | Chousuke | you might have a good idea but I can't make sense of it. |
| 16:29 | kotarak | arohner: besides the macro would need to look like: `(my-fun (quote ~expr)). Your expansion is (my-fun your.name.space/expr). |
| 16:29 | ngoc | kotarak: Thank you. This is a pitfall for new comers. Since this example is for new comers, I think it should be explained in the example. |
| 16:30 | manic12__ | it's like a spreadsheet |
| 16:30 | manic12__ | but it's a tree of objects |
| 16:30 | manic12__ | (refering to clos implementation) |
| 16:31 | manic12__ | inputs and specially declared modifiable attributes can be changed |
| 16:31 | tmountain | maniac12__: I'd determine if you really need "objects" or if you can use Clojure's native types to represent whatever data you're referring to |
| 16:32 | manic12__ | i'm using structmaps from spinoza |
| 16:32 | Chousuke | hm |
| 16:32 | manic12__ | i'm trying to implement a declarative DSL from clos to clojure |
| 16:33 | manic12__ | i haven't used cells very much at all, but it's like cells but lazy eval |
| 16:35 | manic12__ | it's not for specially trained computer scientists, it's a DSL for mechanical & civil engineer types |
| 16:35 | wavis | ,(defn undoable-assoc [the-map key val] (with-meta (assoc the-map key val) {:undone the-map})) |
| 16:35 | clojurebot | DENIED |
| 16:36 | manic12__ | wavis: at some point the user needs handlebars |
| 16:36 | wavis | manic12__: anyway, with that you could (^new-map :undone) |
| 16:36 | wavis | handlebars? |
| 16:36 | manic12__ | probably |
| 16:37 | manic12__ | there has to be at least one mutable thing in the program, and that is the object which gets displayed in the viewer |
| 16:39 | Chousuke | the object displayed is probably a function of the inputs, which are the mutable stuff :) |
| 16:39 | wavis | assuming I have a clue, you just need to change what the viewer is holding to display. the collections to display can still be immutable |
| 16:39 | ngoc | Is there a way to redefine functions? (defn str [& args] 123) will throw error. |
| 16:40 | wavis | so represent the whole display as an immutable structure and swap it |
| 16:40 | manic12__ | the inputs are just going to be entries in the struct map and clojure will copy the whole struct map which gives the ability to synchronize an undo/redo |
| 16:40 | hiredman | ngoc: because str is not defined in the namespace you are in |
| 16:40 | manic12__ | wavis: you are correct |
| 16:41 | ngoc | hiredman: How to solve the problem? |
| 16:41 | manic12__ | but sometimes it's nice to spawn one at the repl |
| 16:41 | manic12__ | if it's not viewing properly or something |
| 16:42 | kotarak | ngoc: you don't want to do this! |
| 16:43 | Chousuke | ngoc: redefining core functions is going to break everything |
| 16:43 | Chousuke | ngoc: what you might do is temporarily rebind them though. |
| 16:43 | hiredman | ngoc: there are many ways to solve it |
| 16:43 | ngoc | (ns clojure.core) then (defn str [& args] "123") solved the problem |
| 16:44 | hiredman | #$%@#$% |
| 16:44 | hiredman | that is not a solution |
| 16:44 | Chousuke | and created a thousand more :) |
| 16:44 | hiredman | clojure.core/str is part of the core of clojure and depended upon by other functions |
| 16:44 | hiredman | changing it breaks all those functions |
| 16:44 | kotarak | People sure have funny definitions for "solved" and "problem"... |
| 16:44 | manic12__ | mutable is not a dirty word |
| 16:44 | hiredman | yes, it is |
| 16:45 | manic12__ | then get rid of refs, agents and atoms |
| 16:45 | Chousuke | cutting off your head solved headache but... |
| 16:45 | Chousuke | solves* |
| 16:45 | kotarak | Chousuke: hmmm? Phantom pain? |
| 16:45 | sproingie | it's a dirty word, but sometimes your problem wants you to talk dirty ;) |
| 16:45 | ngoc | I want to do alias_method_chain like in Ruby/Rails: http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Module.html#M001219 |
| 16:45 | technomancy | noooo!~ |
| 16:45 | sproingie | clojure gives you mutability all over the place. it's just managed. |
| 16:46 | technomancy | alias_method_chain is a maintenance nightmare |
| 16:46 | hiredman | manic12__: but mutation is needed |
| 16:46 | hiredman | so you minimize/control it |
| 16:46 | manic12__ | exactly |
| 16:46 | sproingie | heck atoms arent even all that managed |
| 16:47 | ngoc | I save the original str, redefine it, and call the original function inside the new one |
| 16:47 | sproingie | that's what let is for |
| 16:47 | hiredman | they are managed in the sense that future state is a function of past state |
| 16:47 | hiredman | ngoc: don't |
| 16:47 | kotarak | ngoc: and broke the whole system.... |
| 16:48 | kotarak | ngoc: monkey patching is not a good idea. Don't do it. |
| 16:48 | ngoc | But Rails plugins all work this way, and they do work |
| 16:48 | hiredman | ngoc: when you create a new namespace you have the option of not aliasing bindings from clojure.core |
| 16:48 | technomancy | ngoc: no, they break |
| 16:48 | technomancy | all the time |
| 16:49 | hiredman | so you can leave str out of your namespace and redefine it there |
| 16:49 | manic12__ | I have to implement a memoization scheme for rest of that attributes, but it has to be finer grained than copying the whole struct map, it has to memoize each attribute individually but be able to unbind itself when dependent things change |
| 16:49 | Chousuke | manic12__: copies are cheap |
| 16:49 | Chousuke | manic12__: just give the user a reference :P |
| 16:49 | manic12__ | but for EVERY attribute call? |
| 16:50 | hiredman | attribute call? |
| 16:50 | manic12__ | message |
| 16:50 | hiredman | I would not use spinoza |
| 16:50 | Chousuke | manic12__: in which situation would you even copy the struct map entirely? :/ |
| 16:50 | technomancy | ngoc: rails 3 is removing as many alias_method_chain calls as possible due to this |
| 16:50 | Chousuke | manic12__: I mean, if you assoc to it, that doesn't copy the whole map |
| 16:51 | ngoc | If redefining does not "solve" the problem, is there a way? I want to add feature to an existing function, just like in Rails plugins. |
| 16:51 | Chousuke | (doc binding) |
| 16:51 | clojurebot | "([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before." |
| 16:51 | kotarak | ngoc: you want multimethods |
| 16:51 | sproingie | "just like in Rails" often means "doing it completely wrong" |
| 16:52 | hiredman | I'm pretty sure the original author of spinoza even removed his repo |
| 16:52 | sproingie | monkeypatching everything onto Object... OOP, You're Doing It Wrong |
| 16:52 | hiredman | or not |
| 16:53 | sproingie | there's reasonable use cases for opening up base classes, sure. most of ruby's uses aren't it |
| 16:53 | manic12__ | Chousuke: yeah but I should only need to copy the struct map when information "changes" that invalidates dependent attributes |
| 16:53 | Chousuke | manic12__: I still don't see what "copying" happens if the struct map doesn't change |
| 16:54 | sproingie | you don't need to copy the whole map, you just record a sequence of changes |
| 16:54 | manic12__ | clojure copies just about everything you can look at the source code |
| 16:55 | sproingie | when you need to get everything into the same state, you can condense the changes to a minimal set then generate exactly one new object from that |
| 16:55 | hiredman | eh? |
| 16:55 | Chousuke | huh? |
| 16:55 | hiredman | copies? |
| 16:55 | Chousuke | manic12__: you need to copy *something* to keep the data structures immutable, but it doesn't copy *everything* all the time. |
| 16:55 | Chousuke | that'd be slow |
| 16:55 | manic12__ | sproingie: you're right and that's what i do in clos |
| 16:56 | hiredman | http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation/ |
| 16:56 | Chousuke | hmm, well, that's possible with clojure transients. |
| 16:56 | manic12__ | go to IPersistentMap assoc method and show me that it's not copying every value |
| 16:56 | Chousuke | manic12__: it's not. |
| 16:56 | Chousuke | it shares structure. |
| 16:56 | Chousuke | with its "parent" maps |
| 16:56 | ngoc | How to implement something like (defn f (+ (original-f) + 1)) with multimethods or binding? Binding does not work as expected as the example at http://clojure.org/concurrent_programming shows ("Logging str" is output 5 times). |
| 16:56 | manic12__ | newVals[i]=val; |
| 16:57 | hiredman | ngoc: it does work as expected |
| 16:57 | kotarak | ngoc: bindings works as expected, the output depends on the definition of the original str |
| 16:57 | hiredman | str is called internally by println and the love function |
| 16:57 | Chousuke | manic12__: if you have a map with a thousand objects and you assoc to it, Clojure surely does not copy each of those thousand values |
| 16:57 | sproingie | love? |
| 16:57 | manic12__ | PersistentStructMap.java |
| 16:58 | Chousuke | manic12__: assoc is O(log_32 n) |
| 16:58 | hiredman | sproingie: if I recall, the example on that page defines a function named love |
| 16:58 | sproingie | ah |
| 16:58 | hiredman | loves, pardon me |
| 16:58 | sproingie | i was digging around in the API looking for it ;) |
| 16:59 | manic12__ | ok, Chousuke if you're right than that's even better |
| 16:59 | tomoj | Chousuke is right |
| 16:59 | Chousuke | manic12__: how many items will your struct maps have, anyway? |
| 16:59 | stuartsierra | ~seen jochu |
| 16:59 | clojurebot | no, I have not seen jochu |
| 16:59 | ngoc | hiredman: I thought str called itself, not by println |
| 16:59 | manic12__ | they can have alot, but not enough to make a full copy slow, like 100 to 200 "slots" |
| 17:00 | sproingie | log32 n aka "fast enough for you old man" |
| 17:00 | kotarak | ngoc: yes, str calls itself, which is your str (it print logging and then calls the orig-str) |
| 17:00 | Chousuke | manic12__: maybe *struct* maps do copy all of their values (because usually you don't have so many of them). but it's hopefully not going to be too slow |
| 17:00 | hiredman | ngoc: that is possible as well |
| 17:00 | Chousuke | manic12__: after all, every value is just a pointer. copying a hundred pointers is not too expensive :P |
| 17:01 | manic12__ | it won't |
| 17:01 | manic12__ | no |
| 17:01 | sproingie | i thought structs used a vector underneath |
| 17:01 | manic12__ | in the clos version, it would have to actually go through and unbind dependent slots, I'm sure that's slower than just copying it |
| 17:02 | hiredman | I wonder if there is a point to using structmaps with 200 keys |
| 17:02 | sproingie | oh right struct vs structmap. confoozing |
| 17:02 | Chousuke | ... creating instances of them would be painful :) |
| 17:02 | hiredman | structmaps are supposed to be a optimized case for small maps with the same keys |
| 17:02 | manic12__ | yeah, after a point you would think it would have the offsets in a class object |
| 17:02 | sproingie | hiredman: i could see writing a virtual machine with a slot per bytecode |
| 17:03 | sproingie | but chances are it'd be a singleton |
| 17:03 | hiredman | sproingie: eh? |
| 17:03 | sproingie | you know a big table |
| 17:03 | manic12__ | i'm using structmaps right now because that's what spinoza uses |
| 17:03 | sproingie | nevermind my babbling |
| 17:03 | hiredman | I wonder at what number of keys a struct map ceases to be an optimization |
| 17:03 | sproingie | manic12__: the author of spinoza told me not to waste my time with it |
| 17:04 | hiredman | spinoza :( |
| 17:04 | Chousuke | hiredman: probably never, as the keys are shared between structmap instances |
| 17:04 | manic12__ | maybe so, but I don't plan on using it like a clos, it's a learning tool |
| 17:05 | sproingie | if it's just to learn, then stop optimizing up front |
| 17:05 | manic12__ | real clos does all kinds of optimization tricks for fast generic function dispatch and accessor methods |
| 17:05 | manic12__ | who's optimizing? |
| 17:05 | hiredman | multimethods! |
| 17:05 | manic12__ | i implemented an undo |
| 17:06 | sproingie | you're fretting about copies of data structures that never actually get copied |
| 17:06 | ngoc | Hmm, I feel that binding forces the callers to explicitly list all the plugins they wants to use all the time, like (with-feature1 (with-feature2 (with-feature3 str))), this is ugly. How to plug all the plugins only once when the program starts? |
| 17:06 | sproingie | sounds like optimization concerns |
| 17:06 | tomoj | ngoc: the whole point is that you shouldn't do that :) |
| 17:07 | hiredman | ngoc: I would really recomend you spend more time learning clojure before you begin worrying about writing something that needs a plugin system |
| 17:07 | sproingie | multifns have the start of a nice generic function dispatch, but building on that is still in roll-your-own territory |
| 17:07 | Chousuke | ngoc: design a system that allows people to create new functions by combining the plugins with the base functions |
| 17:07 | manic12__ | there is no declarative programming paradigm in clojure |
| 17:07 | sproingie | looking at watches, i would argue otherwise |
| 17:07 | Chousuke | ie. (def my-cool-function (plugin1 (plugin2 (plugin3 base-function))))) |
| 17:07 | sproingie | it's certainly not declarative like prolog, no |
| 17:08 | manic12__ | i'm not saying declarative is the best, but it makes sense for my application |
| 17:08 | manic12__ | mechanical engineers are visual people |
| 17:08 | manic12__ | spatial |
| 17:09 | manic12__ | (they're so spatial) |
| 17:10 | hiredman | there are a lot of primitives available that a declarative system can be built upon |
| 17:10 | manic12__ | so far I feel like I can't describe anything geometric with clojure because it feels like some kind of strange scheme with an emphasis on immutability |
| 17:10 | hiredman | promises,delays,etc |
| 17:10 | manic12__ | structmaps and vectors? |
| 17:10 | ngoc | hireman: I have been studying Clojure for one month, no big progress at all. Do you have any tips on studying Clojure? |
| 17:11 | hiredman | ngoc: write something small first, the sidebar on the clojure.org website has a list of features to try out |
| 17:11 | manic12__ | as "dumb" as smalltalk and flavors, or even clos is, you can still describe types of objects and how they are contained |
| 17:12 | hiredman | manic12__: erm |
| 17:12 | sproingie | you do have to think functionally. clos with all its declarative syntax sugar still usually comes down to OO |
| 17:12 | manic12__ | um, yeah |
| 17:12 | hiredman | we may have different understandings of "declarative programming" |
| 17:12 | manic12__ | declarative and object oriented are not mutually exclusive |
| 17:13 | hiredman | what do you mean by declarative? |
| 17:13 | sproingie | you can get a lot of declarative behavior out of multifns |
| 17:13 | manic12__ | car has chassis, chassis has wheels |
| 17:14 | sproingie | struct, works fine |
| 17:14 | manic12__ | you can but you can get a lot of milage of of single object dispatch too! |
| 17:14 | ngoc | Chousuke: Do you mean I should study macro? |
| 17:15 | sproingie | multifns have multiple dispatch, they just don't have any kind of MRO for call-next-method to work |
| 17:16 | manic12__ | sproingie: i am very familiar with multiple-object dispatch from clos |
| 17:16 | sproingie | multifns are insanely more powerful than just switching on class. you can destructure an object and switch on some arbitrary function of it |
| 17:16 | hiredman | manic12__: that seems to relate to the dictionary definition of Declarative in that you are declaring relationships, but I don't see how it relates to declarative programming |
| 17:16 | sproingie | that's probably why there's no MRO, how the heck do you determine what the "next" thing is from that |
| 17:17 | kotarak | ngoc: consider a simple program, eg. a logfile parser or something overlookable. And start implementing that. |
| 17:17 | kotarak | ngoc: get comfortable in Clojure before you start with macros... |
| 17:17 | manic12__ | sproingie: that's great, get a bunch of gearheads doing it |
| 17:17 | sproingie | floating around in my head is the idea of dispatching on a sequence instead of a single value, but i don't know offhand what the code would look like |
| 17:18 | sproingie | manic12__: make a bunch of macros that look like autolisp, done |
| 17:18 | sproingie | not saying it's a good lisp, just saying that's what they know |
| 17:18 | manic12__ | they also know icad |
| 17:18 | manic12__ | which is built on flavors |
| 17:19 | hiredman | sproingie: you can dispatch on sequences, just works better with vectors |
| 17:19 | Chousuke | sproingie: the dispatch fn would just be (comp vec map your-dispatch-fn) :P |
| 17:19 | Chousuke | er, wait |
| 17:19 | hiredman | ↑ yeah, use vectors |
| 17:19 | Chousuke | (partial map dfn) |
| 17:19 | sproingie | hiredman: yeah a vector would probably be more efficient, i'm thinking the sequence could be lazy though. |
| 17:20 | sproingie | given arguments foo, bar, baz, generate a MRO. now given foo, bar, baz, a MRO, and a current position, find the next method |
| 17:20 | hiredman | sproingie: the isa stuff is all built to work on vectors already |
| 17:20 | hiredman | (isa? [Object Object] [String Character]) |
| 17:20 | hiredman | ,(isa? [Object Object] [String Character]) |
| 17:20 | clojurebot | false |
| 17:20 | hiredman | bah |
| 17:20 | manic12__ | it's great that clojure has all of these great features with multifns & metadata, but if simple people have a hard time doing simple programming, well I'm sure you would say they need to re-learn |
| 17:21 | hiredman | ,(isa? [String String] [Object Object]) |
| 17:21 | clojurebot | true |
| 17:21 | sproingie | it ain't logo yet |
| 17:21 | manic12__ | I'm trying to apply a simple object system paradigm from flavors and clos to clojure |
| 17:21 | sproingie | i'd rather the bike gets built before the training wheels |
| 17:22 | sproingie | clos is anything but simple |
| 17:23 | hiredman | (defmulti new (fn [& args] (vec (conj (map class (rest args)) (first args))))) |
| 17:24 | hiredman | (defmethod new [:box String Integer] [_ name size] {:name name :size size}) |
| 17:24 | manic12__ | yeah, well clos can be simplified with some meta programming and macros |
| 17:24 | hiredman | of course you couldn't call it new |
| 17:25 | hiredman | it would have to be my-new |
| 17:25 | manic12__ | make-instance? |
| 17:25 | hiredman | and you'd want to map type not class |
| 17:26 | hiredman | and you'd want to add :box as the :tag metadata to the resulting {} |
| 17:26 | manic12__ | you know why java is popular...it creates a framework where programmers don't have to think as hard |
| 17:26 | hiredman | that is a lie |
| 17:26 | sproingie | *snort* |
| 17:26 | manic12__ | icad is the same way |
| 17:27 | hiredman | well, they don't think they have to think |
| 17:27 | hiredman | so they write crap |
| 17:27 | sproingie | i have to think all the time, long and hard, about how to get around the limitations in the language |
| 17:27 | manic12__ | and i hit a limitation in clos, that's why I'm here |
| 17:27 | sproingie | usually i can find a nice library that helps out. which is great til i want to make it work with another library that solved another problem |
| 17:28 | manic12__ | i would like to create a dead-simple geometric library for the icad style declarative/generative/object-oriented programming |
| 17:29 | sproingie | you may be the only one familiar with it. pastebin an example of what it looks like? |
| 17:30 | manic12__ | sometimes i think computer scientists have lost touch with the problems the science was created to solve |
| 17:31 | kotarak | "Computers help us to solve problems we wouldn't have without them." |
| 17:31 | hiredman | ~clojure |
| 17:31 | clojurebot | clojure is a very attractive hammer with a nice heft to it |
| 17:33 | manic12__ | if you have used parametric cad to design physical objects such as machine parts, it shows that things have progressed, but at the same time the software designers lock out the user from being able to really write flexible applications |
| 17:34 | manic12__ | that's why I became a programmer |
| 17:35 | sproingie | computer scientists have never particularly been in touch with the real world. that's not their job. |
| 17:35 | sproingie | engineers create stuff, scientists figure out new principles to create stuff on. |
| 17:36 | sproingie | theory, meet practice. practice, theo-- hey theory, stop wandering off, pay attention. |
| 17:37 | hiredman | manic12__: I think you might want to get a blog |
| 17:39 | manic12__ | i don't think anyone would read my blog |
| 17:41 | hiredman | I dunno, you could grab the mic and inspire the masses to rise as one and throw off the shackles of the computer science intelligentsia |
| 17:41 | sproingie | you have nothing to lose but your boot times! |
| 17:41 | manic12__ | i think i should be an arborist |
| 17:42 | drhodes | there's a race of men who live in the trees |
| 17:43 | manic12__ | tarzan of the kbe trees here |
| 17:45 | manic12__ | i am going to have to get this thing to do a deep copy |
| 17:46 | manic12__ | if it finds a "pointer" to a struct map as a value of an entry, it needs to copy that whole thing too, not just the pointer |
| 17:46 | hiredman | manic12__: :( |
| 17:46 | hiredman | that is horrible |
| 17:48 | manic12__ | the structmaps don't need to contain keys for every message, just the ones that are "changeable" (I hate these "") |
| 17:50 | hiredman | still sounds horrible |
| 17:52 | Chousuke | why does it need a deep copy? |
| 17:53 | Chousuke | I mean, maps nest just fine. :/ |
| 17:53 | manic12__ | alibre design is written i java, i should just get a license to that and run clojure as a scripting language and be done |
| 17:54 | manic12__ | because if you don't deep copy, you when you undo or redo you will get state that belongs to something else |
| 17:54 | manic12__ | it's a very thin skeleton |
| 17:54 | Chousuke | oh, so the pointer is a ref then? |
| 17:55 | manic12__ | no, by "pointer" i mean (identical? val1 val2) |
| 17:55 | Chousuke | but that's not true |
| 17:55 | Chousuke | or, at least I think it isn't. |
| 17:58 | sproingie | not that i don't love clojure, but if you have a clos thing you want to port to java, perhaps you should consider ABCL? |
| 17:58 | sproingie | or one of the many scheme implementations where there's a tinyclos port |
| 17:58 | Chousuke | ,(let [a {:a {:deep :map}} b {:b 1} ] [(assoc b :foo (:a a)) b a]) |
| 17:58 | clojurebot | [{:foo {:deep :map}, :b 1} {:b 1} {:a {:deep :map}}] |
| 18:00 | Chousuke | the :foo value and :a value are identical, but there is no connection between the "parent" maps |
| 18:02 | Chousuke | manic12__: is that what you're worried about, or something else? :/ |
| 18:03 | Chousuke | manic12__: the submaps can freely be the same object, because it's not like anything can change them :) |
| 18:23 | spuz | Hello, I've having a really straing problem accessing external files from clojure |
| 18:23 | spuz | first of all, I cannot load any files using load-file |
| 18:25 | hiredman | have you read the load-file docs? |
| 18:25 | spuz | also, I cannot seem to 'see' files on my hard disk. Running (.exists (java.io.File. "C:/pe5.clj")) returns false even though that file exists |
| 18:26 | spuz | hiredman: yes, I can use relative or absolute paths apparently, but neither seem to work |
| 18:26 | hiredman | have you tried "C:\pe5.clj" |
| 18:26 | spuz | yes |
| 18:27 | spuz | at least "C:\\pe5.clj" |
| 18:27 | manic12__ | Chousuke: those sub objects may be immutable, but if they are the wrong ones then that is a problem |
| 18:27 | spuz | however "C:/Windows" returns true |
| 18:27 | spuz | it's very strange |
| 18:28 | hiredman | spuz: does the pe5.clj file exist? |
| 18:28 | spuz | hiredman: yes! |
| 18:28 | Chousuke | manic12__: how would they be wrong? |
| 18:29 | spuz | I've tried putting it in the current dir and using "pe5.clj" as well |
| 18:29 | hiredman | spuz: what does dir c:\pe5.clj say? |
| 18:29 | Chousuke | manic12__: or is there some situation where the deep copy actually "changes" some of the inner map? :/ |
| 18:29 | spuz | hiredman: hmm file not found! |
| 18:30 | hiredman | so it doesn't exist |
| 18:30 | hiredman | problem solved |
| 18:30 | spuz | hiredman: uh well, not exactly, typing that path into explorer finds the file, but clearly it's not a clojure problem |
| 18:32 | spuz | hiredman: ah, how annoying, I have extensions turned off on this machine and the file was actually called "pe5.clj.txt"! |
| 18:32 | spuz | yes I'm a retard |
| 18:34 | sproingie | blame notepad |
| 18:35 | akhudek | While playing around building a small svg-like vector library using Java2d, I ran into an interesting problem dealing with mutable trees. |
| 18:35 | akhudek | I decided to represent a scene graph as nested vectors inside a ref. |
| 18:35 | hiredman | notepad++ |
| 18:36 | akhudek | Since the scene graph is a shared mutable resource that theoretically multiple threads may modify. |
| 18:36 | hiredman | I actually did a few euler problems in notepad++ |
| 18:36 | akhudek | Now, a common operation may be to frequently change one specific node in the graph. |
| 18:36 | akhudek | Say for a text label during an animation. |
| 18:37 | hiredman | have you seen zippers? |
| 18:37 | akhudek | yes, but you can't have multiple cusors |
| 18:37 | akhudek | A simple animation would likely change a label node in one place, and say another object somewhere else. |
| 18:37 | akhudek | Traversing the tree between both positions each frame seems ineffecient. |
| 18:38 | hiredman | (require '[clojure.zip :as zip]) |
| 18:38 | hiredman | ,(require '[clojure.zip :as zip]) |
| 18:38 | clojurebot | nil |
| 18:39 | akhudek | The only decent solution seems to be to put frequently mutated nodes into references. |
| 18:39 | akhudek | And have the rendering code automatically deref any references it encounters. |
| 18:40 | hiredman | :( |
| 18:40 | hiredman | why do you want multiple cursors? |
| 18:40 | hiredman | how deeply nested are the vectors? |
| 18:41 | akhudek | So that you can refer to more than one object in the scene. |
| 18:41 | hiredman | eh? |
| 18:41 | hiredman | ,(-> '[:a [:b :c]] zip/vector-zip zip/next zip/next zip/next (zip/replace :x) zip/next (zip/replace :y) zip/root) |
| 18:41 | clojurebot | [:a [:x :y]] |
| 18:41 | akhudek | Right, but in a graphics context where you modify more than one node each frame. |
| 18:42 | akhudek | You'd need to move between all nodes you need to change |
| 18:42 | hiredman | that modifies two nodes |
| 18:43 | akhudek | my complaint is that having to move between the two nodes may be a lot of work |
| 18:43 | sproingie | could collect a list of changes and sort it |
| 18:43 | sproingie | sort of like elevator queueing |
| 18:43 | hiredman | you could use something besides vectors |
| 18:43 | sproingie | that too |
| 18:44 | akhudek | such as? |
| 18:44 | hiredman | you could flatten nest vectors by wrapping them into a map |
| 18:44 | akhudek | and have nested maps? |
| 18:44 | sproingie | you normally have to sort scenegraph updates anyway |
| 18:44 | hiredman | {[0 1] :x [0 0] :a} => [[:a :x]] |
| 18:44 | hiredman | no, just one map |
| 18:45 | akhudek | hmm, maybe the problem is in my representation of the graph then |
| 18:45 | hiredman | {[0 1] :x [0 0] :a [1] :p} => [[:a :x] :p] |
| 18:46 | akhudek | I was translating svg elements into vectors like [:group :width 10 :height 10 [:rect :x 1 :y 1] [:rect :x 20 :y 20]] |
| 18:46 | akhudek | my idea was to render these during paint |
| 18:47 | akhudek | by traversing the tree and carrying the state as needed by the svg rendering model |
| 18:47 | hiredman | akhudek: have you looked at how clojure.xml/parse represents xml? |
| 18:47 | akhudek | I should probably do that. |
| 18:47 | akhudek | It doesn't use zippers? |
| 18:48 | hiredman | no, it uses a structmap, but you can traverse it via zippers |
| 18:48 | akhudek | ok, I'll take a look, thanks |
| 18:49 | hiredman | I am rather taken with {[0 1] :x [0 0] :a [1] :p} => [[:a :x] :p] myself |
| 18:59 | danlarkin | ,(+ nil 1) |
| 18:59 | clojurebot | java.lang.NullPointerException |
| 18:59 | danlarkin | suggestions other than try/catch? |
| 18:59 | hiredman | ,(or nil 0) |
| 18:59 | clojurebot | 0 |
| 19:00 | hiredman | ,(-?> nil (partial + 1)) |
| 19:00 | clojurebot | nil |
| 19:00 | hiredman | ,(when nil (+ nil 1)) |
| 19:00 | clojurebot | nil |
| 19:01 | akhudek | ah, my current code is actually nearly the same as clojure.xml in terms of representation |
| 19:01 | danlarkin | I think the first suggestion is best so far |
| 19:01 | akhudek | I simplified to nested vectors here, but really I use structs where a content field contains a vector of structs |
| 19:02 | akhudek | it's great for reading the data, but not so great for rapidly changing several deeply nested nodes |
| 19:03 | akhudek | hiredman: you're representation is interseting |
| 19:04 | hiredman | "I find your representation intriguing, and I would like to subscribe to your newsletter" |
| 19:05 | Chousuke | danlarkin: the maybe monad :P |
| 19:05 | danlarkin | Chousuke: oh jeez! |
| 19:06 | Chousuke | hey, monads are sometimes actually useful :) |
| 19:06 | Chousuke | not just for pretending IO is mathematically pure. |
| 19:19 | akhudek | hmm, your rep. with using a sorted map with an appropriate sort function defining dfs order would work. I'll work with that for now, thanks. :) |
| 20:52 | bpattison | is there anyway in clojure to create/define a hash value through a macro? something like (defmacro m [a] `(func :~a)) ? |
| 20:55 | arohner | bpattison: can you give an example of how you want it to work? |
| 20:56 | arohner | macros transform s-exprs, so it's much easier to figure out what you want if you know the start and end points |
| 20:56 | arohner | :-) |
| 20:57 | bpattison | here's the macro I'm trying to get working |
| 20:57 | bpattison | (defmacro def-keyword [word] |
| 20:57 | bpattison | `(def k-~word |
| 20:57 | bpattison | (constant-semantics |
| 20:57 | bpattison | (lit-conc-seq "~word" nb-char-lit) |
| 20:57 | bpattison | (make-node-keyword :~word)))) |
| 20:57 | bpattison | sorry about all the newlines |
| 20:58 | Makoryu | bpattison: http://gist.github.com |
| 20:58 | Makoryu | :p |
| 20:59 | arohner | right, but you haven't explained where you're starting and where you're ending up, and I have to guess at what this code is supposed to do |
| 20:59 | arohner | give me an example of working code without the macro, and what you want the result of the macro to be |
| 20:59 | bpattison | http://gist.github.com/198618 |
| 21:01 | bpattison | okay, I want it to create a def named "k-~word" that makes use of a hash named ":~word" so the macro would produce "k-new" with hash value ":new" when the macro is invoked with word=new |
| 21:02 | bpattison | and so :new would used in other parts of the code |
| 21:03 | arohner | so calling (m {:word "new"}) would call (def k-new) ? |
| 21:04 | arohner | or (m {:word :new}) would call (def k-word :new) ? |
| 21:06 | bpattison | hmm, its more like creating a short-cut for a larger expression and naming it k-new where that larger expressions uses a hash key of :new as well |
| 21:08 | bpattison | (def-keyword new) would produce (def k-new .... :new ...) |
| 21:10 | bpattison | but I get a syntax error on :~word in the macro |
| 21:19 | arohner | :word is a literal |
| 21:20 | arohner | if you want the keyword-ized version of an argument, use (keyword word) |
| 21:20 | arohner | where word is a symbol or a string |
| 21:20 | arohner | sorry, only a string |
| 21:20 | arohner | i.e. |
| 21:20 | arohner | ,(keyword "foo") |
| 21:20 | clojurebot | :foo |
| 21:20 | hiredman | ,(keyword (name 'foo)) |
| 21:20 | clojurebot | :foo |
| 21:28 | bpattison | arohner: excellent! thanks |
| 21:46 | Makoryu | , (+ 1 "food") |
| 21:46 | clojurebot | java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number |
| 22:01 | kevin__ | , (+ 1 2 3) ; curious |
| 22:01 | clojurebot | 6 |
| 22:02 | kevin__ | nice, i can write a distributed computing app |
| 22:23 | hiredman | ~suddenly |
| 22:23 | clojurebot | CLABANGO! |