#clojure logs

2015-09-09

00:14ska-fanHmm, how do I produce either [a b c] or [a c] depending on some condition without mentioning a or c twice (i.e. not (if cond? ([a b c]) ([a c])))? Or is that an achievement that is worth nothing in functional world?
00:15justin_smithska-fan: ##(if false [a b c] [a c]) -- your version has way too many parens
00:15Bronsaska-fan: you'll have to go with the repetition
00:16ska-fanBronsa: I thought so. Thanks :)
00:18ska-fanjustin_smith: Thanks! Learning two languages at a time (the other is racket) I get confused :)
00:25ska-fanAny other way to make this more concise? https://gist.github.com/mbertheau/6f7debba1a8943930c13
00:26justin_smithska-fan: you can define final-style within the outer let block
00:26justin_smithyou don't need nested let for that
00:26bufhhi
00:27justin_smith(that is, base style and final style can be moved into the top level let, before normal-bar)
00:28bufhI am just beginning to learn clojure - can someone point out ways of making this code more efficient? (https://gist.github.com/singhgurjeet243/208a345c17e8a35fc0be)
00:30justin_smithbufh: you could use a transducer instead of reduce and map - unlike a transducer, the map produces a lazy seq you don't need
00:31bufhjustin_smith: are there examples of transducers you can point me to?
00:32justin_smithbufh: this is the best intro http://clojure.org/transducers
00:32bufhjustin_smith: thanks!
00:32TEttingerit's not quite a beginner thing, transducers, but I think that's mostly because they are, relatively speaking, new. there's nothing terribly complex about them as a concept I think
00:32justin_smithso instead of reduce + (map f c) you can use transduce + (map f) + c
00:33justin_smithTEttinger: well, he was asking about performance, which isn't a beginner thing either is it?
00:33TEttingerI suppose. transducers do seem like a good route here
00:33bufhI am not a CS beginner, just a clojure beginner :)
00:34justin_smithbufh: transducers are pretty unique, and are lower level and more specific than people seem to expect
00:34bufhjustin_smith: seems like it, I haven't seen them in scala or haskell
00:34justin_smiththey replace using a sequence as the universal abstraction with a more general "source of data" and "consumer of data" abstraction
00:35justin_smithfor things like channels, or multi step transforms, where fully implementing sequences is just overhead
00:35justin_smithbufh: haskell doesn't need it because they have a clever compiler, clojure is intentionally unclever
00:35bufhis there a 'zen of clojure' a-la python?
00:35justin_smiththere's definitely a unique clojure approach
00:36justin_smithstuff on clojure.org, plus conj.io, plus examples and suggestions here on IRC will help you figure it out pretty quick I think
00:36justin_smithhttp://conj.io/
00:37bufhsweet
00:38TEttingerjustin_smith: interestingly, when I looked at bufh's the code the first thing I thought was "this could be faster if it used mutable state in sample". I don't know if that's accurate though
00:38justin_smithI don't think mutation would give any advantage in there that a transducer wouldn't
00:39justin_smithbufh: also, just for a lark you could try explicitly using first and second in the definition of test-point - destructuring has a bit of overhead you might want to avoid in a bottleneck
00:40TEttingerwell there's some obvious speedup in using unchecked math and making sure the numbers are type-hinted
00:40TEttingeror merging test-point and gen-point into one fn since they're always together
00:40justin_smithoh yeah, some type hints in a few places would likely help, yeah
00:41bufhhm, I don't know how to use type hints yet
00:41TEttingeryou'll want that reflection warning for math thing that got added in 1.7
00:41justin_smithbufh: http://clojure.org/java_interop#Java Interop-Type Hints
00:41justin_smithoh man, that's not a real link
00:41TEttingerit would show you where numbers are being boxed (objects, reference types, heavier weight) or are being calculated with primitives
00:42justin_smithhttp://clojure.org/java_interop#Java%20Interop-Type%20Hints
00:42TEttingerthis one http://clojuredocs.org/clojure.core/*unchecked-math*
00:43TEttingermath-heavy code can be unusually slow in clojure if you aren't aware of how boxing works and when you want to avoid it
00:44TEttingerboxing is needed to put a primitive int into a collection of any kind, where it becomes an Integer
00:44puredangerA general rule of thumb is that boxed math is about 100x slower than primitive math
00:44bufhgot it, I understand boxing/unboxing on the JVM, but didn't know how to use it in clojure
00:44justin_smith100 is a big number
00:45TEttinger,36r100 ;; is bigger
00:45clojurebot1296
00:45bufhso, how can I ensure, that e.g. gen-point generates an array of double in the JVM as opposed to an array of Double
00:45bufh?
00:45TEttingerthat would be two parts.
00:45justin_smithbufh: well, you would need to use an array first
00:45justin_smithyou can't put primitives in vectors
00:46justin_smith(well, not in normal ones)
00:46TEttingerthey can be put in, they will just change to boxed versions, like int to Integer
00:46justin_smithTEttinger: potato, potato
00:47TEttingeryou're right about the array thing, and arrays are I think about as fast in clojure as they are in java :)
00:49justin_smithbufh: or, instead of an array or vector, you can use vector-of http://conj.io/store/v1/org.clojure/clojure/1.7.0/clj/clojure.core/vector-of/
00:49justin_smithin fact I think vector-of is probably the nicest option here
00:49justin_smith(other than unrolling the code so you don't need a collection at all)
00:50puredangerIt only helps on memory
00:50puredangerPrimitive vecs still box in and out
00:50justin_smithpuredanger: vector-of doesn't help with the boxing issue?
00:50TEttingerhttp://clojuredocs.org/quickref under java interop
00:50justin_smithoh
00:50justin_smithnever mind then!
00:50amalloyska-fan: another option is `[~a ~@(when cond? [b]) ~c]
00:50TEttingerah!
00:51ska-fanamalloy: Hmm! Is that considered hacky?
00:51amalloybut that is some fancypants unquoting stuff that may just be distracting
00:51amalloy*shrug* some people don't seem to like it. i am perfectly happy with it myself, and use it when it's convenient
00:51justin_smithska-fan: it will make people think "hey, this guy is clever, like amalloy"
00:51TEttingeramalloy has some rather fancy pants
00:52justin_smithoh, not much, just on IRC, discussing some guy's pants
00:53TEttingerit's interesting; ~@ is rather often a potential part of a solution but not often used outside of things that are already loaded with macro goodness
00:53ska-fanI have this now: https://gist.github.com/mbertheau/6f7debba1a8943930c13 I guess I could go (let [be (if cond [b] [])] (concat [a] be [c])) but that doesn't strike me as particularly beautiful either.
00:54TEttinger,(concat [:a] (if true :b) [:c])
00:54clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Keyword>
00:54TEttinger,(concat [:a] (if true [:b]) [:c])
00:54clojurebot(:a :b :c)
00:54TEttinger,(concat [:a] (if false [:b]) [:c])
00:54clojurebot(:a :c)
00:54justin_smithTEttinger: yeah, that's what the ~@ trick expands to, right?
00:54TEttingernot sure
00:54ska-fan,[:a (if false :b) :c]
00:54clojurebot[:a nil :c]
00:55TEttingerthe trick I was pointing out was that if returns nil if there's no else
00:55amalloyjustin_smith: more or less
00:55ska-fanAh, concat skips nil.
00:55amalloyska-fan: not exactly
00:55justin_smith,`(:a ~(if false [:b]) :c)
00:55clojurebot(:a nil :c)
00:55amalloyconcat treats things as sequences, and nil is an empty sequences
00:55justin_smitherr
00:55justin_smith,`(:a ~@(if false [:b]) :c)
00:55clojurebot(:a :c)
00:55justin_smith,'`(:a ~@(if false [:b]) :c)
00:55clojurebot(clojure.core/seq (clojure.core/concat (clojure.core/list :a) (if false [:b]) (clojure.core/list :c)))
00:55justin_smithoh yeah, that's about the same :)
00:56TEttingerinteresting
01:00TEttingerbufh, heh, we got side-tracked for a moment with another good yak to shave. but I noticed that you might not actually need the array
01:00TEttingersince all your code is doing is conditionally incrementing a value
01:00bufhok, how?
01:00justin_smithTEttinger: yeah, that's what I was getting at with unrolling
01:00justin_smithbufh: by combining those two separate functions (or splitting more finely)
01:00justin_smithsuch that you don't need the tuple
01:01justin_smithbecause your boxing will be caused by the part where you put the x and y in a collection
01:01ska-fanHmm, filterv but no removev
01:02bufhok, let me try it
01:12bufhhmm, so no appreciable speedup
01:12bufhhttps://gist.github.com/singhgurjeet243/208a345c17e8a35fc0be
01:13justin_smithbufh: oh wait I just realized why you call double on line 25
01:14justin_smithbufh: if you are doing rational math, the unboxing isn't possible - rational math is always slow, and there is no such thing as an unboxed rational
01:14bufhok, but the rational math only enters in that line - after the heavy lifting is already done
01:14justin_smithoh... maybe the rational is only being produced in that one place though
01:14justin_smithhaha, yeah
01:15justin_smithanyway, style wise I prefer (* 4.0 e) to (double (* 4 e))
01:15bufhinfact the new sampler is slower
01:15bufhfair point
01:15bufhon style
01:15justin_smithoh, interesting...
01:16bufhbut not by much
01:16bufhmy suspicion is on the range there
01:16justin_smithI wonder if there's a place where hinting would help there...
01:17amalloybufh: if you use (time) for profiling you will get very unreliable results
01:17amalloyit's just for getting a rough idea of how long stuff is taking
01:17amalloyyou can get reasonable results from criterium instead, if you need to time things
01:17bufhok, but if one approach was 10x faster, that'd probably show up, right?
01:18amalloywellll, maybe. the jvm can do some strange things. often the second one you run is faster, because of JITing, or maybe the first one is faster because of GC...
01:18amalloy10x is a lot, and i would expect that to usually correlate with actually being faster
01:18amalloybut no guarantees, especially if it's like 5us vs 50us
01:18ska-fanHa! (-> [:a] (into (if cond? [:b])) (into [:c])) What do you think?
01:18justin_smith,(transduce + (map inc) [1 2 3 4])
01:18bufh➜ pi lein run
01:18bufh"Elapsed time: 1510.67 msecs"
01:18bufh"Elapsed time: 1309.328 msecs"
01:19clojurebot#error {\n :cause "Wrong number of args (0) passed to: core/map/fn--4537"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (0) passed to: core/map/fn--4537"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 28]\n [clojure.core$transduce invokeStatic "core.clj" 6573]\...
01:19amalloybufh: right, so that's easily within experimental error
01:19justin_smith,(transduce + (map inc) 0 [1 2 3 4])
01:19clojurebot#error {\n :cause "Cannot cast clojure.core$map$fn__4537 to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "Cannot cast clojure.core$map$fn__4537 to java.lang.Number"\n :at [java.lang.Class cast "Class.java" 3176]}]\n :trace\n [[java.lang.Class cast "Class.java" 3176]\n [clojure.core$cast invokeStatic "core.clj" 338]\n [clojure.core$_PLUS_ invokeStatic "core.clj" ...
01:19amalloycriterium exists to give you a little more confidence in these estimates
01:20amalloy,(doc transduce)
01:20clojurebot"([xform f coll] [xform f init coll]); reduce with a transformation of f (xf). If init is not supplied, (f) will be called to produce it. f should be a reducing step function that accepts both 1 and 2 arguments, if it accepts only 2 you can add the arity-1 with 'completing'. Returns the result of applying (the transformed) xf to init and the first item in coll, then applying xf to that result and ...
01:20amalloy,(transduce (map inc) + 0 [1 2 3 4]) ; ??
01:20clojurebot14
01:20justin_smithahh, I had the first two flipped!
01:21justin_smithbufh: that's for you ^ amalloy's example shows how to adapt what you have to a transducer (won't be a huge speedup, but should be a speedup)
01:22bufhsorry, I need a bit more help : how do I convert sample2 to use transducers?
01:22justin_smithbufh: where the above has inc, put your own fn
01:23justin_smithand where it has a vector, replace your range call
01:23justin_smithotherwise it is exactly like amalloy 's example
01:23justin_smithbufh: transduce replaces reduce
01:25bufhi am getting a compilation error: Unable to resolve symbol: transduce in this context
01:25justin_smithbufh: clojure version?
01:25TEttingerare you using clojure 1.7 or newer?
01:25TEttinger,*clojure-version*
01:25clojurebot{:major 1, :minor 8, :incremental 0, :qualifier "alpha3"}
01:26TEttingeryou can check with that in the REPL
01:26bufhits 1.6
01:26bufhok, have to figure out how to upgrade
01:26justin_smithbufh: are you using leiningen?
01:26bufhyea
01:26justin_smithjust change the version number in project.clj, clojure is just a library
01:27justin_smithbufh: also, with clojure 1.7 you can use *warn-on-boxed* for numeric ops
01:29puredanger(set! *unchecked-math* :warn-on-boxed)
01:29justin_smith:global-vars {*warn-on-reflection* true *unchecked-math* :warn-on-boxed}
01:30justin_smith^ that for project.clj
01:31bufhwow boxing warnings across the board
01:31luxbockwhen you use (set! *unchecked-math* :warn-on-boxed) in a namsepace, does it apply only to that ns?
01:31justin_smithit is not namespace specific
01:32justin_smithit changes a var in clojure.core
01:32luxbockI would imagine having *unchecked-math* :warn-on-boxed turned globally on would be pretty annoying
01:32luxbockguess you'd only use it when tweaking some specific thing
01:32justin_smithluxbock: it's the only option - though you can turn it off while compiling libs and then turn it on while loading your own code I guess
01:33justin_smithluxbock: the true root of the annoyingness is the libs that force numeric boxing, if they fix their shit you won't get annoying messages :)
01:33luxbockhmm I see
01:33justin_smithluxbock: I'm being glib about that
01:34luxbockI wouldn't actually know how to fix the boxed warnings in bufh's code, for example in `gen-point`
01:34luxbockyou'd just give type-hints for the return value?
01:34justin_smithluxbock: by using hints in the specific places where the compiler doesn't know the value can remain unboxed
01:34bufhok I changed both samplers to xducers, both are 50% faster
01:34justin_smithnice!
01:35ska-fanWhat's short for (if (nil? a) 300 a) ?
01:35justin_smiththe boxing warnings should help too, once you sort them out
01:35justin_smith(if-not a 300 a)
01:35justin_smith(or a 300)
01:35justin_smiththat last one is my final answer
01:36bufhok lots of boxing and unboxing going on - how do I eliminate it say in test-point ?
01:36ska-fanjustin_smith: Thanks!
01:38justin_smithbufh: [[^double x ^double y]]
01:38justin_smith(in the args vector)
01:38justin_smiththough the vector always boxes x and y, those hints can force unboxing in the expression
01:39justin_smiths/force/facilitate
01:39TEttingerI'm curious how this performs
01:39TEttinger,(let [sqr (fn [^double d] (* d d)) check-point (fn [] (< (+ (sqr (Math/random)) (sqr (Math/random))) 1.0)) n 10000 total (int-array 1 0)] (dotimes [_ n] (if (check-point)(aset ^ints total 0 (unchecked-inc-int (aget ^ints total 0))))) (* 4.0 (/ (aget ^ints total 0) n)))
01:39clojurebot3.15
01:40luxbockjustin_smith: what about `gen-point` in bufh's code?
01:40luxbockI get four boxed math warnings which I have no idea how I would eliminate
01:40TEttingeralso I don't know how I'd type-hint sqr
01:40justin_smithluxbock: that shouldn't have any boxed math happening, but it is of course boxing the values
01:41luxbockBoxed math warning, blah.clj:3:4 - call: public static java.lang.Number clojure.lang.Numbers.unchecked_minus(java.lang.Object,long).
01:41TEttingerso there, the first arg in a subtraction is boxed
01:42TEttingerthe second is a long already, so no worries about that
01:42luxbockah I see, think I got it now
01:43luxbockyep
01:43justin_smithI wouldn't think that (rand) needs a type hint to avoid boxing
01:44luxbockit apparently does
01:44justin_smithweird, this must be set up wrong...
01:45justin_smithoops, wrong clj version in this local repl, don't mind me
01:45bufhok this is another 50% faster https://gist.github.com/singhgurjeet243/208a345c17e8a35fc0be
01:46justin_smithbufh: is that just from adding the ^double hints?
01:46bufh2 things: 1. replacing 2 and 1 with 2.0 and 1.0 in gen-point/gen-and-test-point and 2. by adding the two ^double hints
01:47justin_smithbufh: (defn gen-point [] [(- (* 2.0 ^double (rand)) 1.0) (- (* 2.0 ^double (rand)) 1.0)]) -- this should help too
01:47justin_smith(finally got my own reflection and boxing warning repl opened up)
01:47justin_smithfunny that rand is not hinted / known by the compiler already
01:48bufhok, only 2 box/un warnings and about the same speed
01:48justin_smithluxbock: you were right, I really didn't think rand would be unhinted
01:49luxbockis it faster to call (.nth this-vec 0) than `first`?
01:49justin_smithluxbock: that would be a good one for a criterium test
01:50bufhhow do I fix these?
01:50bufhBoxed math warning, pi/core.clj:24:27 - call: public static java.lang.Number clojure.lang.Numbers.divide(java.lang.Object,long).
01:50bufhBoxed math warning, pi/core.clj:24:20 - call: public static double clojure.lang.Numbers.unchecked_multiply(double,java.lang.Object).
01:50justin_smithbufh: oh, and you can hint gen-and-test-point in the same way - I bet it would speed up even more
01:51justin_smithbufh: those two warnings are just the two one-time ops on line 24
01:51justin_smithdefinitely not a bottleneck
01:52bufhhmm, so no way of making this code faster?
01:52justin_smith(though also very easy to fix with the same kind of type hints we've been doing so far)
01:52justin_smithfaster rng
01:52justin_smithusing java data structures instead of clojure ones
01:53justin_smithbufh: I've had a lot of vodka and whiskey tonight, there might be other tricks that I would think of in the morning
01:54bufhlol, let me not kill the buzz :)
01:54justin_smithoh no, it's all good
01:56Bronsacool kids like to get high on clojure
01:59justin_smithfreenode is where all the cool kids hang out https://twitter.com/stefhatcher/status/641488692809338880
01:59bufhthanks for your help - this is the most useful discourse in any #lang group that I have ever been in
02:02Bronsa(inc justin_smith)
02:02Bronsagah
02:02justin_smiththat bot makes clojure look bad sometimes :P
02:04amalloy(dec lazybot)
02:04lazybot⇒ 36
02:05Bronsa(inc justin_smith)
02:05lazybot⇒ 295
02:23bufhok, so the clojure implementation is only about 50% slower than the java implementation
03:18luxbockhere is the benchmark game implementation of pi-digits in Clojure: http://benchmarksgame.alioth.debian.org/u32/program.php?test=pidigits&amp;lang=clojure&amp;id=5
03:19luxbockslighly more verbose
03:23luxbockwhoa, the Java version of the binary-tree benchmark is actually faster than C or C++
03:35chomwittgoodmorning from greece. refer vs require. we can see in repl with ns-map changes we make to the current ns with refer. is there a command to do the same for require ?
04:29TEttingerluxbock, that's hilarious. the benchmarks game is really now "who can call an external library written in assembly the fastest"
04:37tdammerscan I ask questions about Selmer here?
04:46ddellacosta_tdammers: I don't see why not...question is more if anyone around now has any familiarity with it
04:46Bronsaluxbock: wow that is ridiculous
04:50quiiHello, I am a bit of an emacs noob and need some help. I've got quite comfortable using cider and have a *reasonable* workflow for doing TDD. However i really need some refactoring support. The consensus as far as I am aware is to use https://github.com/clojure-emacs/clj-refactor.el . However when I follow the instructions to install it, it seems to just break cider. I get “C-c C-k is undefined” when i try and run my tests. When I
04:50quii..
04:50quiiSo obviously some kind of conflict but I’m not entirely sure where to start
04:50quiiappreciate any kind of help
04:51tdammersddellacosta_: right...
04:51quiiyup :p
04:51TEttingerquii, it's a bit sleepy right now, stick around and maybe ask again in... 4 hours? that's when east coast US might start getting up
04:51quiiok :)
04:51tdammersso I'm trying to do {% if somevector|count <= 1 %}
04:52tdammerswhere somevector is a context variable that I know is a vector
04:52tdammersgives me a NullPointerException
04:52TEttingertdammers: woah what syntax is hat...
04:52tdammersTEttinger: selmer
04:53ddellacosta_tdammers: no idea how selmer works...but I'll ask some dumb questions to help debug: I'm assuming that that sums the values in the vector? Does it require more than 1 or for no nils to exist in the vector?
04:54tdammersthe goal is to check whether the vector has 0 or 1 elements, or more
04:54ddellacosta_oh, so count is counting the number of items? I see
04:54tdammersif it has 0 or 1, I want to generate a hidden field with the only valid value, otherwise I want to render a dropdown
04:54tdammersI tried {% if (somevector|count) <= 1 %}, but that gives me a parser error
04:55tdammerssaying that (somevector|count) is not a valid filter
04:55TEttingerif it has 0 items, calling ##(seq []) may be trouble
04:55lazybot⇒ nil
04:55TEttinger,(count (seq []))
04:55clojurebot0
04:55TEttingerhm
04:55tdammers,(count nil) ; more interesting edge case
04:55clojurebot0
04:55tdammersbut stil
04:55tdammersl*
04:55chomwittin lein repl (clorure.s[tab] completes with clojure.set clojure.string etc. But i've not loaded them with 'require in the current user namespace
04:56TEttingerhm, nope https://github.com/yogthos/Selmer/blob/master/src/selmer/filters.clj#L226
04:56tdammerswait, turns out {% if somevector|count <= 1 %} does in fact work
04:57tdammersthe exception is caused by something else
04:57tdammers(trial-and-error debugging ftw)
04:57TEttingeris the paren thing maybe calling it somehow?
04:57tdammersno, if I add the parens, the parser gives a nonsensical error, it doesn't even get to run the template at all
04:57tdammersmy guess is that it's a weird edge case in the parser
05:00TEttingerhm
05:00TEttingerscanning through this... https://github.com/yogthos/Selmer/blob/master/src/selmer/filter_parser.clj
05:00TEttingerI can't find any indication that it handles parens sensically
05:00TEttingerthere's nothing like a grouping indicator
05:01tdammersI'd expect it outside of the filter parser
05:01tdammersbut haven't found the expression parser yet
05:05TEttingerwell whatever calls parse is doing something
05:05TEttingereyyyy yogthos
05:05TEttingertdammers has some selmer questions
05:06TEttingerhttps://github.com/yogthos/Selmer/blob/master/src/selmer/parser.clj#L238 tdammers, this looks like the only place it might start to handle parens, and even then it would be something that calls this...
05:06tdammershmm, so far I've been figuring it'd be somewhere in the regexes that deconstruct tags
05:06tdammersutil.clj, somewhere
05:07tdammershttps://github.com/yogthos/Selmer/blob/master/src/selmer/util.clj#L46
05:07tdammerssomewhere around here
05:09tdammershttps://github.com/yogthos/Selmer/blob/master/src/selmer/tags.clj#L141
05:09tdammerslooks like "if" is special
05:10tdammersso there's not really a notion of "expressions" here, is there?
05:10tdammersthat would also explain why binding a seq to a local variable with {% with %} and then trying to iterate over it doesn't work
05:11TEttingerI guess? I don't do any web dev that isn't static webpages on github :)
05:12TEttingerlike the show-off page for the large amounts of art I keep making. http://tommyettinger.github.io/home/PixVoxel/cu3/Firing.html
05:15tdammerslooks nice
05:15tdammerspage locks up firefox somehow though
05:18TEttingerhehe
05:18TEttingerit's a ton of gifs, it does that
05:18tdammersstill locked
05:18tdammersand this isn't shitty hardware, mind you - fairly new i7 thinkpad
05:19TEttingerit's I believe a firefox bug
05:19wasamasaorly
05:19wasamasaloads slowly, but surely here in firefox
05:19TEttingerthere's a page that has even more gifs that you can try wasamasa :)
05:19TEttingerhttp://tommyettinger.github.io/home/PixVoxel/cu3/index.html
05:20tdammersuhm, I think I'd rather not :D
05:20tdammersxkill ftw
05:21TEttingerI have no trouble with chrome
05:21wasamasait always surprised me when a classmate can't even start chromium without it eating up all the memory and hanging on their L512 while I can use it on my X200s just fine
05:21TEttingerL512?
05:21wasamasayeah, at least one generation newer CPU
05:22wasamasamine has a C2D, his an i3
05:22TEttingerhuh...
05:22wasamasathe difference is that I'm using linux and he's got a windows install from work on it :D
05:23TEttingerit's weird why some computers can't handle these poorly-made gif spewing pages
05:23TEttingerI know someone with a 6-year-old linux netbook who can't load any pages I make with even a quarter that many gifs
05:23TEttingerhe uses firefox I think for the reason you gave, chromium uses too much mem
05:24wasamasaI've got to admit, the second site got quite a bit more for downloading
05:24wasamasaboth peter out on me once in a while
05:24wasamasaif it's firefox, it's high CPU usage, for chromium it's a memory leak
05:24TEttingerfor some reason github hasn't warned me about using more than 1GB of repo space for the github pages repo that hosts all that
05:24TEttingerI am using about 4.5 GB now
05:25tdammersdoes git have a space limit?
05:25TEttingergithub says it recommends staying under 1 GB but does not have a hard limit, and will send a polite email if you use too much
05:26tdammersright
05:26TEttingergitlab has a hard 10GB limit for free accounts on their server
05:26tdammerswhich they will probably only start doing once you use an order of magnitude more, or when too many users start doing it
05:26TEttingerbitbucket no idea
05:26tdammersIIRC bitbucket has no limit at all
05:26TEttinger10 TB, sure
05:26tdammerswell, no explicit limit
05:27tdammersI bet the fine print has some sort of FUP
05:27tdammersbitbucket price-shapes on team size instead
05:50OlajydHi TEtttinger :D
05:50TEttingerhey Olajyd!
05:50TEttingerhow's it going?
05:51OlajydTEttinger, going well…had a week off for some job weldone the past few weeks
05:51TEttingergood good!
05:51OlajydYea :)
05:52TEttingerback into coding now though?
05:52OlajydTEttinger, Yep..
05:53OlajydThanks for taking out time to help out, TEttinger
05:54TEttingerno worries, it's always a good way for me to keep my clojure skills sharp. I haven't been using Clojure for anything major for a while, these refreshers for you and me help me remember the clojure I want to use for an upcoming thing
06:02OlajydSo out of curiorsity, is there any function that can force all prior processing to occur before moving on to the next function?
06:14TEttingerOlajyd, I believe there may be, but not for general processing. clojure has a number of tools like this...
06:15TEttingerthere's futures, which you tell to start running as soon as they are declared, and if they have finished when you later request their return value, you get the return immediately, otherwise, you wait until the future finishes
06:16TEttingerthe keyword is "blocking"
06:16TEttingerfutures will block until they can return their final result
06:20Olajydok
06:23OlajydThanks TEttinger, so the reason I asked is because soon we’ll be structuring the code base to something like a pipeline, that for one function to run, a prior function mush have finished running
06:24TEttingerhm, sounds good. I know there are some things in clojure that are similar to futures, like delays, that you might want to look into
06:25TEttingera step that must be completed to move on might be the body of a future, and you just dereference that future when you need it in the next pipeline step (which blocks until the previous step has a final value)
06:26TEttingerI don't know much about the performance of futures and there is likely a better way, though maybe not much better
06:26Olajyduhmmm nice
06:27Olajydwill look into that
06:29OlajydTEttinger, I saw this problem in stackoverflow, a function that takes rows: [[“1” “2” “3”] [“a” “b” “c”]] and produces: ([“1” “2” “3”] [“a” “b” “c”])
06:29Olajydis this possible?
06:30TEttingerjust changing frm [] to () in the outermost?
06:30TEttinger,(seq [["1" "2" "3"] ["a" "b" "c"]])
06:31clojurebot(["1" "2" "3"] ["a" "b" "c"])
06:31TEttinger,(seq {["1" "2" "3"] ["a" "b" "c"]}) ; works on any collection
06:31clojurebot([["1" "2" "3"] ["a" "b" "c"]])
06:31Olajydis it possible to have only [“1” “2” “3”] [“a” “b” “c”] without the brackets?
06:31TEttingerah!
06:31TEttingersort!
06:31TEttingersorta!
06:31Olajydheheh :D
06:32TEttingerso if you have this within another function, there's kinda a way
06:32TEttingerbut there's no way to do multiple returns
06:32Olajydhmmm great
06:33TEttinger,`(map str ~@[["1" "2" "3"] ["a" "b" "c"]])
06:33clojurebot(clojure.core/map clojure.core/str ["1" "2" "3"] ["a" "b" "c"])
06:33Olajydoddcully…deja vu? lol
06:33TEttingerwhich would need to be in a macro or be eval'ed
06:33Olajydhmm
06:33TEttinger,(apply map str [["1" "2" "3"] ["a" "b" "c"]])
06:33clojurebot("1a" "2b" "3c")
06:33TEttingermight be what you want
06:34TEttingerapply can remove the first layer of nesting from a collection
06:36Olajydlol its a function assigned to my colleague though..I’m not very clear with his story on homw to implement it though..wanted to help out but..I’ll just set him up on IRC so he can ask himself
06:37TEttingera clojure function can only return one value. that value could be 1, could be "hello", could be [[1 2 3] [:a :b :c]]
06:39OlajydTEttinger, I’m sorry i dont understand what side effects mean in clojure functions :(
06:39TEttingera clojure function can only return one value. that value could be 1, could be "hello", could be [[1 2 3] [:a :b :c]]
06:40TEttingeryou can have side effects, which are things like changing an atom and then returning some other result unrelated to the atom
06:40Olajydok
06:40TEttingerone way to get two results out of a function is to have two side effects :)
06:41Olajydok
06:41Olajydlol…nice, gotcha :)
06:41TEttinger,[(def res1 (atom []))(def res2 (atom []))]
06:41clojurebot[#'sandbox/res1 #'sandbox/res2]
06:42TEttinger,(defn side-effecting [n] (do (swap! res1 conj n) (swap! res1 conj (inc n)) (* n n n)))
06:42clojurebot#'sandbox/side-effecting
06:42TEttinger,(side-effecting 1)
06:42clojurebot1
06:42TEttinger,(side-effecting 2)
06:42clojurebot8
06:42Olajydhmmm
06:43TEttinger,[@res1 @res2]
06:43clojurebot[[1 2 2 3] []]
06:43TEttingeroh haha
06:43TEttingerI was adding to res1 both times
06:43TEttinger,(defn side-effecting [n] (do (swap! res1 conj n) (swap! res2 conj (inc n)) (* n n n)))
06:43clojurebot#'sandbox/side-effecting
06:43TEttinger,(side-effecting 20)
06:43clojurebot8000
06:43TEttinger,[@res1 @res2]
06:43clojurebot[[1 2 2 3 20] [21]]
06:43aneis refactor-nrepl broken with clojure 1.7?
06:44anetravis builds seem to be failing
06:44Olajyd:)
06:44RurikWhy is swap! named swap! ?
06:44TEttingerthe ! is so you know it isn't safe to call during a transaction IIRC
06:44noogabecause oit swaps the value?
06:45Ruriknooga, I meant ! part
06:45noogaoh
06:45TEttingerI believe it's the transaction reason
06:46Olajydyeaa hmm interesting what is the difference between the .swap and swap!?
06:46TEttingerI don't think there's a .swap that you're expected to use?
06:46Olajydok
06:46TEttingerthat would be calling the java API which I guess you could do... but it wouldn't have a lot of clojure benefits
06:47TEttingerwhen I say java API
06:47TEttingerI meant the java that clojure for the JVM is coded with
06:47TEttingerand that's not the same as the standard java lib that clojure often should use, like for strings
06:48Olajydgotcha
07:02jaaqoI think it read somewhere appending ! to a function name is to say this function has side-effects please be careful
07:04anedoes evaluating the t/ann form of core.typed run the type checker?
07:05aneoh. no it does not.
07:23OlajydI have a compare function to get the maximum value, (reduce #(if (pos? (compare % %2)) %1 %2) [[" " "2009/12/02"] ["4" "2005/02/08"] ["0" "2014/12/02"] ["5" "2005/08/01"] ["2" "2007/09/02"]]) ;=>["5" "2005/08/01”] but I want to go the comarison based on column 1, to give ;=> ["0" "2014/12/02"]
07:24Olajyd,(reduce #(if (pos? (compare % %2)) %1 %2) [[" " "2009/12/02"] ["4" "2005/02/08"] ["0" "2014/12/02"] ["5" "2005/08/01"] ["2" "2007/09/02"]])
07:24clojurebot["5" "2005/08/01"]
07:24tdammersanother selmer question: I need to iterate over a list of things, and use the current iteratee as an index into another thing
07:24tdammerssomething like:
07:25tdammers{% for item in items %}{{ descriptions[item] }}{% endfor %}
07:25tdammersexcept that Selmer doesn't have that kind of syntax
07:25tdammersI tried creating a "lookup" filter, such that I could write:
07:25tdammers{{ descriptions|lookup:item }}
07:25tdammersbut it only works when I pass a string literal
07:26tdammersI can't seem to pass the second argument to that filter from an iteration variable
07:26OlajydTEttinger, you there?
07:27tdammersoh crap, my custom filter gets passed the string "item"
07:31tdammersI think it's time to find a better template library
07:32oddcullyOlajyd: don't compare the whole vector but only the second element
07:37Olajydyeaa
07:38Olajydoddcully any ideas on how to do that?
07:38oddcullydestructuring, `second`
07:39Olajydin the compare function?
07:40oddcullythis is where you find out, what the smaller/larger item, right?
07:40oddcullys/what/&s/
09:28dstocktonis there a debugger that can work with vim/fireplace that anyone has had success with?
09:28dstocktoni tried cider but i couldnt get it to play nicely with evil
09:29anewhat problems did you have with evil and cider?
09:42chomwittwe can see in repl with ns-map changes we make to the current ns with refer. is there a command to do the same for require ?
09:43justin_smithchomwitt: ns-refers iirc
09:45justin_smith no, that's not it
09:46justin_smithchomwitt: ns-aliases works if you used :as when requiring
09:47justin_smithotherwise, just the fact that another ns required does not change your own ns (of course a refer changes ns-map)
09:51visofhi guys
09:51visofhow can i do this haskell using clojure? take 10 (iterate (2*) 3) ?
09:51dstocktonit just wasnt instrumenting right ane, i think the shortcuts are often conflicting
09:51visof[3,6,12,24,48,96,192,384,768,1536]
09:51justin_smith,(take 10 (iterate (partial * 2) 3))
09:51clojurebot(3 6 12 24 48 ...)
09:52visofjustin_smith: what partial do?
09:52dstocktonevil just makes me uneasy and i dont like the default emacs shortcuts
09:52justin_smithvisof: it's a pathetic, weak, incomplete, disappointing substitute for currying
09:53justin_smithvisof: but since we have varargs, it's pretty much the best we can get it seems :P
09:53chouserwow. I wasn't even sure automatic currying was a good idea.
09:54justin_smithchouser: I miss it so much :P
09:54chouservisof: (patial * 2) is basically the same as (fn [x] (* 2 x))
09:54chouserjustin_smith: from?
09:54justin_smithchouser: ocaml, and it's (fn [& args] (apply * 2 args))
09:55justin_smith,((partial * 2) 3 4)
09:55clojurebot24
09:55chouseryes, less "basically", but yes. :-)
09:56visofjustin_smith: chouser thanks guys
09:56visofcan i do composition of functions in clojure?
09:56justin_smithcomp
09:56justin_smith,((comp inc inc inc) 0)
09:56clojurebot3
09:56visofthanks
09:58justin_smithchouser: I only exaggerate my disappointment with partial because I've had people try to tell me partial was the same as currying (which of course it isn't)
09:58chouserrighto
09:58justin_smith"I miss currying now that I do clojure" "but partial is currying" "..."
09:59chouserauto currying and succinct composition are nice for golfing in IRC, but the Clojure code I've been in for the last several months would I think have only been worse if auto currying were used
10:00chouserif (foo a b c d e f) invokes foo but (foo a b c d e) invokes nothing and returns a fn, slightly mystifying code would be even harder to comprehend.
10:01justin_smithchouser: yeah, currying was just an idiom I missed, but the idiom makes little sense without strong typing, and varargs are a nice tradeoff in the end
10:01justin_smithbecause yeah, with clojure's version of type enforcement the errors would be very hard to track down
10:02chouseryeah, I can see that static typing would help reduce the errors between the original code author and the computer
10:02chouser...but subsequent human readers might still have unnecessary difficulty following along
10:03chouserI say "unnecessary" because partial, which is just as good as currying.
10:03justin_smith:P
10:03justin_smithI can almost accept "just as good", given the other trade offs, it's "is the same as" that sets me off
10:04mungojellytyping and testing both seem to me like basically the same strategy: have two versions of the code so they can check each other
10:05justin_smithmungojelly: they also act as documentation - making things explicit that can easily be ambiguous in clojure code
10:06tdammersthe main difference is that tests are blacklists, types are whitelists
10:06mungojellyi really don't understand why we don't use any strategies that match more than two things? maybe because we're too lazy even to do two, usually. :/
10:06tdammers(only really works when everything is typed though)
10:07justin_smithI wish I could get my team to do tests or data types. At least one of those. Hell, I'd settle for some assertions in the code at this point :P
10:08Bronsapuredanger: why is CLJ-1809 no longer in the 1.8 list? it's a serious regression caused by the direct linking changes
10:11oddcullyjustin_smith: lead from the front ;P
10:12justin_smithoddcully: I write tests and use schema. And then I end up needing to deal with accusations that I'm wasting my time doing so.
10:12justin_smithI'm not the lead
10:16snowellGetting management to look past RIGHT NOW and see the value of testing is way harder than it should be
10:16mungojellydoes clojure have yet one of those cute things where you put a test in the form of a transcript in the doc string
10:16justin_smithyou can attach a test as metadata to a function, in practice most of us prefer putting tests in their own namespace
10:19tdammerscommon problem: management prefers irrelevant quantifyable metrics over relevant unquantifyable metrics
10:19Bronsa(inc tdammers)
10:19lazybot⇒ 1
10:20justin_smith(inc tdammers) that's about it
10:20justin_smith(inc tdammers)
10:20lazybot⇒ 2
10:20tdammersI think this happens more often the deeper an organisation's hierarchy
10:21tdammerswith deep hierarchies, almost all managers are somewhere in between the adjacent levels
10:21tdammersso they have to somehow make it such that whatever their subordinates do, they can produce quantifyable evidence that it wasn't their fault
10:23mungojellyconversely, is our intuition true that making coherent stuff that does what we want is what's important, lots of people seem to be profiting off code that just does some unpredictable something, maybe that's exciting
10:26sobelit is exciting
10:26sobeljust..not in the good way
10:28tdammerssomething about local optima
10:28justin_smithmungojelly: in practice, without some kind of typing and/or testing and/or docs you end up with an unmaintainable system
10:29justin_smithnobody knows how to work on anyone else's part of the code base
10:30justin_smithyou can't make large scale changes because too many things break, without any indicators of what your root causes of the bugs are, or where the real error is happening
10:30mungojellyi can accept that economic pressures make most code crap but also shouldn't there be some good code somewhere also, maybe just for fun, sigh
10:30tdammersthere is plenty of good code in the world
10:31mungojellyjustin_smith: but everybody knows that and they still tell us to make unmaintainable brittle systems, are they really getting it wrong or are supple systems more cost than they're worth
10:32mungojellytdammers: can you recommend a project in clojure i should read? i need to read some good code that makes me feel better about the world
10:32justin_smithmungojelly: when the brittleness forces a full rewrite (which I have seen plenty of times) I take that as a sign that suppleness would have been worth it - building it supple once is easier than building from scratch twice
10:33justin_smithI've worked on plenty of clojure projects that wouldn't have happened if the ruby code that preceded it had been more supple
10:34tdammersmungojelly: haven't been doing enough clojure to suggest anything here, but there should be plenty
10:35tdammersmungojelly: I could recommend a bunch of Haskell projects...
10:42mungojellyi've been really annoyed as i've tried to learn to program by the absolute lack of simple interfaces to anything, it's very difficult to learn when nothing at all is simple, and i'm convinced there's no good reason at all
10:43mungojellyhere's my first attempt at throwing a ladder back down to my fellow newbies: working title "7by7grid" it's an interface where what you pass around is lists of 49 RGBA colors
10:44sobelwhen i worked in a ruby shop i saw a lot of OO development
10:45mungojellyso then to make a piece that participates in that interface you just have to print out like 00000000 FFFFFFFF repeat for a while and it shows black and white stripes, etc., it goes right from print hello world to printing something pretty
10:45sobelthey talked about FP but i only saw the clojure developer(s) doing it
10:45visof,(take 10 (rest (iterate (partial * 2) 3)))
10:45clojurebot(6 12 24 48 96 ...)
10:45visof,(rest (iterate (partial * 2) 3))
10:45clojurebot(6 12 24 48 96 ...)
10:46visof(rest (iterate (partial * 2) 3)) guys this expression will return lazy too?
10:46mungojellymost of the functional programming i've seen is basically the same shape as OO anyway, instead of "objects" there's "data" and instead of mutation there's the "next version" of the data
10:54puredangerBronsa: just ticket juggling for Rich
10:55puredangerHe wanted 1805 and 1809 at the top of a list somewhere and this was easiest
10:59sobelmungojelly: sounds good to me. i regularly find pure functions much easier to debug and to compose.
11:01mungojellysobel: yes they work better even if what you're writing in them is a translation of an OO feeling, you can more easily put time travel in because you're more um in control of the data. but so rarely do i feel like the programs i'm reading actually feel functional at heart.
11:02mungojellylike in a book about functional programming there's this beautiful ahhhhh quality to it, and then real life "functional" programs are always mostly really just poking slowly with sticks at piles of data
11:04mungojellythey have god objects, except they're smashed apart into a god pile of data and a god associated set of functions-- which is what an object is, if you think about it
11:04sobelok, i have no idea what you're talking about or trying to do
11:04sobeli make things that work and it's easier in clojure
11:05mungojellyyou'd think if you went to any even moderately large funcitonal program you'd find in there lots of awesome functions that do useful things, which you could then take out and compose into different programs, but no, it's a function like do-specific-thing-to-only-my-pile-of-data
11:06sobelo_O
11:07sobeli can't share your offense that application code is meant for one application, especially when it's built in clojure. the data structures make application core dev pretty easy already.
11:08sobelother languages need lots of (reusable) glue to make them modular, but with lisps you just get right to business because the language provides plenty of glue
11:09mungojellyobviously at some level you have your application specific code, but it would be nice if it were using parts that are as general as possible so everyone else could pick them up and do something else with them
11:10sobelhave you perused clojars?
11:10mungojellyonly a little so far! do you have any particular recommendations?
11:11sobelmost of the community uses leiningen which resolves depedencies through maven repositories, clojars being the main community clojure module repo
11:12mungojellyyeah i've used leiningen to install a few things and clojars was where they came from
11:12sobelok, so if you're looking for a library, search "<topic> clojars" and you should end up in a useful spot
11:14sobelthat may be why you're not seeing library code in applications.
11:28Leonidasmungojelly: I kinda disagree that typing and testing is the same, because typing is not really a second version of your code.
11:29mungojellyLeonidas: yeah it's not another version of the same thing, but it's another related program, a similar but much vaguer program that just says which thingies can flow where
11:30Leonidasmungojelly: yeah, kind of.
11:30Leonidasthe vagueness is depending on your type system, ranging from untyped to hmm, dependently typed.
11:30mungojellyare there any other things in that pattern? like, other versions of your code that you prop it up with. documentation, except if it's only written for humans no one checks it apparently. :/
11:31Leonidasgenerative testing?
11:33mungojellyi've watched like three talks about generative testing now and it sounds cool but i haven't actually used it yet
11:33Leonidasdepending on the problem it can be quite awesome.
11:34mungojellyyeah it doesn't actually fit the problem i'm working with. maybe i should make myself a better problem.
11:36mungojellyi like evolving code and there you get selection, which is similar to testing but less absolute, you can test a variety of things and score them on a curve rather than just pass/fail
11:37sobeli wouldn't like to use code that is tested on a curve
11:37sobelif i need a use case to work, i'd like its unit test to pass
11:37deiodeiodeioI'm using an external library with obscenely verbose logging (through clojure.tools.logging). How do I adjust its log level?
11:38mungojellysobel: well it depends on what it's for, but you can do both, you can say absolutely fail if you don't pass these tests, also i grade you on how fast you did them
11:39sobelperformance is pass-fail to me, too
11:41sobelthat said, performance is often great, but i know where my risk areas are from experience
11:41mungojellyprofiling you break it down and make variations in a quality and inquire, which one runs better. generally people seal it back up and put the "better" one as the one it does, done. another perspective is to keep both possibilities and let it find for itself which one is better, then it can adjust if the "better" path turns brittle.
11:42deiodeiodeio:(
11:43mungojellyi'm astonished by all this code that only knows one way to do each thing. of course it falls over often, there's no understudies for anyone.
11:43sobeldeiodeiodeio: check the docs of the library you used
11:43sobelmungojelly: not sure what you're talking about. my database has a smart execution planner for queries but everything else doesn't need that kind of complexity.
11:44deiodeiodeiosobel: the library does not provide any facilities for setting log levels
11:44sobeldeiodeiodeio: get a better one?
11:44deiodeiodeioer, there is just one
11:44sobelthere's only one logging library for clojure?
11:44deiodeiodeiowhat, no, read what I wrote again
11:45deiodeiodeiothe library I'm using uses clojure.tools.logging
11:45deiodeiodeioliberally
11:45deiodeiodeioand I want to shut it up so I can see my output
11:45deiodeiodeiopreferably without writing any log4j files
11:46snowellI have a physical reaction to seeing log4j/slf4j anymore. No other library produces breaking API changes and incompatible versions like they do
11:47deiodeiodeioyeah me too
11:47sobellooks like i went with timbre
11:48sobeland it has a set-level! function that takes reasonable values like :info
11:48deiodeiodeiohowever, it doesn't seem like clojure.tools.logging exposes any methods of setting verbosity: https://clojure.github.io/tools.logging/
11:49deiodeiodeioyeah, with timbre I would jut re-bind *config* and it would be fine
11:49sobelthe only thing that threw me for a loop with it was it used a background logger, which required i call (shutdown-agents) to exit smoothly
12:00deiodeiodeioanyone? it seems like it shouldn't be hard, but I'm kind of stuck here
12:00justin_smithdeiodeiodeio: clojure.tools.logging is just a frontend to the java logging stuff - it doesn't have anything for setting log levels, I think you'll need to make a .properties file
12:01justin_smithor a log.xml, or whatever
12:02justin_smithdeiodeiodeio: the README for clojure.tools.logging has a 5 line log4j.properties you can copy/paste, the first line sets the output level
12:02justin_smithhttps://github.com/clojure/tools.logging
12:03deiodeiodeiojustin_smith: yeah, thanks.. I would just rather not pollute my project with log4j files just because a library I'm using uses it
12:04justin_smithdeiodeiodeio: they made that decision already - unless you know an alternative that doesn't use log4j, that's where you are at
12:04deiodeiodeioactually, (with-redefs [clojure.tools.logging/log (fn [& args])] (call-to-external-library)) seems to work :)
12:04justin_smithoh man that's evil
12:06rhg135Isn't log usually a macro?
12:07justin_smithrhg135: in this case it is one, yeah https://github.com/clojure/tools.logging/blob/master/src/main/clojure/clojure/tools/logging.clj#L69
12:08justin_smithnow rebinding log* I could see working with with-redefs, but I am surprised rebinding log would work
12:09deiodeiodeioyeah, that would make it problematic
12:09justin_smithdeiodeiodeio: log calls log*
12:09justin_smithbut I still think configuring the lib is better than monkey punching it
12:09deiodeiodeiorebinding log worked it the repl.. rebinding log* seems to work regardless
12:10rhg135Me too, justin_smith
12:10deiodeiodeiojustin_smith: sure, but I refuse to give up now
12:10justin_smithbe careful, monkeys throw poop if you get them mad enough
12:11deiodeiodeiohah
12:11rhg135Monkey punch is a phrase I have not heard in this context
12:11justin_smithrhg135: it's a less innocuous rephrasing of "monkey patch"
12:12justin_smithrhg135: because you are doing something violent to the other code, not just altering it
12:12mdeboardWhat's the difference between "parking" and "blocking" wrt <! vs. <!! in core.async
12:13justin_smithmdeboard: whether the thread is allowed to do other work while your condition waits
12:13mdeboardWill it read from the channel when there is something available?
12:13justin_smithmdeboard: with parking, the thread that was running your code can be reallocated by core.async to do other work
12:13rhg135Yeah, I'd say rebinding a macro name to a function is very bad
12:13justin_smithmdeboard: in both cases your thread resumes execution when data is available, the difference is what is done with your resources while waiting
12:14mdeboardAha thanks justin_smith
12:14mungojellyis the convention here both macros and functions are spelled all lower case? is there some reason they should look the same?
12:14justin_smithmungojelly: upper case is for Classes
12:14justin_smith(not by restriction, but by convention)
12:15justin_smithmungojelly: in lisps functions and macros have always looked the same, as long as the two have existed
12:16mungojellyis it for a reason though? intuitively i feel like maybe it could be useful to macro-ify something that's already a function to change existing code, so i guess it's consistent with that
12:16mdeboardSorry for this stupid question but I'd need to use like `(go-loop [] (do-stuff (<! my-channel)))` to read from the channel in a loop right?
12:17justin_smithmdeboard: well, for that to actually loop you would need a call to recur somewhere
12:17mdeboard(throw a `recur` in there)
12:17mdeboardyeah
12:17mdeboardlol
12:17justin_smithright, yeah, that is pretty much it
12:18mdeboardOk cool
12:19justin_smithmungojelly: it's a convention dating to at least the '60s if not the '50s. I don't know if there is a lot of discussion since then even? I can see a rationale for wanting the difference between special-form, macro, function to be clear though
12:19mungojellyi wasn't born then but from what i've seen i seem to remember it being ALL CAPS ALL THE TIME at first for a while
12:19sobelfrom a tooling perspective i don't want them to be different
12:19justin_smithmungojelly: of course in C where macros have totally different compilation rules and can make whitespace changes totally break your code, UPPER_CASE_MACROS() are needed
12:20justin_smithmungojelly: right, they were case-insensetive, but there was no naming convention that separated special-forms, macros, and functions
12:21justin_smithmungojelly: I had generalized from "upper case" to "any sort of typographical distinction"
12:25mungojellythe early naming conventions in lisp do make it pretty clear they expected you to look up and memorize what every symbol means, nothing about them is guessable, they're not mostly even ordinary words
12:25justin_smithmungojelly: unlike C, lisp style macros don't have lexical gotchas (they don't transform code on a string manipulation level) and while you have to watch out for using them in invalid ways (eg. they are not functions you can pass to a higher order function, they bind values at compile time) the errors won't be nearly as bizarre if you get it wrong
12:26mungojellyjustin_smith: i do understand that in theory but it slips my mind how macro hygiene actually works, does clojure like put a random number at the end of the real name of all your stuff?
12:27justin_smithmungojelly: we don't have actual hygeinic macros, but the ` (syntax-quote) reader-macro does namespace qualify symbols and forces you to use gensyms for new bindings
12:27justin_smithwhich in practice eliminates 98% of the accidental capture problems
12:28mungojellyoh hmm namespace qualify, that makes sense because i've noticed in clojure it's very consistent everything gets namespaced
12:28justin_smith'`(foo)
12:28justin_smith,'`(foo)
12:28clojurebot(clojure.core/seq (clojure.core/concat (clojure.core/list (quote sandbox/foo))))
12:28justin_smithit's verbose, but note how an explicit namespace was added
12:28justin_smithmakes capture much less likely
12:29mungojellyok i see, and that's a good-enough replacement for that actually ideal hygiene algorithm that's complicated enough to have slipped my mind
12:30mungojellyclojure in general seems very practical
12:31justin_smithmungojelly: I re-learned syntax-quote and syntax-case so many times and they still haven't stuck
12:32justin_smith(that is, the scheme version)
12:32justin_smitherr s/syntax-quote/syntax-rules
14:10mdeboardAnyone have any guidance on why this function is not writing to a file but instead returning the `chan`? https://gist.github.com/mattdeboard/431ef638ba64848d247c
14:11justin_smithmdeboard: with-open closes the file on exit, go-loop exits immediately and does its thing in another thread, and returns a chan
14:11justin_smiths/file/writer
14:11justin_smithcloses the writer on exit
14:12mdeboardI see, should I be opening the file inside the go-loop?
14:12justin_smithso what's happening is that the writer is being closed before the code in the go-loop even runs
14:12mdeboardOh, weird.
14:12mdeboardok
14:12justin_smithno, because then it would close before you run the next loop cycle
14:12mdeboardCan I pass the open file as a variable
14:12mdeboardin the `loop` call
14:12justin_smithand go loops don't work with the paradigm of with-open
14:12mdeboard`go-loop`
14:12mdeboardAhhh
14:12mdeboardOk. Huh.
14:12mdeboardSo jus tmanually open/close
14:12justin_smithsince the task can pass between multiple threads etc.
14:12justin_smithyeah
14:13mdeboardMmkay
14:13amalloyjustin_smith: i don't see why that's a problem. you can't use go-loop, but you can use go
14:13amalloy(go (with-open [...] (loop [...] ...)))
14:13justin_smithyeah, I would use lexical closure to access the writer, and then have a task that reads the return chan of the go-loop then immediatly closes and cleans up
14:14justin_smithhmm - and that works despite the parking and such that go is doing?
14:14amalloyof course. that's what go is for, making stuff look sequential
14:14amalloywith-open is just a let and a try/finally, and you know those work
14:15justin_smithamalloy: I guess I expected some weird interaction between the with-open block and the go block, but if they work together, that's handy
14:15amalloyit's not like the FileOutputStream or whatever cares what threads are writing to i
14:15amalloyt
14:15mdeboardHm
14:16amalloyi mean, in fairness i have never tried any of this. but based on how i understand these things to work i would be fairly surprised to be wrong
14:16mdeboardamalloy, https://gist.github.com/mattdeboard/c566cf94a9e510cf86d6 doesn't seem tow ork
14:16justin_smithmdeboard: what exactly fails?
14:16mdeboardThere's just no writing to the output file
14:17amalloymdeboard: try something simpler. write some fixed characters to a file
14:17justin_smithmdeboard: there's no control flow in your code that would cause that loop to exit and thus let the with-open close the writer
14:17justin_smithmdeboard: instead it will sit there and wait for more messages, not letting the with-open shut down
14:17mdeboardok yeah that works
14:18justin_smithso perhaps read until the channel is closed
14:18justin_smithor until you get a magic ::flush value
14:18justin_smithor whatever
14:24amalloyso that actually works, right? it writes things?
14:24mdeboardamalloy, Yep just was a bomb because I'm an idiot and didn't ever exit the loop -_-
14:24mdeboardIn my defense I'm on a phone conference.
14:24amalloyokay that's fine. it's just i was trying to prove it to myself locally and never really use core.async so i am doing stuff wrong
14:25amalloylike i expected https://www.refheap.com/35a77d388881dec359d7174c9 to work but apparently it doesn't
14:26justin_smithamalloy: my concern is the try/catch of the with-open making any sense when you have parking inside
14:26amalloyjustin_smith: go's rewriting code addresses try/catch i'm fairly sure
14:26justin_smithOK
14:26amalloywhy would you worry about try/catch and not about, say, let or loop?
14:26amalloythose are all equally as squirrely
14:26justin_smithhmm...
14:27amalloyor even about function calls, like (println (<! ch))
14:27mdeboardSadly I use clojure so rarely nowadays I remember precious little :(
14:28justin_smithamalloy: I am familiar with let bodies that have multiple threads inside seeing their bindings, for example, but I have no existing model for a try/catch that jumps across thread boundaries
14:28justin_smiththough I admit a park inside the binding vector is weird to me conceptually as well
14:29amalloywell, it't not really multiple threads, of course. it's one thread at a time, possible totaling more than one thread
14:29justin_smithright, but even the one at a time thing interacts oddly with my mental model of try/catch, though this is probably just exposing my ignorance
15:16mdeboardGosh darnnit I do not understand D:
15:19Bronsapuredanger: wrt your tweet, do you want a ticket concerned with just making `satisfies?` faster or with moving the cache from the method level to the protocol level as I suggested as a possible solution?
15:22uptowndoes anyone know whether core.async pub/sub subscribers need to be explicitly unsubscribed from their topics or just close!d to remove them?
15:22uptownand, i suppose, whether publishers clean up internally afterwards?
15:25uptownthere's no doc coverage anywhere that i can find
15:30mdeboardamalloy, justin_smith, turns out using an exception was being swallowed, presumably because of the goroutine, in my usage of `apply`
15:31justin_smithmdeboard: full discussion of that "swallowing" http://stuartsierra.com/2015/05/27/clojure-uncaught-exceptions
15:31justin_smithmdeboard: tl;dr: that's what java does by default for exceptions not in your main thread, you should explicitly use try/catch
15:31mdeboardNice
15:31mdeboardPerfect, thanks.
15:32mdeboardHere's the working form https://gist.github.com/mattdeboard/c566cf94a9e510cf86d6
15:32mdeboardoriginal seen https://gist.github.com/mattdeboard/c566cf94a9e510cf86d6/revisions
15:33justin_smithmdeboard: nice, and the .flush is a good touch too
15:33mdeboardI learned it by watching you, alright?
15:33mdeboardbut seriously you mentioned flushing and it made sense
15:34justin_smithahh, right
15:38mdeboardStupid quesiton probably
15:38mdeboardbut calling bufferedWriter.flush() clears the buffer right?
15:39justin_smithI would expect that, but I don't have proof handy.
15:41mdeboardI'd expect it too but I'm getting some unexpected results
15:42mdeboardI don't think it does no
15:45amalloyjustin_smith: well, by default clojure prints uncaught exceptions to the console
15:45amalloyer, java does
15:45amalloyit's *clojure* that makes those messages hard to find
15:45justin_smithamalloy: as the article says, in the main thread, not in other threads
15:46justin_smithI've had (especially core.async) threads just swallow expections with no printing, exactly as stuartsierra describes
15:46justin_smith*exceptions
15:46amalloythat has not been my experience in java, and i remember core.async at one point had a (try (do-your-stuff) (catch Exception e)) or something very like it
15:46amalloybut i could be remembering something wrong
15:48justin_smithamalloy: (do (.run (Thread. #(fn [] (Thread/sleep 10000) (/ 1 0)))) nil) ; won't work in a bot, of course
15:48justin_smithamalloy: that will print nothing
15:49amalloyjustin_smith: for example, try (doto (Thread. #(throw (Exception. ""))) (.start))
15:49amalloyit doesn't print anything in your repl buffer in emacs, but it *does* go to stdout, which is lein's process
15:49justin_smithahh, my example above was broken
15:50amalloy(and you can see that if you look at the *swank* buffer, or *nrepl* or whatever)
15:50justin_smithyeah
15:50amalloyException in thread "Thread-11" java.lang.Exception: at user$eval2239$fn__2240.invoke(c3f4f6ddbaf4ac46782f4c04098f05de409d4881-init.clj:1) at clojure.lang.AFn.run(AFn.java:22) at java.lang.Thread.run(Thread.java:745)
15:50justin_smithI'm just using a terminal, you are right
15:51amalloyanyway, i think the default uncaught exception handler *is* to print to stderr, but a lot of clojure programs don't make it easy to see stderr
15:51amalloyso i don't really approve of blaming that on java
15:53justin_smithamalloy: yeah, I just double checked and I also get the stack trace in a vanilla java -jar repl
15:53justin_smithamalloy: so clearly something stuartsierra is blaming on java is actually happening in clojure land (maybe core.async related) because I have definitely seen the behavior he is talking about there...
15:53amalloyyes
15:53xemdetiaits a shame the jvm doesn't give you some sort of namespace to output file pipe without some weird logging lib
15:54justin_smithxemdetia: you can do it with timbre (dunno how timbre rates on the weird scale for you though)
15:56xemdetiajustin_smith, it does look good for new stuff but I have a lot of drunk ponies I am leading around with log4j already :(
15:56xemdetiaI will have to make a note
15:58amalloyjustin_smith: the catch in https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L885 is a fun one
15:58amalloybut probably not the issue in this particular case
16:00justin_smithamalloy: odd, I see the map function but no try at that link
16:01amalloyerrr, scroll down a bit? it's right there
16:02justin_smithoh, duh
16:02amalloyhttps://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L462 is another suspicious customer. if i do something equivalent to this uncaught business in my repl, nothing prints to the repl but only to lein's stderr
16:02amalloy(this is probably lein's fault, or nrepl's, rather than core.async's, since i don't think core.async can really do any better)
16:03mdeboardWhat's this syntax doing? `(let [{deletes :in-chan} (some-chan-generating-func)])`
16:03mdeboardspecifically the map
16:03mdeboardas the first binding for let
16:04mdeboardIs it some kindof map-deconstructing bind?
16:05mdeboarddestructuring bind*
16:05justin_smithmdeboard: destructuring
16:05justin_smithyes
16:05justin_smith,(let [{a :a} {:a 42}] a)
16:05clojurebot42
16:06justin_smith,(let [{{{c :c} :b} :a} {:a {:b {:c 42}}}] c)
16:06clojurebot42
16:08justin_smith,(let [{{{[one two three] :c} :b} :a} {:a {:b {:c [41 42 43]}}}] two)
16:08clojurebot42
16:08justin_smithperhaps destructuring would be more pleasingly consistent if it grabbed items from sequences backwards
16:15devnWith defrecords you can add arbitrary key value pairs
16:16devnHow does this affect performance, if say you have 5 fields specified in the record definition
16:16devnand you add tack on an additional k/v pair
16:16devnwhere the field is not specified
16:17justin_smithdevn: the fields defined for the record are still (incrementally) faster, unless you dissoc one of the defined keys, then you get a vanilla map back iirc
16:17amalloydevn: there's an extra implicit field named __extmap, which is just a map of all the non-basis keyvals specified for this instance
16:17amalloydo you? i thought you just couldn't do that
16:17amalloy,(defrecord Foo [x])
16:17clojurebotsandbox.Foo
16:17amalloy,(dissoc (Foo. 1) :x)
16:17clojurebot{}
16:18amalloy,(class (dissoc (Foo. 1) :x))
16:18clojurebotclojure.lang.PersistentArrayMap
16:18amalloyhuh. has it always been that way?
16:18justin_smithamalloy: as long as I remember
16:18justin_smithI recall Bronsa complaining about some annoying consequences of this for his project
16:22Bronsaamalloy: yeah it has
16:22Bronsajustin_smith: no, no, my issue was a bug with record literals, which is fixed in 1.8
16:23justin_smithoh, cool
16:23Bronsawhich I noticed yesterday actually caused a bug in scheme a while ago
17:20kavkazI have a function which requires several functions I defined myself. I probably won't be reusing them elsewhere. Right now I have them defined with letfn. Is it better to define them with defn or just keep it this way and not have any of them in the namespace?
17:21kavkazI read somewhere, perhaps in a book that you should use anonymous functions (or functions of that nature) within a function and not pollute the namespace
17:21kavkazbut I'm not sure if it's idiomatic to have long Clojure functions
17:21justin_smithkavkaz: I'd call that a style choice.
17:22justin_smithkavkaz: a compromise would be a top level letfn (though that would be weird), or use defn- to make private definitions
17:22blake_Testing is easier if you let them pollute the namespace.
17:24justin_smithblake_: that's true, but I usually prefer the thing where tests cover what you expose publicly, rather than testing all the internals
17:25justin_smiththen again lately I'd settle for tests existing at all :P
17:25blake_justin_smith: That's--hah--probably a good clue, though, I think: If it's something you need to test, maybe it's not a good idea to bury it.
17:26justin_smithvery good point
17:27kavkazjustin_smith: I see.
17:27kavkazThe thing is that the three functions are in a top-level letfn
17:27justin_smithkavkaz: another consideration is that fp and oo sometimes have different philosophies about what is hidden and why
17:27kavkazI might as well just define them with defn
17:27kavkazAh I see
17:28justin_smithlike in fp you want to be able to hide your implementation details so consumers don't break a data structure abstraction, but expose state
17:29justin_smithso it might be OK to expose functions (as long as they preserve your key data structure abstractions)
17:29kavkazjustin_smith: Interesting, I kind of get what you're saying. Can you give me an example?
17:30justin_smithkavkaz: if you implemented an immutable data structure, but had a setter method that mutated it for performance reasons, I would hide the setter
17:31justin_smithif you have a helper function that doesn't break your data abstraction, but simply implements part of your implementation logic, that's not as bad to expose
17:31justin_smithas long as that helper doesn't allow mutation of some sort, or breaking some other invariant your lib assumes / exposes
17:31kavkazjustin_smith: Ah I see, that makes sense now
17:32kavkazHonestly these functions are just part of a large procedure.
17:32justin_smithkavkaz: given that we are using immutable data for most things in clojure, we don't have to be quite as careful about hiding things - the damage a misbehaving client can do is reduced
17:32justin_smithkavkaz: yeah, I figured, that's the normal thing in clojure code
17:33blake_A big difference from OO to FP is that FP doesn't require as much encapsulation, since there's a philosophy of avoiding side-effects.
17:33justin_smithright
17:33kavkazI've seen in a Clojure book before the author using multimethods and protocols, but I've never touched those two before
17:33justin_smithkavkaz: those become more helpful if you are writing a library where you want end users of the lib to provide concrete functionality
17:33justin_smiththe kind of thing that gets called IOC or DI in OO
17:34kavkazOh I see. It's like abstract class in Java?
17:35kavkazProtocols that is... sort of?
17:35justin_smithkavkaz: protocols are backed by java interfaces
17:35hlolliJustin Smith, just curious, are you not also a csound user?
17:35justin_smithor well, jvm interfaces, which are what also backs java interfaces
17:35justin_smithhlolli: yes I am, I use csound a lot (but not at work)
17:35kavkazI mixed up abstract classess and interfaces
17:35justin_smithwell, they are very similar in usage, yeah
17:36justin_smithmultimethods are similar, but they allow more flexibility in dispatch
17:36justin_smithand "default implementations" which are similar to abstract class funcitonality in a way
17:37hlolliOk, Im programming alot with csoung API in Clojure. Maybe you can help me with one thing, since I'm trying to live code with csound using clojure. I'm trying to find a way to make add-watch non-destrucitve. There is to say, if I put an errorous function in add-watch function, it will not fail the Agent and stop everything?
17:37justin_smithhlolli: so I assume you follow the csound mailing list? I've been active there on and off.
17:37hlolliYes that's where this name rang a bell.
17:37kavkazjustin_smith: blake_ Thanks for your helps, I gotta go now
17:37blake_kavkaz: NP
17:38justin_smithhlolli: have you checked agent-error and set-error-handler!
17:38blake_Wow, csound, that takes me back.
17:39justin_smithhlolli: there's a few related things all listed together here - http://conj.io/ - if you check the section about agents
17:39hlollinope, will do!
17:39justin_smithblake_: csound is still alive
17:39blake_Yeah, but it's been years since I played with it.
17:40justin_smithblake_: it looks like there may be a new version of cecelia supporting csound again coming out before long
17:41hlollinice, I will check it out. I've made some algorithms for live-coding but Im hoping to use more recursion. I think I also need to read more about multimethods, there is to say, the way a pattern would behave with different instruments. But that is for future task.
17:41blake_justin_smith: Neat.
17:41justin_smithblake_: also, csound supports live instrument definition, and multi-core
17:42justin_smith(or, newer versions do that is)
17:42blake_Gonna say, it's come a long way.
17:56teomaWhere do asynchronous Quil exception messages go in Cider? I don't see them in the REPL or error buffers, but I've confirmed they appear when starting `lein repl' from the shell.
17:56hlolliOk I looked into set-error-handler! and agent-error. Both of those will not prevent an agent failing, only saving last value without error in a failed agent. My failures are coming trough add-watch wathcers. So If there's a way that the watcher would not evaluate an errorous function in the first place, then it would never fail an agent. I'm thing about some catch/throw kind of way, but maybe validators could work too?
17:58hlolliHave you tried teoma, nREPL buffer, if you're using cider-jack-in it should be created in emacs.
17:59teomahlolli: is that *nrepl-messages*? I don't see the error there...
18:00hlollinrepl-server? Do you have that window? Im currently using shell to create lein repl and I use cider-connect so I may be wrong about the buffer name.
18:01justin_smithhlolli: what about putting a try/catch on your watching function?
18:01justin_smitherr, inside
18:02teomahlolli: *nrepl-messages* seems to be the only buffer with nrepl in its name.
18:02hlolliweird, are you using cider-jack-in?
18:03teomahlolli: yes.
18:04hlolliEither you must have closed that buffer accedentaly, can try closing cider and restart it. Or there's some cider setting you have that prevents nrepl-server from being generated. Assuming you are using the moser recent version of cider and cider-nrepl.
18:05hlolli(dont know what happens when pasing code to irc)
18:05hlolli(defn event-register [instr p-name matrix pattern]
18:05hlolli ;[instr p-name & {:keys [on-tikk]}]
18:05hlolli (add-watch x-agent (keyword (apply str (name p-name) "-play"))
18:05hlolli (fn [k r old-state new-state]
18:05hlolli (let [on-tikk (event-calculator matrix pattern)
18:05hlolli mod-div (->> (map #(Math/ceil (/ (+ % 0.0001) 256)) on-tikk)
18:06hlolli (apply max)
18:06hlolli (* 256))
18:06hlolli pat-len (count on-tikk)
18:06hlolli t-256 (mod (new-state :t-stack) mod-div)
18:06hlolli ]
18:06hlolli (if (not= (new-state :t-stack) (old-state :t-stack))
18:06hlolli (if (some #(= t-256 %) (map double on-tikk))
18:06hlolli (do (eval instr)
18:06hlolli
18:06hlolli (prn (mod (new-state :t-stack) 256))
18:06hlolli ;(prn instr on-tikk "?") ;(prn k (new-state :bar) (new-state :section))
18:06hlolli (send (eval (symbol "hlolli.clock" p-name)) (fn [p-map] (assoc p-map :arp-index (mod (inc (p-map :arp-index)) (p-map :arp-len)))))
18:06hlolli )))))))
18:06hlolli
18:06justin_smithhlolli: please use refheap.com for code samples
18:06hlolliok, sorry wont do that again. But since it's here, can you see a good place to set the watcher, justin?
18:06hlolliok will do! sorry
18:07teomahlolli: I have Cider 0.9.1. Maybe it's because nrepl-log-messages is nil (the default).
18:08teomahlolli: Oh, actually it's not nil, though the default is nil.
18:08sdegutisJust stopped by to apologize for my recent behavior. I've been insufferable, arrogant, haughty, boastful, rude, disrespectful, and in general impolite. I'll do my best to not be such an annoyance anymore, and to be much more grateful for all your help. On that note, thanks for all your help everyone.
18:09noogawow
18:09hlolliDid you configure ~/.lein/profiles.clj and set cider-nrepl version etc?
18:09teomahlolli: yes, I have :plugins [[cider/cider-nrepl "0.9.1"]] there.
18:10justin_smithhlolli: you could surround the let block with a a try/catch that just prints the exception
18:11hlolliok nice thanks Justin, will try that!
18:11justin_smithhlolli: also your eval could be a resolve call (and that would be much better)
18:11justin_smitherr, the one wherey you have (send (eval ...)) that is
18:11noogahlolli: what's that code for?
18:13hlolliIt's a time-schedule function, takes in numbers that are triggered from 0 to 255 and the iteration speed of the counter that is modulo of 256 is adjusted by beats per minute. A way to quickly create musical timing patters. But this is one way of many possible. With less code I always loose freedome but gain coding speed.
18:15noogahlolli: overtone huh?
18:15hlolliok, will try resolve call. But this part of the function is just to update pattern info, so it iterates note index so I can make arpeggio patterns or scale patterns.
18:15justin_smithnooga: not overtone, overtone has at-at which is much simpler than this
18:15justin_smithin fact, you might find it helpful to look at at-at for a good example of scheduling recurring timed tasks
18:16justin_smithor even use at-at even if not using the rest of overtone :)
18:16hlolliI only use overtone for timing, there's to say, I have an impulse coming from overtone, that's all. All else is Csound based.
18:16noogaI discovered extempore recently
18:17noogait's not clojure but looks interesting, fast enough to perform synthesis on the fly
18:18hlolliI tried metro and chnset for csound. But csound events are inaccurate from +/- 100ms while coming from overtone it's +/- 5ms, can't find a way to get this same accuracy from csound. But then again I know supercollider developers have been really progrimming a good accurate clock while csound development has too little been based on live-coding etc.
18:18hlolliwell, "synthesis" itn't extempore all sample based?
18:20justin_smithhlolli: it supports sample-based dsp, but I don't know if it ships with anything interesting
18:20justin_smithsurely not as complete a set of ugens as csound or even supercollider would give you
18:22hlolliYes, extempore sounds good, at least from Andrew Soerensen, really liked his performance when I heard him. Also Im trying to hack with extempore since it has really good emacs multiplexer and also emacs-osc to have the letters dance with the beats.
18:22noogahlolli: you can write a function that writes individual audio samples to dsp
18:22justin_smithit's like comparing ms paint to blender, because both can do pixels on a screen, and hey, if you implemented a few functions you could probably do what blender does in paint, right?
18:23blake_No good. MS is closed source.
18:23hlolliyes, I will admit, samples sound much better, but I'm afraid that once I go samples I will get stuck there and learn little new about sound synthesis.
18:23hlolliBut I ofcourse use samples alot.
18:23noogahttp://benswift.me/2012/06/07/dsp-basics-in-extempore/
18:24justin_smithblake_: OK tuxpaint and blender :P
18:24noogathese are not samples as in prerecorded sound clips
18:24justin_smithnooga: right, that shows you how to turn pixels on and off. Now make a convincing texture of hair on a 3d character.
18:25noogawell I think it's much more flexible than ugens if you want to write a synthesizer
18:25justin_smithnooga: that's right, it's individual DSP samples. It's still very low level and getting from that to what csound or supercollider provides is years of work.
18:25noogaor at least experiment with synthesis
18:25noogawell
18:26hlollinooga, good question. I guess I could find out, I understand the basics of audio-buffers etc. But can't say I could do it now without internet. Audio programming book would be good source for this. But I guess javasound would be the tool to use.
18:26blake_Which is cool, man. If that's what you're interested in. I still like to write DBMSes...
18:26noogasome day I'll build a modular synth FROM HARDWARE >:D
18:27justin_smithhlolli: steven yi (one of the csound devs) has pink, which is a clojure project that does dsp in pure clojure
18:27justin_smithhlolli: this might provide exactly what you want - though it is young, and doesn't have a lot - but it has a whole lot more than extempore does
18:27hlolliexcacly, I've been following up on him alot.
18:28justin_smithnooga: I guess my complaint about the audio api that extempore provides is that it doesn't give me much I couldn't do myself in any language that can hook up to OS audio drivers. And if I'm going to be rolling that much on my own, why do I even need their language?
18:29hlollicsound is just such a good fully packed tool, and I know csound, so I've been too hesitant of learning pink and/or supercollider. But I did go deep into overtone.
18:30noogajustin_smith: don't know, but I'm sure Andrew had a blast writing it
18:34teomaI heard a Rich Hickey lecture where he said Overtone's scheduler suffered from problems that core.async could address. Just curious, do you know what he meant?
18:44hlolliNo, problems I have been having when trying to prorgam schedulers is that when the state: time is on a specific state and should do event on that state, then the time state could live long enough for more than one event to shoot off. But it's not connected to at I think.
18:47hlolliAnyhov, Justin, this worked! The agent does not crash, but the "problem" now is that I need to find a way for clojure to store my function calls, or redesign it, so that it will continue calling the last function call that worked, but it's much better, even if one pattern fails, the other will continue. But for now a major bug has been solved.
18:54justin_smithhlolli: I bet you could do something interesting with core.async, and either repeatedly sending events to a channel, or recirculating them as they are handled back to the sending function for them to come again after a delay
18:55justin_smithhlolli: what you are doing now reads as a bit clumsy - it is using some very powerful tools that clojure provides where there are more nuanced (and less powerful) tools that could make this simpler
18:57hlolliyes, this is very clumsy for sure. Im learning as Im programming. I've been looking into core.async and for sure I will give that a try for learning experience.
18:58hlolliI did try atoms insted of agents and also some schedulers at stackoverflow, but so far using agents and watchers, I've been able to get the most accurate results. Don't know why, but I just experiment with lot of things and choose the best result.
19:01hlolliwell, the force behind the clock is overtone, form there I have on-event function handler that send counted ticks from impulse to a numberpile that is stored in agent, from the agent I will control the events. These agents could be dismissed perhaps but I need some way of storing pattern info in a map etc.
19:01justin_smithhlolli: the way you are using the agent with watches, you could have a go-loop per instrument, and a pub/sub (a writer to a publishing channel replacing the agent, readers of subscriber channels replacing the watches)
19:03hlolliyes defenitely, I'm very new to core.async, but it shouldn't take a long time to switch over. I may need to rewrite the code anyway to make it more clear and easy to read.
19:09hlolliit's 1am in berlin, so I need to hit the bed. Hope to talk later Justin! Gute Nacht.
19:13amalloyi should start using that. "sorry guys, it's 1am in berlin. i gotta go"
19:14gfredericks~g2g is <reply> It's 1am in berlin
19:14clojurebotIk begrijp
19:14gfredericks~g2g is <reply> pager just went off
19:14clojurebotAlles klar
19:14gfredericks~g2g is <reply> realized haskell is better
19:14clojurebotAck. Ack.
19:15gfredericks~g2g is <reply> personal segfault
19:15clojurebotYou don't have to tell me twice.
19:16ferz_Hello gents, I crash my REPL when I try to bind input to symbol like so (def data (slurp *in*))
19:16sdegutisWhen running some clojure.test tests via CIDER, and you get an error, is there a way to show what line triggered the error?
19:16gfredericksferz_: shouldn't (slurp *in*) hang?
19:16sdegutisAll it tells me is the name of the exception (NullPointerException).
19:16ferz_Am I doing something wrong? I am able to get initial input but then it crashes with an exception after I run more commands
19:16gfrederickssdegutis: I'd check *e in the repl
19:16sdegutisgfredericks: oh cool never knew about *e thanks.
19:17gfredericksnp
19:17ferz_gfredericks: I think it does but I ended my input with ctrl-d , whats the standard way to get input and bind it to a symbol
19:18gfredericksferz_: depends how much you want
19:18sdegutisIs a lexer or parser a good use-case for using transducers?
19:18ferz_gfredericks: so I have to manually specify something?
19:18sdegutisIt seems kind of like it's right up its alley, but I can't be sure.
19:23ferz_I have 4 lines coming in from user input, how do I capture them / bind every word to one long vector for reuse?
19:24sdegutisferz_: It's not clear what you're asking, what the context is.
19:24ferz_sdegutis: that's the context hackerrank.com/challenges/diagonal-difference
19:28sdegutisOkay.
19:30ferz_So whats the standard way to capture the input in a variable.
19:31sdegutisferz_: Probably just read *in*.
19:31sdegutisferz_: (slurp *in*) I'm guessing.
19:31sdegutis,(slurp *in*)
19:31clojurebot""
19:32sdegutisThat should do it I bet.
19:33ferz_right except this is what I get http://pastebin.com/UFm0SV3L
19:34sdegutisferz_: It probably won't work inside a REPL due to the nature of a REPL hijacking *in* for your convenience.
19:34sdegutisferz_: test it using normal standard-input procedures in a terminal.
19:34ferz_oh so it's the REPL issue then? Technically it's not my code per se?
19:36ferz_I know there is a (flush) function so I was thinking maybe I am forgetting it or something.
19:38amalloyif you slurp *in* you close *in* afterwards, and then the repl can't read new commands from you
19:38amalloyyou can just slurp (string-reader "1 2 3 4") instead, and then later replace that with *in* when you're running for real
19:39ferz_hm, I'll try that
19:39sdegutisferz_: basically, write your code to take an input, and in the real code use *in*, and while testing use (string-reader "1 2 3 4\n")
19:40sdegutisferz_: a normal function parameter will suffice for this
19:40ferz_I'll try that, thanks
19:43ferz_I know I probably sound retarded but I am new to Clojure and trying to learn it by solving some challenges online but they are very specific in their input and etc. it gets confusing with Clojure.
19:48neoncontrailsferz_: have a look around. There's lots of challenge sites, and I think they each attract a certain demographic
19:49neoncontrailsMy personal favorite is Project Euler. It's not Clojure specific, but you'll learn a lot implementing 10 solutions or so
19:50ferz_I did some Euler before, it's pretty math heavy unfortunately
19:52neoncontrailsThere's usually a mathematical interpretation to those problems that can help you avoid brute-force labor, that's true
19:53TEttingermy favorite clojure problem is "make it short enough to do something unusual but also fit in one IRC message"
19:54neoncontrailsI'm not sure that they're really "math problems," in the sense that what they really require is a bit of sophistication and cleverness with how you approach large numbers and number sequences that will blow your stack if you're not careful
19:54TEttingerI think of euler as math-heavy personally
19:54ferz_yeah thats heavy CS/Math lol
19:55TEttingerI never got past pre-calculus in college
19:55ferz_I tapped out at Calc 2 so I haven't studied anything beyond that
19:56neoncontrailsBoo calculus. Hooray linear algebra
19:56neoncontrails(I never truly fancied math until LinAlg)
19:56ferz_See, I didn't even get to that
19:56ferz_I am sure I wouldn't mind other mathematics but Cal 2 (integration) got me good..
19:57ferz_I did well in Trig, Geometry, Algebra
19:57neoncontrailsConsider taking it if you like computers. You'll find it a lot more relatable than calculus, certainly
19:57ferz_I wouldn't be able to that's the thing.
19:57ferz_I had to switch majors eventually
19:58neoncontrailsDon't be so hard on yourself! Linear algebra doesn't necessarily depend on calculus. At some schools it's not even a prerequisite
19:59ferz_I might watch online lectures, that's about it
20:00neoncontrails@ferz_: You might enjoy this essay. Strang's terrific -- and his lectures are online, free! http://www-math.mit.edu/~gs/papers/essay.pdf
20:00ferz_it is a pre-req in my uni lol
20:00ferz_I am mostly disillusioned by college anyway
20:01ferz_had a teacher for "C programming" who didn't know about K&R.
20:07neoncontrailsCan someone show me how to format this code to take an operator as input and apply it to the expression? http://pastebin.com/BzV4LA7Y
20:08neoncontrailsThis works for adding x and y, but I had to manually write in the +. (apply (:val @op) [x y)) doesn't work here
20:09neoncontrailsPretend I closed that vector
20:10justin_smithneoncontrails: you'd need [(:val @x) (:val @y)]
20:10neoncontrailsOh, right. Good call
20:11justin_smith,(do (def op (atom +)) (def x (atom 12)) (def y (atom 30)))
20:11clojurebot#'sandbox/y
20:12justin_smith,(apply @op [@x @y])
20:12clojurebot42
20:12neoncontrailsOutstanding!
20:12amalloy(quote + arg) seems super wrong
20:13justin_smithneoncontrails: of course you would also need to do the :val dereference for your version
20:13amalloy,(quote + arg)
20:13clojurebot+
20:13justin_smithneoncontrails: though fyi you can put things other than hash-maps in atoms
20:13justin_smith(as above of course)
20:14neoncontrailsjustin_smith: Can you explain briefly what (do ...) is doing here?
20:14justin_smith,(quote x y z a b c d e f g wat)
20:14clojurebotx
20:15justin_smithneoncontrails: it lets me make less screen scroll by putting three defs in one clojurebot command
20:15neoncontrailsHaha, bravo. So it's not strictly necessary
20:16justin_smith,(quote x (System/exit 0) (println "WAT"))
20:16clojurebotx
20:24neoncontrailsjustin_smith: Just to clarify your example and amalloy's, what's the issue with the way I used quote?
20:25neoncontrailsI recognize that it's not correct, but I'm not sure I understand why
20:27amalloyquote receives a single expression, and protects that expression from evaluation: in (let [x 1] [x, (quote x)]), x evaluates to 1, but (quote x) evaluates to x
20:27amalloygiving quote more than one expression just makes no sense
20:28hiredmanhttp://dev.clojure.org/jira/browse/CLJ-1282
20:28hiredmanthe comments on that issue
20:28neoncontrailsI see. I was hoping the quote might be a wrapper I could use to safely pass operators around without evaluating them
20:29neoncontrailsBut that was just a hope
20:56mdeboardthanks to amalloy and justin_smith I am now poised to reap sweet, sweet StackOverflow points http://stackoverflow.com/questions/23600387/how-do-you-write-to-a-log-file-in-clojure-using-core-async/32491340#32491340
20:56mdeboardLook at me, I am the expert now
20:58dbaschmdeboard: that’s good, because when Stack Exchange goes public they’ll issue shares to users proportionally to their karma points
20:58mdeboardSweeeeeeeeet!
20:58mdeboardI have a whole 430
20:59dbaschmdeboard: I just made that up of course
20:59mdeboardThat puts me in 95th percentile I'm sure
20:59mdeboarddbasch, Too late, you said it, You're liable
21:00dbaschhaving one upvoted answer probably puts you in the 95th percentile
21:00mdeboard(I do not give a rip about SO karma etc., I was being cheeky :))
21:01mdeboard(I also do not actually know how SO works)
21:06amalloymdeboard: you are actually in the top 4% of SO users
21:07diminishedprimeIf I'm writing a macro and want to name an argument "name" as in [name & rest], is there a way to do that without running into issues from clojure.core/name ?
21:07mdeboardwat.
21:07mdeboardI guess the bar is pretty low.
21:07amalloyyes, it is
21:07mdeboardand the user base is high
21:07mdeboardi.e. huffing spray paint
21:07amalloyor wait maybe i am doing bad math?
21:07mdeboarddiminishedprime, I'd say don't call it 'name' or any other .. name that stomps stdlib functions.
21:08mdeboard-name, name- are easy alternatives
21:08mdeboardthing-name, etc., etc.
21:08amalloyhttp://stackoverflow.com/users/495154/mattdeboard claims top 68%, but http://stackexchange.com/leagues/1/alltime/stackoverflow/2008-07-31/495154#495154 makes it look like your rank is pretty high
21:08mdeboard...leagues?
21:08mdeboardwelp
21:08amalloyoh, that's all of stackexchange
21:08mdeboard*deletes account*
21:10diminishedprimemdeboard: I suppose that'd be the best solution. Is there a generally accepted practice for naming when you want to name something that's already in the stdlib?
21:10diminishedprimemdeboard: I.E. -name- vs name-
21:11amalloyit is good fun to call it name, and then later try to call clojure.core/name
21:11amalloyi don't know why you would want to rob yourself of that adventure
21:11mdeboarddiminishedprime, I sure don't know. Local (to your codebase) consistency is more important than a language-wide stylebook (unless we're talking about Python)
21:12mdeboardJust generally you should avoid stomping built-ins :)
21:13diminishedprimemdeboard: Yeah, that makes sense. I didn't really think of what the overall effect would be to override "name" (or for that matter if it's even possible), but I see that if anything else in that namespace was using the stdlib name, then there'd be some serious issues.
21:15mdeboardwell it would only matter inside that function body of course
21:16diminishedprimemdeboard: Yeah, but that body is potentially quite large, the macro system would be used for a dsl for some business folk.
21:16mdeboardi see
21:19diminishedprimemdeboard: Thanks a lot!
21:20mdeboardyou're welcome
21:40chomwittcontrary to some tutorials i've read in the lein repl i can use (fully qualified) symbols from other ns , like clojure.string or ns defined by me. How can i check which namespaces have been required(loaded) in the current ns?
21:40amalloychomwitt: namespace loading is global. if someone else loads a namespace, the stuff in it comes into existence and anyone can use it
21:41amalloybut you generally should specifically require anything you need, so that you don't rely on "oh this other file is loading the namespace i need" and then that stops working when namespace load order changes or whatever
21:44chomwittamalloy: the strange to me is that none introductory material i've read is clear (to me at least) on this topic.
21:44chomwittfor example first time i learn that namespace loading is global (what ever that means exactly, cause i'm newbie in clojure) :-)
21:46chomwitti've have an ebook in front of me now that says that in a repl in a ns i must require clojure.set.. but i use it with no require
21:46justin_smithchomwitt: well, some code somewhere alreayd required it
21:46chomwittexcept if that require happens one time per session and i've forgot it
21:47amalloychomwitt: there are a lot of things you "must" do, like look both ways before crossing the street, but there's no law of physics that forces you to
21:47amalloymost of the time, no car hits you
21:47amalloybut it's still something you should do
21:48chomwittjustin_smith: should i reboot my pc to reset and test a fresh repl so that nothing would have already 'required clojure.set or whatever?
21:48amalloyjustin_smith: clojure.core requires clojure.set and clojure.string
21:49justin_smithchomwitt: no, that's not really needed
21:49justin_smithamalloy: oh, I wasn't aware
21:50justin_smithamalloy: in a virgin java -jar repl, clojure.set/union gives me a ClassNotFoundException for clojure.set
21:50justin_smith:P
21:50justin_smithI wouldn't be surprised that every other lib ever written uses both those though
21:51chomwittso maybe 'lein repl' does some things differently..
21:51TEttingerI rarely use clojure.set for some reason
21:51justin_smithoh, it definitely does
21:51emdashcommaYesterday I was facing an awkward REPL situation
21:51emdashcommaI put the code at the end of Ch. 4 of Brave Clojure in a file and then opened a REPL -- I got a lot of runtime exceptions
21:51chomwittjustin_smith: was that line related to my last one?
21:52emdashcommaI then typed all of it into a REPL outside of that project, and it worked fine -- what's going on?
21:52justin_smithchomwitt: yes - lein repl uses nrepl, that loads a bunch of things that are not present in a "vanilla" clojure.jar repl
21:52chomwittjustin_smith: thanks
21:52justin_smithemdashcomma: which functions were causing the errors
21:53emdashcommaLet me get the exact line
21:54chomwitti think i'd help me to have a command like 'ns-map' to check the status of loaded (required?) ns in my current one. now i probe with TAB to see what's loaded.
21:55emdashcomma> Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: create in this context
21:55emdashcomma'create' is nowhere in the code, though
21:55justin_smithchomwitt: all-ns
21:55amalloyjustin_smith: what about clojure.string?
21:56justin_smithamalloy: that one is loaded
21:56amalloyprobably clojure.repl loads string then, not clojure.core
21:57justin_smithamalloy: nope, clojure.repl is loaded here https://www.refheap.com/109368
21:57chomwittjustin_smith: thanks again .
21:58justin_smithchomwitt: here is a fun one: (into {} (map ns-publics (all-ns)))
21:58amalloyright, i said string, not set. i wasn't disagreeing with you
21:59amalloyi was clearly wrong about clojure.set, and also concluding that it's probably not clojure.core that loads clojure.string, but clojure.repl
21:59alif-baaemdashcomma: and what code were you running
22:00chomwittjustin_smith: thats a lot output do digest !
22:01emdashcommahttp://pastebin.com/PtFpNvrj
22:03justin_smithchomwitt: see also clojure.repl/apropos
22:03justin_smith,(clojure.repl/apropos "namespace")
22:03clojurebot(clojure.core/namespace clojure.core/namespace-munge)
22:04justin_smith,(clojure.repl/apropos-doc "namespace")
22:04clojurebot#error {\n :cause "No such var: clojure.repl/apropos-doc"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: No such var: clojure.repl/apropos-doc, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "No such var: clojure.repl/apropos-doc"\n :at [clojure.lan...
22:04justin_smith,(clojure.repl/apropos "apropos")
22:04clojurebot(clojure.repl/apropos)
22:04justin_smithhmm, must be an extension I forget where from
22:08justin_smith,(clojure.repl/find-doc "namespace")
22:08clojurebot-------------------------\nclojure.core/*data-readers*\n Map from reader tag symbols to data reader Vars.\n\n When Clojure starts, it searches for files named 'data_readers.clj'\n at the root of the classpath. Each such file must contain a literal\n map of symbols, like this:\n\n {foo/bar my.project.foo/bar\n foo/baz my.project/baz}\n\n The first symbol in each pair is a tag that w...
22:08justin_smiththat's the one, repl/find-doc, searches for a string and regex in clojure doc strings