2015-08-25
| 00:00 | justin_smith | TEttinger: are you suggesting that different amounts of structural sharing would happen with different jvms? |
| 00:01 | TEttinger | I'm fairly certain that's currently the case for Sun's JVM on JDK 6 and strings versus OpenJDK 6 |
| 00:01 | andyf | TEttinger: 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:02 | andyf | If 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:02 | TEttinger | justin_smith: I know there are a lot of references to ???.sun.??? packages when profiling string-array or even char[] heavy code |
| 00:02 | justin_smith | interesting |
| 00:03 | TEttinger | one 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:04 | andyf | One 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:06 | andyf | It probably eliminates some extra cases in the code or something, but seems like a waste if the common case is short vectors. |
| 00:07 | justin_smith | andyf: isn't that what ztellman's big optimization with tuples was about? |
| 00:07 | justin_smith | the one that wasn't able to merge in because of 1.7 changes iirc |
| 00:11 | andyf | justin_smith: That optimization would eliminate that chunk of otherwise unused memory, yes. |
| 00:12 | andyf | It was also expected to speed things up in other ways other than avoiding that extra memory, I thought. |
| 00:14 | Olajyd | Hi TEttinger |
| 00:15 | TEttinger | hey Olajyd! |
| 00:16 | Olajyd | uhmmm vey well thanks, and you? |
| 00:16 | Olajyd | *very |
| 00:16 | andyf | Oops. 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:17 | Olajyd | TEttinger, I ran into a problem and thought I should Ping you :) |
| 00:18 | TEttinger | what's up? |
| 00:19 | TEttinger | so 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:20 | TEttinger | if 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:22 | talios | if 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:24 | justin_smith | ,(zipmap [:a :b] [1 2]) |
| 00:24 | clojurebot | {:a 1, :b 2} |
| 00:25 | talios | hah - and I just hit zipmap :) |
| 00:25 | talios | in the docs |
| 00:25 | Olajyd | TEttinger, haha, yea.. thanks :) |
| 00:25 | talios | I knew there was something I was mssing, and I was thinking zippers or zip-with :) |
| 00:26 | Olajyd | TEttinger, here’s the code on pastebin https://www.refheap.com/108697 |
| 00:26 | justin_smith | ,(defn zippedy-do-da [coll] (zipmap '[zippedy do dah zippedy day my oh my what a wonderful day] coll))) |
| 00:26 | clojurebot | #'sandbox/zippedy-do-da |
| 00:26 | justin_smith | ,(zippedy-do-da (range)) |
| 00:26 | clojurebot | {zippedy 3, do 1, dah 2, day 11, my 7, ...} |
| 00:27 | talios | :P |
| 00:27 | justin_smith | sorry, that was silly |
| 00:28 | TEttinger | Olajyd: 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:28 | TEttinger | ,010 |
| 00:28 | clojurebot | 8 |
| 00:28 | TEttinger | the examples are all fine, and if they stay as strings there's no issue |
| 00:28 | Olajyd | TEttinger, ok |
| 00:29 | Olajyd | TEttinger, I wanted to be able to change the index 0 of `prev-col-val` |
| 00:30 | talios | oh nREPL how I love thee. NOT. |
| 00:31 | talios | whats worse than an uber long stacktrace? ONLY showing the first line of a stacktrace, that inside PersistentHashMap |
| 00:31 | Olajyd | TEttinger, 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:31 | talios | PersistentArrayMap actually |
| 00:31 | justin_smith | talios: you can do (.printStackTrace *e) |
| 00:31 | justin_smith | talios: *e always points to the last exception |
| 00:32 | talios | w00t - and thats solve it. stupid repl - I'd reworked some code, then re-ran from repl history - which assumed a different data structure :) |
| 00:35 | Olajyd | TEttinger, I dont knw if thats the way to go anyway, what do you think? |
| 00:35 | TEttinger | I think I have an... unusual and small solution |
| 00:37 | Olajyd | TEttinger, this is data immuability problem right? |
| 00:38 | TEttinger | ,(defn replicate-header-value [col data] (reductions (fn [a b] (if (empty? (nth b col)) (assoc b col (nth a col)) b)) data)) |
| 00:38 | clojurebot | #'sandbox/replicate-header-value |
| 00:38 | TEttinger | ,(replicate-header-value 1 [["04" "2" "3"] ["04" "" "5"] ["5" "16" ""] ["07" "" "36"] ["07" "" "34"] ["07" "25" "34"]]) |
| 00:38 | clojurebot | (["04" "2" "3"] ["04" "2" "5"] ["5" "16" ""] ["07" "16" "36"] ["07" "16" "34"] ...) |
| 00:39 | TEttinger | clojurebot cuts off output if the sequence is too long, but it looks right |
| 00:39 | TEttinger | ,(replicate-header-value 2 [["04" "2" "3"] ["04" "" "5"] ["5" "16" ""] ["07" "" "36"] ["07" "" "34"] ["07" "25" "34"]]) |
| 00:39 | clojurebot | (["04" "2" "3"] ["04" "" "5"] ["5" "16" "5"] ["07" "" "36"] ["07" "" "34"] ...) |
| 00:40 | TEttinger | ,(replicate-header-value 2 [["5" "16" ""] ["07" "" "36"] ["07" "" "34"] ["07" "25" "34"]]) |
| 00:40 | clojurebot | (["5" "16" ""] ["07" "" "36"] ["07" "" "34"] ["07" "25" "34"]) |
| 00:40 | TEttinger | yep, if the header has an empty string it doesn't change it |
| 00:40 | Olajyd | ok |
| 00:40 | TEttinger | ,(replicate-header-value 1 [["5" "16" ""] ["07" "" "36"] ["07" "" "34"] ["07" "25" "34"]]) |
| 00:40 | clojurebot | (["5" "16" ""] ["07" "16" "36"] ["07" "16" "34"] ["07" "25" "34"]) |
| 00:40 | TEttinger | do you want me to explain it? |
| 00:40 | Olajyd | yes please :) |
| 00:41 | TEttinger | reductions 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:42 | TEttinger | so 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:42 | Olajyd | oh nice, this is the first time I’m seeing reductions though, TEttinger, |
| 00:42 | TEttinger | it's an uncommon one. I have found it comes up not often, but often enough to be useful |
| 00:43 | TEttinger | the fn that I pass to it likely needs explaining. |
| 00:44 | TEttinger | (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:45 | Olajyd | ok great, thanks |
| 00:45 | TEttinger | it 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:46 | Olajyd | TEttinger, out of curiorsity, what was I doing wrong in the problem? |
| 00:46 | TEttinger | I honestly didn't check that closely since I was pretty sure there was a less complicated way |
| 00:47 | TEttinger | you're right, it's immutability related |
| 00:47 | TEttinger | (assoc prev-col-val 0 (get row col)) doesn't change prev-col-val, it returns a new copy |
| 00:48 | TEttinger | so that was just doing the modification and throwing it away right after |
| 00:48 | Olajyd | hmm, now I get it :) |
| 00:48 | TEttinger | you would likely want to go about that way using loop/recur, which can be complicated sometimes, or an atom, which is effectively mutable |
| 00:49 | TEttinger | loop and recur are preferred for a number of reasons, but an atom is fine while you're learning |
| 00:50 | TEttinger | oh 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:50 | TEttinger | the " b" at the very end is the else block of the if |
| 00:50 | TEttinger | so it returns the upcoming arg unaltered if it isn't empty in the column |
| 00:53 | Olajyd | TEttinger, thanks :) |
| 00:53 | TEttinger | glad to help! |
| 00:54 | Olajyd | 8) , I’ve adjusted my time so that I can meet you online, :D |
| 00:54 | TEttinger | haha nice |
| 00:55 | TEttinger | yeah it seemed earlier than before |
| 00:55 | TEttinger | great! |
| 00:56 | Olajyd | Hopefully tomorrow I’ll ping you |
| 00:57 | ttt_fff | is 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:58 | TEttinger | ttt_fff, interesting. personally I find haskell hard to read when it uses $ |
| 00:58 | TEttinger | otherwise it's rather clean |
| 00:58 | ttt_fff | i find the pattern matching notation / type sigs very concise |
| 00:58 | ttt_fff | more so than any macros I can rig up with () |
| 00:58 | jeaye | ttt_fff: I'm just the opposite. |
| 00:58 | jeaye | Can't stand the haskell syntax, really love s-exprs |
| 01:00 | TEttinger | I kinda stopped caring about syntax a while ago |
| 01:00 | ttt_fff | i'm writing a new config langauge |
| 01:00 | ttt_fff | and need to decie between haskell like vs scheme like |
| 01:00 | TEttinger | haskell's going to be harder to parse I imagine |
| 01:00 | arrdem | why are you writing your own parser... |
| 01:00 | TEttinger | have you looked at Io? |
| 01:00 | arrdem | just use datastructures |
| 01:01 | arrdem | I'm sure there are several fine Haskell config file readers |
| 01:01 | arrdem | no need to run off and invent a new language |
| 01:01 | TEttinger | you could even use something that "looks" like haskell but really just pattern matches/regex replaces to clojure/scheme data structures |
| 04:09 | gilliard | Given 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:12 | TEttinger | ,(max-key (mapv #(.nextInt (java.util.Random. %)) (range 1 100))) |
| 04:12 | clojurebot | #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:13 | jeaye | gilliard: Maybe naive, but map f over the range, then sort, then take the first. |
| 04:13 | TEttinger | ,(doc max-key) |
| 04:13 | clojurebot | "([k x] [k x y] [k x y & more]); Returns the x for which (k x), a number, is greatest." |
| 04:13 | kungi | I 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:14 | TEttinger | ,(into (sorted-map) (map (fn [n] [n (.nextInt (java.util.Random. n))]) (range 1 100))) |
| 04:14 | clojurebot | {1 -1155869325, 2 -1154715079, 3 -1155099828, 4 -1157023572, 5 -1157408321, ...} |
| 04:15 | TEttinger | ah |
| 04:15 | TEttinger | ,(into (sorted-map-by val) (map (fn [n] [n (.nextInt (java.util.Random. n))]) (range 1 100))) |
| 04:15 | clojurebot | #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:15 | TEttinger | ,(into (sorted-map-by second) (map (fn [n] [[n (.nextInt (java.util.Random. n))]]) (range 1 100))) |
| 04:15 | clojurebot | #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:15 | TEttinger | agh |
| 04:16 | gilliard | jeaye: Yeah that was my idea but I'm hoping for something simpler... |
| 04:17 | magnars | kungi: It's a work in process. You can find all my Emacs settings in https://github.com/magnars/.emacs.d :) |
| 04:17 | jeaye | (first (sort > (map f (range 1 n)))) is simpler than everything shown above, I thinkg |
| 04:17 | oddcully | ,(apply max-key (fn [x] (* x x)) (range 5)) |
| 04:17 | clojurebot | 4 |
| 04:18 | magnars | kungi: 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:19 | gilliard | jeaye: That gives me the maximum value for (f n) but I want to know which n produces that. |
| 04:19 | jeaye | gilliard: My mistake |
| 04:19 | kungi | magnars: Thank you! |
| 04:22 | gilliard | Thanks oddcully |
| 04:22 | gilliard | ,(doc max-key) ; basically restates my question :) |
| 04:22 | clojurebot | "([k x] [k x y] [k x y & more]); Returns the x for which (k x), a number, is greatest." |
| 04:23 | oddcully | (inc TEttinger) |
| 04:23 | lazybot | ⇒ 64 |
| 04:23 | gilliard | ,(source max-key) ; is nice too |
| 04:24 | clojurebot | Source not found\n |
| 04:25 | TEttinger | ,(apply max-key #(.nextInt (java.util.Random. %)) (range 5)) |
| 04:25 | clojurebot | 2 |
| 04:26 | TEttinger | ,(apply max-key #(.nextInt (java.util.Random. %)) (range 500)) |
| 04:26 | clojurebot | 402 |
| 04:26 | TEttinger | nice |
| 04:26 | TEttinger | ,(.nextInt (java.util.Random. 402)) |
| 04:26 | clojurebot | -1000815519 |
| 04:26 | TEttinger | hm |
| 04:26 | gilliard | lol |
| 04:26 | TEttinger | that seems not right |
| 04:26 | TEttinger | ,(.nextInt (java.util.Random. 2)) |
| 04:26 | clojurebot | -1154715079 |
| 04:26 | TEttinger | ,(.nextInt (java.util.Random. 0)) |
| 04:26 | clojurebot | -1155484576 |
| 04:27 | hyPiRion | TEttinger: next int is just a random int based on the seed you gave it |
| 04:27 | TEttinger | are they all negative??? |
| 04:27 | lazybot | TEttinger: Yes, 100% for sure. |
| 04:27 | hyPiRion | oh |
| 04:27 | TEttinger | I know |
| 04:27 | hyPiRion | ,(.nextInt (java.util.Random. -1155484576)) |
| 04:27 | clojurebot | -1764305998 |
| 04:27 | TEttinger | what on earth... |
| 04:27 | hyPiRion | ,(.nextInt (java.util.Random. -1073741824)) |
| 04:27 | clojurebot | 664794208 |
| 04:27 | hyPiRion | coincidence I guess. |
| 04:28 | TEttinger | ,(map #(.nextInt (java.util.Random. %)) (range 5)) |
| 04:28 | clojurebot | (-1155484576 -1155869325 -1154715079 -1155099828 -1157023572) |
| 04:28 | TEttinger | yeah... that seems like a LCG problem |
| 04:28 | oddcully | quick, get the booky! TEttinger is on a run |
| 04:28 | hyPiRion | Looks like the first value isn't that non-random |
| 04:29 | TEttinger | ,(map #(.nextInt (java.util.Random. %)) (range 5)) |
| 04:29 | clojurebot | (-1155484576 -1155869325 -1154715079 -1155099828 -1157023572) |
| 04:29 | TEttinger | it's seeded hyPiRion |
| 04:30 | TEttinger | what's weird is that it seems like for a large consecutive range of seeds, the first number is negative... |
| 04:30 | hyPiRion | TEttinger: What I meant was that the highest bits of the first value seems to be very similar |
| 04:31 | BorePlusPlus | If 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:31 | hyPiRion | ,(map #(let [r (java.util.Random. %)] (.nextInt r) (.nextInt r)) (range 5)) ;; looks fine here |
| 04:31 | clojurebot | (-723955400 431529176 1260042744 -1879439976 -396984392) |
| 04:31 | TEttinger | ,(map #(.nextInt (java.util.Random. %)) (range 36rRANDOMNESS 36rRANDOMNESX)) |
| 04:31 | clojurebot | (-559045358 -559430107 -558275860 -558660609 -548272389) |
| 04:31 | TEttinger | interesting |
| 04:31 | gilliard | yes, it looks like any two consecutive seeds produce pretty close nextInts |
| 04:32 | TEttinger | ,(map #(.nextInt (java.util.SplittableRandom. %)) (range 36rRANDOMNESS 36rRANDOMNESX)) |
| 04:32 | clojurebot | #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:33 | gilliard | ,(map #(.nextInt (java.security.SecureRandom. (byte-array %))) (range 50)) |
| 04:33 | clojurebot | (-956323137 -1820334814 -1691674753 533104038 1374720712 ...) |
| 04:33 | luxbock | magnars: 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:33 | TEttinger | &(map #(.nextInt (java.util.SplittableRandom. %)) (range 36rRANDOMNESS 36rRANDOMNESX)) |
| 04:33 | lazybot | java.lang.ClassNotFoundException: java.util.SplittableRandom |
| 04:34 | magnars | luxbock: it's paredit-wrap-round, bound to M-( by default I think |
| 04:35 | luxbock | magnars: ah cool |
| 04:35 | TEttinger | woah what, neither bot uses java 8 now? https://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html |
| 04:36 | kungi | magnars: 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:36 | TEttinger | huh, must not be used by lazybot at least. my lazybot gives (-522495519 1499783386 -58986586 574128689 1912616253) |
| 04:37 | oddcully | (frequencies (map #(compare (.nextInt (java.util.Random. %)) 0) (range (Integer/MAX_VALUE)))) ; {-1 1073739864, 1 1073743783} |
| 04:37 | magnars | kungi: hah, glad to hear that :) the next episode will be out on friday |
| 04:37 | kungi | magnars: \o/ |
| 04:39 | TEttinger | (frequencies (map #(compare (.nextInt (java.util.Random. %)) 0) (range 0xffff))) |
| 04:39 | TEttinger | ,(frequencies (map #(compare (.nextInt (java.util.Random. %)) 0) (range 0xffff))) |
| 04:39 | clojurebot | {-1 33492, 1 32043} |
| 04:40 | TEttinger | a ha! |
| 04:40 | TEttinger | ,(frequencies (map #(compare (.nextInt (java.util.Random. %)) 0) (range 0xfff))) |
| 04:40 | clojurebot | {-1 4095} |
| 04:40 | TEttinger | up to 0xfff it only produces negative first numbers! |
| 04:41 | luxbock | magnars: what kind of keyboard are you using? |
| 04:41 | magnars | luxbock: Norwegian MBP |
| 04:45 | luxbock | magnars: 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:45 | luxbock | works great for Emacs |
| 04:45 | luxbock | because it puts your thumbs to work |
| 04:46 | magnars | yeah, 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:48 | kungi | luxbock: I use a kinesis advantage keyboard which is also just great for emacs and typing in general. |
| 05:02 | crocket | Is it possible to use robert hooke on multimethods? |
| 06:33 | dxlr8r | hello, any recommendations on a socket server library for clojure? I just need basic functionality |
| 06:44 | notarobot_ | dxlr8r: http://www.luminusweb.net/docs/websockets.md |
| 06:46 | dxlr8r | notarobot_: not websocket, regular socket server :) |
| 06:58 | notarobot_ | dxlr8r: oops sorry |
| 06:58 | H4ns | dxlr8r: what are you looking for in a socket library, really? |
| 07:03 | dxlr8r | H4ns: implementing a socket in my application? |
| 07:03 | Olajyd | HI, oddcully |
| 07:04 | dxlr8r | found this in the end, https://github.com/bguthrie/async-sockets , looks ok :) |
| 07:10 | Olajyd | Hi, 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:11 | Olajyd | updated link: https://www.refheap.com/108708 |
| 07:14 | dstockton | Olajyd: no expert, but I think you want to look at something like loop/recur |
| 07:14 | Olajyd | :| |
| 07:14 | dxlr8r | was just going to suggest that :) |
| 07:14 | dstockton | and pass the previous-col-val to the next iteration |
| 07:14 | Olajyd | uhmm, I want to avoid using the loop/recur form |
| 07:15 | oddcully | Olajyd: isn't this just another view on the problem from earlier? |
| 07:17 | oddcully | it it is: ,(reductions (fn [old new] (if (empty? new) old new)) ["a" "" "b" "" "" "c"]) |
| 07:18 | Olajyd | yeaa, oddcully, I just want to understand it more |
| 07:19 | Olajyd | oddcully, maybe you could shed more lights on data immuatability :) |
| 07:20 | oddcully | my guess is, that this has nothing to do with mutable data |
| 07:20 | oddcully | but your brain wants to write imperative code |
| 07:22 | oddcully | like having a "def last" outside of the loop where you want to keep track of the last good value |
| 07:22 | oddcully | with loop/recur or a reduce you just send the last good value just back into the loop |
| 07:26 | negaduck | hi! 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:32 | pseudonymous | I'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:33 | schmir | pseudonymous: (jdbc/query db ["<query"> ...]) |
| 07:33 | schmir | pseudonymous: where jdbc is clojure.java.jdbc |
| 07:33 | pseudonymous | I tried that, though INSERT statements aren't allowed there. |
| 07:34 | schmir | jdbc/execute! |
| 07:35 | pseudonymous | schmir: 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:36 | schmir | Olajyd: IMHO you should forget about refs and atoms when starting with clojure development |
| 07:36 | schmir | pseudonymous: how about praised be schmir :) |
| 07:36 | oddcully | karma *nudgenudge* |
| 07:37 | Olajyd | schmir, hmmm |
| 07:37 | pseudonymous | schmir: You could quite possibly be one of the machine gods - if not, I'll at least petition them for your inclusion :) |
| 07:37 | schmir | pseudonymous: thanks :) |
| 07:38 | schmir | Olajyd: really. I'm developing a commercial clojure program and never used a ref |
| 07:39 | schmir | git grep atom |wc -l says 16, where I have above 10k lines of code |
| 07:40 | Olajyd | schmir, 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:40 | Olajyd | *problem |
| 07:41 | Olajyd | schmir, does `reductions` work with a lazy-sequence? |
| 07:43 | schmir | Olajyd: yes, why shouldn't it work |
| 07:44 | oddcully | ,(take 10 (reductions (fn [old new] (if (empty? new) old new)) (cycle ["a" "" "b" "" "c"]))) |
| 07:45 | clojurebot | ("a" "a" "b" "b" "c" ...) |
| 07:46 | Olajyd | so the thing is I’m using clojure with Apache-spark, and the apache-spark, data-structures are usually in lazy-sequences :| |
| 07:46 | justin_smith | reductions can take a lazy-sequence, and it returns one |
| 07:59 | gfredericks | ,(reductions (comp second list) 5 '(0 1 2 3 4)) |
| 07:59 | clojurebot | (5 0 1 2 3 ...) |
| 07:59 | gfredericks | ,(reductions (comp second list) 0 ()) |
| 07:59 | clojurebot | (0) |
| 08:00 | gfredericks | ,(reductions (comp second list) 1 *1) |
| 08:00 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Var$Unbound> |
| 08:06 | Olajyd | can somebody explain (.toJavaRDD)? |
| 08:07 | justin_smith | it'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:09 | justin_smith | if 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:11 | Olajyd | ok |
| 08:12 | Olajyd | Thanks justin_smith |
| 08:21 | Olajyd | justin_smith, I got another question |
| 08:22 | Olajyd | Is it possible to convert clojure.lang.LazySeq to toJavaRDD? |
| 08:25 | justin_smith | Olajyd: toJavaRDD is a method, not a class - what class does toJavaRDD belong to? |
| 08:26 | Olajyd | I just google it though, :) |
| 08:27 | Olajyd | but ultimately I want to convert the clojure.lang.LazySeq to type JavaRDD |
| 08:28 | Olajyd | tried this though (r (-> result (.toJavaRDD))) |
| 08:28 | justin_smith | that's equivalent to (r (.toJavaRDD result)) |
| 08:29 | justin_smith | what is result? |
| 08:29 | justin_smith | a lazy-seq? |
| 08:29 | Olajyd | yes |
| 08:30 | justin_smith | that'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:30 | Olajyd | Dont knw whether i’m making a mistake though :| |
| 08:30 | justin_smith | I don't know spark well enough to know how one constructs RDD objects |
| 08:30 | justin_smith | Olajyd: are you using spark directly? are you using a lib like flambo? |
| 08:31 | Olajyd | oh great that explains why I’m getting this `No matching field found: toJavaRDD for class clojure.lang.LazySeq` right? |
| 08:31 | Olajyd | justin_smith, exactly :) |
| 08:31 | justin_smith | yeah, it's trying to tell you exactly what I just tried to explain |
| 08:31 | justin_smith | Olajyd: I mentioned two options... |
| 08:31 | Olajyd | you farmiliar with flambo, justin_smith? |
| 08:33 | justin_smith | Olajyd: I saw sorenmacbeth give a couple talks about it, and I know it's a spark wrapper |
| 08:33 | justin_smith | I haven't used it though |
| 08:34 | Olajyd | great |
| 08:36 | justin_smith | Olajyd: 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:38 | Olajyd | ok 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:40 | justin_smith | I'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:02 | gilliard | (frequencies (map #(compare (.nextInt (java.util.Random. %)) 0) (range (Integer/MIN_VALUE) (Integer/MAX_VALUE)))) ; => {1 2147483647, -1 2147483648} |
| 09:03 | gilliard | As I read that, it seems impossible to get "0" as a response to nextInt... |
| 09:03 | justin_smith | ,(frequencies (map #(compare (.nextInt (java.util.Random. %)) 0) (range (Integer/MIN_VALUE) (Integer/MAX_VALUE)))) |
| 09:03 | clojurebot | eval service is offline |
| 09:03 | gilliard | How long have you got ;) |
| 09:03 | justin_smith | haha |
| 09:03 | gfredericks | gilliard: that might be true |
| 09:03 | oddcully | gilliard: thought the same with half of the numbers |
| 09:03 | gfredericks | ,(.nextInt (java.util.Random. Integer/MAX_VALUE)) |
| 09:03 | clojurebot | -1631654733 |
| 09:04 | gilliard | oddcully, gfredericks: yes it might be true, mightn't it? |
| 09:05 | gfredericks | gilliard: that's not the full seed range though |
| 09:05 | oddcully | gilliard: at at least as first number |
| 09:05 | gfredericks | I think zero should be possible, set me see if I can reverse engineer it |
| 09:05 | gilliard | oddcully: looking at the source of j.u.Random, I don't see how it is, but gfredericks is about to show me! |
| 09:06 | gilliard | oh yes, the seed is a long, and even I don't have that kind of patience... |
| 09:06 | oddcully | ah right it's a long. now i need pmap |
| 09:07 | gfredericks | gilliard: the seed is a long but it's truncated to 48 bits I think |
| 09:07 | gfredericks | have to check the constructor to be sure |
| 09:07 | gilliard | Yes: http://developer.classpath.org/doc/java/util/Random-source.html |
| 09:08 | justin_smith | ~gfredericks |is| about to show you. |
| 09:08 | clojurebot | Ok. |
| 09:08 | gfredericks | the whole algorithm is 48 bits |
| 09:09 | justin_smith | hey did you guys hear that there is a new fridge that leaks your gmail credentials? the world is stupid |
| 09:10 | gfredericks | I don't know enough arithmetic to reverse engineer this any better than just searching higher |
| 09:10 | gilliard | I got interested after reading this: http://franklinta.com/2014/08/31/predicting-the-next-math-random-in-java/ |
| 09:12 | gfredericks | ,(defn java-random [seed] (-> seed (unchecked-add 0x5deece66d) (unchecked-multiply 0x5deece66d) (bit-shift-right 16) (unchecked-int))) |
| 09:12 | clojurebot | #'sandbox/java-random |
| 09:12 | ebzzry | How/where is let* defined? |
| 09:12 | gfredericks | ,(java-random 42) |
| 09:12 | clojurebot | #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:12 | gfredericks | ,(defn java-random [^long seed] (-> seed (unchecked-add 0x5deece66d) (unchecked-multiply 0x5deece66d) (bit-shift-right 16) (unchecked-int))) |
| 09:12 | clojurebot | #'sandbox/java-random |
| 09:12 | gfredericks | ,(java-random 42) |
| 09:12 | clojurebot | -1139325123 |
| 09:12 | gfredericks | ,(.nextInt (java.util.Random. 42)) |
| 09:12 | clojurebot | -1170105035 |
| 09:12 | gfredericks | aw poop |
| 09:13 | akabander | When I do (doc let) it says clojure.core/let |
| 09:13 | gfredericks | ,(doc let) |
| 09:14 | clojurebot | "([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:14 | gfredericks | ,(.nextInt (java.util.Random 2464063869)) |
| 09:14 | clojurebot | #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:14 | akabander | ,(clojure-version) |
| 09:14 | clojurebot | "1.8.0-alpha3" |
| 09:14 | oddcully | gfredericks: 0-4096 as seed gives a negative |
| 09:14 | gfredericks | ,(.nextInt (java.util.Random. 2464063869)) |
| 09:14 | clojurebot | 0 |
| 09:14 | oddcully | ah there ya go |
| 09:15 | oddcully | (inc gfredericks) |
| 09:15 | lazybot | ⇒ 145 |
| 09:15 | gfredericks | gilliard: ^ I found that after 17 seconds of searching |
| 09:15 | akabander | Hmm, I get more data from doc, maybe the lein repl is doing something? |
| 09:15 | oddcully | ,(Long/toBinaryString 2464063869) |
| 09:15 | clojurebot | "10010010110111101010000101111101" |
| 09:16 | justin_smith | akabander: I think it's more that clojurebot's version is truncated |
| 09:16 | gfredericks | gilliard: this result is actually expected for *any* decent RNG |
| 09:16 | justin_smith | akabander: did you have a question about clojure.core/let ? that is the namespace it comes from |
| 09:16 | justin_smith | akabander: in clojure.core namespaces don't map 1-1 with files though |
| 09:17 | gfredericks | your 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:17 | gfredericks | s/expected/unsurprising/ |
| 09:17 | gilliard | gfredericks: That's why I was surprised. I had thought the seed was an Integer. |
| 09:17 | akabander | I was trying to answer ebzzry, but I think I answered wrong with (doc let) and not let* |
| 09:18 | gfredericks | gilliard: even if it were, it should only be surprising if the RNG guarantees it will generate every value exactly once |
| 09:18 | akabander | I don't have a let* in my repl, so it's not core. |
| 09:18 | ebzzry | akabander: the same in my case |
| 09:19 | justin_smith | akabander: let* is a special form, it is defined in java |
| 09:19 | justin_smith | let is a macro calling let*, it is in clojure.core |
| 09:19 | akabander | justin_smith: It was ebzzry who was asking. |
| 09:19 | gilliard | gfredericks: I would expect any value to be equally likely (give or take). |
| 09:19 | justin_smith | ahh, I missed that, sorry |
| 09:19 | ebzzry | justin_smith: ok. thanks. |
| 09:20 | akabander | It's cool, I got your attention, which got the correct answer for ebzzry :^) |
| 09:20 | justin_smith | ebzzry: there's a function that tells you if something is a special-form |
| 09:20 | akabander | Conveniently for me, I'm reading the macro section of "Joy", so the source for let almost makes sense to me! |
| 09:20 | ebzzry | do you know where in tha java source can I see the definition of let* and fn*? |
| 09:20 | justin_smith | ,(special-symbol? 'let*) |
| 09:20 | clojurebot | true |
| 09:21 | justin_smith | ebzzry: one moment, it's not too hard to find... |
| 09:21 | ebzzry | justin_smith: thanks |
| 09:23 | gfredericks | gilliard: for a deterministic generator with 32 bit seed and 32 bit output, that implies generating every value exactly once |
| 09:23 | justin_smith | ebzzry: 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:23 | gfredericks | i.e., the generator is a permutation of the seed |
| 09:24 | justin_smith | ebzzry: so in Compiler.java it sets up "Opcodes" for parsing / binding, and let* is one of those |
| 09:25 | justin_smith | ebzzry: 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:25 | jeaye | 9K line file -_- |
| 09:25 | ebzzry | justin_smith: thanks |
| 09:25 | justin_smith | jeaye: clojure's java is far from the prettiest :P |
| 09:25 | gilliard | gfredericks: Ack, thanks. And because it's a 48bit seed, nextLong actually does have some gaps. |
| 09:26 | justin_smith | ebzzry: this appears to be the meat of it https://github.com/clojure/clojure/blob/1d5237f9d7db0bc5f6e929330108d016ac7bf76c/src/jvm/clojure/lang/Compiler.java#L6218 |
| 09:27 | justin_smith | ebzzry: 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:31 | gfredericks | gilliard: yep |
| 10:02 | snowell | Say I have a map {:one 1 :two 2} and I want to do a (let {:keys [one two]} myMap) on it |
| 10:03 | snowell | But instead of having to specify the symbols, I just want to destructure all the keys of the map |
| 10:03 | snowell | Is there an idiomatic (or any) way to accomplish this? |
| 10:03 | snowell | I tried (into [] (map (comp symbol name) (keys myMap))), but no dice |
| 10:03 | akabander | snowell: I was wondering this earlier, I think there'd be issues with symbols in the body of the expression? |
| 10:04 | snowell | It's not a huge deal. Just wanted to preserve a little readability |
| 10:04 | gfredericks | snowell: nope, no way to do that, and that would be discouraged too |
| 10:04 | akabander | Reader/compiler/runtime confusion? |
| 10:04 | gfredericks | since it means you can't tell by looking at the code what it does |
| 10:04 | gilliard | programmer confusion |
| 10:04 | snowell | gfredericks: that's fair |
| 10:05 | gfredericks | e.g., say I have (fn [{destructure-all-keys}] (+ a b)) |
| 10:05 | gfredericks | ^ what does + mean there? |
| 10:05 | gfredericks | sometimes it's clojure.core/+ but other times it's the :+ key of the map you pass in |
| 10:06 | snowell | Yeah, that would be no bueno |
| 10:06 | gfredericks | clojure & associated macros are typically designed so that when a name becomes part of the lexical scope, you can see it explicitly |
| 10:06 | gfredericks | even at the expense of a little verbosity |
| 10:07 | noncom|2 | i think a macros can be written to enable that |
| 10:07 | noncom|2 | but that is a very bad practice... |
| 10:07 | gfredericks | you can't do it with a macro in a straightforward way |
| 10:07 | gfredericks | because macros operate at compile-time and you don't know what keys there are until runtime |
| 10:08 | noncom|2 | the macro could take all keys and symbolize them and intern them with their values |
| 10:08 | gfredericks | "all keys"? |
| 10:08 | noncom|2 | yes.. |
| 10:08 | R0B_ROD | Hi |
| 10:08 | akabander | It would conceptually expand to a big messy let statement. |
| 10:09 | gfredericks | noncom|2: where do you get the list of keys from at compile-time? |
| 10:09 | akabander | Aha, that's the technical problem that was bugging me |
| 10:09 | gfredericks | the only way to do something like that is to call eval at runtime |
| 10:09 | gfredericks | which basically means you're calling the compiler every time the function gets run |
| 10:10 | noncom|2 | gfredericks: 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:10 | gfredericks | noncom|2: I think whatever you're imagining will boil down to calling eval |
| 10:11 | gfredericks | the 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:12 | noncom|2 | yeah, maybe eval.. |
| 10:13 | noncom|2 | no need to walk, just intern them all. anyway you're already screwed if you're doing this kind of thing imho.. |
| 10:16 | crocket | gfredericks, What do you make with clojure nowadays? any meaningful project? |
| 10:20 | snowell | cfleming: I take back anything bad I thought about Cursive. I'm enjoying my time with it immensely. Thanks! |
| 10:21 | gfredericks | noncom|2: does "intern" mean "create some vars"? |
| 10:21 | gfredericks | crocket: I use it at work and I'm maintaining test.check |
| 10:22 | noncom|2 | gfredericks: yes, sorry, i meant that. well, first to make the symbols, intern them within the curent environment and assign vars to them |
| 10:23 | gfredericks | noncom|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:24 | noncom|2 | gfredericks: 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:25 | gfredericks | noncom|2: you can't dynamically access the lexical environment, no |
| 10:25 | gfredericks | it's not reified, it's compiled into bytecode |
| 10:25 | noncom|2 | for example, let has simpler rules on variable reassign |
| 10:25 | gfredericks | in the code (let [a (inc x)] (f x)), "a" does not exist in any meaningful way |
| 10:25 | noncom|2 | hmmm |
| 10:26 | gfredericks | contrasted with (def b 12) where b is a var you can poke and do things with |
| 10:26 | noncom|2 | well, 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:29 | crocket | gfredericks, doesn't sound very interesting. |
| 10:41 | justin_smith | crocket: on the contrary, test.check is fascinating, you should take a look at what it does |
| 10:52 | akabander | noncom|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:53 | noncom|2 | akabander: 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:53 | snowell | Sorry I started all that! :D |
| 10:54 | akabander | Haha, 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:55 | akabander | It's an interesting puzzle, in the same way "how would I weaponize grey goo" is interesting. |
| 10:59 | justin_smith | I know, instead of implicit local bindings, we could implement content tracking in clojure.string, sending all data to google between every string transform |
| 11:01 | akabander | Yeah, a local redis would not be cloudy enough. |
| 11:01 | justin_smith | nor would it be as careless with client data |
| 11:01 | akabander | But I like the google idea because every query could be "i'm feeling lucky" |
| 11:01 | justin_smith | haha |
| 11:03 | chance123 | ||||| >>>>> WHAT IS YOUR DOMAIN NAME WORTH? Vist >>> www.VALBOT.com <<< FREE DOMAIN VALUATION! or GOOGLE >>> VALBOT.com <<< ||||| |
| 11:04 | sdegutis | Is it possible define a defmethod in a namespace that has no access to the defmulti? |
| 11:05 | justin_smith | no, defmethod actually alters the defmulti created var itself |
| 11:05 | sdegutis | Dang. |
| 11:05 | sdegutis | I'm trying to do my configs up using these. |
| 11:05 | H4ns | erm, you can define methods for multimethods created in other namespaces |
| 11:06 | H4ns | I'm not sure if I'm misunderstanding the question or justin_smith's answer, though. |
| 11:06 | justin_smith | H4ns: yes, but he wants to do it without accessing the namespace with the defmethod in it |
| 11:06 | justin_smith | err, without the defmulti |
| 11:06 | justin_smith | H4ns: he said with no access, if you can load the namespace that is access |
| 11:06 | justin_smith | perhaps I misunderstood the question |
| 11:06 | justin_smith | sdegutis: by "no access" do you mean "cannot require the ns at runtime" ? |
| 11:14 | sdegutis | justin_smith: ah no I meant inside the (ns). |
| 11:14 | sdegutis | Inside the ns that defines the defmulti, I want to :require the namespaces that define the defmethods. |
| 11:14 | sdegutis | This is the thing not possible, accurate? |
| 11:15 | justin_smith | yeah, that shit's cray |
| 11:15 | H4ns | sdegutis: you could create an extra namespace for the defmulti |
| 11:15 | justin_smith | there's probably a hack using resolve and require at runtime, but it aint worth it bro |
| 11:15 | sdegutis | trudat |
| 11:16 | sdegutis | Perhaps using defmulti for configs is dumb. |
| 11:16 | justin_smith | you can use defmulti - just put the defmulti in a namespace with no implementation logic in it |
| 11:16 | sdegutis | Oh right. |
| 11:16 | justin_smith | and put the implementation logic in another namespace, higher in the tree |
| 11:16 | sdegutis | So A requires B,C,D which each require Z, and A requires Z to call it's defmulti. |
| 11:17 | sdegutis | where B,C,D each have a defmethod for Z's defmulti |
| 11:17 | sdegutis | amirite? |
| 11:17 | justin_smith | sdegutis: I think I've said this before, but defmulti and defprotocol belong in vapid namespaces that only define abstractions and no implementation details |
| 11:17 | justin_smith | sdegutis: yes, something like that |
| 11:17 | sdegutis | justin_smith: weird. |
| 11:18 | sdegutis | I like circular dependencies. Sad Haskell/Clojure don't support them. |
| 11:18 | justin_smith | sdegutis: this is platonic epistimology, where the abstract essence of things is prior to their concrete manifestation |
| 11:18 | sdegutis | Does "accidents" fit in there somewhere? |
| 11:18 | akabander | I knew that Philosophy degree would come in handy! |
| 11:18 | justin_smith | sdegutis: but if you use your abstractions properly, every circular dependency becomes a non-circular one |
| 11:20 | sdegutis | This is not magic enough for me. |
| 11:20 | sdegutis | I need more magic. |
| 11:20 | justin_smith | ruby is over there -> |
| 11:20 | sdegutis | I think I'll derive a namespace via string. |
| 11:20 | sdegutis | Then I'll load the var in that namespace. |
| 11:21 | sdegutis | So for :production I'll load #'config.production/config |
| 11:21 | sdegutis | Deal? |
| 11:21 | justin_smith | sdegutis: symbols and resolve are more direct, but this is the path to evil |
| 11:21 | justin_smith | and by "evil" I mean your own pain and suffering in the future |
| 11:22 | sdegutis | This is top-level config-setting stuff. |
| 11:22 | sdegutis | This is the absolutely most correct place to use magic. |
| 11:22 | sdegutis | Heck I'm even using lein-environ! |
| 11:22 | sdegutis | Now, web handler routing and such, that's a much more questionable place to use black magic. |
| 11:23 | justin_smith | I already described the clean way to do this, and I know you understood it because you basically repeated it back to me. |
| 11:23 | sdegutis | Using defmulti? |
| 11:24 | sdegutis | I started implementing it, then I didn't like how much repetition there was in (ns config.dev) (defmulti configs :dev ...) |
| 11:24 | sdegutis | See "dev" in that file twice. Bad. |
| 11:24 | justin_smith | right, 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:25 | justin_smith | sdegutis: I don't think this is a constrcutive conversation any more. |
| 11:25 | sdegutis | Pragmatism always trumps correctness. The only time this seems to not be true is when correctness serves pragmatism. |
| 11:25 | sdegutis | In 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:37 | sdegutis | Got it: (defn get-config-for [env] (-> (str/join "." [(ns-name *ns*) env]) (symbol) (ns-resolve 'config) (var-get))) |
| 11:38 | sdegutis | Ahh, found a bug in lein-environ :'( |
| 11:39 | sdegutis | Fatal 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:39 | sdegutis | That sucks. |
| 11:39 | sdegutis | I vaguely remember there was some way you could inject code using Leiningen... |
| 11:44 | justin_smith | sdegutis: 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:45 | Sorella | "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:45 | Sorella | if things were late bound. |
| 11:46 | justin_smith | Sorella: clojure does not support circular dependencies without indirection. |
| 11:46 | Sorella | (You can work around that limitation, of course. But it's still a limitation :/) |
| 11:46 | snowell | Anybody 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:46 | justin_smith | it's an intentional choice not to support them, not laziness or lack of creativity |
| 11:46 | Sorella | Oh, I didn't mean to imply Clojure supports recursive deps. |
| 11:46 | justin_smith | I'm saying it doesn't support them due to a choice not to support them. |
| 11:47 | justin_smith | and it's a choice I personally agree with |
| 11:47 | Sorella | justin_smith: that's fine. I was just questioning the choice of word "properly" here :) |
| 11:47 | Sorella | As it implies "circular dependencies" are bad (at least to me) |
| 11:47 | justin_smith | Sorella: yes, and we disagree on that particular value judgment |
| 11:48 | hante_monsta | Does clojure has queue? |
| 11:48 | justin_smith | hante_monsta: yeah, there's a few choices in fact |
| 11:49 | justin_smith | the main one being clojure.lang.persistentqueue/EMPTY |
| 11:49 | hante_monsta | justin_smith: such as? |
| 11:49 | R0B_ROD | Hello all, new to everything... |
| 11:49 | justin_smith | ,(-> clojure.lang.persistentqueue/EMPTY (conj 1)) |
| 11:49 | clojurebot | #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:49 | justin_smith | err... |
| 11:49 | sdegutis | justin_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:50 | justin_smith | ,(-> clojure.lang.PersistentQueue/EMPTY (conj 1)) |
| 11:50 | clojurebot | #object[clojure.lang.PersistentQueue 0x477c7fed "clojure.lang.PersistentQueue@20"] |
| 11:50 | hante_monsta | snowell: Cursive, does not indent well some macros definition |
| 11:50 | justin_smith | ,(-> clojure.lang.PersistentQueue/EMPTY (conj 1) (->> (into [])) |
| 11:50 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 11:50 | justin_smith | ,(-> clojure.lang.PersistentQueue/EMPTY (conj 1) (->> (into []))) |
| 11:50 | clojurebot | [1] |
| 11:50 | justin_smith | hante_monsta: sorry for the many mistakes getting to it, but see above |
| 11:50 | sdegutis | I'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:51 | justin_smith | ,(-> clojure.lang.PersistentQueue/EMPTY (conj 1) (conj 2) (pop) (->> (into []))) |
| 11:51 | clojurebot | [2] |
| 11:51 | hante_monsta | Is there any O complexity table about Clojure's fns? |
| 11:52 | justin_smith | hante_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:52 | hante_monsta | justin_smith: thanks, very appriciaty, I wonder why I ca't find that in the docs (google) for some reason |
| 11:52 | rhg135 | What is the advantage of a persistent queue over a vector? |
| 11:52 | Sorella | hante_monsta: they're usually the same as the mutable counterparts (in amortised time). |
| 11:52 | Sorella | rhg135: queues support O(1) insertion at the end, and O(1) removal at the beginning. |
| 11:52 | philth | hante_monsta: https://www.innoq.com/blog/st/2010/04/clojure-performance-guarantees/ ? |
| 11:52 | frogbyte | Hello there |
| 11:52 | rhg135 | Ah |
| 11:53 | rhg135 | Thanks |
| 11:53 | hante_monsta | Thanks++ |
| 11:53 | Sorella | In clojure it has to touch more than one element, though, but we still consider it constant time. |
| 11:53 | justin_smith | rhg135: that's why I used conj / pop in my example |
| 11:53 | philth | hante_monsta: (inc :thanks) |
| 11:53 | justin_smith | rhg135: to do the fast ops |
| 11:53 | philth | ;) |
| 11:53 | sdegutis | Data composition trumps function composition when available. |
| 11:54 | rhg135 | The ways of failure are strong with this one |
| 11:55 | sdegutis | I'm just thinking about Compojure. |
| 11:55 | frogbyte | I 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:55 | sdegutis | It 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:55 | justin_smith | frogbyte: apply |
| 11:55 | Sorella | sdegutis: 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:55 | justin_smith | frogbyte: (apply clojure.java.shell/sh coll) |
| 11:55 | frogbyte | thanks |
| 11:55 | sdegutis | Whereas building up a data of route handlers is much more inspectable and flexible, and can still be acted on with a given request. |
| 11:56 | hante_monsta | I 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:56 | sdegutis | Sorella: parametric modules? sir you sound like an OCamler not a Haskeller |
| 11:56 | justin_smith | Sorella: have you looked at stuartsierra's component lib? |
| 11:56 | hante_monsta | But my head unzip thinking about it |
| 11:56 | Sorella | Not a sir, but I'm more of a Newspeaker :P |
| 11:56 | Sorella | justin_smith: I haven't. What's that? |
| 11:56 | justin_smith | Sorella: components can be parameterized, and can be re-initialized at runtime with new parameters |
| 11:57 | justin_smith | Sorella: 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:57 | sdegutis | Sorella: never heard of that term |
| 11:57 | sdegutis | From 1984? |
| 11:58 | Sorella | sdegutis: a Smalltalk dialect: http://www.newspeaklanguage.org/. It has first-class parametric modules, and no global namespace. |
| 11:58 | justin_smith | Sorella: 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:58 | sdegutis | Sounds horrifying. |
| 11:59 | justin_smith | Sorella: anyway, complete game-changer in terms of managing stateful resources in clojure, I recommend it very highly |
| 11:59 | Sorella | It 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:59 | Sorella | justin_smith: sounds interesting :D |
| 12:01 | justin_smith | Sorella: 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:01 | rhg135 | You can do runtime redefinition? With component |
| 12:01 | justin_smith | because it made it clear exactly which part of the system was misconfigured or missing a required resource from the OS |
| 12:01 | hante_monsta | justin_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:01 | justin_smith | hante_monsta: yup, it's very nice |
| 12:02 | justin_smith | hante_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:03 | hante_monsta | justin_smith: Schema is really good as well, and compojure api is a game changer too (atleast for me) |
| 12:03 | justin_smith | hante_monsta: which took a bit of wrangling (because at first glance that looks like it needs to be circular...) |
| 12:03 | GivenToCode | im 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:04 | hante_monsta | justin_smith: I used too to make a notification system along with core.async |
| 12:04 | justin_smith | nice |
| 12:04 | hante_monsta | justin_smith: Why haskell doesn't have this, or does? |
| 12:05 | justin_smith | GivenToCode: the trick is on line 175 - the call to -> |
| 12:06 | justin_smith | GivenToCode: -> is a macro that takes the result of each form, and makes it the new first arg to the next form |
| 12:07 | justin_smith | GivenToCode: you can find docs and examples for -> on http://conj.io, and feel free to follow up with more questions |
| 12:07 | snowell | justin_smith: Is it good/better form to wrap function names in parens like that in -> where there are no other args? |
| 12:07 | GivenToCode | justin_smith, so 1 is the first arg to run-queries, and the result of run-queries is the first arg to first? |
| 12:07 | justin_smith | snowell: that's a style argument - I don't usually do it, other people think you should always do it |
| 12:07 | justin_smith | GivenToCode: exactly! |
| 12:08 | justin_smith | GivenToCode: whoever wrote that code really loves the -> macro... |
| 12:08 | GivenToCode | justin_smith, if you were to rewrite it, what idioms would you prefer? |
| 12:09 | justin_smith | GivenToCode: I would make some of those simple nested calls |
| 12:09 | justin_smith | like (response (first (run-queries 1))) |
| 12:09 | justin_smith | which compiles to be the same thing as the -> version |
| 12:09 | clojurebot | No entiendo |
| 12:12 | rhg135 | What is wrong with -> |
| 12:13 | justin_smith | rhg135: it's not wrong, I find it a little silly when you are only nesting 3 calls though |
| 12:13 | justin_smith | especially three calls where there is only 1 arg to each step |
| 12:13 | justin_smith | rhg135: but it's a style choice I guess |
| 12:13 | rhg135 | Some people are allergic to parens though |
| 12:14 | akabander | Allergies can be overcome with enough exposure |
| 12:14 | rhg135 | Yeah |
| 12:15 | akabander | I get annoyed when people use "->" as a reason why Clojure "isn't so bad" |
| 12:15 | akabander | They're operating from false assumptions (that parens are bad). |
| 12:15 | rhg135 | That is a dumb reason |
| 12:15 | justin_smith | (inc ((()))) |
| 12:15 | justin_smith | lazybot: hello |
| 12:16 | justin_smith | (inc parens) |
| 12:16 | lazybot | ⇒ 1 |
| 12:16 | akabander | But you see it in intro to clojure pieces all the time. "Don't like parens? Look you can use -> instead!" |
| 12:16 | Bronsa | (inc (((() |
| 12:16 | lazybot | ⇒ 1 |
| 12:16 | justin_smith | Bronsa: so weird |
| 12:17 | Bronsa | I might be to blame for that :E |
| 12:17 | rhg135 | Semantics over syntax forever |
| 12:18 | justin_smith | ,(compare "semantics" "syntax") |
| 12:18 | clojurebot | -20 |
| 12:18 | justin_smith | it seems the jvm disagrees, sorry |
| 12:18 | hante_monsta | "you don't know nothing jvm" |
| 12:19 | Bronsa | ,(compare "a" "c") |
| 12:19 | clojurebot | -2 |
| 12:19 | Bronsa | ,(compare "a" "d") |
| 12:19 | rhg135 | As do all the jvm coders who like java |
| 12:19 | clojurebot | -3 |
| 12:19 | Bronsa | uh |
| 12:19 | hante_monsta | rhg135: was just a joke, just a joke. |
| 12:21 | ainz | clojure or haskel better? |
| 12:22 | ainz | about performance. |
| 12:22 | snowell | ainz: I assume you will only get a biased opinion in a clojure chat :) |
| 12:22 | snowell | And it probably depends on what you value more |
| 12:22 | rhg135 | hante_monsta: I just refered to the people who claim syntax makes a language unusable, not a reply |
| 12:22 | ainz | :) |
| 12:22 | ainz | thank sir |
| 12:22 | Sorella | ainz: performance in what context? |
| 12:22 | justin_smith | haskell will calculate answers faster, with clojure you'll get correct code sooner (and most of us will claim it is more fun too) |
| 12:23 | ainz | thanks |
| 12:23 | hante_monsta | rhg135: I doesn't make it unsable, but it make me not want to use it |
| 12:23 | Sorella | They'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:23 | rhg135 | That I can agree with |
| 12:25 | Sorella | akabander: I'm particularly not a fan of the prefix syntax used by Clojure, although paredit makes a very good use of it. |
| 12:25 | hante_monsta | Sorella: On the counterpart some people in Java are interested in raw performance without the use of RAII |
| 12:26 | Sorella | I'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:27 | Sorella | hante_monsta: which is... weird, given that Java isn't particularly that great at raw performance either. |
| 12:29 | justin_smith | Sorella: it's in a special niche when you combine performance and portability as criteria though |
| 12:32 | Sorella | That's likely true. Makes me wonder if Rust might replace it in that area though, eventually. |
| 12:32 | justin_smith | it 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:32 | hante_monsta | Sorella: People still love their C++, and don't want to change. |
| 12:34 | ralph___ | 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:36 | Sorella | ralph___: (flatten [a [b [c] d]]) => [a b c d] |
| 12:36 | ralph___ | Sorella: But I want them out of the collection, not flattened. |
| 12:36 | ralph___ | Sorella: However, thanks. |
| 12:36 | Sorella | ralph___: out of the collection...? |
| 12:36 | rhg135 | Apply? |
| 12:37 | ralph___ | rhg135: But what function to apply? |
| 12:37 | Bronsa | ralph___: you can't do that, functions can only return one value |
| 12:37 | Bronsa | ralph___: do you need this while writing a macro? |
| 12:37 | ralph___ | Bronsa: OK and yes. |
| 12:37 | Bronsa | ,`(foo ~'(bar baz )) |
| 12:37 | Sorella | ralph___: ,@the-collection will expand the collection |
| 12:37 | rhg135 | Ah, nvm then |
| 12:37 | clojurebot | (sandbox/foo (bar baz)) |
| 12:37 | Bronsa | ,`(foo ~'@(bar baz )) |
| 12:37 | clojurebot | (sandbox/foo (clojure.core/deref (bar baz))) |
| 12:38 | Bronsa | ,`(foo ~@'(bar baz )) ;;err |
| 12:38 | clojurebot | (sandbox/foo bar baz) |
| 12:38 | Sorella | Oh, I'm mixing Lisps, apparently |
| 12:38 | Bronsa | Sorella: yeah ,@ is CL, ~@ is clj |
| 12:39 | ralph___ | Bronsa, Sorella: Aha, yes, that seems like the ticket. Thanks! |
| 12:39 | Bronsa | ralph___: note that ~@ works only inside a ` context and only inside a collection. You still can't splice things into the top-level |
| 12:40 | ralph___ | Bronsa: I think that should be OK. It doesn't have to be top-level, just within the current scope. |
| 12:42 | justin_smith | Sorella: about flatten |
| 12:42 | justin_smith | ~flatten |
| 12:42 | clojurebot | flatten 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:42 | justin_smith | also ##(flatten "hello") |
| 12:42 | lazybot | ⇒ () |
| 12:42 | justin_smith | ,(flatten {:a 0}) |
| 12:42 | clojurebot | () |
| 12:43 | Bronsa | ,(flatten 1) |
| 12:43 | clojurebot | () |
| 12:44 | justin_smith | ,(flatten #{1 2 3 :set :go}) |
| 12:44 | clojurebot | () |
| 12:44 | phillord | I've used flatten some of the time |
| 12:45 | justin_smith | phillord: well it does say "rarely" and not "never" the right answer |
| 12:45 | justin_smith | phillord: but it's good to remember its many pitfalls |
| 12:45 | phillord | I needed it for "user interface" reasons. |
| 12:46 | justin_smith | phillord: oh man that reminds me I am supposed to be helping with some frontend stuff today and I already feel dirty |
| 12:47 | phillord | consider a function like "and" but which works either on lists or arguments |
| 12:48 | phillord | so (and a b c) or (and [a b c]) should return true iff a, b and c |
| 12:48 | phillord | but also (and a [b c]) or (and a [b [c]]) |
| 12:49 | phillord | well, that's what I used it for, good or bad |
| 12:49 | justin_smith | phillord: it's a truisim in systems science that weird messy shit happens on system boundaries |
| 12:49 | justin_smith | one of those boundaries of course is app / user |
| 12:49 | phillord | that's a good aphorism |
| 12:49 | justin_smith | see also biodiversity where two ecosystems meet - this isn't always a bad thing |
| 12:50 | phillord | given that my library is entirely a system boundary I think that gives me a good excuse! |
| 12:50 | justin_smith | haha |
| 12:50 | justin_smith | sure |
| 12:51 | phillord | actually, 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:15 | doritostains | lein.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:17 | justin_smith | lein definitely generates huge command lines... |
| 13:20 | amalloy | $google windows xargs |
| 13:20 | lazybot | [linux - Windows equivalent to xargs? - Super User] http://superuser.com/questions/652492/windows-equivalent-to-xargs |
| 13:21 | jorr | If 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:21 | jorr | I 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:22 | mindbender1 | Does anyone have a working systemd script for datomic? |
| 13:22 | justin_smith | jorr: 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:24 | justin_smith | eg. if ./resources/ is in :resource-paths then I can access ./resources/public/app.js via (io/resource "public/app.js") |
| 13:24 | jorr | justin_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:24 | justin_smith | yes, that is how it should work |
| 13:24 | jorr | justin_smith: Hmm, okay thanks, I'm sure it'll work with some more fiddling then. |
| 13:25 | justin_smith | of course io/resource either returns nil or a input source which you would then hand to slurp or with-open or whatever |
| 13:26 | amalloy | i 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:27 | justin_smith | amalloy: maybe it's a classic flandersization problem |
| 13:27 | amalloy | $google flandersization |
| 13:27 | lazybot | [Flanderization - TV Tropes] http://tvtropes.org/pmwiki/pmwiki.php/Main/Flanderization |
| 13:27 | wvxvw | hi there. Newbie question. Why is my REPL not finding any dependencies / is unable to require anything but the Java / Clojure own libraries? |
| 13:27 | hiredman | well, vars are just a way to have you routes update when you recompile ring routes |
| 13:28 | justin_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:28 | jorr | justin_smith: aah that was it, thanks so much. |
| 13:28 | justin_smith | jorr: np |
| 13:28 | wvxvw | I have a ~/.lein/profiles.clj with pomegranate, and I'm sure it's on my HD, but REPL cannot load it. |
| 13:29 | justin_smith | wvxvw: how do you go about requiring it? |
| 13:29 | amalloy | there are a million "xargs.bat" files that are like "FOR file in %*; %1 %file" |
| 13:29 | wvxvw | (require '[cemerick.pomegranate :as p]) |
| 13:29 | wvxvw | => FileNotFoundException Could not locate cemerick/pomegranate... |
| 13:29 | justin_smith | wvxvw: it could be your profiles.clj is malformed, can you share a paste of it? |
| 13:30 | wvxvw | justin_smith: it's really simple, here it is: |
| 13:30 | justin_smith | no multi line pastes please |
| 13:30 | wvxvw | {:user {:plugins [[cider/cider-nrepl "0.8.2"] [lein-exec "0.3.1"] [com.cemerick/pomegranate "0.3.0"]]}} |
| 13:30 | wvxvw | |
| 13:30 | justin_smith | pomegranate is not a plugin |
| 13:30 | wvxvw | well... that's almost one :) |
| 13:30 | justin_smith | you need it under :dependencies |
| 13:30 | wvxvw | ah... |
| 13:30 | wvxvw | let me try that |
| 13:31 | wvxvw | are other plugins and why the difference? |
| 13:31 | justin_smith | wvxvw: plugins are things added to lein's classpath while loading up your project and preparing to run it |
| 13:31 | justin_smith | they can do special things, up to and including adding things to your app's classpath |
| 13:32 | wvxvw | yes, that's what I'd like to happen |
| 13:32 | justin_smith | wvxvw: 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:32 | wvxvw | I mean, why would other things not be able to do that? |
| 13:32 | justin_smith | wvxvw: the plugin route for adding an app dep is the weird roundabout way, dependencies are the direct simple way |
| 13:33 | wvxvw | justin_smith, I really fail to see the difference. |
| 13:33 | justin_smith | wvxvw: lein is a tool that builds your classpath |
| 13:33 | justin_smith | wvxvw: a plugin can manipulate the way lein does that through arbitrary code, if it chooses to |
| 13:33 | wvxvw | I think that classpath is a... not very smart concept... why would it even use that? |
| 13:34 | justin_smith | wvxvw: a dependency is much simpler - it is directly added to your app's class path, with no other special gimmicks or tricks |
| 13:34 | justin_smith | wvxvw: the classpath is why you can use 8 different versions of clojure in 8 different projects and not worry about this breaking anything |
| 13:35 | wvxvw | Not really no... :) Sorry, Python can do away pretty well without such things. CL too, just to name some other language. |
| 13:35 | justin_smith | wvxvw: and they internally have something much like the classpath for setting your visible packages |
| 13:36 | wvxvw | But you don't need a ton of setup in random places to do that. You can do it all from the interactive session. |
| 13:36 | justin_smith | or else you can break app b by changing a dep in app a (which is the common case) |
| 13:37 | justin_smith | wvxvw: 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:39 | wvxvw | well, 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:39 | justin_smith | wvxvw: I never had any luck having multiple versions of a single CL lib available at once |
| 13:39 | wvxvw | I run it in exactly this very moment :) |
| 13:40 | wvxvw | Maxima can't load together with quicklisp, so I run Maxima separately from the SLIME I work with |
| 13:40 | wvxvw | Sorry, back to where we started |
| 13:40 | phillord | wvxvw: 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:40 | wvxvw | (require '[cemerick.pomegranate :as p]) still errors |
| 13:41 | justin_smith | wvxvw: can you paste your new profiles.clj? |
| 13:41 | wvxvw | But I _don't have to_ use a virtual environment. |
| 13:41 | wvxvw | {:user {:plugins [[cider/cider-nrepl "0.8.2"] [lein-exec "0.3.1"]] :dependencies [[com.cemerick/pomegranate "0.3.0"]]}} |
| 13:41 | wvxvw | here |
| 13:42 | justin_smith | that should be working... |
| 13:42 | wvxvw | nope, the same exact error |
| 13:43 | wvxvw | FileNotFoundException Could not locate cemerick/pomegranate__init.class or cemerick/pomegranate.clj on classpath. clojure.lang.RT.load (RT.java:449) |
| 13:43 | wvxvw | here's the full text |
| 13:45 | justin_smith | wvxvw: 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:45 | justin_smith | wvxvw: have you restarted the repl since changing profiles.clj? |
| 13:45 | wvxvw | justin_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:46 | justin_smith | wvxvw: 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:46 | amalloy | wvxvw: no, there aren't. the only hidden variable is what you are typing that's causing that error |
| 13:46 | justin_smith | lein is installed locally by and for my user, and has no system level config |
| 13:46 | justin_smith | s/no other visible/no other available |
| 13:47 | wvxvw | you never know... what about $JAVA_... stuff? Can this influence it? Maybe $CLASSPATH, $MAVEN_... stuff? |
| 13:47 | justin_smith | if you changed the $MAVEN stuff that could provoke a not-found type error, or force re-download of artifacts |
| 13:48 | justin_smith | it would not simply make a dep unavailable from the repl |
| 13:48 | justin_smith | it would fail |
| 13:48 | wvxvw | can you locate the jar with pomegranate? So that I could check I have it too? |
| 13:48 | wvxvw | No, I never changed it by hand, but, again, you never know, different system, different package manager etc. |
| 13:49 | justin_smith | wvxvw: it is in ~/.m2/repository/com/cemerick/pomegranate/0.3.0/ |
| 13:49 | wvxvw | Because, apparently, it does make a dependency unavailable from repl. |
| 13:49 | amalloy | wvxvw: 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:49 | justin_smith | wvxvw: lein is the package manager |
| 13:49 | wvxvw | it's not really a package manager, since it cannot install or search for packages... it's 0.33% package manager :D |
| 13:50 | justin_smith | wvxvw: it does both, and those are its primary jobs |
| 13:50 | wvxvw | well, it kinda fails at that big time :) |
| 13:50 | wvxvw | yes, I do have that jar at exactly the same location |
| 13:50 | justin_smith | wvxvw: 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:51 | wvxvw | it is installed today, about an hour ago |
| 13:51 | oddcully | there is the plz plugin for lein to make it search and add deps |
| 13:51 | wvxvw | what I'm doing with it: |
| 13:51 | amalloy | i 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:51 | wvxvw | $ lein repl |
| 13:51 | justin_smith | OK after changing your ~/.lein/profiles.clj a fresh lein repl should be able to load pomegranate |
| 13:51 | wvxvw | then: |
| 13:51 | wvxvw | (require '[cemerick.pomegranate :as p]) |
| 13:51 | wvxvw | nothing more |
| 13:52 | amalloy | and you have done this anew since changing your profiles |
| 13:52 | wvxvw | also, is there probably some way to make it start faster? Just in case... |
| 13:53 | justin_smith | ~faster |
| 13:53 | clojurebot | faster is https://github.com/technomancy/leiningen/wiki/Faster |
| 13:53 | justin_smith | wvxvw: ^ see link |
| 13:53 | wvxvw | thanks, will do |
| 13:55 | wvxvw | ok, 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:55 | wvxvw | go figure |
| 13:56 | wvxvw | Thank you justin_smith, I guess :) |
| 13:57 | amalloy | (inc justin_smith) |
| 13:57 | lazybot | ⇒ 291 |
| 14:04 | justin_smith | wvxvw: 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:06 | wvxvw | justin_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:06 | wvxvw | s/asd fily/asd file/ |
| 14:07 | justin_smith | wvxvw: so if my dep tree contains 100 deps going recursively, I make 100 symlinks if I want to ensure reproducable behavior? |
| 14:08 | wvxvw | in that case I'd have modified the global registry (the asdf configuration file) and have copies of it loaded on per project basis |
| 14:08 | justin_smith | also, 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:09 | wvxvw | but 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:09 | justin_smith | wvxvw: using clojure I use large numbers of very small libs |
| 14:10 | justin_smith | my 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:10 | wvxvw | then 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:10 | justin_smith | we don't have or need virtual environments with clojure |
| 14:11 | wvxvw | instead you have an extremely convoluted and uncomfortable way of importing libraries? |
| 14:11 | justin_smith | usually - I guess some people use them to bundle non-clojure services along with the jar in one place I guess |
| 14:11 | justin_smith | wvxvw: once you accept some simple premises it's neither, but I do understand there's no accounting for taste |
| 14:12 | wvxvw | this 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:12 | justin_smith | wvxvw: 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:13 | justin_smith | wvxvw: I know what those programs are, and have found them less reliable than lein |
| 14:13 | wvxvw | lein 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:13 | justin_smith | wvxvw: it does both! |
| 14:13 | justin_smith | it installs to a local cache |
| 14:13 | wvxvw | but no, it doesn't! |
| 14:13 | justin_smith | it searches with "lein search" |
| 14:13 | wvxvw | there's no such command line option |
| 14:13 | justin_smith | ? |
| 14:13 | wvxvw | install Install the current project to the local repository. |
| 14:14 | justin_smith | I just ran "lein search pomegranate" |
| 14:14 | wvxvw | this isn't installing a library, this is finding the dependency for the project |
| 14:14 | justin_smith | wvxvw: that is what "lein deps" does |
| 14:14 | rhg135 | It does install |
| 14:14 | rhg135 | To your local repo |
| 14:14 | wvxvw | but the help says otherwise, whome should I trust? |
| 14:15 | rhg135 | It says that too |
| 14:15 | wvxvw | I want to install globally... local is a bonus, but most of the time this isn't what I want... |
| 14:16 | justin_smith | wvxvw: 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:16 | rhg135 | You could use plain jvm if you dislike lein |
| 14:16 | justin_smith | I think ant does global installs |
| 14:16 | justin_smith | right |
| 14:17 | wvxvw | well, I don't really care about what is considered normal :) practical for me outweights what others consider normal |
| 14:18 | wvxvw | and 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:18 | justin_smith | I think you'll find not using lein in the clojure ecosystem is a lot more work than using lein is |
| 14:18 | rhg135 | What would a global install do for you? |
| 14:19 | rhg135 | Using python was painful here |
| 14:19 | wvxvw | I'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:19 | wvxvw | Well, it wasn't painful for me. |
| 14:20 | rhg135 | Lucky |
| 14:20 | wvxvw | Global install in details |
| 14:20 | wvxvw | well, you see, java, for instance, has a way to make a global install on Linux. |
| 14:20 | wvxvw | there's a whole packaging system in place etc. |
| 14:21 | wvxvw | Too bad most Java programmers don't know about it... |
| 14:21 | rhg135 | Maven... |
| 14:21 | wvxvw | so you end up having multiple copies of the same jars over and over in many places |
| 14:21 | justin_smith | wvxvw: no, it uses one cache, you might have multiple versions, but only one copy of each version |
| 14:22 | wvxvw | Maven 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:22 | justin_smith | wvxvw: 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:22 | wvxvw | Also, Linux way of installing java is independent of Maven, so... |
| 14:22 | justin_smith | wvxvw: and, given the same project.clj, I can come back 10 years later and use the same versions of everything |
| 14:23 | justin_smith | I wish Linux package managers were as reliable about versions and isolation as lein is, I guess nix comes close |
| 14:23 | wvxvw | That'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:23 | justin_smith | wvxvw: I come back to projects years later, it works like that |
| 14:24 | justin_smith | wvxvw: because package version deploys are effectively immutable |
| 14:24 | wvxvw | you 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:24 | justin_smith | wvxvw: this is why we accept the weird parts of lein (including no global installs, needing a project.clj for everything...) - the increased repeatability |
| 14:25 | wvxvw | What if I don't care about it? |
| 14:25 | justin_smith | then don't use lein |
| 14:25 | wvxvw | but there's no alternative... except for lots of manual labor... |
| 14:25 | rhg135 | Boot is nice |
| 14:26 | rhg135 | Not as nice as lein, but yeah |
| 14:26 | wvxvw | will it locate and install libraries available in some centralized repository into a global repository? |
| 14:26 | wvxvw | (on the machine I'm working on that is) |
| 14:26 | rhg135 | Yes |
| 14:26 | justin_smith | rhg135: that's not true, it uses a classpath to manage versions via the maven schema |
| 14:26 | justin_smith | it's not what he wants |
| 14:27 | justin_smith | he wants unversioned global installs |
| 14:27 | rhg135 | Set you're maven repo to be global |
| 14:27 | rhg135 | Like /m2 |
| 14:27 | rhg135 | Oh |
| 14:27 | justin_smith | rhg135: by global he means no version qualification |
| 14:27 | wvxvw | that's not true |
| 14:27 | justin_smith | bbl, lunch |
| 14:27 | rhg135 | Unversioned, blasphemy |
| 14:28 | wvxvw | by global I mean the same thing as Java packages are installed on Linux |
| 14:28 | wvxvw | no Maven |
| 14:28 | wvxvw | just rpm / deb |
| 14:28 | wvxvw | it's much faster, easier to manage and more secure |
| 14:28 | rhg135 | No such global repo exists |
| 14:29 | wvxvw | well... that's one of the problems :) |
| 14:29 | rhg135 | I know only of maven |
| 14:29 | wvxvw | (to make it fair, for example, there isn't one such repo for CL either) |
| 14:29 | rhg135 | It works great though |
| 14:29 | wvxvw | which is unfortunate and sad, but that's how it is. |
| 14:29 | wvxvw | well, that probably depends on what you want it to do :) |
| 14:31 | rhg135 | You specify your deps, if they're in your local repo, uses that, else, downloads it |
| 14:32 | wvxvw | well, this is bad, and I'll tell you why |
| 14:32 | wvxvw | It seems ok as long as you are the user of your program |
| 14:32 | wvxvw | but 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:33 | rhg135 | They are |
| 14:33 | wvxvw | I mean, you don't want the Windows-style installs, where all DLLs come with the program |
| 14:33 | wvxvw | no, they aren't, and that's the problem |
| 14:33 | rhg135 | They aren't |
| 14:33 | wvxvw | you don't want your users to install lein |
| 14:33 | wvxvw | neither maven etc. |
| 14:33 | rhg135 | They don't |
| 14:33 | wvxvw | then how will they get their libraries? |
| 14:34 | rhg135 | You can use plain java |
| 14:34 | wvxvw | hahaha |
| 14:34 | wvxvw | lol |
| 14:34 | wvxvw | seriously, and how that solves the problem? |
| 14:34 | rhg135 | Download them manually |
| 14:34 | rhg135 | Or via rpm etc |
| 14:34 | wvxvw | seriously? come on. You will distribute your program with a readme which says users need to download stuff from the internet? |
| 14:35 | wvxvw | In what universe? :) |
| 14:35 | tatut | in reality, I think most will just ship a uberjar with everything, wvxvw seems to want something different |
| 14:35 | rhg135 | Try running a python app with deps without setuptools |
| 14:35 | rhg135 | That's fun |
| 14:36 | wvxvw | you 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:36 | danlentz_ | why not? |
| 14:36 | danlentz_ | lots of people seem to be distributing CL libraries |
| 14:37 | wvxvw | rhg135, 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:37 | wvxvw | but, most importantly, you don't do it in python. |
| 14:37 | wvxvw | you do it using rpm / dep and such |
| 14:37 | wvxvw | and this is where the real problem is. You need global install |
| 14:38 | rhg135 | Isn't there a non standard setup lib some use |
| 14:38 | rhg135 | I meant that |
| 14:38 | wvxvw | there's pip, but what I'm getting at is distributing the program, not the library for other programmers |
| 14:39 | wvxvw | this is the three staged process: programmer writes the program, package maintainer packages it and the user installs it and uses. |
| 14:39 | danlentz_ | wvxvw: cl offers quicklisp (quicklisp.org) with a facility called a "dist" |
| 14:39 | wvxvw | In case of CL, it's broken at package maintainer - you simply cannot package your program so that a user could just install it... |
| 14:40 | rhg135 | I need pygame vY. My distro only has vX. Oh dear |
| 14:40 | danlentz_ | wvxvw: huh? |
| 14:40 | danlentz_ | nonsense |
| 14:40 | wvxvw | yes, there are limitations on what is packaged / available, but at least in pricniple it's possible |
| 14:40 | wvxvw | with Clojure / CL doesn't seem to be possible |
| 14:41 | danlentz_ | ok, sorry i joined in |
| 14:41 | wvxvw | danlentz_ well. The only CL program distributed on Fedora is Maxima |
| 14:41 | danlentz_ | well, fedora is not a cl distribution mechanism, is it? |
| 14:42 | wvxvw | I 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:42 | danlentz_ | Waaa. I cant download Ubuntu from the Mac app store |
| 14:42 | danlentz_ | yeah |
| 14:42 | danlentz_ | well, look at ASDF |
| 14:42 | danlentz_ | and quicklisp |
| 14:42 | wvxvw | Fedora is a distribution of programs, and that's what I'm talking about |
| 14:43 | wvxvw | Look, I probably know about quicklisp and ASDF than you do... and that's why I'm saying this in the first place... |
| 14:43 | wvxvw | they are not tools for installing programs. |
| 14:43 | wvxvw | they are for programmers, not the users |
| 14:44 | wvxvw | To give you more specifics: I wrote a library in CL, bindings for link-grammar C++ library. |
| 14:45 | wvxvw | Now, I wanted to package it for Fedora so that someone who wants to use the library could install it with dnf / yum |
| 14:45 | wvxvw | There is no way at the moment to do that. |
| 14:45 | wvxvw | The infrastructure that existed once is long gone |
| 14:45 | wvxvw | New isn't there yet. |
| 14:45 | danlentz_ | ok, apologies for basking in the ignorance that makes me think im using it effectively |
| 14:46 | wvxvw | this is not it. I'm talking about different process / different purpose |
| 14:46 | wvxvw | distributing programs =/= resolving dependencies |
| 14:47 | danlentz_ | a quicklisp dist can package and distribute software |
| 14:47 | wvxvw | :0 |
| 14:47 | danlentz_ | and ASDF system can build and install libraries |
| 14:47 | wvxvw | no... |
| 14:48 | danlentz_ | and both are arbitrarily extensible platforms |
| 14:48 | wvxvw | We are talking about integration with package managers, does it explain it better? |
| 14:48 | danlentz_ | i see |
| 14:48 | wvxvw | Can quicklisp produce a package installabe on Android? |
| 14:49 | wvxvw | it can produce a program, something you can drop on your computer and run - that's true |
| 14:49 | danlentz_ | i'm using clojure to install an app that can package and run on iOS |
| 14:49 | danlentz_ | clojurescript rather |
| 14:49 | wvxvw | but packaging for a package manager is an entirely different process |
| 14:50 | danlentz_ | i see, though. But you are limiting "package manager" to mean yum or apt |
| 14:50 | wvxvw | alright, sorry, I must go, duty calls. |
| 14:50 | wvxvw | I just mentioned Android (that'd be GooglePlay, or w/e it's called) |
| 14:50 | wvxvw | anyhow, sorry, I must be bowing out. Nice talking to you guys :) |
| 15:25 | hanate_monsta | Would people (this community) bash on me if solve problems in imperative way in Clojure? :) |
| 15:26 | snowell | Bashing doesn't help anyone! |
| 15:26 | {blake} | We're not really bashers here. |
| 15:26 | snowell | But 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:27 | hanate_monsta | I wanna do the opposite. |
| 15:27 | {blake} | We might say we're disappointed in you. =P |
| 15:27 | snowell | lolwut |
| 15:27 | hanate_monsta | YES! |
| 15:27 | {blake} | But I'd be open to hearing why you wanted to do so. |
| 15:27 | hanate_monsta | Games! |
| 15:29 | hanate_monsta | Could 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:29 | hanate_monsta | LIARS! |
| 15:31 | {blake} | Entity Component Systems? |
| 15:31 | hanate_monsta | Garbage! |
| 15:32 | {blake} | Socrates, Plato, Aristotle? Morons! |
| 15:32 | hanate_monsta | I 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:41 | clojurebot | #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:42 | justin_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:56 | justin_smith | {blake}: it's just a vector doing nothing |
| 16:57 | justin_smith | ,((fn [] [1 2 3] :OK)) |
| 16:57 | clojurebot | :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:13 | justin_smith | {blake}: no, with require you do |
| 17:13 | oddcully | note the difference between (:require) in ns and (require) |
| 17:14 | {blake} | When used directly, yeah, but in the :require clause you don't. |
| 17:14 | justin_smith | {blake}: the difference is that () is being used for the prefix form of require there |
| 17:14 | justin_smith | {blake}: neither requires (or even allows) a quote in the :require form |
| 17:14 | {blake} | Oh. |
| 17:14 | justin_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:14 | justin_smith | and 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:16 | justin_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:16 | justin_smith | that's the prefix thing that the () example is using above |
| 17:16 | justin_smith | and 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:18 | justin_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:18 | justin_smith | which 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:19 | justin_smith | OK |
| 17:20 | justin_smith | {blake}: does't require it, but that's the idiom |
| 17:20 | {blake} | Right. Fair enough. |
| 18:17 | oneness | anyone out there tinkered with adding pre and post to defmulti? |
| 18:22 | justin_smith | oneness: you mean like a pre-condition on the dispatch function? because there is nothing else on the defmulti level itself |
| 18:22 | justin_smith | or do you mean on one of your defmethods - either should work |
| 18:25 | oneness | I mean to add pre and post contract to the defmulti so all defined methods automatically abide by it. |
| 18:26 | oneness | looked at a bit to defmulti and looks like it does not support :pre and :post. |
| 18:35 | amalloy | oneness: just define an ordinary function that delegates to your multimethod |
| 18:35 | amalloy | (and put the conditions on that, of course) |
| 18:38 | hiredman | or put them on the dispatch function, or each defmethod, or... |
| 19:16 | justin_smith | $mail oneness I just created a multimethod dispatch function with :pre conditions and it absolutely works |
| 19:16 | lazybot | Message saved. |
| 19:16 | justin_smith | ,(defmulti foo (fn [& args] {:pre [(even? (count args))]} (first args))) |
| 19:16 | clojurebot | #'sandbox/foo |
| 19:17 | justin_smith | ,(defmethod foo :default [& _] :OK) |
| 19:17 | clojurebot | #object[clojure.lang.MultiFn 0x6f992b1 "clojure.lang.MultiFn@6f992b1"] |
| 19:17 | justin_smith | ,(foo :a :b) |
| 19:17 | clojurebot | :OK |
| 19:17 | justin_smith | ,(foo :a :b :c) |
| 19:17 | clojurebot | #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:17 | justin_smith | ,(foo :a :b :c :d) |
| 19:17 | clojurebot | :OK |
| 21:08 | AWizzArd | There 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:09 | AWizzArd | Java 8. |
| 21:09 | justin_smith | AWizzArd: you can make a java.util.function.Function that delegates to your fn |
| 21:09 | justin_smith | fn does not implement java.util.function.Function, and from what I hear never will |
| 21:10 | justin_smith | function.Function has a constructor that take a callable right? |
| 21:10 | AWizzArd | Oho, why not implement it? |
| 21:10 | AWizzArd | Function is an interface. |
| 21:10 | justin_smith | oh right |
| 21:10 | justin_smith | so you could use reify |
| 21:10 | AWizzArd | I see it has some apply method that I can implement. |
| 21:11 | AWizzArd | But 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:11 | justin_smith | reify isn't so hard to use |
| 21:12 | amalloy | AWizzArd: reify is what makes it easy |
| 21:12 | amalloy | there can't be any tighter integration, because clojure isn't going to require java 8 anytime soon |
| 21:12 | amalloy | so it can't have a Function implementation built in |
| 21:14 | AWizzArd | amalloy: yes okay, depending on J8 is maybe too early, but I was thinking of the “never will” that justin_smith mentioned. |
| 21:15 | AWizzArd | amalloy: with the conditional compilation reader macros, couldn’t there be two compilation targets, of which J8 is one? |
| 21:16 | amalloy | do you have a conditional compilation reader macro that works for java, in which IFn and AFn and all that are defined? |
| 21:22 | AWizzArd | amalloy: two branches then. All patches are done on the current/classical brand and simply get merged into the J8 one. |
| 21:24 | amalloy | feel free to propose this on clojure-dev. i predict it will not go far |
| 21:24 | AWizzArd | amalloy: 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:24 | amalloy | i 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:28 | AWizzArd | Perhaps future versions of Java will add interesting features that would increase the motivation to use them |
| 21:51 | camm_v222 | Hi, I'm new at Clojure. Perhaps you know a web site, book, or video tutorials where I can learn about it? |
| 21:52 | namra | camm_v222: http://www.braveclojure.com/ |
| 21:52 | namra | camm_v222: another one -> https://aphyr.com/posts/301-clojure-from-the-ground-up-welcome |
| 21:53 | namra | http://shop.oreilly.com/product/0636920034292.do |
| 21:54 | camm_v222 | Thanks namra, I really appreaciate it. |
| 21:55 | namra | there are other well know clojure books, but unfortunately forgot their names :/ |
| 21:56 | namra | camm_v222: http://clojure.org/books?responseToken=a59c3eac653721eb2b49c7b99f5aa5d6 --- there you go |
| 21:56 | namra | many 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:19 | talios | if there an (if-let) variant that accepts multiple binding forms at all? Can't seem to spot one.. |
| 22:19 | talios | s/if/is/ |
| 22:19 | gfredericks | talios: not in clojure or contribs I don't think |
| 22:20 | justin_smith | nope |
| 22:20 | gfredericks | there's been a bunch of discussions about that |
| 22:20 | justin_smith | there have been various proposals but no unanimity of how it would work |
| 22:20 | gfredericks | I am pretty happy with prismatic/fnhouse |
| 22:21 | talios | doh, 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:56 | nxqd | hi 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:57 | gfredericks | nxqd: what do you want that to evaluate to? |
| 22:58 | nxqd | I just found contain? I think it's what I need. |
| 22:58 | nxqd | thanks for helping :) |
| 22:58 | gfredericks | np |
| 23:28 | sdegutis | How can I profile all the time `lein run` is taking before -main is actually called? |
| 23:39 | gfredericks | time lein run -m clojure.main -e '(println (quote hello))' |
| 23:40 | gfredericks | though that probably won't require your code |
| 23:40 | gfredericks | so you'll want to add a require in there too |
| 23:40 | gfredericks | doing both will tell you how much time is lein & clojure and how much time is compiling your code |
| 23:41 | sdegutis | gfredericks: it's definitely a good start though for a baseline |
| 23:42 | ddellacosta | nxqd: 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:42 | ddellacosta | &(get {:foo "foo"} :bar "bar") |
| 23:42 | lazybot | ⇒ "bar" |
| 23:43 | neoncontrails | What's the most idiomatic way in Clojure to keep iterating a lazy-seq until the values are no longer changing? |
| 23:43 | sdegutis | WHOA |
| 23:44 | sdegutis | (require 'my.main.namespace) takes 6673.242276 msecs |
| 23:44 | gfredericks | sdegutis: if you find the clojure jar in your ~/.m2 you can also run that with `time java -jar clojure.jar -e '(println :hello)'` |
| 23:44 | neoncontrails | ,(take 10 (iterate (fn [x] (Math/cos x)) 1)) |
| 23:44 | clojurebot | (1 0.5403023058681398 0.8575532158463934 0.6542897904977791 0.7934803587425656 ...) |
| 23:44 | sdegutis | Is it normal that it should take 6 seconds to require all my project's namespaces? |
| 23:45 | gfredericks | sdegutis: not too surprising |
| 23:46 | gfredericks | sdegutis: it probably includes loading all your libraries too |
| 23:46 | sdegutis | :( |
| 23:46 | sdegutis | Right. |
| 23:46 | neoncontrails | Take <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:47 | gfredericks | neoncontrails: you want to detect when you get the same value twice in a row? |
| 23:48 | amalloy | neoncontrails: you want to wait until cos(x)~=x? for what values of x is that true |
| 23:48 | sdegutis | gfredericks: but is it reasonable for just loading a bunch of libs to take that long? |
| 23:48 | sdegutis | I mean all they should be doing is a bunch of (def) and (defn) right? |
| 23:48 | gfredericks | amalloy: something between 0 and pi I think |
| 23:48 | gfredericks | sdegutis: well it's compiling all of that code to classes |
| 23:48 | amalloy | between 0 and pi/4 even, i would think |
| 23:49 | gfredericks | sdegutis: I think ztellman had one weird trick to speed it up that might not be incorporated yet |
| 23:49 | neoncontrails | amalloy: How did I not see that before. Thank you! |
| 23:49 | sdegutis | gfredericks: oooo |
| 23:49 | amalloy | how did what i said helped? |
| 23:51 | neoncontrails | I 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:51 | amalloy | i didn't offer a solution |
| 23:52 | amalloy | not one i recognized, anyway |
| 23:53 | gfredericks | ,(->> (iterate #(Math/cos %) 1) (partition 2 1) (remove (fn [[a b]] (not= a b))) (ffirst)) |
| 23:53 | clojurebot | 0.7390851332151607 |
| 23:53 | gfredericks | ,(Math/cos 0.7390851332151607) |
| 23:53 | clojurebot | 0.7390851332151607 |
| 23:53 | neoncontrails | You asked the question in just the right way I suppose :) |
| 23:53 | neoncontrails | ,(take-while (fn [x] (not (= x (Math/cos x)))) (iterate (fn [x] (Math/cos x)) 1)) |
| 23:53 | clojurebot | (1 0.5403023058681398 0.8575532158463934 0.6542897904977791 0.7934803587425656 ...) |
| 23:54 | neoncontrails | gfredericks: Interesting, can you briefly explain the logic? |
| 23:54 | gfredericks | neoncontrails: (partition 2 1 coll) gives you adjacent pairs |
| 23:55 | gfredericks | e.g., ##(partition 2 1 '[a b c d]) |
| 23:55 | lazybot | ⇒ ((a b) (b c) (c d)) |
| 23:55 | gfredericks | so then just run through the list until you find two that are equal |
| 23:55 | neoncontrails | Aha, very good |
| 23:57 | neoncontrails | (inc gfredericks) |
| 23:57 | lazybot | ⇒ 146 |
| 23:57 | neoncontrails | (inc amalloy) |
| 23:57 | lazybot | ⇒ 295 |
| 23:57 | amalloy | you can also just write that function once, call it fix |
| 23:58 | neoncontrails | That's a good point. I'll do that now as an exercise |
| 23:58 | amalloy | good thing you said, because i was about to paste a correct definition |
| 23:59 | amalloy | (which IMO turns out to be a lot clearer than a partition/iterate solution) |
| 23:59 | gfredericks | ~amalloy |was about to paste| a correct definition |
| 23:59 | clojurebot | In Ordnung |