2015-02-02
| 00:00 | justin_s3ith | zapho53 (go-loop (let [[f, reply-chan] (<! file-chan)] (>! reply-chan (fs/readFile f))) (go (let [result-chan (chan) _ (>! file-chan ["file", result-chan]) res1 (<! result-chan) _ (>! file-chan res1 result-chan) ...] (console/log resN)) ; something like this I think |
| 00:02 | justin_s3ith | zapho53: basic idea is have a file reader in a go block, and repeatedly pass it file names and get back file contents (which happen to be file names) |
| 00:02 | zapho53 | justin_smith: Thanks. Looking at it now. |
| 00:02 | justin_s3ith | zapho53: that's a rough sketch |
| 00:02 | justin_s3ith | but the basic idea should be right |
| 00:06 | zapho53 | justin_smith: Sorry to say my fFirst impression is the JS is much simpler :( |
| 00:07 | justin_s3ith | zapho53: not a great example |
| 00:07 | justin_s3ith | zapho53: that is to say, there are other things core.async does better, and the simple examples won't really show it |
| 00:08 | zapho53 | justin_smith: I think the JS is fairly representative of typical nested callbacks. |
| 00:09 | zapho53 | justin_smith: I've chosen this simple example because I want to see what typical transposed Node -> CLJS code would look like. |
| 00:10 | zapho53 | justin_smith: My concern is whether core.async makes the code easier to understand, ie. simpler. Not convinced so far :( |
| 00:10 | justin_s3ith | OK |
| 00:10 | dnolen | zapho53: I've programmed JS for 10 years professionally, JS callback code is an abomination |
| 00:10 | dnolen | zapho53: what is your example that you want to see a simpler version of of? |
| 00:10 | justin_s3ith | dnolen: you can probably do a much better job of translating that nested callback example than I did |
| 00:11 | justin_s3ith | http://pastebin.com/JM1wEz5z |
| 00:11 | zapho53 | dnolen: http://pastebin.com/JM1wEz5z |
| 00:12 | dnolen | zapho53: justin_s3ith example is not the write way to do it |
| 00:12 | dnolen | zapho53: write a callback to channel helper once and for all |
| 00:12 | justin_s3ith | I'm actually glad to hear that |
| 00:12 | dnolen | s/write/right |
| 00:13 | zapho53 | dnolen: OK. I've looked around a bit but can't find a simple JS -> core.async example. I'm pretty new to core.async |
| 00:13 | zapho53 | dnolen: I went through Tim Baldridge's great examples but they're all in clj/cljs so couldn't quite make the connection mentally |
| 00:15 | zapho53 | dnolen: I'm asking here because for me a canonical JS callback -> cljs/core.async snippet would nail it for me. |
| 00:15 | dnolen | zapho53: well first off, expecting to understand core.async in anything less than a couple of weeks is unrealistic |
| 00:16 | zapho53 | dnolen: No, I've been at it for a while, on and off. |
| 00:16 | dnolen | zapho53: a core.async version of your snippet is literally a version w/o callback nothing to see here |
| 00:16 | dnolen | (let [res (<! ...) res (<! ...) ...] ...) |
| 00:16 | zapho53 | dnolen: I'm half way there. Just missing a kind of mental JS equivalent. I get the conecepts as bits and pieces. |
| 00:17 | dnolen | zapho53: there is no JS equivalent, unless you are using js-csp |
| 00:18 | dnolen | zapho53: https://github.com/ubolonton/js-csp |
| 00:19 | zapho53 | dnolen: The example was taken from an article by Byan Gilbert about his asynchronize library |
| 00:21 | dnolen | zapho53: anyways my earlier point still stands. With core.async for that code the only thing that will change is no callbacks |
| 00:21 | zapho53 | dnolen: Are you saying my snippet doesn't contain callbacks? |
| 00:21 | dnolen | zapho53: I'm not saying anything about your snippet other than that is typical JS callback hell |
| 00:22 | dnolen | zapho53: the problem with justin_s3ith "solution" is that it's at the wrong level of abstraction you would never write it that way |
| 00:22 | zapho53 | dnolen: Yes, that's why I posted it - to see how core.async would improve on it. |
| 00:22 | dnolen | zapho53: Node.js fns are have a regular form, it's trivial to write a channelizer thing |
| 00:23 | zapho53 | dnolen: An example would help. Then I'll let it rest :) |
| 00:23 | dnolen | zapho53: which I already answered, it's no different if you used generators - it would look like straightline code w/ no callbacks |
| 00:24 | zapho53 | dnolen: OK, thanks. |
| 00:24 | dnolen | zapho53: your example is covered in this more general case I blogged about http://swannodette.github.io/2013/08/31/asynchronous-error-handling/ |
| 00:25 | dnolen | zapho53: your example is covered where ES6 generators are discussed, core.async goes way further, pretty much any example you might encounter about Go has a trivial translation |
| 00:26 | zapho53 | dnolen: Didn't see that one. Looks exactly like what I was looking for. Thanks. |
| 00:28 | PigDude | dnolen: i think that zapho53 is curious about the ellipses in your example. i'd be curious too, how <! is pulling the files off some channel in the right order while the file opening is still non-blocking. also, zapho53's code provides a place to handle each file read error explicitly, whereas your blog post only demonstrates generic error-handling for a series of channel reads, but the <? becomes verbose too with specific error handling (though the |
| 00:29 | dnolen | PigDude: your question means you need to read to blog post several more times |
| 00:29 | dnolen | PigDude: and the previous blog entries too |
| 00:31 | dnolen | PigDude: but the hint is that <! is semantically blocking, but not really blocking, once that sinks in the rest makes sense |
| 00:31 | PigDude | dnolen: pardon me for not reading the *previous* blog post. the mechanics of <! in this case were not clear from the first post alone (which was a quick read) |
| 00:32 | dnolen | PigDude: I'm just pointing out that you were interjecting on a conversation where some expressed at least some experience /w core.async :) |
| 00:32 | dnolen | s/some/soneone |
| 00:32 | dnolen | erg someone |
| 00:32 | PigDude | dnolen: i've used core.async in production code, in a library targetting both clojure and cljs runtime |
| 00:33 | dnolen | PigDude: right, but I don't think zapho53 was expressing confusion about <! |
| 00:33 | PigDude | dnolen: but to be fair it's been a few months. either way, i could see why zapho53 would be confused. |
| 00:33 | dnolen | PigDude: could be wrong about that of course, I didn't read all the backlog |
| 00:34 | PigDude | dnolen: i could see how to somebody new to core.async the <! usage there could be confusing because without some special handling, those reads would be either blocking or non-deterministic |
| 00:34 | PigDude | dnolen: so mostly i was hoping to provoke further discussion for zapho53's sake :) |
| 00:35 | dnolen | PigDude: ok but it's simple, <! is semantically blocking w/o actually tying up a whole thread :) |
| 00:40 | PigDude | dnolen: ah, i see my confusion -- you're proposing an API used like (let [f1 (<! (read-file fname1)) f2 (<! (read-file... ] , while i was reading as (let [out (file-reader fname1 fname2 ... fnamen) f1 (<! out) f2 (<! out) ... ] ;; sorry for the confusion! |
| 00:42 | dnolen | PigDude: yeah, sorry, my point was that you could write the imperative thing w/o callbacks |
| 00:42 | PigDude | dnolen: i was thinking of the question as "how do i express something waiting for n files to be read" and came up with a clunky api in my head, the other version is definitely simpler and more flexible |
| 00:44 | PigDude | dnolen: and then i thought you were saying "he wants to hear from somebody with experience with core.async" and got a little huffy ;) |
| 00:45 | dnolen | PigDude: sorry I didn't mean to assume anything, and I sounded like I did |
| 01:30 | zacts | hi clojurists |
| 01:42 | riceandbeans | do carbs make you sleepy or energitic? |
| 01:47 | zacts | I hear energetic |
| 01:50 | riceandbeans | so is it protein that makes you sleepy? |
| 01:57 | zacts | riceandbeans: milk does, but partly I think due to the lactose |
| 01:57 | zacts | cow's milk |
| 02:01 | ddellacosta | crazy Clojurists, always on about macro-nutrients |
| 02:07 | bonanza | Hi, |
| 02:08 | bonanza | does anybody know, why I'm getting HTMLCollection by this expression: (-> dom-node .-children) |
| 02:08 | bonanza | but a normal JS array with this: dom_node.children |
| 02:08 | bonanza | where dom-node/dom_node is some HTML node in my app |
| 02:09 | bonanza | ofc I'm talking about clojurescript in the first sentence |
| 02:39 | michaelr525 | hmm |
| 02:39 | michaelr525 | so I wonder, compojure-api or liberator? |
| 02:40 | bonanza | michaelr525: are you refering to my question? |
| 02:40 | michaelr525 | bonanza: nope, that's my own question |
| 02:40 | michaelr525 | what was yours? |
| 02:40 | bonanza | "does anybody know, why I'm getting HTMLCollection by this expression: (-> dom-node .-children)" |
| 02:40 | bonanza | "but a normal JS array with this: dom_node.children" |
| 02:41 | bonanza | "where dom-node/dom_node is some HTML node in my app" |
| 02:41 | bonanza | in another words, |
| 02:41 | TEttinger | I'm wondering if .- and internal . are different |
| 02:41 | bonanza | I'm trying to translate this to clojurescript with no luck |
| 02:41 | bonanza | document.querySelector("#news-list").children[0].children[0].className |
| 02:42 | bonanza | . means refering to functions, |
| 02:42 | bonanza | .- to properties |
| 02:42 | bonanza | (like (.-length some-array)) |
| 02:42 | TEttinger | so is dom_node.children getting a function or what? |
| 02:42 | bonanza | anyway, how to express this "document.querySelector("#news-list").children[0].children[0].className" in CLJS? |
| 02:43 | bonanza | well, I tried "(-> (reagent/dom-node this) .-children (aget 0) .-children (aget 0) .-className)" but I'm just getting "undefined" |
| 02:43 | bonanza | "children" is a DOM node property |
| 02:44 | bonanza | it's an array |
| 02:44 | TEttinger | (-> document (.querySelector "#news-list") .-children first .-children first .-className) |
| 02:44 | bonanza | one more thing: "(reagent/dom-node this)" actually returns a dom node, it's a library function but it doesn't matter, it's just a DOM node |
| 02:45 | TEttinger | maybe something like that? |
| 02:45 | bonanza | let's try |
| 02:46 | bonanza | I got "Uncaught Error: [object HTMLCollection] is not ISeqable" |
| 02:46 | bonanza | that's another story - I should have got a plain JS array but instead I have HTMLCollection returned |
| 02:47 | TEttinger | hm |
| 02:47 | TEttinger | try taking out the - ? |
| 02:47 | TEttinger | I really don't know how the JS underlying this works |
| 02:50 | bonanza | I tried, but then I've got an error "object is not a function", |
| 02:51 | bonanza | which is understandable since these are properties, not functions |
| 02:51 | TEttinger | I wonder if [0] is actually accessing a property 0 |
| 02:52 | TEttinger | in which case you'd use (-> document (.querySelector "#news-list") .-children (get 0) .-children (get 0) .-className) |
| 02:53 | TEttinger | or, depending on weirdness levels, (-> document (.querySelector "#news-list") .-children (get "0") .-children (get "0") .-className) |
| 02:53 | bonanza | it seems like it does, |
| 02:53 | bonanza | this is the output of this expression: "(-> (.querySelector js/document "#news-list") .-children (aget 0))" => "(document.querySelector("#news-list").children[(0)])" |
| 02:54 | bonanza | get is a function for getting from normal CLJ data types, |
| 02:54 | bonanza | aget is for Java(-script) arrays |
| 02:54 | TEttinger | I was wondering if it wasn't actually an array |
| 02:55 | bonanza | It is - following expression works as exprected: (-> (.querySelector js/document "#news-list") .-children (aget 0)) |
| 02:55 | bonanza | i.e. it selects first ("0") node from "children" of #news-list |
| 02:56 | bonanza | but when I try to get first child of *that* node, I get "undefined" |
| 02:56 | TEttinger | uh hm. check its type however you do that in cljs? |
| 02:56 | TEttinger | (doc type) |
| 02:56 | clojurebot | "([x]); Returns the :type metadata of x, or its Class if none" |
| 02:58 | bonanza | yeah, but what node are you refering to? |
| 02:58 | TEttinger | first ("0") node from "children" of #news-list |
| 02:58 | bonanza | function HTMLDivElement() { [native code] } |
| 02:59 | TEttinger | yeah I have no idea how this works |
| 02:59 | bonanza | it's a normal HTML div element, it's just a way CLJS prints it |
| 02:59 | TEttinger | michaelr525: you seem to know something about cljs, which is about 10x more than I can say |
| 03:06 | michaelr525 | hmm |
| 03:06 | michaelr525 | what? |
| 03:06 | clojurebot | what is not a bug |
| 03:06 | michaelr525 | what |
| 03:10 | Mr0rris0 | lol it said that to me too |
| 03:10 | Mr0rris0 | what? |
| 03:10 | clojurebot | what is http://gist.github.com/306174 |
| 03:10 | Mr0rris0 | what? |
| 03:10 | clojurebot | what with pervasive side effects |
| 03:10 | Mr0rris0 | what? |
| 03:10 | clojurebot | what is cells |
| 03:10 | michaelr525 | TEttinger: I've been disconnected. What was the problem? |
| 03:11 | Mr0rris0 | what? |
| 03:11 | clojurebot | what is exceptions |
| 03:12 | TEttinger2 | michaelr525: bonanza is having issues with html elements not acting like collections |
| 03:13 | bonanza | or - acting like HTMLCollections, not as arrays (as I'd expect) |
| 03:13 | michaelr525 | why do you expect them to be arrays? |
| 03:15 | bonanza | because I'd like to get first elements from them, |
| 03:16 | bonanza | or, in other case (not presented here), I need to loop over such array |
| 03:17 | zacts | how can I easily convert a vector of vectors into a map of maps (map the data structure)? |
| 03:18 | michaelr525 | bonanza: (-> (.querySelector js/document "#mich") (.-children) (aget 0)) |
| 03:18 | bonanza | in other words, I simply need this "(-> some-HTML-node .-children (aget 0) .-children (aget 0))" to be equal to this "some_HTML_node.children[0].children[0]" |
| 03:18 | bonanza | michaelr525: yeah, that works, |
| 03:19 | bonanza | problem is when I have *two* such expressions in a row |
| 03:19 | bonanza | like in above example |
| 03:19 | michaelr525 | let me try a sec |
| 03:20 | michaelr525 | bonanza: works for me |
| 03:20 | michaelr525 | bonanza: maybe your html structure doesn't match what you expecet |
| 03:20 | bonanza | simply put, this "(-> (reagent/dom-node this) .-children (aget 0))" gives me a first parent (some div in my case) |
| 03:20 | michaelr525 | (-> (.querySelector js/document "#mich") (.-children) (aget 0) (.-children) (aget 0)) |
| 03:21 | bonanza | but this "(-> (reagent/dom-node this) .-children (aget 0) .-children (aget 0))" gives me nothing, where there *are* children of that node (one child, to be exact) |
| 03:22 | bonanza | this is my compiled invocation (no optimizations): "((reagent.core.dom_node.call(null,this$).children[(0)]).children[(0)])" |
| 03:22 | michaelr525 | what does (reagent/dom-node) return? |
| 03:23 | TEttinger3 | zacts: ##(let [vecvec [["a" "A" "b" "B"] ["z" "Z" "y" "Y"]]] (into {} (map #(into {}) vecvec))) |
| 03:23 | lazybot | clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox6330/eval12173/fn--12174 |
| 03:23 | TEttinger3 | zacts: ##(let [vecvec [["a" "A" "b" "B"] ["z" "Z" "y" "Y"]]] (into {} (map #(into {} %) vecvec))) |
| 03:23 | lazybot | java.lang.ClassCastException: java.lang.Character cannot be cast to java.util.Map$Entry |
| 03:23 | TEttinger3 | gah |
| 03:23 | bonanza | michaelr525: just a plain DOM node |
| 03:24 | bonanza | michaelr525: https://github.com/reagent-project/reagent/blob/master/src/reagent/core.cljs#L151 |
| 03:24 | bonanza | reagent is a CLJS React wrapper |
| 03:25 | bonanza | michaelr525: in this case, "root node of a mounted component" is my #news-list div |
| 03:26 | TEttinger3 | zacts: ##(let [vecvec [["a" "A" "b" "B"] ["z" "Z" "y" "Y"]]] (apply hash-map (map #(apply hash-map %) vecvec))) |
| 03:26 | lazybot | ⇒ {{"a" "A", "b" "B"} {"z" "Z", "y" "Y"}} |
| 03:26 | michaelr525 | bonanza: does it work fine when you use javascript api and not dom-node? |
| 03:26 | TEttinger3 | that has a map as a key and a map as a value |
| 03:27 | michaelr525 | what's that .' syntax btw? |
| 03:27 | bonanza | michaelr525: yes - "document.querySelector("#news-list").children[0].children[0]" gives me desired node |
| 03:28 | michaelr525 | bonanza: and dom-node returns the same type as querySelector? |
| 03:28 | bonanza | the thing is that I just have a container which has "content" and "scrollbar", and after mounting that container node in a DOM, I need to select the "scroller" (div inside) of a "scrollbar" |
| 03:29 | bonanza | michaelr525: yes, it returns a plain DOM node (as in http://facebook.github.io/react/docs/working-with-the-browser.html) |
| 03:29 | michaelr525 | do you wait until it's rendered? |
| 03:30 | bonanza | yes, because React works that way, it operates on "Virtual DOM" |
| 03:31 | bonanza | and to get a plain DOM node, you have to wait till it's "mounted" into, then you can select it |
| 03:32 | michaelr525 | could you maybe "inspect" the desired element in chrome dev tools and paste a screenshot somewhere? |
| 03:36 | bonanza | michaelr525: screenshot of a page? |
| 03:37 | bonanza | or a dom structure? |
| 03:37 | drakezhard | Hi does anyone know how to use (proxy) to extend a class? |
| 03:38 | bonanza | michaelr525: OK, I'll give you a DOM structure to see |
| 03:43 | bonanza | michaelr525: there's it: http://i.imgur.com/IC0qa2e.jpg |
| 03:45 | michaelr525 | hmm |
| 03:45 | michaelr525 | looks ok |
| 03:45 | Viesti | argh |
| 03:46 | Viesti | trying to make a custom reporter for cljs.test |
| 03:46 | Viesti | targeting karma |
| 03:46 | Viesti | for some reason, I can't pass a custom :reporter key to the environment :( |
| 03:47 | michaelr525 | bonanza: maybe try fetching them one at a time and inspecting their types and content? |
| 03:47 | Viesti | (run-tests (test/empty-env :karma) 'xxx.app-test) |
| 03:47 | Viesti | this should probably do it |
| 03:48 | michaelr525 | bonanza: browser-repl for example prints result types like that: #<[object HTMLDivElement]>, #<[object HTMLCollection]> |
| 03:48 | michaelr525 | so it's easy to know what you are getting |
| 03:50 | bonanza | michaelr525: well, the problem is that if I print result by plain js/console.log I got a HTMLCollection, like [item: function, namedItem: function] |
| 03:50 | bonanza | i.e. it prints like this, when I click, there is my "div.scroller" at [0], but I cannot select this by (aget 0) |
| 03:51 | michaelr525 | i meant to use cljs repl |
| 03:52 | bonanza | michaelr525: result will be the same as printing it by ex. (println ...) |
| 03:53 | bonanza | michaelr525: because it just uses IPrettyPrint interface under the hood |
| 03:54 | michaelr525 | so when you (println (dom-node "#news-list")) you get HTMLCollection? |
| 03:55 | michaelr525 | and (println (-> (dom-node "#news-list") (-.children)))? |
| 03:55 | michaelr525 | and (println (-> (dom-node "#news-list") (-.children) (aget 0))? |
| 03:55 | michaelr525 | i think you get my point |
| 03:55 | michaelr525 | did you try debugging like that? |
| 03:56 | bonanza | michaelr525: actually, (println (reagent/dom-node this)) yields "#<[object HTMLDivElement]>" |
| 03:56 | bonanza | and that's normal since it's a div, after all |
| 03:56 | michaelr525 | right |
| 03:57 | michaelr525 | what about the next step and the next one? |
| 03:57 | Viesti | has anyone tried to make a custom reporter for cljs.test? |
| 03:58 | bonanza | michaelr525: http://pastebin.com/wwLndRDJ |
| 04:00 | michaelr525 | bonanza: ok, just go on and when you get a result you didn't expect, inspect the problematic node at hand. that's what i'd do.. |
| 04:01 | bonanza | michaelr525: I'll definately try :) |
| 04:01 | bonanza | michaelr525: thanks for your effort |
| 04:05 | michaelr525 | let me know what you came up with |
| 04:24 | zacts | ah thanks |
| 04:41 | dysfun | is there a builtin equivalent to (fn [seq pred] (let [a (filter pred seq) b (remove pred seq)] [a b])) ? |
| 04:41 | dysfun | probably with the argument order reversed |
| 04:47 | Glenjamin | ,(doc split-with) |
| 04:47 | clojurebot | "([pred coll]); Returns a vector of [(take-while pred coll) (drop-while pred coll)]" |
| 04:47 | Glenjamin | oh, not quite |
| 04:51 | hyPiRion | it's just (juxt filter remove) |
| 04:53 | hyPiRion | group-by is a generalisation if you need to separate values even more |
| 04:56 | dysfun | juxt is good, thanks |
| 04:56 | dysfun | and does anyone know of a great example of cond-> ? |
| 04:56 | dysfun | it's very difficult to google for |
| 05:01 | hyPiRion | dysfun: (cond-> foo true (assoc :a :b)) acts as (assoc foo :a :b), and (cond-> foo false (assoc :a :b)) acts as foo only |
| 05:01 | hyPiRion | and they chain |
| 05:02 | hyPiRion | ,(map (cond-> % (odd? %) (* 2) (even? %) (* 3) (neg? %) -) (range -3 3)) |
| 05:02 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: % in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 05:02 | hyPiRion | ,(map #(cond-> % (odd? %) (* 2) (even? %) (* 3) (neg? %) -) (range -3 3)) |
| 05:02 | clojurebot | (6 6 2 0 2 ...) |
| 05:05 | dysfun | hrm, so effectively a conditional pipeline? |
| 05:05 | hyPiRion | yep |
| 05:06 | dysfun | so this might be useful, for example for performing a bunch of data correction? |
| 05:06 | dysfun | if data displays this brokenness, fix it this way? |
| 05:07 | fairuz | anyone use Tinkerpop stack with clojure here? :) |
| 05:07 | dysfun | fairuz: did a very small amount with the orientdb library |
| 05:07 | hyPiRion | dysfun: yeah, that's an example |
| 05:07 | dysfun | hyPiRion: hrm. any other good cases you can think of, in terms of the high level? |
| 05:13 | hyPiRion | dysfun: Well, afaik it was introduced because Rich (?) had a lot of code which looked like this: |
| 05:13 | hyPiRion | (let [a input, a (if (old-style? a) (update-in a [:res] update-to-new) a), a (if (negative-results? a) (fix-results a) a)] (do-something-with a)) |
| 05:14 | hyPiRion | With cond->, that's (let [a (cond-> in (old-style? in) (update-in [:res] update-to-new) (negative-results? in) (fix-results))] (do-something-with a)) |
| 05:16 | dysfun | right, so again that's pretty much a data fixing up use case :) |
| 05:17 | Glenjamin | it's fairly good in speccing ring middleware |
| 05:17 | hyPiRion | Well, that's the examples I managed to come up with right now :p |
| 05:17 | Glenjamin | (-> app (cond-> dev wrap-stacktrace)) |
| 06:20 | dysfun | Glenjamin: ooh yes, that's quite a nice one |
| 06:20 | dysfun | in fact, i've got a pattern for dealing with that that i'm not happy with, so i'm going to rewrite it in that manner |
| 06:22 | Glenjamin | it's actually not ideal for that, because you can only do one middleware per condition |
| 06:22 | dysfun | that's fine, they're already in functions for grouping |
| 06:22 | Glenjamin | unless you do (cond-> test? (-> () () ())) |
| 06:22 | dysfun | hrm, that could work |
| 06:33 | Viesti | hmm |
| 06:33 | Viesti | is there something like alter-var-root for ClojureScript? |
| 06:34 | Glenjamin | you can probably just use def |
| 06:34 | Viesti | hmm so how do I override a def in another namespace? |
| 06:41 | CookedGr1phon | Hey all. I want something which behaves like a promise mixed with an atom. Is there such a thing without two derefs? |
| 06:42 | CookedGr1phon | i.e. I want to promise and deliver later, block on read until it's delivered, but also with the possibility of changing it later on |
| 06:44 | Glenjamin | CookedGr1phon: i don't think that exists out of the box, but you could probably reify something |
| 07:03 | clgv | CookedGr1phon: maybe you should separate both concerns |
| 07:03 | clgv | CookedGr1phon: as soon as it is delivered you can wrap it in an atom and pass that along |
| 07:04 | CookedGr1phon | that's pretty much what I've done |
| 07:06 | clgv | well, then you do not need something merged ;) |
| 07:07 | CookedGr1phon | I meant that's what I've done since asking the question |
| 08:21 | LukasK | Hi, i tried to add the clojars repo to my maven nexus but it is not working |
| 08:23 | clgv | LukasK: did you add it as "proxy repository"? |
| 08:25 | LukasK | our nexus admin did, the type of the repo is proxy. but when i click on browse storage (nexus browser UI) there is just a corrupt archetype-catalog.xml |
| 08:26 | LukasK | browse remote is working |
| 08:26 | clgv | LukasK: and the index download is enabled as well? |
| 08:26 | LukasK | i dont think so |
| 08:26 | clgv | LukasK: it is enabled by default if you add a new proxy rep as far as I have seen |
| 08:27 | clgv | when you enable that, you can search for clojars artifacts in your nexus instance |
| 08:27 | LukasK | ok i ask my nexus admin if he enabled the index download, but if it is enabled by default and it is not working there must be another problem |
| 08:28 | clgv | LukasK: clojars.org/repo is the location |
| 08:30 | clgv | LukasK: do you know by any chance how your admin detects "failed logins"? nexus has an rss feed but you cant use that for fail2ban :( |
| 08:32 | LukasK | sorry clgv, i have no idea |
| 08:32 | clgv | LukasK: ok |
| 08:32 | clgv | it's pretty weird to have an rss feed for it but not to include it in the log files... |
| 09:05 | LukasK | hmm nexus can't download the clojars index |
| 09:07 | clgv | LukasK: mine did so yesterday.. |
| 09:20 | LukasK | hmm strange |
| 09:22 | LukasK | ah it's working :P |
| 09:22 | LukasK | just took forever but now it is working :P |
| 09:49 | Scorchin | Hello, I'm using cider in emacs now instead of nREPL. Everything looks good so far, but it's not running the tests for a Clojure test when I run `C-c ,` or `C-c C-,`. It just shows "Testing..." in my mode line but no output. Has anyone seen this before and know what the fix is? |
| 10:00 | Scorchin | Never mind, figured it out. Had to add `[cider/cider-nrepl "0.8.2"]` to my :user :profiles hash |
| 10:37 | dnolen | just release ClojureScript 0.0-2760, fixes some ns parsing regressions introduced by 0.0-2755 |
| 10:39 | clgv | dnolen: regarding the versions. is there a roadmap or essential features that need to be done before having some kind of 1.0 release? |
| 10:40 | dnolen | clgv: Google Closure Module support, fixing tons of bugs (> 100 open issues in JIRA), optional bootstrap at a minimum |
| 10:41 | clgv | dnolen: ok, sounds like a lot of work |
| 10:41 | dnolen | clgv: yep |
| 10:41 | daniel__ | what about 0.1? :) |
| 10:50 | muhuk | Greetings. Which convention do you use for constructors in your libs; foo/make-foo or foo/create or foo/new ? |
| 10:50 | Glenjamin | module.exports = function(){} |
| 10:51 | Glenjamin | oh, wrong channel |
| 10:51 | Glenjamin | duh |
| 10:51 | Glenjamin | ignore me |
| 10:51 | stuartsierra | muhuk: I use just "foo" if it creates a new Foo; "new-foo" if I want to distinguish from returning a pre-existing foo; and "create-foo" if it has side effects (e.g. updating a database) |
| 10:53 | gfredericks | concoct-foo |
| 10:53 | gfredericks | discover-foo |
| 10:53 | muhuk | stuartsierra: so foo/foo, it's likely to be imported as foo |
| 10:53 | gfredericks | invent-foo |
| 10:53 | llasram | gfredericks: derive-foo ? |
| 10:53 | llasram | gfredericks: ooh: evolve-foo |
| 10:53 | gfredericks | imagine-foo |
| 10:54 | gfredericks | prove-foo-by-construction |
| 10:57 | stuartsierra | I generally like to name non-side-effecting functions as nouns for the thing they return. |
| 10:57 | stuartsierra | My side-effecting functions are verbs. |
| 10:57 | stuartsierra | So "foo" or "new-foo" are pure constructors. |
| 10:57 | stuartsierra | "create-foo" has side-effects. |
| 10:57 | muhuk | stuartsierra: makes sense. Thanks! |
| 10:58 | stuartsierra | And yes, I do end up with a lot of foo/foo, but it doesn't really bother me. |
| 10:58 | stuartsierra | I also break these rules all the time :) |
| 11:01 | uris77 | rules are meant to be broken :) |
| 11:02 | gfredericks | I like breaking the "rules are meant to be broken" rule |
| 11:03 | clgv | gfredericks: no self-referential statements allowed! you probably know what this has done to mathmatics ;) |
| 11:04 | gfredericks | arguably the prior statement was already self referential |
| 11:04 | TimMc | (defn allocate-tmp-stack-frame [] nil) |
| 11:05 | gfredericks | (inc TimMc) |
| 11:05 | lazybot | ⇒ 88 |
| 11:05 | clojurebot | No entiendo |
| 11:05 | hyPiRion | ,(let [x [1]] (aset (.tail x) 0 2) x) ; <- breaking the rules |
| 11:05 | clojurebot | [2] |
| 11:05 | clgv | gfredericks: maybe it was just a suggestion ;) |
| 11:05 | TimMc | I suppose that should have a ! at the end. |
| 11:05 | clgv | gfredericks: or an observation |
| 11:06 | clgv | hyPiRion: that's to easy to spot - convert an array to a vector and then modify the underlying array values ;) |
| 11:07 | hyPiRion | or just do this |
| 11:07 | hyPiRion | (let [x [1]] (aset (.tail x) 0 x) x) |
| 11:13 | sdegutis | I can't help but notice tons of similarities between Clojure and Haskell. |
| 11:17 | hipsterslapfight | well they're both functional languages sure |
| 11:18 | clgv | but on of them has a, let's say, "suboptimal" syntax ;) |
| 11:18 | sdegutis | hipsterslapfight: They both have things like comp and partial, they both have plenty of ways to operate on lists, they both encourage writing small, pure functions... |
| 11:19 | hipsterslapfight | about the only thing i really miss from haskell is auto currying |
| 11:20 | sdegutis | hipsterslapfight: you don't miss the compile-time type safety? |
| 11:20 | hipsterslapfight | sdegutis: no, if that were the case i'd be using haskell still :v |
| 11:20 | CookedGr1phon | hipsterslapfight: but in return you get varargs |
| 11:21 | hipsterslapfight | CookedGr1phon: sure, i have mixed feeligns on variadic functions though ... |
| 11:24 | tcrayford____ | sdegutis: haskell was an explicit inspiration for rich when designing cleaxjure |
| 11:24 | sdegutis | tcrayford____: huh, I didn't know that |
| 11:24 | sdegutis | That explains a lot of the similarities. |
| 11:27 | sdegutis | Are Clojure's lazy sequence functions essentially lazy in the same way as any of Haskell's list functions? |
| 11:30 | stuartsierra | sdegutis: not really |
| 11:30 | sdegutis | oh ok |
| 11:30 | stuartsierra | I mean, you can use them to achieve similar ends, but the mechanism is totally different. |
| 11:30 | stuartsierra | In Haskell, evaluation itself is lazy, even function arguments. |
| 11:30 | stuartsierra | List laziness just falls out of that. |
| 11:31 | stuartsierra | Clojure functions always use strict evaluation semantics. Lazy sequences are a special-purpose data structure for achieving laziness in one specific area. |
| 11:34 | tbaldridge | Haskell's laziness can also have the same problems as lazy seqs in Clojure. In haskell it's possible to get into a situation where a while chain of calls are held in memory since you haven't executed them yet. Those calls could result in a single integer which would have been cheaper to evaluate when they were constructed. |
| 11:34 | tbaldridge | So I kindof compare that to some of Clojure's issues with "holding the head |
| 11:34 | tbaldridge | ... of seqs" |
| 11:39 | mdrogalis | tbaldridge: Are promise channels out in any core.async releases yet? |
| 11:39 | tbaldridge | not that I know of, puredanger would be the one to ask about that |
| 11:39 | mdrogalis | tbaldridge: Okay, thanks man. |
| 11:49 | sdegutis | tbaldridge, stuartsierra: ahh, that's very informative, thank you |
| 12:11 | zerokarmaleft | it's all just lambda calculus |
| 12:11 | clgv | $karma zerokarmaleft |
| 12:11 | lazybot | zerokarmaleft has karma 0. |
| 12:16 | llasram | (inc zerokarmaleft) |
| 12:16 | lazybot | ⇒ 1 |
| 12:17 | hellofunk | lol that was scary there for a moment |
| 12:24 | zerokarmaleft | some people just want to watch the world burn |
| 12:30 | dnolen | cfleming: ping |
| 12:30 | csd_ | Is there any way for me to have a function use global var foo of the current namespace calling the function, rather than global var foo of the namespace the function is in? |
| 12:31 | llasram | csd_: That honestly sounds horrific :-). Dynamic vars are the closest you'd get (fortunately) |
| 12:32 | csd_ | its for testing purposes |
| 12:32 | csd_ | i have a function that references a global ref, and i want to test the function |
| 12:33 | csd_ | (open to alternatives) |
| 12:33 | llasram | csd_: It's not without its own limitations, but maybe `with-redefs`? |
| 12:33 | justin_s3ith | csd_: it can be hacked with a macro |
| 12:33 | justin_s3ith | but that's macro abuse |
| 12:34 | justin_s3ith | brb getting rid of this silly nick |
| 12:34 | csd_ | with-redefs looks like it would do the trick |
| 12:35 | Frozenlock | Is there a way to list all the methods of a protocol? |
| 12:37 | justin_smith | Frozenlock: look up its source? |
| 12:37 | justin_smith | Frozenlock: it should be possible via reflection too actually, but all the methods should have to be right there in the protocol def, so I think that's easier |
| 12:37 | csd_ | llasram-- thx, that works. what would the typical approach be when someone is trying to test a function that uses global state? |
| 12:38 | justin_smith | csd_: :P stop using global state maybe? |
| 12:38 | csd_ | but i need it |
| 12:38 | justin_smith | OK |
| 12:38 | Frozenlock | justin_smith: yeah I did that, but I get "Can't define method not in interfaces" when I try a method defined in the source :-/ |
| 12:38 | justin_smith | Frozenlock: that makes me think the arg count doesn't match |
| 12:38 | llasram | csd_: I'm actually with justin_smith on this one. I'm skeptical of general actual need for global state |
| 12:39 | llasram | (modulo wanting to use a library which is written to depend on it) |
| 12:39 | justin_smith | csd_: it should be possible to segregate the management of global state from program logic |
| 12:39 | csd_ | llasram, writing an IRC server? |
| 12:39 | Frozenlock | justin_smith: hmm maybe... let me check that. |
| 12:39 | justin_smith | csd_: if you really need global state, make a logicless shim (which won't need testing) plus a pure function with all the logic (easy to test) |
| 12:40 | justin_smith | csd_: very similar to the trick of using a function to generate the expansion for a macro |
| 12:40 | llasram | csd_: Why would that necessitate process-global state, where you wouldn't be able to have e.g. the same JVM running multiple servers simultaneously on different ports? |
| 12:40 | csd_ | sorry i don't understand the question |
| 12:41 | justin_smith | csd_: what if an app needs two or more instances of what your code implements |
| 12:41 | llasram | csd_: I'm saying that just because you have state doesn't mean it needs to be "global" |
| 12:41 | Frozenlock | justin_smith: Everything looks okay. Would you mind checking this very short example and telling me if there's any obvious problem? https://www.refheap.com/96802 |
| 12:41 | csd_ | i'm implementing global state with a ref, and each client will be its own thread, and will have functions to access global state |
| 12:42 | csd_ | this is an area i'm pretty ignorant in so i'm learning as i go |
| 12:42 | llasram | csd_: But why does it have to be global? Why don't the threads start with a reference to the ref passed in as an initial argument instead? |
| 12:43 | tbaldridge | csd_: you could still use a ref, but pass it in to each client thread when you construct it |
| 12:43 | csd_ | i was initially thinking of doing it that way, llasram, but someone smarter than i suggested otherwise, asking why should a single connection need access to everything |
| 12:44 | tbaldridge | bleh, didn't see what llasram wrote |
| 12:45 | justin_smith | csd_: if it's global, then everyone get's full access, that's no different than passing it as an arg |
| 12:45 | justin_smith | *gets |
| 12:46 | justin_smith | Frozenlock: all I can think is maybe a typehint that the result is Object? that seems like an odd thing to need though. |
| 12:46 | csd_ | , do you know of any good reading on architecting this sort of thing? |
| 12:46 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: do in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 12:46 | csd_ | sorry my ERC is broken :-/ |
| 12:47 | csd_ | -- that was addressed to you |
| 12:47 | csd_ | jesus |
| 12:47 | llasram | csd_: https://github.com/stuartsierra/component |
| 12:47 | justin_smith | csd_: sicp covers the general concept of transforming global state into explicit args iirc, but that's a tiny part of what it covers, and is actually pretty simple once you do it a few times |
| 12:47 | justin_smith | csd_: and yeah, component has some stuff built around that idea too |
| 12:48 | justin_smith | (inc llasram) |
| 12:48 | lazybot | ⇒ 47 |
| 12:48 | csd_ | ok i'll check it out thanks |
| 12:48 | justin_smith | almost forgot to inc dnolen for saving that newb from my shitty code last night |
| 12:48 | justin_smith | (inc dnolen) |
| 12:48 | lazybot | ⇒ 20 |
| 13:06 | Frozenlock | ,(clojure.pprint/pprint (->> (clojure.reflect/reflect clojure.lang.IAtom) :members (map :name))) |
| 13:06 | clojurebot | #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.pprint> |
| 13:06 | Frozenlock | ,(->> (clojure.reflect/reflect clojure.lang.IAtom) :members (map :name)) |
| 13:06 | clojurebot | #<CompilerException java.lang.ClassNotFoundException: clojure.reflect, compiling:(NO_SOURCE_PATH:0:0)> |
| 13:07 | Frozenlock | grr... here's the result (swap swap swap reset swap compareAndSet) |
| 13:07 | justin_smith | Frozenlock: perhaps you need to require some namespaces |
| 13:07 | justin_smith | ,(require 'clojure.pprint 'cojure.reflect) |
| 13:07 | clojurebot | #<FileNotFoundException java.io.FileNotFoundException: Could not locate cojure/reflect__init.class or cojure/reflect.clj on classpath.> |
| 13:07 | justin_smith | well, at least we have the pprint |
| 13:07 | Frozenlock | :-p |
| 13:08 | Frozenlock | I just wanted to show what was visible... 'deref' is not there. Any ideas why? |
| 13:09 | felixflores | Can anyone tell me why transit is not recognizing java.sql.Timestamp even after I've defined a handler for it? https://gist.github.com/felixflores/20a8cfa034628cae09ac |
| 13:11 | Frozenlock | oh dang... deref might be a IDeref method. |
| 13:11 | clgv | Frozenlock: there is IDeref |
| 13:11 | clgv | ah you got it |
| 13:12 | clgv | future, promise and ref implement IDeref as well |
| 13:12 | R0B_ROD | !seen godd2 |
| 13:13 | clgv | it's "$seen" afaik |
| 13:13 | justin_smith | $seen godd2 |
| 13:13 | lazybot | godd2 was last seen quittingPing timeout: 246 seconds 20 hours and 56 minutes ago. |
| 13:13 | clgv | strange order |
| 13:19 | felixflores | ignore me. I made a stupid mistake. I didn't send the appropriate MIME type |
| 13:21 | justin_smith | Frozenlock: yeah, I see that too, no actual deref in the IAtom methods |
| 13:21 | clgv | how do I find out the client IP from a ring request? |
| 13:21 | justin_smith | Frozenlock: do you remember if that was maybe protected? |
| 13:21 | clgv | I need that for monitoring abuse of the web app |
| 13:21 | Frozenlock | justin_smith: No, it looks like deref is an IDeref method, not an IAtom one. |
| 13:22 | justin_smith | Frozenlock: aha, for some reason I saw deref in the IAtom source, maybe I was mistakenly looking at an old version of the code |
| 13:22 | clgv | ah there is :remote-addr |
| 13:23 | Frozenlock | justin_smith: I saw it too (https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Atom.java#L29) which is why I didn't even think of looking in other interfaces. |
| 13:27 | tbaldridge | Frozenlock: there is a IDeref interface. |
| 13:28 | R0B_ROD | thanks justin_smith |
| 14:20 | ben_vulpes | anyone have a handle on clojure-west promo codes? |
| 14:20 | ben_vulpes | i missed the early reg :( |
| 14:25 | justin_smith | ben_vulpes: yeah that was over fast, and you're probably in the same boat I am where you would be buying your own ticket |
| 14:26 | noonian | us pdxers late to the party should all register together for the 10% discount |
| 14:28 | justin_smith | noonian: sounds like an excellent plan |
| 14:28 | justin_smith | "clojerk discount" |
| 14:28 | noonian | lol nice |
| 14:50 | crazydiamond | Hi. Can I wrap function (or macro?) deftest into my function? I.e. to have bunch of tests generated (e.g. to test single function on multiple data)? |
| 14:51 | slipset | hmm, maybe look into :pre and :post |
| 14:51 | slipset | which are like asserts? |
| 14:51 | slipset | or, better yet, could you show us an example of what you're trying to achieve? |
| 14:52 | crazydiamond | ah.. design by contract? :D |
| 14:53 | justin_smith | crazydiamond: you can define a test with defn similarly to how :pre and :post are defined https://clojuredocs.org/clojure.core/test |
| 14:53 | justin_smith | yeah, :pre and :post are more similar to design by contract, and :test is for tdd |
| 14:53 | justin_smith | though frequently/usually people directly use assert or clojure.test/deftest |
| 14:53 | crazydiamond | yep, I want TDD |
| 14:54 | crazydiamond | but I have repetition, like this: http://dpaste.com/09RV7F4 |
| 14:54 | slipset | crazydiamond: if you're into TDD, checkout midje and autotest |
| 14:54 | justin_smith | crazydiamond: you can always define a function to be called inside tests |
| 14:55 | justin_smith | crazydiamond: calling deftest inside defn seems odd to me |
| 14:55 | hyPiRion | gfredericks: Implementation of factorial using a Y combinator: |
| 14:55 | hyPiRion | ,(((->(->>(#(% %)(->>(!(->>(($ $)?)#()(->[?])))#()(->[$]))))(->> #()(->[!])))(->>(->>(({(=(+)$)#(*)}(= =)#(* $(!(- $(*))))))#()(->[$]))#()(->[!]))) 10) |
| 14:55 | clojurebot | 3628800 |
| 14:55 | crazydiamond | justin_smith, yes, but every time... if I would have 50 tests, that would be 50 functions... |
| 14:55 | arrdem | (inc hyPiRion) ;; that's revolting but you deserve it. |
| 14:55 | lazybot | ⇒ 64 |
| 14:56 | justin_smith | crazydiamond: if there is duplicated logic between the tests, you can define one function, if there isn't there's no point in putting it in a function |
| 14:56 | hyPiRion | I implemented SKI as well. Pretty sure that proves Swearjure is turing complete, no? |
| 14:56 | slipset | crazydiamond: also, maybe you should look into propertybased/generative testing |
| 14:57 | justin_smith | crazydiamond: also, that defn that calls deftest is not doing what you think it does |
| 14:57 | slipset | seems like you're using your functions to generate test-data for your tests? |
| 14:57 | justin_smith | crazydiamond: you are repeatedly redefining the same test |
| 14:57 | crazydiamond | justin_smith, yep. I realized that. my test doesn't fail (but it should) |
| 14:57 | crazydiamond | huh |
| 14:57 | arrdem | hyPiRion: now if only it were TCO'd it'd be useful as well |
| 14:57 | justin_smith | crazydiamond: test_run_func would need to be a macro |
| 14:58 | justin_smith | crazydiamond: also, camelcase and snake case for functions is a bad idea, it confuses readers. CamelCase is for classes, snake_case is for json / db keystrings. For clojure vars use kebab-case |
| 14:59 | hyPiRion | arrdem: Hrm. Need to find a way to implement trampoline. |
| 14:59 | slipset | hyPiRion: you need to stop with this hand crafting nonsense and write a clojure2swearjure code-walking macro |
| 15:00 | slipset | or something ;) |
| 15:00 | hyPiRion | slipset: I'm not that far away from doing that actually |
| 15:00 | slipset | Don't you write compilers for a living? |
| 15:01 | hyPiRion | yes |
| 15:01 | hyPiRion | I found the SKI properties while working on my swearjure interpreter. |
| 15:02 | crazydiamond | thanks for help |
| 15:02 | Frozenlock | What's the clojure way of doing the 'extends' part of this: "final public class Atom extends ARef implements IAtom" ? |
| 15:02 | crazydiamond | I wonder if I may just change defn to defmacro for test_run_func |
| 15:02 | hyPiRion | (Clarification: I don't implement a swearjure interpreter for work) |
| 15:02 | tbaldridge | Frozenlock: you can do it with proxy, but I'm not sure that's what you want |
| 15:02 | justin_smith | Frozenlock: deftype could do it, or proxy |
| 15:02 | tbaldridge | Frozenlock: what are you trying to do? |
| 15:02 | justin_smith | wait, maybe deftype can't |
| 15:03 | Frozenlock | adding IRef to a deftype without reimplementing all the methods. |
| 15:03 | justin_smith | Frozenlock: for interfaces, you can use deftype or defrecord to extend, for concrete classes you need proxy or gen-class I think |
| 15:04 | justin_smith | Frozenlock: oh, that's easy - clojure won't complain about partial coverage at all |
| 15:04 | justin_smith | Frozenlock: just add an IRef clause to your deftype |
| 15:04 | tbaldridge | yeah, it'll just throw NotImplementedException on any unspecified methods |
| 15:04 | justin_smith | if/when they are called :) |
| 15:04 | Frozenlock | Well, I want those methods... |
| 15:04 | justin_smith | Frozenlock: wait, what? |
| 15:05 | justin_smith | you want methods from an interface, but don't want to implement them? |
| 15:05 | Bronsa | justin_smith: he's ok with the impl provided by ARef |
| 15:05 | justin_smith | ahh, right |
| 15:05 | slipset | tbaldridge: just curious, the idea of implementing the go-macro as a state-machine, is that something that falls out of Hoare's CSP, the Go-lang implementation of CSP or out of the bright heads like yourself? |
| 15:05 | Frozenlock | Bronsa: yes, that. |
| 15:06 | Bronsa | Frozenlock: genclass/proxy are the only way to do that ATM |
| 15:06 | Frozenlock | If you look at this https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Atom.java#L17, you can see that Atom is just using ARef. |
| 15:06 | justin_smith | Frozenlock: you can do that kind of thing with proxy or gen-class |
| 15:06 | justin_smith | or just write some java |
| 15:07 | Bronsa | or use a custom version of clojure https://github.com/Bronsa/clojure/blob/defclass/src/clj/clojure/interop.clj#L27 ;) |
| 15:08 | justin_smith | Bronsa: I'm not sure whether I love that or hate it... definitely one of the extremes, just not sure which yet. |
| 15:10 | {blake} | OK, so I'm now maintaining/expanding this app I've built, at the very bottom of which, there's a call (.javaMethod obj). And now I've discovered obj MAY be nil. I can catch the nil going in, or I can make the call at the bottom return nil instead of trying to make the call. |
| 15:11 | justin_smith | {blake}: some-> can be helpful for either (depending on your current code) |
| 15:12 | justin_smith | ,(some-> "hello" .toUppercase) |
| 15:12 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: toUppercase for class java.lang.String> |
| 15:12 | justin_smith | ,(some-> "hello" .toUpperCase) |
| 15:12 | clojurebot | "HELLO" |
| 15:12 | justin_smith | ,(some-> nil .toUpperCase) |
| 15:12 | clojurebot | nil |
| 15:12 | {blake} | justin_smith: Interesting. I think. =P |
| 15:13 | justin_smith | {blake}: easy enough to turn (.meth O) into (some-> O .meth) and get free short-circuiting on nil |
| 15:13 | ianhedoesit | ,(.toUpperCase "hello") |
| 15:13 | clojurebot | "HELLO" |
| 15:13 | justin_smith | of course this works nicely with chaining |
| 15:13 | ianhedoesit | ,(.toUpperCase nil) |
| 15:13 | clojurebot | #<NullPointerException java.lang.NullPointerException> |
| 15:14 | ianhedoesit | neat |
| 15:14 | {blake} | justin_smith: Yeah...Hmmm. That argues for doing it higher level, I think. Because I can make the least traumatic change that, and it's easy to apply as-needed without making large assumptions about...things. |
| 15:15 | justin_smith | ,(some-> {:a 0} :b inc) ; also useful without interop |
| 15:15 | clojurebot | nil |
| 15:15 | justin_smith | ,(some-> {:a 0} :a inc) |
| 15:15 | clojurebot | 1 |
| 15:17 | {blake} | (inc justin_smith) |
| 15:17 | lazybot | ⇒ 179 |
| 15:27 | muhuk | I have a function that takes a namespace as a keyword like this (foo :bar.baz.foobar), it needs to call some bar.baz.foobar/bat then. But bat is not always named bat, it can be something else for another namespace. How do you suggest I set up the protocol here? |
| 15:27 | muhuk | Having an alias of bat with a fixed name comes to mind: (def that-thing bat) |
| 15:32 | amalloy | muhuk: that seems like a really weird function to write. why do you have a function looking up arbitrary things in arbitrary namespaces represented as keywords? |
| 15:33 | muhuk | amalloy: :) good question |
| 15:34 | Mr0rris0 | maybe its not arbitrary? |
| 15:34 | muhuk | amalloy: it's for a library I'm working on. It provides different backends, and it is extensible |
| 15:34 | muhuk | amalloy: that's why I'm not creating a static table |
| 15:34 | amalloy | okay, so put things in a map? |
| 15:35 | amalloy | namespaces are great for compile-time lookups, and maps are great for runtime lookups |
| 15:35 | AeroNotix | muhuk: you might want to use defgeneric |
| 15:35 | AeroNotix | uhm, defmulti, sorry |
| 15:35 | AeroNotix | too much CL |
| 15:36 | justin_smith | muhuk: why not a map from keyword to implementation? or a defmulti yeah |
| 15:36 | muhuk | amalloy: I think I couldn't describe my situation. fn in question here: https://github.com/muhuk/clecs/blob/master/src/clecs/core.clj I'll take a param to go find the backend. |
| 15:36 | justin_smith | muhuk: the keyword -> symbol -> var-in-ns -> function thing is so indirected |
| 15:37 | muhuk | AeroNotix: that's a cool idea, except it'll be a bit backwards maybe |
| 15:37 | muhuk | justin_smith: hi |
| 15:37 | muhuk | justin_smith: yes, you're right |
| 15:38 | justin_smith | muhuk: depending on your other needs, any number of those steps in the middle could be skipped by just providing the thing it dereferenced to |
| 15:38 | amalloy | muhuk: so like, your caller, whoever is calling this function, has to pass you a namespace they wrote, right? as a keyword, for some reason. and in that namespace there are functions they had to write, yes? |
| 15:38 | justin_smith | eg. providing a symbol instead of keyword, var instead of symbol, function instead of var |
| 15:39 | muhuk | amalloy: they, or 3rd parties. Not known by clecs. |
| 15:39 | AeroNotix | it sounds like you might want a protocol then |
| 15:39 | justin_smith | yeah, I would use a multimethod or protocol, that's exactly what those things are for |
| 15:39 | amalloy | so, it's no more trouble for them to instead pass you a map, which contains the functions that would have been in a namespace |
| 15:39 | AeroNotix | if you know what you're going to call on the object, you pass in an instance of that and call the right methods on it |
| 15:40 | muhuk | justin_smith: suppose I give you a backend, as a lein dep, you'd need to read the source to find out which fn to use. |
| 15:41 | muhuk | justin_smith: but you already know the ns (hopefully) |
| 15:41 | justin_smith | muhuk: why? you pass me something implementing my protocol or multimethod, I call the protocol / multi methods |
| 15:41 | AeroNotix | justin_smith: this |
| 15:41 | justin_smith | muhuk: I don't need to know anything about your ns in order to call implementations of my protocol |
| 15:41 | justin_smith | just pass me the thing that satisfies it and we are good |
| 15:41 | AeroNotix | just a value of something which implements the protocol |
| 15:42 | justin_smith | exactly! |
| 15:42 | muhuk | I don't want the consumer to know anything more than the ns of the backend |
| 15:42 | muhuk | (if I can get away with it) |
| 15:43 | justin_smith | passing a map from keyword to keyword (said keyword needing -> string -> symbol -> var -> deref translation to be used) is just a very inefficient way of doing the same thing |
| 15:43 | AeroNotix | you don't need to know *anything* about the backend at all |
| 15:43 | justin_smith | muhuk: the consumer doesn't need to even know the ns! |
| 15:43 | AeroNotix | muhuk: you already know the operations you want to call on that object, right? |
| 15:43 | justin_smith | muhuk: if you implement my protocol, all I need to know is the methods I defined for my protocol |
| 15:43 | justin_smith | that's it |
| 15:43 | justin_smith | nothing else |
| 15:43 | AeroNotix | muhuk: look up defprotocol |
| 15:44 | justin_smith | (well that plus an instance of a thing that implements it, but how that's done is none of my business as the caller) |
| 15:44 | muhuk | justin_smith: see core.clj, suppose I removed that require |
| 15:44 | justin_smith | muhuk: the caller only needs to know it's protocol |
| 15:44 | justin_smith | muhuk: it can call the protocol methods |
| 15:44 | muhuk | justin_smith: and pass the ns as a symbol or keyword to make-world |
| 15:44 | justin_smith | the object implementing those methods is known because it is anonymously passed in |
| 15:45 | justin_smith | muhuk: why should the caller give a shit about your ns at all? it shouldn't matter |
| 15:45 | AeroNotix | muhuk: make a protocol which mandates `make-world` as a function, pass in a value which implements that |
| 15:45 | justin_smith | muhuk: the implementor shouldn't even need to implement an ns |
| 15:45 | jackhill | I'm having trouble with clooj: I only get a blank window, nothing is drawn in it. Has anyone else seen this? |
| 15:45 | muhuk | justin_smith: ok, how does the consumer call make-world and choose a backend then? |
| 15:45 | justin_smith | muhuk: it doesn't chose a backend, the end user passes one to it |
| 15:46 | muhuk | jackhill: it used to work for me. Any particular reason why you're not using Lighttable? |
| 15:46 | justin_smith | and make-world is a part of the implementor's protocol / is the implementor's multimethod, so they know how to call it |
| 15:47 | muhuk | justin_smith: I don't want the backend to be imported by consumer. How does that work? |
| 15:47 | jackhill | muhuk: I just wanted to try it out, but I suspect something is wrong with my Java setup, so I would like to get that fixed |
| 15:47 | muhuk | you guys are inverting my deps |
| 15:47 | justin_smith | muhuk: why not? they are creating something that is designed around the back-end's needs |
| 15:47 | muhuk | jackhill: probably. Maybe try another GUI app. |
| 15:47 | justin_smith | so why shouldn't they import an interface defined by that backend? |
| 15:48 | jackhill | muhuk: do you have a suggestion? |
| 15:48 | muhuk | jackhill: not really. You can try compiling a minimal swing example maybe. |
| 15:49 | muhuk | justin_smith: not really, backends should be interchangeable. |
| 15:49 | justin_smith | muhuk: make the backends all use the same protocol |
| 15:49 | justin_smith | same idea |
| 15:49 | mmitchell | I want to catch exceptions based on their ex-data contents. Any suggestions for how to do this? An existing library perhaps? Also, are there any plans to provide this sort of thing in clojure core? |
| 15:49 | justin_smith | the backends all use the same protocol, the frontends pass in an instance of a thing implementing said protocol to the backend |
| 15:50 | justin_smith | thus both frontend and backend are fully interchangable |
| 15:50 | justin_smith | muhuk: if you really must use magic keys in a map instead of a formal interface, just use {:f x :g y} etc. where x and y are just functions, don't force people to implement special namespaces |
| 15:51 | muhuk | justin_smith: I still don't like it if the consumer is calling stuff directly on the backends. |
| 15:51 | amalloy | mmitchell: slingshot is basically it, i think. maybe gfredericks has something, called catch-data? |
| 15:51 | muhuk | justin_smith: map doesn't do it either. |
| 15:51 | mmitchell | oh slingshot right! |
| 15:51 | justin_smith | muhuk: the consumer is calling what the implementor explicitly passed to it |
| 15:51 | amalloy | yeah, he totally does |
| 15:51 | mmitchell | will have a look at catch-data too |
| 15:51 | amalloy | i'd try catch-data first |
| 15:51 | mmitchell | cool will do |
| 15:51 | justin_smith | muhuk: doesn't do what? |
| 15:52 | justin_smith | muhuk: are you aware that a namespace is a map from symbols to vars? |
| 15:52 | muhuk | justin_smith: I don't know which backends are available, so I can't create a map. |
| 15:52 | justin_smith | it's just less flexible because we use it in special ways via require and resolution |
| 15:52 | justin_smith | but if you don't need those features, why use an ns? |
| 15:52 | justin_smith | muhuk: I think you are being silly |
| 15:53 | muhuk | well, you can always move on. It's not a first on IRC. |
| 15:54 | justin_smith | muhuk: I wanted to be sure you understood your options, and the extra complexity you are imposing on yourself. If the options are too simple and you prefer the complexity, have at it, hope that's enjoyable to you. No biggie. |
| 15:55 | AeroNotix | boom |
| 15:55 | mmitchell | +1 on catch-data looks nice and simple. Thanks! |
| 16:00 | csd_ | - I'm still confused after watching Stuart Sierra's two videos on components, and reading the example code. At some point I think a global var needs to be defined if you're going to let concurrent threads have access to shared state, no? |
| 16:01 | csd_ | @justin_smith |
| 16:01 | dnolen | ClojureScript now support Nashorn based REPL https://github.com/clojure/clojurescript/commit/d0c9451035d3a9adf9a32e16e759d1e4384268dc |
| 16:01 | justin_smith | csd_: for shared mutable state you can pass an atom to each component |
| 16:01 | amalloy | csd_: no, you can pass those threads whatever state you want without a global |
| 16:01 | justin_smith | csd_: it's not global because it could pass a different atom to a different set of components |
| 16:01 | justin_smith | what amalloy said |
| 16:02 | csd_ | would you be able to put in a pastebin a small sketch of what you mean? |
| 16:02 | tbaldridge | csd_: if you start and stop a system within a single let you can store the state as a local. I do this all the time when writing tests. |
| 16:03 | csd_ | if have a local context, create a ref inside it, and then pass the ref to threads, will one thread's mutation of the ref show up in the other threads ? |
| 16:03 | justin_smith | absolutely |
| 16:04 | justin_smith | wouldn't be much point to refs if it didn't in fact |
| 16:05 | csd_ | ok seems a bit clearer now |
| 16:07 | csd_ | so crudely, the better solution would be something like: (let [state (ref {})] (map #(do-stuff state %) [threads])) |
| 16:07 | justin_smith | csd_: something with that basic outline, yeah |
| 16:07 | csd_ | ok |
| 16:08 | justin_smith | csd_: advantage being, of course, that testing is now much easier |
| 16:08 | justin_smith | if you do it right |
| 16:09 | csd_ | this is one of those concepts that coming from python etc takes a while to get used to |
| 16:09 | amalloy | gfredericks: wait, i remember us talking about the locals-capture feature in catch-data, and you removed it, but i thought you also made throw-data into a function instead of a macro (since it now doesn't have any macro-y features) |
| 16:10 | justin_smith | csd_: it's a place where we have options we can articulate, while imperative languages leave only one way to do it for the most part :) |
| 16:11 | gfredericks | amalloy: well it does have the macro-y feature of not making noise in your stacktrace |
| 16:11 | amalloy | hah. well, fair enough |
| 16:12 | gfredericks | I remember talking about that and the other point was that anybody tring to use throw-data not in the call position is a weirdo |
| 16:12 | justin_smith | us weirdos get no respect |
| 16:14 | amalloy | gfredericks: https://www.refheap.com/d80a9dd79c1374bae013e88a4 |
| 16:14 | amalloy | all this has happened before, and will happen again |
| 16:14 | gfredericks | I look forward to round 3 |
| 16:15 | amalloy | feature request: add to docstring for throw-data: "macro instead of a function to protect you from yourself, you weirdo" |
| 16:16 | gfredericks | patches welcome |
| 16:18 | gfredericks | ~patches is <reply> welcome |
| 16:18 | clojurebot | Roger. |
| 16:18 | Glenjamin | what is throw-data from? |
| 16:19 | Glenjamin | is throw-data just comp throw ex-info ? |
| 16:19 | amalloy | Glenjamin: yes |
| 16:19 | gfredericks | github.com/gfredericks/catch-data |
| 16:19 | Glenjamin | presumably throw being a macro means that doesn't just work |
| 16:19 | gfredericks | throw isn't even a macro but yeah that doesn't work |
| 16:19 | Glenjamin | s/macro/special-form |
| 16:20 | gfredericks | ,(comp throw ex-info) |
| 16:20 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: throw in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 16:20 | gfredericks | ,(let [throw #(throw %)] (comp throw ex-info)) |
| 16:20 | clojurebot | #<core$comp$fn__4458 clojure.core$comp$fn__4458@3fceb526> |
| 16:20 | Glenjamin | makes sense |
| 16:21 | gfredericks | I'm going to go add a comment above (defmacro throw-data) to save amalloy some time next time |
| 16:22 | amalloy | ;; amalloy please stop bothering me, you agreed this should be a macro |
| 16:37 | amalloy | so, i have written two different functions in my config-map-munging file that look like (reduce (partial apply assoc) x y), and i can't decide whether it would be more readable or less if i extracted that out into a function. also i don't know what name i would give to (partial reduce (partial apply assoc)) |
| 16:37 | amalloy | er, assoc-in |
| 16:38 | gfredericks | amalloy: this isn't what reduce-kv is for is it? |
| 16:38 | amalloy | i'm reducing over a seq, not a map |
| 16:38 | amalloy | reducing *into* a map |
| 16:39 | Glenjamin | isn't that (into {}) ? |
| 16:39 | amalloy | Glenjamin: yeah if it were actually assoc (like i first said) it would be. but i'm using assoc-in |
| 16:39 | Glenjamin | right |
| 16:39 | amalloy | on a seq like ([[:x :y] 1] [[:a] 2]) |
| 16:40 | DerGuteMoritz | how about assoc-into |
| 16:40 | amalloy | that's cute |
| 16:40 | DerGuteMoritz | hehe |
| 16:41 | gfredericks | ininto |
| 16:41 | uptown` | is there a lein plugin to profile performance or a way to wrap tests with a profiler to get a sense of how efficient a given form or fn is? |
| 16:42 | tcrayford____ | uptown`: that's intensely difficult on the JVM |
| 16:42 | uptown` | thought so but we live in hope |
| 16:42 | tcrayford____ | generally I'd recommend using FlightRecorder for profiling, and criterium for benchmarking |
| 16:43 | tcrayford____ | e.g. the JVM after the JIT has warmed up, will sometimes completely eliminate benchmark code, etc |
| 16:45 | tcrayford____ | http://docs.oracle.com/javacomponents/jmc-5-4/jfr-runtime-guide/run.htm for flight recorder (assumes you're on an oracle jvm iirc) |
| 16:45 | tcrayford____ | https://github.com/hugoduncan/criterium for criterium |
| 16:45 | tcrayford____ | though note you'll want to turn off leiningen's default jvm options - it turns off most of the advanced JIT optimizations |
| 16:46 | tcrayford____ | (just throw `:jvm-opts ^:replace ["-server"]` in your project.clj, or in a benchmark/profile specific thing) |
| 16:47 | tcrayford____ | note: I've seen perf differences of 5000x times different because of different benchmarking code, different ordering on benchmark runs etc. It's *incredibly* difficult to measure perf numbers on the JVM and have them be useful |
| 16:57 | uptown` | thanks for the pointer |
| 16:57 | uptown` | i'll see if i can get any traction |
| 17:00 | tcrayford____ | uptown`: sure. I'm giving a talk on clojure and performance at a user group tomorrow, so this has been on my mind a bunch lately :) |
| 17:01 | tcrayford____ | uptown`: glad I could help :) |
| 17:03 | Bronsa | tcrayford____: will you upload slides/notes somewhere? I'd be interested :) |
| 17:03 | tcrayford____ | Bronsa: I'll (hopefully) post a video somewhere |
| 17:03 | Bronsa | ah, that's even better |
| 17:06 | justin_smith | tcrayford____: for that 5kx diff, were lazy seqs being forced or not a factor? |
| 17:07 | tcrayford____ | justin_smith: nope, just reordered benchmarks |
| 17:07 | tcrayford____ | like |
| 17:08 | tcrayford____ | (do (bench a) (bench b)) (do (bench b) (bench a)) performs astonishingly differently |
| 17:10 | justin_smith | image of the ancient aliens guy, caption: "hotspot" |
| 17:11 | tcrayford____ | exactly |
| 17:14 | uptown` | *cries* so true |
| 17:24 | TimMc | ~aot |
| 17:24 | clojurebot | aot is Ahead Of Time compilation |
| 17:24 | TimMc | ~aot |
| 17:24 | clojurebot | http://i.qkme.me/3vb225.jpg |
| 17:47 | gfredericks | ~aot |was| so ahead of its time |
| 17:47 | clojurebot | In Ordnung |
| 17:50 | cfleming | dnolen: pong |
| 17:52 | denik | I'm having trouble writing integration tests that depend on channels. For example: I publish 100 messages to rabbitMQ, then, in a go-loop I want to pull each & count to make sure I have 100. |
| 17:53 | denik | This is mostly to make sure the go-loop pulls down every message rather than to test rmq |
| 17:54 | cfleming | tcrayford____: I'd also be very interested in video/slides/notes to your talk |
| 17:55 | dnolen | cfleming: so how do I get Cursive to understand my Clojure Maven project?, also how can I setup a REPL? Do I just need to specify the entire REPL command? Include nrepl? |
| 17:55 | dnolen | cfleming: if this is documented somewhere I'm more than happy to read over the setup |
| 17:56 | hiredman_ | denik: pulling from rabbit mq is blocking io you should not be doing in a go block |
| 17:56 | cfleming | dnolen: Not really documented unfortunately. This is about as good as it gets: https://cursiveclojure.com/userguide/projects.html |
| 17:56 | denik | horedman: how then? |
| 17:57 | denik | hiredman_: I need someway to feed rmq into core.async chans |
| 17:57 | cfleming | dnolen: It should just work. You can set up a REPL using the "Use normal process" option instead of "Run with Leiningen". That does assume nREPL is on the classpath, right. |
| 17:58 | cfleming | dnolen: That basically starts a Java process with the classpath of the module you select, and starts an nREPL server |
| 17:59 | cfleming | dnolen: Actually, I lie - it will automatically add the version of nREPL shipped with Cursive to the classpath. |
| 18:00 | cfleming | dnolen: So you should just be able to run it. |
| 18:00 | dnolen | cfleming: what Module am I supposed to be selecting? "Java"? |
| 18:01 | cfleming | dnolen: Right, you set it up as a Java project |
| 18:01 | cfleming | dnolen: But do you already have a Maven project you want to import? |
| 18:01 | dnolen | cfleming: yes it's a pre-existing Maven project |
| 18:02 | dnolen | cfleming: so I should import it? |
| 18:02 | cfleming | dnolen: Ok, then you want File->Import project, Import from external model, Maven, then follow the options |
| 18:13 | cfleming | dnolen: Back in a bit - if that doesn't work, let me know the steps you're trying and I'll try to reproduce. I'll update that doc too, since a few people are using Maven now |
| 18:14 | dnolen | cfleming: ok so I imported but the same thing always happens for me, nothing is resolveable |
| 18:14 | dnolen | cfleming: i.e. the source code |
| 18:14 | AeroNotix | Which kafka client do people recommend/ |
| 18:14 | dnolen | is all highlighted |
| 18:14 | AeroNotix | ? |
| 18:15 | cfleming | dnolen: Has it created source dirs in the right places? Blue folders in the project view? |
| 18:15 | AeroNotix | people are using just maven for clojure? |
| 18:15 | dnolen | cfleming: blue java folder but not a blue clj one |
| 18:15 | dnolen | AeroNotix: yes |
| 18:15 | AeroNotix | dnolen: why? |
| 18:15 | dnolen | AeroNotix: lots of reasons |
| 18:16 | cfleming | AeroNotix: It just works, I guess |
| 18:16 | AeroNotix | dnolen: such as? |
| 18:16 | dnolen | AeroNotix: I'm not going to enumerate them for you |
| 18:16 | AeroNotix | :( |
| 18:16 | cfleming | dnolen: If you mark the folder as source, are things resolved correctly? Right click, mark as source |
| 18:16 | AeroNotix | I'm genuinely curious what I might be missing out |
| 18:16 | AeroNotix | on |
| 18:16 | cfleming | dnolen: Sorry, right click, mark directory as, source |
| 18:17 | dnolen | cfleming: ok that fixed that thanks! |
| 18:17 | amalloy | AeroNotix: better integration with a zillion java tools is one thing, i imagine |
| 18:17 | AeroNotix | amalloy: such as the IDEs and things? |
| 18:17 | cfleming | dnolen: What you'll find is that that source folder will be removed next time your project is synced |
| 18:17 | cfleming | dnolen: You'll have to add something to your POM so that Maven knows that's a source root |
| 18:18 | cfleming | dnolen: Whatever the :source-paths Maven equivalent is |
| 18:20 | cfleming | dnolen: Actually, check the Clojure project for inspiration, looks like it uses a Clojure Maven plugin to do that |
| 18:20 | dnolen | cfleming: hrm REPL interactions don't work |
| 18:20 | dnolen | I mean the REPL works |
| 18:20 | dnolen | but commands to send stuff to the REPL don't |
| 18:24 | dnolen | cfleming: ok got it working, a little weird but this is good enough for me |
| 18:25 | cfleming | dnolen: What did you have to change? |
| 18:25 | cfleming | dnolen: For the REPL, I mean? |
| 18:26 | dnolen | cfleming: I think I had to exclude some directories? |
| 18:27 | cfleming | dnolen: That sounds strange - normally it should just require an open active REPL, and to be doing it from a Clojure source file |
| 18:29 | dbronico | hey all. i'm new to cljs and am wondering what the idiomatic way to store the response from an xhr call would be in cljs without the callback function being a giant function with all of the program logic. |
| 18:30 | dnolen | cfleming: anyways this is good enough for me, after all this time in Cursive for ClojureScript dev now I just want to use it all the time |
| 18:30 | dnolen | dbronico: you should look into core.async |
| 18:30 | amalloy | cfleming: put dnolen's testimonial on your website somewhere |
| 18:31 | raspasov | cfleming: I've always been connecting to a remote REPL (running in a terminal window) and it works great for me; just trying to run a local version to test out the break points etc - I believe it has to run locally right? |
| 18:32 | dbronico | dnolen: I actually was, but was a little stuck on how to store. like, do this async thing and put it on the channel, but I can't have below it, (def xhr-response (take! the-chan)), can I? |
| 18:33 | raspasov | just trying to make it work with https://github.com/ninjudd/lein-protobuf , for some reason the protocol buffer classes don't get added to the classpath I believe and I get CompilerException java.lang.ClassNotFoundException when try to run locally |
| 18:33 | dnolen | dbronico: you can as long as you're in a go block |
| 18:33 | raspasov | maybe it doesn't play nicely with the leiningen plugin somehow? |
| 18:33 | dbronico | dnolen: oh, ok. and then I can use xhr-response outside of the go block? |
| 18:34 | cfleming | dnolen: Great, good to hear :-) |
| 18:34 | dnolen | dbronico: by storing it somewhere sure |
| 18:34 | cfleming | dnolen: I have a build coming out in the next day or two, hopefully the following one will have CLJS REPLs based on all the new hotness |
| 18:35 | dnolen | dbronico: you might want to ask your question in the #clojurescript channel, show us the JS code you would write and someone can show you how to do it better in core.async |
| 18:35 | dnolen | cfleming: sweet! |
| 18:35 | dbronico | dnolen: oh, ok. i didn't know it had a dedicated chan. thanks! |
| 18:36 | cfleming | raspasov: No, you can run it remotely too, but you'll have to create a remote debug connection. Run->Edit Configurations->+->Remote, then start your JVM with the parameters it shows you |
| 18:36 | cfleming | raspasov: Connect the remote debugger then the remote REPL, all should work |
| 18:36 | raspasov | cfleming: oh great, that's cool, let me try |
| 18:36 | cfleming | raspasov: Someone confirmed on the mailing list the other day that that works, let me know if you have problems |
| 18:43 | raspasov | cfleming: "Run->Edit Configurations->+->Remote, then start your JVM with the parameters it shows you" - are there special parameters I need to add when running lein repl? |
| 18:45 | cfleming | raspasov: Yeah, where it says "Command line arguments for running remote JVM" you need to add those to your JVM startup, in your project.clj |
| 18:46 | raspasov | hm I don't see that, could it be because I'm on 13.1 ? |
| 18:50 | raspasov | http://i3.minus.com/iXvgpqOA3r2J7.png |
| 19:08 | trptcolin | how (if at all) does one get korma (with the postgres jdbc adapter) to tell them how many rows got updated? |
| 19:09 | trptcolin | seems like i always get a single record (if any were updated) or an empty seq |
| 19:09 | trptcolin | w/ no way to see how many succeeded |
| 19:09 | tcrayford____ | trptcolin: are you using RETURNING ? |
| 19:10 | trptcolin | oh clojure.java.jdbc is all good |
| 19:10 | tcrayford____ | oh ok :/ |
| 19:11 | trptcolin | well, "all good" meaning there exists some path where i can get what i want |
| 19:11 | trptcolin | yeah... i really like the idea of being able to share pieces of queries, something something composable something |
| 19:12 | trptcolin | but every library is frustrating when i'm in the internals trying to figure out a monkeypatch to make it work like i want :) |
| 19:12 | {blake} | I tried Korma on Friday, along with Yesql, and I'm using straight JDBC. |
| 19:12 | raspasov | ORM = OMG :) |
| 19:13 | rhg135 | indeed |
| 19:13 | tcrayford____ | trptcolin: sorry I can't help more :( |
| 19:13 | trptcolin | tcrayford____: no worries, thanks for the try :) |
| 19:14 | cfleming | raspasov: That's the remote REPL - the config you want is just called "Remote", it's for remote debugging |
| 19:15 | cfleming | raspasov: You need two connections to the remote JVM - the debugger and the REPL |
| 19:15 | raspasov | cfleming: ah got it, I'm blind |
| 19:15 | {blake} | cfleming: As long as you're hanging around...what's the magic for starting the debugger? |
| 19:15 | raspasov | /don't follow instructions carefully/ lol |
| 19:16 | raspasov | I'm sure cfleming is having a hard time working with all of asking questions :-) |
| 19:16 | raspasov | all of us* |
| 19:16 | {blake} | I hardly see how we can be held accountable for a lack of adequate cloning technology. |
| 19:18 | raspasov | haha well |
| 19:22 | AeroNotix | ok what's the deal with lazy-seqs |
| 19:22 | AeroNotix | I have found some code which blocks outside of a lazy-seq, but works inside of one |
| 19:22 | AeroNotix | "works" |
| 19:22 | amalloy | AeroNotix: ? |
| 19:23 | AeroNotix | hmm |
| 19:23 | AeroNotix | it's 1:21am |
| 19:23 | AeroNotix | Should I be doing this.... |
| 19:26 | noonian | AeroNotix: what do you mean 'works inside' of lazy-seq? if you aren't every realizing the lazy seq it might just never be executing the blocking code |
| 19:26 | AeroNotix | noonian: yeah that's what I just realised |
| 19:27 | noonian | heh |
| 19:27 | AeroNotix | this is inside a library |
| 19:28 | noonian | what library/code? |
| 19:28 | AeroNotix | clj-kafka |
| 19:30 | AeroNotix | I actually can't get it to read messages out of a kafka queue for some reason |
| 19:30 | AeroNotix | and the laziness inside the read with clj-kafka covered up something for a while |
| 19:32 | TimMc | Ugh, just got bit by http://dev.clojure.org/jira/browse/CLJ-1232 |
| 19:32 | noonian | sounds frustrating. I have zero experience with kafka so probably can't be much help. If you posted some code snippets someone might notice something funky. |
| 19:32 | AeroNotix | noonian: just run of the mill stuff really. Straight out the README. |
| 19:32 | TimMc | (defn foo ^Hint [] ...) fails when a.b.Hint is not imported in the namespaces that *calls* that fn. |
| 19:33 | cfleming | raspasov: If it weren't for you people I'd be at version 7 by now, instead of still in beta :) |
| 19:33 | AeroNotix | TimMc: :( |
| 19:33 | raspasov | cfleming: lol |
| 19:33 | cfleming | {blake}: Are you having problems starting the debugger? |
| 19:33 | {blake} | cfleming: Yes! Uh...where is it? =P |
| 19:33 | cfleming | raspasov: Actually, that's mostly true of my daughter rather than tech support |
| 19:34 | cfleming | {blake}: Haha, I see |
| 19:34 | raspasov | raspasov: haha well |
| 19:34 | raspasov | cfleming: haha well |
| 19:34 | cfleming | {blake}: See here under Starting a debug REPL: https://cursiveclojure.com/userguide/repl.html |
| 19:35 | cfleming | {blake}: There's no real doc on this at the moment, in the meantime you can try https://confluence.jetbrains.com/display/IntelliJIDEA/Debugger |
| 19:35 | cfleming | {blake}: That's Java specific but mostly relevant |
| 19:35 | cfleming | There are bugfixes for the debugger in the next build too |
| 19:36 | {blake} | cfleming: Oh, okay, cool, I'll give it a shot. I didn't think that would work. |
| 19:36 | {blake} | cfleming: When are we going to be able to buy? |
| 19:36 | cfleming | {blake}: Yeah - make sure you're on 0.1.44, lots of fixes there |
| 19:36 | cfleming | {blake}: Not sure, but the shortlist for a version 1 is getting shorter |
| 19:37 | {blake} | cfleming: Cool. Yeah, I'm up-to-date. |
| 19:45 | andyf | TimMc: Fortunately clj-1232 has a pretty easy workaround - add import, or edit function to fully qualify the type. I was going to recommend voting, but see you already have |
| 19:46 | cfleming | TimMc andyf: The other workaround is to type hint the var, not the args vector |
| 19:47 | TimMc | andyf: Easy, but annoying and bloaty. Also, I'm annoyed at Rich for saying it shouldn't be fixed at all. |
| 19:48 | cfleming | TimMc: Yeah, I hate that bug. |
| 19:49 | cfleming | TimMc: Fortunately type hinting the var works fine, so that's what I do everywhere. |
| 19:49 | cfleming | TimMc: With an imported class, I mean. |
| 19:56 | TimMc | cfleming: I found if I put a newline after the arity hint it's not so bad -- it increases vertical space use, but at least the giant Java class names don't push the arglist waaaay over. |
| 19:56 | cfleming | TimMc: Any reason you don't want to hint the var? |
| 20:00 | OldTree | is it possible to use Om's transact function outside of a component? |
| 20:01 | amalloy | yeah, hinting the var is the thing you're supposed to do |
| 20:02 | amalloy | i basically regard hinting the argvector with a non-primitive type to be an accidental feature and am not terribly surprised when it doesn't work |
| 20:02 | hiredman_ | which is hilarious, because it used to not work at all, until someone tried to unify the two ways to hint the return type |
| 20:03 | cfleming | amalloy: I'd say based on the doc, you're *supposed* to hint the arg vector, but no-one does because of this bug |
| 20:03 | amalloy | what doc? |
| 20:04 | cfleming | amalloy: http://clojure.org/java_interop#Java%20Interop-Type%20Hints |
| 20:04 | cfleming | "For function return values, the type hint can be placed before the arguments vector:" |
| 20:05 | cfleming | The doc for fn and defn make no mention of type hints at all |
| 20:06 | cfleming | I guess the only advantage is that you can hint individual arities differently |
| 20:07 | cfleming | Although IMO that's probably bad, or at least confusing, form anyway |
| 20:15 | gfredericks | dangit I'm writing a little data diff/patch library |
| 20:15 | gfredericks | how could this have happened. |
| 20:15 | dangit | Are you taking my name in vain? |
| 20:16 | gfredericks | no in vein |
| 20:16 | gfredericks | also sometimes in vane |
| 20:21 | cfleming | I've always wondered who someone is - they must get pinged a lot |
| 20:22 | amalloy | hey, speaking of, whatever happened to the guy named so? |
| 20:22 | amalloy | $karma so |
| 20:22 | lazybot | so has karma -33. |
| 20:29 | gfredericks | oh is that why so gets dec'd |
| 20:30 | amalloy | gfredericks: yeah, numerous times i heard people complain that he kept making the word "so" get the username-highlight treatment in their clients |
| 20:31 | gfredericks | (dec so) ; serves him or her right |
| 20:31 | lazybot | ⇒ -34 |
| 20:40 | gfredericks | there we go https://github.com/gfredericks/minus |
| 20:40 | gfredericks | now it just needs a decent algorithm or two |
| 20:41 | amalloy | ahaha that algorithm. too good |
| 20:42 | gfredericks | hey man it works great and anybody can understand it |
| 20:42 | amalloy | i was like, wow, what algorithm could be correct but trivial |
| 20:42 | amalloy | question answered |
| 20:56 | justin_smith | gfredericks: seeing the defmulti for diff, I expected something using data.diff at first |
| 20:57 | justin_smith | (inc dangit) |
| 20:57 | lazybot | ⇒ 1 |
| 21:12 | gfredericks | justin_smith: well it could but that would be an impl detail |
| 21:27 | dnolen | https://github.com/omcljs/om |
| 21:29 | julianleviston | Building a thing to run n things in “parallel” using core.async go blocks… but I want the results to be co-ordinated into a set of results and the main body to block until the results are in, at which time it does something contingent on them finishing. This code is currently sitting in a doseq block… is there a nice way to do this? What would you call this? is it fanning? I can only think of doing it via a bunch |
| 21:29 | julianleviston | n go blocks, then a blocking loop that takes n values off a “results chan”… is that a good way? |
| 21:37 | julianleviston | Maybe I’ll take a stab at that and see what happens. |
| 21:38 | justin_smith | between "doing it via a bunch" and "n go blocks" I think your irc client ate something |
| 21:43 | julianleviston | I wrote: Building a thing to run n things in “parallel” using core.async go blocks… but I want the results to be co-ordinated into a set of results and the main body to block until the results are in, at which time it does something contingent on them finishing. This code is currently sitting in a doseq block… is there a nice way to do this? What would you call this? is it fanning? I can only think of doing it vi |
| 21:43 | julianleviston | bunch of n go blocks, then a blocking loop that takes n values off a “results chan”… is that a good way? |
| 21:43 | amalloy | julianleviston: there is a maximum length to the length of an IRC message |
| 21:44 | justin_smith | julianleviston: your message is cut off (even eariler this time) |
| 21:44 | amalloy | your client doesn't seem to know what it is |
| 21:44 | julianleviston | Maybe my expressions capacity got broken |
| 21:44 | julianleviston | ah.... |
| 21:44 | julianleviston | That’s weird. |
| 21:44 | julianleviston | lol |
| 21:44 | julianleviston | Building a thing to run n things in "parallel" using core.async go blocks, but I want the results to be co-ordinated into a set of results and the main body to block until the results are in, |
| 21:44 | julianleviston | at which time it does something contingent on them finishing. |
| 21:45 | julianleviston | This code is currently sitting in a doseq block. Is there a nice way to do this? What would you call this? is it fanning? |
| 21:45 | julianleviston | I can only think of doing it via a bunch of n go blocks, then a blocking loop that takes n values off "a results chan"... is that a good way? |
| 21:45 | julianleviston | Hopefully all that came thru :) |
| 21:45 | julianleviston | (it may have been due to strange chars I was typing) |
| 21:46 | justin_smith | julianleviston: that idea looks perfectly reasonable (now that I know there is nothing insane hiding in the truncating part) |
| 21:46 | julianleviston | haha :) |
| 21:46 | julianleviston | ok thanks. |
| 21:46 | justin_smith | julianleviston: a function that spawns one of the worker go blocks |
| 21:46 | justin_smith | and then a go block that sends your inputs to those channels, and then waits on all of them coming back, perhaps with a timeout or whatever |
| 21:47 | justin_smith | that is, function that spawns the worker go blocks, then run it N times etc. |
| 21:50 | julianleviston | yep. Just seems a little clunky to write it myself. I kind of assumed there would be prior work... like ?oh, that?s a fanning pattern, just use the fan function from blah blah? or something... |
| 21:51 | julianleviston | but I’m halfway done writing it so, all good :) |
| 21:51 | justin_smith | julianleviston: oh yeah, that likely exists, I can't name the function though |
| 21:51 | justin_smith | haha |
| 21:52 | drsco | julianleviston: have you looked at pipeline or pipeline-async? |
| 21:52 | julianleviston | drsco: do they work on cljs? |
| 21:53 | drsco | yep |
| 21:53 | julianleviston | drsco: I did look at them and followed a tute oh them… but I wasn’t sure coz the tute was for clj, not cljs. |
| 21:53 | drsco | used pipeline-async yesterday |
| 21:53 | julianleviston | drsco: ah ok. cool… that sounds like it’d be helpful... |
| 21:53 | julianleviston | I find the dox a bit… terse. |
| 21:53 | drsco | yeh, i didn't see that mentioned on the clojure docs either, but i found some docs elsewhere that did mention. lemme see if i can find the link. |
| 21:54 | julianleviston | good if you know what they’re talking about... |
| 21:54 | drsco | for sure. precise, but hard to puzzle the use case unless you've seen it before. |
| 21:55 | julianleviston | drsco: no, not really… I think it’s hard to even see the use case sometimes, even if you’ve had it before... |
| 21:55 | drsco | julianleviston: check this http://www.core-async.info/reference/apidocs#pipeline_async |
| 21:56 | julianleviston | drsco: until you’ve built it yourself… then you’re like… “oh… this thing here!” |
| 21:56 | julianleviston | yeah that site is great! |
| 21:56 | drsco | page is slow. painful client side rendering, but nice looking. |
| 21:56 | julianleviston | ironically for about 2 weeks I could never get it to load on safari… works fine on chrome tho. |
| 21:56 | drsco | i like how it breaks out the clojure and cljs source. very handy. |
| 21:57 | drsco | weird. looks like maybe it's polymer or material design type of thing. probably relying on something slightly experimental. |
| 21:57 | julianleviston | drsco: isn’t it the same as the main clojure site for core async? |
| 21:57 | julianleviston | drsco: I really don’t undrestand what the desc of pipeline-async means. :( |
| 21:57 | drsco | the part from the docstring is. no inlined source on clojure docs i don't think. |
| 21:58 | julianleviston | drsco: ah ok. |
| 21:58 | drsco | hmm...well i think it does what you're asking for. let me see if i can break it down. i'm pretty new to this still. |
| 21:58 | julianleviston | drsco: I guess pipeline-async handles the “paralleling |
| 21:58 | julianleviston | “paralleling” part... |
| 21:59 | julianleviston | and then I’d write a doseq n underneath that blocked the main go block until I had all the results in? |
| 21:59 | justin_smith | julianleviston: yeah, it does the fanning out, and then you can then feed it into your own fan in (via the design of the function parallelized) |
| 21:59 | julianleviston | got it. |
| 22:00 | drsco | right, af is a transducer that runs on the fan in part. |
| 22:00 | julianleviston | um… |
| 22:00 | julianleviston | it is? |
| 22:01 | julianleviston | I’m not confident I can write a transducer, and that’s not what the doc says. |
| 22:01 | drsco | it could just be a simple 1-to-1, but it doesn't have to be |
| 22:01 | drsco | wait, i'm wrong. my mistake |
| 22:01 | julianleviston | I’ve looked quite a bit into transducers, but they’re complex. |
| 22:01 | julianleviston | drsco: phew! :) |
| 22:01 | julianleviston | ironically it’s complex to understand them because they’re so simple. |
| 22:02 | drsco | af is the async function. derp. |
| 22:02 | julianleviston | yay! :) |
| 22:02 | JustinusIII | does transducers require understanding of reducers? |
| 22:02 | drsco | but using them isn't so tricky. |
| 22:02 | drsco | http://matthiasnehlsen.com/blog/2014/10/06/Building-Systems-in-Clojure-2/ |
| 22:02 | julianleviston | drsco: using tranducers is easy. Making them is tricky. |
| 22:02 | drsco | i enjoyed that article a lot. nice graphic. |
| 22:02 | justin_smith | JustinusIII: not really - transducers are stackable transformations you can put on some source of data |
| 22:03 | justin_smith | julianleviston: uhm (filter isafoo?) is a transducer |
| 22:03 | justin_smith | julianleviston: or (map frob-it) |
| 22:03 | justin_smith | ,(type (map even?)) |
| 22:03 | clojurebot | clojure.core$map$fn__4507 |
| 22:03 | julianleviston | justin_smith: sorry I mean making a function that creates transducers. |
| 22:03 | justin_smith | ,(fn [] (map even?)) |
| 22:03 | clojurebot | #<sandbox$eval49$fn__50 sandbox$eval49$fn__50@799b710e> |
| 22:03 | justin_smith | :P |
| 22:04 | justin_smith | julianleviston: they may seem weird, but they are not actually super hard |
| 22:04 | drsco | and they're composable with comp, stackable as you said |
| 22:04 | julianleviston | justin_smith: what do you call functions that create transducers? |
| 22:04 | justin_smith | right. They do what I expected eg. nested usage of map to do when I first learned clojure |
| 22:05 | justin_smith | ,(sequence (comp (filter even?) (map inc)) (range 10)) |
| 22:05 | clojurebot | (1 3 5 7 9) |
| 22:05 | justin_smith | there's a pair of transducers composed and applied to a lazy-seq |
| 22:05 | TEttinger | it's weird how comp is in reverse order here |
| 22:05 | TEttinger | or not reversed I guess |
| 22:05 | justin_smith | TEttinger: middleware style :) |
| 22:06 | drsco | yeh, it's mindbending |
| 22:06 | drsco | just a little |
| 22:06 | julianleviston | justin_smith: yeah, the thing that is hard is creating your own transducer factory. |
| 22:06 | justin_smith | julianleviston: when do you need to do that? |
| 22:07 | julianleviston | justin_smith: when you want to write map, or something different than the provided ones. |
| 22:07 | drsco | julianleviston: take a look at the streaming-buffer example in the link i posted above |
| 22:07 | julianleviston | drsco: why? |
| 22:07 | drsco | or log-count in the same one, that one is a bit simpler |
| 22:08 | justin_smith | OK, but one main point of transducers is not needing to implement eg. map over and over - you just pull in the transducers that have them all defined |
| 22:08 | drsco | it describes how to make your own transducing function |
| 22:08 | JustinusIII | reducers in Joy Of Clojure 2 was scary....I didn't have the courage to look into transducers after that |
| 22:08 | justin_smith | JustinusIII: I think it's much easier when you get to a point where you've done the stuff they abstract over enough times to realize the benefit |
| 22:09 | julianleviston | drsco: I’m pretty familiar wth transducer usage. |
| 22:09 | julianleviston | drsco: just not the nomenclature... |
| 22:09 | drsco | ah, ok, got it. |
| 22:09 | julianleviston | drsco: aparently. |
| 22:09 | julianleviston | drsco: so map is an example of a transducing function? |
| 22:10 | julianleviston | drsco: a “tranducing function” is any function that has a single-arity that produces a transducer, yes? |
| 22:10 | drsco | perhaps i'm not using the right nomenclature either. should probably verify. |
| 22:10 | justin_smith | julianleviston: if you provide one arg, yes |
| 22:10 | JustinusIII | justin_smith: hmmm....what are the best resources to learn transducers? |
| 22:10 | justin_smith | julianleviston: the single arg thing isn't a pre-req |
| 22:10 | julianleviston | justin_smith: that’s a single arity, is it not? |
| 22:10 | julianleviston | justin_smith: ah ok. |
| 22:11 | justin_smith | julianleviston: right, but the arg count is an implementation detail is all I am saying |
| 22:11 | julianleviston | I think rich hickey’s trandsucer talks are the best. He explains well. |
| 22:11 | justin_smith | a transducer with two or three args could exist, as long as it has the right behaviors |
| 22:11 | drsco | justin_smith: because map, filter, et al already had two and three arity versions, right? |
| 22:11 | justin_smith | I like this talk by Rich Hickey on transducers. Opens with the classic burrito joke. https://www.youtube.com/watch?v=6mTbuzafcII |
| 22:12 | justin_smith | drsco: right |
| 22:12 | justin_smith | julianleviston: he gives a really nice intro to what the point of transducers is |
| 22:13 | justin_smith | julianleviston: even just the first couple minutes is very informative |
| 22:13 | julianleviston | justin_smith: it is a great talk. As is the precursor talk... |
| 22:13 | julianleviston | I really liked his core async ones, too... |
| 22:13 | julianleviston | plus, this page is obviously pretty useful… http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming |
| 22:20 | julianleviston | god I can never remember which of <! or >! is which, or which order they go in. GUH |
| 22:21 | justin_smith | julianleviston: in a let block, the > or < will point in the direction the data is going |
| 22:21 | julianleviston | justin_smith: that makes no sense. |
| 22:21 | julianleviston | justin_smith: sorry, but these things always depend on your perspective, and mine isn’t fixed. |
| 22:21 | justin_smith | so (let [result (<! c)] ...) |
| 22:21 | julianleviston | justin_smith: again… that doesn’t help. |
| 22:21 | justin_smith | that means c has contents going into result |
| 22:22 | justin_smith | OK |
| 22:22 | julianleviston | justin_smith: yeah, I know when I look it up, but what’s to say that it’s pointing to the data, or the channel? |
| 22:22 | julianleviston | justin_smith: lol :) |
| 22:22 | justin_smith | julianleviston: the arrow points in the direction the data moves |
| 22:22 | justin_smith | > means left to right |
| 22:23 | justin_smith | < means right to left |
| 22:23 | julianleviston | justin_smith: in relation to what, positionally? |
| 22:23 | julianleviston | justin_smith: the syntax of clojure? |
| 22:23 | justin_smith | the thing that gets the data, and the thing that sends it |
| 22:23 | justin_smith | right |
| 22:23 | rerb | Newbie alert. I want to swap a couple of values in a vector. What's the idiomatic way of going from, e.g., [1 2 3 4] to [1 3 2 4]? |
| 22:23 | julianleviston | ok… so !> chan is put? |
| 22:23 | justin_smith | the binding in the let block will be to the left of the (<! call) |
| 22:23 | justin_smith | right |
| 22:23 | gfredericks | rerb: an assoc call |
| 22:24 | justin_smith | because the place the data is going is to the right of >! |
| 22:24 | gfredericks | (defn swap [m k1 k2] (assoc m k1 (get m k2) k2 (get m k1))) |
| 22:24 | julianleviston | so <! means takne? |
| 22:24 | amalloy | !> doesn't exist, it's >! |
| 22:24 | julianleviston | take* |
| 22:24 | justin_smith | julianleviston: right |
| 22:24 | julianleviston | gfredericks: don’t def swap! |
| 22:24 | gfredericks | okay |
| 22:25 | julianleviston | gfredericks: IMHO. |
| 22:25 | rerb | gfredericks - thanks |
| 22:25 | gfredericks | np |
| 22:25 | julianleviston | amalloy: see my problem? lol |
| 22:25 | julianleviston | it’s fine… just annoying |
| 22:25 | amalloy | *shrug* everyone has to figure out their own mnemonics |
| 22:25 | julianleviston | amalloy: exactly. That’s the problem. |
| 22:25 | gfredericks | we need to standardize on mnemonics |
| 22:25 | amalloy | how do you keep + and * straight? |
| 22:25 | julianleviston | amalloy: I’ve never once had to look up put or take tho... |
| 22:26 | amalloy | they're both crossy mathy things |
| 22:26 | gfredericks | (inc amalloy) |
| 22:26 | julianleviston | amalloy: it’s not quite the same, actually… |
| 22:26 | lazybot | ⇒ 220 |
| 22:26 | amalloy | both make numbers bigger |
| 22:26 | julianleviston | amalloy: - and + would be a better example/ |
| 22:26 | julianleviston | amalloy: and the’re clearly different. |
| 22:26 | TEttinger | yeah, and I always mess up my addition and tetration operators |
| 22:26 | justin_smith | amalloy: or even > and < in a math context :) |
| 22:26 | julianleviston | + has more strokes than - |
| 22:27 | gfredericks | I'm always confusing unchecked-byte with alter-var-root |
| 22:27 | julianleviston | justin_smith: > and < is a better example. the big part is linguistically on the left… we say “5 is greater than 3” |
| 22:27 | julianleviston | lol… ok maybe I’m being a douche… point taken. |
| 22:27 | amalloy | julianleviston: justin_smith was trying to give you an analogous mnemonic |
| 22:28 | amalloy | but instead of stopping to think about it you immediately reponded "that makes no sense" |
| 22:28 | julianleviston | amalloy: I value his help, and what I was annoyed about wasn’t him. |
| 22:28 | julianleviston | amalloy: I have thought about it a fair bit, actually :) I’m not flaming at the moment. |
| 22:29 | justin_smith | julianleviston: in general, in data-flow or related types of frameworks, you often see some kind of "arrow" as an operator that indicates which direction your data is flowing in a given statement |
| 22:29 | justin_smith | > and < are popular constituent characters for "flow of data" arrows |
| 22:30 | TimMc | cfleming: Hinting the var with a classname looks icky. :-P (It makes it a little harder to read.) |
| 22:30 | julianleviston | justin_smith: yeah, I know this. I’m not debating the logic of using it. I just generally expect Rich to make saner decisions than “the majority did it that way”. |
| 22:30 | justin_smith | OK |
| 22:30 | julianleviston | at the end of the day it doesn’t matter, tho… I’ll just be quiet. It’s just syntax. |
| 22:31 | julianleviston | Oh… the pling is the pling of “whatchout”? |
| 22:31 | justin_smith | general question: would people hate you for remapping <! and >! to more verbose names in your code? |
| 22:31 | justin_smith | julianleviston: the bang? yeah |
| 22:31 | julianleviston | justin_smith: It’s cool… I want to use the condoned names. Thanks for being so supportive… :) |
| 22:31 | TimMc | _GT__BANG_ is a good choice |
| 22:31 | julianleviston | justin_smith: revelation! |
| 22:31 | TimMc | but not for both |
| 22:31 | TimMc | hmmm |
| 22:31 | justin_smith | (inc TimMc) |
| 22:31 | lazybot | ⇒ 89 |
| 22:31 | julianleviston | lol |
| 22:31 | TimMc | I have karma for the stupidest things. |
| 22:32 | julianleviston | (inc TimMc) |
| 22:32 | lazybot | ⇒ 90 |
| 22:32 | TimMc | amalloy has karma for actually helping people |
| 22:32 | justin_smith | I've likely got an even mix |
| 22:32 | julianleviston | (dec julianleviston ) |
| 22:32 | lazybot | ⇒ -1 |
| 22:33 | julianleviston | clojureland is so pretty :) <3 |
| 22:33 | amalloy | i like to imagine that the ! is the channel |
| 22:33 | justin_smith | oh, nice :) |
| 22:33 | amalloy | stuff being pushed into it, squeezed out of it, via the <> |
| 22:34 | julianleviston | amalloy: yeah, I used to do that, too… then I forgot which side it went on. LOL. But now I undrestand it’s the bang of danger, I can always know. |
| 22:38 | julianleviston | drsco: thanks for the help, the async fanning worked nicely. I should probably rewrite it to use pipeline now tho… because I have unlimited width… which is not good. I like the pipeline fn which requires a parallelism argument… mine just fans infinitely. |
| 22:40 | raspasov_ | julianleviston: are you using core async pipelines? |
| 22:40 | julianleviston | raspasov_: I’m about ti. |
| 22:40 | julianleviston | to* |
| 22:41 | raspasov_ | Cool I use them as well |
| 22:41 | raspasov_ | Pretty good, you know about the pipeline vs pipeline-blocking? |
| 22:41 | julianleviston | raspasov_: not really… do tell :) |
| 22:41 | julianleviston | raspasov_: the doc says “same but blocking” lol :) |
| 22:42 | raspasov_ | Depending on the type of operations you are going to do |
| 22:42 | raspasov_ | If there's going to be blocking IO calls basically use blocking otherwise you are going to exhaust the limited core async thread pool potentially fast |
| 22:43 | justin_smith | amalloy: gfredericks: thanks for the laugh |
| 22:43 | amalloy | you're welcome |
| 22:43 | amalloy | i think if obtainance were a word it would quickly degrade to obtenance, so i can't advocate that choice |
| 22:44 | julianleviston | raspasov_: the work I’m doing is caching some data… |
| 22:45 | gfredericks | catch-data! |
| 22:45 | julianleviston | lol. |
| 22:45 | raspasov_ | Caching data in memory? |
| 22:45 | raspasov_ | On the same machine? |
| 22:45 | julianleviston | raspasov_: yissir! |
| 22:45 | julianleviston | raspasov_: in cljs, tho. |
| 22:46 | raspasov_ | Oh |
| 22:46 | raspasov_ | I'm pretty sure there's no blocking there |
| 22:46 | julianleviston | raspasov_: yeah, no core.cache for me. |
| 22:46 | raspasov_ | It's only one thread |
| 22:46 | julianleviston | raspasov_: yeah. |
| 22:47 | julianleviston | it’s only a tiny memoizationy kind of cache anyway. |
| 22:47 | raspasov_ | Ok well I don't even know if you really get any benefit from pipelining on cljs? |
| 22:47 | julianleviston | raspasov_: just wanted to make sure I didn’t do it in sequence too much or it takes too ages. |
| 22:47 | julianleviston | raspasov_: I don’t either! :) |
| 22:48 | raspasov_ | Yea you should benchmark with and without |
| 22:48 | julianleviston | raspasov_: I’m experimenting… but it seems to be faster with my fanning in place… |
| 22:48 | julianleviston | raspasov_: at this stage I’d be happy if my UI didn’t block. |
| 22:48 | raspasov_ | Yea I have no experience with pipeline on cljs |
| 22:49 | raspasov_ | That's always good to avoid ! :) |
| 22:49 | raspasov_ | You building a web app? |
| 22:50 | Lewix | hello all |
| 22:51 | Lewix | https://gist.github.com/6ewis/f86d3c0721e79197712c - please some insight |
| 22:51 | drsco | julianleviston: glad to hear it's working out |
| 22:51 | julianleviston | raspasov_: yeah, a really difficult one. |
| 22:51 | julianleviston | raspasov_: Well, for me… seeing as it has been my first clojure app… |
| 22:51 | julianleviston | raspasov_: rewriting it from Ember. |
| 22:51 | raspasov_ | Difficult = learning = good ;) |
| 22:51 | julianleviston | raspasov_: indeed! |
| 22:51 | raspasov_ | Even better lol! |
| 22:52 | Lewix | julianleviston: how do you like it. Im new too |
| 22:52 | justin_smith | Lewix: can you explain what you think ` is for? |
| 22:52 | julianleviston | Lewix: I’m not that new… |
| 22:52 | Lewix | justin_smith: changing it to the data structure list |
| 22:52 | justin_smith | Lewix: it being... |
| 22:52 | julianleviston | Lewix: about 7 months into clojure… more or less... |
| 22:53 | Lewix | justin_smith: I see. It's only me myself and i then..sniff |
| 22:53 | julianleviston | Lewix: lol how new are you? |
| 22:53 | justin_smith | Lewix: the problem here is that (1 2 3 4) is evaluated before your function is run |
| 22:53 | justin_smith | Lewix: if you want to be able to provide a list in that way, second would need to be a macro |
| 22:54 | Lewix | julianleviston: two days ago new |
| 22:54 | julianleviston | Lewix: wow… that *is* new. |
| 22:54 | julianleviston | Lewix: is CLJ your first lisp? |
| 22:54 | TEttinger | ` is the syntax-quote, and it's not meant for newbies. I've used clojure for at least 2 years now, off and on, and I have never used it |
| 22:54 | julianleviston | Lewix: just FYI, on your gist, you should probably mention your expected output, too... |
| 22:54 | justin_smith | Lewix: functions get their args evaluated before they are called, macros get access to the raw form of the provided arguments, and can modify them before they are evaluated |
| 22:54 | Lewix | justin_smith: so it doesnt expect it as arg |
| 22:55 | justin_smith | Lewix: can you rephrase that? |
| 22:55 | Lewix | justin_smith: sorry |
| 22:55 | julianleviston | Lewix: yeah, what are you trying to do? |
| 22:55 | julianleviston | raspasov: mmm |
| 22:56 | julianleviston | raspasov: Using Om. |
| 22:56 | Lewix | justin_smith: so if i have a function fn and arg [arg], it expect a data structure right? |
| 22:56 | Lewix | and ( 1 2 3 4) is not a pure list |
| 22:56 | justin_smith | Lewix: the function doesn't get to decide how its args are evaluated |
| 22:57 | justin_smith | in clojure source code, (f) means invoke f (except for a few very specific contexts) |
| 22:57 | julianleviston | Lewix: maybe you mean to write ‘list not `list |
| 22:57 | TEttinger | julianleviston, wrong quote |
| 22:57 | TEttinger | ,(defn snd [coll] (nth coll 1)) |
| 22:57 | clojurebot | #'sandbox/snd |
| 22:57 | justin_smith | ,(+ 1 (+ 2 3)) ; in this case, (+ 2 3) is not passed to the top level +, it is evaluated to 5 first |
| 22:57 | clojurebot | 6 |
| 22:57 | TEttinger | ,(snd '(0 1 2 3)) |
| 22:57 | clojurebot | 1 |
| 22:57 | julianleviston | tho that wouldn’t work very well... |
| 22:58 | julianleviston | Lewix: it’d be good to know what you’re trying to do. |
| 22:58 | Lewix | julianleviston: i thought my gist was informative enough |
| 22:58 | Lewix | if you read the comments |
| 22:58 | justin_smith | Lewix: in order to change the rules for evaluation, you need to use a macro |
| 22:58 | TEttinger | (doc second) |
| 22:58 | clojurebot | "([x]); Same as (first (next x))" |
| 22:58 | julianleviston | Lewix: your gist just says it doesn’t work. |
| 22:59 | justin_smith | Lewix: and making (1 2 3) mean '(1 2 3) means changing evaluation rules |
| 22:59 | TEttinger | I think you should not start with macros |
| 22:59 | TEttinger | start with 4clojure maybe |
| 22:59 | justin_smith | agreed |
| 22:59 | TEttinger | $google 4clojure |
| 22:59 | lazybot | [4clojure – Welcome!] https://www.4clojure.com/ |
| 22:59 | julianleviston | (second (1 2 3 4)) isn’t valid syntax… because (1 2 3 4) means “run the function called 1 with the arduments 2 3 4) |
| 23:00 | Lewix | julianleviston: what i thought. thanks |
| 23:00 | Lewix | justin_smith: thank you |
| 23:00 | TEttinger | also, [] is strongly preferred for list-like data instead of '() |
| 23:00 | Lewix | TEttinger: isnt [] vectors |
| 23:00 | TEttinger | yes |
| 23:00 | justin_smith | Lewix: np |
| 23:00 | TEttinger | they're extremely similar |
| 23:00 | julianleviston | Lewix: which brings me back to my question… what are you trying to do? |
| 23:00 | Lewix | julianleviston: learning |
| 23:00 | Lewix | simple |
| 23:00 | TEttinger | vectors however don't quote their insides |
| 23:00 | justin_smith | Lewix: most of clojure is defined in terms of interfaces, not concrete classes, so it is quite rare that you actually need a list rather than a vector |
| 23:01 | Lewix | justin_smith: i see - thanks. i have a long way to go |
| 23:01 | justin_smith | Lewix: if you repeatedly add items to the front, yes you want an actual list, otherwise using a vector loses nothing |
| 23:01 | julianleviston | Lewix: in that case, all lists that are being used as data must be quoted, or they will be evaluated as function calls… |
| 23:01 | Lewix | thanks guys |
| 23:01 | Lewix | back to playing with some code |
| 23:02 | julianleviston | Lewix: you might want to look into defn next. :) |
| 23:02 | TEttinger | map filter reduce are all important, and you'll get to them quickly I hope |
| 23:03 | justin_smith | Lewix: actually, now that I think about it "list the functions that work on a list but break when supplied a vector" would be a fun clojure trivia question |
| 23:04 | justin_smith | Lewix: I think the answer is very close to 0 if it isn't 0 |
| 23:04 | justin_smith | any suggestions? I can't think of any... |
| 23:05 | TEttinger | map, filter, reduce, and a few others are kinda the building blocks of most other functions in clojure. they're where clojure starts to have a massive edge over java in succinctness of code beyond just "no java boilerplate" |
| 23:05 | justin_smith | (in clojure.core that is) |
| 23:05 | justin_smith | TEttinger: yup, and all of those seamlessly turn a vector into a seq if needed |
| 23:08 | TEttinger | ,(eval (list + 1 2)) |
| 23:08 | clojurebot | #<ExceptionInInitializerError java.lang.ExceptionInInitializerError> |
| 23:08 | TEttinger | uh.... |
| 23:08 | TEttinger | ,(eval '(+ 1 2)) |
| 23:08 | justin_smith | TEttinger: security restrictions :P |
| 23:08 | clojurebot | 3 |
| 23:08 | TEttinger | nope |
| 23:08 | justin_smith | oh, wow |
| 23:08 | TEttinger | ,(eval [+ 1 2]) |
| 23:08 | clojurebot | #<ExceptionInInitializerError java.lang.ExceptionInInitializerError> |
| 23:08 | justin_smith | ,(eval [+ 1 2]) |
| 23:08 | clojurebot | #<ExceptionInInitializerError java.lang.ExceptionInInitializerError> |
| 23:08 | justin_smith | wat |
| 23:09 | TEttinger | needs quoted |
| 23:09 | TEttinger | eval |
| 23:09 | TEttinger | ,(eval '[+ 1 2]) |
| 23:09 | justin_smith | ,(eval (seq [+ 1 2])) |
| 23:09 | clojurebot | [#<core$_PLUS_ clojure.core$_PLUS_@2e18648a> 1 2] |
| 23:09 | clojurebot | #<ExceptionInInitializerError java.lang.ExceptionInInitializerError> |
| 23:09 | justin_smith | wurt |
| 23:09 | justin_smith | OK |
| 23:09 | justin_smith | ,(eval (seq '[+ 1 2])) |
| 23:09 | clojurebot | 3 |
| 23:09 | justin_smith | :P |
| 23:10 | TEttinger | hiredman_ is the boss, lazybot can't eval |
| 23:10 | justin_smith | TEttinger: anyway, point taken - eval definitely behaves very differently when supplied a vector :) |
| 23:10 | TEttinger | lol |
| 23:10 | TEttinger | I had to rack my brain on that one |
| 23:11 | TEttinger | I was thinking, peek/pop? |
| 23:11 | justin_smith | oh yeah, that changes in behavior too |
| 23:11 | justin_smith | so we have eval, peek, pop |
| 23:11 | TEttinger | but it's documented |
| 23:11 | justin_smith | and of course conj |
| 23:11 | justin_smith | yeah |
| 23:11 | julianleviston | but we weren’t talking about behaviour. |
| 23:11 | julianleviston | list the functions that work on a list but break when supplied a vector |
| 23:11 | justin_smith | ahh, yeah, the code doesn't break |
| 23:11 | julianleviston | ;-) |
| 23:12 | justin_smith | it just does something different :) |
| 23:12 | justin_smith | (inc julianleviston) |
| 23:12 | lazybot | ⇒ 1 |
| 23:12 | TEttinger | yay karma |
| 23:12 | justin_smith | for the technical save |
| 23:12 | julianleviston | lol |
| 23:12 | julianleviston | (julianleviston) |
| 23:13 | julianleviston | I can’t call myself :( |
| 23:13 | TEttinger | (identity julianleviston) |
| 23:13 | lazybot | julianleviston has karma 1. |
| 23:13 | TEttinger | (identity justin_smith) |
| 23:13 | lazybot | justin_smith has karma 179. |
| 23:13 | julianleviston | (map identity [justin_smith julianleviston]) |
| 23:13 | julianleviston | (help) |
| 23:14 | julianleviston | lol. sorry everyone. |
| 23:14 | justin_smith | haha |
| 23:14 | TEttinger | it is just a little bot quirk. it doesn't eval it |
| 23:14 | justin_smith | ((juxt inc dec) julianleviston) |
| 23:14 | TEttinger | it's like justin_smith++ in C++ channels |
| 23:14 | justin_smith | I like (juxt inc dec) for bad puns - it leaves karma unchanged just as you would expect |
| 23:15 | julianleviston | TEttinger: today is the first day I was exposed to this ;) |
| 23:16 | TEttinger | here's a good evil C obfuscation: [18:46;31] <jdaywin> for (int c = 10; c--; c >= -10) { } // will stop after 0, of course, not -9, but at a glance not everyone will notice |
| 23:17 | julianleviston | TEttinger: oh that’s quite cool… it took me 20 seconds to work out! |
| 23:18 | TEttinger | heh, it was after he brought up that any loop that needs to stop before 0 can be done without all 3 forms: for (int c = 10; --c;) { } |
| 23:19 | TEttinger | or after 0 with c-- |
| 23:19 | justin_smith | oh wow that is evil |
| 23:19 | justin_smith | (it's been a while since I touched C) |
| 23:19 | TEttinger | yes, I'm glad I don't use much of that kind of iteration these days |
| 23:20 | TEttinger | you can write some crazy for loop one-liners though |
| 23:20 | raspasov_ | Wait why does that stop lol? |
| 23:20 | justin_smith | gfredericks: I think one could turn this into a slide in a talk about boxing of primitives in clojure http://i.imgur.com/R89vgJB.jpg |
| 23:20 | julianleviston | raspasov: the last two segments are out of order. |
| 23:21 | julianleviston | c - - will get to 0… which is the condition clause. |
| 23:21 | raspasov_ | Oh shit lol |
| 23:21 | TEttinger | raspasov: the condition is c--, and 0 is falsy in C |
| 23:21 | julianleviston | raspasov: and 0 is logical false in c. |
| 23:21 | raspasov_ | Got it :) |
| 23:21 | julianleviston | TEttinger: much succincter! ;-) |
| 23:21 | TEttinger | lol |
| 23:21 | raspasov_ | I guess even in PHP that would "work" lol |
| 23:22 | raspasov_ | Java? |
| 23:22 | julianleviston | TEttinger: (intentional abuse of the English language intended). |
| 23:22 | TEttinger | that's adorable, justin_smith |
| 23:22 | justin_smith | it could also be used as a set theory intro, if you replaced the equation |
| 23:22 | julianleviston | oh my god. it IS. |
| 23:22 | julianleviston | that’s so cool |
| 23:23 | justin_smith | ,#{:cat #{:cat}} |
| 23:23 | clojurebot | #{:cat #{:cat}} |
| 23:23 | gfredericks | justin_smith: but it's so obviously about cons cells |
| 23:23 | justin_smith | aha |
| 23:23 | justin_smith | gfredericks: just needs something about "taking the tail" maybe "holding onto the head" |
| 23:24 | justin_smith | so if we take the tail of (cons cat (cons cat nil)) it will freak out and swat the other cat... |
| 23:24 | gfredericks | for some reason I've never put internet photos in any of my slides |
| 23:25 | julianleviston | gfredericks: coincidentally, I’ve never slid on any photos of the internet. |
| 23:26 | gfredericks | (inc julianleviston) |
| 23:26 | lazybot | ⇒ 2 |
| 23:27 | gfredericks | omg |
| 23:27 | gfredericks | somebody help me out |
| 23:27 | gfredericks | (first (range)) ;; => 0 |
| 23:27 | gfredericks | (second (range)) ;; => 1 |
| 23:27 | gfredericks | (with-redefs [first second] (first (range))) ;; hangs |
| 23:28 | justin_smith | $source second |
| 23:28 | lazybot | second is http://is.gd/9vPOzT |
| 23:28 | gfredericks | oh hah of course |
| 23:28 | gfredericks | that's the best |
| 23:28 | justin_smith | it becomes an infinite loop |
| 23:28 | gfredericks | (inc justin_smith) |
| 23:28 | lazybot | ⇒ 180 |
| 23:29 | raspasov_ | gfredericks: why are you redefing first to be second? :D |
| 23:29 | julianleviston | raspasov: I’m guessing it’s for the lols. |
| 23:29 | raspasov_ | Lol |
| 23:29 | justin_smith | gfredericks is a madman |
| 23:30 | rhg135 | #define 1 0 |
| 23:30 | SegFaultAX | Is that analogous to do `True, False = False, True` in Python? :) |
| 23:31 | gfredericks | raspasov_: it's only temporary |
| 23:31 | julianleviston | coz we have the immutability on our side… ironically. |
| 23:32 | rhg135 | I'm afraid people actually do this stuff |
| 23:33 | justin_smith | it's humor, kind of like using 1nth or 3nd in normal text |
| 23:36 | justin_smith | or that story from the cyberiad about the machine that can make anything starting with the letter n |