#clojure logs

2015-02-02

00:00justin_s3ithzapho53 (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:02justin_s3ithzapho53: 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:02zapho53justin_smith: Thanks. Looking at it now.
00:02justin_s3ithzapho53: that's a rough sketch
00:02justin_s3ithbut the basic idea should be right
00:06zapho53justin_smith: Sorry to say my fFirst impression is the JS is much simpler :(
00:07justin_s3ithzapho53: not a great example
00:07justin_s3ithzapho53: that is to say, there are other things core.async does better, and the simple examples won't really show it
00:08zapho53justin_smith: I think the JS is fairly representative of typical nested callbacks.
00:09zapho53justin_smith: I've chosen this simple example because I want to see what typical transposed Node -> CLJS code would look like.
00:10zapho53justin_smith: My concern is whether core.async makes the code easier to understand, ie. simpler. Not convinced so far :(
00:10justin_s3ithOK
00:10dnolenzapho53: I've programmed JS for 10 years professionally, JS callback code is an abomination
00:10dnolenzapho53: what is your example that you want to see a simpler version of of?
00:10justin_s3ithdnolen: you can probably do a much better job of translating that nested callback example than I did
00:11justin_s3ithhttp://pastebin.com/JM1wEz5z
00:11zapho53dnolen: http://pastebin.com/JM1wEz5z
00:12dnolenzapho53: justin_s3ith example is not the write way to do it
00:12dnolenzapho53: write a callback to channel helper once and for all
00:12justin_s3ithI'm actually glad to hear that
00:12dnolens/write/right
00:13zapho53dnolen: 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:13zapho53dnolen: I went through Tim Baldridge's great examples but they're all in clj/cljs so couldn't quite make the connection mentally
00:15zapho53dnolen: I'm asking here because for me a canonical JS callback -> cljs/core.async snippet would nail it for me.
00:15dnolenzapho53: well first off, expecting to understand core.async in anything less than a couple of weeks is unrealistic
00:16zapho53dnolen: No, I've been at it for a while, on and off.
00:16dnolenzapho53: a core.async version of your snippet is literally a version w/o callback nothing to see here
00:16dnolen(let [res (<! ...) res (<! ...) ...] ...)
00:16zapho53dnolen: I'm half way there. Just missing a kind of mental JS equivalent. I get the conecepts as bits and pieces.
00:17dnolenzapho53: there is no JS equivalent, unless you are using js-csp
00:18dnolenzapho53: https://github.com/ubolonton/js-csp
00:19zapho53dnolen: The example was taken from an article by Byan Gilbert about his asynchronize library
00:21dnolenzapho53: anyways my earlier point still stands. With core.async for that code the only thing that will change is no callbacks
00:21zapho53dnolen: Are you saying my snippet doesn't contain callbacks?
00:21dnolenzapho53: I'm not saying anything about your snippet other than that is typical JS callback hell
00:22dnolenzapho53: the problem with justin_s3ith "solution" is that it's at the wrong level of abstraction you would never write it that way
00:22zapho53dnolen: Yes, that's why I posted it - to see how core.async would improve on it.
00:22dnolenzapho53: Node.js fns are have a regular form, it's trivial to write a channelizer thing
00:23zapho53dnolen: An example would help. Then I'll let it rest :)
00:23dnolenzapho53: which I already answered, it's no different if you used generators - it would look like straightline code w/ no callbacks
00:24zapho53dnolen: OK, thanks.
00:24dnolenzapho53: your example is covered in this more general case I blogged about http://swannodette.github.io/2013/08/31/asynchronous-error-handling/
00:25dnolenzapho53: 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:26zapho53dnolen: Didn't see that one. Looks exactly like what I was looking for. Thanks.
00:28PigDudednolen: 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:29dnolenPigDude: your question means you need to read to blog post several more times
00:29dnolenPigDude: and the previous blog entries too
00:31dnolenPigDude: but the hint is that <! is semantically blocking, but not really blocking, once that sinks in the rest makes sense
00:31PigDudednolen: 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:32dnolenPigDude: I'm just pointing out that you were interjecting on a conversation where some expressed at least some experience /w core.async :)
00:32dnolens/some/soneone
00:32dnolenerg someone
00:32PigDudednolen: i've used core.async in production code, in a library targetting both clojure and cljs runtime
00:33dnolenPigDude: right, but I don't think zapho53 was expressing confusion about <!
00:33PigDudednolen: but to be fair it's been a few months. either way, i could see why zapho53 would be confused.
00:33dnolenPigDude: could be wrong about that of course, I didn't read all the backlog
00:34PigDudednolen: 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:34PigDudednolen: so mostly i was hoping to provoke further discussion for zapho53's sake :)
00:35dnolenPigDude: ok but it's simple, <! is semantically blocking w/o actually tying up a whole thread :)
00:40PigDudednolen: 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:42dnolenPigDude: yeah, sorry, my point was that you could write the imperative thing w/o callbacks
00:42PigDudednolen: 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:44PigDudednolen: and then i thought you were saying "he wants to hear from somebody with experience with core.async" and got a little huffy ;)
00:45dnolenPigDude: sorry I didn't mean to assume anything, and I sounded like I did
01:30zactshi clojurists
01:42riceandbeansdo carbs make you sleepy or energitic?
01:47zactsI hear energetic
01:50riceandbeansso is it protein that makes you sleepy?
01:57zactsriceandbeans: milk does, but partly I think due to the lactose
01:57zactscow's milk
02:01ddellacostacrazy Clojurists, always on about macro-nutrients
02:07bonanzaHi,
02:08bonanzadoes anybody know, why I'm getting HTMLCollection by this expression: (-> dom-node .-children)
02:08bonanzabut a normal JS array with this: dom_node.children
02:08bonanzawhere dom-node/dom_node is some HTML node in my app
02:09bonanzaofc I'm talking about clojurescript in the first sentence
02:39michaelr525hmm
02:39michaelr525so I wonder, compojure-api or liberator?
02:40bonanzamichaelr525: are you refering to my question?
02:40michaelr525bonanza: nope, that's my own question
02:40michaelr525what was yours?
02:40bonanza"does anybody know, why I'm getting HTMLCollection by this expression: (-> dom-node .-children)"
02:40bonanza"but a normal JS array with this: dom_node.children"
02:41bonanza"where dom-node/dom_node is some HTML node in my app"
02:41bonanzain another words,
02:41TEttingerI'm wondering if .- and internal . are different
02:41bonanzaI'm trying to translate this to clojurescript with no luck
02:41bonanzadocument.querySelector("#news-list").children[0].children[0].className
02:42bonanza. means refering to functions,
02:42bonanza.- to properties
02:42bonanza(like (.-length some-array))
02:42TEttingerso is dom_node.children getting a function or what?
02:42bonanzaanyway, how to express this "document.querySelector("#news-list").children[0].children[0].className" in CLJS?
02:43bonanzawell, I tried "(-> (reagent/dom-node this) .-children (aget 0) .-children (aget 0) .-className)" but I'm just getting "undefined"
02:43bonanza"children" is a DOM node property
02:44bonanzait's an array
02:44TEttinger(-> document (.querySelector "#news-list") .-children first .-children first .-className)
02:44bonanzaone 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:45TEttingermaybe something like that?
02:45bonanzalet's try
02:46bonanzaI got "Uncaught Error: [object HTMLCollection] is not ISeqable"
02:46bonanzathat's another story - I should have got a plain JS array but instead I have HTMLCollection returned
02:47TEttingerhm
02:47TEttingertry taking out the - ?
02:47TEttingerI really don't know how the JS underlying this works
02:50bonanzaI tried, but then I've got an error "object is not a function",
02:51bonanzawhich is understandable since these are properties, not functions
02:51TEttingerI wonder if [0] is actually accessing a property 0
02:52TEttingerin which case you'd use (-> document (.querySelector "#news-list") .-children (get 0) .-children (get 0) .-className)
02:53TEttingeror, depending on weirdness levels, (-> document (.querySelector "#news-list") .-children (get "0") .-children (get "0") .-className)
02:53bonanzait seems like it does,
02:53bonanzathis is the output of this expression: "(-> (.querySelector js/document "#news-list") .-children (aget 0))" => "(document.querySelector("#news-list").children[(0)])"
02:54bonanzaget is a function for getting from normal CLJ data types,
02:54bonanzaaget is for Java(-script) arrays
02:54TEttingerI was wondering if it wasn't actually an array
02:55bonanzaIt is - following expression works as exprected: (-> (.querySelector js/document "#news-list") .-children (aget 0))
02:55bonanzai.e. it selects first ("0") node from "children" of #news-list
02:56bonanzabut when I try to get first child of *that* node, I get "undefined"
02:56TEttingeruh hm. check its type however you do that in cljs?
02:56TEttinger(doc type)
02:56clojurebot"([x]); Returns the :type metadata of x, or its Class if none"
02:58bonanzayeah, but what node are you refering to?
02:58TEttingerfirst ("0") node from "children" of #news-list
02:58bonanzafunction HTMLDivElement() { [native code] }
02:59TEttingeryeah I have no idea how this works
02:59bonanzait's a normal HTML div element, it's just a way CLJS prints it
02:59TEttingermichaelr525: you seem to know something about cljs, which is about 10x more than I can say
03:06michaelr525hmm
03:06michaelr525what?
03:06clojurebotwhat is not a bug
03:06michaelr525what
03:10Mr0rris0lol it said that to me too
03:10Mr0rris0what?
03:10clojurebotwhat is http://gist.github.com/306174
03:10Mr0rris0what?
03:10clojurebotwhat with pervasive side effects
03:10Mr0rris0what?
03:10clojurebotwhat is cells
03:10michaelr525TEttinger: I've been disconnected. What was the problem?
03:11Mr0rris0what?
03:11clojurebotwhat is exceptions
03:12TEttinger2michaelr525: bonanza is having issues with html elements not acting like collections
03:13bonanzaor - acting like HTMLCollections, not as arrays (as I'd expect)
03:13michaelr525why do you expect them to be arrays?
03:15bonanzabecause I'd like to get first elements from them,
03:16bonanzaor, in other case (not presented here), I need to loop over such array
03:17zactshow can I easily convert a vector of vectors into a map of maps (map the data structure)?
03:18michaelr525bonanza: (-> (.querySelector js/document "#mich") (.-children) (aget 0))
03:18bonanzain 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:18bonanzamichaelr525: yeah, that works,
03:19bonanzaproblem is when I have *two* such expressions in a row
03:19bonanzalike in above example
03:19michaelr525let me try a sec
03:20michaelr525bonanza: works for me
03:20michaelr525bonanza: maybe your html structure doesn't match what you expecet
03:20bonanzasimply put, this "(-> (reagent/dom-node this) .-children (aget 0))" gives me a first parent (some div in my case)
03:20michaelr525(-> (.querySelector js/document "#mich") (.-children) (aget 0) (.-children) (aget 0))
03:21bonanzabut 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:22bonanzathis is my compiled invocation (no optimizations): "((reagent.core.dom_node.call(null,this$).children[(0)]).children[(0)])"
03:22michaelr525what does (reagent/dom-node) return?
03:23TEttinger3zacts: ##(let [vecvec [["a" "A" "b" "B"] ["z" "Z" "y" "Y"]]] (into {} (map #(into {}) vecvec)))
03:23lazybotclojure.lang.ArityException: Wrong number of args (1) passed to: sandbox6330/eval12173/fn--12174
03:23TEttinger3zacts: ##(let [vecvec [["a" "A" "b" "B"] ["z" "Z" "y" "Y"]]] (into {} (map #(into {} %) vecvec)))
03:23lazybotjava.lang.ClassCastException: java.lang.Character cannot be cast to java.util.Map$Entry
03:23TEttinger3gah
03:23bonanzamichaelr525: just a plain DOM node
03:24bonanzamichaelr525: https://github.com/reagent-project/reagent/blob/master/src/reagent/core.cljs#L151
03:24bonanzareagent is a CLJS React wrapper
03:25bonanzamichaelr525: in this case, "root node of a mounted component" is my #news-list div
03:26TEttinger3zacts: ##(let [vecvec [["a" "A" "b" "B"] ["z" "Z" "y" "Y"]]] (apply hash-map (map #(apply hash-map %) vecvec)))
03:26lazybot⇒ {{"a" "A", "b" "B"} {"z" "Z", "y" "Y"}}
03:26michaelr525bonanza: does it work fine when you use javascript api and not dom-node?
03:26TEttinger3that has a map as a key and a map as a value
03:27michaelr525what's that .' syntax btw?
03:27bonanzamichaelr525: yes - "document.querySelector("#news-list").children[0].children[0]" gives me desired node
03:28michaelr525bonanza: and dom-node returns the same type as querySelector?
03:28bonanzathe 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:29bonanzamichaelr525: yes, it returns a plain DOM node (as in http://facebook.github.io/react/docs/working-with-the-browser.html)
03:29michaelr525do you wait until it's rendered?
03:30bonanzayes, because React works that way, it operates on "Virtual DOM"
03:31bonanzaand to get a plain DOM node, you have to wait till it's "mounted" into, then you can select it
03:32michaelr525could you maybe "inspect" the desired element in chrome dev tools and paste a screenshot somewhere?
03:36bonanzamichaelr525: screenshot of a page?
03:37bonanzaor a dom structure?
03:37drakezhardHi does anyone know how to use (proxy) to extend a class?
03:38bonanzamichaelr525: OK, I'll give you a DOM structure to see
03:43bonanzamichaelr525: there's it: http://i.imgur.com/IC0qa2e.jpg
03:45michaelr525hmm
03:45michaelr525looks ok
03:45Viestiargh
03:46Viestitrying to make a custom reporter for cljs.test
03:46Viestitargeting karma
03:46Viestifor some reason, I can't pass a custom :reporter key to the environment :(
03:47michaelr525bonanza: maybe try fetching them one at a time and inspecting their types and content?
03:47Viesti(run-tests (test/empty-env :karma) 'xxx.app-test)
03:47Viestithis should probably do it
03:48michaelr525bonanza: browser-repl for example prints result types like that: #<[object HTMLDivElement]>, #<[object HTMLCollection]>
03:48michaelr525so it's easy to know what you are getting
03:50bonanzamichaelr525: well, the problem is that if I print result by plain js/console.log I got a HTMLCollection, like [item: function, namedItem: function]
03:50bonanzai.e. it prints like this, when I click, there is my "div.scroller" at [0], but I cannot select this by (aget 0)
03:51michaelr525i meant to use cljs repl
03:52bonanzamichaelr525: result will be the same as printing it by ex. (println ...)
03:53bonanzamichaelr525: because it just uses IPrettyPrint interface under the hood
03:54michaelr525so when you (println (dom-node "#news-list")) you get HTMLCollection?
03:55michaelr525and (println (-> (dom-node "#news-list") (-.children)))?
03:55michaelr525and (println (-> (dom-node "#news-list") (-.children) (aget 0))?
03:55michaelr525i think you get my point
03:55michaelr525did you try debugging like that?
03:56bonanzamichaelr525: actually, (println (reagent/dom-node this)) yields "#<[object HTMLDivElement]>"
03:56bonanzaand that's normal since it's a div, after all
03:56michaelr525right
03:57michaelr525what about the next step and the next one?
03:57Viestihas anyone tried to make a custom reporter for cljs.test?
03:58bonanzamichaelr525: http://pastebin.com/wwLndRDJ
04:00michaelr525bonanza: 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:01bonanzamichaelr525: I'll definately try :)
04:01bonanzamichaelr525: thanks for your effort
04:05michaelr525let me know what you came up with
04:24zactsah thanks
04:41dysfunis there a builtin equivalent to (fn [seq pred] (let [a (filter pred seq) b (remove pred seq)] [a b])) ?
04:41dysfunprobably with the argument order reversed
04:47Glenjamin,(doc split-with)
04:47clojurebot"([pred coll]); Returns a vector of [(take-while pred coll) (drop-while pred coll)]"
04:47Glenjaminoh, not quite
04:51hyPiRionit's just (juxt filter remove)
04:53hyPiRiongroup-by is a generalisation if you need to separate values even more
04:56dysfunjuxt is good, thanks
04:56dysfunand does anyone know of a great example of cond-> ?
04:56dysfunit's very difficult to google for
05:01hyPiRiondysfun: (cond-> foo true (assoc :a :b)) acts as (assoc foo :a :b), and (cond-> foo false (assoc :a :b)) acts as foo only
05:01hyPiRionand they chain
05:02hyPiRion,(map (cond-> % (odd? %) (* 2) (even? %) (* 3) (neg? %) -) (range -3 3))
05:02clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: % in this context, compiling:(NO_SOURCE_PATH:0:0)>
05:02hyPiRion,(map #(cond-> % (odd? %) (* 2) (even? %) (* 3) (neg? %) -) (range -3 3))
05:02clojurebot(6 6 2 0 2 ...)
05:05dysfunhrm, so effectively a conditional pipeline?
05:05hyPiRionyep
05:06dysfunso this might be useful, for example for performing a bunch of data correction?
05:06dysfunif data displays this brokenness, fix it this way?
05:07fairuzanyone use Tinkerpop stack with clojure here? :)
05:07dysfunfairuz: did a very small amount with the orientdb library
05:07hyPiRiondysfun: yeah, that's an example
05:07dysfunhyPiRion: hrm. any other good cases you can think of, in terms of the high level?
05:13hyPiRiondysfun: Well, afaik it was introduced because Rich (?) had a lot of code which looked like this:
05:13hyPiRion(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:14hyPiRionWith 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:16dysfunright, so again that's pretty much a data fixing up use case :)
05:17Glenjaminit's fairly good in speccing ring middleware
05:17hyPiRionWell, that's the examples I managed to come up with right now :p
05:17Glenjamin(-> app (cond-> dev wrap-stacktrace))
06:20dysfunGlenjamin: ooh yes, that's quite a nice one
06:20dysfunin 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:22Glenjaminit's actually not ideal for that, because you can only do one middleware per condition
06:22dysfunthat's fine, they're already in functions for grouping
06:22Glenjaminunless you do (cond-> test? (-> () () ()))
06:22dysfunhrm, that could work
06:33Viestihmm
06:33Viestiis there something like alter-var-root for ClojureScript?
06:34Glenjaminyou can probably just use def
06:34Viestihmm so how do I override a def in another namespace?
06:41CookedGr1phonHey all. I want something which behaves like a promise mixed with an atom. Is there such a thing without two derefs?
06:42CookedGr1phoni.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:44GlenjaminCookedGr1phon: i don't think that exists out of the box, but you could probably reify something
07:03clgvCookedGr1phon: maybe you should separate both concerns
07:03clgvCookedGr1phon: as soon as it is delivered you can wrap it in an atom and pass that along
07:04CookedGr1phonthat's pretty much what I've done
07:06clgvwell, then you do not need something merged ;)
07:07CookedGr1phonI meant that's what I've done since asking the question
08:21LukasKHi, i tried to add the clojars repo to my maven nexus but it is not working
08:23clgvLukasK: did you add it as "proxy repository"?
08:25LukasKour 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:26LukasKbrowse remote is working
08:26clgvLukasK: and the index download is enabled as well?
08:26LukasKi dont think so
08:26clgvLukasK: it is enabled by default if you add a new proxy rep as far as I have seen
08:27clgvwhen you enable that, you can search for clojars artifacts in your nexus instance
08:27LukasKok 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:28clgvLukasK: clojars.org/repo is the location
08:30clgvLukasK: 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:32LukasKsorry clgv, i have no idea
08:32clgvLukasK: ok
08:32clgvit's pretty weird to have an rss feed for it but not to include it in the log files...
09:05LukasKhmm nexus can't download the clojars index
09:07clgvLukasK: mine did so yesterday..
09:20LukasKhmm strange
09:22LukasKah it's working :P
09:22LukasKjust took forever but now it is working :P
09:49ScorchinHello, 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:00ScorchinNever mind, figured it out. Had to add `[cider/cider-nrepl "0.8.2"]` to my :user :profiles hash
10:37dnolenjust release ClojureScript 0.0-2760, fixes some ns parsing regressions introduced by 0.0-2755
10:39clgvdnolen: regarding the versions. is there a roadmap or essential features that need to be done before having some kind of 1.0 release?
10:40dnolenclgv: Google Closure Module support, fixing tons of bugs (> 100 open issues in JIRA), optional bootstrap at a minimum
10:41clgvdnolen: ok, sounds like a lot of work
10:41dnolenclgv: yep
10:41daniel__what about 0.1? :)
10:50muhukGreetings. Which convention do you use for constructors in your libs; foo/make-foo or foo/create or foo/new ?
10:50Glenjaminmodule.exports = function(){}
10:51Glenjaminoh, wrong channel
10:51Glenjaminduh
10:51Glenjaminignore me
10:51stuartsierramuhuk: 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:53gfredericksconcoct-foo
10:53gfredericksdiscover-foo
10:53muhukstuartsierra: so foo/foo, it's likely to be imported as foo
10:53gfredericksinvent-foo
10:53llasramgfredericks: derive-foo ?
10:53llasramgfredericks: ooh: evolve-foo
10:53gfredericksimagine-foo
10:54gfredericksprove-foo-by-construction
10:57stuartsierraI generally like to name non-side-effecting functions as nouns for the thing they return.
10:57stuartsierraMy side-effecting functions are verbs.
10:57stuartsierraSo "foo" or "new-foo" are pure constructors.
10:57stuartsierra"create-foo" has side-effects.
10:57muhukstuartsierra: makes sense. Thanks!
10:58stuartsierraAnd yes, I do end up with a lot of foo/foo, but it doesn't really bother me.
10:58stuartsierraI also break these rules all the time :)
11:01uris77rules are meant to be broken :)
11:02gfredericksI like breaking the "rules are meant to be broken" rule
11:03clgvgfredericks: no self-referential statements allowed! you probably know what this has done to mathmatics ;)
11:04gfredericksarguably the prior statement was already self referential
11:04TimMc(defn allocate-tmp-stack-frame [] nil)
11:05gfredericks(inc TimMc)
11:05lazybot⇒ 88
11:05clojurebotNo entiendo
11:05hyPiRion,(let [x [1]] (aset (.tail x) 0 2) x) ; <- breaking the rules
11:05clojurebot[2]
11:05clgvgfredericks: maybe it was just a suggestion ;)
11:05TimMcI suppose that should have a ! at the end.
11:05clgvgfredericks: or an observation
11:06clgvhyPiRion: that's to easy to spot - convert an array to a vector and then modify the underlying array values ;)
11:07hyPiRionor just do this
11:07hyPiRion(let [x [1]] (aset (.tail x) 0 x) x)
11:13sdegutisI can't help but notice tons of similarities between Clojure and Haskell.
11:17hipsterslapfightwell they're both functional languages sure
11:18clgvbut on of them has a, let's say, "suboptimal" syntax ;)
11:18sdegutishipsterslapfight: 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:19hipsterslapfightabout the only thing i really miss from haskell is auto currying
11:20sdegutishipsterslapfight: you don't miss the compile-time type safety?
11:20hipsterslapfightsdegutis: no, if that were the case i'd be using haskell still :v
11:20CookedGr1phonhipsterslapfight: but in return you get varargs
11:21hipsterslapfightCookedGr1phon: sure, i have mixed feeligns on variadic functions though ...
11:24tcrayford____sdegutis: haskell was an explicit inspiration for rich when designing cleaxjure
11:24sdegutistcrayford____: huh, I didn't know that
11:24sdegutisThat explains a lot of the similarities.
11:27sdegutisAre Clojure's lazy sequence functions essentially lazy in the same way as any of Haskell's list functions?
11:30stuartsierrasdegutis: not really
11:30sdegutisoh ok
11:30stuartsierraI mean, you can use them to achieve similar ends, but the mechanism is totally different.
11:30stuartsierraIn Haskell, evaluation itself is lazy, even function arguments.
11:30stuartsierraList laziness just falls out of that.
11:31stuartsierraClojure functions always use strict evaluation semantics. Lazy sequences are a special-purpose data structure for achieving laziness in one specific area.
11:34tbaldridgeHaskell'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:34tbaldridgeSo I kindof compare that to some of Clojure's issues with "holding the head
11:34tbaldridge... of seqs"
11:39mdrogalistbaldridge: Are promise channels out in any core.async releases yet?
11:39tbaldridgenot that I know of, puredanger would be the one to ask about that
11:39mdrogalistbaldridge: Okay, thanks man.
11:49sdegutistbaldridge, stuartsierra: ahh, that's very informative, thank you
12:11zerokarmaleftit's all just lambda calculus
12:11clgv$karma zerokarmaleft
12:11lazybotzerokarmaleft has karma 0.
12:16llasram(inc zerokarmaleft)
12:16lazybot⇒ 1
12:17hellofunklol that was scary there for a moment
12:24zerokarmaleftsome people just want to watch the world burn
12:30dnolencfleming: ping
12:30csd_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:31llasramcsd_: That honestly sounds horrific :-). Dynamic vars are the closest you'd get (fortunately)
12:32csd_ its for testing purposes
12:32csd_i have a function that references a global ref, and i want to test the function
12:33csd_(open to alternatives)
12:33llasramcsd_: It's not without its own limitations, but maybe `with-redefs`?
12:33justin_s3ithcsd_: it can be hacked with a macro
12:33justin_s3ithbut that's macro abuse
12:34justin_s3ithbrb getting rid of this silly nick
12:34csd_with-redefs looks like it would do the trick
12:35FrozenlockIs there a way to list all the methods of a protocol?
12:37justin_smithFrozenlock: look up its source?
12:37justin_smithFrozenlock: 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:37csd_llasram-- thx, that works. what would the typical approach be when someone is trying to test a function that uses global state?
12:38justin_smithcsd_: :P stop using global state maybe?
12:38csd_but i need it
12:38justin_smithOK
12:38Frozenlockjustin_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:38justin_smithFrozenlock: that makes me think the arg count doesn't match
12:38llasramcsd_: I'm actually with justin_smith on this one. I'm skeptical of general actual need for global state
12:39llasram(modulo wanting to use a library which is written to depend on it)
12:39justin_smithcsd_: it should be possible to segregate the management of global state from program logic
12:39csd_llasram, writing an IRC server?
12:39Frozenlockjustin_smith: hmm maybe... let me check that.
12:39justin_smithcsd_: 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:40justin_smithcsd_: very similar to the trick of using a function to generate the expansion for a macro
12:40llasramcsd_: 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:40csd_sorry i don't understand the question
12:41justin_smithcsd_: what if an app needs two or more instances of what your code implements
12:41llasramcsd_: I'm saying that just because you have state doesn't mean it needs to be "global"
12:41Frozenlockjustin_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:41csd_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:42csd_this is an area i'm pretty ignorant in so i'm learning as i go
12:42llasramcsd_: 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:43tbaldridgecsd_: you could still use a ref, but pass it in to each client thread when you construct it
12:43csd_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:44tbaldridgebleh, didn't see what llasram wrote
12:45justin_smithcsd_: if it's global, then everyone get's full access, that's no different than passing it as an arg
12:45justin_smith*gets
12:46justin_smithFrozenlock: all I can think is maybe a typehint that the result is Object? that seems like an odd thing to need though.
12:46csd_, do you know of any good reading on architecting this sort of thing?
12:46clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: do in this context, compiling:(NO_SOURCE_PATH:0:0)>
12:46csd_sorry my ERC is broken :-/
12:47csd_-- that was addressed to you
12:47csd_jesus
12:47llasramcsd_: https://github.com/stuartsierra/component
12:47justin_smithcsd_: 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:47justin_smithcsd_: and yeah, component has some stuff built around that idea too
12:48justin_smith(inc llasram)
12:48lazybot⇒ 47
12:48csd_ok i'll check it out thanks
12:48justin_smithalmost forgot to inc dnolen for saving that newb from my shitty code last night
12:48justin_smith(inc dnolen)
12:48lazybot⇒ 20
13:06Frozenlock,(clojure.pprint/pprint (->> (clojure.reflect/reflect clojure.lang.IAtom) :members (map :name)))
13:06clojurebot#<ClassNotFoundException java.lang.ClassNotFoundException: clojure.pprint>
13:06Frozenlock,(->> (clojure.reflect/reflect clojure.lang.IAtom) :members (map :name))
13:06clojurebot#<CompilerException java.lang.ClassNotFoundException: clojure.reflect, compiling:(NO_SOURCE_PATH:0:0)>
13:07Frozenlockgrr... here's the result (swap swap swap reset swap compareAndSet)
13:07justin_smithFrozenlock: perhaps you need to require some namespaces
13:07justin_smith,(require 'clojure.pprint 'cojure.reflect)
13:07clojurebot#<FileNotFoundException java.io.FileNotFoundException: Could not locate cojure/reflect__init.class or cojure/reflect.clj on classpath.>
13:07justin_smithwell, at least we have the pprint
13:07Frozenlock:-p
13:08FrozenlockI just wanted to show what was visible... 'deref' is not there. Any ideas why?
13:09felixfloresCan 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:11Frozenlockoh dang... deref might be a IDeref method.
13:11clgvFrozenlock: there is IDeref
13:11clgvah you got it
13:12clgvfuture, promise and ref implement IDeref as well
13:12R0B_ROD!seen godd2
13:13clgvit's "$seen" afaik
13:13justin_smith$seen godd2
13:13lazybotgodd2 was last seen quittingPing timeout: 246 seconds 20 hours and 56 minutes ago.
13:13clgvstrange order
13:19felixfloresignore me. I made a stupid mistake. I didn't send the appropriate MIME type
13:21justin_smithFrozenlock: yeah, I see that too, no actual deref in the IAtom methods
13:21clgvhow do I find out the client IP from a ring request?
13:21justin_smithFrozenlock: do you remember if that was maybe protected?
13:21clgvI need that for monitoring abuse of the web app
13:21Frozenlockjustin_smith: No, it looks like deref is an IDeref method, not an IAtom one.
13:22justin_smithFrozenlock: aha, for some reason I saw deref in the IAtom source, maybe I was mistakenly looking at an old version of the code
13:22clgvah there is :remote-addr
13:23Frozenlockjustin_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:27tbaldridgeFrozenlock: there is a IDeref interface.
13:28R0B_RODthanks justin_smith
14:20ben_vulpesanyone have a handle on clojure-west promo codes?
14:20ben_vulpesi missed the early reg :(
14:25justin_smithben_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:26noonianus pdxers late to the party should all register together for the 10% discount
14:28justin_smithnoonian: sounds like an excellent plan
14:28justin_smith"clojerk discount"
14:28noonianlol nice
14:50crazydiamondHi. 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:51slipsethmm, maybe look into :pre and :post
14:51slipsetwhich are like asserts?
14:51slipsetor, better yet, could you show us an example of what you're trying to achieve?
14:52crazydiamondah.. design by contract? :D
14:53justin_smithcrazydiamond: you can define a test with defn similarly to how :pre and :post are defined https://clojuredocs.org/clojure.core/test
14:53justin_smithyeah, :pre and :post are more similar to design by contract, and :test is for tdd
14:53justin_smiththough frequently/usually people directly use assert or clojure.test/deftest
14:53crazydiamondyep, I want TDD
14:54crazydiamondbut I have repetition, like this: http://dpaste.com/09RV7F4
14:54slipsetcrazydiamond: if you're into TDD, checkout midje and autotest
14:54justin_smithcrazydiamond: you can always define a function to be called inside tests
14:55justin_smithcrazydiamond: calling deftest inside defn seems odd to me
14:55hyPiRiongfredericks: Implementation of factorial using a Y combinator:
14:55hyPiRion,(((->(->>(#(% %)(->>(!(->>(($ $)?)#()(->[?])))#()(->[$]))))(->> #()(->[!])))(->>(->>(({(=(+)$)#(*)}(= =)#(* $(!(- $(*))))))#()(->[$]))#()(->[!]))) 10)
14:55clojurebot3628800
14:55crazydiamondjustin_smith, yes, but every time... if I would have 50 tests, that would be 50 functions...
14:55arrdem(inc hyPiRion) ;; that's revolting but you deserve it.
14:55lazybot⇒ 64
14:56justin_smithcrazydiamond: 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:56hyPiRionI implemented SKI as well. Pretty sure that proves Swearjure is turing complete, no?
14:56slipsetcrazydiamond: also, maybe you should look into propertybased/generative testing
14:57justin_smithcrazydiamond: also, that defn that calls deftest is not doing what you think it does
14:57slipsetseems like you're using your functions to generate test-data for your tests?
14:57justin_smithcrazydiamond: you are repeatedly redefining the same test
14:57crazydiamondjustin_smith, yep. I realized that. my test doesn't fail (but it should)
14:57crazydiamondhuh
14:57arrdemhyPiRion: now if only it were TCO'd it'd be useful as well
14:57justin_smithcrazydiamond: test_run_func would need to be a macro
14:58justin_smithcrazydiamond: 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:59hyPiRionarrdem: Hrm. Need to find a way to implement trampoline.
14:59slipsethyPiRion: you need to stop with this hand crafting nonsense and write a clojure2swearjure code-walking macro
15:00slipsetor something ;)
15:00hyPiRionslipset: I'm not that far away from doing that actually
15:00slipsetDon't you write compilers for a living?
15:01hyPiRionyes
15:01hyPiRionI found the SKI properties while working on my swearjure interpreter.
15:02crazydiamondthanks for help
15:02FrozenlockWhat's the clojure way of doing the 'extends' part of this: "final public class Atom extends ARef implements IAtom" ?
15:02crazydiamondI wonder if I may just change defn to defmacro for test_run_func
15:02hyPiRion(Clarification: I don't implement a swearjure interpreter for work)
15:02tbaldridgeFrozenlock: you can do it with proxy, but I'm not sure that's what you want
15:02justin_smithFrozenlock: deftype could do it, or proxy
15:02tbaldridgeFrozenlock: what are you trying to do?
15:02justin_smithwait, maybe deftype can't
15:03Frozenlockadding IRef to a deftype without reimplementing all the methods.
15:03justin_smithFrozenlock: for interfaces, you can use deftype or defrecord to extend, for concrete classes you need proxy or gen-class I think
15:04justin_smithFrozenlock: oh, that's easy - clojure won't complain about partial coverage at all
15:04justin_smithFrozenlock: just add an IRef clause to your deftype
15:04tbaldridgeyeah, it'll just throw NotImplementedException on any unspecified methods
15:04justin_smithif/when they are called :)
15:04FrozenlockWell, I want those methods...
15:04justin_smithFrozenlock: wait, what?
15:05justin_smithyou want methods from an interface, but don't want to implement them?
15:05Bronsajustin_smith: he's ok with the impl provided by ARef
15:05justin_smithahh, right
15:05slipsettbaldridge: 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:05FrozenlockBronsa: yes, that.
15:06BronsaFrozenlock: genclass/proxy are the only way to do that ATM
15:06FrozenlockIf 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:06justin_smithFrozenlock: you can do that kind of thing with proxy or gen-class
15:06justin_smithor just write some java
15:07Bronsaor use a custom version of clojure https://github.com/Bronsa/clojure/blob/defclass/src/clj/clojure/interop.clj#L27 ;)
15:08justin_smithBronsa: 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:11justin_smith{blake}: some-> can be helpful for either (depending on your current code)
15:12justin_smith,(some-> "hello" .toUppercase)
15:12clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: toUppercase for class java.lang.String>
15:12justin_smith,(some-> "hello" .toUpperCase)
15:12clojurebot"HELLO"
15:12justin_smith,(some-> nil .toUpperCase)
15:12clojurebotnil
15:12{blake}justin_smith: Interesting. I think. =P
15:13justin_smith{blake}: easy enough to turn (.meth O) into (some-> O .meth) and get free short-circuiting on nil
15:13ianhedoesit,(.toUpperCase "hello")
15:13clojurebot"HELLO"
15:13justin_smithof course this works nicely with chaining
15:13ianhedoesit,(.toUpperCase nil)
15:13clojurebot#<NullPointerException java.lang.NullPointerException>
15:14ianhedoesitneat
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:15justin_smith,(some-> {:a 0} :b inc) ; also useful without interop
15:15clojurebotnil
15:15justin_smith,(some-> {:a 0} :a inc)
15:15clojurebot1
15:17{blake}(inc justin_smith)
15:17lazybot⇒ 179
15:27muhukI 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:27muhukHaving an alias of bat with a fixed name comes to mind: (def that-thing bat)
15:32amalloymuhuk: 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:33muhukamalloy: :) good question
15:34Mr0rris0maybe its not arbitrary?
15:34muhukamalloy: it's for a library I'm working on. It provides different backends, and it is extensible
15:34muhukamalloy: that's why I'm not creating a static table
15:34amalloyokay, so put things in a map?
15:35amalloynamespaces are great for compile-time lookups, and maps are great for runtime lookups
15:35AeroNotixmuhuk: you might want to use defgeneric
15:35AeroNotixuhm, defmulti, sorry
15:35AeroNotixtoo much CL
15:36justin_smithmuhuk: why not a map from keyword to implementation? or a defmulti yeah
15:36muhukamalloy: 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:36justin_smithmuhuk: the keyword -> symbol -> var-in-ns -> function thing is so indirected
15:37muhukAeroNotix: that's a cool idea, except it'll be a bit backwards maybe
15:37muhukjustin_smith: hi
15:37muhukjustin_smith: yes, you're right
15:38justin_smithmuhuk: 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:38amalloymuhuk: 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:38justin_smitheg. providing a symbol instead of keyword, var instead of symbol, function instead of var
15:39muhukamalloy: they, or 3rd parties. Not known by clecs.
15:39AeroNotixit sounds like you might want a protocol then
15:39justin_smithyeah, I would use a multimethod or protocol, that's exactly what those things are for
15:39amalloyso, 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:39AeroNotixif 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:40muhukjustin_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:41muhukjustin_smith: but you already know the ns (hopefully)
15:41justin_smithmuhuk: why? you pass me something implementing my protocol or multimethod, I call the protocol / multi methods
15:41AeroNotixjustin_smith: this
15:41justin_smithmuhuk: I don't need to know anything about your ns in order to call implementations of my protocol
15:41justin_smithjust pass me the thing that satisfies it and we are good
15:41AeroNotixjust a value of something which implements the protocol
15:42justin_smithexactly!
15:42muhukI don't want the consumer to know anything more than the ns of the backend
15:42muhuk(if I can get away with it)
15:43justin_smithpassing 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:43AeroNotixyou don't need to know *anything* about the backend at all
15:43justin_smithmuhuk: the consumer doesn't need to even know the ns!
15:43AeroNotixmuhuk: you already know the operations you want to call on that object, right?
15:43justin_smithmuhuk: if you implement my protocol, all I need to know is the methods I defined for my protocol
15:43justin_smiththat's it
15:43justin_smithnothing else
15:43AeroNotixmuhuk: look up defprotocol
15:44justin_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:44muhukjustin_smith: see core.clj, suppose I removed that require
15:44justin_smithmuhuk: the caller only needs to know it's protocol
15:44justin_smithmuhuk: it can call the protocol methods
15:44muhukjustin_smith: and pass the ns as a symbol or keyword to make-world
15:44justin_smiththe object implementing those methods is known because it is anonymously passed in
15:45justin_smithmuhuk: why should the caller give a shit about your ns at all? it shouldn't matter
15:45AeroNotixmuhuk: make a protocol which mandates `make-world` as a function, pass in a value which implements that
15:45justin_smithmuhuk: the implementor shouldn't even need to implement an ns
15:45jackhillI'm having trouble with clooj: I only get a blank window, nothing is drawn in it. Has anyone else seen this?
15:45muhukjustin_smith: ok, how does the consumer call make-world and choose a backend then?
15:45justin_smithmuhuk: it doesn't chose a backend, the end user passes one to it
15:46muhukjackhill: it used to work for me. Any particular reason why you're not using Lighttable?
15:46justin_smithand make-world is a part of the implementor's protocol / is the implementor's multimethod, so they know how to call it
15:47muhukjustin_smith: I don't want the backend to be imported by consumer. How does that work?
15:47jackhillmuhuk: 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:47muhukyou guys are inverting my deps
15:47justin_smithmuhuk: why not? they are creating something that is designed around the back-end's needs
15:47muhukjackhill: probably. Maybe try another GUI app.
15:47justin_smithso why shouldn't they import an interface defined by that backend?
15:48jackhillmuhuk: do you have a suggestion?
15:48muhukjackhill: not really. You can try compiling a minimal swing example maybe.
15:49muhukjustin_smith: not really, backends should be interchangeable.
15:49justin_smithmuhuk: make the backends all use the same protocol
15:49justin_smithsame idea
15:49mmitchellI 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:49justin_smiththe backends all use the same protocol, the frontends pass in an instance of a thing implementing said protocol to the backend
15:50justin_smiththus both frontend and backend are fully interchangable
15:50justin_smithmuhuk: 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:51muhukjustin_smith: I still don't like it if the consumer is calling stuff directly on the backends.
15:51amalloymmitchell: slingshot is basically it, i think. maybe gfredericks has something, called catch-data?
15:51muhukjustin_smith: map doesn't do it either.
15:51mmitchelloh slingshot right!
15:51justin_smithmuhuk: the consumer is calling what the implementor explicitly passed to it
15:51amalloyyeah, he totally does
15:51mmitchellwill have a look at catch-data too
15:51amalloyi'd try catch-data first
15:51mmitchellcool will do
15:51justin_smithmuhuk: doesn't do what?
15:52justin_smithmuhuk: are you aware that a namespace is a map from symbols to vars?
15:52muhukjustin_smith: I don't know which backends are available, so I can't create a map.
15:52justin_smithit's just less flexible because we use it in special ways via require and resolution
15:52justin_smithbut if you don't need those features, why use an ns?
15:52justin_smithmuhuk: I think you are being silly
15:53muhukwell, you can always move on. It's not a first on IRC.
15:54justin_smithmuhuk: 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:55AeroNotixboom
15:55mmitchell+1 on catch-data looks nice and simple. Thanks!
16:00csd_- 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:01csd_@justin_smith
16:01dnolenClojureScript now support Nashorn based REPL https://github.com/clojure/clojurescript/commit/d0c9451035d3a9adf9a32e16e759d1e4384268dc
16:01justin_smithcsd_: for shared mutable state you can pass an atom to each component
16:01amalloycsd_: no, you can pass those threads whatever state you want without a global
16:01justin_smithcsd_: it's not global because it could pass a different atom to a different set of components
16:01justin_smithwhat amalloy said
16:02csd_would you be able to put in a pastebin a small sketch of what you mean?
16:02tbaldridgecsd_: 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:03csd_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:03justin_smithabsolutely
16:04justin_smithwouldn't be much point to refs if it didn't in fact
16:05csd_ok seems a bit clearer now
16:07csd_so crudely, the better solution would be something like: (let [state (ref {})] (map #(do-stuff state %) [threads]))
16:07justin_smithcsd_: something with that basic outline, yeah
16:07csd_ok
16:08justin_smithcsd_: advantage being, of course, that testing is now much easier
16:08justin_smithif you do it right
16:09csd_this is one of those concepts that coming from python etc takes a while to get used to
16:09amalloygfredericks: 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:10justin_smithcsd_: 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:11gfredericksamalloy: well it does have the macro-y feature of not making noise in your stacktrace
16:11amalloyhah. well, fair enough
16:12gfredericksI 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:12justin_smithus weirdos get no respect
16:14amalloygfredericks: https://www.refheap.com/d80a9dd79c1374bae013e88a4
16:14amalloyall this has happened before, and will happen again
16:14gfredericksI look forward to round 3
16:15amalloyfeature request: add to docstring for throw-data: "macro instead of a function to protect you from yourself, you weirdo"
16:16gfrederickspatches welcome
16:18gfredericks~patches is <reply> welcome
16:18clojurebotRoger.
16:18Glenjaminwhat is throw-data from?
16:19Glenjaminis throw-data just comp throw ex-info ?
16:19amalloyGlenjamin: yes
16:19gfredericksgithub.com/gfredericks/catch-data
16:19Glenjaminpresumably throw being a macro means that doesn't just work
16:19gfredericksthrow isn't even a macro but yeah that doesn't work
16:19Glenjamins/macro/special-form
16:20gfredericks,(comp throw ex-info)
16:20clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: throw in this context, compiling:(NO_SOURCE_PATH:0:0)>
16:20gfredericks,(let [throw #(throw %)] (comp throw ex-info))
16:20clojurebot#<core$comp$fn__4458 clojure.core$comp$fn__4458@3fceb526>
16:20Glenjaminmakes sense
16:21gfredericksI'm going to go add a comment above (defmacro throw-data) to save amalloy some time next time
16:22amalloy;; amalloy please stop bothering me, you agreed this should be a macro
16:37amalloyso, 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:37amalloyer, assoc-in
16:38gfredericksamalloy: this isn't what reduce-kv is for is it?
16:38amalloyi'm reducing over a seq, not a map
16:38amalloyreducing *into* a map
16:39Glenjaminisn't that (into {}) ?
16:39amalloyGlenjamin: yeah if it were actually assoc (like i first said) it would be. but i'm using assoc-in
16:39Glenjaminright
16:39amalloyon a seq like ([[:x :y] 1] [[:a] 2])
16:40DerGuteMoritzhow about assoc-into
16:40amalloythat's cute
16:40DerGuteMoritzhehe
16:41gfredericksininto
16:41uptown`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:42tcrayford____uptown`: that's intensely difficult on the JVM
16:42uptown`thought so but we live in hope
16:42tcrayford____generally I'd recommend using FlightRecorder for profiling, and criterium for benchmarking
16:43tcrayford____e.g. the JVM after the JIT has warmed up, will sometimes completely eliminate benchmark code, etc
16:45tcrayford____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:45tcrayford____https://github.com/hugoduncan/criterium for criterium
16:45tcrayford____though note you'll want to turn off leiningen's default jvm options - it turns off most of the advanced JIT optimizations
16:46tcrayford____(just throw `:jvm-opts ^:replace ["-server"]` in your project.clj, or in a benchmark/profile specific thing)
16:47tcrayford____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:57uptown`thanks for the pointer
16:57uptown`i'll see if i can get any traction
17:00tcrayford____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:01tcrayford____uptown`: glad I could help :)
17:03Bronsatcrayford____: will you upload slides/notes somewhere? I'd be interested :)
17:03tcrayford____Bronsa: I'll (hopefully) post a video somewhere
17:03Bronsaah, that's even better
17:06justin_smithtcrayford____: for that 5kx diff, were lazy seqs being forced or not a factor?
17:07tcrayford____justin_smith: nope, just reordered benchmarks
17:07tcrayford____like
17:08tcrayford____(do (bench a) (bench b)) (do (bench b) (bench a)) performs astonishingly differently
17:10justin_smithimage of the ancient aliens guy, caption: "hotspot"
17:11tcrayford____exactly
17:14uptown`*cries* so true
17:24TimMc~aot
17:24clojurebotaot is Ahead Of Time compilation
17:24TimMc~aot
17:24clojurebothttp://i.qkme.me/3vb225.jpg
17:47gfredericks~aot |was| so ahead of its time
17:47clojurebotIn Ordnung
17:50cflemingdnolen: pong
17:52denikI'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:53denikThis is mostly to make sure the go-loop pulls down every message rather than to test rmq
17:54cflemingtcrayford____: I'd also be very interested in video/slides/notes to your talk
17:55dnolencfleming: 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:55dnolencfleming: if this is documented somewhere I'm more than happy to read over the setup
17:56hiredman_denik: pulling from rabbit mq is blocking io you should not be doing in a go block
17:56cflemingdnolen: Not really documented unfortunately. This is about as good as it gets: https://cursiveclojure.com/userguide/projects.html
17:56denikhoredman: how then?
17:57denikhiredman_: I need someway to feed rmq into core.async chans
17:57cflemingdnolen: 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:58cflemingdnolen: That basically starts a Java process with the classpath of the module you select, and starts an nREPL server
17:59cflemingdnolen: Actually, I lie - it will automatically add the version of nREPL shipped with Cursive to the classpath.
18:00cflemingdnolen: So you should just be able to run it.
18:00dnolencfleming: what Module am I supposed to be selecting? "Java"?
18:01cflemingdnolen: Right, you set it up as a Java project
18:01cflemingdnolen: But do you already have a Maven project you want to import?
18:01dnolencfleming: yes it's a pre-existing Maven project
18:02dnolencfleming: so I should import it?
18:02cflemingdnolen: Ok, then you want File->Import project, Import from external model, Maven, then follow the options
18:13cflemingdnolen: 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:14dnolencfleming: ok so I imported but the same thing always happens for me, nothing is resolveable
18:14dnolencfleming: i.e. the source code
18:14AeroNotixWhich kafka client do people recommend/
18:14dnolenis all highlighted
18:14AeroNotix?
18:15cflemingdnolen: Has it created source dirs in the right places? Blue folders in the project view?
18:15AeroNotixpeople are using just maven for clojure?
18:15dnolencfleming: blue java folder but not a blue clj one
18:15dnolenAeroNotix: yes
18:15AeroNotixdnolen: why?
18:15dnolenAeroNotix: lots of reasons
18:16cflemingAeroNotix: It just works, I guess
18:16AeroNotixdnolen: such as?
18:16dnolenAeroNotix: I'm not going to enumerate them for you
18:16AeroNotix:(
18:16cflemingdnolen: If you mark the folder as source, are things resolved correctly? Right click, mark as source
18:16AeroNotixI'm genuinely curious what I might be missing out
18:16AeroNotixon
18:16cflemingdnolen: Sorry, right click, mark directory as, source
18:17dnolencfleming: ok that fixed that thanks!
18:17amalloyAeroNotix: better integration with a zillion java tools is one thing, i imagine
18:17AeroNotixamalloy: such as the IDEs and things?
18:17cflemingdnolen: What you'll find is that that source folder will be removed next time your project is synced
18:17cflemingdnolen: You'll have to add something to your POM so that Maven knows that's a source root
18:18cflemingdnolen: Whatever the :source-paths Maven equivalent is
18:20cflemingdnolen: Actually, check the Clojure project for inspiration, looks like it uses a Clojure Maven plugin to do that
18:20dnolencfleming: hrm REPL interactions don't work
18:20dnolenI mean the REPL works
18:20dnolenbut commands to send stuff to the REPL don't
18:24dnolencfleming: ok got it working, a little weird but this is good enough for me
18:25cflemingdnolen: What did you have to change?
18:25cflemingdnolen: For the REPL, I mean?
18:26dnolencfleming: I think I had to exclude some directories?
18:27cflemingdnolen: That sounds strange - normally it should just require an open active REPL, and to be doing it from a Clojure source file
18:29dbronicohey 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:30dnolencfleming: 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:30dnolendbronico: you should look into core.async
18:30amalloycfleming: put dnolen's testimonial on your website somewhere
18:31raspasovcfleming: 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:32dbronicodnolen: 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:33raspasovjust 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:33dnolendbronico: you can as long as you're in a go block
18:33raspasovmaybe it doesn't play nicely with the leiningen plugin somehow?
18:33dbronicodnolen: oh, ok. and then I can use xhr-response outside of the go block?
18:34cflemingdnolen: Great, good to hear :-)
18:34dnolendbronico: by storing it somewhere sure
18:34cflemingdnolen: 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:35dnolendbronico: 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:35dnolencfleming: sweet!
18:35dbronicodnolen: oh, ok. i didn't know it had a dedicated chan. thanks!
18:36cflemingraspasov: 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:36cflemingraspasov: Connect the remote debugger then the remote REPL, all should work
18:36raspasovcfleming: oh great, that's cool, let me try
18:36cflemingraspasov: Someone confirmed on the mailing list the other day that that works, let me know if you have problems
18:43raspasovcfleming: "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:45cflemingraspasov: 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:46raspasovhm I don't see that, could it be because I'm on 13.1 ?
18:50raspasovhttp://i3.minus.com/iXvgpqOA3r2J7.png
19:08trptcolinhow (if at all) does one get korma (with the postgres jdbc adapter) to tell them how many rows got updated?
19:09trptcolinseems like i always get a single record (if any were updated) or an empty seq
19:09trptcolinw/ no way to see how many succeeded
19:09tcrayford____trptcolin: are you using RETURNING ?
19:10trptcolinoh clojure.java.jdbc is all good
19:10tcrayford____oh ok :/
19:11trptcolinwell, "all good" meaning there exists some path where i can get what i want
19:11trptcolinyeah... i really like the idea of being able to share pieces of queries, something something composable something
19:12trptcolinbut 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:12raspasovORM = OMG :)
19:13rhg135indeed
19:13tcrayford____trptcolin: sorry I can't help more :(
19:13trptcolintcrayford____: no worries, thanks for the try :)
19:14cflemingraspasov: That's the remote REPL - the config you want is just called "Remote", it's for remote debugging
19:15cflemingraspasov: You need two connections to the remote JVM - the debugger and the REPL
19:15raspasovcfleming: 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:15raspasov /don't follow instructions carefully/ lol
19:16raspasovI'm sure cfleming is having a hard time working with all of asking questions :-)
19:16raspasovall of us*
19:16{blake}I hardly see how we can be held accountable for a lack of adequate cloning technology.
19:18raspasovhaha well
19:22AeroNotixok what's the deal with lazy-seqs
19:22AeroNotixI have found some code which blocks outside of a lazy-seq, but works inside of one
19:22AeroNotix"works"
19:22amalloyAeroNotix: ?
19:23AeroNotixhmm
19:23AeroNotixit's 1:21am
19:23AeroNotixShould I be doing this....
19:26noonianAeroNotix: 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:26AeroNotixnoonian: yeah that's what I just realised
19:27noonianheh
19:27AeroNotixthis is inside a library
19:28noonianwhat library/code?
19:28AeroNotixclj-kafka
19:30AeroNotixI actually can't get it to read messages out of a kafka queue for some reason
19:30AeroNotixand the laziness inside the read with clj-kafka covered up something for a while
19:32TimMcUgh, just got bit by http://dev.clojure.org/jira/browse/CLJ-1232
19:32nooniansounds 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:32AeroNotixnoonian: just run of the mill stuff really. Straight out the README.
19:32TimMc(defn foo ^Hint [] ...) fails when a.b.Hint is not imported in the namespaces that *calls* that fn.
19:33cflemingraspasov: If it weren't for you people I'd be at version 7 by now, instead of still in beta :)
19:33AeroNotixTimMc: :(
19:33raspasovcfleming: lol
19:33cfleming{blake}: Are you having problems starting the debugger?
19:33{blake}cfleming: Yes! Uh...where is it? =P
19:33cflemingraspasov: Actually, that's mostly true of my daughter rather than tech support
19:34cfleming{blake}: Haha, I see
19:34raspasovraspasov: haha well
19:34raspasovcfleming: haha well
19:34cfleming{blake}: See here under Starting a debug REPL: https://cursiveclojure.com/userguide/repl.html
19:35cfleming{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:35cfleming{blake}: That's Java specific but mostly relevant
19:35cflemingThere 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:36cfleming{blake}: Yeah - make sure you're on 0.1.44, lots of fixes there
19:36cfleming{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:45andyfTimMc: 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:46cflemingTimMc andyf: The other workaround is to type hint the var, not the args vector
19:47TimMcandyf: Easy, but annoying and bloaty. Also, I'm annoyed at Rich for saying it shouldn't be fixed at all.
19:48cflemingTimMc: Yeah, I hate that bug.
19:49cflemingTimMc: Fortunately type hinting the var works fine, so that's what I do everywhere.
19:49cflemingTimMc: With an imported class, I mean.
19:56TimMccfleming: 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:56cflemingTimMc: Any reason you don't want to hint the var?
20:00OldTreeis it possible to use Om's transact function outside of a component?
20:01amalloyyeah, hinting the var is the thing you're supposed to do
20:02amalloyi 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:02hiredman_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:03cflemingamalloy: I'd say based on the doc, you're *supposed* to hint the arg vector, but no-one does because of this bug
20:03amalloywhat doc?
20:04cflemingamalloy: http://clojure.org/java_interop#Java%20Interop-Type%20Hints
20:04cfleming"For function return values, the type hint can be placed before the arguments vector:"
20:05cflemingThe doc for fn and defn make no mention of type hints at all
20:06cflemingI guess the only advantage is that you can hint individual arities differently
20:07cflemingAlthough IMO that's probably bad, or at least confusing, form anyway
20:15gfredericksdangit I'm writing a little data diff/patch library
20:15gfrederickshow could this have happened.
20:15dangitAre you taking my name in vain?
20:16gfredericksno in vein
20:16gfredericksalso sometimes in vane
20:21cflemingI've always wondered who someone is - they must get pinged a lot
20:22amalloyhey, speaking of, whatever happened to the guy named so?
20:22amalloy$karma so
20:22lazybotso has karma -33.
20:29gfredericksoh is that why so gets dec'd
20:30amalloygfredericks: yeah, numerous times i heard people complain that he kept making the word "so" get the username-highlight treatment in their clients
20:31gfredericks(dec so) ; serves him or her right
20:31lazybot⇒ -34
20:40gfredericksthere we go https://github.com/gfredericks/minus
20:40gfredericksnow it just needs a decent algorithm or two
20:41amalloyahaha that algorithm. too good
20:42gfrederickshey man it works great and anybody can understand it
20:42amalloyi was like, wow, what algorithm could be correct but trivial
20:42amalloyquestion answered
20:56justin_smithgfredericks: seeing the defmulti for diff, I expected something using data.diff at first
20:57justin_smith(inc dangit)
20:57lazybot⇒ 1
21:12gfredericksjustin_smith: well it could but that would be an impl detail
21:27dnolenhttps://github.com/omcljs/om
21:29julianlevistonBuilding 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:29julianlevistonn go blocks, then a blocking loop that takes n values off a “results chan”… is that a good way?
21:37julianlevistonMaybe I’ll take a stab at that and see what happens.
21:38justin_smithbetween "doing it via a bunch" and "n go blocks" I think your irc client ate something
21:43julianlevistonI 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:43julianlevistonbunch of n go blocks, then a blocking loop that takes n values off a “results chan”… is that a good way?
21:43amalloyjulianleviston: there is a maximum length to the length of an IRC message
21:44justin_smithjulianleviston: your message is cut off (even eariler this time)
21:44amalloyyour client doesn't seem to know what it is
21:44julianlevistonMaybe my expressions capacity got broken
21:44julianlevistonah....
21:44julianlevistonThat’s weird.
21:44julianlevistonlol
21:44julianlevistonBuilding 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:44julianlevistonat which time it does something contingent on them finishing.
21:45julianlevistonThis 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:45julianlevistonI 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:45julianlevistonHopefully all that came thru :)
21:45julianleviston(it may have been due to strange chars I was typing)
21:46justin_smithjulianleviston: that idea looks perfectly reasonable (now that I know there is nothing insane hiding in the truncating part)
21:46julianlevistonhaha :)
21:46julianlevistonok thanks.
21:46justin_smithjulianleviston: a function that spawns one of the worker go blocks
21:46justin_smithand 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:47justin_smiththat is, function that spawns the worker go blocks, then run it N times etc.
21:50julianlevistonyep. 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:51julianlevistonbut I’m halfway done writing it so, all good :)
21:51justin_smithjulianleviston: oh yeah, that likely exists, I can't name the function though
21:51justin_smithhaha
21:52drscojulianleviston: have you looked at pipeline or pipeline-async?
21:52julianlevistondrsco: do they work on cljs?
21:53drscoyep
21:53julianlevistondrsco: 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:53drscoused pipeline-async yesterday
21:53julianlevistondrsco: ah ok. cool… that sounds like it’d be helpful...
21:53julianlevistonI find the dox a bit… terse.
21:53drscoyeh, 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:54julianlevistongood if you know what they’re talking about...
21:54drscofor sure. precise, but hard to puzzle the use case unless you've seen it before.
21:55julianlevistondrsco: no, not really… I think it’s hard to even see the use case sometimes, even if you’ve had it before...
21:55drscojulianleviston: check this http://www.core-async.info/reference/apidocs#pipeline_async
21:56julianlevistondrsco: until you’ve built it yourself… then you’re like… “oh… this thing here!”
21:56julianlevistonyeah that site is great!
21:56drscopage is slow. painful client side rendering, but nice looking.
21:56julianlevistonironically for about 2 weeks I could never get it to load on safari… works fine on chrome tho.
21:56drscoi like how it breaks out the clojure and cljs source. very handy.
21:57drscoweird. looks like maybe it's polymer or material design type of thing. probably relying on something slightly experimental.
21:57julianlevistondrsco: isn’t it the same as the main clojure site for core async?
21:57julianlevistondrsco: I really don’t undrestand what the desc of pipeline-async means. :(
21:57drscothe part from the docstring is. no inlined source on clojure docs i don't think.
21:58julianlevistondrsco: ah ok.
21:58drscohmm...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:58julianlevistondrsco: I guess pipeline-async handles the “paralleling
21:58julianleviston“paralleling” part...
21:59julianlevistonand then I’d write a doseq n underneath that blocked the main go block until I had all the results in?
21:59justin_smithjulianleviston: 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:59julianlevistongot it.
22:00drscoright, af is a transducer that runs on the fan in part.
22:00julianlevistonum…
22:00julianlevistonit is?
22:01julianlevistonI’m not confident I can write a transducer, and that’s not what the doc says.
22:01drscoit could just be a simple 1-to-1, but it doesn't have to be
22:01drscowait, i'm wrong. my mistake
22:01julianlevistonI’ve looked quite a bit into transducers, but they’re complex.
22:01julianlevistondrsco: phew! :)
22:01julianlevistonironically it’s complex to understand them because they’re so simple.
22:02drscoaf is the async function. derp.
22:02julianlevistonyay! :)
22:02JustinusIIIdoes transducers require understanding of reducers?
22:02drscobut using them isn't so tricky.
22:02drscohttp://matthiasnehlsen.com/blog/2014/10/06/Building-Systems-in-Clojure-2/
22:02julianlevistondrsco: using tranducers is easy. Making them is tricky.
22:02drscoi enjoyed that article a lot. nice graphic.
22:02justin_smithJustinusIII: not really - transducers are stackable transformations you can put on some source of data
22:03justin_smithjulianleviston: uhm (filter isafoo?) is a transducer
22:03justin_smithjulianleviston: or (map frob-it)
22:03justin_smith,(type (map even?))
22:03clojurebotclojure.core$map$fn__4507
22:03julianlevistonjustin_smith: sorry I mean making a function that creates transducers.
22:03justin_smith,(fn [] (map even?))
22:03clojurebot#<sandbox$eval49$fn__50 sandbox$eval49$fn__50@799b710e>
22:03justin_smith:P
22:04justin_smithjulianleviston: they may seem weird, but they are not actually super hard
22:04drscoand they're composable with comp, stackable as you said
22:04julianlevistonjustin_smith: what do you call functions that create transducers?
22:04justin_smithright. They do what I expected eg. nested usage of map to do when I first learned clojure
22:05justin_smith,(sequence (comp (filter even?) (map inc)) (range 10))
22:05clojurebot(1 3 5 7 9)
22:05justin_smiththere's a pair of transducers composed and applied to a lazy-seq
22:05TEttingerit's weird how comp is in reverse order here
22:05TEttingeror not reversed I guess
22:05justin_smithTEttinger: middleware style :)
22:06drscoyeh, it's mindbending
22:06drscojust a little
22:06julianlevistonjustin_smith: yeah, the thing that is hard is creating your own transducer factory.
22:06justin_smithjulianleviston: when do you need to do that?
22:07julianlevistonjustin_smith: when you want to write map, or something different than the provided ones.
22:07drscojulianleviston: take a look at the streaming-buffer example in the link i posted above
22:07julianlevistondrsco: why?
22:07drscoor log-count in the same one, that one is a bit simpler
22:08justin_smithOK, 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:08drscoit describes how to make your own transducing function
22:08JustinusIIIreducers in Joy Of Clojure 2 was scary....I didn't have the courage to look into transducers after that
22:08justin_smithJustinusIII: 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:09julianlevistondrsco: I’m pretty familiar wth transducer usage.
22:09julianlevistondrsco: just not the nomenclature...
22:09drscoah, ok, got it.
22:09julianlevistondrsco: aparently.
22:09julianlevistondrsco: so map is an example of a transducing function?
22:10julianlevistondrsco: a “tranducing function” is any function that has a single-arity that produces a transducer, yes?
22:10drscoperhaps i'm not using the right nomenclature either. should probably verify.
22:10justin_smithjulianleviston: if you provide one arg, yes
22:10JustinusIIIjustin_smith: hmmm....what are the best resources to learn transducers?
22:10justin_smithjulianleviston: the single arg thing isn't a pre-req
22:10julianlevistonjustin_smith: that’s a single arity, is it not?
22:10julianlevistonjustin_smith: ah ok.
22:11justin_smithjulianleviston: right, but the arg count is an implementation detail is all I am saying
22:11julianlevistonI think rich hickey’s trandsucer talks are the best. He explains well.
22:11justin_smitha transducer with two or three args could exist, as long as it has the right behaviors
22:11drscojustin_smith: because map, filter, et al already had two and three arity versions, right?
22:11justin_smithI like this talk by Rich Hickey on transducers. Opens with the classic burrito joke. https://www.youtube.com/watch?v=6mTbuzafcII
22:12justin_smithdrsco: right
22:12justin_smithjulianleviston: he gives a really nice intro to what the point of transducers is
22:13justin_smithjulianleviston: even just the first couple minutes is very informative
22:13julianlevistonjustin_smith: it is a great talk. As is the precursor talk...
22:13julianlevistonI really liked his core async ones, too...
22:13julianlevistonplus, this page is obviously pretty useful… http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming
22:20julianlevistongod I can never remember which of <! or >! is which, or which order they go in. GUH
22:21justin_smithjulianleviston: in a let block, the > or < will point in the direction the data is going
22:21julianlevistonjustin_smith: that makes no sense.
22:21julianlevistonjustin_smith: sorry, but these things always depend on your perspective, and mine isn’t fixed.
22:21justin_smithso (let [result (<! c)] ...)
22:21julianlevistonjustin_smith: again… that doesn’t help.
22:21justin_smiththat means c has contents going into result
22:22justin_smithOK
22:22julianlevistonjustin_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:22julianlevistonjustin_smith: lol :)
22:22justin_smithjulianleviston: the arrow points in the direction the data moves
22:22justin_smith> means left to right
22:23justin_smith< means right to left
22:23julianlevistonjustin_smith: in relation to what, positionally?
22:23julianlevistonjustin_smith: the syntax of clojure?
22:23justin_smiththe thing that gets the data, and the thing that sends it
22:23justin_smithright
22:23rerbNewbie 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:23julianlevistonok… so !> chan is put?
22:23justin_smiththe binding in the let block will be to the left of the (<! call)
22:23justin_smithright
22:23gfredericksrerb: an assoc call
22:24justin_smithbecause the place the data is going is to the right of >!
22:24gfredericks(defn swap [m k1 k2] (assoc m k1 (get m k2) k2 (get m k1)))
22:24julianlevistonso <! means takne?
22:24amalloy!> doesn't exist, it's >!
22:24julianlevistontake*
22:24justin_smithjulianleviston: right
22:24julianlevistongfredericks: don’t def swap!
22:24gfredericksokay
22:25julianlevistongfredericks: IMHO.
22:25rerbgfredericks - thanks
22:25gfredericksnp
22:25julianlevistonamalloy: see my problem? lol
22:25julianlevistonit’s fine… just annoying
22:25amalloy*shrug* everyone has to figure out their own mnemonics
22:25julianlevistonamalloy: exactly. That’s the problem.
22:25gfrederickswe need to standardize on mnemonics
22:25amalloyhow do you keep + and * straight?
22:25julianlevistonamalloy: I’ve never once had to look up put or take tho...
22:26amalloythey're both crossy mathy things
22:26gfredericks(inc amalloy)
22:26julianlevistonamalloy: it’s not quite the same, actually…
22:26lazybot⇒ 220
22:26amalloyboth make numbers bigger
22:26julianlevistonamalloy: - and + would be a better example/
22:26julianlevistonamalloy: and the’re clearly different.
22:26TEttingeryeah, and I always mess up my addition and tetration operators
22:26justin_smithamalloy: or even > and < in a math context :)
22:26julianleviston+ has more strokes than -
22:27gfredericksI'm always confusing unchecked-byte with alter-var-root
22:27julianlevistonjustin_smith: > and < is a better example. the big part is linguistically on the left… we say “5 is greater than 3”
22:27julianlevistonlol… ok maybe I’m being a douche… point taken.
22:27amalloyjulianleviston: justin_smith was trying to give you an analogous mnemonic
22:28amalloybut instead of stopping to think about it you immediately reponded "that makes no sense"
22:28julianlevistonamalloy: I value his help, and what I was annoyed about wasn’t him.
22:28julianlevistonamalloy: I have thought about it a fair bit, actually :) I’m not flaming at the moment.
22:29justin_smithjulianleviston: 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:29justin_smith> and < are popular constituent characters for "flow of data" arrows
22:30TimMccfleming: Hinting the var with a classname looks icky. :-P (It makes it a little harder to read.)
22:30julianlevistonjustin_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:30justin_smithOK
22:30julianlevistonat the end of the day it doesn’t matter, tho… I’ll just be quiet. It’s just syntax.
22:31julianlevistonOh… the pling is the pling of “whatchout”?
22:31justin_smithgeneral question: would people hate you for remapping <! and >! to more verbose names in your code?
22:31justin_smithjulianleviston: the bang? yeah
22:31julianlevistonjustin_smith: It’s cool… I want to use the condoned names. Thanks for being so supportive… :)
22:31TimMc_GT__BANG_ is a good choice
22:31julianlevistonjustin_smith: revelation!
22:31TimMcbut not for both
22:31TimMchmmm
22:31justin_smith(inc TimMc)
22:31lazybot⇒ 89
22:31julianlevistonlol
22:31TimMcI have karma for the stupidest things.
22:32julianleviston(inc TimMc)
22:32lazybot⇒ 90
22:32TimMcamalloy has karma for actually helping people
22:32justin_smithI've likely got an even mix
22:32julianleviston(dec julianleviston )
22:32lazybot⇒ -1
22:33julianlevistonclojureland is so pretty :) <3
22:33amalloyi like to imagine that the ! is the channel
22:33justin_smithoh, nice :)
22:33amalloystuff being pushed into it, squeezed out of it, via the <>
22:34julianlevistonamalloy: 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:38julianlevistondrsco: 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:40raspasov_julianleviston: are you using core async pipelines?
22:40julianlevistonraspasov_: I’m about ti.
22:40julianlevistonto*
22:41raspasov_Cool I use them as well
22:41raspasov_Pretty good, you know about the pipeline vs pipeline-blocking?
22:41julianlevistonraspasov_: not really… do tell :)
22:41julianlevistonraspasov_: the doc says “same but blocking” lol :)
22:42raspasov_Depending on the type of operations you are going to do
22:42raspasov_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:43justin_smithamalloy: gfredericks: thanks for the laugh
22:43amalloyyou're welcome
22:43amalloyi think if obtainance were a word it would quickly degrade to obtenance, so i can't advocate that choice
22:44julianlevistonraspasov_: the work I’m doing is caching some data…
22:45gfrederickscatch-data!
22:45julianlevistonlol.
22:45raspasov_Caching data in memory?
22:45raspasov_On the same machine?
22:45julianlevistonraspasov_: yissir!
22:45julianlevistonraspasov_: in cljs, tho.
22:46raspasov_Oh
22:46raspasov_I'm pretty sure there's no blocking there
22:46julianlevistonraspasov_: yeah, no core.cache for me.
22:46raspasov_It's only one thread
22:46julianlevistonraspasov_: yeah.
22:47julianlevistonit’s only a tiny memoizationy kind of cache anyway.
22:47raspasov_Ok well I don't even know if you really get any benefit from pipelining on cljs?
22:47julianlevistonraspasov_: just wanted to make sure I didn’t do it in sequence too much or it takes too ages.
22:47julianlevistonraspasov_: I don’t either! :)
22:48raspasov_Yea you should benchmark with and without
22:48julianlevistonraspasov_: I’m experimenting… but it seems to be faster with my fanning in place…
22:48julianlevistonraspasov_: at this stage I’d be happy if my UI didn’t block.
22:48raspasov_Yea I have no experience with pipeline on cljs
22:49raspasov_That's always good to avoid ! :)
22:49raspasov_You building a web app?
22:50Lewixhello all
22:51Lewixhttps://gist.github.com/6ewis/f86d3c0721e79197712c - please some insight
22:51drscojulianleviston: glad to hear it's working out
22:51julianlevistonraspasov_: yeah, a really difficult one.
22:51julianlevistonraspasov_: Well, for me… seeing as it has been my first clojure app…
22:51julianlevistonraspasov_: rewriting it from Ember.
22:51raspasov_Difficult = learning = good ;)
22:51julianlevistonraspasov_: indeed!
22:51raspasov_Even better lol!
22:52Lewixjulianleviston: how do you like it. Im new too
22:52justin_smithLewix: can you explain what you think ` is for?
22:52julianlevistonLewix: I’m not that new…
22:52Lewixjustin_smith: changing it to the data structure list
22:52justin_smithLewix: it being...
22:52julianlevistonLewix: about 7 months into clojure… more or less...
22:53Lewixjustin_smith: I see. It's only me myself and i then..sniff
22:53julianlevistonLewix: lol how new are you?
22:53justin_smithLewix: the problem here is that (1 2 3 4) is evaluated before your function is run
22:53justin_smithLewix: if you want to be able to provide a list in that way, second would need to be a macro
22:54Lewixjulianleviston: two days ago new
22:54julianlevistonLewix: wow… that *is* new.
22:54julianlevistonLewix: is CLJ your first lisp?
22:54TEttinger` 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:54julianlevistonLewix: just FYI, on your gist, you should probably mention your expected output, too...
22:54justin_smithLewix: 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:54Lewixjustin_smith: so it doesnt expect it as arg
22:55justin_smithLewix: can you rephrase that?
22:55Lewixjustin_smith: sorry
22:55julianlevistonLewix: yeah, what are you trying to do?
22:55julianlevistonraspasov: mmm
22:56julianlevistonraspasov: Using Om.
22:56Lewixjustin_smith: so if i have a function fn and arg [arg], it expect a data structure right?
22:56Lewixand ( 1 2 3 4) is not a pure list
22:56justin_smithLewix: the function doesn't get to decide how its args are evaluated
22:57justin_smithin clojure source code, (f) means invoke f (except for a few very specific contexts)
22:57julianlevistonLewix: maybe you mean to write ‘list not `list
22:57TEttingerjulianleviston, wrong quote
22:57TEttinger,(defn snd [coll] (nth coll 1))
22:57clojurebot#'sandbox/snd
22:57justin_smith,(+ 1 (+ 2 3)) ; in this case, (+ 2 3) is not passed to the top level +, it is evaluated to 5 first
22:57clojurebot6
22:57TEttinger,(snd '(0 1 2 3))
22:57clojurebot1
22:57julianlevistontho that wouldn’t work very well...
22:58julianlevistonLewix: it’d be good to know what you’re trying to do.
22:58Lewixjulianleviston: i thought my gist was informative enough
22:58Lewixif you read the comments
22:58justin_smithLewix: in order to change the rules for evaluation, you need to use a macro
22:58TEttinger(doc second)
22:58clojurebot"([x]); Same as (first (next x))"
22:58julianlevistonLewix: your gist just says it doesn’t work.
22:59justin_smithLewix: and making (1 2 3) mean '(1 2 3) means changing evaluation rules
22:59TEttingerI think you should not start with macros
22:59TEttingerstart with 4clojure maybe
22:59justin_smithagreed
22:59TEttinger$google 4clojure
22:59lazybot[4clojure – Welcome!] https://www.4clojure.com/
22:59julianleviston(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:00Lewixjulianleviston: what i thought. thanks
23:00Lewixjustin_smith: thank you
23:00TEttingeralso, [] is strongly preferred for list-like data instead of '()
23:00LewixTEttinger: isnt [] vectors
23:00TEttingeryes
23:00justin_smithLewix: np
23:00TEttingerthey're extremely similar
23:00julianlevistonLewix: which brings me back to my question… what are you trying to do?
23:00Lewixjulianleviston: learning
23:00Lewixsimple
23:00TEttingervectors however don't quote their insides
23:00justin_smithLewix: 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:01Lewixjustin_smith: i see - thanks. i have a long way to go
23:01justin_smithLewix: if you repeatedly add items to the front, yes you want an actual list, otherwise using a vector loses nothing
23:01julianlevistonLewix: in that case, all lists that are being used as data must be quoted, or they will be evaluated as function calls…
23:01Lewixthanks guys
23:01Lewixback to playing with some code
23:02julianlevistonLewix: you might want to look into defn next. :)
23:02TEttingermap filter reduce are all important, and you'll get to them quickly I hope
23:03justin_smithLewix: 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:04justin_smithLewix: I think the answer is very close to 0 if it isn't 0
23:04justin_smithany suggestions? I can't think of any...
23:05TEttingermap, 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:05justin_smith(in clojure.core that is)
23:05justin_smithTEttinger: yup, and all of those seamlessly turn a vector into a seq if needed
23:08TEttinger,(eval (list + 1 2))
23:08clojurebot#<ExceptionInInitializerError java.lang.ExceptionInInitializerError>
23:08TEttingeruh....
23:08TEttinger,(eval '(+ 1 2))
23:08justin_smithTEttinger: security restrictions :P
23:08clojurebot3
23:08TEttingernope
23:08justin_smithoh, wow
23:08TEttinger,(eval [+ 1 2])
23:08clojurebot#<ExceptionInInitializerError java.lang.ExceptionInInitializerError>
23:08justin_smith,(eval [+ 1 2])
23:08clojurebot#<ExceptionInInitializerError java.lang.ExceptionInInitializerError>
23:08justin_smithwat
23:09TEttingerneeds quoted
23:09TEttingereval
23:09TEttinger,(eval '[+ 1 2])
23:09justin_smith,(eval (seq [+ 1 2]))
23:09clojurebot[#<core$_PLUS_ clojure.core$_PLUS_@2e18648a> 1 2]
23:09clojurebot#<ExceptionInInitializerError java.lang.ExceptionInInitializerError>
23:09justin_smithwurt
23:09justin_smithOK
23:09justin_smith,(eval (seq '[+ 1 2]))
23:09clojurebot3
23:09justin_smith:P
23:10TEttingerhiredman_ is the boss, lazybot can't eval
23:10justin_smithTEttinger: anyway, point taken - eval definitely behaves very differently when supplied a vector :)
23:10TEttingerlol
23:10TEttingerI had to rack my brain on that one
23:11TEttingerI was thinking, peek/pop?
23:11justin_smithoh yeah, that changes in behavior too
23:11justin_smithso we have eval, peek, pop
23:11TEttingerbut it's documented
23:11justin_smithand of course conj
23:11justin_smithyeah
23:11julianlevistonbut we weren’t talking about behaviour.
23:11julianlevistonlist the functions that work on a list but break when supplied a vector
23:11justin_smithahh, yeah, the code doesn't break
23:11julianleviston;-)
23:12justin_smithit just does something different :)
23:12justin_smith(inc julianleviston)
23:12lazybot⇒ 1
23:12TEttingeryay karma
23:12justin_smithfor the technical save
23:12julianlevistonlol
23:12julianleviston(julianleviston)
23:13julianlevistonI can’t call myself :(
23:13TEttinger(identity julianleviston)
23:13lazybotjulianleviston has karma 1.
23:13TEttinger(identity justin_smith)
23:13lazybotjustin_smith has karma 179.
23:13julianleviston(map identity [justin_smith julianleviston])
23:13julianleviston(help)
23:14julianlevistonlol. sorry everyone.
23:14justin_smithhaha
23:14TEttingerit is just a little bot quirk. it doesn't eval it
23:14justin_smith((juxt inc dec) julianleviston)
23:14TEttingerit's like justin_smith++ in C++ channels
23:14justin_smithI like (juxt inc dec) for bad puns - it leaves karma unchanged just as you would expect
23:15julianlevistonTEttinger: today is the first day I was exposed to this ;)
23:16TEttingerhere'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:17julianlevistonTEttinger: oh that’s quite cool… it took me 20 seconds to work out!
23:18TEttingerheh, 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:19TEttingeror after 0 with c--
23:19justin_smithoh wow that is evil
23:19justin_smith(it's been a while since I touched C)
23:19TEttingeryes, I'm glad I don't use much of that kind of iteration these days
23:20TEttingeryou can write some crazy for loop one-liners though
23:20raspasov_Wait why does that stop lol?
23:20justin_smithgfredericks: 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:20julianlevistonraspasov: the last two segments are out of order.
23:21julianlevistonc - - will get to 0… which is the condition clause.
23:21raspasov_Oh shit lol
23:21TEttingerraspasov: the condition is c--, and 0 is falsy in C
23:21julianlevistonraspasov: and 0 is logical false in c.
23:21raspasov_Got it :)
23:21julianlevistonTEttinger: much succincter! ;-)
23:21TEttingerlol
23:21raspasov_I guess even in PHP that would "work" lol
23:22raspasov_Java?
23:22julianlevistonTEttinger: (intentional abuse of the English language intended).
23:22TEttingerthat's adorable, justin_smith
23:22justin_smithit could also be used as a set theory intro, if you replaced the equation
23:22julianlevistonoh my god. it IS.
23:22julianlevistonthat’s so cool
23:23justin_smith,#{:cat #{:cat}}
23:23clojurebot#{:cat #{:cat}}
23:23gfredericksjustin_smith: but it's so obviously about cons cells
23:23justin_smithaha
23:23justin_smithgfredericks: just needs something about "taking the tail" maybe "holding onto the head"
23:24justin_smithso if we take the tail of (cons cat (cons cat nil)) it will freak out and swat the other cat...
23:24gfredericksfor some reason I've never put internet photos in any of my slides
23:25julianlevistongfredericks: coincidentally, I’ve never slid on any photos of the internet.
23:26gfredericks(inc julianleviston)
23:26lazybot⇒ 2
23:27gfredericksomg
23:27gfrederickssomebody help me out
23:27gfredericks(first (range)) ;; => 0
23:27gfredericks(second (range)) ;; => 1
23:27gfredericks(with-redefs [first second] (first (range))) ;; hangs
23:28justin_smith$source second
23:28lazybotsecond is http://is.gd/9vPOzT
23:28gfredericksoh hah of course
23:28gfredericksthat's the best
23:28justin_smithit becomes an infinite loop
23:28gfredericks(inc justin_smith)
23:28lazybot⇒ 180
23:29raspasov_gfredericks: why are you redefing first to be second? :D
23:29julianlevistonraspasov: I’m guessing it’s for the lols.
23:29raspasov_Lol
23:29justin_smithgfredericks is a madman
23:30rhg135#define 1 0
23:30SegFaultAXIs that analogous to do `True, False = False, True` in Python? :)
23:31gfredericksraspasov_: it's only temporary
23:31julianlevistoncoz we have the immutability on our side… ironically.
23:32rhg135I'm afraid people actually do this stuff
23:33justin_smithit's humor, kind of like using 1nth or 3nd in normal text
23:36justin_smithor that story from the cyberiad about the machine that can make anything starting with the letter n