2009-01-16
| 00:22 | durka | is it possible to define a lazy seq that is reified 100 elements at a time |
| 00:22 | durka | i suppose i could just use flatten |
| 00:32 | durka | so given that the namespaces a.b.c and a.b.d exist, and a.b.c/f and a.b.d/g are functions in them |
| 00:32 | durka | i sort of want to do this |
| 00:33 | durka | (use 'a.b) |
| 00:33 | durka | (c/f "blah") (d/g "quux") |
| 00:33 | durka | but it doesn't work |
| 00:34 | durka | is there a way to do that kind of thing? |
| 00:37 | Chouser | (require '[a.b.c :as c] '[a.b.d :as d] |
| 00:37 | Chouser | ) |
| 00:37 | Chouser | I think. |
| 00:38 | Chouser | or even: (require '(a.b [c :as c] [d :as d])) |
| 00:38 | durka | thanks |
| 03:38 | sleven | why is it much faster to write to Derby than to postgresql? |
| 04:58 | timothypratley | In Rich's ants.clj there is a global 'running', how does this get set to false? [is it ever?] |
| 05:01 | hiredman | it would have to be a binding, a set!, or a def |
| 05:01 | hiredman | I have not looked at ants.clj, but maybe running is a flag, and if you set it to false the simulation stops |
| 05:02 | timothypratley | http://clojure.googlegroups.com/web/ants.clj |
| 05:02 | timothypratley | yeah that's what I thought, |
| 05:02 | timothypratley | except it never gets set to false |
| 05:02 | hiredman | I imagine you would set it to nil in the repl |
| 05:03 | timothypratley | ah :) |
| 12:34 | danlarkin | this is a goof, http://kiwi.cabal.fi/home/aki/misc/cons-ceremony.txt |
| 12:41 | durka | heh |
| 12:41 | durka | bit of a verbose trace there |
| 13:20 | Lau_of_DK | Good evening all |
| 13:23 | cgrand | evening, Lau! |
| 13:23 | durka | good afternoon |
| 13:23 | Lau_of_DK | ;) |
| 13:49 | clojurebot | svn rev 1216; lift loops from expression contexts |
| 14:03 | kefka | I'm using Svn rev 1178. I do not have gen-and-save-class. Do I need a newer version of Clojure? |
| 14:06 | danlarkin | kefka: why not update anyway, you'll get lots of bug fixes :) |
| 14:06 | hiredman | the gen-and-save stuff is mostly gone |
| 14:06 | danlarkin | regarding your question, though, gen-and-save-class is old school |
| 14:06 | hiredman | a lot of changes in those areas |
| 14:07 | kefka | Ok, so gen-and-save-class is outdated? What do I do if I want to generate a .class file on the fly? |
| 14:07 | hiredman | ,(doc compile) |
| 14:07 | clojurebot | ------------------------- clojure.core/compile ([lib]) Compiles the namespace named by the symbol lib into a set of classfiles. The source for the lib must be in a proper classpath-relative directory. The output files will go into the directory specified by *compile-path*, and that directory too must be in the classpath. |
| 14:07 | hiredman | er |
| 14:08 | hiredman | kefka: you should avoid generating .class files on the fly |
| 14:10 | kefka | hiredman: Ok. So what are current best practices for generating a standalone executable? |
| 14:10 | hiredman | what are you doing that requires it? |
| 14:10 | hiredman | clojurebot: stand alone? |
| 14:10 | clojurebot | Excuse me? |
| 14:10 | kefka | I'm sending an executable to a remote machine that has the JVM but not a Clojure intrepreter. |
| 14:10 | hiredman | kefka: well, you will need the clojure.jar regardless |
| 14:11 | clows | that clojurebot doc just made me realize what i did wrong with gen-class :) |
| 14:11 | hiredman | the class clojure generates are just stubs that call to clojure |
| 14:15 | clows | if I wanted to subclass a swing class and use that in clojure (and also call methods of that subclass form clojure). would using gen-class allow me do to that? |
| 14:16 | Chousuke | gen-class or proxy perhaps |
| 14:16 | hiredman | clows: I would look at proxy |
| 14:17 | clows | I tried proxy first but i can't seem to be able to access the added methods |
| 14:17 | hiredman | proxy does 90% of what people want from gen-class and does it with less fuss and muss |
| 14:17 | hiredman | oh |
| 14:17 | hiredman | yeah |
| 14:17 | clows | might be my fault ofc |
| 14:17 | hiredman | nah |
| 14:17 | hiredman | proxy doesn't let you add methods |
| 14:17 | hiredman | that is right, for subclassing you still want gen-class |
| 14:17 | clows | ok |
| 14:18 | hiredman | clojurebot: gen-class? |
| 14:18 | clojurebot | No, hiredman, you want gen-interface + proxy |
| 14:18 | clows | I'm thinking just doing that stuff in java might be the best way to go anyway ... it kinda gets messy in clojure |
| 14:18 | Chousuke | AFAIK if you only need to override superclass methods then proxy works. otherwise you need gen-class |
| 14:19 | clows | that'd explain i think |
| 14:20 | hiredman | http://clojure.org/compilation <- |
| 14:22 | hiredman | http://gist.github.com/34229 <-- nasty bean maker macros using gen-class |
| 14:23 | hiredman | hmm |
| 14:23 | clows | I struggled with gen-class because i didn't have the right classpath ... meh ... but it seems to work now. thats a start :) |
| 14:26 | Chousuke | gen-class is a lot easier to use now than it used to be though :P |
| 14:28 | clows | it seems easy enough. once you read about *compile-path* ... |
| 14:31 | Chouser_ | one thing to keep in mind is that lots of stuff that in Java would require a subclass with new methods or data members can be done in Clojure with proxy and closures. |
| 14:32 | Chouser_ | If you really truly need new methods, then you will have to compile something (gen-class or gen-interface) |
| 14:33 | Lau_of_DK | Chouser_: Why isnt your nick verified? |
| 14:33 | Lau_of_DK | registered |
| 14:50 | pjb3 | I'd like to have a ref that contains a vector |
| 14:50 | pjb3 | and have some way to call a function like take on it |
| 14:50 | pjb3 | where it returns n items from the vector, but also removes them from the vector in the ref |
| 14:51 | pjb3 | but obviously in a safe way, so if there are multiple threads pulling stuff from the ref, things don't get taken twice by different threads |
| 14:51 | pjb3 | does that make sense? ideas? |
| 14:51 | pjb3 | Is there a name for that kind of pattern? |
| 14:52 | durka | that's a transaction isn't it |
| 14:53 | pjb3 | well, it would probably invlove a transaction |
| 14:53 | pjb3 | but in thinking about it initially it's tricky because you want to modify what's in the collection |
| 14:54 | durka | (doc pop) |
| 14:54 | clojurebot | For a list or queue, returns a new list/queue without the first item, for a vector, returns a new vector without the last item. If the collection is empty, throws an exception. Note - not the same as rest/butlast.; arglists ([coll]) |
| 14:54 | hiredman | pjb3: you want a write lock |
| 14:54 | hiredman | or whatever it is called you you block others from writing |
| 14:54 | pjb3 | hiredman: yeah, but I thought the whole point of clojure was to avoid having to manage locks :) |
| 14:55 | pjb3 | ,(pop '(1 2 3)) |
| 14:55 | clojurebot | (2 3) |
| 14:55 | hiredman | pjb3: depends |
| 14:55 | pjb3 | see, but I need the 1 as well |
| 14:55 | hiredman | (doc peek) |
| 14:55 | clojurebot | For a list or queue, same as first, for a vector, same as, but much more efficient than, last. If the collection is empty, returns nil.; arglists ([coll]) |
| 14:55 | pjb3 | ,(peek "xyz") |
| 14:55 | clojurebot | java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IPersistentStack |
| 14:55 | pjb3 | ,(peek [1 2 3]) |
| 14:55 | clojurebot | 3 |
| 14:56 | hiredman | ,(peek (seq "xyz")) |
| 14:56 | clojurebot | java.lang.ClassCastException: clojure.lang.StringSeq cannot be cast to clojure.lang.IPersistentStack |
| 14:56 | hiredman | I see |
| 14:56 | pjb3 | ,(peek '(1 2 3)) |
| 14:56 | clojurebot | 1 |
| 14:56 | hiredman | actually |
| 14:56 | hiredman | yeah, transactions, thats the ticket |
| 14:56 | pjb3 | What I want is: |
| 14:57 | pjb3 | (def stuff (ref '(1 2 3))) |
| 14:57 | pjb3 | (take-and-remove 2) => (1 2) |
| 14:57 | pjb3 | @stuff => (3) |
| 14:57 | hiredman | so if you do the read and write in the same dosync block |
| 14:58 | hiredman | (same transaction) |
| 14:58 | pjb3 | ,(take 2 '(1 2 3 4 5)) |
| 14:58 | clojurebot | (1 2) |
| 14:59 | pjb3 | ,(drop 2 '(1 2 3 4 5)) |
| 14:59 | clojurebot | (3 4 5) |
| 14:59 | pjb3 | ah, there it is, do that in a dosync |
| 15:00 | hiredman | (doc split-at) |
| 15:00 | clojurebot | Returns a vector of [(take n coll) (drop n coll)]; arglists ([n coll]) |
| 15:00 | pjb3 | ,(split-at 2 '(1 2 3 4 5)) |
| 15:00 | clojurebot | [(1 2) (3 4 5)] |
| 15:01 | durka | heh, the source of split-at is its docstring |
| 15:01 | Chousuke | :) |
| 15:01 | tomsw | Can anyone explain why I get a "method not found" error from java when I try this: (doto (javax.swing.JFrame.) |
| 15:01 | tomsw | (.setLayout (java.awt.GridLayout. 2 2 3 3)))? |
| 15:02 | tomsw | It's from http://en.wikibooks.org/wiki/Clojure_Programming/By_Example - I'm just trying to get the hang of things |
| 15:02 | hiredman | tomsw: $5 says you have an old version of clojure |
| 15:02 | hiredman | what is the exact message? |
| 15:03 | tomsw | hiredman: java.lang.IllegalArgumentException: No matching method found: .setLayout for class javax.swing.JFrame (NO_SOURCE_FILE:0) |
| 15:04 | hiredman | yeah |
| 15:05 | hiredman | you are using the new doto syntax with an old version of clojure |
| 15:05 | pjb3 | I don't get an error when I run that, just seems to not really do aything |
| 15:05 | pjb3 | other than return the JFrame |
| 15:05 | pjb3 | oh yeah, that's probably it |
| 15:05 | durka | well it won't until you .show the JFrame |
| 15:05 | pjb3 | (.show *1) |
| 15:05 | pjb3 | and there it is :) |
| 15:05 | hiredman | you can tell because of the ".setLayout" the fact that it sees the "." in the method name |
| 15:06 | tomsw | hiredman: you mean it should be trying to call "setLayout" without the leading dot |
| 15:06 | hiredman | yes |
| 15:06 | hiredman | clojurebot: svn? |
| 15:06 | clojurebot | svn is http://clojure.googlecode.com/svn/trunk/ |
| 15:07 | Chousuke | tomsw: download the newer release from google code, or get the latest SVN |
| 15:07 | tomsw | hiredman: thanks. I'll install it & pester you all with silly questions in a bit :) |
| 15:07 | Chousuke | clojurebot: download |
| 15:07 | clojurebot | download is http://code.google.com/p/clojure/downloads/list |
| 15:14 | Chouser_ | pjb3: you have your transaction function worked out? |
| 15:16 | pjb3 | Chouser_: Yeah, I haven't written it out yet, but it should just be (let [things (take n the-list)] (drop n the-list) things) |
| 15:16 | pjb3 | how do I set the ref to the dropped version of the list? |
| 15:17 | hiredman | (doc alter) |
| 15:17 | clojurebot | Must be called in a transaction. Sets the in-transaction-value of ref to: (apply fun in-transaction-value-of-ref args) and returns the in-transaction-value of ref.; arglists ([ref fun & args]) |
| 15:18 | Chouser_ | (dosync (let [things (take n the-list)] (alter the-list drop n) things)) I think |
| 15:19 | pjb3 | (def stuff (ref '(1 2 3 4 5 6 7 8 9))) |
| 15:19 | pjb3 | (dosync (alter stuff drop 3)) |
| 15:19 | pjb3 | java.lang.ClassCastException: clojure.lang.PersistentList |
| 15:19 | pjb3 | same for |
| 15:19 | pjb3 | (dosync (alter @stuff drop 3)) |
| 15:19 | Chouser_ | ah, indeed. (alter stuff #(drop 3 %)) |
| 15:20 | durka | (alter stuff (switch drop) 3) |
| 15:20 | durka | (defn switch [f] #(f %2 %1)) |
| 15:20 | Chouser_ | heh |
| 15:20 | durka | i find myself using that all the time |
| 15:20 | Chouser_ | really? I just use #(foo arg %) |
| 15:21 | pjb3 | What's the difference between alter and commute |
| 15:21 | pjb3 | ? |
| 15:21 | pjb3 | (doc alter) |
| 15:21 | clojurebot | Must be called in a transaction. Sets the in-transaction-value of ref to: (apply fun in-transaction-value-of-ref args) and returns the in-transaction-value of ref.; arglists ([ref fun & args]) |
| 15:21 | pjb3 | (doc commute) |
| 15:21 | clojurebot | Must be called in a transaction. Sets the in-transaction-value of ref to: (apply fun in-transaction-value-of-ref args) and returns the in-transaction-value of ref. At the commit point of the transaction, sets the value of ref to be: (apply fun most-recently-committed-value-of-ref args) Thus fun should be commutative, or, failing that, you must accept last-one-in-wins behavior. commute allows for more c |
| 15:22 | pjb3 | I guess commute is faster, so if your operation is communative, you would use that instead of alter? |
| 15:22 | clows | java.lang.NoSuchMethodError: clojure.lang.Util.equal ... has that method been renamed by any chance? |
| 15:22 | Chouser_ | commute is to be used on commutative functions, alter for others |
| 15:23 | pjb3 | I assume replacing the value of a ref with another value is not communative |
| 15:23 | pjb3 | especailly in this case |
| 15:23 | pjb3 | so alter is needed |
| 15:23 | durka | ,(show clojure.lang.Util) |
| 15:23 | clojurebot | java.lang.Exception: Unable to resolve symbol: show in this context |
| 15:23 | durka | clows: there is a static equals method, is that it? |
| 15:23 | Chouser_ | no, alter and commute are always for replacing the value of a ref with another. The difference is the function you pass to each of them. |
| 15:24 | Chouser_ | I used 'alter' because it's safer. It takes thought to determine if 'commute' will be ok in a given situation. |
| 15:24 | pjb3 | ,(def x (ref 1)) |
| 15:24 | clojurebot | DENIED |
| 15:25 | clows | dukra: yeah i think so |
| 15:25 | clows | I get this error message when trying to (load-file) my test file... java.lang.NoSuchMethodError: clojure.lang.Util.equal(Ljava/lang/Object;Ljava/lang/Object;)Z (internal.clj:26) |
| 15:26 | Chouser_ | clows: you may need to do a clean and rebuild of clojure, those functions have changed recently. |
| 15:26 | pjb3 | (def x (ref 1)) |
| 15:26 | pjb3 | (dosync (alter x inc)) |
| 15:26 | clows | I thought I did but ... yeah will do again :) |
| 15:26 | pjb3 | (dosync (commute x inc)) |
| 15:26 | Chouser_ | cleans are supposed to happen automatically now, but someone on the group said that fixed a similar problem for them. |
| 15:27 | pjb3 | so both of those work, but in that case, you want to use commute, because the operation is communative |
| 15:27 | Chouser_ | pjb3: the difference will only show up under contention, when two threads are in the transaction at the same time. |
| 15:27 | pjb3 | I'm not sure I understand how to tell if my function is communative |
| 15:27 | Chouser_ | for your 'drop' case, i'm pretty sure you need 'alter' |
| 15:27 | pjb3 | Chouser_: yeah, I agree |
| 15:28 | pjb3 | Or would you? |
| 15:28 | pjb3 | Because if I have 2 threads that need to get 10 items from the list |
| 15:28 | pjb3 | to work on |
| 15:28 | pjb3 | they don't care which ones |
| 15:28 | durka | if you don't care which one gets in first... |
| 15:28 | durka | then it should be commutative |
| 15:28 | rhickey | pjb3: you must use alter |
| 15:29 | durka | i stand corrected |
| 15:29 | durka | what did i miss |
| 15:29 | pjb3 | The thread doesn't care which items it gets, so shouldn't that be communative? |
| 15:29 | Chouser_ | with commute, you may see a different value for the ref than will actually be committed. |
| 15:29 | rhickey | pjb3: it does care that it doesn't get he same items as another |
| 15:30 | pjb3 | (dosync (let [items (take 5 stuff)] (comute stuff #(drop 5 %)))) |
| 15:30 | clows | I think it's a clojure contrib issue (I might have to update that too) :) |
| 15:30 | pjb3 | that's what we are talking about doing |
| 15:30 | Chouser_ | In your case if you used commute, the list would always shrink by the right amount, but two threads may get overlapping values, and other may get skipped. |
| 15:30 | pjb3 | rhickey: that is true |
| 15:30 | rhickey | pjb3: that's plainly read-modify-write, must be alter |
| 15:31 | pjb3 | rhickey: Ok, I'll take your word for it, like you said yesterday, I obviously need to read Java Concurrency in Practice |
| 15:31 | rhickey | commute is for things like a tasks-done counter, each transaction wants to increment it, but doesn't care about specific before/after values |
| 15:31 | pjb3 | so when doing alter |
| 15:31 | pjb3 | with the dosync above |
| 15:31 | pjb3 | or commute I mean |
| 15:31 | pjb3 | in the case above |
| 15:32 | pjb3 | if the transaction detects there is a conflict, it won't run the take again? |
| 15:32 | rhickey | pjb3: with commute there is never a conflict |
| 15:32 | rhickey | each transaction takes the at-commit time value and modifies it |
| 15:33 | rhickey | you need alter, gotta run... |
| 15:33 | pjb3 | rhickey: thanks, I believe you, just trying to understand it better |
| 15:34 | Chouser_ | pjb3: I believe the commutes will get queued up and applied again later. |
| 15:36 | pjb3 | Chouser_: so what happens with alter? |
| 15:37 | Chouser_ | with alter, if there's a conflict the whole transaction will be retried. |
| 15:37 | Chouser_ | I think. :-) |
| 15:37 | pjb3 | and what does "the whole transaction" mean? |
| 15:37 | Chouser_ | The outermost enclosing dosync |
| 15:37 | pjb3 | because I assume that means everything in the body of the dosync, right? |
| 15:38 | Chouser_ | yes |
| 15:38 | pjb3 | so if the ref has the numbers 1 - 9 in it |
| 15:38 | pjb3 | then thread a starts the dosync from above |
| 15:38 | clows | (updating clojure-contrib fixed that btw .... I love it when i trip over my own feet) |
| 15:38 | pjb3 | first is does take 3 on the ref |
| 15:38 | pjb3 | which returns 1 2 3 |
| 15:38 | pjb3 | then thread b does take 3 on the same ref, also returning 1 2 3 |
| 15:39 | pjb3 | then thread a does the drop in the alter , which leaves 4 - 9 in the ref |
| 15:39 | pjb3 | then thread b tries to do the the drop, which would also leave 4 - 9, but that's a conflict |
| 15:40 | pjb3 | so then thread b should restart that dosync, do take 3 which this time returns 4 5 6, because the ref has been altered by thread a to have just 4 - 9 left |
| 15:40 | hiredman | in a comute there is no conflict |
| 15:40 | pjb3 | then thread b does the drop, leaving 7 8 9 and everybody is happy |
| 15:40 | hiredman | you are describing alter's behaviour |
| 15:40 | Chouser_ | pjb3: I think that's right. |
| 15:41 | pjb3 | thread a got 1 2 3 and thread b got 4 5 6 |
| 15:41 | pjb3 | hiredman: so what happens differently if I replace alter with commute? |
| 15:41 | hiredman | in a comute, the last one in wins |
| 15:41 | pjb3 | so in the case of commute, if would just blindy do the drop, not checking for conflicts? |
| 15:42 | hiredman | there are no conflicts with commute |
| 15:42 | pjb3 | gotcha |
| 15:42 | hiredman | so why would it check? |
| 15:42 | pjb3 | so a transaction never restarts when there is just commute in there |
| 15:42 | pjb3 | I get it now |
| 15:43 | pjb3 | so to round out my example from above, if I incorrectly did commute instead of alter, both threads would get 1 2 3 |
| 15:43 | pjb3 | which is wrong |
| 15:43 | pjb3 | and 4 - 9 would be left in the ref |
| 15:43 | Chouser_ | two threads doing the commute, each dropping 3 would still end up dropping 6 total. |
| 15:44 | Chouser_ | no, 7-9 would be left in the ref |
| 15:44 | Chouser_ | the commutes would all happen, just not necessarily in the same order as seen inside the transactions. |
| 15:48 | pjb3 | Chouser_: ah, you are right, both threads would get 1 2 3, but would each drop, so only 7 8 9 would be left |
| 15:48 | pjb3 | so 1 2 3 would get processed twice |
| 15:48 | pjb3 | and 4 5 6 never would |
| 15:48 | Chouser_ | I think that's right. |
| 15:49 | pjb3 | that;s all assuming the threads actually interleave in that way I described above |
| 15:49 | Chouser_ | right, it would be a race condition -- sometimes you'd get unwanted results. |
| 15:49 | pjb3 | this would definitely be one of those nasty concurrency bugs you might not catch until the app is in production |
| 15:49 | Chouser_ | which is why I use 'alter' until I'm quite sure that 'commute' is ok. |
| 15:49 | Chouser_ | :-) |
| 15:50 | rhickey | pjb3: alter is always correct, so no need to get into commute until you are trying to solve a performance issue |
| 15:50 | pjb3 | rhickey: good point |
| 15:50 | pjb3 | or unless it is a simple counter and you are just using inc |
| 15:51 | rhickey | pjb3: there are lots of valid uses of commute, like making an entry in a map |
| 15:51 | pjb3 | sure |
| 15:51 | Chouser_ | I wonder if premature optimization is frequently caused by insufficiently interesting problems. |
| 15:51 | rhickey | you don't care if someone has added something else in the meantime |
| 15:51 | rhickey | Chouser_: :) |
| 15:51 | pjb3 | rhickey: you might care if someone has already set a value for that key, right? |
| 15:52 | rhickey | pjb3: yes |
| 15:52 | rhickey | more useful for a cache-like thing |
| 15:52 | Chouser_ | the function you pass to commute will be run twice? |
| 15:53 | rhickey | or generated keys |
| 15:53 | pjb3 | rhickey: you missed it while you were gone, but now I actually understand why I need to use alter :) |
| 15:53 | rhickey | Chouser_: yes, twice |
| 15:53 | rhickey | pjb3: great! |
| 15:54 | Chouser_ | so merge-with might sometimes be a useful option in a commute. |
| 15:59 | rhickey | Chouser_: yes, good example |
| 16:12 | rfgpfeiffer | Java interop seems to choke on inner classes |
| 16:12 | rfgpfeiffer | http://gist.github.com/48138 |
| 16:16 | rfgpfeiffer | I don't use inner classes myself, i found this in a paper and wanted to try it out on the REPL |
| 16:16 | Chouser_ | rfgpfeiffer: the problem is not the inner class but the anonymous package |
| 16:17 | Chouser_ | I moved R into a package P, and then (.makeAnI (new P.R)) works fine, no import needed. |
| 16:18 | rfgpfeiffer | Chouser_: thanks, I will try it |
| 16:26 | edw | Hi. My net connection sucks (or will suck once I leave the coffee shop) and I was wondering if there's a nice downloadable set of docs (PDF, HTML tarball, or something similar). |
| 16:27 | Chousuke | well, you can always use find-doc and doc in a clojure REPL. Other than that, there's the (non-free) clojure book beta |
| 16:28 | Chouser_ | there's a PDF of the website, but it may be too out-of-date now to bother with. |
| 16:29 | hiredman | you could just print the website to pdf |
| 16:29 | Chousuke | though special forms don't have very useful doc strings. All the info of them is on the website |
| 16:29 | Chouser_ | the html pages have print stylesheets, so yeah, you might try what hiredman said. |
| 16:29 | edw | Thanks. I haven't read enough of the docs to know that procedures have documentation. |
| 16:30 | Chousuke | (doc find-doc) |
| 16:30 | clojurebot | Prints documentation for any var whose documentation or name contains a match for re-string-or-pattern; arglists ([re-string-or-pattern]) |
| 16:37 | edw | Thanks. I'm making about 40 PDFs right now. |
| 16:38 | danlarkin | you can always just download a copy of the website if you want |
| 16:41 | pjb3 | danlarkin: how do you download a copy of the website? |
| 16:42 | danlarkin | wget can follow links |
| 16:44 | hiredman | looks like however I did it already got pushed out of my shell history |
| 16:44 | pjb3 | danlarkin: Is it really as easy as wget --magic http://clojure.org? |
| 16:44 | pjb3 | or do you have to do a bunch of hacking to get a reasonable local copy? |
| 16:46 | danlarkin | yeah, wget -m http://clojure.org |
| 16:46 | hiredman | I think http://www.easysw.com/htmldoc/ is what I used |
| 16:46 | hiredman | made a pdf of the website |
| 16:47 | pjb3 | danlarkin: that didn't work, some error about a certificate |
| 16:48 | hiredman | actually I guess I used the .org version |
| 16:48 | pjb3 | wget --no-check-certificate -m http://clojure.org |
| 16:48 | pjb3 | that gets past the cert error, but then you only get index.html |
| 16:51 | danlarkin | *shrug* |
| 16:51 | danlarkin | -m stands for --mirror |
| 16:51 | danlarkin | which "Turn on options suitable for mirroring. This option turns on recursion and time-stamping, sets infinite recursion depth and keeps FTP directory listings." |
| 16:51 | pjb3 | danlarkin: hmmm..well, it don't work :) |
| 17:01 | danlarkin | ok, here's an incantation that works for me |
| 17:01 | danlarkin | wget --no-check-certificate --mirror -k -w 2 -p clojure.org --convert-links clojure.org |
| 17:02 | danlarkin | -p flag probably not necessary |
| 17:09 | pjb3 | danlarkin: all the links start with / |
| 17:10 | pjb3 | Would have to either run it through a web server locally or figure out a way chomp those off |
| 17:11 | danlarkin | donno, I'm no wget master |
| 17:11 | danlarkin | maybe there's an option for chomping those |
| 17:26 | danlarkin | if I'm merging two hash-maps together and I want to remove an element from the first, the appropriate way to do that would be associate it with nil in the second, right? |
| 17:26 | danlarkin | ,(:foo (merge {:foo 'bar} {:foo nil})) |
| 17:26 | clojurebot | nil |
| 17:26 | danlarkin | ,(:foo {:not-foo 'bar}) |
| 17:26 | clojurebot | nil |
| 17:27 | Chouser_ | a nil value is not the same as a non-existent entry |
| 17:28 | Chouser_ | I don't think there's any way to use merge or merge-with and end up with fewer entries than when you started. |
| 17:28 | danlarkin | yeahh |
| 17:28 | Chouser_ | do you have a list of keys you want to remove? |
| 17:28 | hiredman | (doc dissoc) |
| 17:28 | clojurebot | dissoc[iate]. Returns a new map of the same (hashed/sorted) type, that does not contain a mapping for key(s).; arglists ([map] [map key] [map key & ks]) |
| 17:29 | danlarkin | Well I want a function to return a hash-map and I'll merge that with another |
| 17:29 | danlarkin | but if the function wants to /remove/ an element... |
| 17:29 | hiredman | dissoc |
| 17:30 | Chouser_ | can it return a 2-item vector? [#{set of keys to dissoc} {map to merge}) ? |
| 17:30 | danlarkin | Hmm |
| 17:30 | hiredman | ,(dissoc {:a 1 :b 2} :a) |
| 17:30 | clojurebot | {:b 2} |
| 17:30 | danlarkin | Chouser_: yes I suppose it could, although that's uglier :-/ |
| 17:30 | hiredman | ,(apply dissoc {:a 1 :b 2} #{:a :b}) |
| 17:30 | clojurebot | {} |
| 17:31 | hiredman | danlarkin: why can't the function just dissoc the element it wants to remove? |
| 17:32 | Chouser_ | danlarkin: if you're sure you never want to have a nil value in your final map, I bet we could write something nice to use nil as a sentinel to mean dissoc |
| 17:32 | danlarkin | hiredman: because if I have the function return a hash-map and merge that with another that's no different than just not returning the element from the function |
| 17:33 | danlarkin | Chouser_: mmm. yeah it will be allowed nils now that I think about it. I guess I could use :BALLS or something :) |
| 17:34 | danlarkin | perhaps I'll just have this function return the entire map and not merge it, even though that's amazing either |
| 17:34 | Chouser_ | yeah, you could pass in the other map and have the function do the merging. |
| 17:35 | danlarkin | yeah |
| 17:37 | clows | when i have an anonymous function within an anonymous function *ponder* what does % refer to in that case? |
| 17:38 | danlarkin | can't nest #() forms |
| 17:38 | clows | ok |
| 18:07 | danlarkin | so who's excited for a sweet night of clojure programming?! |
| 18:08 | rhickey | I am! |
| 18:08 | danlarkin | woo hooo |
| 18:13 | grosours | hi there |
| 18:14 | rhickey | hi |
| 18:26 | stuhood | could coercion and type hinting be combined somehow? |
| 18:26 | stuhood | the coercion example on the wiki is really simple, but it is already an example of coercion being ugly |
| 18:27 | stuhood | from |
| 18:27 | stuhood | (defn foo [n] (loop [i 1] (if (< i n) (recur (inc i)) i))) |
| 18:27 | stuhood | to |
| 18:27 | stuhood | (defn foo2 [n] (let [n (int n)] (loop [i (int 0)] (if (< i n) (recur (inc i)) i)))) |
| 18:29 | stuhood | would be nicer to use: |
| 18:29 | stuhood | (defn foo [#^int n] (loop [#^int i 1] (if (< i n) (recur (inc i)) i))) |
| 18:29 | dreish | I think having to give extra information to the compiler so it can make your code go faster is always going to be inherently "ugly". That's somewhere way down the list of reasons premature optimization is forbidden. |
| 18:29 | hiredman | stuhood: how is that nicer? |
| 18:30 | stuhood | it doesn't contain another level of nesting |
| 18:30 | stuhood | for the let |
| 18:30 | sp00oon | hey all. was wondering if it was worth my time & money to buy the Stuart Halloway beta book |
| 18:31 | dreish | sp00oon: If you're just starting out, I'd say absolutely. |
| 18:40 | sp00oon | dreish: Yes. Am just getting my toes wet ;) Thx. |
| 18:42 | stuhood | also, it isn't really worth making a ticket about, but 'foo2' at http://clojure.org/java_interop#toc36 won't compile because it contains an extra paren |
| 19:45 | LARefugee | Anyone see Charles Nutter's recent talk about the JRuby implementation at InfoQ? |
| 19:58 | danlarkin | LARefugee: I haven't, link me? |
| 20:00 | LARefugee | danlarkin: http://www.infoq.com/presentations/nutter-jruby-jvm-lang-summit;jsessionid=4F95BB3A93601B4AE6F69BE064CEBEDD |
| 20:00 | danlarkin | thanks |
| 20:01 | LARefugee | It was gnarly. Ruby is very difficult to make fast. |
| 20:01 | LARefugee | On the jvm at least |
| 20:04 | dreish | Yet just when you thought no one could invent a slower language, along comes Groovy. |
| 20:06 | bitbckt | LARefugee: it isn't particularly quick on C, either. REE is somewhat better, though. |
| 20:08 | bitbckt | Charlie likes to puff about JRuby being comparable in speed to Ruby 1.9 and quicker than Ruby 1.8.6 |
| 20:08 | bitbckt | but that really isn't saying much |
| 20:22 | LARefugee | I haven't looked at REE too closely. Besides better memory performance what's the biggest win? |
| 20:25 | LARefugee | Ruby's been around since 1993! No decen implementation yet. 1.9 was supposed to be a proof-of-concept on the way to 2.0. |
| 20:27 | LARefugee | I was thinking JRuby might be it but after Nutter's talk I'm not so sure people should trust it. |
| 20:40 | danlarkin | this talk makes me think JRuby is just like |
| 20:40 | danlarkin | not worth it |
| 20:40 | danlarkin | with the amount of work arounds they have to do |
| 20:42 | LARefugee | danlarkin: I've read Nutter say that the jvm is a good platform for dynamic languages. Sure didn't seem like it, at least not for ruby. |
| 20:44 | danlarkin | srsly |
| 20:55 | dreish | I think it helps if your language features correspond reasonably closely with what the computer can actually do in a reasonable amount of time. |
| 22:26 | LARefugee | clojurebot: logs? |
| 22:26 | clojurebot | logs is http://clojure-log.n01se.net/ |
| 22:57 | Chouser | clojurebot, mind your grammar. "logs are" |
| 22:57 | danlarkin | patches welcome |
| 22:57 | Chouser | heh |
| 22:57 | danlarkin | couldn't resist, haha |
| 23:00 | danlarkin | :-o someone actually using clojure-json, sweeeet http://github.com/sethtrain/clojure-github/blob/e27d790078307ecf40840d1c0f9817e03f8e6ea3/src/org/buntin/github/email.clj |
| 23:04 | danlarkin | I might change the namespace |
| 23:04 | danlarkin | having my name in there bothers me |
| 23:05 | durka | i mean, you did write it |
| 23:06 | danlarkin | yeah but |
| 23:06 | danlarkin | it's lame |
| 23:07 | Chouser | danlarkin: have your CA in? You could lobby to have it in contrib. |
| 23:08 | danlarkin | true |
| 23:20 | durka | goodnight all |
| 23:20 | durka | this marks the end of winter break, so we'll see how much time school permits for clojure hacking |
| 23:22 | danlarkin | you make your own destiny! |
| 23:44 | danlarkin | joshua choi's fnparse is really cool |
| 23:57 | danlarkin | now if I could just remember BNF from university |