#clojure logs

2015-08-25

00:00justin_smithTEttinger: are you suggesting that different amounts of structural sharing would happen with different jvms?
00:01TEttingerI'm fairly certain that's currently the case for Sun's JVM on JDK 6 and strings versus OpenJDK 6
00:01andyfTEttinger: I'm actually not writing much code (yet). Turns out there is a "Java Object Layout" library that does most of the "peeking under the covers" work for me. I'm mainly writing a little bit of code to use that and measuring memory footprint of a few Clojure data structures.
00:02andyfIf I get energetic enough, I may also write some code to generate graphs that can be layed out with GraphViz to show their structure.
00:02TEttingerjustin_smith: I know there are a lot of references to ???.sun.??? packages when profiling string-array or even char[] heavy code
00:02justin_smithinteresting
00:03TEttingerone of those is the implementation of string internally I think, and it may change for large and small strings (like arraymap being used for small {} maps in clojure)
00:04andyfOne little fact I hadn't noticed before -- Every PersistentVector, no matter how few elements it has, allocates an array of 32 references, which are all null for vectors with < 32 items.
00:06andyfIt probably eliminates some extra cases in the code or something, but seems like a waste if the common case is short vectors.
00:07justin_smithandyf: isn't that what ztellman's big optimization with tuples was about?
00:07justin_smiththe one that wasn't able to merge in because of 1.7 changes iirc
00:11andyfjustin_smith: That optimization would eliminate that chunk of otherwise unused memory, yes.
00:12andyfIt was also expected to speed things up in other ways other than avoiding that extra memory, I thought.
00:14OlajydHi TEttinger
00:15TEttingerhey Olajyd!
00:16Olajyduhmmm vey well thanks, and you?
00:16Olajyd*very
00:16andyfOops. My mistake. I didn't realize until now that this null vector I mentioned was the same null vector shared by all short vectors. It isn't a unique new one for every short vector. So not really much a waste of memory at all.
00:17OlajydTEttinger, I ran into a problem and thought I should Ping you :)
00:18TEttingerwhat's up?
00:19TEttingerso far we've covered... most of the weird edge cases in clojure in like the first week and a half. so this is a good start :)
00:20TEttingerif it isn't covered by the standard library, somehow the tasks that you have been given have been almost certain to find that problem, haha
00:22taliosif I have a sequence [1 2] - whats the easiest way of splicing that with [:a :b] to return a map of {:a 1 :b 2} - nothing simple jumps out me?
00:24justin_smith,(zipmap [:a :b] [1 2])
00:24clojurebot{:a 1, :b 2}
00:25talioshah - and I just hit zipmap :)
00:25taliosin the docs
00:25OlajydTEttinger, haha, yea.. thanks :)
00:25taliosI knew there was something I was mssing, and I was thinking zippers or zip-with :)
00:26OlajydTEttinger, here’s the code on pastebin https://www.refheap.com/108697
00:26justin_smith,(defn zippedy-do-da [coll] (zipmap '[zippedy do dah zippedy day my oh my what a wonderful day] coll)))
00:26clojurebot#'sandbox/zippedy-do-da
00:26justin_smith,(zippedy-do-da (range))
00:26clojurebot{zippedy 3, do 1, dah 2, day 11, my 7, ...}
00:27talios:P
00:27justin_smithsorry, that was silly
00:28TEttingerOlajyd: hm, just so you know, if you try to read numbers prefixed with 0, they are treated not as decimal numbers (which allow 0-9 as digits), but octal (only 0-7, with "010" representing what would normally be 8)
00:28TEttinger,010
00:28clojurebot8
00:28TEttingerthe examples are all fine, and if they stay as strings there's no issue
00:28OlajydTEttinger, ok
00:29OlajydTEttinger, I wanted to be able to change the index 0 of `prev-col-val`
00:30taliosoh nREPL how I love thee. NOT.
00:31talioswhats worse than an uber long stacktrace? ONLY showing the first line of a stacktrace, that inside PersistentHashMap
00:31OlajydTEttinger, so that I can make reference to it, the `prev-col-val` seem to keep track of the previous column value, that the way I thought of solving the problem though
00:31taliosPersistentArrayMap actually
00:31justin_smithtalios: you can do (.printStackTrace *e)
00:31justin_smithtalios: *e always points to the last exception
00:32taliosw00t - and thats solve it. stupid repl - I'd reworked some code, then re-ran from repl history - which assumed a different data structure :)
00:35OlajydTEttinger, I dont knw if thats the way to go anyway, what do you think?
00:35TEttingerI think I have an... unusual and small solution
00:37OlajydTEttinger, this is data immuability problem right?
00:38TEttinger,(defn replicate-header-value [col data] (reductions (fn [a b] (if (empty? (nth b col)) (assoc b col (nth a col)) b)) data))
00:38clojurebot#'sandbox/replicate-header-value
00:38TEttinger,(replicate-header-value 1 [["04" "2" "3"] ["04" "" "5"] ["5" "16" ""] ["07" "" "36"] ["07" "" "34"] ["07" "25" "34"]])
00:38clojurebot(["04" "2" "3"] ["04" "2" "5"] ["5" "16" ""] ["07" "16" "36"] ["07" "16" "34"] ...)
00:39TEttingerclojurebot cuts off output if the sequence is too long, but it looks right
00:39TEttinger,(replicate-header-value 2 [["04" "2" "3"] ["04" "" "5"] ["5" "16" ""] ["07" "" "36"] ["07" "" "34"] ["07" "25" "34"]])
00:39clojurebot(["04" "2" "3"] ["04" "" "5"] ["5" "16" "5"] ["07" "" "36"] ["07" "" "34"] ...)
00:40TEttinger,(replicate-header-value 2 [["5" "16" ""] ["07" "" "36"] ["07" "" "34"] ["07" "25" "34"]])
00:40clojurebot(["5" "16" ""] ["07" "" "36"] ["07" "" "34"] ["07" "25" "34"])
00:40TEttingeryep, if the header has an empty string it doesn't change it
00:40Olajydok
00:40TEttinger,(replicate-header-value 1 [["5" "16" ""] ["07" "" "36"] ["07" "" "34"] ["07" "25" "34"]])
00:40clojurebot(["5" "16" ""] ["07" "16" "36"] ["07" "16" "34"] ["07" "25" "34"])
00:40TEttingerdo you want me to explain it?
00:40Olajydyes please :)
00:41TEttingerreductions is one of my favorite rare-ish clojure functions. when you encounter a problem that can be solved with reductions, you sometimes have much shorter code
00:42TEttingerso it acts almost exactly like reduce, but instead of returning only the final result of calling the given function on each pair, it instead returns each result it got along the way (and the first element is the same as the first element of the collection, I think)
00:42Olajydoh nice, this is the first time I’m seeing reductions though, TEttinger,
00:42TEttingerit's an uncommon one. I have found it comes up not often, but often enough to be useful
00:43TEttingerthe fn that I pass to it likely needs explaining.
00:44TEttinger(fn [a b] (if (empty? (nth b col)) (assoc b col (nth a col)) b)) ;; reductions, like reduce, takes a pair of args. a is the previous value that reductions generated (and it will be in the final result). b is the upcoming element from the collection we pass
00:45Olajydok great, thanks
00:45TEttingerit checks if the nth item in the upcoming element (which is b) at position col is empty. since "" can be treated like a seq, (empty? "") returns true, since it's an empty sequence of characters.
00:46OlajydTEttinger, out of curiorsity, what was I doing wrong in the problem?
00:46TEttingerI honestly didn't check that closely since I was pretty sure there was a less complicated way
00:47TEttingeryou're right, it's immutability related
00:47TEttinger(assoc prev-col-val 0 (get row col)) doesn't change prev-col-val, it returns a new copy
00:48TEttingerso that was just doing the modification and throwing it away right after
00:48Olajydhmm, now I get it :)
00:48TEttingeryou would likely want to go about that way using loop/recur, which can be complicated sometimes, or an atom, which is effectively mutable
00:49TEttingerloop and recur are preferred for a number of reasons, but an atom is fine while you're learning
00:50TEttingeroh and the last part of the function: (assoc b col (nth a col)) ;; this just takes the upcoming arg, changes the col with the empty string to the previous value's string in the same column
00:50TEttingerthe " b" at the very end is the else block of the if
00:50TEttingerso it returns the upcoming arg unaltered if it isn't empty in the column
00:53OlajydTEttinger, thanks :)
00:53TEttingerglad to help!
00:54Olajyd8) , I’ve adjusted my time so that I can meet you online, :D
00:54TEttingerhaha nice
00:55TEttingeryeah it seemed earlier than before
00:55TEttingergreat!
00:56OlajydHopefully tomorrow I’ll ping you
00:57ttt_fffis anyone here from a haskell background? I used to love clojure, but after 2 years of haskell, I find prefix notation and ()'s very hard to get used to
00:58TEttingerttt_fff, interesting. personally I find haskell hard to read when it uses $
00:58TEttingerotherwise it's rather clean
00:58ttt_fffi find the pattern matching notation / type sigs very concise
00:58ttt_fffmore so than any macros I can rig up with ()
00:58jeayettt_fff: I'm just the opposite.
00:58jeayeCan't stand the haskell syntax, really love s-exprs
01:00TEttingerI kinda stopped caring about syntax a while ago
01:00ttt_fffi'm writing a new config langauge
01:00ttt_fffand need to decie between haskell like vs scheme like
01:00TEttingerhaskell's going to be harder to parse I imagine
01:00arrdemwhy are you writing your own parser...
01:00TEttingerhave you looked at Io?
01:00arrdemjust use datastructures
01:01arrdemI'm sure there are several fine Haskell config file readers
01:01arrdemno need to run off and invent a new language
01:01TEttingeryou could even use something that "looks" like haskell but really just pattern matches/regex replaces to clojure/scheme data structures
04:09gilliardGiven a fn, 'f', which takes a single number and returns a single number, I would like to find the value in (range 1 n) which produces the largest output when fed into f. What's a neat way to do that?
04:12TEttinger,(max-key (mapv #(.nextInt (java.util.Random. %)) (range 1 100)))
04:12clojurebot#error {\n :cause "Wrong number of args (1) passed to: core/max-key"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: core/max-key"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.RestFn invoke "RestFn.java" 412]\n [sandbox$eval26 invokeStatic "NO_SOURCE_FILE" 0]\n [sand...
04:13jeayegilliard: Maybe naive, but map f over the range, then sort, then take the first.
04:13TEttinger,(doc max-key)
04:13clojurebot"([k x] [k x y] [k x y & more]); Returns the x for which (k x), a number, is greatest."
04:13kungiI am currently watching magnars Parens of the Dead videos. In there he uses "clj-autotest" in emacs which I can't find on ELPA. Any idea where this elisp file comes from?
04:14TEttinger,(into (sorted-map) (map (fn [n] [n (.nextInt (java.util.Random. n))]) (range 1 100)))
04:14clojurebot{1 -1155869325, 2 -1154715079, 3 -1155099828, 4 -1157023572, 5 -1157408321, ...}
04:15TEttingerah
04:15TEttinger,(into (sorted-map-by val) (map (fn [n] [n (.nextInt (java.util.Random. n))]) (range 1 100)))
04:15clojurebot#error {\n :cause "Wrong number of args (2) passed to: core/val"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (2) passed to: core/val"\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" 36]\n [clojure.lang.AFunction compare "AFunction.java" 47]\n [clojure.lang.Pe...
04:15TEttinger,(into (sorted-map-by second) (map (fn [n] [[n (.nextInt (java.util.Random. n))]]) (range 1 100)))
04:15clojurebot#error {\n :cause nil\n :via\n [{:type java.lang.UnsupportedOperationException\n :message nil\n :at [clojure.lang.APersistentVector key "APersistentVector.java" 452]}]\n :trace\n [[clojure.lang.APersistentVector key "APersistentVector.java" 452]\n [clojure.lang.APersistentVector getKey "APersistentVector.java" 131]\n [clojure.lang.APersistentMap cons "APersistentMap.java" 29]\n [clojure.lan...
04:15TEttingeragh
04:16gilliardjeaye: Yeah that was my idea but I'm hoping for something simpler...
04:17magnarskungi: It's a work in process. You can find all my Emacs settings in https://github.com/magnars/.emacs.d :)
04:17jeaye(first (sort > (map f (range 1 n)))) is simpler than everything shown above, I thinkg
04:17oddcully,(apply max-key (fn [x] (* x x)) (range 5))
04:17clojurebot4
04:18magnarskungi: so if you want to give it a shot, the code is here https://github.com/magnars/.emacs.d/blob/master/site-lisp/clj-autotest.el
04:19gilliardjeaye: That gives me the maximum value for (f n) but I want to know which n produces that.
04:19jeayegilliard: My mistake
04:19kungimagnars: Thank you!
04:22gilliardThanks oddcully
04:22gilliard,(doc max-key) ; basically restates my question :)
04:22clojurebot"([k x] [k x y] [k x y & more]); Returns the x for which (k x), a number, is greatest."
04:23oddcully(inc TEttinger)
04:23lazybot⇒ 64
04:23gilliard,(source max-key) ; is nice too
04:24clojurebotSource not found\n
04:25TEttinger,(apply max-key #(.nextInt (java.util.Random. %)) (range 5))
04:25clojurebot2
04:26TEttinger,(apply max-key #(.nextInt (java.util.Random. %)) (range 500))
04:26clojurebot402
04:26TEttingernice
04:26TEttinger,(.nextInt (java.util.Random. 402))
04:26clojurebot-1000815519
04:26TEttingerhm
04:26gilliardlol
04:26TEttingerthat seems not right
04:26TEttinger,(.nextInt (java.util.Random. 2))
04:26clojurebot-1154715079
04:26TEttinger,(.nextInt (java.util.Random. 0))
04:26clojurebot-1155484576
04:27hyPiRionTEttinger: next int is just a random int based on the seed you gave it
04:27TEttingerare they all negative???
04:27lazybotTEttinger: Yes, 100% for sure.
04:27hyPiRionoh
04:27TEttingerI know
04:27hyPiRion,(.nextInt (java.util.Random. -1155484576))
04:27clojurebot-1764305998
04:27TEttingerwhat on earth...
04:27hyPiRion,(.nextInt (java.util.Random. -1073741824))
04:27clojurebot664794208
04:27hyPiRioncoincidence I guess.
04:28TEttinger,(map #(.nextInt (java.util.Random. %)) (range 5))
04:28clojurebot(-1155484576 -1155869325 -1154715079 -1155099828 -1157023572)
04:28TEttingeryeah... that seems like a LCG problem
04:28oddcullyquick, get the booky! TEttinger is on a run
04:28hyPiRionLooks like the first value isn't that non-random
04:29TEttinger,(map #(.nextInt (java.util.Random. %)) (range 5))
04:29clojurebot(-1155484576 -1155869325 -1154715079 -1155099828 -1157023572)
04:29TEttingerit's seeded hyPiRion
04:30TEttingerwhat's weird is that it seems like for a large consecutive range of seeds, the first number is negative...
04:30hyPiRionTEttinger: What I meant was that the highest bits of the first value seems to be very similar
04:31BorePlusPlusIf I have namespaces in format like this: migrate/step_01.clj, migrate/step_02.clj, migrate/step_03.clj and I would like to get a list of all functions called up from namespaces step-01, step-02 and step-03, is this something that is streaightforward to do?
04:31hyPiRion,(map #(let [r (java.util.Random. %)] (.nextInt r) (.nextInt r)) (range 5)) ;; looks fine here
04:31clojurebot(-723955400 431529176 1260042744 -1879439976 -396984392)
04:31TEttinger,(map #(.nextInt (java.util.Random. %)) (range 36rRANDOMNESS 36rRANDOMNESX))
04:31clojurebot(-559045358 -559430107 -558275860 -558660609 -548272389)
04:31TEttingerinteresting
04:31gilliardyes, it looks like any two consecutive seeds produce pretty close nextInts
04:32TEttinger,(map #(.nextInt (java.util.SplittableRandom. %)) (range 36rRANDOMNESS 36rRANDOMNESX))
04:32clojurebot#error {\n :cause "java.util.SplittableRandom"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassNotFoundException: java.util.SplittableRandom, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6891]}\n {:type java.lang.ClassNotFoundException\n :message "java.util.SplittableRandom"\n :at [java.net.URLClassLoader$1 run...
04:33gilliard,(map #(.nextInt (java.security.SecureRandom. (byte-array %))) (range 50))
04:33clojurebot(-956323137 -1820334814 -1691674753 533104038 1374720712 ...)
04:33luxbockmagnars: is the command you use to insert () and slurp a built-in, your own custom fn or do you just press ( and slurp really quickly one after another?
04:33TEttinger&(map #(.nextInt (java.util.SplittableRandom. %)) (range 36rRANDOMNESS 36rRANDOMNESX))
04:33lazybotjava.lang.ClassNotFoundException: java.util.SplittableRandom
04:34magnarsluxbock: it's paredit-wrap-round, bound to M-( by default I think
04:35luxbockmagnars: ah cool
04:35TEttingerwoah what, neither bot uses java 8 now? https://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html
04:36kungimagnars: when are you releasing the next video for PotD? It inspired me to rewrite large parts of my Emacs config yesterday and really learn clj-refactor. :-)
04:36TEttingerhuh, must not be used by lazybot at least. my lazybot gives (-522495519 1499783386 -58986586 574128689 1912616253)
04:37oddcully(frequencies (map #(compare (.nextInt (java.util.Random. %)) 0) (range (Integer/MAX_VALUE)))) ; {-1 1073739864, 1 1073743783}
04:37magnarskungi: hah, glad to hear that :) the next episode will be out on friday
04:37kungimagnars: \o/
04:39TEttinger(frequencies (map #(compare (.nextInt (java.util.Random. %)) 0) (range 0xffff)))
04:39TEttinger,(frequencies (map #(compare (.nextInt (java.util.Random. %)) 0) (range 0xffff)))
04:39clojurebot{-1 33492, 1 32043}
04:40TEttingera ha!
04:40TEttinger,(frequencies (map #(compare (.nextInt (java.util.Random. %)) 0) (range 0xfff)))
04:40clojurebot{-1 4095}
04:40TEttingerup to 0xfff it only produces negative first numbers!
04:41luxbockmagnars: what kind of keyboard are you using?
04:41magnarsluxbock: Norwegian MBP
04:45luxbockmagnars: I was coding exclusively on the MBP keyboard for a long time but I recently purchased the Atreus keyboard from technomancy and it's really nice
04:45luxbockworks great for Emacs
04:45luxbockbecause it puts your thumbs to work
04:46magnarsyeah, that looks pretty nice - and I'm not surprised that technomancy's keyboard is Emacs friendly :) but I'm spending 2+ hours commuting on a train every day, so portability trumps all
04:48kungiluxbock: I use a kinesis advantage keyboard which is also just great for emacs and typing in general.
05:02crocketIs it possible to use robert hooke on multimethods?
06:33dxlr8rhello, any recommendations on a socket server library for clojure? I just need basic functionality
06:44notarobot_dxlr8r: http://www.luminusweb.net/docs/websockets.md
06:46dxlr8rnotarobot_: not websocket, regular socket server :)
06:58notarobot_dxlr8r: oops sorry
06:58H4nsdxlr8r: what are you looking for in a socket library, really?
07:03dxlr8rH4ns: implementing a socket in my application?
07:03OlajydHI, oddcully
07:04dxlr8rfound this in the end, https://github.com/bguthrie/async-sockets , looks ok :)
07:10OlajydHi, any advice on how to think about / model what seems inherently "stateful" in the clojure context? Is there a better way to manage "state" than passing around mutating refs? I feel like Im about to understand something bigger but am a little stuck, I have a sample code on pastebin https://www.refheap.com/108707, Can I find a way of keeping track of previous-col-val without mutating it? any suggestions? :)
07:11Olajydupdated link: https://www.refheap.com/108708
07:14dstocktonOlajyd: no expert, but I think you want to look at something like loop/recur
07:14Olajyd:|
07:14dxlr8rwas just going to suggest that :)
07:14dstocktonand pass the previous-col-val to the next iteration
07:14Olajyduhmm, I want to avoid using the loop/recur form
07:15oddcullyOlajyd: isn't this just another view on the problem from earlier?
07:17oddcullyit it is: ,(reductions (fn [old new] (if (empty? new) old new)) ["a" "" "b" "" "" "c"])
07:18Olajydyeaa, oddcully, I just want to understand it more
07:19Olajydoddcully, maybe you could shed more lights on data immuatability :)
07:20oddcullymy guess is, that this has nothing to do with mutable data
07:20oddcullybut your brain wants to write imperative code
07:22oddcullylike having a "def last" outside of the loop where you want to keep track of the last good value
07:22oddcullywith loop/recur or a reduce you just send the last good value just back into the loop
07:26negaduckhi! Are chans disposable? Is it ok to create massive number of chans and goes as a reaction to events or in a loop? Should I close chans? In this article: http://dimagog.github.io/blog/clojure/clojurescript/2013/07/12/making-http-requests-from-clojurescript-with-core.async/ -- in the GET function the author closes a chan. Is this necessary? Or this is just to make sure nobody puts anything on this chan?
07:32pseudonymousI'm feeling as if I miss something incredibly simple. But HoneySQL outputs something like ["<query>" "<arg1>" "<arg2"> "<arg3">] and I can't for the life of me figure out how to execute the damned thing. (sql/db-do-commands seems to expect a query where all the parameters are already inserted..?)
07:33schmirpseudonymous: (jdbc/query db ["<query"> ...])
07:33schmirpseudonymous: where jdbc is clojure.java.jdbc
07:33pseudonymousI tried that, though INSERT statements aren't allowed there.
07:34schmirjdbc/execute!
07:35pseudonymousschmir: O_O It works - praised be the machine god! Thank you.. Really :P I was doc'ing random functions in both honeysql's and clojure.java.jdbc's namespaces trying to find what it is I was supposed to use
07:36schmirOlajyd: IMHO you should forget about refs and atoms when starting with clojure development
07:36schmirpseudonymous: how about praised be schmir :)
07:36oddcullykarma *nudgenudge*
07:37Olajydschmir, hmmm
07:37pseudonymousschmir: You could quite possibly be one of the machine gods - if not, I'll at least petition them for your inclusion :)
07:37schmirpseudonymous: thanks :)
07:38schmirOlajyd: really. I'm developing a commercial clojure program and never used a ref
07:39schmirgit grep atom |wc -l says 16, where I have above 10k lines of code
07:40Olajydschmir, wow, so the problem is that although the use of `reductions` work for that problmem, I’m wondering what if the `rows` is a lazy-sequence?
07:40Olajyd*problem
07:41Olajydschmir, does `reductions` work with a lazy-sequence?
07:43schmirOlajyd: yes, why shouldn't it work
07:44oddcully,(take 10 (reductions (fn [old new] (if (empty? new) old new)) (cycle ["a" "" "b" "" "c"])))
07:45clojurebot("a" "a" "b" "b" "c" ...)
07:46Olajydso the thing is I’m using clojure with Apache-spark, and the apache-spark, data-structures are usually in lazy-sequences :|
07:46justin_smithreductions can take a lazy-sequence, and it returns one
07:59gfredericks,(reductions (comp second list) 5 '(0 1 2 3 4))
07:59clojurebot(5 0 1 2 3 ...)
07:59gfredericks,(reductions (comp second list) 0 ())
07:59clojurebot(0)
08:00gfredericks,(reductions (comp second list) 1 *1)
08:00clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Var$Unbound>
08:06Olajydcan somebody explain (.toJavaRDD)?
08:07justin_smithit's a method being called on no object - guaranteed to be an error unless it's inside a doto or -> or ->> chain or similar
08:09justin_smithif it is inside a doto, ->, ->> etc. then it is a method being called on whatever object is inserted into the form at compile time by that macro
08:11Olajydok
08:12OlajydThanks justin_smith
08:21Olajydjustin_smith, I got another question
08:22OlajydIs it possible to convert clojure.lang.LazySeq to toJavaRDD?
08:25justin_smithOlajyd: toJavaRDD is a method, not a class - what class does toJavaRDD belong to?
08:26OlajydI just google it though, :)
08:27Olajydbut ultimately I want to convert the clojure.lang.LazySeq to type JavaRDD
08:28Olajydtried this though (r (-> result (.toJavaRDD)))
08:28justin_smiththat's equivalent to (r (.toJavaRDD result))
08:29justin_smithwhat is result?
08:29justin_smitha lazy-seq?
08:29Olajydyes
08:30justin_smiththat's not going to work, because in the world of the jvm methods belong to classes, and nobody defined a .toJavaRDD method on the clojure.lang.LazySeq class
08:30OlajydDont knw whether i’m making a mistake though :|
08:30justin_smithI don't know spark well enough to know how one constructs RDD objects
08:30justin_smithOlajyd: are you using spark directly? are you using a lib like flambo?
08:31Olajydoh great that explains why I’m getting this `No matching field found: toJavaRDD for class clojure.lang.LazySeq` right?
08:31Olajydjustin_smith, exactly :)
08:31justin_smithyeah, it's trying to tell you exactly what I just tried to explain
08:31justin_smithOlajyd: I mentioned two options...
08:31Olajydyou farmiliar with flambo, justin_smith?
08:33justin_smithOlajyd: I saw sorenmacbeth give a couple talks about it, and I know it's a spark wrapper
08:33justin_smithI haven't used it though
08:34Olajydgreat
08:36justin_smithOlajyd: if your project is to use spark, you might find it helpful to review the docs on interop with clojure http://clojure.org/java_interop
08:38Olajydok say u want to advice, I did some of the evaluation in clojure but i need to convert it back to type RDD for further stuff, what will u suggest?
08:40justin_smithI'd look for a method in the spark lib somewhere that makes an RDD instance out of a collection or array - it's easy to turn a lazy-seq into either of those
09:02gilliard(frequencies (map #(compare (.nextInt (java.util.Random. %)) 0) (range (Integer/MIN_VALUE) (Integer/MAX_VALUE)))) ; => {1 2147483647, -1 2147483648}
09:03gilliardAs I read that, it seems impossible to get "0" as a response to nextInt...
09:03justin_smith,(frequencies (map #(compare (.nextInt (java.util.Random. %)) 0) (range (Integer/MIN_VALUE) (Integer/MAX_VALUE))))
09:03clojureboteval service is offline
09:03gilliardHow long have you got ;)
09:03justin_smithhaha
09:03gfredericksgilliard: that might be true
09:03oddcullygilliard: thought the same with half of the numbers
09:03gfredericks,(.nextInt (java.util.Random. Integer/MAX_VALUE))
09:03clojurebot-1631654733
09:04gilliardoddcully, gfredericks: yes it might be true, mightn't it?
09:05gfredericksgilliard: that's not the full seed range though
09:05oddcullygilliard: at at least as first number
09:05gfredericksI think zero should be possible, set me see if I can reverse engineer it
09:05gilliardoddcully: looking at the source of j.u.Random, I don't see how it is, but gfredericks is about to show me!
09:06gilliardoh yes, the seed is a long, and even I don't have that kind of patience...
09:06oddcullyah right it's a long. now i need pmap
09:07gfredericksgilliard: the seed is a long but it's truncated to 48 bits I think
09:07gfrederickshave to check the constructor to be sure
09:07gilliardYes: http://developer.classpath.org/doc/java/util/Random-source.html
09:08justin_smith~gfredericks |is| about to show you.
09:08clojurebotOk.
09:08gfredericksthe whole algorithm is 48 bits
09:09justin_smithhey did you guys hear that there is a new fridge that leaks your gmail credentials? the world is stupid
09:10gfredericksI don't know enough arithmetic to reverse engineer this any better than just searching higher
09:10gilliardI got interested after reading this: http://franklinta.com/2014/08/31/predicting-the-next-math-random-in-java/
09:12gfredericks,(defn java-random [seed] (-> seed (unchecked-add 0x5deece66d) (unchecked-multiply 0x5deece66d) (bit-shift-right 16) (unchecked-int)))
09:12clojurebot#'sandbox/java-random
09:12ebzzryHow/where is let* defined?
09:12gfredericks,(java-random 42)
09:12clojurebot#error {\n :cause "integer overflow"\n :via\n [{:type java.lang.ArithmeticException\n :message "integer overflow"\n :at [clojure.lang.Numbers throwIntOverflow "Numbers.java" 1501]}]\n :trace\n [[clojure.lang.Numbers throwIntOverflow "Numbers.java" 1501]\n [clojure.lang.Numbers multiply "Numbers.java" 1867]\n [clojure.lang.Numbers$LongOps multiply "Numbers.java" 467]\n [clojure.lang.Numbers ...
09:12gfredericks,(defn java-random [^long seed] (-> seed (unchecked-add 0x5deece66d) (unchecked-multiply 0x5deece66d) (bit-shift-right 16) (unchecked-int)))
09:12clojurebot#'sandbox/java-random
09:12gfredericks,(java-random 42)
09:12clojurebot-1139325123
09:12gfredericks,(.nextInt (java.util.Random. 42))
09:12clojurebot-1170105035
09:12gfredericksaw poop
09:13akabanderWhen I do (doc let) it says clojure.core/let
09:13gfredericks,(doc let)
09:14clojurebot"([bindings & body]); binding => binding-form init-expr Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts therein."
09:14gfredericks,(.nextInt (java.util.Random 2464063869))
09:14clojurebot#error {\n :cause "java.lang.Class cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Class cannot be cast to clojure.lang.IFn"\n :at [sandbox$eval47 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval47 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval47 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 694...
09:14akabander,(clojure-version)
09:14clojurebot"1.8.0-alpha3"
09:14oddcullygfredericks: 0-4096 as seed gives a negative
09:14gfredericks,(.nextInt (java.util.Random. 2464063869))
09:14clojurebot0
09:14oddcullyah there ya go
09:15oddcully(inc gfredericks)
09:15lazybot⇒ 145
09:15gfredericksgilliard: ^ I found that after 17 seconds of searching
09:15akabanderHmm, I get more data from doc, maybe the lein repl is doing something?
09:15oddcully,(Long/toBinaryString 2464063869)
09:15clojurebot"10010010110111101010000101111101"
09:16justin_smithakabander: I think it's more that clojurebot's version is truncated
09:16gfredericksgilliard: this result is actually expected for *any* decent RNG
09:16justin_smithakabander: did you have a question about clojure.core/let ? that is the namespace it comes from
09:16justin_smithakabander: in clojure.core namespaces don't map 1-1 with files though
09:17gfredericksyour output is 32 bits and you tried 2^32 seeds, so there's a decent chance you won't see any particular value but that you will see it sometime later
09:17gfrederickss/expected/unsurprising/
09:17gilliardgfredericks: That's why I was surprised. I had thought the seed was an Integer.
09:17akabanderI was trying to answer ebzzry, but I think I answered wrong with (doc let) and not let*
09:18gfredericksgilliard: even if it were, it should only be surprising if the RNG guarantees it will generate every value exactly once
09:18akabanderI don't have a let* in my repl, so it's not core.
09:18ebzzryakabander: the same in my case
09:19justin_smithakabander: let* is a special form, it is defined in java
09:19justin_smithlet is a macro calling let*, it is in clojure.core
09:19akabanderjustin_smith: It was ebzzry who was asking.
09:19gilliardgfredericks: I would expect any value to be equally likely (give or take).
09:19justin_smithahh, I missed that, sorry
09:19ebzzryjustin_smith: ok. thanks.
09:20akabanderIt's cool, I got your attention, which got the correct answer for ebzzry :^)
09:20justin_smithebzzry: there's a function that tells you if something is a special-form
09:20akabanderConveniently for me, I'm reading the macro section of "Joy", so the source for let almost makes sense to me!
09:20ebzzrydo you know where in tha java source can I see the definition of let* and fn*?
09:20justin_smith,(special-symbol? 'let*)
09:20clojurebottrue
09:21justin_smithebzzry: one moment, it's not too hard to find...
09:21ebzzryjustin_smith: thanks
09:23gfredericksgilliard: for a deterministic generator with 32 bit seed and 32 bit output, that implies generating every value exactly once
09:23justin_smithebzzry: well, it's weird, but here's part of it :) https://github.com/clojure/clojure/blob/1d5237f9d7db0bc5f6e929330108d016ac7bf76c/src/jvm/clojure/lang/Compiler.java#L44
09:23gfredericksi.e., the generator is a permutation of the seed
09:24justin_smithebzzry: so in Compiler.java it sets up "Opcodes" for parsing / binding, and let* is one of those
09:25justin_smithebzzry: next step in the chain is a map of specials https://github.com/clojure/clojure/blob/1d5237f9d7db0bc5f6e929330108d016ac7bf76c/src/jvm/clojure/lang/Compiler.java#L110
09:25jeaye9K line file -_-
09:25ebzzryjustin_smith: thanks
09:25justin_smithjeaye: clojure's java is far from the prettiest :P
09:25gilliardgfredericks: Ack, thanks. And because it's a 48bit seed, nextLong actually does have some gaps.
09:26justin_smithebzzry: this appears to be the meat of it https://github.com/clojure/clojure/blob/1d5237f9d7db0bc5f6e929330108d016ac7bf76c/src/jvm/clojure/lang/Compiler.java#L6218
09:27justin_smithebzzry: which makes sense now that I think about it - let is a thing that takes a body of code and binds things, so of course it would be part of the compiler, and it would mainly do parsing and binding...
09:31gfredericksgilliard: yep
10:02snowellSay I have a map {:one 1 :two 2} and I want to do a (let {:keys [one two]} myMap) on it
10:03snowellBut instead of having to specify the symbols, I just want to destructure all the keys of the map
10:03snowellIs there an idiomatic (or any) way to accomplish this?
10:03snowellI tried (into [] (map (comp symbol name) (keys myMap))), but no dice
10:03akabandersnowell: I was wondering this earlier, I think there'd be issues with symbols in the body of the expression?
10:04snowellIt's not a huge deal. Just wanted to preserve a little readability
10:04gfrederickssnowell: nope, no way to do that, and that would be discouraged too
10:04akabanderReader/compiler/runtime confusion?
10:04gfrederickssince it means you can't tell by looking at the code what it does
10:04gilliardprogrammer confusion
10:04snowellgfredericks: that's fair
10:05gfrederickse.g., say I have (fn [{destructure-all-keys}] (+ a b))
10:05gfredericks^ what does + mean there?
10:05gfrederickssometimes it's clojure.core/+ but other times it's the :+ key of the map you pass in
10:06snowellYeah, that would be no bueno
10:06gfredericksclojure & associated macros are typically designed so that when a name becomes part of the lexical scope, you can see it explicitly
10:06gfrederickseven at the expense of a little verbosity
10:07noncom|2i think a macros can be written to enable that
10:07noncom|2but that is a very bad practice...
10:07gfredericksyou can't do it with a macro in a straightforward way
10:07gfredericksbecause macros operate at compile-time and you don't know what keys there are until runtime
10:08noncom|2the macro could take all keys and symbolize them and intern them with their values
10:08gfredericks"all keys"?
10:08noncom|2yes..
10:08R0B_RODHi
10:08akabanderIt would conceptually expand to a big messy let statement.
10:09gfredericksnoncom|2: where do you get the list of keys from at compile-time?
10:09akabanderAha, that's the technical problem that was bugging me
10:09gfredericksthe only way to do something like that is to call eval at runtime
10:09gfrederickswhich basically means you're calling the compiler every time the function gets run
10:10noncom|2gfredericks: no, not on compile time. the macros just inserts the facility that interns the symbols. not at compile time. i say macros because it will easily allow to pass a custom body of code like with the 'let statement
10:10gfredericksnoncom|2: I think whatever you're imagining will boil down to calling eval
10:11gfredericksthe only other option is walking the code to figure out what symbols it references, which is tricky because clojure doesn't have a facility to macroexpand/analyze the code
10:12noncom|2yeah, maybe eval..
10:13noncom|2no need to walk, just intern them all. anyway you're already screwed if you're doing this kind of thing imho..
10:16crocketgfredericks, What do you make with clojure nowadays? any meaningful project?
10:20snowellcfleming: I take back anything bad I thought about Cursive. I'm enjoying my time with it immensely. Thanks!
10:21gfredericksnoncom|2: does "intern" mean "create some vars"?
10:21gfrederickscrocket: I use it at work and I'm maintaining test.check
10:22noncom|2gfredericks: yes, sorry, i meant that. well, first to make the symbols, intern them within the curent environment and assign vars to them
10:23gfredericksnoncom|2: so they'd have to be dynamic vars and you'd have to use binding? I think there are a lot of ways that would break
10:24noncom|2gfredericks: sure there are lot of ways this can break - the whole idea is very risky and dirty.. as for dynamic - idk.. is there no way in clojure to access the current environment and modify it?
10:25gfredericksnoncom|2: you can't dynamically access the lexical environment, no
10:25gfredericksit's not reified, it's compiled into bytecode
10:25noncom|2for example, let has simpler rules on variable reassign
10:25gfredericksin the code (let [a (inc x)] (f x)), "a" does not exist in any meaningful way
10:25noncom|2hmmm
10:26gfrederickscontrasted with (def b 12) where b is a var you can poke and do things with
10:26noncom|2well, we cold just build a (eval (let [.. ] body)) from the map - i mean the let assignemnt block can be taken directly from the map
10:29crocketgfredericks, doesn't sound very interesting.
10:41justin_smithcrocket: on the contrary, test.check is fascinating, you should take a look at what it does
10:52akabandernoncom|2: It seems like a lot of effort to do something that's counter to the Zen of Clojure. I mean, it's an interesting idea, but surely we could harness your power for good?
10:53noncom|2akabander: sure we could! :) i just came about when someone asked about all this, so I just told my thoughts, I am not advocating for anything here :)
10:53snowellSorry I started all that! :D
10:54akabanderHaha, it's just that I find myself trying to figure out how to make it work... then "omg wtf am I doing?!" kicks in.
10:55akabanderIt's an interesting puzzle, in the same way "how would I weaponize grey goo" is interesting.
10:59justin_smithI know, instead of implicit local bindings, we could implement content tracking in clojure.string, sending all data to google between every string transform
11:01akabanderYeah, a local redis would not be cloudy enough.
11:01justin_smithnor would it be as careless with client data
11:01akabanderBut I like the google idea because every query could be "i'm feeling lucky"
11:01justin_smithhaha
11:03chance123||||| >>>>> WHAT IS YOUR DOMAIN NAME WORTH? Vist >>> www.VALBOT.com <<< FREE DOMAIN VALUATION! or GOOGLE >>> VALBOT.com <<< |||||
11:04sdegutisIs it possible define a defmethod in a namespace that has no access to the defmulti?
11:05justin_smithno, defmethod actually alters the defmulti created var itself
11:05sdegutisDang.
11:05sdegutisI'm trying to do my configs up using these.
11:05H4nserm, you can define methods for multimethods created in other namespaces
11:06H4nsI'm not sure if I'm misunderstanding the question or justin_smith's answer, though.
11:06justin_smithH4ns: yes, but he wants to do it without accessing the namespace with the defmethod in it
11:06justin_smitherr, without the defmulti
11:06justin_smithH4ns: he said with no access, if you can load the namespace that is access
11:06justin_smithperhaps I misunderstood the question
11:06justin_smithsdegutis: by "no access" do you mean "cannot require the ns at runtime" ?
11:14sdegutisjustin_smith: ah no I meant inside the (ns).
11:14sdegutisInside the ns that defines the defmulti, I want to :require the namespaces that define the defmethods.
11:14sdegutisThis is the thing not possible, accurate?
11:15justin_smithyeah, that shit's cray
11:15H4nssdegutis: you could create an extra namespace for the defmulti
11:15justin_smiththere's probably a hack using resolve and require at runtime, but it aint worth it bro
11:15sdegutistrudat
11:16sdegutisPerhaps using defmulti for configs is dumb.
11:16justin_smithyou can use defmulti - just put the defmulti in a namespace with no implementation logic in it
11:16sdegutisOh right.
11:16justin_smithand put the implementation logic in another namespace, higher in the tree
11:16sdegutisSo A requires B,C,D which each require Z, and A requires Z to call it's defmulti.
11:17sdegutiswhere B,C,D each have a defmethod for Z's defmulti
11:17sdegutisamirite?
11:17justin_smithsdegutis: I think I've said this before, but defmulti and defprotocol belong in vapid namespaces that only define abstractions and no implementation details
11:17justin_smithsdegutis: yes, something like that
11:17sdegutisjustin_smith: weird.
11:18sdegutisI like circular dependencies. Sad Haskell/Clojure don't support them.
11:18justin_smithsdegutis: this is platonic epistimology, where the abstract essence of things is prior to their concrete manifestation
11:18sdegutisDoes "accidents" fit in there somewhere?
11:18akabanderI knew that Philosophy degree would come in handy!
11:18justin_smithsdegutis: but if you use your abstractions properly, every circular dependency becomes a non-circular one
11:20sdegutisThis is not magic enough for me.
11:20sdegutisI need more magic.
11:20justin_smithruby is over there ->
11:20sdegutisI think I'll derive a namespace via string.
11:20sdegutisThen I'll load the var in that namespace.
11:21sdegutisSo for :production I'll load #'config.production/config
11:21sdegutisDeal?
11:21justin_smithsdegutis: symbols and resolve are more direct, but this is the path to evil
11:21justin_smithand by "evil" I mean your own pain and suffering in the future
11:22sdegutisThis is top-level config-setting stuff.
11:22sdegutisThis is the absolutely most correct place to use magic.
11:22sdegutisHeck I'm even using lein-environ!
11:22sdegutisNow, web handler routing and such, that's a much more questionable place to use black magic.
11:23justin_smithI already described the clean way to do this, and I know you understood it because you basically repeated it back to me.
11:23sdegutisUsing defmulti?
11:24sdegutisI started implementing it, then I didn't like how much repetition there was in (ns config.dev) (defmulti configs :dev ...)
11:24sdegutisSee "dev" in that file twice. Bad.
11:24justin_smithright, by having the defmulti in a file that has no impl logic, and then having impl logic in a separate namespace, and code invoking the method in a third
11:25justin_smithsdegutis: I don't think this is a constrcutive conversation any more.
11:25sdegutisPragmatism always trumps correctness. The only time this seems to not be true is when correctness serves pragmatism.
11:25sdegutisIn this case, the benefits of defmulti are not really needed, since I'm the only implementor of all the defmulti's, and they're all known at compile time.
11:37sdegutisGot it: (defn get-config-for [env] (-> (str/join "." [(ns-name *ns*) env]) (symbol) (ns-resolve 'config) (var-get)))
11:38sdegutisAhh, found a bug in lein-environ :'(
11:39sdegutisFatal one too. You can't have two Lein processes running at the same time in two different envs, because it touches .lein-env to know what configs to use.
11:39sdegutisThat sucks.
11:39sdegutisI vaguely remember there was some way you could inject code using Leiningen...
11:44justin_smithsdegutis: injecting code via leiningen and constructing namespaces at runtim from strings are not the jedi way, young padawan, these are the ways of the sith
11:45Sorella"justin_smith> sdegutis: but if you use your abstractions properly, every circular dependency becomes a non-circular one" I find this to be bending the definition of "properly" quite a bit. Circular dependencies should be supported in languages, since they arise naturally, it's just hard to do so (specially when you have types). Would be possible in Clojure
11:45Sorellaif things were late bound.
11:46justin_smithSorella: clojure does not support circular dependencies without indirection.
11:46Sorella(You can work around that limitation, of course. But it's still a limitation :/)
11:46snowellAnybody aware of a keybinding or such in Cursive Clojure to indent a block of code correctly (as opposed to just moving the whole block left/right a tab)?
11:46justin_smithit's an intentional choice not to support them, not laziness or lack of creativity
11:46SorellaOh, I didn't mean to imply Clojure supports recursive deps.
11:46justin_smithI'm saying it doesn't support them due to a choice not to support them.
11:47justin_smithand it's a choice I personally agree with
11:47Sorellajustin_smith: that's fine. I was just questioning the choice of word "properly" here :)
11:47SorellaAs it implies "circular dependencies" are bad (at least to me)
11:47justin_smithSorella: yes, and we disagree on that particular value judgment
11:48hante_monstaDoes clojure has queue?
11:48justin_smithhante_monsta: yeah, there's a few choices in fact
11:49justin_smiththe main one being clojure.lang.persistentqueue/EMPTY
11:49hante_monstajustin_smith: such as?
11:49R0B_RODHello all, new to everything...
11:49justin_smith,(-> clojure.lang.persistentqueue/EMPTY (conj 1))
11:49clojurebot#error {\n :cause "clojure.lang.persistentqueue"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassNotFoundException: clojure.lang.persistentqueue, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.ClassNotFoundException\n :message "clojure.lang.persistentqueue"\n :at [java.net.URLClassLoader$1 ...
11:49justin_smitherr...
11:49sdegutisjustin_smith: I have three different ways of running code: from `lein run` which is always "development", from `lein test` which is always "test", and from `java -jar mywebsite.jar` which can be either "staging" or "production". I need to come up with a unified way of getting about 30 configuration variables depending on which environment I'm running in.
11:50justin_smith,(-> clojure.lang.PersistentQueue/EMPTY (conj 1))
11:50clojurebot#object[clojure.lang.PersistentQueue 0x477c7fed "clojure.lang.PersistentQueue@20"]
11:50hante_monstasnowell: Cursive, does not indent well some macros definition
11:50justin_smith,(-> clojure.lang.PersistentQueue/EMPTY (conj 1) (->> (into []))
11:50clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
11:50justin_smith,(-> clojure.lang.PersistentQueue/EMPTY (conj 1) (->> (into [])))
11:50clojurebot[1]
11:50justin_smithhante_monsta: sorry for the many mistakes getting to it, but see above
11:50sdegutisI'm thinking :injections is probably the simplest, safest and most reliable way to set an environment variable when inside `lein run` or `lein test`.
11:51justin_smith,(-> clojure.lang.PersistentQueue/EMPTY (conj 1) (conj 2) (pop) (->> (into [])))
11:51clojurebot[2]
11:51hante_monstaIs there any O complexity table about Clojure's fns?
11:52justin_smithhante_monsta: there's one in the book "Clojure High Performance Programming" - I seem to recall there might be one in a Chas Emerick blog post somewhere too?
11:52hante_monstajustin_smith: thanks, very appriciaty, I wonder why I ca't find that in the docs (google) for some reason
11:52rhg135What is the advantage of a persistent queue over a vector?
11:52Sorellahante_monsta: they're usually the same as the mutable counterparts (in amortised time).
11:52Sorellarhg135: queues support O(1) insertion at the end, and O(1) removal at the beginning.
11:52philthhante_monsta: https://www.innoq.com/blog/st/2010/04/clojure-performance-guarantees/ ?
11:52frogbyteHello there
11:52rhg135Ah
11:53rhg135Thanks
11:53hante_monstaThanks++
11:53SorellaIn clojure it has to touch more than one element, though, but we still consider it constant time.
11:53justin_smithrhg135: that's why I used conj / pop in my example
11:53philthhante_monsta: (inc :thanks)
11:53justin_smithrhg135: to do the fast ops
11:53philth;)
11:53sdegutisData composition trumps function composition when available.
11:54rhg135The ways of failure are strong with this one
11:55sdegutisI'm just thinking about Compojure.
11:55frogbyteI need to use the function clojure.java.shell/sh which accepts variable argument. how can I transform a vector so that it can be accepted by this function?
11:55sdegutisIt builds an opaque data structure that can then be acted on (by asking it to handle a request) but can't be inspected at all.
11:55justin_smithfrogbyte: apply
11:55Sorellasdegutis: configuration is one of the things I find particularly hard in Clojure :/ I've used a atom for my last project, which allows rebinding the configuration at runtime (pretty useful in some cases), but I miss parametric modules.
11:55justin_smithfrogbyte: (apply clojure.java.shell/sh coll)
11:55frogbytethanks
11:55sdegutisWhereas building up a data of route handlers is much more inspectable and flexible, and can still be acted on with a given request.
11:56hante_monstaI am reading about game programming with js that expose some imperative algorithms and data structures, and I am trying to find the functional counte parts, for example, people say that I can replace doublylinkedlist with zippers
11:56sdegutisSorella: parametric modules? sir you sound like an OCamler not a Haskeller
11:56justin_smithSorella: have you looked at stuartsierra's component lib?
11:56hante_monstaBut my head unzip thinking about it
11:56SorellaNot a sir, but I'm more of a Newspeaker :P
11:56Sorellajustin_smith: I haven't. What's that?
11:56justin_smithSorella: components can be parameterized, and can be re-initialized at runtime with new parameters
11:57justin_smithSorella: component is a library for building systems in terms of data dependencies, solves a lot of typical clojure problems with initialization and sanely building state
11:57sdegutisSorella: never heard of that term
11:57sdegutisFrom 1984?
11:58Sorellasdegutis: a Smalltalk dialect: http://www.newspeaklanguage.org/. It has first-class parametric modules, and no global namespace.
11:58justin_smithSorella: https://github.com/stuartsierra/component I recommend trying it in a fairly new project first - it's easier to figure out how to use it from a clean slate, and after you know the ins and outs you can adapt an existing project to use it pretty easily
11:58sdegutisSounds horrifying.
11:59justin_smithSorella: anyway, complete game-changer in terms of managing stateful resources in clojure, I recommend it very highly
11:59SorellaIt has optional typing too, which is one of the things I don't particularly agree with in the design of the language (I'd have gradual ones, but types are hard for first-class modules).
11:59Sorellajustin_smith: sounds interesting :D
12:01justin_smithSorella: a pattern i find very useful is to make a helper that prints out the name of each component as it starts up, which just last night saved me lots of grief when figuring out how to set up a staging environment
12:01rhg135You can do runtime redefinition? With component
12:01justin_smithbecause it made it clear exactly which part of the system was misconfigured or missing a required resource from the OS
12:01hante_monstajustin_smith: I am using that for one of my web projects, is really easy to use. Just passing the components map as a request context.
12:01justin_smithhante_monsta: yup, it's very nice
12:02justin_smithhante_monsta: in my case, my server has multiple ways to talk to the outside world, so the http-server is one component, but the kafka connection to our compute cluster is another, and the websocket connections to clients are in a third, and there's a higher level set of components that allow each to invoke messages sent on the others
12:03hante_monstajustin_smith: Schema is really good as well, and compojure api is a game changer too (atleast for me)
12:03justin_smithhante_monsta: which took a bit of wrangling (because at first glance that looks like it needs to be circular...)
12:03GivenToCodeim trying to learn a bit of clojure and looking at some code, can anyone tell me what the "(first)" in this line means? https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Clojure/compojure/hello/src/hello/handler.clj#L177
12:04hante_monstajustin_smith: I used too to make a notification system along with core.async
12:04justin_smithnice
12:04hante_monstajustin_smith: Why haskell doesn't have this, or does?
12:05justin_smithGivenToCode: the trick is on line 175 - the call to ->
12:06justin_smithGivenToCode: -> is a macro that takes the result of each form, and makes it the new first arg to the next form
12:07justin_smithGivenToCode: you can find docs and examples for -> on http://conj.io, and feel free to follow up with more questions
12:07snowelljustin_smith: Is it good/better form to wrap function names in parens like that in -> where there are no other args?
12:07GivenToCodejustin_smith, so 1 is the first arg to run-queries, and the result of run-queries is the first arg to first?
12:07justin_smithsnowell: that's a style argument - I don't usually do it, other people think you should always do it
12:07justin_smithGivenToCode: exactly!
12:08justin_smithGivenToCode: whoever wrote that code really loves the -> macro...
12:08GivenToCodejustin_smith, if you were to rewrite it, what idioms would you prefer?
12:09justin_smithGivenToCode: I would make some of those simple nested calls
12:09justin_smithlike (response (first (run-queries 1)))
12:09justin_smithwhich compiles to be the same thing as the -> version
12:09clojurebotNo entiendo
12:12rhg135What is wrong with ->
12:13justin_smithrhg135: it's not wrong, I find it a little silly when you are only nesting 3 calls though
12:13justin_smithespecially three calls where there is only 1 arg to each step
12:13justin_smithrhg135: but it's a style choice I guess
12:13rhg135Some people are allergic to parens though
12:14akabanderAllergies can be overcome with enough exposure
12:14rhg135Yeah
12:15akabanderI get annoyed when people use "->" as a reason why Clojure "isn't so bad"
12:15akabanderThey're operating from false assumptions (that parens are bad).
12:15rhg135That is a dumb reason
12:15justin_smith(inc ((())))
12:15justin_smithlazybot: hello
12:16justin_smith(inc parens)
12:16lazybot⇒ 1
12:16akabanderBut you see it in intro to clojure pieces all the time. "Don't like parens? Look you can use -> instead!"
12:16Bronsa(inc (((()
12:16lazybot⇒ 1
12:16justin_smithBronsa: so weird
12:17BronsaI might be to blame for that :E
12:17rhg135Semantics over syntax forever
12:18justin_smith,(compare "semantics" "syntax")
12:18clojurebot-20
12:18justin_smithit seems the jvm disagrees, sorry
12:18hante_monsta"you don't know nothing jvm"
12:19Bronsa,(compare "a" "c")
12:19clojurebot-2
12:19Bronsa,(compare "a" "d")
12:19rhg135As do all the jvm coders who like java
12:19clojurebot-3
12:19Bronsauh
12:19hante_monstarhg135: was just a joke, just a joke.
12:21ainzclojure or haskel better?
12:22ainzabout performance.
12:22snowellainz: I assume you will only get a biased opinion in a clojure chat :)
12:22snowellAnd it probably depends on what you value more
12:22rhg135hante_monsta: I just refered to the people who claim syntax makes a language unusable, not a reply
12:22ainz:)
12:22ainzthank sir
12:22Sorellaainz: performance in what context?
12:22justin_smithhaskell will calculate answers faster, with clojure you'll get correct code sooner (and most of us will claim it is more fun too)
12:23ainzthanks
12:23hante_monstarhg135: I doesn't make it unsable, but it make me not want to use it
12:23SorellaThey're... uh, very different, and it's hard to really compare them. Clojure's JVM implementation isn't *that* interested in raw performance, but a solution in Clojure may be or may not be faster than a solution in Haskell, for particular subsets of problems
12:23rhg135That I can agree with
12:25Sorellaakabander: I'm particularly not a fan of the prefix syntax used by Clojure, although paredit makes a very good use of it.
12:25hante_monstaSorella: On the counterpart some people in Java are interested in raw performance without the use of RAII
12:26SorellaI'm not sure I'd call this particular prefix syntax "bad" per se. But it has a few places where I'd prefer expressing things with another notation. Most other things (e.g.: Agda) that rely on text but are expressive are too complicated though, and tooling/syntax errors become trickier.
12:27Sorellahante_monsta: which is... weird, given that Java isn't particularly that great at raw performance either.
12:29justin_smithSorella: it's in a special niche when you combine performance and portability as criteria though
12:32SorellaThat's likely true. Makes me wonder if Rust might replace it in that area though, eventually.
12:32justin_smithit has massive inertia, and gets used in the sorts of settings where deciding to use a new language is a 5 year exploritory process
12:32hante_monstaSorella: People still love their C++, and don't want to change.
12:34ralph___Can anyone offer how to take a collection and dump it's contents in place? Examples @ https://www.refheap.com/108717 or: [a b c] -> a b c
12:36Sorellaralph___: (flatten [a [b [c] d]]) => [a b c d]
12:36ralph___Sorella: But I want them out of the collection, not flattened.
12:36ralph___Sorella: However, thanks.
12:36Sorellaralph___: out of the collection...?
12:36rhg135Apply?
12:37ralph___rhg135: But what function to apply?
12:37Bronsaralph___: you can't do that, functions can only return one value
12:37Bronsaralph___: do you need this while writing a macro?
12:37ralph___Bronsa: OK and yes.
12:37Bronsa,`(foo ~'(bar baz ))
12:37Sorellaralph___: ,@the-collection will expand the collection
12:37rhg135Ah, nvm then
12:37clojurebot(sandbox/foo (bar baz))
12:37Bronsa,`(foo ~'@(bar baz ))
12:37clojurebot(sandbox/foo (clojure.core/deref (bar baz)))
12:38Bronsa,`(foo ~@'(bar baz )) ;;err
12:38clojurebot(sandbox/foo bar baz)
12:38SorellaOh, I'm mixing Lisps, apparently
12:38BronsaSorella: yeah ,@ is CL, ~@ is clj
12:39ralph___Bronsa, Sorella: Aha, yes, that seems like the ticket. Thanks!
12:39Bronsaralph___: note that ~@ works only inside a ` context and only inside a collection. You still can't splice things into the top-level
12:40ralph___Bronsa: I think that should be OK. It doesn't have to be top-level, just within the current scope.
12:42justin_smithSorella: about flatten
12:42justin_smith~flatten
12:42clojurebotflatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.
12:42justin_smithalso ##(flatten "hello")
12:42lazybot⇒ ()
12:42justin_smith,(flatten {:a 0})
12:42clojurebot()
12:43Bronsa,(flatten 1)
12:43clojurebot()
12:44justin_smith,(flatten #{1 2 3 :set :go})
12:44clojurebot()
12:44phillordI've used flatten some of the time
12:45justin_smithphillord: well it does say "rarely" and not "never" the right answer
12:45justin_smithphillord: but it's good to remember its many pitfalls
12:45phillordI needed it for "user interface" reasons.
12:46justin_smithphillord: oh man that reminds me I am supposed to be helping with some frontend stuff today and I already feel dirty
12:47phillordconsider a function like "and" but which works either on lists or arguments
12:48phillordso (and a b c) or (and [a b c]) should return true iff a, b and c
12:48phillordbut also (and a [b c]) or (and a [b [c]])
12:49phillordwell, that's what I used it for, good or bad
12:49justin_smithphillord: it's a truisim in systems science that weird messy shit happens on system boundaries
12:49justin_smithone of those boundaries of course is app / user
12:49phillordthat's a good aphorism
12:49justin_smithsee also biodiversity where two ecosystems meet - this isn't always a bad thing
12:50phillordgiven that my library is entirely a system boundary I think that gives me a good excuse!
12:50justin_smithhaha
12:50justin_smithsure
12:51phillordactually, several system boundaries at once -- user interface to programmatic library, mutable to immutable, and Clojure to Java. I hope I satisfied everybody, of course. But in the real world....
13:15doritostainslein.bat trampoline is giving me the error "input line too long" on a Windows 2003 server. Is there a way to fix this or should I just do with out trampoline?
13:17justin_smithlein definitely generates huge command lines...
13:20amalloy$google windows xargs
13:20lazybot[linux - Windows equivalent to xargs? - Super User] http://superuser.com/questions/652492/windows-equivalent-to-xargs
13:21jorrIf I want to be able to read a config file consistenly in a jar built with lein uberjar, where do I put the config file?
13:21jorrI expected resource-paths in project.clj to work, but I'm not able to find anything in those paths at the repl with (java.clojure.io/resource "bla")
13:22mindbender1Does anyone have a working systemd script for datomic?
13:22justin_smithjorr: I load files via the resource-paths all the time - are you looking for the resource in a path relative to the resource-path entry?
13:24justin_smitheg. if ./resources/ is in :resource-paths then I can access ./resources/public/app.js via (io/resource "public/app.js")
13:24jorrjustin_smith: I think so... can I just reference the directory in resource-path, then that directory will be searched? I think I listed the path to the file itself and not just directory.
13:24justin_smithyes, that is how it should work
13:24jorrjustin_smith: Hmm, okay thanks, I'm sure it'll work with some more fiddling then.
13:25justin_smithof course io/resource either returns nil or a input source which you would then hand to slurp or with-open or whatever
13:26amalloyi am amazed, searching for "windows xargs" to see if there is a simple solution to doritostains's issue. everyone on the entire internet thinks that xargs is just a way to invoke a program N times (which it is), rather than a way to pass a large command-line to a single program invocation (which it also it)
13:27justin_smithamalloy: maybe it's a classic flandersization problem
13:27amalloy$google flandersization
13:27lazybot[Flanderization - TV Tropes] http://tvtropes.org/pmwiki/pmwiki.php/Main/Flanderization
13:27wvxvwhi there. Newbie question. Why is my REPL not finding any dependencies / is unable to require anything but the Java / Clojure own libraries?
13:27hiredmanwell, vars are just a way to have you routes update when you recompile ring routes
13:28justin_smith"The act of taking a single (often minor) action or trait of a character within a work and exaggerating it more and more over time until it completely consumes the character."
13:28jorrjustin_smith: aah that was it, thanks so much.
13:28justin_smithjorr: np
13:28wvxvwI have a ~/.lein/profiles.clj with pomegranate, and I'm sure it's on my HD, but REPL cannot load it.
13:29justin_smithwvxvw: how do you go about requiring it?
13:29amalloythere are a million "xargs.bat" files that are like "FOR file in %*; %1 %file"
13:29wvxvw(require '[cemerick.pomegranate :as p])
13:29wvxvw=> FileNotFoundException Could not locate cemerick/pomegranate...
13:29justin_smithwvxvw: it could be your profiles.clj is malformed, can you share a paste of it?
13:30wvxvwjustin_smith: it's really simple, here it is:
13:30justin_smithno multi line pastes please
13:30wvxvw{:user {:plugins [[cider/cider-nrepl "0.8.2"] [lein-exec "0.3.1"] [com.cemerick/pomegranate "0.3.0"]]}}
13:30wvxvw
13:30justin_smithpomegranate is not a plugin
13:30wvxvwwell... that's almost one :)
13:30justin_smithyou need it under :dependencies
13:30wvxvwah...
13:30wvxvwlet me try that
13:31wvxvware other plugins and why the difference?
13:31justin_smithwvxvw: plugins are things added to lein's classpath while loading up your project and preparing to run it
13:31justin_smiththey can do special things, up to and including adding things to your app's classpath
13:32wvxvwyes, that's what I'd like to happen
13:32justin_smithwvxvw: dependencies are meant to be required directly by your app. A dependency that is not meant to be a plugin will not end up adding anything to your runtime classpath.
13:32wvxvwI mean, why would other things not be able to do that?
13:32justin_smithwvxvw: the plugin route for adding an app dep is the weird roundabout way, dependencies are the direct simple way
13:33wvxvwjustin_smith, I really fail to see the difference.
13:33justin_smithwvxvw: lein is a tool that builds your classpath
13:33justin_smithwvxvw: a plugin can manipulate the way lein does that through arbitrary code, if it chooses to
13:33wvxvwI think that classpath is a... not very smart concept... why would it even use that?
13:34justin_smithwvxvw: a dependency is much simpler - it is directly added to your app's class path, with no other special gimmicks or tricks
13:34justin_smithwvxvw: the classpath is why you can use 8 different versions of clojure in 8 different projects and not worry about this breaking anything
13:35wvxvwNot really no... :) Sorry, Python can do away pretty well without such things. CL too, just to name some other language.
13:35justin_smithwvxvw: and they internally have something much like the classpath for setting your visible packages
13:36wvxvwBut you don't need a ton of setup in random places to do that. You can do it all from the interactive session.
13:36justin_smithor else you can break app b by changing a dep in app a (which is the common case)
13:37justin_smithwvxvw: anyway, regardless of our personal judgment of the jvm's resource and dependency management strategies, the reason that plugins and dependencies are different is because plugins do weird magic stuff which might include influencing your runtime available packages, while dependencies alter your runtime available packages and do nothing else
13:39wvxvwwell, it's not something I can influence, so for now, I'll probably have to suck it up. But it's really not something I'd like to put up with in the long run :)
13:39justin_smithwvxvw: I never had any luck having multiple versions of a single CL lib available at once
13:39wvxvwI run it in exactly this very moment :)
13:40wvxvwMaxima can't load together with quicklisp, so I run Maxima separately from the SLIME I work with
13:40wvxvwSorry, back to where we started
13:40phillordwvxvw: actually python does have nearly the same thing, for exactly the same reason, which is virtual envs. Diff is these run in different VMs
13:40wvxvw(require '[cemerick.pomegranate :as p]) still errors
13:41justin_smithwvxvw: can you paste your new profiles.clj?
13:41wvxvwBut I _don't have to_ use a virtual environment.
13:41wvxvw{:user {:plugins [[cider/cider-nrepl "0.8.2"] [lein-exec "0.3.1"]] :dependencies [[com.cemerick/pomegranate "0.3.0"]]}}
13:41wvxvwhere
13:42justin_smiththat should be working...
13:42wvxvwnope, the same exact error
13:43wvxvwFileNotFoundException Could not locate cemerick/pomegranate__init.class or cemerick/pomegranate.clj on classpath. clojure.lang.RT.load (RT.java:449)
13:43wvxvwhere's the full text
13:45justin_smithwvxvw: hey I just replaced my profiles.clj with the one you pasted, and started a fresh repl with no project, and was able to require cemerick.pomegranage using the exact require you pasted
13:45justin_smithwvxvw: have you restarted the repl since changing profiles.clj?
13:45wvxvwjustin_smith this only means there are some hidden variables, like environment variables, configuration files elsehwere etc, stuff that neither of us is aware of, but you have them and I don't.
13:46justin_smithwvxvw: no, I have no other visible config for lein other than what lein self-installs and the profiles.clj which I replaced with yours
13:46amalloywvxvw: no, there aren't. the only hidden variable is what you are typing that's causing that error
13:46justin_smithlein is installed locally by and for my user, and has no system level config
13:46justin_smiths/no other visible/no other available
13:47wvxvwyou never know... what about $JAVA_... stuff? Can this influence it? Maybe $CLASSPATH, $MAVEN_... stuff?
13:47justin_smithif you changed the $MAVEN stuff that could provoke a not-found type error, or force re-download of artifacts
13:48justin_smithit would not simply make a dep unavailable from the repl
13:48justin_smithit would fail
13:48wvxvwcan you locate the jar with pomegranate? So that I could check I have it too?
13:48wvxvwNo, I never changed it by hand, but, again, you never know, different system, different package manager etc.
13:49justin_smithwvxvw: it is in ~/.m2/repository/com/cemerick/pomegranate/0.3.0/
13:49wvxvwBecause, apparently, it does make a dependency unavailable from repl.
13:49amalloywvxvw: the thing i would like to know is, starting from a terminal $ prompt, what are you typing that causes you to get this error message
13:49justin_smithwvxvw: lein is the package manager
13:49wvxvwit's not really a package manager, since it cannot install or search for packages... it's 0.33% package manager :D
13:50justin_smithwvxvw: it does both, and those are its primary jobs
13:50wvxvwwell, it kinda fails at that big time :)
13:50wvxvwyes, I do have that jar at exactly the same location
13:50justin_smithwvxvw: and if it is failing to do those things you should ensure your version is up to date and that you are using it correctly
13:51wvxvwit is installed today, about an hour ago
13:51oddcullythere is the plz plugin for lein to make it search and add deps
13:51wvxvwwhat I'm doing with it:
13:51amalloyi find it frustrating to try and help you, wvxvw, because you would prefer to argue about how lein should act, and guess at possible solutions to your problem that, if you had the experience justin_smith and i have, are clearly not possible issues, rather than follow suggested debugging steps like "what are you doing that causes this error"
13:51wvxvw$ lein repl
13:51justin_smithOK after changing your ~/.lein/profiles.clj a fresh lein repl should be able to load pomegranate
13:51wvxvwthen:
13:51wvxvw(require '[cemerick.pomegranate :as p])
13:51wvxvwnothing more
13:52amalloyand you have done this anew since changing your profiles
13:52wvxvwalso, is there probably some way to make it start faster? Just in case...
13:53justin_smith~faster
13:53clojurebotfaster is https://github.com/technomancy/leiningen/wiki/Faster
13:53justin_smithwvxvw: ^ see link
13:53wvxvwthanks, will do
13:55wvxvwok, for no reason this time it worked. I honestly didn't do anything. in fact, I had it all recorded as a macro, so I just re-ran exactly the same stuff I did before, and it worked.
13:55wvxvwgo figure
13:56wvxvwThank you justin_smith, I guess :)
13:57amalloy(inc justin_smith)
13:57lazybot⇒ 291
14:04justin_smithwvxvw: I'm legitimately curious, how one uses different versions of the same CL lib within two projects on the same machine using the same install, because in my various usage of defpackage I never saw a version parameter
14:06wvxvwjustin_smith: you can symlink the asd fily into your project directory, it's the place where quicklisp will look up first, before the global registry / local-projects
14:06wvxvws/asd fily/asd file/
14:07justin_smithwvxvw: so if my dep tree contains 100 deps going recursively, I make 100 symlinks if I want to ensure reproducable behavior?
14:08wvxvwin that case I'd have modified the global registry (the asdf configuration file) and have copies of it loaded on per project basis
14:08justin_smithalso, how does one keep this in sync with a team, forcing everyone to have all the same things manually installed so the symlinks work?
14:09wvxvwbut that doesn't sound like a realistic scenario at this point... in all my years of working with CL, I didn't accumulate enough libraries to run into the kind of problems
14:09justin_smithwvxvw: using clojure I use large numbers of very small libs
14:10justin_smithmy app has many project files right now, in one of these projects "lein deps :tree | wc -l" tells me I have aproximately 200 libs in my tree of deps
14:10wvxvwthen again, you'd need something like virtual environment, but, again, in my experience, the problem people have which encourage them to have a virtual enviroment is usually bad planning (which is not so unusual)
14:10justin_smithwe don't have or need virtual environments with clojure
14:11wvxvwinstead you have an extremely convoluted and uncomfortable way of importing libraries?
14:11justin_smithusually - I guess some people use them to bundle non-clojure services along with the jar in one place I guess
14:11justin_smithwvxvw: once you accept some simple premises it's neither, but I do understand there's no accounting for taste
14:12wvxvwthis isn't taste really... let me explain. With things like pip / gem / cabal etc you learn to expect that there is a program to install stuff, find stuff etc.
14:12justin_smithwvxvw: I find it very helpful to know with 100% certainty that my team mates get exactly the lib versions I get, without any extra effort needed beyond what is required to make things work locally
14:13justin_smithwvxvw: I know what those programs are, and have found them less reliable than lein
14:13wvxvwlein is called a project manager, but it doesn't really know how to do any of that. It cannot search, it cannot install (because, technically, there isn't even a place to install to)
14:13justin_smithwvxvw: it does both!
14:13justin_smithit installs to a local cache
14:13wvxvwbut no, it doesn't!
14:13justin_smithit searches with "lein search"
14:13wvxvwthere's no such command line option
14:13justin_smith?
14:13wvxvwinstall Install the current project to the local repository.
14:14justin_smithI just ran "lein search pomegranate"
14:14wvxvwthis isn't installing a library, this is finding the dependency for the project
14:14justin_smithwvxvw: that is what "lein deps" does
14:14rhg135It does install
14:14rhg135To your local repo
14:14wvxvwbut the help says otherwise, whome should I trust?
14:15rhg135It says that too
14:15wvxvwI want to install globally... local is a bonus, but most of the time this isn't what I want...
14:16justin_smithwvxvw: sadly wanting to install globally isn't normal, or easy with lein. Which is why I said that if you can accept some simple premises (one of these is "no such thing as global installs"), it can be quite nice. If you can't accept it's premises, I encourage finding a build tool you like better.
14:16rhg135You could use plain jvm if you dislike lein
14:16justin_smithI think ant does global installs
14:16justin_smithright
14:17wvxvwwell, I don't really care about what is considered normal :) practical for me outweights what others consider normal
14:18wvxvwand if the answer is "it is what it is", then yes, I can understand it. Many languages and environments are built on this very principle :)
14:18justin_smithI think you'll find not using lein in the clojure ecosystem is a lot more work than using lein is
14:18rhg135What would a global install do for you?
14:19rhg135Using python was painful here
14:19wvxvwI'm just a random bystander, Clojure isn't my primary language. But, if we were to compare it to Java, then it's simply not improving on how bad Java is in this regard...
14:19wvxvwWell, it wasn't painful for me.
14:20rhg135Lucky
14:20wvxvwGlobal install in details
14:20wvxvwwell, you see, java, for instance, has a way to make a global install on Linux.
14:20wvxvwthere's a whole packaging system in place etc.
14:21wvxvwToo bad most Java programmers don't know about it...
14:21rhg135Maven...
14:21wvxvwso you end up having multiple copies of the same jars over and over in many places
14:21justin_smithwvxvw: no, it uses one cache, you might have multiple versions, but only one copy of each version
14:22wvxvwMaven doesn't always have what you need. I've had a (mis)fortune to work on various sized Java projects and therenever was a case when all dependencies were managed by Maven.
14:22justin_smithwvxvw: the key is reproducibility - that is, given the same project.clj two different developers on different machines are guaranteed to have exactly the same versions of everything
14:22wvxvwAlso, Linux way of installing java is independent of Maven, so...
14:22justin_smithwvxvw: and, given the same project.clj, I can come back 10 years later and use the same versions of everything
14:23justin_smithI wish Linux package managers were as reliable about versions and isolation as lein is, I guess nix comes close
14:23wvxvwThat's more of a wishful thinking. It will never work exactly like that. But you may have higher degree of confidence, that's true.
14:23justin_smithwvxvw: I come back to projects years later, it works like that
14:24justin_smithwvxvw: because package version deploys are effectively immutable
14:24wvxvwyou are trying to convince me by means of a single person making experiment in a non-controled enviroment? :P Seriously, that's not going to cut it
14:24justin_smithwvxvw: this is why we accept the weird parts of lein (including no global installs, needing a project.clj for everything...) - the increased repeatability
14:25wvxvwWhat if I don't care about it?
14:25justin_smiththen don't use lein
14:25wvxvwbut there's no alternative... except for lots of manual labor...
14:25rhg135Boot is nice
14:26rhg135Not as nice as lein, but yeah
14:26wvxvwwill it locate and install libraries available in some centralized repository into a global repository?
14:26wvxvw(on the machine I'm working on that is)
14:26rhg135Yes
14:26justin_smithrhg135: that's not true, it uses a classpath to manage versions via the maven schema
14:26justin_smithit's not what he wants
14:27justin_smithhe wants unversioned global installs
14:27rhg135Set you're maven repo to be global
14:27rhg135Like /m2
14:27rhg135Oh
14:27justin_smithrhg135: by global he means no version qualification
14:27wvxvwthat's not true
14:27justin_smithbbl, lunch
14:27rhg135Unversioned, blasphemy
14:28wvxvwby global I mean the same thing as Java packages are installed on Linux
14:28wvxvwno Maven
14:28wvxvwjust rpm / deb
14:28wvxvwit's much faster, easier to manage and more secure
14:28rhg135No such global repo exists
14:29wvxvwwell... that's one of the problems :)
14:29rhg135I know only of maven
14:29wvxvw(to make it fair, for example, there isn't one such repo for CL either)
14:29rhg135It works great though
14:29wvxvwwhich is unfortunate and sad, but that's how it is.
14:29wvxvwwell, that probably depends on what you want it to do :)
14:31rhg135You specify your deps, if they're in your local repo, uses that, else, downloads it
14:32wvxvwwell, this is bad, and I'll tell you why
14:32wvxvwIt seems ok as long as you are the user of your program
14:32wvxvwbut when you try to distribute it for others to use, you want the shared libraries to be available not only to you, but to others too
14:33rhg135They are
14:33wvxvwI mean, you don't want the Windows-style installs, where all DLLs come with the program
14:33wvxvwno, they aren't, and that's the problem
14:33rhg135They aren't
14:33wvxvwyou don't want your users to install lein
14:33wvxvwneither maven etc.
14:33rhg135They don't
14:33wvxvwthen how will they get their libraries?
14:34rhg135You can use plain java
14:34wvxvwhahaha
14:34wvxvwlol
14:34wvxvwseriously, and how that solves the problem?
14:34rhg135Download them manually
14:34rhg135Or via rpm etc
14:34wvxvwseriously? come on. You will distribute your program with a readme which says users need to download stuff from the internet?
14:35wvxvwIn what universe? :)
14:35tatutin reality, I think most will just ship a uberjar with everything, wvxvw seems to want something different
14:35rhg135Try running a python app with deps without setuptools
14:35rhg135That's fun
14:36wvxvwyou see, I'm so bitter not because of Clojure. CL lacks this infrastructure too. Some time ago I wanted to package my small and unimportant library in a way that others could use it too, and I realized that I can't.
14:36danlentz_why not?
14:36danlentz_lots of people seem to be distributing CL libraries
14:37wvxvwrhg135, setuptools is a built-in package. You can, if you wanted to, make a distribution which installs all it needs. Not a usual thing to do, but also not so uncommon.
14:37wvxvwbut, most importantly, you don't do it in python.
14:37wvxvwyou do it using rpm / dep and such
14:37wvxvwand this is where the real problem is. You need global install
14:38rhg135Isn't there a non standard setup lib some use
14:38rhg135I meant that
14:38wvxvwthere's pip, but what I'm getting at is distributing the program, not the library for other programmers
14:39wvxvwthis is the three staged process: programmer writes the program, package maintainer packages it and the user installs it and uses.
14:39danlentz_wvxvw: cl offers quicklisp (quicklisp.org) with a facility called a "dist"
14:39wvxvwIn case of CL, it's broken at package maintainer - you simply cannot package your program so that a user could just install it...
14:40rhg135I need pygame vY. My distro only has vX. Oh dear
14:40danlentz_wvxvw: huh?
14:40danlentz_nonsense
14:40wvxvwyes, there are limitations on what is packaged / available, but at least in pricniple it's possible
14:40wvxvwwith Clojure / CL doesn't seem to be possible
14:41danlentz_ok, sorry i joined in
14:41wvxvwdanlentz_ well. The only CL program distributed on Fedora is Maxima
14:41danlentz_well, fedora is not a cl distribution mechanism, is it?
14:42wvxvwI looked through the sources of the package, and I've also read the guidelines for packaging Lisp programs for RHEL distros (from previous century - nothing newer)
14:42danlentz_Waaa. I cant download Ubuntu from the Mac app store
14:42danlentz_yeah
14:42danlentz_well, look at ASDF
14:42danlentz_and quicklisp
14:42wvxvwFedora is a distribution of programs, and that's what I'm talking about
14:43wvxvwLook, I probably know about quicklisp and ASDF than you do... and that's why I'm saying this in the first place...
14:43wvxvwthey are not tools for installing programs.
14:43wvxvwthey are for programmers, not the users
14:44wvxvwTo give you more specifics: I wrote a library in CL, bindings for link-grammar C++ library.
14:45wvxvwNow, I wanted to package it for Fedora so that someone who wants to use the library could install it with dnf / yum
14:45wvxvwThere is no way at the moment to do that.
14:45wvxvwThe infrastructure that existed once is long gone
14:45wvxvwNew isn't there yet.
14:45danlentz_ok, apologies for basking in the ignorance that makes me think im using it effectively
14:46wvxvwthis is not it. I'm talking about different process / different purpose
14:46wvxvwdistributing programs =/= resolving dependencies
14:47danlentz_a quicklisp dist can package and distribute software
14:47wvxvw:0
14:47danlentz_and ASDF system can build and install libraries
14:47wvxvwno...
14:48danlentz_and both are arbitrarily extensible platforms
14:48wvxvwWe are talking about integration with package managers, does it explain it better?
14:48danlentz_i see
14:48wvxvwCan quicklisp produce a package installabe on Android?
14:49wvxvwit can produce a program, something you can drop on your computer and run - that's true
14:49danlentz_i'm using clojure to install an app that can package and run on iOS
14:49danlentz_clojurescript rather
14:49wvxvwbut packaging for a package manager is an entirely different process
14:50danlentz_i see, though. But you are limiting "package manager" to mean yum or apt
14:50wvxvwalright, sorry, I must go, duty calls.
14:50wvxvwI just mentioned Android (that'd be GooglePlay, or w/e it's called)
14:50wvxvwanyhow, sorry, I must be bowing out. Nice talking to you guys :)
15:25hanate_monstaWould people (this community) bash on me if solve problems in imperative way in Clojure? :)
15:26snowellBashing doesn't help anyone!
15:26{blake}We're not really bashers here.
15:26snowellBut I will say the first time I took something imperative I wrote in Clojure and changed it to a pure function it felt AMAZING
15:27hanate_monstaI wanna do the opposite.
15:27{blake}We might say we're disappointed in you. =P
15:27snowelllolwut
15:27hanate_monstaYES!
15:27{blake}But I'd be open to hearing why you wanted to do so.
15:27hanate_monstaGames!
15:29hanate_monstaCould I translate your silence as bashing? I knew it.
15:29{blake}heh
15:29{blake}But the world is moving toward pure functional games!!
15:29hanate_monstaLIARS!
15:31{blake}Entity Component Systems?
15:31hanate_monstaGarbage!
15:32{blake}Socrates, Plato, Aristotle? Morons!
15:32hanate_monstaI meant, Clojure produce so much garbage (you know GC)
15:32{blake}Oh, well, yeah. That's a good argument against using Clojure for games generally.
15:40{blake}Is there a way for Clojure to query the JVM? See what the heap size is?
15:41{blake},(.maxMemory (Runtime/getRuntime))
15:41clojurebot#error {\n :cause "Reference To Runtime is not allowed"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.SecurityException: Reference To Runtime is not allowed, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6891]}\n {:type java.lang.SecurityException\n :message "Reference To Runtime is not allowed"\n :at [clojurebot.s...
15:42justin_smith{blake}: check out the javadoc for System and Runtime, yeah
15:42{blake}I looked at System first and didn't see anything...I'll look harder. =P
16:55{blake}OK, I have a function defined as (defn promote[req][req]...(stuff)...) and I just now noticed I have the arg list in there twice. It works but why? Is it reading that as a multiple-arity situation with only one arity?
16:56justin_smith{blake}: it's just a vector doing nothing
16:57justin_smith,((fn [] [1 2 3] :OK))
16:57clojurebot:OK
16:57{blake}Oh. Right. I guess if there were nothing else it would return the arguments.
17:10{blake}Sounds like a Jimmy Buffet song: "Just A Vector Doin' Nothin'"
17:11{blake}OK, here's a style question. It has seemed to me that the preference for using require is pass vector.
17:11{blake}(:require [clojure.set :as set...)
17:12{blake}To the point where I was surprised to see "(require '(clojure.java io))" in the docs.
17:13{blake}I guess the vector is preferred because you don't have to do the ' mark?
17:13justin_smith{blake}: no, with require you do
17:13oddcullynote the difference between (:require) in ns and (require)
17:14{blake}When used directly, yeah, but in the :require clause you don't.
17:14justin_smith{blake}: the difference is that () is being used for the prefix form of require there
17:14justin_smith{blake}: neither requires (or even allows) a quote in the :require form
17:14{blake}Oh.
17:14justin_smith{blake}: those are two different things - prefix require, which is universally despised, and nobody uses
17:14{blake}So why prefer the vector?
17:14justin_smithand a require with a qualifying vector
17:15{blake}justin_smith: Oh! I didn't know it was universally despised. Why is it universally despised?
17:15{blake}Awkward to actually use?
17:16justin_smith{blake}: if you do (:require (clojure.java [io :as io] [shell :as shell])) it is hard to grep for usage of clojure.java.io or clojure.java.shell
17:16justin_smiththat's the prefix thing that the () example is using above
17:16justin_smithand note that when using :as etc. you should still be using [] inside it
17:17{blake}Ahhh. OK. And, yeah, I prefer :as more and more with any require.
17:18justin_smith{blake}: but I hope it's clear I am not talking about using :as or not - I am talking about the prefix form of require
17:18justin_smithwhich is what your require with () actually was
17:18{blake}Yeah, I get it.
17:19{blake}I meant "in addition to that, I'm tending to use :as which requires the vector, right?"
17:19justin_smithOK
17:20justin_smith{blake}: does't require it, but that's the idiom
17:20{blake}Right. Fair enough.
18:17onenessanyone out there tinkered with adding pre and post to defmulti?
18:22justin_smithoneness: you mean like a pre-condition on the dispatch function? because there is nothing else on the defmulti level itself
18:22justin_smithor do you mean on one of your defmethods - either should work
18:25onenessI mean to add pre and post contract to the defmulti so all defined methods automatically abide by it.
18:26onenesslooked at a bit to defmulti and looks like it does not support :pre and :post.
18:35amalloyoneness: just define an ordinary function that delegates to your multimethod
18:35amalloy(and put the conditions on that, of course)
18:38hiredmanor put them on the dispatch function, or each defmethod, or...
19:16justin_smith$mail oneness I just created a multimethod dispatch function with :pre conditions and it absolutely works
19:16lazybotMessage saved.
19:16justin_smith,(defmulti foo (fn [& args] {:pre [(even? (count args))]} (first args)))
19:16clojurebot#'sandbox/foo
19:17justin_smith,(defmethod foo :default [& _] :OK)
19:17clojurebot#object[clojure.lang.MultiFn 0x6f992b1 "clojure.lang.MultiFn@6f992b1"]
19:17justin_smith,(foo :a :b)
19:17clojurebot:OK
19:17justin_smith,(foo :a :b :c)
19:17clojurebot#error {\n :cause "Assert failed: (even? (count args))"\n :via\n [{:type java.lang.AssertionError\n :message "Assert failed: (even? (count args))"\n :at [sandbox$eval25$fn__26 doInvoke "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval25$fn__26 doInvoke "NO_SOURCE_FILE" 0]\n [clojure.lang.RestFn invoke "RestFn.java" 436]\n [clojure.lang.MultiFn invoke "MultiFn.java" 238]\n [sandbox$eval103 inv...
19:17justin_smith,(foo :a :b :c :d)
19:17clojurebot:OK
21:08AWizzArdThere is this Java method which takes a java.util.function.Function. How can I pass it some Clojure function? (.method my-fn) doesn’t work.
21:09AWizzArdJava 8.
21:09justin_smithAWizzArd: you can make a java.util.function.Function that delegates to your fn
21:09justin_smithfn does not implement java.util.function.Function, and from what I hear never will
21:10justin_smithfunction.Function has a constructor that take a callable right?
21:10AWizzArdOho, why not implement it?
21:10AWizzArdFunction is an interface.
21:10justin_smithoh right
21:10justin_smithso you could use reify
21:10AWizzArdI see it has some apply method that I can implement.
21:11AWizzArdBut seriously, there should be something in Clojure that makes this easy. Clojure is deeply integrated into the JVM, and I don’t think it should stop this here.
21:11justin_smithreify isn't so hard to use
21:12amalloyAWizzArd: reify is what makes it easy
21:12amalloythere can't be any tighter integration, because clojure isn't going to require java 8 anytime soon
21:12amalloyso it can't have a Function implementation built in
21:14AWizzArdamalloy: yes okay, depending on J8 is maybe too early, but I was thinking of the “never will” that justin_smith mentioned.
21:15AWizzArdamalloy: with the conditional compilation reader macros, couldn’t there be two compilation targets, of which J8 is one?
21:16amalloydo you have a conditional compilation reader macro that works for java, in which IFn and AFn and all that are defined?
21:22AWizzArdamalloy: two branches then. All patches are done on the current/classical brand and simply get merged into the J8 one.
21:24amalloyfeel free to propose this on clojure-dev. i predict it will not go far
21:24AWizzArdamalloy: you think the current interest in Java 8 is too small when weighted with the required effort that would have to be put into such a development?
21:24amalloyi don't know justin_smith's "never" is based on some specific statement from someone with authority or just a rough estimate, but with my limited information i expect it will be a very long time
21:28AWizzArdPerhaps future versions of Java will add interesting features that would increase the motivation to use them
21:51camm_v222Hi, I'm new at Clojure. Perhaps you know a web site, book, or video tutorials where I can learn about it?
21:52namracamm_v222: http://www.braveclojure.com/
21:52namracamm_v222: another one -> https://aphyr.com/posts/301-clojure-from-the-ground-up-welcome
21:53namrahttp://shop.oreilly.com/product/0636920034292.do
21:54camm_v222Thanks namra, I really appreaciate it.
21:55namrathere are other well know clojure books, but unfortunately forgot their names :/
21:56namracamm_v222: http://clojure.org/books?responseToken=a59c3eac653721eb2b49c7b99f5aa5d6 --- there you go
21:56namramany people recommend "the joy of clojure" but iirc it's not an introduction more like a book for people who already have experience with clojure
22:19taliosif there an (if-let) variant that accepts multiple binding forms at all? Can't seem to spot one..
22:19talioss/if/is/
22:19gfrederickstalios: not in clojure or contribs I don't think
22:20justin_smithnope
22:20gfredericksthere's been a bunch of discussions about that
22:20justin_smiththere have been various proposals but no unanimity of how it would work
22:20gfredericksI am pretty happy with prismatic/fnhouse
22:21taliosdoh, I wonder if I can use core.match for what I want, and match on a pair of things. basically I have a map and I want to conditional run something if 2 specific keys are present.
22:56nxqdhi guys, what is the safe way to get a value in a map based on a key where that key is not available : (def a {:a 2}) (:b a)
22:57gfredericksnxqd: what do you want that to evaluate to?
22:58nxqdI just found contain? I think it's what I need.
22:58nxqdthanks for helping :)
22:58gfredericksnp
23:28sdegutisHow can I profile all the time `lein run` is taking before -main is actually called?
23:39gfrederickstime lein run -m clojure.main -e '(println (quote hello))'
23:40gfredericksthough that probably won't require your code
23:40gfredericksso you'll want to add a require in there too
23:40gfredericksdoing both will tell you how much time is lein & clojure and how much time is compiling your code
23:41sdegutisgfredericks: it's definitely a good start though for a baseline
23:42ddellacostanxqd: a little late but you should also take a look at the behavior of get, that may be a simpler way to do what you want without doing some kind of check first
23:42ddellacosta&(get {:foo "foo"} :bar "bar")
23:42lazybot⇒ "bar"
23:43neoncontrailsWhat's the most idiomatic way in Clojure to keep iterating a lazy-seq until the values are no longer changing?
23:43sdegutisWHOA
23:44sdegutis(require 'my.main.namespace) takes 6673.242276 msecs
23:44gfrederickssdegutis: if you find the clojure jar in your ~/.m2 you can also run that with `time java -jar clojure.jar -e '(println :hello)'`
23:44neoncontrails,(take 10 (iterate (fn [x] (Math/cos x)) 1))
23:44clojurebot(1 0.5403023058681398 0.8575532158463934 0.6542897904977791 0.7934803587425656 ...)
23:44sdegutisIs it normal that it should take 6 seconds to require all my project's namespaces?
23:45gfrederickssdegutis: not too surprising
23:46gfrederickssdegutis: it probably includes loading all your libraries too
23:46sdegutis:(
23:46sdegutisRight.
23:46neoncontrailsTake <acceptably large fixnum> obviously gets the right answer eventually, but I'm curious how to short-circuit the evaluation when the values stop oscillating
23:47gfredericksneoncontrails: you want to detect when you get the same value twice in a row?
23:48amalloyneoncontrails: you want to wait until cos(x)~=x? for what values of x is that true
23:48sdegutisgfredericks: but is it reasonable for just loading a bunch of libs to take that long?
23:48sdegutisI mean all they should be doing is a bunch of (def) and (defn) right?
23:48gfredericksamalloy: something between 0 and pi I think
23:48gfrederickssdegutis: well it's compiling all of that code to classes
23:48amalloybetween 0 and pi/4 even, i would think
23:49gfrederickssdegutis: I think ztellman had one weird trick to speed it up that might not be incorporated yet
23:49neoncontrailsamalloy: How did I not see that before. Thank you!
23:49sdegutisgfredericks: oooo
23:49amalloyhow did what i said helped?
23:51neoncontrailsI think I was hitting a wall trying to access the (last (butlast sequence)) and compare it to the (last sequence), but yours is a much better solution
23:51amalloyi didn't offer a solution
23:52amalloynot one i recognized, anyway
23:53gfredericks,(->> (iterate #(Math/cos %) 1) (partition 2 1) (remove (fn [[a b]] (not= a b))) (ffirst))
23:53clojurebot0.7390851332151607
23:53gfredericks,(Math/cos 0.7390851332151607)
23:53clojurebot0.7390851332151607
23:53neoncontrailsYou asked the question in just the right way I suppose :)
23:53neoncontrails,(take-while (fn [x] (not (= x (Math/cos x)))) (iterate (fn [x] (Math/cos x)) 1))
23:53clojurebot(1 0.5403023058681398 0.8575532158463934 0.6542897904977791 0.7934803587425656 ...)
23:54neoncontrailsgfredericks: Interesting, can you briefly explain the logic?
23:54gfredericksneoncontrails: (partition 2 1 coll) gives you adjacent pairs
23:55gfrederickse.g., ##(partition 2 1 '[a b c d])
23:55lazybot⇒ ((a b) (b c) (c d))
23:55gfredericksso then just run through the list until you find two that are equal
23:55neoncontrailsAha, very good
23:57neoncontrails(inc gfredericks)
23:57lazybot⇒ 146
23:57neoncontrails(inc amalloy)
23:57lazybot⇒ 295
23:57amalloyyou can also just write that function once, call it fix
23:58neoncontrailsThat's a good point. I'll do that now as an exercise
23:58amalloygood thing you said, because i was about to paste a correct definition
23:59amalloy(which IMO turns out to be a lot clearer than a partition/iterate solution)
23:59gfredericks~amalloy |was about to paste| a correct definition
23:59clojurebotIn Ordnung