2012-04-01
| 00:00 | TimMc | y3di: Symbols that the compiler special-cases. |
| 00:00 | TimMc | They're built into the compiler as literals. |
| 00:02 | TimMc | y3di: https://github.com/clojure/clojure/blob/1.3.x/src/jvm/clojure/lang/Compiler.java#L39 |
| 00:03 | TimMc | Not everything that the compiler special cases is a special form; many of those are just for optimization or bootstrapping. |
| 00:24 | y3di | wait, whats the difference between binding and let? |
| 00:32 | TimMc | dynamic and lexical scope |
| 00:32 | Frozenlock | http://stackoverflow.com/questions/1523240/let-vs-binding-in-clojure |
| 00:34 | Frozenlock | Is there a function to compress files? |
| 00:40 | Frozenlock | This might do : https://github.com/bonega/pacl |
| 00:44 | muhoo | ns_pablo: preroutes? |
| 00:48 | ns_pablo | muhoo: what do you mean? |
| 00:48 | muhoo | ns_pablo: http://www.webnoir.org/autodoc/1.0.0/noir.core-api.html#noir.core/pre-route |
| 00:48 | ns_pablo | afaik preroutes are used to aggregate behaviors for multiple routes, like checking for authentication |
| 00:49 | ns_pablo | how would I use preroutes in this way? |
| 00:50 | ns_pablo | I'm new with Noir, so forgive me if it's something obvious... |
| 00:50 | muhoo | i dunno, exactly, it's just a guess. |
| 00:50 | muhoo | http://www.webnoir.org/tutorials/routes |
| 00:50 | muhoo | i'm new too |
| 00:50 | muhoo | maybe you could use resp/redirect |
| 00:51 | muhoo | to redirect based on the "module" url |
| 00:52 | muhoo | like (pre-route "/foo" {} (resp/redirect "/soemwher/else")) ? |
| 00:52 | Frozenlock | I think it doesn't solve the basic issue, which if I'm right was to be able to simply specifiy a part of the url. "/test" instead of "/blog/test". |
| 00:52 | ns_pablo | well, that might work... I'll take a look at the source to see what exactly is preroute doing |
| 00:52 | ns_pablo | Frozenlock but it might be a start towards a homegrown solution |
| 00:55 | ns_pablo | what I'm really looking for is something like this http://www.padrinorb.com/guides/mounting-applications |
| 01:04 | ns_pablo | This would be actually pretty easy to accomplish with Moustache: http://pastie.org/3707127 |
| 04:10 | wei_ | aoeu |
| 04:11 | wei_ | oops sorry |
| 06:35 | espringe | I've written a parser, which produces an in-memory sexpresion that can be eval'd or what not. But I want to transform it into a a string, that is valid clojure code. Is there a built-in function for that? |
| 06:36 | espringe | e.g. when it turns the three letter string 'dog' into the five-lettter "dog" (adds quotes) |
| 06:39 | morphling | espringe: pr |
| 06:39 | espringe | morphling: perfect, thanks |
| 06:40 | bsteuber | or pr-str |
| 06:43 | laurus | Are people still working on Incanter? |
| 06:46 | bsteuber | laurus: given https://github.com/liebke/incanter/network - yes |
| 06:49 | laurus | bsteuber, interesting, thanks for that. |
| 08:20 | jayunit100 | how does clojure "know" when its reached the end of a lazy-seq ? |
| 08:20 | jayunit100 | (doc lazy-seq) |
| 08:20 | clojurebot | "([& body]); Takes a body of expressions that returns an ISeq or nil, and yields a Seqable object that will invoke the body only the first time seq is called, and will cache the result and return it on all subsequent seq calls. See also - realized?" |
| 08:22 | jayunit100 | Im looking at the code for the partition function in https://github.com/richhickey/clojure-contrib/blob/master/src/main/clojure/clojure/contrib/string.clj..... and trying to figure out how it is that the (lazy-seq ... ) function ever returns. |
| 08:26 | gfredericks | jayunit100: without looking at it, the confusion probably comes from the fact that lazy-seq is a macro |
| 08:26 | gfredericks | macros don't follow the normal rules of evaluation |
| 08:26 | jayunit100 | oh duh |
| 08:26 | jayunit100 | thanks that helps okay. |
| 08:27 | jayunit100 | so... lazy-seq is probably taking my function and implementing the ISeq interfaces for me. |
| 08:28 | gfredericks | whatever body you pass to lazy-seq has to return a seq |
| 08:29 | gfredericks | what lazy-seq does is prevent the body from being evaluated until necessary |
| 08:30 | gfredericks | regarding your earlier question about how clojure knows it has reached the end -- same as with a non-lazy seq. If the rest method returns nil (I believe) then that's the end |
| 08:30 | gfredericks | give or take a few details |
| 08:30 | gfredericks | the fact that it's lazy only changes when the sequence is computed, not how you interact with it |
| 08:30 | gfredericks | as a consumer of the seq |
| 08:39 | jayunit100 | (macroexpand clojure.contrib.string/partition) |
| 08:39 | jayunit100 | seems to return something not-useful |
| 08:40 | raek | jayunit100: macroexpand is a function so you have to give it the unevaluated code |
| 08:40 | raek | (macroexpand '(clojure.contrib.string/partition ...)) |
| 08:41 | raek | ,(macroexpand '(when x a b c)) |
| 08:41 | clojurebot | (if x (do a b c)) |
| 08:42 | jayunit100 | hmmmmm |
| 08:43 | raek | also, clojure.contrib.string is outdated |
| 08:43 | raek | if possible, use clojure.string instead |
| 08:43 | jayunit100 | user=> (require 'clojure.contrib.string) |
| 08:43 | jayunit100 | nil |
| 08:43 | jayunit100 | user=> (macroexpand '(clojure.contrib.string/partition pattern largeString)) |
| 08:43 | jayunit100 | (clojure.contrib.string/partition pattern largeString) |
| 08:43 | raek | are you sure partition is not just a regular function? |
| 08:44 | jayunit100 | it is . but i thought macroexpand would look for macros inside of it :) |
| 08:44 | jayunit100 | I guess it doesnt work that way :( |
| 08:44 | raek | the code in a function body is not inserted into the call site |
| 08:44 | jayunit100 | but im surprised it didnt through an error. |
| 08:44 | jayunit100 | throw i mean. |
| 08:45 | jayunit100 | should macroexpand throw an error if a function is given as input |
| 08:45 | raek | macroexpand takes an arbitrary expression and expands any macros in it |
| 08:45 | raek | in you case there were none, so the input was the same as the output |
| 08:46 | raek | think of macroexpand as a pre-filtering step of the compiler |
| 08:46 | raek | jayunit100: anyway, you can copy the body of the partition source code and pass it to macroexpand |
| 08:47 | raek | ,(macroexpand '(lazy-seq (when x (cons y z)))) |
| 08:47 | clojurebot | (new clojure.lang.LazySeq (fn* [] (when x (cons y z)))) |
| 08:48 | raek | here you see a glimpse of how lazy seqs are implemented |
| 08:57 | gfredericks | jayunit100: one thing that may not be obvious is that because macros are effective at compile-time, a macro is only concerned with the _forms_ of the code that is given to the macro |
| 08:58 | gfredericks | (defmacro is-string? [x] (if (string? x) true false)) |
| 08:58 | gfredericks | (is-string? "foo") will emit true |
| 08:58 | gfredericks | (let [s "foo"] (is-string? s)) will emit false |
| 08:59 | gfredericks | so when you wrote (macroexpand '(clojure.contrib.string/partition pattern |
| 08:59 | gfredericks | largeString)) |
| 09:00 | gfredericks | eh nevermind I don't have anything else to say |
| 09:02 | RickInGA | TheBusby: you around? |
| 09:39 | Lajla | &(:fart {:fart "lol"}) |
| 09:39 | lazybot | ⇒ "lol" |
| 09:40 | Lajla | &({:fart "lol"} :fart) |
| 09:40 | lazybot | ⇒ "lol" |
| 09:40 | Lajla | &(:fart {:diarrhoea "lol"}) |
| 09:40 | lazybot | ⇒ nil |
| 09:55 | gtrak`` | anyone ever write a physics engine? I'm getting some fun 'emergent' behavior :-), not sure where to go to learn about how to do this right: http://www.youtube.com/watch?v=415OTzYEXsk |
| 09:57 | gfredericks | gtrak``: what's going on in this video? |
| 09:58 | gfredericks | in particular with the all the balls falling to one side thing |
| 09:58 | gtrak`` | ah, that's from user input, applying an acceleration |
| 09:58 | AimHere | He forgot to switch the second law of thermodynamics on ;) |
| 09:58 | gfredericks | okay; that was my guess |
| 09:58 | gtrak`` | the emergent parts are the collisions that should happen and don't and the funny orbiting and sticking |
| 09:58 | tmciver | gtrak``: yes, I'm curious too. It looks like the balls stick together sometimes. |
| 09:59 | tmciver | gtrak``: if you didn't intend for that behavior, it might be a bug with the collision detection. |
| 09:59 | gfredericks | maybe he programmed in gravity :) |
| 09:59 | gtrak`` | van der waals forces |
| 10:00 | tmciver | gtrak``: Really? Is it supposed to be a molecular simulator? |
| 10:00 | gtrak`` | j/k about that, yea, collision detection's borken, fun thing about this kind of thing is it's impossible to test :-) |
| 10:01 | gfredericks | that can't be true |
| 10:01 | gfredericks | is it deterministic? |
| 10:01 | gtrak`` | well, *hard* to test |
| 10:01 | gfredericks | oh okay then :) |
| 10:01 | tmciver | Yes, it should be testable. |
| 10:02 | gtrak`` | yea, it's all functional except for a single atom swap! on top |
| 10:02 | gfredericks | run the thing and expect that at each step the balls aren't closer than their radius |
| 10:02 | gfredericks | watch the failures come piling in |
| 10:03 | gfredericks | oh I just imagined doing it multithreaded where each ball is a ref |
| 10:03 | gtrak`` | oh gosh, haha, that would be awful |
| 10:03 | gfredericks | and you have a spatial index telling you which balls are nearby that you need to coordinate with |
| 10:03 | gtrak`` | but actually the drawing thread is separate, the simulation runs at 500fps |
| 10:04 | tmciver | nice |
| 10:04 | gtrak`` | no optimization really, I'm impressed with the jvm |
| 10:06 | gtrak`` | gfredericks, yea, the spatial index is one way to avoid checking every object against every object, right now it's n^2 |
| 10:08 | y3di | ref and atoms are pretty similar |
| 10:09 | gtrak`` | i imagine if you're doing all the calcs on one thread like me, an atom's much better |
| 10:10 | gfredericks | y3di: yeah using refs would allow you to do some updates in parallel |
| 10:10 | gtrak`` | and there's an issue with throughput vs latency, it's always better to have predictable latency |
| 10:11 | gtrak`` | in games i mean |
| 10:12 | gtrak`` | i could use refs for scripted events, but not a tight simulation like this |
| 10:12 | gfredericks | I didn't mean it too seriously :) |
| 10:12 | gfredericks | although it'd be interesting to know what kind of scalability that would buy |
| 10:13 | gtrak`` | hmm, i could probably pmap some things |
| 10:13 | gtrak`` | if you're curious: https://github.com/gtrak/quilltest/blob/master/src/quilltest/balls.clj |
| 10:15 | y3di | how come some functions like swap! have a bang at the end? |
| 10:15 | y3di | what does the ! represent? |
| 10:15 | gtrak`` | ! generally means mutable i think |
| 10:15 | gfredericks | sometimes mutation, sometimes hazardness... |
| 10:15 | gfredericks | sometimes it has to do with dosync specifically I think |
| 10:15 | gfredericks | in the case of swap! |
| 10:16 | tmciver | gtrak``: how is your collision checking n^2? I wrote a very simple 2D physics engine in Java some time ago but I believe my collision checking was something approximating n factorial: check one object against all others, if it wasn't colliding with anything, remove if from the list of objects to check. Then continue with the rest of them. |
| 10:16 | tmciver | s/remove if/remove it |
| 10:16 | gfredericks | tmciver: that sounds n^2 to me |
| 10:16 | gfredericks | you're checking all pairs |
| 10:17 | tmciver | I'm terrible at this complexity stuff. |
| 10:17 | gfredericks | tmciver: it's addition vs multiplication |
| 10:17 | gtrak`` | (filter (fn [[a b]] (p/colliding? (:rigid-body a) (:rigid-body b)))(for [x guys y guys [x y])) |
| 10:17 | gfredericks | tmciver: factorial is (apply * (range n)), whereas in this case it is (apply + (range n)) |
| 10:17 | gfredericks | which is asymptotically equiv to n^2 |
| 10:18 | gtrak`` | i could fix that for to remove duplicate pairs if I keep a set |
| 10:18 | gtrak`` | but it's still n^2 |
| 10:18 | tmciver | gtrak``: you *may* be able to do better than that; aren't you chekcking objects against themselves and rechecking objects that can be known not to be colliding with anything? |
| 10:19 | gfredericks | I think that's what he means by removing duplicate pairs |
| 10:19 | gtrak`` | yea, i can def do better, but like i said, it's totally fast enough right now for casual things :-), i want to make it right though |
| 10:19 | gfredericks | tmciver: if an algorithm has anything to do with factorials you don't have much hope for doing anything with more than 10 objects |
| 10:21 | tmciver | gfredericks: so the algo I described is something less than n^2. I don't know what kind of frame rate I was getting but my simulator seemed to move along with much more that 10 objects. |
| 10:21 | gtrak`` | duplicate as in [:a :b] = [:b :a] |
| 10:22 | gfredericks | tmciver: less than n^2 steps in absolute terms, but in complexity terms it is still n^2 |
| 10:22 | tmciver | gfredericks: makes sense. |
| 10:22 | tmciver | gtrak``: also duplicate as in checking :a against :a |
| 10:22 | gtrak`` | n^2 -5 is still n^2, so is n^2 -5x |
| 10:23 | gfredericks | n^2-5n you mean? :) |
| 10:23 | gtrak`` | tmciver, yea, I caught that one, just didn't paste it in |
| 10:23 | gtrak`` | gfredericks, yes :-) |
| 10:24 | gfredericks | and most relevant to this case is that 0.5*n^2 is still n^2 |
| 10:34 | jayunit100 | what is a " body of expressions" |
| 10:34 | y3di | why would you use futures over a function that started a new java thread? |
| 10:35 | y3di | jayunit100: in context to defining macros? |
| 10:35 | jayunit100 | yeah |
| 10:36 | gfredericks | y3di: futures are syntactically simpler, and take care of providing a box for the result of the computation to go in |
| 10:36 | gfredericks | they might also be thread-pooled |
| 10:37 | gfredericks | and maybe even do the binding thing |
| 10:38 | jayunit100 | im wondering... what it means to take a "body of expressions" as input. Is that synonymous to taking "n expressions" |
| 10:38 | gfredericks | yeah it means multiple experssions |
| 10:38 | y3di | jayunit100: i believe so |
| 10:38 | gfredericks | the canonical example is do |
| 10:38 | y3di | gfredericks: what's thread pooling? |
| 10:39 | gfredericks | y3di: runs the futures in a thread pool instead of creating a new thread for each one indiscriminately |
| 10:39 | gfredericks | which I assume means creating a million futures is more feasible than a million threads |
| 10:39 | y3di | so that means, oh ok, so futures will essentially wait for threeads to free up |
| 10:39 | gtrak`` | y3di, i think in general you should separate computations (values) from the details of their execution, future is more abstract than a thread but gets the job done |
| 10:40 | gfredericks | &(->> (for [x (range 1000000)] (future x)) (map deref) (apply +)) |
| 10:40 | lazybot | java.lang.SecurityException: You tripped the alarm! future-call is bad! |
| 10:41 | gtrak`` | if you look at haskell's 'everything's lazy', that's more obvious |
| 10:41 | gtrak`` | they might take it too far, though |
| 10:42 | gfredericks | oh I guess that code snippet doesn't actually illustrate anything since it's lazy |
| 10:42 | gfredericks | would have to doall before the map |
| 10:43 | jayunit100 | hmmm it looks like (lazy-seq) cant have nils in the middle .... since that is the "end" of a the list. |
| 10:44 | gfredericks | jayunit100: nil values should be fine |
| 10:44 | jayunit100 | then how will the lazy-seq "know" when the list is done ? |
| 10:44 | jayunit100 | it would be infinitely long ? |
| 10:44 | gfredericks | it's when the entire rest of the sequence is null |
| 10:44 | gfredericks | not just one of the entries |
| 10:45 | jayunit100 | oh ok. so if "rest" is null |
| 10:45 | jayunit100 | where rest is a list. |
| 10:45 | gfredericks | right |
| 10:45 | gfredericks | &(count (lazy-seq (cons 1 nil))) |
| 10:45 | lazybot | ⇒ 1 |
| 10:46 | gfredericks | &(count (lazy-seq nil)) |
| 10:46 | lazybot | ⇒ 0 |
| 10:46 | jayunit100 | is there a way to grep the history of my repl |
| 10:46 | jayunit100 | like in bash? |
| 10:46 | jayunit100 | ,(history) |
| 10:46 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: history in this context, compiling:(NO_SOURCE_PATH:0)> |
| 10:53 | jayunit100 | that is, maybe someone knows where the repl stores history so i can hack it. |
| 11:02 | jayunit100 | hmmm.. is there a way to reload the current lein namespace ? |
| 11:02 | jayunit100 | i.e. reload the source without explicitly mentioning a file name. |
| 11:03 | mega` | youst lein not lein.core? |
| 11:03 | mega` | just* |
| 11:03 | jayunit100 | you mean.... |
| 11:04 | jayunit100 | i ran "lein repl" from the root of a project.. and made some changes to multiple files. |
| 11:04 | mega` | i dont realy know the use case are you writing a plugin ?? why do you whant to reaload the source |
| 11:04 | jayunit100 | can I reload the project in lein |
| 11:04 | jayunit100 | no , much simpler than that. |
| 11:04 | llasram | jayunit100: (require 'your.namespace :reload) ? |
| 11:04 | mega` | oo the project |
| 11:04 | jayunit100 | Im just editing more than one file in a clojure project |
| 11:05 | jayunit100 | ---- im used to clicking "clean" in eclipse. assuming there is an analog in lein ? |
| 11:05 | jayunit100 | sorry about the confusion :) |
| 11:07 | jayunit100 | (other than ctrl-c) |
| 11:08 | jayunit100 | hmm this is interesting - looks like "time" doesnt evaluate an anonymous function that is passed in. I wonder why ? |
| 11:09 | jayunit100 | ,(time #(reduce + (range 1000))) |
| 11:09 | clojurebot | "Elapsed time: 0.429 msecs" |
| 11:09 | clojurebot | #<sandbox$eval27$ret__3993__auto____28 sandbox$eval27$ret__3993__auto____28@118b78d> |
| 11:09 | mega` | , (time (reduce + (range 10000))) |
| 11:09 | clojurebot | "Elapsed time: 69.498 msecs" |
| 11:09 | clojurebot | 49995000 |
| 11:09 | mega` | its a macro |
| 11:11 | gtrak`` | ,(time (#(reduce + (range 1000))) |
| 11:11 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading> |
| 11:11 | mega` | missing a paren |
| 11:11 | gtrak`` | ,(time (#(reduce + (range 1000)))) |
| 11:11 | clojurebot | "Elapsed time: 1.219 msecs" |
| 11:11 | clojurebot | 499500 |
| 11:11 | gtrak`` | jayunit100, or for more clarity |
| 11:12 | gtrak`` | ,#(reduce + (range 1000))) |
| 11:12 | clojurebot | #<sandbox$eval139$fn__140 sandbox$eval139$fn__140@f2e01b> |
| 11:13 | mega` | , (macroexpand '(time (#(reduce + (range 1000))))) |
| 11:13 | clojurebot | (let* [start__3992__auto__ (. java.lang.System (clojure.core/nanoTime)) ret__3993__auto__ ((fn* [] (reduce + (range 1000))))] (clojure.core/prn (clojure.core/str "Elapsed time: " (clojure.core// (clojure.core/double (clojure.core/- (. java.lang.System (clojure.core/nanoTime)) start__3992__auto__)) 1000000.0) " msecs")) ret__3993__auto__) |
| 11:14 | jayunit100 | okay.... |
| 11:14 | mega` | clear as paj |
| 11:15 | jayunit100 | Im trying to understand whats the difference when I wrap the anonymous functoin in a closure. |
| 11:15 | jayunit100 | ,#(reduce + [1 2]) |
| 11:15 | clojurebot | #<sandbox$eval193$fn__194 sandbox$eval193$fn__194@5abaee> |
| 11:15 | gtrak`` | huh? |
| 11:15 | jayunit100 | ,(#(reduce + [1 2])) |
| 11:15 | clojurebot | 3 |
| 11:15 | jayunit100 | ha |
| 11:15 | jayunit100 | okay |
| 11:15 | jayunit100 | wrapping it in clojure results in evaluation. |
| 11:15 | gtrak`` | there it is, eureka!!! |
| 11:15 | jayunit100 | :] |
| 11:16 | gtrak`` | actually, the anonymous function is a closure, wrapping it in parens executes a function, just like anything else |
| 11:16 | gtrak`` | ,(1) |
| 11:16 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn> |
| 11:17 | jayunit100 | ok |
| 11:24 | jayunit100 | (bump question about grepping through lein history). |
| 11:32 | jayunit100 | i do see a .lein folder, but that seems not to have any history data in it. |
| 11:53 | yoklov | is there a better way to get the current value of 'this' in clojurescript than (js* "this") |
| 11:54 | mega` | theres a this-as macro |
| 11:54 | yoklov | is there? |
| 11:55 | yoklov | still not really what I'm looking for. |
| 11:55 | gtrak`` | huh, why wouldn't that be the same thing? |
| 11:55 | yoklov | oh wait |
| 11:55 | mega` | js/this maybe works |
| 11:56 | yoklov | i misunderstood what this-as did |
| 11:56 | gtrak`` | http://www.chris-granger.com/2012/02/20/overtone-and-clojurescript/ |
| 11:56 | gtrak`` | there's an example |
| 11:58 | mega` | https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/core.clj#L205 |
| 11:58 | yoklov | yup |
| 11:58 | yoklov | i was already on that page actually haha |
| 11:58 | yoklov | looking for something like that. |
| 11:59 | gtrak`` | gawd, extend-type is pretty intense |
| 12:00 | mega` | yea maybe extract some functions there |
| 12:02 | yoklov | they'd have to be in the api if you did that though, right? |
| 12:02 | yoklov | because it's a macro and you couldn't defn- them |
| 12:02 | mega` | you can call functions from macros |
| 12:02 | yoklov | not private ones though, right? |
| 12:02 | yoklov | in a separate namespace |
| 12:03 | yoklov | i actually am unsure how clojure deals with that, its an issue I always thought racket dealt with inelegantly |
| 12:03 | mega` | you can call them while generating the code |
| 12:03 | yoklov | right |
| 12:03 | mega` | you cant refere to them in the produced code but you cant do that in cljs anny way |
| 12:04 | yoklov | hm, i guess less of that is actual macro output than i thought at first glance |
| 12:04 | mega` | Oo o ok |
| 12:04 | mega` | yea its mostly code and branches |
| 12:07 | jayunit100 | hungarian notation for clojure ! |
| 12:07 | jayunit100 | http://web.mst.edu/~cpp/common/hungarian.html |
| 12:07 | mega` | love it |
| 12:07 | mega` | start doing that |
| 12:08 | TimMc | noooo, that's Systems Hungarian |
| 12:08 | TimMc | https://en.wikipedia.org/wiki/Hungarian_notation#Systems_vs._Applications_Hungarian |
| 12:09 | jayunit100 | ah good point |
| 12:10 | mega` | i had a robotics corse in scool where whe had to use a simelar notation |
| 12:10 | jayunit100 | what about maps/arrays/lists |
| 12:10 | mega` | write o-* like in "object" :D |
| 12:11 | jayunit100 | ,(nth "ABC") |
| 12:11 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$nth> |
| 12:11 | jayunit100 | oops meant to put that in the repl |
| 12:12 | yoklov | comma included? :p |
| 12:12 | jayunit100 | yup |
| 12:12 | jayunit100 | dont ask |
| 12:12 | yoklov | i mean, it is whitespace :) |
| 12:12 | jayunit100 | ha |
| 12:13 | jayunit100 | its funny b/c no joke then i did it in the repl to w/ the comma . |
| 12:27 | jayunit100 | ,(seq (.toCharArray "ASDF")) |
| 12:27 | clojurebot | (\A \S \D \F) |
| 12:27 | jayunit100 | this seems awefully non-elegant |
| 12:27 | mega` | Oo |
| 12:27 | mega` | , (seq "ASDF") |
| 12:27 | clojurebot | (\A \S \D \F) |
| 12:27 | mega` | pew pew |
| 12:28 | gtrak`` | what else would it be? |
| 12:28 | gtrak`` | maybe it just looks ugly :-) |
| 12:28 | jayunit100 | well.. figured ther'd be a function for it |
| 12:29 | mega` | , (apply str (seq "ASDF")) |
| 12:29 | clojurebot | "ASDF" |
| 12:29 | jayunit100 | with all this "clojurscript", "clojure in python" stuff... Im thinking it might be best to avoid java artifacts when possible |
| 12:29 | jayunit100 | ,(seq "ASDF") |
| 12:29 | clojurebot | (\A \S \D \F) |
| 12:29 | jayunit100 | ha |
| 12:38 | mega` | reddit has a time machine now :D :D :D :D |
| 12:56 | jonasen | lynaghk`: ping |
| 13:02 | hhutch | ibdknox: are you around? |
| 13:06 | jayunit100 | um need some newbie help on a find-first-repeated-character . |
| 13:06 | jayunit100 | http://pastebin.com/iCTmxAX4 |
| 13:07 | jayunit100 | if anyone has 3 milliseconds to look. Error is : ClassCastException java.lang.Character cannot be cast to clojure.lang.IFn problems.core/eval816 (NO_SOURCE_FILE:196) |
| 13:07 | mk | jayunit100: you seem to be putting a character into a list and accidentally executing it |
| 13:08 | mega` | you are using underline in your names |
| 13:08 | jayunit100 | no underlines ? |
| 13:08 | mega` | thats clearly the prob |
| 13:08 | mega` | ofc |
| 13:08 | jayunit100 | wow |
| 13:08 | mk | jayunit100: the convention is to use - instead of _ |
| 13:09 | jayunit100 | (defn first-duplicate-char [str-in] |
| 13:09 | jayunit100 | (loop [list-Rem (seq str-in) set-Seen (set [])] |
| 13:09 | jayunit100 | (print (type list-Rem) " " list-Rem (next list-Rem) "\n") |
| 13:09 | jayunit100 | (if (= 0 (count str-in)) |
| 13:09 | jayunit100 | nil |
| 13:09 | jayunit100 | (if (some #(= (first list-Rem) %) set-Seen) |
| 13:09 | mega` | also to create a set use #{} |
| 13:09 | jayunit100 | (first list-Rem) |
| 13:09 | jayunit100 | (recur |
| 13:09 | jayunit100 | (seq (next list-Rem)) |
| 13:09 | jayunit100 | (conj set-Seen (first list-Rem))))))) |
| 13:09 | dnolen | jayunit100: please don't paste in channel |
| 13:09 | jayunit100 | oh god that was ugly sorry wont do it again. |
| 13:09 | mega` | , (class #{}) |
| 13:10 | clojurebot | clojure.lang.PersistentHashSet |
| 13:10 | dnolen | ,(let [x_cool 1] (+ 1 x_cool)) |
| 13:10 | clojurebot | 2 |
| 13:10 | jayunit100 | I think underlines are okay. |
| 13:10 | dnolen | jayunit100: they are |
| 13:11 | mk | just don't use them in your code if you want it to be easy to read |
| 13:11 | dnolen | jayunit100: as mk says, _ are not idiomatic in names |
| 13:12 | jayunit100 | updated.... But still fails .... :(. Whats the best way to debug this ? http://pastebin.com/RCXHy7bb |
| 13:12 | mk | (first list_Rem) looks like it has 3 elements at a glance, while (first list-rem) has just 2 |
| 13:13 | TimMc | mk: Huh, that hasn't been a problem for me. |
| 13:13 | TimMc | ...but maye that's because I've been doing some Python programming |
| 13:14 | lynaghk | jonasen: pong |
| 13:14 | jonasen | lynaghk: I released 0.0.3 |
| 13:14 | mk | TimMc: it's subtle. It's just a bit of extra noise that you don't need (like the capitals on Rem) |
| 13:14 | lynaghk | jonasen: yeah, I just saw that. Thanks! |
| 13:15 | jayunit100 | yeah. the rem should be lower case. |
| 13:15 | lynaghk | I'll do one last run through with cljx and open source that later today |
| 13:15 | jayunit100 | but of course... my concern is this weird cast thingy. it seems perfect to me. the recursion prints out the correct smaller list on every iteration. |
| 13:16 | jayunit100 | update --- okay, its definetly failing when it completes. For some reason... the return value is being evaluated or something... rather than just printed out at the REPL. |
| 13:17 | lynaghk | jonasen: also, re: mailing list. I don't think it would hurt. There seem to be a lot of people watching Kibit, so it'd be interesting to see what everyone is doing with it. Github chats are skewed to people with, er, issues. |
| 13:17 | mega` | jayunit100: http://pastebin.com/3P9Qd8P7 |
| 13:17 | mega` | jayunit100: just to show you some stuff |
| 13:17 | dnolen | jonasen: lynaghk: I know I've said this before, but kibit is awesome! |
| 13:18 | jayunit100 | mega thanks |
| 13:18 | jonasen | dnolen: thanks! |
| 13:18 | jayunit100 | mega`: thanks i mean. :-] |
| 13:18 | dnolen | jonasen: lynaghk: I gave kibit 0.2 a run on Clojure itself and it ran suprisingly quickly. |
| 13:18 | lynaghk | dnolen: yes, it is crazy awesome! |
| 13:18 | mk | what does non-repetitive mean? |
| 13:19 | mk | which problem is this from? |
| 13:19 | dnolen | so kibit can easily handle 14000 lines of Clojure which is going to bigger than most Clojure / ClojureScript projects |
| 13:19 | mega` | jayunit100: the ` is dear to me |
| 13:19 | lynaghk | dnolen: your speed test might make this a moot point, but will the fork/join stuff work automagically once it's merged into core.logic? |
| 13:20 | jayunit100 | ha |
| 13:20 | jonasen | dnolen: I've done some optimizations on a private branch so I know how to make it run quicker if necessary :) |
| 13:20 | dnolen | lynaghk: probably, but I haven't looked into it quickly. |
| 13:20 | dnolen | jonasen: yeah as the rules get larger you probably want to do some indexing. |
| 13:20 | dnolen | I mean I haven't look into it deeply. |
| 13:21 | dnolen | jonasen: is it pretty easy to add your own rules right now? |
| 13:21 | jonasen | dnolen: no. This release is mostly for Kevin ;) More to come! |
| 13:22 | dnolen | jonasen: yeah I imagine different shops would want to add rules for work practices. |
| 13:22 | lynaghk | dnolen: later today I'll be releasing a kibit-based lein plugin for rewriting sources. There is an option for custom rules in that |
| 13:22 | lynaghk | dnolen: depending on what you want to do with your custom rules. |
| 13:23 | dnolen | jonasen: one thing to think about is very complex rules really are possible - did the file ever get closed kind of thing. non thread safe Java types etc. You could probably even detect race conditions in ClojureScript. |
| 13:24 | dnolen | lynaghk: very cool! |
| 13:27 | jayunit100 | ok migrated to stack overflow : I think the issue is that the return val is being evaluated. not sure why though. probably a good lesson in here, somewhere. http://stackoverflow.com/questions/9966483/clojure-return-value-being-evaluated .. |
| 13:34 | TimMc | jayunit100: (set []) is #{}, (seq (next ...)) is (next ...), #'some on a set should really be #'contains |
| 13:34 | jayunit100 | TimMc ? |
| 13:35 | TimMc | &(contains? (set "hello") \o) |
| 13:35 | lazybot | ⇒ true |
| 13:35 | jayunit100 | oh i see, again not idiomatic. |
| 13:35 | TimMc | And I think you want rest, not next. |
| 13:35 | jayunit100 | yeah, I was doing that just to validate the types and make them super explicit. |
| 13:35 | jayunit100 | why rest not next? |
| 13:36 | jayunit100 | ,(= (rest [1 2]) (next [1 2])) |
| 13:36 | clojurebot | true |
| 13:36 | xeqi | ,(= (rest []) (next [])) |
| 13:36 | clojurebot | false |
| 13:36 | jayunit100 | touche. |
| 13:37 | hhutch | dnolen: have you used ibdknox's monet? |
| 13:38 | dnolen | hhutch: i have not |
| 13:38 | jayunit100 | TimMc: same problem still exists, even after changing to "rest" . |
| 13:38 | mfex | jayunit100, the exceptions are probably thrown by functions using first-duplicate-char, rather than in the function itself |
| 13:39 | hhutch | dnolen: you've done a bit of canvas+clojurescript though, right? |
| 13:39 | dnolen | hhutch: actually not much |
| 13:39 | dnolen | hhutch: do you have a general question? |
| 13:39 | hhutch | dnolen: ok. i'm just concerned about the cpu usage |
| 13:40 | dnolen | hhutch: I would just program canvas directly w/ CLJS |
| 13:41 | dnolen | hhutch: monet I think monet may lean on some of the higher level CLJS features which is not so good of your doing lots of custom drawing and perf really matters. |
| 13:41 | dnolen | hhutch: ibdknox would know better than I tho I haven't looked at monet closely. |
| 13:41 | hhutch | dnolen: well, the issue with monet that i can see, which is just using canvas directly, is that it has a draw-loop which is redrawing the canvas constantly |
| 13:41 | jayunit100 | mfex hmm. im calling it from the repl. |
| 13:42 | jayunit100 | mfex: |
| 13:42 | jayunit100 | OMG THANK YOU |
| 13:42 | hhutch | i have a cellular automata that is eating up 100% cpu when run in chrome |
| 13:42 | jayunit100 | my problem was that I was wrapping the call in another closure somewhere. |
| 13:42 | dnolen | hhutch: just write your own thing :) |
| 13:43 | hhutch | dnolen: yeah i'm going to, i just wanted to see if anybody else had looked at the issue |
| 13:43 | mfex | jayunit100, the function can still use some work tho :) |
| 13:43 | jayunit100 | Man.. It would be cool if clojure could embed some kind of safeguards for this. I always run into this problem. |
| 13:43 | jayunit100 | Yeah, I was trying to hack it together as fast as possible without using the cheatsheet |
| 13:43 | hhutch | dnolen: thanks |
| 13:43 | dnolen | hhutch: fwiw, even pure JS I tend to avoid libraries for custom canvas drawing. |
| 13:44 | jayunit100 | Im finding that i generally spend to much time w/ lein and docs when im learning new clojure stuff.. rather than focuing on writing stateless/dynamic lisp. the latter i think is more important as a first step . |
| 13:44 | Frozenlock | Is there a way to send a file to a Noir server by simply double clicking on an hyperlink shortcut? I want the user to be able to go the website and at the same time send pre-made data (small file). I'm thinking of using B64 encoded file in the url, but it feels like an ugly hack. |
| 13:45 | TimMc | jayunit100: I did a full answer on stackoverflow |
| 13:46 | jayunit100 | Cool thanks. Im cleaning it up now. |
| 13:49 | weavejester | Has anyone ran into problems with lein2 and trampoline? |
| 13:49 | dnolen | weavejester: yep |
| 13:49 | dnolen | weavejester: well I should qualify that - lein2 and lein-cljsbuild w/ trampoline doesn't seem to work. |
| 13:49 | weavejester | dnolen: Are you getting an "Unreadable form" error? |
| 13:50 | dnolen | weavejester: hmm, no I wasn't getting a specific error - just wasn't working. |
| 13:50 | weavejester | Hm… I don't see any issues open like this. I guess I'll report it. |
| 13:51 | TimMc | jayunit100: Made some more edits. I think I'm done. |
| 13:56 | TimMc | jayunit100: Your problem was that (= 0 (count str-in)) never changes, so you eventually try to call first on nil. |
| 13:56 | TimMc | Don't know if you saw that -- I edited it in just now. |
| 13:57 | AimHere | Idiomatically, isn't (= 0 (count str-in)) better written as (zero? (count str-in)) or even better (empty? str-in) ? |
| 13:57 | jayunit100 | TimMc: actually that wasnt causing the bug. it was the way i called it at the repl |
| 13:58 | TimMc | &(first nil) ; oh, you might be right... |
| 13:58 | lazybot | ⇒ nil |
| 13:58 | jayunit100 | AimHere: yeah. much more idiomatic to do it that way. |
| 13:58 | andyfingerhut | Would a github-related question be out of line here, if it is for a Clojure project on github? |
| 13:58 | jayunit100 | TimMc: I suggest edit your answer to clarify that the function, inspite of its ugliness, works as is. |
| 13:59 | jayunit100 | andyfingerhut: i think its okay to ask slightly off topic questions sparingly. |
| 13:59 | TimMc | Ah, it does! |
| 13:59 | dnolen | andyfingerhut: all Clojure related things allowed ;) |
| 13:59 | jayunit100 | TimMc: what does & do ? |
| 14:00 | AimHere | Tells the bot to evaluate it |
| 14:00 | AimHere | If you want a second opinion, use a comma instead |
| 14:00 | AimHere | ,(first nil) |
| 14:00 | andyfingerhut | I forked someone else's project, committed some changes, made a pull request, they pulled them in, but they also had their own changes that aren't in my version. If I want to get up to the latest, should I delete my fork and create a new one based on their latest version, or is there a different way? |
| 14:00 | clojurebot | nil |
| 14:00 | jayunit100 | sorry guys btw ....... im a hadoop developer so i never get to do any clojure and im constantly reusing variables and state... so i have a hard time getting back into clojureland. |
| 14:02 | TimMc | andyfingerhut: If you pull from upstream (their repo) into yours, you can get the changes. |
| 14:02 | mega` | andyfingerhut: your pull only needs to contain the changes you made.... are they in collition with there changes |
| 14:02 | mega` | ? |
| 14:03 | andyfingerhut | TimMc: You mean in my local repo on my laptop, I do a "git pull" with some kind of additional args to indicate the pull should come from their github repo instead of my github repo? |
| 14:04 | TimMc | yep, don't remember the incantation off the top of my head |
| 14:04 | andyfingerhut | TimMc: Thanks, I'll look at some docs focused in that area. Probably need to figure out the correct remote branch name. |
| 14:04 | TimMc | git remote add upstream git://... ; git fetch upstream ; git merge upstream/master |
| 14:05 | mega` | http://gitref.org/remotes/ |
| 14:05 | TimMc | those last two can probably be combined into git pull upstream master |
| 14:05 | andyfingerhut | Thanks. Those are definitely going in my own personal git cheatsheet for future reference, since I won't be doing it very often. |
| 14:06 | TimMc | I had to go into my `history` list to find that. |
| 14:07 | mega` | no github related april fools?? seen |
| 14:08 | TimMc | There's this, whatever it is: http://cloud.github.com/ |
| 14:09 | mega` | pritty :P |
| 14:10 | jayunit100 | how come the REPL can't evaluate a destructured list |
| 14:10 | TimMc | ...but I don't know how old it is. |
| 14:10 | jayunit100 | ,[[head & tail] [1 2 3 4]] |
| 14:10 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: head in this context, compiling:(NO_SOURCE_PATH:0)> |
| 14:11 | mega` | jayunit100: needs to be a let statment |
| 14:11 | TimMc | jayunit100: 1) Destructuring is a thing certain macros do, such as let |
| 14:11 | TimMc | 2) evaluation is done on code, not data |
| 14:12 | jayunit100 | i guess 1) explains why this fails : |
| 14:12 | jayunit100 | ,([[head & tail] [1 2 3 4]]) |
| 14:12 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: head in this context, compiling:(NO_SOURCE_PATH:0)> |
| 14:12 | Bronsa | .(let [[head & tail] [1 2 3 4]] [head tail]) |
| 14:12 | mega` | , (let [[h & t] (range 1 5)] (inc h)) |
| 14:12 | clojurebot | 2 |
| 14:13 | xeqi | ,((fn [h & t] [h t]) [1 2 3 4]) |
| 14:13 | clojurebot | [[1 2 3 4] nil] |
| 14:13 | xeqi | heh |
| 14:13 | taapa | How does one decide on Hiccup or Enlive for web app? Each has its pros & cons. |
| 14:13 | andyfingerhut | Yep, other macros are loop for doseq defn fn defmacro if-let when-let. There might be others, but those are most common places I've seen destructuring used. |
| 14:14 | mega` | https://www.google.com/intl/en/chrome/multitask.html |
| 14:24 | TimMc | taapa: Hiccup doesn't html-encode strings by default, which is kind of terrible. |
| 14:24 | TimMc | taapa: On the other hand, enlive is tricky to learn. |
| 14:26 | taapa | TimMc: thanks these are new to me. I like Enlive way of separating concern, cleaner. But just to know why people prefer Hiccup such as being the default in Noir. |
| 14:26 | gfredericks | TimMc: would there be an easy way to change hiccup so that it did? |
| 14:26 | gfredericks | I guess you could box up strings that you wanted kept raw |
| 14:27 | yoklov | taapa: personal preference matters too. |
| 14:28 | yoklov | ah, nm didn't see your 2nd message |
| 14:28 | xeqi | taapa: I think the desire to be simple wins there |
| 14:28 | xeqi | so that it is faster to get going |
| 14:31 | hhutch | taapa: personally, I think enlive vs hiccup breaks down this way... |
| 14:31 | taapa | My guess is Hiccup is an DSL, thus appealing if you want Clojure to be domain language of all your problems. But I wonder how do you code in Hiccup if you have a web designer that is not progammer. |
| 14:31 | hhutch | dev teams that consist entirely of clojure devs, or clojure devs are entirely responsible for the HTML markup, want to use hiccup |
| 14:32 | hhutch | if you are working with web designers who can produce html/css though, enlive is a dream |
| 14:32 | taapa | hhutch: thanks |
| 14:33 | hhutch | taapa: also enfocus now exists (the clojurescript version of enlive) ... which changes the landscape as well |
| 14:33 | hhutch | from what i've seen though, most ppl that use enlive also use hiccup |
| 14:34 | taapa | enfaces? will take a look. |
| 14:34 | taapa | enfocus I mean |
| 14:34 | taapa | not a bad idea to combine both I guess |
| 14:35 | hhutch | http://ckirkendall.github.com/enfocus-site/ |
| 14:35 | gf3 | ibdknox: yt? |
| 14:36 | taapa | hhutch: thanks for the link. |
| 14:36 | hhutch | sure |
| 14:40 | yoklov | there's also crate which is clojurescript hiccup :p |
| 14:41 | taapa | hiccup vs enlive => enfocus vs crate :( |
| 14:42 | hhutch | taapa: do you know jquery ? |
| 14:42 | taapa | hhutch: no, mainly back end |
| 14:43 | hhutch | or, are you familiar with manipulating dom elements with css selectors? |
| 14:44 | hhutch | that's all that enlive is. Also, if you ever have a need to do things like scrape html documents, enlive is very useful |
| 14:46 | taapa | hhutch: guess i have to play with them a bit first. thanks for advice. |
| 15:21 | kjellski | Why is clooj showing only my input as output? |
| 15:24 | Frozenlo` | Is there a way to create a temporary file? One that is never written to disk? |
| 15:25 | kjellski | nvm… crashed after first start… now it works as expected... |
| 15:25 | mega` | Frozenlo: you on a unix system? |
| 15:26 | Frozenlo` | No.. |
| 15:26 | mk | Frozenlo`: you can write to a bytebuffer of some sort |
| 15:27 | mega` | Frozenlo: so windows? |
| 15:27 | Frozenlock | Yes, win7 |
| 15:27 | mk | Frozenlock: otherwise, java allows you to create a temporary file in the system's default temp path (but this writes to disk) |
| 15:28 | Frozenlock | mk: bytebuffer seems good, assuming I can apply the same functions as for ordinary files. |
| 15:28 | mega` | Frozenlock: why a file are you going to pass it to some other program? |
| 15:28 | mega` | Frozenlock: nm |
| 15:28 | Frozenlock | I want to use https://github.com/bonega/pacl to zip some data, but it requires a file as input |
| 15:29 | mk | Frozenlock: you won't be able to treat it as a file, but you can use bufferedoutputstream etc. on it |
| 15:30 | mk | Frozenlock: "Just extracts all files from something that can be coerced into an inputstream" |
| 15:31 | mk | Frozenlock: you might want to check if the output does something similar |
| 15:31 | Frozenlock | I'll read about streams, brb :) |
| 15:33 | mk | Frozenlock: they wrap each other |
| 15:45 | Frozenlock | Ok I'm lost. How does one send data to a stream? |
| 15:45 | mk | Frozenlock: what kind of data? |
| 15:45 | Frozenlock | A map in this case |
| 15:46 | mk | Frozenlock: depends. A stream is a stream - it's linear. How are you going to stuff a map into a stream? |
| 15:46 | Frozenlock | Or rather ultimately a string (once in a file) |
| 15:46 | mk | Frozenlock: any preference? if not, what are you plotting to do? |
| 15:46 | Frozenlock | Well like I said I want to zip it. |
| 15:47 | rlb | Frozenlock: if you just mean write it so you can read it back later, you can use (binding [*out* stream] (prn foo)). |
| 15:47 | mk | ok, so you have some arbitrary string, and you want to turn it into an "inputstream" that the library you linked to can read |
| 15:47 | Frozenlock | Exactly. |
| 15:48 | Frozenlock | Unless of course I'm doing extra steps for nothing and there's an easier way to achieve this goal... |
| 15:48 | mk | Frozenlock: http://stackoverflow.com/questions/782178/how-do-i-convert-a-string-to-an-inputstream-in-java#782183 |
| 15:50 | pedroteixeira | hello folks! in clojurescript, any tips when getting "namespace already declared"? |
| 15:51 | mk | pedroteixeira: I know nothing of this, but perhaps try to change your namespace declarations to new ones |
| 15:51 | pedroteixeira | mk: ok, thanks |
| 15:52 | mk | pedroteixeira: there are a few different functions which might do something to the namespace, so check if you're defining it with one, and then with another |
| 15:52 | rlb | Frozenlock: with-in-str? |
| 15:53 | rlb | ,(doc with-in-str) |
| 15:53 | clojurebot | "([s & body]); Evaluates body in a context in which *in* is bound to a fresh StringReader initialized with the string s." |
| 15:53 | mk | pedroteixeira: I'm not sure how cljs implements namespaces, but another issue might be that your namespace conflicts with something js already uses, like document.Math |
| 15:53 | rlb | ,(with-in-str "drinkme" (read-line)) |
| 15:53 | clojurebot | "drinkme" |
| 15:54 | eiro | hello |
| 15:54 | mk | eiro: hey, welcome |
| 15:54 | eiro | thanks |
| 15:54 | rlb | or |
| 15:54 | rlb | ,(with-in-str "{:a 5}" (read)) |
| 15:55 | clojurebot | {:a 5} |
| 15:55 | Frozenlock | mk: Unable to resolve classname: ByteArrayInputStream :( |
| 15:55 | mk | Frozenlock: it's in the package java.io - import the package, or qualify the name :) |
| 15:57 | rlb | Frozenlock: if you're just trying to *write* the map, then is prn not good enough? |
| 15:57 | Frozenlock | Oh yes, it worked. Now the moment of truth ^^ |
| 15:57 | Frozenlock | rlb: I really don't know... I will check what it does |
| 15:57 | mk | rlb: it needs to become an inputstream so that it can be passed to a library |
| 15:58 | rlb | mk: to a zip library? |
| 15:58 | Frozenlock | rlb: yes |
| 15:58 | mk | rlb: yep - I think it was linked above |
| 15:59 | Frozenlock | https://github.com/bonega/pacl |
| 16:00 | rlb | mk: right, I just misunderstood. |
| 16:01 | Frozenlock | Grrr... No method in multimethod 'compress' for dispatch value: class java.io.ByteArrayInputStream |
| 16:01 | mk | I think it might be possible to bind "string" to *in* and then pass *in* into the library? |
| 16:01 | Frozenlock | From the source: defmethod compress clojure.lang.IPersistentCollection |
| 16:02 | mk | Frozenlock: weird. Pass ["this is a dumb way to do it"] to the function |
| 16:03 | Frozenlock | That's for me or the library? :p |
| 16:03 | mega | is it ON? |
| 16:03 | mk | Frozenlock: for the library, and because we don't know how to use the library yet :) |
| 16:03 | rlb | if you don't mind everything being in RAM, you can prn to a string, then create a reader (*in*) from the string via with-in-str, but I don't know if that creates a reader that the zip lib will accept. |
| 16:03 | mk | in the end that might be a bad idea but it's worth testing |
| 16:04 | mk | I guess it's trying to serialize a collection? |
| 16:04 | rlb | Of course if you want to stream to the zlib lib, that'll take a bit more work. |
| 16:05 | Frozenlock | -> [Thrown class java.lang.NullPointerException] |
| 16:06 | Frozenlock | Meh, I might be better off trying to find something else to compress. Surely I'm not the first wanting to compress data? |
| 16:06 | mk | Frozenlock: hmm. Maybe there's a better way - do you just want to zip a string into a file? Do you need to get it out later? |
| 16:07 | pedroteixeira | mk: just to let others know, upgrading to clojurescript tag r1006 fixed it |
| 16:07 | Frozenlock | Yes, but on another machine- so for now I really just need to compress it and dump it somewhere. |
| 16:08 | mk | pedroteixeira: thanks - glad you solved it |
| 16:09 | mk | will it be easier to leave it uncompressed than it will be to solve the compression issue? |
| 16:11 | Frozenlock | Sure, it would be easier.. but I don't want "easier", I want "fully working" :p |
| 16:11 | Frozenlock | And as a last resort I can print to file and then compress. However I don't like the idea of this extra file on the disk. |
| 16:12 | mk | Frozenlock: http://docs.oracle.com/javase/6/docs/api/java/util/zip/ZipOutputStream.html |
| 16:13 | mk | Frozenlock: you could also search for 'using zipoutputstream' or somesuch |
| 16:18 | Frozenlock | http://tripoverit.blogspot.ca/2008/04/java-create-zip-file-in-memory.html This looks promising |
| 16:19 | Frozenlock | And this too :D http://clojure-log.n01se.net/date/2011-05-23.html |
| 16:19 | Frozenlock | Thank god for IRC logs. |
| 16:21 | rlb | Frozenlock: something like this: |
| 16:21 | rlb | ? |
| 16:21 | rlb | (with-file [zip (java.util.zip.ZipOutputStream. |
| 16:21 | rlb | (clojure.java.io/output-stream "foo.zip"))] |
| 16:21 | rlb | (binding [*out* zip] |
| 16:21 | rlb | (prn some-map))) |
| 16:21 | rlb | s/with-file/with-open/ |
| 16:21 | mk | maybe some day someone searching will see the links you posted now. zip zipping compressing how to compress file string |
| 16:23 | Frozenlock | rlb: trying now! |
| 16:24 | rlb | Oh, and I didn't test that at all (obviously) -- I just guessed... |
| 16:25 | Frozenlock | => ZIP file must have at least one entry. The solution is near :) |
| 16:25 | Frozenlock | Give me some time, I want to try to figure this one out. |
| 16:28 | rlb | Frozenlock: certainly |
| 16:34 | autodidakto | Anyone have any thoughts about the Expectations unit testing framework? (http://blog.jayfields.com/2011/11/clojure-expectations-introduction.html) |
| 16:39 | Frozenlock | (with-open [zip (java.util.zip.ZipOutputStream. |
| 16:39 | Frozenlock | (clojure.java.io/output-stream "foo.zip"))] |
| 16:39 | Frozenlock | (-> zip (.putNextEntry (java.util.zip.ZipEntry. "foo.txt"))) |
| 16:39 | Frozenlock | (binding [*out* zip] |
| 16:39 | Frozenlock | (prn tt))) |
| 16:39 | Frozenlock | => java.util.zip.ZipOutputStream cannot be cast to java.io.Writer |
| 16:39 | Frozenlock | What did I miss? |
| 16:40 | rlb | Frozenlock: oh, wait -- this is a *zipfile* class (i.e. zip/unzip) -- I was thinking about gzip... |
| 16:40 | rlb | ? |
| 16:40 | rlb | s/this is/is this/ |
| 16:40 | mk | Frozenlock: you have to construct a Writer, with zipoutputstream as a parameter |
| 16:40 | rlb | i.e. zip is file based, gzip is stream based. |
| 16:40 | mk | Frozenlock: PrintWriter, for example |
| 16:41 | rlb | Oh, that -- right -- will (writer ...) handle it? |
| 16:41 | rlb | i.e. (java.io/writer (...)) |
| 16:41 | Frozenlock | rlb: yes, it's a zip, not a gzip compression |
| 16:41 | rlb | as a wrapper |
| 16:42 | rlb | But that will only work if the zipoutputstream is actually a normal output stream -- and I don't actaully know that (haven't looked). |
| 16:42 | mk | rlb: what do you mean by normal? |
| 16:43 | rlb | mk: just meant something that clojure.java.io/writer can handle. |
| 16:43 | rlb | ,(doc clojure.java.io/writer) |
| 16:43 | clojurebot | "([x & opts]); Attempts to coerce its argument into an open java.io.Writer. Default implementations always return a java.io.BufferedWriter. Default implementations are provided for Writer, BufferedWriter, OutputStream, File, URI, URL, Socket, and String. If the argument is a String, it tries to resolve it first as a URI, then as a local file name. URIs with a 'file' protocol are converted to local... |
| 16:44 | mk | Frozenlock: create a PrintWriter(zipstream), and use its .append() or print or println methods to write your string |
| 16:45 | rlb | Frozenlock: do you really need a zip file (as opposed to a gzip file)? |
| 16:45 | rlb | If not: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/zip/GZIPOutputStream.html |
| 16:46 | rlb | Which I would assume behaves more like a normal stream. |
| 16:46 | Frozenlock | rlb: yes. However I will keep this for future references, thanks ^^ |
| 16:46 | mk | rlb: writer might work, since it seems to wrap outputstreams |
| 16:46 | Raynes | Frozenlock: https://github.com/Raynes/fs/blob/master/src/fs/compression.clj#L10 |
| 16:46 | mk | rlb: streams are just sequences of bytes (or characters, etc) |
| 16:48 | rlb | mk: I know -- I just meant that I hadn't checked to see if zipoutputstream was a normal stream (i.e. was actually subclassed from outputstream). It is. |
| 16:48 | mk | rlb: they can be fed into the disk, or into the network, or into a byte array. From that perspective, gzip and zip are identical |
| 16:49 | rlb | And the reason I had started to wonder was because zip is an archive format, rather than just a compresion format. |
| 16:49 | mk | rlb: it's usually very safe to assume that it is - I've never seen a class ending in OutputStream that didn't extend/implement the right things |
| 16:49 | rlb | But they've obviously implemented the class as a normal outputstream. |
| 16:49 | rlb | mk: right, but since I wasn't sure, I wondered. |
| 16:50 | mk | rlb: sure, but you can implement outputstreams for archives that aren't compressed - streams are very flexible :) |
| 16:50 | mk | for example, you can create various CryptoOutputStreams with parameters, and they'll encrypt according to your public key or what have you |
| 16:51 | rlb | I know -- I just wasn't *certain* about that class until I actually looked at that particular class's docs. |
| 16:51 | mk | you can also attach HashOutputStreams (or Input) and feed data through them, and they'll tell you the MD5 or SHA1 of the bytes |
| 16:52 | mk | rlb: yep :) don't mind me, I'm just being overinformative |
| 16:52 | Frozenlock | Raynes: thanks, but I want to zip on-the-fly, without a prior file on the disk. |
| 16:52 | Raynes | Frozenlock: Oh, I thought you wanted to extract a zip file. |
| 16:53 | Raynes | Frozenlock: If you write something for that, please contribute it to fs. |
| 16:53 | rlb | mk: didn't know about the hash*streams. |
| 16:53 | mk | Raynes: String -> new zip file on disk |
| 16:54 | Frozenlock | Raynes: it's more like mk and rlb are writting it and I watch helplessly :P |
| 17:00 | Frozenlock | Almost! The zip-file is there, an the foo.txt inside it. However the .txt is empty |
| 17:00 | Frozenlock | (with-open [zip (java.util.zip.ZipOutputStream. |
| 17:00 | Frozenlock | (clojure.java.io/output-stream "foo.zip"))] |
| 17:00 | Frozenlock | (-> zip (.putNextEntry (java.util.zip.ZipEntry. "foo.txt"))) |
| 17:00 | Frozenlock | (.append (java.io.PrintWriter. zip true) "This is a string")) |
| 17:00 | Frozenlock | ... |
| 17:00 | Frozenlock | I'll find a paste site |
| 17:03 | Frozenlock | https://gist.github.com/2278682 |
| 17:10 | mk | Frozenlock: hmm, try using println instead of .append? |
| 17:11 | rads | has anyone tried using node.js with the latest version of lein-cljsbuid? |
| 17:11 | Frozenlock | I tried .write, .append, .print... |
| 17:12 | Frozenlock | Of course... it works with println! |
| 17:12 | rads | I'm getting an error with clojurescript r1006 with any node.js compilation I try |
| 17:12 | Frozenlock | :D |
| 17:12 | Frozenlock | But why? |
| 17:13 | mk | Frozenlock: I don't actually know, unfortunately - random guess |
| 17:13 | mega` | rads: compiler error? |
| 17:13 | rlb | Frozenlock: you're probably not closing the stream -- i.e. println has a newline which is forcing the flush. |
| 17:13 | rads | mega`: yeah. I think it might have been fixed here: https://github.com/clojure/clojurescript/commit/7472ab9013ad5d2b3468daabe20ba3479546f287 |
| 17:14 | rads | the error I'm getting comes from dependency-order-visit |
| 17:14 | rlb | Frozenlock: you could probably also just flush the stream manually, but closing everything properly should handle it. |
| 17:14 | mk | with-open doesn't auto-close? |
| 17:14 | rads | java.lang.String cannot be cast to clojure.lang.Associative |
| 17:14 | mk | closing a stream will flush it, and close (and flush) any sub-streams |
| 17:15 | rads | mega`: it happens even with a blank file with just an (ns) declaration |
| 17:18 | mega` | rads: 1.2.3? |
| 17:18 | mega` | rads: 0.1.5 ? |
| 17:18 | rads | yeah |
| 17:18 | rads | node.js compilation breaks from 0.1.2 on |
| 17:19 | rads | there was another clojurescript error in the version before r1006 too |
| 17:20 | rads | so I've been using 0.1.1 for now |
| 17:20 | rads | when I use that version my code compiles and runs just fine |
| 17:21 | mega` | rads: ill test it out brb |
| 17:25 | rads | just in case this didn't send since I got disconnected: mega`: awesome! thanks. I would test it out with r1006 myself, but I don't know much about adding my own development versions of dependencies with leiningen |
| 17:25 | yoklov | anyone want to checkout a neat clojurescript page i made? http://thomcc.github.com/hex/ |
| 17:26 | mk | yoklov: pretty |
| 17:27 | yoklov | haha, thanks |
| 17:27 | dnolen | yoklov: nice! |
| 17:28 | dnolen | yoklov: so you've done a CLJ and a CLJS app now :) |
| 17:28 | yoklov | haha, yup |
| 17:28 | yoklov | i've done other clj stuff but nothing that interesting (and even more stuff that never got completed) |
| 17:29 | dnolen | yoklov: well I liked dunjeon! |
| 17:29 | yoklov | dnolen: dunjeon was a lot of fun to make |
| 17:29 | mk | it runs somewhat slowly if you do randomize |
| 17:29 | yoklov | yeah |
| 17:29 | yoklov | mk: the more cells on the board, the slower it runs :/ |
| 17:30 | yoklov | i use `frequencies` and sets, which… take their toll. |
| 17:31 | mk | do you precompute the next round? because if you do a timeout, and then compute, perhaps you should compute, and then timeout |
| 17:31 | yoklov | the upshot of the way i do it now is it would be trivial to change to support an infinite grid if there were a faster hashmap implementation |
| 17:31 | yoklov | hm, i hadn't thought of reordering that |
| 17:31 | dnolen | yoklov: it's nice and I imagine it will only get faster w/ time. |
| 17:32 | mk | yoklov: what do the alive and dead mean? |
| 17:33 | yoklov | mk: they're the rules, if a cell has one of the yellow numbers in `alive` neighbors and is active, it will be alive in the next round, if it has one of the numbers in `dead` and is dead, it will come to life the next round |
| 17:33 | yoklov | if that makes any sense |
| 17:34 | yoklov | dnolen: yup, that was my thinking too; |
| 17:35 | alexbaranosky | when does Clojure wrap thrown exceptions in Runtime exceptions? |
| 17:37 | yoklov | mk: no dice, still crawls after doing randomize if i reorder those |
| 17:37 | mk | so alive applies to alive cells, and is a sort of "must be these to keep alive", and dead applies to dead, and means "this many to come alive" |
| 17:37 | yoklov | yup. |
| 17:37 | yoklov | actually i think it's faster in general if i do reorder them. |
| 17:37 | mk | yoklov: you shorten the timeout based on how long the computation took, yeah? |
| 17:38 | yoklov | no. i just do a timeout every 200ms |
| 17:38 | mk | yoklov: gotcha - initially I thought that alive meant what it took to come alive, and dead meant what it took to kill ;) |
| 17:39 | yoklov | yeah, i couldn't really think of any way to describe that in only a couple words |
| 17:39 | mk | yoklov: check system time before and after the calculation. So, start timer, display, calculate next round, stop timer, subtract now from start, subtract that from 200, timeout |
| 17:39 | yoklov | right no i'm familiar |
| 17:40 | yoklov | you think it's really worth it though? it will still chug when it gets to the point that a computation takes more than 200ms |
| 17:41 | mk | yoklov: sure, why not? how long do the rounds take? |
| 17:42 | yoklov | after random? i just timed one which took nearly a second :/ |
| 17:42 | amalloy | alexbaranosky: only on 1.3 - that change is reverted in 1.4 |
| 17:43 | yoklov | (according to chrome dev console timelines) |
| 17:43 | mk | this hex pattern is rather pretty, and all of the combinations of alive/dead seem to produce very nice results - I'm trying nil/dead:1 now, and just starting with a dot |
| 17:44 | alexbaranosky | amalloy, thanks |
| 17:45 | yoklov | mk: that one looks very cool. |
| 17:47 | yoklov | mk: the way i do it now hteres no chance of it skipping frames, if i did it the other way i think it would skip frames but keep a more consistent tick rate |
| 17:47 | mk | yoklov: you could also pretend that each cell is 3 units... and then have 8 states in each cell to check (or each cell 7, with 2^7 states) |
| 17:48 | yoklov | well |
| 17:48 | yoklov | the way i could get the biggest benefit is by just using a 2d array for the cells |
| 17:48 | mk | ...that might actually be easier than it seems, since perhaps clojure could just calculate all those state values for you |
| 17:49 | mk | yoklov: nah, I think you're right to avoid the 2d array, they're boring :) |
| 17:49 | yoklov | they are |
| 17:50 | yoklov | but if i do it your way each cell would have 3 atoms in it? |
| 17:50 | yoklov | or hm |
| 17:56 | mk | do we have the ability to stuff clojurescript into a <script> tag, and have it run? |
| 18:02 | gfredericks | mk: how would that work? send the cljs up to a compiler-service after it gets loaded in the browser? |
| 18:03 | yoklov | mk: no, the clojurescript compiler is written in clojure, and not clojurescript |
| 18:04 | mk | but... clojurescript is clojure... |
| 18:04 | gfredericks | people should stop saying that |
| 18:04 | mk | so the compiler is written in clojurescript? |
| 18:04 | yoklov | no, it's written in clojure. |
| 18:04 | yoklov | if it were in clojurescript it could bootstrap itself. |
| 18:04 | yoklov | and you could use clojurescript in a script tag. |
| 18:05 | gtrak`` | mk, you can't have macros without eval, clojurescript doesn't have either |
| 18:05 | mk | yoklov: yes, exactly - like with coffeescript :) |
| 18:05 | mk | how much work would need to be done for a js compiler? |
| 18:09 | yoklov | writing it in cljs is not really a goal for performance reasons (you'd need eval, i think, which can't happen if you do closure compiling) |
| 18:10 | yoklov | and writing in js? meh. no clue, sounds _extremely_ hard |
| 18:11 | gfredericks | it can't be impossible to do it in cljs |
| 18:11 | gfredericks | compiling is just a function and cljs is turing complete...am I missing something? |
| 18:11 | gfredericks | is it just much messier? |
| 18:12 | yoklov | well, just because something is turing complete doesn't mean it can do that. |
| 18:12 | yoklov | htere are plenty of undecidable problems |
| 18:12 | yoklov | but |
| 18:12 | gtrak`` | it's not impossible? clojurescript was meant to be a step forward for clojure-in-clojure, you'd need a full clojure-in-clojure to do it |
| 18:13 | yoklov | i have no idea. i think the issue is that it would suck more to do. |
| 18:13 | mk | yoklov: the set of undecidable problems for any two given turing complete things are identical |
| 18:13 | mk | yes, it would suck more |
| 18:13 | yoklov | also it would require rewriting the compiler into cljs |
| 18:13 | mk | is the compiler written in java? |
| 18:14 | yoklov | clojure! |
| 18:14 | yoklov | jvm clojure |
| 18:14 | mk | oh, well then that should convert right over to cljs... |
| 18:15 | Frozenlock | mk: I'm trying to put what I've learn earlier into a function taking optional argument (many files to zip), but I think I might have messed up with the recur. Would you mind to take a quick look? https://gist.github.com/2279100 |
| 18:15 | Frozenlock | The function works if I remove the (when.... (drop 2 remain)) part and use it for a single file to zip. |
| 18:16 | amalloy | i think you want [name cont remain], not [name cont & remain] |
| 18:17 | yoklov | mk: the languages aren't the same :/. they're very close, but certainly not identical. Also, if the cljs compiler were written in cljs, compilation would be slower than it already is |
| 18:18 | Frozenlock | Wouldn't it be nil either way? (If I don't give other filename that is..) |
| 18:19 | mk | yoklov: yeah, I don't know too much about cljs. Compilation of a few lines shouldn't be too bad though |
| 18:20 | yoklov | well you'd lose macros, is a proble |
| 18:20 | Frozenlock | amalloy: you were right... thanks :) |
| 18:21 | mk | yoklov: that might be alright, as a start |
| 18:21 | yoklov | eh, i'd rather have macros than cljs-in-cljs |
| 18:22 | yoklov | though maybe you could work around that, idk. |
| 18:22 | yoklov | really i'd rather the compiler worked faster. even in its current state it's frustruating. |
| 18:22 | Frozenlock | Now I just need to find how to do the inverse... unzip on-the-fly without a file on disk. |
| 18:22 | mk | Frozenlock: I'd guess zipinputstream |
| 18:23 | Frozenlock | Indeed |
| 18:26 | rads | mega`: I tested my code with clojurescript r1006, and it seems to compile fine, so there must be something with lein-cljsbuild that breaks node.js compilation |
| 18:30 | mega` | rads: what did your test include? |
| 18:39 | muhoo | i'm complietely baffled by this ppassage in hex: https://refheap.com/paste/1634 |
| 18:39 | Zoka | cemerick: CCW [0.7.0] beta looks great, no more printlns for me :) |
| 18:39 | cemerick | Zoka: :-) |
| 18:40 | cemerick | Is that what you're planning on using from here on out? |
| 18:40 | muhoo | it seems like it's calling a vector with something as an arg |
| 18:41 | muhoo | ah, vectors ara callbale, got it. nm |
| 18:41 | muhoo | callable even |
| 18:41 | Zoka | cemerick: Yes, I could not use it before due to the nREPL conflict between ringMon and CCW |
| 18:42 | cemerick | ah, right |
| 18:42 | cemerick | that shouldn't change much at all from here on out |
| 18:43 | cemerick | the easy stacking of HTTP on top has made me far more comfortable with the architecture, etc. |
| 18:43 | yoklov | muhoo: yeah |
| 18:43 | cemerick | 0.2.0 is still beta, so there's lots of little details to nail down, but it seems quite solid |
| 18:43 | yoklov | that code… its a little bit hacky at poitns |
| 18:44 | Zoka | I did not have any problems so far |
| 18:44 | yoklov | (i'm happy people are looking at it though :) |
| 18:45 | Zoka | I am really glad that CCW is in good shape since Emacs is not my cup of tea :) |
| 18:45 | muhoo | it's very cool. and it's only like 150 lines of cljs loks like |
| 18:45 | cemerick | Insofar as everyone using lein2 is using nREPL, it's gotten quite a beating from a testing perspective. |
| 18:47 | Zoka | Meanwhile, they should try lein2 webrepl, that works fine. :) |
| 18:48 | muhoo | webrepl? isnt' that himera? |
| 18:48 | Zoka | No, Himera is for ClojureScript |
| 18:49 | Zoka | This is similar, but for Clojure proper |
| 18:49 | mk | in ccw, I had trouble with it not using 1.3, and I didn't like that it opened a new repl view each time, rather than having one view with numerous repls hooked into debug and console... |
| 18:50 | yoklov | muhoo: haha, yup, I usually try to be concise in my code. |
| 18:50 | yoklov | emacs 4 life! |
| 18:51 | Zoka | mk: Now lets you use whatever is in your project.clj, but you have to do m2e import of pom.xml generated by 'lein pom' |
| 18:51 | Zoka | mk: lein2 native support is comming shortly |
| 18:52 | cemerick | mk: numerous REPLs in one view? Is there another tool that works like that? |
| 18:52 | mk | Zoka: sounds excellent |
| 18:52 | mk | cemerick: the console and debug views do this (not sure about other tools...) |
| 18:53 | cemerick | oh, in Eclipse you mean |
| 18:53 | Zoka | cemirck: one man's feature is another man's bug |
| 18:53 | cemerick | Yeah, I quite dislike how the Console view in Eclipse works. |
| 18:54 | mk | cemerick: yes. It would mean that I always had to move the view to the right place whenever a new one started |
| 18:54 | muhoo | yoklov: it's very cool. though i had to do stuff like this in order to attempt to get my feeble brain around it: https://refheap.com/paste/1635 |
| 18:54 | mk | cemerick: what's the problem with it? that you can't pull them apart? |
| 18:54 | cemerick | mk: they always start in the same region as where you put the last one |
| 18:55 | cemerick | I've always found the sub-view design very confusing |
| 18:55 | mk | cemerick: when I closed mine, it seemed to pick an arbitrary new position, perhaps beside console |
| 18:55 | Zoka | cemerick: you can open more than one REPL tab in CCW to the same process? |
| 18:55 | mk | cemerick: why is that? |
| 18:56 | cemerick | Zoka: sure, just connect to the same port |
| 18:56 | cemerick | I suppose a button in the REPLView to do that would be good |
| 18:58 | Zoka | cemerick: that is feature I like, since you can run some slow thing in one tab, while dion normal stuff in another. |
| 18:58 | Zoka | s /dion/doing/ |
| 18:59 | Zoka | cemerick: do you remember how to switch editor in structural mode in CCW? |
| 19:00 | mk | are haskell typeclasses essentially clojure protocols? |
| 19:03 | yoklov | haskells typeclasses can also dispatch on returntype |
| 19:03 | mk | yoklov: dispatch? returntype? |
| 19:03 | amalloy | mk: "use implementation X if the caller expects an Integer, and implementation Y if they expect a String" |
| 19:04 | yoklov | err, so they're polymorphic on the function's returntype, whereas protocols are only polymorphic on the function itself |
| 19:04 | mk | ah, I see. Yes, that's right - thanks |
| 19:05 | amalloy | $heval read "5" :: Int |
| 19:05 | lazybot | ⇒ 5 |
| 19:05 | yoklov | so you can use `read` where something expects an integer, and it's the same as Integer/parseInt |
| 19:05 | yoklov | yeah. |
| 19:05 | yoklov | had no clue lazybot was that talented. |
| 19:06 | amalloy | there's another haskell bot in here somewhere |
| 19:06 | amalloy | > 5 |
| 19:06 | amalloy | except i can't remember how to trigger him |
| 19:06 | gfredericks | amalloy: have you tried a monad? |
| 19:07 | amalloy | maybe |
| 19:08 | gfredericks | ~rimshot |
| 19:08 | clojurebot | Badum, *tish* |
| 19:09 | mk | I decided to learn about monads a couple of days ago, and ended up having to learn a bunch of haskell... |
| 19:10 | mk | I think I'm at the point where I'm close to understanding what a monad is |
| 19:11 | yoklov | it's been a while since i did anything with them, so i might be defining this too narrowly, but iirc its just a type which helps you thread a value through some computation |
| 19:13 | mk | yoklov: that's part of it, I think, but there's also the IO part, and other things |
| 19:13 | yoklov | IO is still computation. |
| 19:13 | yoklov | though you could be right i don't recall. I remember reading about the list monad in haskell was what made them click for me. |
| 19:13 | mk | yoklov: what value do you thread through it? |
| 19:14 | yoklov | oh |
| 19:14 | yoklov | the value representing the state of the world |
| 19:14 | yoklov | brb |
| 19:14 | mk | yoklov: I've had several things click, but I don't think I get monads yet |
| 19:16 | mk | ah, right. Yeah, and haskell is affecting or acting on the state. I've read a post that was suggesting that this was the wrong way to think of it, that IO basically left a bunch of unfinished computations that were waiting for main (or something like that) |
| 19:26 | yoklov | maybe, but thats might be just because haskell has laziness to worry about |
| 19:27 | yoklov | in terms of thinking of monads in general i don't think that's a bad way to think about the specific case of IO |
| 19:27 | yoklov | i could be wrong though. |
| 19:28 | mk | the world-state idea is still a bit confusing for me, since IO gains type String, for example |
| 19:30 | yoklov | yeah, you're probably better off asking #haskell. |
| 19:30 | yoklov | err, not with a period. |
| 19:31 | jimduey_ | If you're interested in monads in clojure, may I humbly suggest http://clojure.net. |
| 19:31 | yoklov | or maybe someone else here can help |
| 19:32 | gfredericks | jimduey_: that's quite a domain name there |
| 19:32 | jimduey_ | Yeah, I picked it up in the very early days of Clojure. |
| 19:34 | mk | yoklov: I tend to ask there when I get stuck. I did the whole "hey guys, what's a monad" thing a couple days ago, and it went from "it's just an interface" and "when you figure out what they are, you'll think 'is that all??' " to "you need to either learn haskell, or category theory in order to understand monads" over the course of a number of minutes |
| 19:35 | jimduey_ | That middle comment could very well be from me. :) |
| 19:36 | brehaut | IMO the best way to learn what a monad is is to spend time reading the code, performing reductions by hand, and writing implementations of your own |
| 19:36 | mk | jimduey_: thanks for the link - I'll read through the monads-in-clojure page |
| 19:37 | jimduey_ | mk: feel free to shoot me any questions you might have. |
| 19:37 | mk | brehaut: yeah, but that's also the slowest way, and requires you to be proficient in a monady language haskell |
| 19:37 | brehaut | mk: it does not |
| 19:38 | brehaut | i learn monads by writing implementations in javascript and python |
| 19:38 | brehaut | s/learn/learnt/ |
| 19:38 | mk | jimduey_: thanks |
| 19:39 | mk | brehaut: any examples that were particularly enlightening? (I know js but not python) |
| 19:39 | brehaut | mk: id start of trying to write an identity monad, and then a maybe |
| 19:40 | mk | brehaut: I think I've done both, though I'm unsure if they meet the various criteria and functions associated with monads |
| 19:44 | yoklov | mk: if they say you need to understand cat. theory or haskell they're wrong |
| 19:46 | brehaut | mk https://refheap.com/paste/1640 |
| 19:46 | brehaut | rough around the edges, but IdentityM and MaybeM in JS |
| 19:46 | mk | yoklov: I figured, but I don't know if the thing that will make people grok monads exists |
| 19:47 | brehaut | the thing to make you grok monads is to put in the work to grok monads |
| 19:48 | mk | brehaut: definitely - but definitions of "work" vary, from "learn haskell or category theory" to "just think of it as an interface in java" |
| 19:49 | brehaut | learning category theory is about as far away from learning monads for function programming as you can get :P |
| 19:50 | brehaut | and re haskell: any language with closures is a suitable enviroment for learning about monadic constructions |
| 19:50 | brehaut | haskells syntax just happens to make it much less painful to write large pieces of monadic code |
| 19:52 | mk | brehaut: introduce corresponds to "return", I take it |
| 19:52 | brehaut | yes |
| 19:52 | mk | I'm still hazy on the equivalence of bind with fmap and join |
| 19:53 | brehaut | for two reasons: a) return is a reserved word b) i think introduce is slightly clearer name for it when you are learning: it introduces a value into the monadic context |
| 19:53 | justin1 | what's the easiest way to sort a map a custom order of its keys? ie I have a map {:a 1 :b 2 :c 3} and I want to get a sorted map ordered {:b :c :a}? |
| 19:53 | brehaut | (ie, theres less semantic overloading with what most programmers think return does) |
| 19:55 | jimduey_ | justin1: Depends on what you want. If you want a sequence of the key value pairs from a map once, use a variant of 'sort'. |
| 19:55 | jimduey_ | If you want an actual map that will always return the values in a sorted order, use a sorted map. |
| 19:55 | jimduey_ | You can specify the comparator to sort with in both instances. |
| 19:56 | mk | justin1: what jimduey_ said, and have a look at sorted-map-by. You might also find http://clojure.org/cheatsheet useful |
| 19:56 | jimduey_ | brehaut: Nothing turns the light on for monads like actually working with them at the REPL. |
| 19:56 | brehaut | jimduey_: absolutely |
| 19:57 | justin1 | thanks guys, I'm just wondering if there's a quick way to build make a comparator to return a specific, arbitrary order based on the keys |
| 19:57 | mk | jimduey_: "A monadic function is a function that accepts a value and returns a monadic value" - can the value be itself a monadic value, and does a monadic function count as a monadic value? |
| 19:57 | brehaut | jimduey_: although for state-m i found a simple example and then did all the reductions by hand on paper |
| 19:57 | jimduey_ | And implementing a couple is a great exercise if you have the patience. |
| 19:58 | mk | jimduey_: by the value, I mean the value that is accepted |
| 19:59 | jimduey_ | mk: The value passed in can be any value, even a monadic value. But in that case, it's treated like any other value. Nothing special happens just because it's a monadic value. |
| 19:59 | jimduey_ | And a monadic function does not count as a monadic value. |
| 20:00 | jimduey_ | Though in some monads, monadic values are functions. They are different than monadic functions in those monads. Which is where some of the confusion comes in. |
| 20:00 | jimduey_ | I try to untangle that in some later posts. |
| 20:00 | mk | jimduey_: I take it that this is because it is unwrapped before being given to the Monad-wrapped function (my thoughts are burrito-explanation flavoured here) |
| 20:02 | jimduey_ | If I get your question correctly, the answer is no. Any value passed to a monadic function is just used as is, there is no unwrapping. But the function returns a monadic value. |
| 20:05 | mk | supposing that 1,[1] -> [2] (this is just addition within a monad), what sort of function will allow [1][1]->[2]? |
| 20:05 | brehaut | well bind only takes a unary function, so you need to partial your addition |
| 20:05 | brehaut | and then wrap it up in a return |
| 20:06 | brehaut | so that it returns a monadic value |
| 20:06 | jimduey_ | Yeah, a monadic function by definition only accepts a single parameter. |
| 20:06 | brehaut | that operation of taking a non monadic function and making it return a monadic value is called lifting |
| 20:09 | brehaut | mk, i mucked up my bind definitions above |
| 20:09 | mk | how far above? |
| 20:10 | brehaut | mk in the refheap paste |
| 20:10 | brehaut | mk, bind: function (f) { return (this.v !== null) ? f(this.v) : new MaybeM(null); } |
| 20:11 | brehaut | mk: and usage would be new MaybeM(1).bind(function (v) { return new MaybeM(v + 1); }).v |
| 20:11 | mk | you removed the monad wrapper around the returned value? |
| 20:11 | brehaut | thats correct |
| 20:11 | mk | are you sure that's right? |
| 20:12 | brehaut | yes |
| 20:12 | mk | but then bind doesn't return a monadic value |
| 20:12 | brehaut | exactly |
| 20:12 | brehaut | well |
| 20:12 | brehaut | sort of |
| 20:12 | brehaut | it does because the function passed to it does |
| 20:14 | mk | yes I see |
| 20:14 | brehaut | the type of the function bind takes is a -> m a |
| 20:16 | mk | one of the confusing things about monads is how bind can be seen either as taking a monadic value and a monadic function, returning a monadic value; or as taking a monadic value, and returning a function with a closure that takes functions and spits out the prior-mentioned result value |
| 20:17 | jimduey_ | yeah, I can see how that's confusing when you first see monads. I typically only focus on the 1st perspective. |
| 20:24 | gfredericks | ,(prn (keyword "foo (System/exit)")) |
| 20:24 | clojurebot | :foo (System/exit) |
| 21:00 | Frozenlock | Is there a way to put a default file name in (choose-file) in the seesaw library? |
| 21:08 | jasox | Need help people, can not configure slime to work with emacs24. Please can someone tell me what is easiest way to configure slime with emacs. If someone have links for useful dot files. ANYTHON !! Thanks |
| 21:09 | bpr | does ring.middleware.wrap-file follow symlinks? |
| 21:09 | mega` | jasox: w8 for link |
| 21:10 | Raynes | w8? wait? |
| 21:10 | mega` | Raynes: yea dont play games much? :D |
| 21:10 | Raynes | Please don't do that unless you're typing on a keyboard in klingon and you don't know how to spell 'wait' on it. |
| 21:11 | mega` | jasox: http://marmalade-repo.org/packages/starter-kit |
| 21:11 | autodidakto | Raynes: omglol |
| 21:11 | Raynes | rofl |
| 21:11 | autodidakto | Raynes: you're complaing about w8? srsly? |
| 21:11 | Raynes | yarly |
| 21:11 | weavejester | bpr: The easiest way is to check it out, I think. It should do… because it just uses the normal Java I/O libraries. |
| 21:11 | mega` | Raynes: where in a chat this is absolutly the playes for w8, brb, etc .... |
| 21:12 | jasox | Yeah I instelled it. But can not configure it. What should I add in .emacs |
| 21:12 | jasox | Official tutorial is not working for me :/ |
| 21:12 | Raynes | Yikes. |
| 21:12 | weavejester | mega`: I'm trying to decide if you're doing an april-fools :) |
| 21:12 | Raynes | Yeah, I'm thinking he is. At least, I'll sleep better tonight if I think that. |
| 21:13 | mega` | jasox: create a .emacs.d directory |
| 21:13 | mega` | jasox: and make init.el file |
| 21:13 | mega` | jasox: o w8 i think 24 alreddy has package.el |
| 21:13 | bpr | weavejester: It looks like it doesn't. |
| 21:13 | jasox | and ? |
| 21:14 | autodidakto | weavejester, Raynes: stop being a h8ter |
| 21:14 | Raynes | kk |
| 21:14 | autodidakto | as mega said, he's absolutely the playa |
| 21:14 | jasox | mega`, it has |
| 21:14 | mega` | jasox: so M-x and package-list-packages |
| 21:15 | mega` | jasox: and C-s to search for clojure-mode |
| 21:15 | mega` | jasox: press x to select the package for instalation |
| 21:15 | jasox | k |
| 21:15 | mega` | jasox: i mean i to select it and x to install |
| 21:16 | mega` | jasox: get the test mode and clojurescript while your att it |
| 21:16 | jasox | "get the test mode and clojurescript while your att it" - don't get it |
| 21:17 | mega` | jasox: u can select multiple packages for install |
| 21:17 | jasox | k |
| 21:20 | mega` | jasox: when your done whit that you need to get the swank-clojure plugin for leiningen |
| 21:28 | jasox | mega`, ok what should I do then. |
| 21:29 | mega` | jasox: you have lein installed? |
| 21:29 | jasox | yes |
| 21:29 | mega` | jasox: and swank-clojure? |
| 21:30 | yoklov | how can i get a more, uh, useful string version (or print one out) of a structure in cljs? right now the best i've got in most cases is [object Object] |
| 21:30 | jasox | mega`, yes |
| 21:30 | mega` | jasox: then navigate to your project |
| 21:30 | mega` | jasox: and use M-x clojure-jack-in |
| 21:31 | jasox | WOW, finally. Thank you mega` |
| 21:32 | timvisher | hey kids |
| 21:32 | timvisher | can anyone point me to the rationale behind clojure's lack of support for currying? |
| 21:32 | amalloy | timvisher: varargs |
| 21:32 | mega` | timvisher: there the partial function |
| 21:33 | timvisher | mega`: completely aware of that. That's not really currying in the Haskell sense. |
| 21:33 | timvisher | amalloy: that's the rationale? as in JVM varargs? |
| 21:34 | amalloy | no, as in clojure varargs |
| 21:34 | amalloy | how do you curry the + function? it takes any number of args |
| 21:34 | timvisher | gotcha |
| 21:34 | yoklov | timvisher: think about things like zipWith3 in haskell. |
| 21:34 | yoklov | you don't need ugliness like that in clojure. |
| 21:34 | timvisher | yoklov: i actually have no experience with Haskell ;) |
| 21:34 | yoklov | (as a result, you hava ugliness in partial application) |
| 21:34 | yoklov | ah |
| 21:34 | timvisher | but I'll take your word for it |
| 21:34 | amalloy | yoklov: it's an ugliness tradeoff, yeah |
| 21:34 | autodidakto | Clojure vs Haskell, as well as currying, also comes out in difference over pattern matching |
| 21:35 | timvisher | it's quite obvious once you state it that way |
| 21:35 | amalloy | autodidakto: well, that's a feature that can be added on top of what clojure already has |
| 21:36 | xeqi | autodidakto: core.match is pretty good |
| 21:36 | mk | clojure functions that take varargs can be thought of as taking lists, instead |
| 21:37 | yoklov | mk: doesn't solve the problem though, because during partial application they aren't taking a list |
| 21:37 | autodidakto | xeqi: ah yes. I've been meaning to check that you |
| 21:37 | autodidakto | amalloy: how would you go about it? |
| 21:38 | amalloy | i'd probably just ask dnolen to do it |
| 21:38 | amalloy | and then he'd be like "oh, i already did, mate, it's in core.match" |
| 21:38 | amalloy | assuming that for april fools he fakes an australian accent |
| 21:38 | mk | yoklov: the cases of partial application on vararg fns that I can think of involve the non-vararg parts (as if you're initializing the function) - is partial application of varargs common? |
| 21:39 | yoklov | ,(map (partial + 5) [1 2 3]) |
| 21:39 | autodidakto | amalloy: kangaroo.match maybe, hehe heh |
| 21:39 | clojurebot | (6 7 8) |
| 21:39 | autodidakto | ,(+ 5 [1 2 3]) |
| 21:39 | clojurebot | #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number> |
| 21:40 | autodidakto | oh duh, map |
| 21:40 | yoklov | thats usually when i use partial application |
| 21:41 | autodidakto | yoklov: as a short/simple-function-like-shortcut? |
| 21:41 | yoklov | yeah |
| 21:41 | autodidakto | ,(map #(+ %) [1 2 3]) |
| 21:41 | clojurebot | (1 2 3) |
| 21:41 | autodidakto | deer |
| 21:41 | yoklov | or if i want to express somethign iin a snooty way |
| 21:41 | autodidakto | ,(map #(+ 5 %) [1 2 3]) |
| 21:41 | clojurebot | (6 7 8) |
| 21:41 | yoklov | ,(map (partial map +) [[1 2] [3 4]] [[5 6] [7 8]]) |
| 21:41 | clojurebot | ((6 8) (10 12)) |
| 21:42 | autodidakto | *head explodes* |
| 21:42 | mk | yoklov: yeah somewhat, though you might as well think of add as (+ a b list-goes-here) |
| 21:42 | yoklov | lol, think of (partial map +) as `point-add` |
| 21:42 | autodidakto | that's snooty. did you type that with your pinky fingers in the air? |
| 21:42 | yoklov | yeah. |
| 21:43 | yoklov | ,(map (partial + 1 2 3) [4 5]) |
| 21:43 | clojurebot | (10 11) |
| 21:44 | yoklov | mk: varargs and currying just don't mix well |
| 21:44 | mk | ,(map (partial + 6) [4 5]) |
| 21:44 | clojurebot | (10 11) |
| 21:44 | mk | I agree, but I'm not sure I'm a fan of either |
| 21:44 | yoklov | right, but you can only do that because you know that (+ a b c … rst) is the same as (+ (+ a b c) … rst) |
| 21:45 | yoklov | thats certainly not true in every case. |
| 21:46 | mk | + is a pretty good case for varargs, but it's really just (sum [1 2 3...]) |
| 21:46 | mega` | &(doc sum) ; dont think whe have sum |
| 21:46 | lazybot | java.lang.RuntimeException: Unable to resolve var: sum in this context |
| 21:47 | mega` | mk: so yea + is the sum |
| 21:47 | brehaut | sum is (apply + …) |
| 21:47 | yoklov | it's just apply + |
| 21:47 | Raynes | Or (reduce +) |
| 21:47 | yoklov | (partial apply +) :p |
| 21:47 | yoklov | (or reduce) |
| 21:47 | Raynes | #(apply + %) |
| 21:47 | clojurebot | Cool story bro. |
| 21:47 | mk | the reason I don't like varargs is that they are placed in arbitrary places in some of our functions (like in the middle), and some functions take lists when they may as well take varargs |
| 21:48 | autodidakto | ,((partial apply +) '(1 2 3)) |
| 21:48 | clojurebot | 6 |
| 21:48 | mega` | mk: in the midle?? what |
| 21:48 | Raynes | In the middle of a gunfight. |
| 21:48 | mk | mega`: yeah, let me find it... |
| 21:49 | autodidakto | Raynes: Never bring a vararg knife to the middle of a curry gunfight |
| 21:49 | autodidakto | at least that's my understanding |
| 21:49 | amalloy | btw, since we're discussing apply vs reduce, my favorite explanatory tool is ##((juxt apply reduce) (partial list '+) (range 5)) |
| 21:49 | lazybot | ⇒ [(+ 0 1 2 3 4) (+ (+ (+ (+ 0 1) 2) 3) 4)] |
| 21:50 | yoklov | mk: i really wouldn't want to part with vararg map. |
| 21:50 | autodidakto | ,(doc juxt) |
| 21:50 | clojurebot | "([f] [f g] [f g h] [f g h & fs]); Takes a set of functions and returns a fn that is the juxtaposition of those fns. The returned fn takes a variable number of args, and returns a vector containing the result of applying each fn to the args (left-to-right). ((juxt a b c) x) => [(a x) (b x) (c x)]" |
| 21:50 | amalloy | yeah, god help us if we had zipWith5 in the language. blech |
| 21:51 | mk | the best way to explain apply on its own, I think, is as injecting the given function into the front of the given list. It's an injector. |
| 21:51 | brehaut | amalloy: (partial list '+) (range 5) is cute, but why not just (list* '+ (range 5)) ? |
| 21:51 | amalloy | uhhh |
| 21:51 | amalloy | because that doesn't illustrate the point? |
| 21:51 | yoklov | mk: well but then it gets hairy, because some languages (ruby, for one) call reduce inject :p |
| 21:51 | yoklov | smalltalk too i think. |
| 21:52 | amalloy | the point is that reduce and apply do different things; i'm not just calling ((partial list '+) (range 5)) |
| 21:52 | Raynes | That's because it was named by a Japanese guy. |
| 21:52 | mega` | yoklov: .net cals it Aggregate |
| 21:52 | yoklov | right but he said it was injecting… yeah nevermind |
| 21:52 | brehaut | oh right |
| 21:52 | autodidakto | yoklov: inject is the more common synonym, but i like reduce is an alias to the method |
| 21:52 | autodidakto | *but i think reduce is |
| 21:52 | Raynes | That's because .NET was created by suits with no human bodies inside. |
| 21:52 | mk | yoklov: map throws the varargs as params, so initially that looked fine - but then - have you used map to map into vararg functions? because that sounds interesting |
| 21:52 | autodidakto | Raynes: Report to HR, immediately |
| 21:53 | yoklov | mk, you mean like my example above? |
| 21:53 | yoklov | ,(map (partial map +) [[1 2] [3 4]] [[5 6] [7 8]]) |
| 21:53 | clojurebot | ((6 8) (10 12)) |
| 21:53 | amalloy | &(apply map vector [[1 2 3] [4 5 6]]) |
| 21:53 | lazybot | ⇒ ([1 4] [2 5] [3 6]) |
| 21:53 | yoklov | oh thats neat. |
| 21:53 | amalloy | ~zip |
| 21:53 | clojurebot | zip is not necessary in clojure, because map can walk over multiple sequences, acting as a zipWith. For example, (map list '(1 2 3) '(a b c)) yields ((1 a) (2 b) (3 c)) |
| 21:54 | autodidakto | *head explodes* |
| 21:55 | autodidakto | oh right right, when given multiple lists/vectors/maps.. map takes one from each at a time.. |
| 21:55 | mk | right, yeah - those are in fact interesting |
| 21:56 | mega` | , (map + (range 0 4) (range 0 8)) |
| 21:56 | clojurebot | (0 2 4 6) |
| 21:57 | autodidakto | and stops when the shortest list ends... |
| 21:57 | mk | autodidakto: it takes all of the first elements in all of the given collections, and then shoves them into the given function as params (and then the second elements, then third...) |
| 21:57 | mk | ,(apply map vector [1 2] {:a 8 :b 9}) |
| 21:57 | clojurebot | ([1 :a :b] [2 8 9]) |
| 21:57 | autodidakto | mk: I see. thanks |
| 21:58 | autodidakto | but what's that apply do? |
| 21:58 | autodidakto | ,(map vector [1 2] {:a 8 :b 9}) |
| 21:58 | clojurebot | ([1 [:a 8]] [2 [:b 9]]) |
| 21:58 | autodidakto | hmm |
| 21:58 | xeqi | ,((partial map vector [1 2]) {:a 8 :b 9}) |
| 21:58 | clojurebot | ([1 [:a 8]] [2 [:b 9]]) |
| 21:58 | mega` | &(doc apply) |
| 21:58 | lazybot | ⇒ "([f args] [f x args] [f x y args] [f x y z args] [f a b c d & args]); Applies fn f to the argument list formed by prepending intervening arguments to args." |
| 21:59 | mk | I like to imagine them as.. dropping down, so [1 2 3 4] becomes vertical, and them map runs the function down this vertical strip. When given varargs, they all just roll down vertically |
| 22:00 | autodidakto | ,(map str [1a 2a 3a] [1b 2b 3b]) |
| 22:00 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.NumberFormatException: Invalid number: 1a> |
| 22:01 | mk | oh, apply is the one that takes varargs in the middle |
| 22:01 | autodidakto | ,(map str ["1a" "2a" "3a"] ["1b" "2b" "3b"]) |
| 22:01 | clojurebot | ("1a1b" "2a2b" "3a3b") |
| 22:01 | amalloy | no it doesn't |
| 22:01 | mega` | mk: only the last one has varargs |
| 22:01 | mk | could be wrong, I'll check |
| 22:02 | autodidakto | scroll up to the last lazybot |
| 22:03 | mk | it lies |
| 22:03 | mk | ,(apply vector 1 2 3 4 5 6 7 8 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 '(99 999)) |
| 22:03 | clojurebot | [1 2 3 4 5 ...] |
| 22:03 | amalloy | okay... |
| 22:04 | mk | you can put an arbitrary number of arguments into the middle, and they are all injected into "args" |
| 22:04 | amalloy | i mean, i guess i see what you mean by varargs in the middle, there |
| 22:05 | mk | what's described as "args" can actually only be one argument. If you try to apply into an apply, you'll end up applying... I'm going to cut that sentence off there |
| 22:06 | mega` | https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L596 |
| 22:07 | mk | apply is what you pull out when you want to use a list as varargs |
| 22:07 | mega` | &(doc spread) |
| 22:07 | lazybot | java.lang.RuntimeException: Unable to resolve var: spread in this context |
| 22:07 | TimMc | mega`: That's private, I think. |
| 22:07 | mega` | yea |
| 22:08 | TimMc | &(meta #'clojure.core/spread) |
| 22:08 | lazybot | ⇒ {:ns #<Namespace clojure.core>, :name spread, :arglists ([arglist]), :private true, :static true, :line 574, :file "clojure/core.clj"} |
| 22:08 | TimMc | ...and doesn't have :doc anyhow. |
| 22:09 | mk | it's two functions up in that link above |
| 22:09 | amalloy | spread is just list*, iirc |
| 22:09 | amalloy | except that it's a primitive used to define functions like apply and list* |
| 22:09 | amalloy | &(#'clojure.core/spread 1 2 [3 4]) |
| 22:09 | lazybot | clojure.lang.ArityException: Wrong number of args (3) passed to: core$spread |
| 22:10 | mega` | takes a seq directly |
| 22:10 | amalloy | right, it's (partial apply list*) |
| 22:10 | amalloy | &(#'clojure.core/spread [1 2 [3 4]]) |
| 22:10 | lazybot | ⇒ (1 2 3 4) |
| 22:10 | amalloy | &((partial apply list*) [1 2 [3 4]]) |
| 22:10 | lazybot | ⇒ (1 2 3 4) |
| 22:13 | autodidakto | amalloy: can you give me another clue to understanding apply? |
| 22:13 | mk | apply is kinda like a cons that gets evaluated |
| 22:13 | scriptor | autodidakto: what other languages do you know? |
| 22:14 | mk | ,(cons '+ '(1 2 3)) |
| 22:14 | clojurebot | (+ 1 2 3) |
| 22:14 | autodidakto | scriptor: ruby |
| 22:14 | mega` | , (eval (cons '+ '(1 2 3))) |
| 22:14 | clojurebot | #<Exception java.lang.Exception: SANBOX DENIED> |
| 22:14 | scriptor | hmm, not sure about the equivalent of apply in ruby |
| 22:14 | mk | (eval (cons '+ '(1 2 3))) |
| 22:14 | mega` | :( |
| 22:15 | mk | hmm |
| 22:15 | mk | > 6 |
| 22:15 | scriptor | autodidakto: in a sense, apply is like ruby's send, except that it works on functions, not methods |
| 22:15 | mega` | :D |
| 22:15 | amalloy | scriptor: it's like ruby's splat operator |
| 22:15 | mk | (apply + '(1 2 3)) |
| 22:16 | amalloy | (apply f a b c) => f(a, b, *c) |
| 22:16 | scriptor | yes, that too |
| 22:16 | autodidakto | hmm |
| 22:17 | scriptor | splat + higher order func |
| 22:17 | mk | autodidakto: at first think of apply as taking two arguments - a function, and a list |
| 22:18 | mk | it puts the function at the front of the list, and then runs away (the new list is evaluated, as a list usually would be) |
| 22:19 | mk | alternatively, if you have a function and it's missing a bunch of arguments, apply removes the brackets from that list, and puts them at the end of the function |
| 22:20 | mk | apply fun '( 1 2 3) -> eval'd(fun 1 2 3) |
| 22:20 | autodidakto | ,(str '(1 2 3)) |
| 22:20 | clojurebot | "(1 2 3)" |
| 22:20 | autodidakto | ,(apply str '(1 2 3)) |
| 22:20 | clojurebot | "123" |
| 22:20 | mk | ,(str 1 2 3) |
| 22:20 | clojurebot | "123" |
| 22:21 | mk | in your first expression, you gave a list to str, but it expects varargs |
| 22:22 | mk | apply is for turning any function that takes varargs into the same function, but taking a list |
| 22:23 | autodidakto | using the individual items of the list as it's arguments? |
| 22:23 | autodidakto | *its |
| 22:23 | mk | yep |
| 22:24 | mk | varargs can be thought of as being a list anyway |
| 22:24 | autodidakto | "alternatively, if you have a function and it's missing a bunch of arguments, apply removes the brackets from that list, " is this what amalloy was talking about with the splat operator? |
| 22:25 | scriptor | autodidakto: more or less |
| 22:25 | amalloy | i don't want to be held responsible for any description of apply that makes it sound like it's manipulating source forms like brackets |
| 22:26 | mk | right - keep in mind that's not what it actually does. But when you're looking at something like... |
| 22:26 | scriptor | yes, don't really think about it in terms of shuffling parentheses around, it takes the function f and uses the elements of the list as its arguments |
| 22:27 | mk | ,(str '(1 2 3)) |
| 22:27 | clojurebot | "(1 2 3)" |
| 22:28 | scriptor | autodidakto: what don't you still get? |
| 22:29 | mk | and you mess around with it and you find that (str 1 2 3) works just fine... well, the diff between the two is a pair of brackets. So you use apply |
| 22:31 | autodidakto | ,(map vector [1 2 3] [4 5 6]) |
| 22:31 | clojurebot | ([1 4] [2 5] [3 6]) |
| 22:31 | autodidakto | ,(apply map vector [[1 2 3] [4 5 6]]) |
| 22:31 | clojurebot | ([1 4] [2 5] [3 6]) |
| 22:31 | autodidakto | I'm trying to see how apply, like, went into the outter [vector] |
| 22:32 | mk | ,(map vector [1 2 3] [4 5 6]) |
| 22:32 | clojurebot | ([1 4] [2 5] [3 6]) |
| 22:32 | autodidakto | oh, by putting map inside it...? |
| 22:32 | mk | ,(apply map vector '( [1 2 3] [4 5 6])) |
| 22:32 | clojurebot | ([1 4] [2 5] [3 6]) |
| 22:32 | mk | by putting both map and vector inside it |
| 22:33 | autodidakto | that would be the same as the "<mk> apply fun '( 1 2 3) -> eval'd(fun 1 2 3)" thing you said |
| 22:33 | scriptor | autodidakto: with your second expression, you're telling apply, "take the function map, and pass it 'vector' as the first argument, and [1 2 3] and [4 5 6] as the 2 and 3rd arguments" |
| 22:34 | autodidakto | scriptor: ah. that helps too |
| 22:34 | mk | the vararg thing is why I think it's easier to think of apply as shoving all the left-side arguments into the single right-side list |
| 22:35 | mk | (apply list 1 '(22) 3 '(4)) |
| 22:35 | mk | ,(apply list 1 '(22) 3 '(4)) |
| 22:35 | clojurebot | (1 (22) 3 4) |
| 22:36 | mk | ,(list 1 '(22) 3 , 4) |
| 22:36 | clojurebot | (1 (22) 3 4) |
| 22:36 | autodidakto | could you say that apply is a way to "prepare" the arguments for a given function? |
| 22:36 | yoklov | autodidakto, sort of |
| 22:37 | yoklov | so i don't know if clojure does it this way |
| 22:37 | autodidakto | though by the name "apply", i guess it would be the other way around |
| 22:37 | yoklov | however typically |
| 22:37 | yoklov | evaluators are made up of two runctions |
| 22:37 | yoklov | `eval` and `apply` |
| 22:37 | scriptor | autodidakto: there's no 'preparing' done, it's about applying a given function to a list of arguments |
| 22:37 | yoklov | apply takes a function and a list of arguments, and applies the function to the arguments |
| 22:37 | scriptor | or a vector of args |
| 22:37 | yoklov | and eval uses apply to eval everything |
| 22:38 | yoklov | so, when you type (apply foo '(bar baz)) it gets evaluated the same as (foo 'bar 'baz) |
| 22:38 | mk | autodidakto: you can think of it that way, because it's equivalent to how it's done, but not actually how it's done. Also, in (apply f :a :b '(1)), :a :b are arguments, too |
| 22:39 | yoklov | oh right, apply in clojure does that. |
| 22:40 | yoklov | right, and apply just calls .applyTo on the function |
| 22:40 | yoklov | with the args made into a list |
| 22:41 | mk | autodidakto: do you have a good handle on the two-parameter apply? where it's just a function and a list (or vector, or seq)? |
| 22:42 | autodidakto | mk: good enough I think |
| 22:42 | autodidakto | in that case i think "I have a list, but now I want to use the items in that list as my arguments" |
| 22:43 | mk | ,(apply list :a :b [3 4]) |
| 22:43 | clojurebot | (:a :b 3 4) |
| 22:44 | mk | ,(apply (partial list :a :b) [3 4]) |
| 22:44 | clojurebot | (:a :b 3 4) |
| 22:44 | mk | that's how the multi-param version of apply works (or another way to think of it) |
| 22:45 | autodidakto | in that first apply, how does it "know" to open up the vector? |
| 22:45 | autodidakto | (apply list :a :b [3 4] [5 6]) |
| 22:45 | autodidakto | ,(apply list :a :b [3 4] [5 6]) |
| 22:45 | clojurebot | (:a :b [3 4] 5 6) |
| 22:46 | mk | autodidakto: it's the last argument |
| 22:47 | autodidakto | i see |
| 22:47 | autodidakto | ,(apply (partial list :a :b) [3 4] [5 6]) |
| 22:47 | clojurebot | (:a :b [3 4] 5 6) |
| 22:47 | mk | ,(apply (partial (partial list :a :b) [3 4]) [5 6]) |
| 22:47 | clojurebot | (:a :b [3 4] 5 6) |
| 22:48 | mk | ,(apply (partial list :a :b [3 4]) [5 6]) |
| 22:48 | clojurebot | (:a :b [3 4] 5 6) |
| 22:48 | mk | there's apply, then there's the stuff in the middle, and then there's the last item |
| 22:49 | mk | the stuff in the middle is the function and its first few params |
| 22:51 | autodidakto | Is there an easy way to describe the situation in which apply is needed and a simple (fn arg1 arg2) wouldn't work? |
| 22:51 | mk | you have a list, and you need to use that list inside a function that takes varargs |
| 22:52 | autodidakto | with the list as it's varargs? or all it's args? |
| 22:52 | autodidakto | *its |
| 22:53 | mk | as its varargs |
| 22:53 | mk | ,(+ '(1 2 3)) |
| 22:53 | clojurebot | #<ClassCastException java.lang.ClassCastException> |
| 22:53 | mk | ,(apply + '(1 2 3)) |
| 22:53 | clojurebot | 6 |
| 22:54 | autodidakto | gotcha |
| 22:54 | mk | (obviously if you were typing this in, you would just remove the brackets in the first case, but '(1 2 3) is meant to stand in for a symbol) |
| 22:55 | autodidakto | i'll start looking around for examples of apply in use and think about what's going. |
| 22:56 | autodidakto | mk, scriptor, amalloy: thanks for the tutoring :) |
| 22:57 | mk | np. The only thing you need to know about apply is that if you have a list, and a vararg function, you can use apply |
| 22:57 | autodidakto | ah, yoklov too |
| 22:57 | mk | ...apply could have been averted if none of our functions used varargs :P |
| 22:58 | yoklov | haha, no clue if i helped at all :p |
| 22:58 | yoklov | mk: you'd still need it in eval |
| 22:58 | mk | yoklov: yeah yeah :) |
| 22:58 | scriptor | no prob, eventually you'll find a place where apply will come in handy and it'll all click |
| 22:59 | autodidakto | mk: does that have something to do you with rant about varargs? |
| 23:00 | autodidakto | yoklov: I was intrigued about what you said about evaluators using eval/apply. I'm remembering the logo of the videos for the SICP book (which i havent finished *cough*)... the wizard with Eval/Apply in his crystal ball |
| 23:00 | yoklov | oh yeah |
| 23:00 | yoklov | exactly that. |
| 23:00 | yoklov | you should finish that. sicp is amazing :) |
| 23:01 | autodidakto | yoklov: the math-based examples make me squint at the screen |
| 23:01 | mk | autodidakto: yes. It also has to do with that part about varargs being in the middle, because that fun application of apply that you started with is... hard to start with |
| 23:01 | mk | ,(apply map vector [[1 2 3] [4 5 6]]) |
| 23:01 | clojurebot | ([1 4] [2 5] [3 6]) |
| 23:01 | yoklov | hah, the math in that book is a killer. |
| 23:02 | yoklov | regardless what i'm talking about was chapter 4 |
| 23:02 | autodidakto | yoklov: cool. I'll look it up |
| 23:02 | autodidakto | mk: i see |
| 23:03 | mk | ...I just realized why ,(+ 1 2) works in my repl even though it has a weird symbol at the very front |
| 23:06 | scriptor | isn't , treated the same as whitespace? |
| 23:06 | mk | yes. |
| 23:07 | autodidakto | ,(doc ,str) |
| 23:07 | clojurebot | "([] [x] [x & ys]); With no args, returns the empty string. With one arg x, returns x.toString(). (str nil) returns the empty string. With more than one arg, returns the concatenation of the str values of the args." |
| 23:07 | mk | "cool, my repl accepts the same special initial symbols as clojurebot - that's pretty convenient for pasting" |
| 23:08 | scriptor | autodidakto: don't need the , before str |
| 23:08 | mk | , is whitespace |
| 23:08 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: is in this context, compiling:(NO_SOURCE_PATH:0)> |
| 23:09 | autodidakto | right right, just confirming your point |
| 23:10 | autodidakto | yoklov: SICP is really quotable -> It is no exaggeration to regard this as the most fundamental idea in programming: The evaluator, which determines the meaning of expressions in a programming language, is just another program. To appreciate this point is to change our images of ourselves as programmers. We come to see ourselves as designers of languages, rather than only users of languages designed by others. |
| 23:11 | yoklov | haha, sicp is really amazing. chapter 4 is my favorite :) |
| 23:11 | mk | ,(apply apply apply map vector [[[[1 2 3] [4 5 6]]]]) |
| 23:12 | clojurebot | ([1 4] [2 5] [3 6]) |
| 23:13 | autodidakto | mk: ouch, thanks :) |
| 23:15 | muhoo | autodidakto: then what about people who design languages for designers of languages? |
| 23:16 | autodidakto | muhoo: they sit in the lotus position, hovering 3 feet off the floor |
| 23:17 | muhoo | or in a hammock. |
| 23:17 | autodidakto | muhoo: taking the year off |
| 23:18 | muhoo | "In a hammock, nobody knows you're not sleeping." -- Rich Hickey |
| 23:18 | autodidakto | Which really sums up clojure development.... I think |
| 23:20 | autodidakto | There needs to be a comic of him lying in a hammock, taking the year off, and braiding his hair... hmm what other memes can i shove in there... |
| 23:26 | autodida | muhoo: Is there an online collection of rhickey quotes taken wonderfully out of context? |
| 23:30 | arohner | is there an an await that works for future? |
| 23:32 | mk | autodida: you might try searching the logs at http://clojure-log.n01se.net/ |
| 23:32 | amalloy | arohner: isn't that just...deref? |
| 23:33 | Raynes | Or download all of the logs from raynes.me/logs/irc.freenode.net/clojure and grep them. |
| 23:33 | arohner | amalloy: I was thinking await did something it didn't, which is block on all agents (i.e. without listing them) |
| 23:33 | arohner | I'm writing some tests, and I'd like the test to block until all futures are finished, but I'd like to not explicitly list them |
| 23:35 | autodida | according to clojure, rhickey hasn't been seen since 08? |
| 23:35 | Raynes | $seen rhicky |
| 23:35 | lazybot | I have never seen rhicky. |
| 23:35 | Raynes | $seen rhickey |
| 23:35 | lazybot | rhickey was last seen joining on clojure 1 week and 6 days ago. |
| 23:35 | muhoo | wow, didn't know he used to be ini this channel. |
| 23:35 | Raynes | muhoo: He used to talk on this channel a lot. |
| 23:35 | muhoo | 2010, looks like |
| 23:35 | TimMc | He pops in with announcements every once in a while. |
| 23:36 | Raynes | Guys. 1 week, 6 days ago. |
| 23:36 | TimMc | Raynes: "joining" |
| 23:36 | Raynes | Yes, but he was here. |
| 23:36 | Raynes | It's fair that he doesn't join very often though. With 400+ users every day, it can get a little hairy. |
| 23:36 | slyrus | but he went out |
| 23:37 | TimMc | I remember him coming in and asking naming advice for what ended up being called "realized?" |
| 23:37 | mk | there's actually a secret channel where all the oldhats talk about things |
| 23:37 | TimMc | I can see why he doesn't show up much. |
| 23:37 | muhoo | i'm sure there is a backchannel still. |
| 23:37 | technomancy | mk: it's called irc.thinkrelevance.com |
| 23:37 | muhoo | hehehe |
| 23:40 | muhoo | well i'm sure linus doesn't hang around in #linux |
| 23:41 | muhoo | nor guido in #python, etc etc |
| 23:41 | autodidakto | linus: my sounds card breaks the drivers, what's with that? |
| 23:43 | muhoo | he was, however, active on the lkml for a long time, may still be even, i dunno. |
| 23:44 | mk | many of the channels for more popular languages are pretty much tech support. Nobody stays around for long enough for there to be a productive community |
| 23:45 | autodidakto | mk: do the tech support conversations swamp the deeper ones? or? |
| 23:46 | muhoo | i've seen people in #debian and #emacs who've been there over a decade though. |
| 23:46 | brehaut | they are all weighed down by their beards. they literally could not leave, even if they wanted to |
| 23:47 | mk | it's encouraging to see new users (especially when they're using your clojure libs), but devs start to leave if there's too much noise |
| 23:47 | muhoo | brehaut: that is awesome. thank you for that. |
| 23:49 | autodidakto | beards stuck under those old school loud, big-key keyboards |
| 23:49 | autodidakto | 10 years of tech support is enough to grey a beard, though |
| 23:51 | muhoo | autodidakto: http://www.flickr.com/photos/two_pi_r/264672521/ |
| 23:52 | technomancy | nobody talks about Emacs in #emacs though, so that's different |
| 23:52 | technomancy | it's mostly politics and bot abuse |
| 23:53 | autodidakto | muhoo: hehe yeah |
| 23:53 | brehaut | technomancy: emacs is now sufficiently intelligent that it can maintain political discourse and nobody notices? |
| 23:53 | brehaut | im not sure if that says more for emacs, or political debate |
| 23:54 | technomancy | brehaut: M-x no-u |
| 23:55 | brehaut | i cant tell if thats a joke i havent got, or if an emacs package i havent got |
| 23:56 | technomancy | political "debate" these days consist mostly of "no, YOU're the one who is wrong!!!oneone" |
| 23:56 | technomancy | so it's easy to automate, I guess? |
| 23:56 | brehaut | ah. lol |
| 23:56 | brehaut | heh yeah |
| 23:56 | brehaut | hidden markov model ? |
| 23:56 | brehaut | or just random |
| 23:56 | technomancy | brehaut: oh man |
| 23:56 | brehaut | its not like either party is actually listening to each other |
| 23:56 | technomancy | just ask rudybot about pretty much anything |
| 23:56 | technomancy | it's reminiscent of talk show radio |
| 23:56 | brehaut | lol |
| 23:57 | brehaut | is that a #emacs bot? |
| 23:57 | technomancy | yeah, he picks a random unlikely word from your line and searches his logs for a line that matches |
| 23:57 | technomancy | it's hilarious how often it almost makes sens |
| 23:57 | technomancy | e |
| 23:57 | brehaut | haha |
| 23:58 | autodidakto | sounds like some kind of post-apocolyptic dystopia... uncaring robots have taken over. |
| 23:59 | brehaut | id rather the uncaring robots than any american political faction |
| 23:59 | autodidakto | talk show radio -> Rush Limbot |
| 23:59 | brehaut | the robots are at least logical |
| 23:59 | muhoo | politics for me is a particularly insidious form of bikeshedding |