#clojure logs

2014-11-01

00:04mercwithamouthping
00:05justin_smith$ping
00:05lazybotjustin_smith: Ping completed in 0 seconds.
00:10Raynes$ping google.com
00:10lazybotRaynes: FAILURE!
00:10RaynesOh no
00:10RaynesThe googles is unpingable
00:11justin_smithRaynes: so I got far enough with lazybot to break everything with the new lib version, and then far enough to make it all compile nicely again and connect - now for things like joining channels and responding to them!
00:11justin_smith$google teh googles
00:11lazybot[Teh Google | Mother Jones] http://www.motherjones.com/kevin-drum/2009/02/teh-google
00:12Raynesjustin_smith: Yay!
01:26zspencerSo, I'm pretty sure I just re-wrote a built in clojure function I'm unaware of
01:27pdkk what does it do
01:27zspencerhttps://gist.github.com/zspencer/c3e8baeec900858fd053
01:27zspencerI'm trying to explain it in words
01:27zspencerand I can't
01:27zspencerother than "It conversts a map of vectors to a vector of maps"
01:27zspencerwhich isn't a good description
01:28zspenceris there a word for this?
01:29pdkthat use case seems specialized enough that i'd be surprised if it was builtin honestly
01:29zspencerHmm
01:29zspencerI figured this would be pretty common
01:31justin_smithzspencer: woah, those names
01:31zspencerWhen I can't think of a good name, I just type until my fingers bleed
01:31zspencer;)
01:32justin_smith,(apply merge-with #(conj [] %1 %2) [{:a 1 :b 2} {:a 3 :b 4}])
01:32clojurebot{:b [2 4], :a [1 3]}
01:33justin_smithzspencer: that's what you want, right?
01:33justin_smithoh duy (facepalm)
01:33zspenceryes
01:33justin_smith,(apply merge-with vector [{:a 1 :b 2} {:a 3 :b 4}])
01:33clojurebot{:b [2 4], :a [1 3]}
01:33justin_smithmuch better
01:34pdkmodern miracles
01:34justin_smithzspencer: the one thing that sucks about that is the behavior for non overlapping keys
01:34justin_smith,(apply merge-with vector [{:a 1 :b 2 :c 3} {:a 3 :b 4 :d 4} {:a 5}])
01:34clojurebot{:d 4, :c 3, :b [2 4], :a [[1 3] 5]}
01:34justin_smithoh ick!
01:34justin_smithand that nesting thing...
01:39amalloyjustin_smith: it's hard to imagine merge-with vector ever being a good plan. better to start from {:a [1] ...} and use merge-with into
01:39justin_smithamalloy: yeah, working an a merge-with / into solution right now
01:39zspenceryea my starting vector could be many entries
01:41amalloy(reduce (fn [acc m] (reduce (fn [m [k v]] (if (contains? m k) (update-in m [k] into v) (assoc m k [v]))) acc m) {} vector-of-maps)?
01:42justin_smith,((fn [& ms] (let [base (zipmap (set (mapcat keys ms)) (repeat []))] (reduce #(merge-with conj % %2) base ms))) {:a 1 :b 2 :c 3} {:a 3 :b 4 :d 4} {:a 5})
01:42clojurebot{:a [1 3 5], :d [4], :b [2 4], :c [3]}
01:43zspencerthat seems a bit harder to follow than my solution :/
01:43zspencermuch terser
01:44amalloy,((fn [vector-of-maps] (reduce (fn [acc m] (reduce (fn [m [k v]] (if (contains? m k) (update-in m [k] conj v) (assoc m k [v]))) acc m)) {} vector-of-maps)) [{:a 1 :b 2} {:a 3 :b 4}]) is another option
01:44clojurebot{:a [1 3], :b [2 4]}
01:44justin_smithzspencer: one difference though is it comtains exactly two names I wouldn't know already based on my knowledge of clojure
01:44amalloydoes less preprocessing than justin_smith's, but is probably harder to follow
01:46zspencerso you create a set of all the keys from the map
01:46justin_smithzspencer: all the keys from all the maps
01:46zspencerthen you reduce the maps onto that set ofkeys
01:46zspencerusing merge-with conj
01:46justin_smith(inc case they have different keys)
01:46lazybot⇒ 1
01:46justin_smithright
01:47zspenceryes all keys from all maps
01:47justin_smithactually there was some silliness in there
01:47justin_smith,((fn [& ms] (let [base (zipmap (set (mapcat keys ms)) (repeat []))] (apply merge-with conj base ms))) {:a 1 :b 2 :c 3} {:a 3 :b 4 :d 4} {:a 5})
01:47clojurebot{:a [1 3 5], :d [4], :b [2 4], :c [3]}
01:47justin_smithmuch better
01:48justin_smithsince merge-with is varargs we can just use apply
01:48zspencerthe (repeat []) sets each of the new keys to []
01:48justin_smithright, with the help of zipmap
01:48justin_smith,(zipmap (range 10) (repeat []))
01:48clojurebot{0 [], 7 [], 1 [], 4 [], 6 [], ...}
01:49justin_smithin the newer version I realized that reduce merge-with is the same as apply merge-with (but noisier) and that #(conj % %2) is just conj when you know there are two arguments
01:50justin_smith,((fn [& ms] (let [base (zipmap (mapcat keys ms) (repeat []))] (apply merge-with conj base ms))) {:a 1 :b 2 :c 3} {:a 3 :b 4 :d 4} {:a 5})
01:50clojurebot{:d [4], :a [1 3 5], :b [2 4], :c [3]}
01:50justin_smiththe call to set was redundant too, since this is a hash-map
01:52zspenceryea, thought that it wouldn't really matter
01:52zspencerwell, I mean, theoretically it would reduce the amount oftimes repeat was called
01:52justin_smithtechnically it does some pointless conj calls I bet
01:52justin_smithright
01:52justin_smiththe conj is more expensive
01:52justin_smithrepeat just returns the same thing every time, way cheap :)
01:53zspencerit shouldn't do any extra conj calls
01:53justin_smithwhy wouldn't it?
01:53justin_smith$source zipmap
01:53lazybotzipmap is http://is.gd/p8ndwz
01:53justin_smithI mean conj inside zipmap
01:53zspenceroh wait, you mean zipmap insdie conj
01:53zspencergotcha
01:53justin_smithor assoc
01:53justin_smithyeah, I mean assoc (though conj would do the same thing)
01:54justin_smithbut calling set has its own set of conj calls, so it's likely a near wash
01:55zspenceryeah
01:55justin_smiththe faster version would use distinct I guess, but we are aiming for clarity at this point anyway
01:56justin_smithoh, distinct uses a set anyway, so never mind that
01:56justin_smith$source distinct
01:56lazybotdistinct is http://is.gd/KRHiA5
01:57zspencernice
01:57zspencerthanks justin_smith
01:57zspencerI've been out of clojure for ~6 months
01:57justin_smithnp
01:57zspencerso all my skills are rusty
01:58justin_smithI try to keep my skills sharp by doing my best to help people with questions on #clojure
01:59zspencerwell played ;)
01:59zspencerYea, I'll start idling in here again
01:59justin_smithit's true though!
01:59zspencerJust dropped my day job, so more free time to work on fun code
02:00justin_smithhere's to lot's of the fun freedom, and little of the dismal pointlessness that can come with an unemployed spell, then
02:00justin_smith(past time for me to get another day job myself)
02:01zspenceryea, I've got freelancer work lined up
02:01zspencerand a full time gig in a month
02:01justin_smithI've been freelancing, but with little reason to leave the house things are different
02:01justin_smithoh, cool
02:01zspencerjust a temporary respite from 1 full time job and 3 freelancing gigs to 3 freelancing gigs :)
02:02TEttingerhang on, getting this for another channel
02:02TEttinger~ask
02:02clojurebotThe Ask To Ask protocol wastes more bandwidth than any version of the Ask protocol, so just ask your question.
02:04pdkmaybe some of us enjoy irc 20 questions!!
02:04justin_smithpdk: is your question about something blue?
02:05pdkcould be
02:05justin_smiththat's not how one plays 20 questions at all!
02:05pdkit's a game about asking 20 questions
02:05pdkwho said any of them got resolved?
02:06zspencerSounds like code review
02:11rritochDoes clojure provide any function to unquote cquoted strings? (ex. "\\'\n" -> "'\n")
02:13mindbender1Good day all!
02:16mindbender1I need a function (condf-> (fn []) :true ["value"] :false nil :default :value)
02:16TEttingerrritoch, that example seems like just removing the first escaped backslash
02:17TEttingermindbender1, is this for 4clojure?
02:17rritochTEttinger: Clojure quotes newlines but not single quotes
02:17rritoch,"\'"
02:17clojurebot#<RuntimeException java.lang.RuntimeException: Unsupported escape character: \'>
02:17amalloymindbender1: that request doesn't appear to make any sense at all. how do you envision this function being used? like, an actual compiling example
02:18TEttinger,"\\'"
02:18clojurebot"\\'"
02:18rritoch,"'\n"
02:18clojurebot"'\n"
02:19rritochSo I need (= (somefunc "\\'\n") "'\n")
02:21rritochTechnically this should also be true (= (somefunc "\\'\\n") "'\n") if cslashes are unescaped properly
02:24rritochThis is the closest I found but it doesn't handle \r\n\t properly
02:24rritoch,(clojure.string/replace "\\'\n" #"\\(.)" "$1")
02:24clojurebot"'\n"
02:25TEttinger,(clojure.string/replace "\\'\\n" #"\\(.)" "$1")
02:25clojurebot"'n"
02:25TEttingerI see your problem
04:24raspasovhey guys does anyone have experience with CRTDs, specifically I'm curious if anyone has ever tried or seen an implementation of persistent (in the Clojure PersistentHashMap sense) CRDTs
05:36rritoch,(let [cunescape (fn [s] (apply str (map #(-> %1 (clojure.string/replace "\\r" "\r") (clojure.string/replace "\\n" "\n") (clojure.string/replace "\\t" "\t") (clojure.string/replace #"\\(.)" "$1")) (re-seq #"\\.|[^\\]*" s))))] (cunescape "test\\r\\n\\t\\'"))
05:36clojurebot"test\r\n\t'"
05:37rritochAny ideas on how to improve this? I thinkk I solved the unescape cslashes problem, but this code is a bit redundant with all of these replacements so it must be improvable
05:49rritoch,(let [cunescape (fn [s] (apply str (map #(reduce (fn [l [m r]] (clojure.string/replace l m r)) %1 [["\\r" "\r"] ["\\n" "\n"]["\\t" "\t"][#"\\(.)" "$1"]]) (re-seq #"\\.|[^\\]*" s))))] (cunescape "test\\r\\n\\t\\'"))
05:49clojurebot"test\r\n\t'"
05:50rritochThats about as clean as I can get it... Still ugly
06:14SagiCZ1could anyone explain this? i wanted to require some namespaces like this:
06:14SagiCZ1(ns this-ns (:require (prefix [other-ns :refer :all] [other-ns2 :refer :all] [prefix2.other-ns3 :refer :all])))
06:14SagiCZ1and i got this exception "Found lib name 'indicator.moving-average' containing period with prefix 'swarm'. lib names inside prefix lists must not contain periods"
06:18SagiCZ1i thought that if the ns3 is deeper than the other ns i can just add the necessary prefix
06:18rritochSagiCZ1: Remove the parenthesis and wrap prefix with [] as [prefix]
06:19rritoch(ns this-ns (:require [prefix] [other-ns :refer :all] ....))
06:20SagiCZ1rritoch: thanks but that tries to find a ns called prefix_init.class
06:21rritochSo your trying to load multiple namespaces into the same prefix?
06:21SagiCZ1i have multiple namespaces with the same prefix, i dont want to repeat the prefix for each
06:22SagiCZ1it works for one level nesting
06:23SagiCZ1i learned this from incanter, see thsi http://stackoverflow.com/a/22600355
06:24rritochOk, so where does this prefix2 come from?
06:26SagiCZ1lets say there is a namespace called incanter.prefix2.namespace ,how would i require it using the method above?
06:28rritochOk, I see. It probably works similarly to import, but testing that theory now.
06:33rritochLooks like you will need to separate them, (ns this-ns (:require (prefix [other-ns :refer :all] [other-ns2 :refer :all]) (prefix.prefix2 [.other-ns3 :refer :all]))
06:33rritocherr: ns this-ns (:require (prefix [other-ns :refer :all] [other-ns2 :refer :all]) (prefix.prefix2 .other-ns3 :refer :all]))
06:34rritochI can't get this synergy to work correctly, I'm not working directly from the box with IRC on it... just remove the dot from .other-ns3 @ the end.
06:38SagiCZ1rritoch: ok, i guess i will keep them separated, thanks for the effort though
09:35lazylambdaHello everyone, can anyone here kindly explain in layman terms the difference between monads and transducers?
09:38mearnshthe cheese on top tastes better
09:39mearnshlazylambda: i can't but this thread might help you? https://news.ycombinator.com/item?id=8344002
09:40lazylambdamearnsh: Thanks, I'll check that out
10:06justin_smithSagiCZ1: prefix require is discouraged, and no, it does not nest at all
10:07justin_smithmearnsh: a transducer is much less formally defined, and much less general, for one thing.
10:08justin_smithmearnsh: in a very vague way you could compare a transducer to a function that can be lifted into a monad. But the problem is that the point of monads is that any function can be lifted into them so...
10:08mearnshi know about that much. the definition thing isn't really an important distinction though because you could produce a formal definition of a transducer
10:09justin_smithso maybe a context that can use a transducer can be compared to a weak kind of monad
10:09mearnshlazylambda was asking but thanks
10:09justin_smithoh, oops
10:09justin_smithlazylambda: ^ respondend to the wrong person, sorry
10:11SagiCZ1justin_smith: good morning, is it discouraged? why is that so? i just copied it from incanter but i dont have to use it if its not good
10:12justin_smithSagiCZ1: I guess you could say it is a somewhat controversial feature
10:12justin_smithas you have learned it does not nest
10:12justin_smiththe argument against it is that it makes it hard to use a searching tool like grep to find usage of a namespace
10:12SagiCZ1i see, that makes sense
10:13justin_smithI figured this out after transforming a bunch of namespaces to use this style...
10:13lazylambdajustin_smith: thanks for the response.. so basically transducers are less powerful than monads?
10:14justin_smithlazylambda: yes, much more limited. Also I like bbloom's idea that we should aim to use the weakest construct we can for a given problem.
10:15lazylambdajustin_smith: why?, for performance reasons?
10:16justin_smithnot really - I think that's unrelated
10:16justin_smithfor code complexity reasons
10:16justin_smithgoto is a very powerful construct, and tends to perform very well
10:16justin_smithbut it's usually better to use something weaker like if or case
10:17lazylambdajustin_smith: I see, that makes sense. I read in Sedgewick's algorithms book that wide interfaces are usually a bad thing
10:17justin_smithI think that is a similar thing, yes
10:18justin_smithlazylambda: that said, I have definitely had situations where I wished we had an efficient and sugared monad in clojure
10:18justin_smithwe have some libs with monads but they are a bit clunky and they are slow
10:18lazylambdajustin_smith: What about algo.monad or whatever it's called
10:18justin_smithyeah
10:19justin_smithalgo.monad doesn't have the kind of sugar and compiler support that haskell monads have
10:19lazylambdajustin_smith: I've never used monads before, I don't even understand them very well yet. I only know the very basic haskell stuff, but I am planning to go deeper
10:19justin_smithlazylambda: I think there are a lot of us in that boat
10:20justin_smithI keep trying, but the abstractions haven't fully sunk in
10:20justin_smithtransducers are a different kind of thing entirely - they mostly exist for efficiency reasons
10:20lazylambdajustin_smith: will monads be useful in clojure though? my friend who is more experienced in haskell tells me that monads are weird without a type system. Is that true?
10:21justin_smithto the degree that they are a coding convenience, it is mostly for someone implementing something like core.async where you want an efficent version of map, filter, reduce, etc. for your context
10:21lazylambdamany haskell folks say that monads aren't really that difficult, but people take time to get them because the concept is so abstract.
10:22lazylambdaI see
10:23justin_smithlazylambda: monads can simplify making and using pure functions that need to carry multiple values (like if I want to chain some function calls and also build up a string in parallel)
10:23justin_smithlazylambda: yeah, they are not complex, just hard to intuit
10:24justin_smithlazylambda: that's the problem with much of category theory - you don't get it because it's hard to imagine something that insanely general and simple
10:24justin_smithlazylambda: many of the inventors and enthusiasts of category theory were fond of calling it "generalized abstract nonsense"
10:25lazylambdajustin_smith, yes, indeed. I am planning to learn about all of that in the future. I am focusing on clojure right now though. Just got me the 2nd edition of joy of clojure, and the reasoned schemer :D
10:26justin_smithlazylambda: clojure is great, and very pragmatic
10:26bbloomjustin_smith: it's not my idea: https://en.wikipedia.org/wiki/Rule_of_least_power
10:26justin_smithlazylambda: we use immutability and function purity because they make great building blocks, but without the mathematical approach of haskell
10:27justin_smithbbloom: I should have guessed you did not invent it, thanks for the reference
10:27lazylambdajustin_smith: exactly what I like about it. Before that, I was using common lisp, which is nice. I think it's bit messy and less aesthetically pleasing though.
10:27justin_smithlazylambda: yeah, idiomatic common lisp is often not very functional at all
10:28lazylambdajustin_smith: indeed
10:30lazylambdajustin_smith: Clojure did borrow the best ideas of all worlds and combined them in a nice and consistent way.
10:30justin_smithbbloom: seeing that article, wow, let me count the ways that modern js / ajax heavy web design violates that principle
10:30justin_smithlazylambda: consistent enough at least :) there are rough edges, but the choices are generally very well thought out
10:31justin_smith,(flatten {:a 0 :b 1 :c 2}) ; for example
10:31clojurebot()
10:31bbloomjustin_smith: honestly, i don't necessarily agree with the way this wiki page frames it
10:31justin_smithbbloom: OK
10:32bbloomjustin_smith: i think the emphasis on turing completeness is misguided -- i'm interested in the power of the typical/encouraged usage. i don't care if it happens to be turing complete, i care that the "pit of success" encourages minimal use of power
10:32justin_smithbbloom: as alluded to in the sql example there
10:33bbloomjustin_smith: ah yes,
10:33justin_smithbut only vaguely
10:34lazylambdajustin_smith: that was weird. I thought seq would be called on the arg first before flattening
10:36bbloom~flatten
10:36clojurebotflatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.
10:36justin_smithlazylambda: yeah, it is weird, and on top of that even a correctly designed flatten would be a code smell (why isn't your data shaped properly in the first place, are you really willing to make your code so un-general that a collection can't be the base case)
10:37bbloomthat said, i really do want a auto-splicing vector type :-)
10:37justin_smithseems like something you could do with finger-trees right?
10:37lazylambdajustin_smith: Can you elaborate on that last point?
10:38bbloomjustin_smith: probably more likely rrb vectors, yeah
10:38justin_smithlazylambda: if you need flatten, I take it as a sign that the algorithm that handed you the data to be flattened was poorly constructed because it is handing you inconsistently shaped data
10:39justin_smithlazylambda: because with a consistent shape, concat would suffice
10:40lazylambdajustin_smith: ah yes. so you mean the input may contain different types of collections within the structure you're trying to flatten?
10:41justin_smithlazylambda: in practice, if someone thinks they need flatten, we can look at the function generating the data, and figure out where it is intermingling single elements and lists of elements inconsistently, and fix that
10:42lazylambdajustin_smith: I see
10:42zenlambdais there a way to 'escape out of' thread-first (->) ?