2015-08-14
| 01:28 | neo` | hello |
| 01:42 | justin_smith | hi |
| 02:37 | loke | I have a sorted-map that is keyed on a string. Now, I want to modify a small subset of the values based on some criteria, and I will only know which ones by looking at each value in sequence. In other words: I don't know what the keys are until I inspect each value. |
| 02:37 | loke | My question is, what is the most efficient way to do this? |
| 02:37 | loke | I can see two options: One is to traverse all values, finding the keys and then do a bunch of update-in on those keys |
| 02:38 | loke | The other alternative is to effectivelly rebuilding the entire map using a reduction of conj from an empty sorted-map, modifying the elements that needs modifying |
| 02:38 | loke | Is there a better solution? |
| 02:42 | Olajyd | Hi @justin_smith |
| 02:46 | Seylerius | Olajyd: This is IRC, not Twitter. The convention here is "Hi name", or "name: What was the error message?". Just for future reference. |
| 02:47 | TEttinger | yeah, it's funny how @Seylerius has become more common that just Seylerius |
| 02:47 | TEttinger | well |
| 02:47 | TEttinger | more common than before |
| 02:47 | TEttinger | loke: thinking about this... |
| 02:48 | loke | My current version does (reduce conj (sorted-map) (map [[k v]] {k (maybe-transform v)})) |
| 02:48 | Olajyd | Kindly help me fix this code: (defn my-subs [st from end] (let [f (if (neg? from) (+ (count st) from) from)] (subs st f end)) Thing is when I do this (my-subs -14 3) I get a java.lang.stringoutof bounds, thing is I want it to return an empty string .. |
| 02:48 | loke | But it ends up rebuilding the entire thing, and then a typical list contains a few thousand entries and only maybe 5 will need to be changed. |
| 02:49 | Olajyd | Am sorry I dont know how to post a code block on IRC |
| 02:49 | TEttinger | Olajyd: |
| 02:49 | TEttinger | ~pastebin |
| 02:49 | clojurebot | pastebin how about refheap? https://www.refheap.com/ |
| 02:49 | loke | Olajyd: You don't. You use a pastebin. |
| 02:50 | Olajyd | Thanks loke |
| 02:50 | Olajyd | Seylerius noted :) |
| 02:50 | amalloy | loke: are you concerned with the overhead of traversing the whole map, or only the overhead of rebuilding it? |
| 02:50 | TEttinger | ,(defn my-subs [st from end] (let [f (if (neg? from) (+ (count st) (mod from (count st))) from)] (subs st f end)) |
| 02:50 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 02:51 | loke | amalloy: Rebuilding it. I have to traverse it anyway. |
| 02:51 | TEttinger | ,(defn my-subs [st from end] (let [f (if (neg? from) (+ (count st) (mod from (count st))) from)] (subs st f end))) |
| 02:51 | clojurebot | #'sandbox/my-subs |
| 02:51 | TEttinger | ,(my-subs "string" -14 3) |
| 02:51 | clojurebot | #error {\n :cause "String index out of range: -7"\n :via\n [{:type java.lang.StringIndexOutOfBoundsException\n :message "String index out of range: -7"\n :at [java.lang.String substring "String.java" 1911]}]\n :trace\n [[java.lang.String substring "String.java" 1911]\n [clojure.core$subs invokeStatic "core.clj" 4784]\n [clojure.core$subs invoke "core.clj" -1]\n [sandbox$my_subs invokeStatic... |
| 02:51 | amalloy | loke: so just use the original map as your reduce's initial value, and a function like (fn [m [k v]] (if whatever m (assoc m k (whatever v)))) |
| 02:52 | loke | amalloy: ooooh. Stupid me |
| 02:52 | loke | Thanks |
| 02:53 | amalloy | see also reduce-kv, to make this cheaper |
| 02:53 | Olajyd | Tettinger the string for example is “clojurestring” |
| 02:56 | TEttinger | hm |
| 02:56 | Olajyd | use cases (mysubs -14 3) ;=> Error, (my-subs -13 3) ;=> “clo”, |
| 02:56 | TEttinger | ,(defn my-subs [st from end] (let [f (if (neg? from) (max (+ (count st) from) 0) from)] (subs st f end))) ;; if you just want to cap negative indices to 0, this works fine. |
| 02:56 | clojurebot | #'sandbox/my-subs |
| 02:56 | TEttinger | ,(my-subs "clojurestring" -14 3) |
| 02:57 | clojurebot | "clo" |
| 02:57 | TEttinger | ,(my-subs "clojurestring" -7 3) |
| 02:57 | clojurebot | #error {\n :cause "String index out of range: -3"\n :via\n [{:type java.lang.StringIndexOutOfBoundsException\n :message "String index out of range: -3"\n :at [java.lang.String substring "String.java" 1911]}]\n :trace\n [[java.lang.String substring "String.java" 1911]\n [clojure.core$subs invokeStatic "core.clj" 4784]\n [clojure.core$subs invoke "core.clj" -1]\n [sandbox$my_subs invokeStatic... |
| 02:57 | TEttinger | hm... |
| 02:58 | Olajyd | what I really want is (my-subs -14 3) ;=> “clo” and (my-subs -1 7) ;=> “ ” (my-subs -7 7) ;=> “ “ |
| 02:58 | TEttinger | ok but you really should supply the string argument that you expect... I don't really know why there is a space there |
| 02:59 | Olajyd | sorry just wanted you to knw its an empty string |
| 03:00 | TEttinger | ,(my-subs "clojurestring" -7 3) |
| 03:00 | clojurebot | #error {\n :cause "String index out of range: -3"\n :via\n [{:type java.lang.StringIndexOutOfBoundsException\n :message "String index out of range: -3"\n :at [java.lang.String substring "String.java" 1911]}]\n :trace\n [[java.lang.String substring "String.java" 1911]\n [clojure.core$subs invokeStatic "core.clj" 4784]\n [clojure.core$subs invoke "core.clj" -1]\n [sandbox$my_subs invokeStatic... |
| 03:00 | TEttinger | sorry |
| 03:01 | TEttinger | ,(my-subs "clojurestring" -7 3) |
| 03:01 | clojurebot | #error {\n :cause "String index out of range: -3"\n :via\n [{:type java.lang.StringIndexOutOfBoundsException\n :message "String index out of range: -3"\n :at [java.lang.String substring "String.java" 1911]}]\n :trace\n [[java.lang.String substring "String.java" 1911]\n [clojure.core$subs invokeStatic "core.clj" 4784]\n [clojure.core$subs invoke "core.clj" -1]\n [sandbox$my_subs invokeStatic... |
| 03:03 | Olajyd | TEttinger (my-subs “clojurestring” -7 3) ;=> should return an empty string |
| 03:03 | TEttinger | ah, it's doing this in my code: |
| 03:03 | TEttinger | ,(subs "clojurestring" 6 3) |
| 03:03 | clojurebot | #error {\n :cause "String index out of range: -3"\n :via\n [{:type java.lang.StringIndexOutOfBoundsException\n :message "String index out of range: -3"\n :at [java.lang.String substring "String.java" 1911]}]\n :trace\n [[java.lang.String substring "String.java" 1911]\n [clojure.core$subs invokeStatic "core.clj" 4784]\n [clojure.core$subs invoke "core.clj" -1]\n [sandbox$eval236 invokeStatic... |
| 03:03 | TEttinger | subs may be the wrong thing to use here, oddly |
| 03:04 | TEttinger | ,(subs "clojurestring" 6 9) |
| 03:04 | clojurebot | "est" |
| 03:04 | Olajyd | TEttinger, How the problem is to try and replicate the way python handles substrings |
| 03:04 | Olajyd | sorry wanted typing *however* |
| 03:05 | TEttinger | so it looks like you need to validate or possibly swap the order of from and end. since subs needs end to be greater than or equal to from |
| 03:05 | Olajyd | Teetinger, exactly |
| 03:05 | TEttinger | ,(mod -14 7) |
| 03:05 | clojurebot | 0 |
| 03:05 | TEttinger | ,(mod -14 5) |
| 03:05 | clojurebot | 1 |
| 03:05 | TEttinger | hm |
| 03:05 | TEttinger | ,(rem -14 5) |
| 03:05 | clojurebot | -4 |
| 03:06 | TEttinger | do you want large negative numbers to loop around from the end of the string more than once? |
| 03:07 | Olajyd | if its possible.. |
| 03:07 | TEttinger | like for the string "don", position 0 is d, position -3 is d, position -6 could be d |
| 03:08 | Olajyd | nope position -6 should be equal to 0 |
| 03:08 | TEttinger | yeah, in don 0 is d |
| 03:09 | Olajyd | basically large negative values should start from 0 index |
| 03:10 | TEttinger | oh so a clamp? |
| 03:10 | TEttinger | so -3 -4 -5 for a length 3 string are all the same? |
| 03:11 | Olajyd | TEttiner yes, so when used in the subs, as the starting position it’ll start from 0 |
| 03:12 | TEttinger | ,(defn my-subs [st from end] (let [f (if (neg? from) (max (+ (count st) from) 0) from) ] (if (<= f end) (subs st f end) ""))) |
| 03:12 | clojurebot | #'sandbox/my-subs |
| 03:12 | TEttinger | ,(my-subs "clojurestring" -14 3) |
| 03:12 | clojurebot | "clo" |
| 03:12 | TEttinger | ,(my-subs "clojurestring" -11 3) |
| 03:12 | clojurebot | "o" |
| 03:13 | TEttinger | that look right? |
| 03:13 | TEttinger | ,(my-subs "clojurestring" -7 3) |
| 03:13 | clojurebot | "" |
| 03:13 | Olajyd | sure |
| 03:13 | Olajyd | exactly |
| 03:14 | Olajyd | TEttinger, please can you take a min to put me through |
| 03:16 | TEttinger | oh uh sure |
| 03:17 | Olajyd | TEttinger, thanks I really appreciate the help |
| 03:18 | TEttinger | (if (neg? from) (max (+ (count st) from) 0) from) ;; so this does mostly what your code did. it just makes sure that it uses the higher number of 0, or the count of the string plus the negative offset. so if it would go negative, 0 is higher than that, so it uses 0. |
| 03:18 | Olajyd | TEttinger, I got lost in trying to implement it |
| 03:18 | Olajyd | when I was doing it on my own |
| 03:18 | TEttinger | (if (<= f end) (subs st f end) "") ;; this is pretty simple and it turns out being the only real missing thing in yours |
| 03:19 | TEttinger | it just makes sure that f is less than or equal to end, if it is it gets the substring, if not, returns empty string |
| 03:19 | Olajyd | Thanks, I owe you a drink :) |
| 03:19 | TEttinger | heh thanks |
| 03:20 | TEttinger | if there's anything that I can improve about it to make it more compatible with python-like strings, let me know |
| 03:21 | Olajyd | IRC has helped me alot, thanks to TEttiner, justin_smith and oddcully |
| 03:23 | Olajyd | TEttinger, is there anyway to find out if you or someone else is online |
| 03:26 | jeaye | Olajyd: /whois |
| 03:26 | TEttinger | Olajyd: yeah, there's usually a list of people in a channel in most IRC clients. you can also (in almost all clients) use the command /whois TEttinger |
| 03:26 | TEttinger | like if I type: /whois Olajyd |
| 03:27 | TEttinger | I think he tried "/quit" |
| 03:27 | jeaye | haha |
| 03:29 | TEttinger | apparently his IP is in Nigeria, which brings the number of countries in Africa with Clojure users to at least 2. Hooray global userbase! |
| 04:54 | tgoossens | If a java class uses this (gen-class) file: https://gist.github.com/tgoossens/81915c9d3b47acb677dd. Will parser be slurped everytime I use the static function -run or only once? |
| 05:17 | TEttinger | tgoossens: a def is executed once, usually. you may want defonce if you specifically want the file slurped only once, even if the file is required more than once |
| 05:18 | TEttinger | I don't really know what circumstances that code gets called when gen-class is involved though |
| 05:19 | TEttinger | I would have expected gen-class would only export methods, but now that I think about it... those very often would need defs, and those defs may not be constant, so it must run some code to handle the toplevel def calls |
| 05:20 | TEttinger | I really don't know how it works interacting with java. I'd definitely make it defonce if you don't want slurp frenzy potentially |
| 05:20 | TEttinger | it shouldn't run every time you call -run though |
| 09:26 | jeaye | What's the idiomatic way to run a function over each element of a sequence which matches a predicate? |
| 09:27 | jeaye | Being very new to clojure, I found myself in a doseq and trying to use a continue statement, but that's clearly not the ideal route. |
| 09:29 | snowell | jeaye: filter is your friend |
| 09:29 | snowell | ,(filter even? [1 2 3 4 5 6]) |
| 09:29 | clojurebot | (2 4 6) |
| 09:30 | snowell | Put your predicate as the first arg, doseq over the result |
| 09:33 | jeaye | snowell: Ah, yes. |
| 09:33 | jeaye | Thank you. |
| 09:55 | Olajyd | Please how can I handle “*” amd “\” as string in the following (last (clojure.string/split “2001/900*34/68” #”*”)) ;=> “34/68” |
| 09:56 | chouser | ,(clojure.string/split “2001/900*34/68” #”\*”)) |
| 09:56 | clojurebot | #<RuntimeException java.lang.RuntimeException: Invalid token: “2001/900*34/68”> |
| 09:56 | snowell | Silly fancy quotes |
| 09:56 | snowell | ,(clojure.string/split "2001/900*34/68" #"\*") |
| 09:56 | clojurebot | ["2001/900" "34/68"] |
| 09:57 | snowell | Sorry to steal your thunder, chouser. I had the same answer prepped without the fancy quotes :) |
| 09:57 | chouser | :-) no problem! |
| 09:59 | snowell | Olajyd: You have to escape the * in your regex like so ^ |
| 10:12 | Olajyd | snowell the “*” string is it a special character |
| 10:12 | snowell | In a regex, yes. And the # before the string signifies that it's a regex |
| 10:15 | Olajyd | snowell, the # is same as using re-pattern right? |
| 10:16 | snowell | Yup |
| 10:17 | snowell | Well, # is actually better for hard-coded regex patterns. re-pattern is for when you need it dynamically generated |
| 10:25 | Olajyd | snowell, lol I’m lost there? |
| 10:26 | snowell | Haha it's OK. They do the same thing :) |
| 10:26 | Bronsa | Olajyd: do you understand the difference between [1] and (vector 1)? |
| 10:27 | Bronsa | that's the same difference between #"foo" and (re-pattern "foo") |
| 10:27 | Bronsa | one is a read-time value, the other is a run-time value |
| 10:33 | Olajyd | snowell, Lol I actually want to use it like this: (re-pattern “*”) and I’m getting an error |
| 10:34 | Olajyd | Bronsa, gotcha |
| 10:34 | Olajyd | So how do I go about it |
| 10:36 | pbx | interaction on the big screen! |
| 10:36 | Olajyd | This is what i want to do: Given (def delim “/“ ) (last (coljure.string/split “foo/bar” (re-pattern delim))) ;=> “bar” |
| 10:36 | pbx | oh nm, wrong channel :\ |
| 10:37 | Olajyd | Thing is `delim` can change to something like (def delim “*“) |
| 10:39 | Olajyd | and thus (last (coljure.string/split “foo-bart*bar” (re-pattern delim))) ;=> Error |
| 10:41 | cenzhe | hi all. I have nested calls to pmap, i.e., with (pmap f s), inside the f, it also calls pmap |
| 10:42 | cenzhe | Like this, the number of threads gets exploded fairly fast, making the load of the system unmanageable |
| 10:42 | cenzhe | Do you guys have any suggestions to improve this? |
| 10:43 | cenzhe | Creating a thread pool from which the pmap futures runs? I can only find `send-via` has the option to specify a thread pool |
| 11:32 | justin_smith | go answer Olayjyd's question he needs (re-pattern "\\*") because "\*" is an illegal string |
| 11:32 | justin_smith | despite #"\*" being a legal regex literal |
| 11:46 | sdegutis | How can you get a pseudo-random list with even distribution? |
| 11:47 | sdegutis | ,(->> (range) (take 3) (cycle) (take 10) (shuffle)) ;; notice it's disproportionate and not evenly distributed |
| 11:47 | clojurebot | [1 2 0 2 0 ...] |
| 11:48 | sdegutis | Whoops that's a horrible example. |
| 11:49 | sdegutis | In fact, I just realized it not only does not demonstrate my problem, it actually solved it. |
| 11:49 | sdegutis | Woot. |
| 11:56 | justin_smith | cenzhe: I would make a thread pool executor via interop, and use that along with a queue |
| 11:56 | cenzhe | justin_smith: yah, I'm reading code from [this link](https://github.com/TheClimateCorporation/claypoole) |
| 11:57 | cenzhe | It takes the same logic as you just said |
| 11:57 | justin_smith | oh, cool |
| 11:58 | cenzhe | :D My functions can block on IO, making things messier |
| 11:58 | cenzhe | I was about to use core.async, utilize the go block, but later found go block stops upon seeing function definition |
| 12:00 | sdegutis | I found that accidental solution really funny. So I shared it briefly here. Dead silence. Went to tell my wife about it. Blank stare. WHAT THE HELL IS WRONG WITH EVERYONE. |
| 12:03 | gfredericks | hiredman: what does "suffer through everyone's edge cases" mean? |
| 12:04 | gfredericks | sdegutis: why wouldn't (repeatedly #(rand-int 3)) do what you wanted? |
| 12:06 | sdegutis | gfredericks: It might, let me check. But either way, the code I wrote down to demonstrate my problem doesn't actually demonstrate the problematic behavior, it demonstrates exactly what I was trying to do but didn't realize how to. |
| 12:07 | gfredericks | sdegutis: I guess it depends on whether you want the same number of everything or a truly random sample |
| 12:07 | sdegutis | gfredericks: Oh I see. The code you posted shows the exact behavior I have now. |
| 12:07 | gfredericks | e.g., your code will never generate all 0's |
| 12:07 | sdegutis | gfredericks: I want the order to be random but the distribution to be even. |
| 12:07 | sdegutis | gfredericks: Right. |
| 12:07 | gfredericks | so (repeatedly #(rand-int 3)) doesn't work then |
| 12:08 | sdegutis | Right. (take 10 (repeatedly #(rand-int 3))) gave me (0 2 1 1 1 1 0 1 1 1) just now and that's what I came here asking how to avoid. |
| 12:08 | sdegutis | And in trying to demonstrate the problem, I accidentally wrote down the perfect solution. |
| 12:08 | gfredericks | it has a uniform distribution but I don't think that's what you mean by "distribution to be even" |
| 12:08 | sdegutis | So it sounds to me like the problem has been all along that I just really suck at communicating. |
| 12:08 | gfredericks | it's the hardest part of everything |
| 12:09 | gfredericks | except weightlifting |
| 12:09 | sdegutis | :) |
| 12:33 | {blake} | Actually, getting people to weighlift properly takes a ton of communicating. =P |
| 12:33 | {blake} | But I digress. I'm trying to split a text document up by words and using: (clojure.string/split md #"([A-Za-z'])+") |
| 12:34 | {blake} | But this gets me all the spaces and "\r\n"s as words, too. |
| 12:38 | gfredericks | re-seq? |
| 12:39 | {blake} | gfredericks: Yeah, that'd...probably work. I swear I had this with a regular split, tho'. |
| 12:48 | sdegutis | Where'd technomancy go. |
| 12:48 | {blake} | Indonesia? |
| 12:48 | tcrayford____ | thailand |
| 12:51 | amalloy | {blake}: you sure you don't want \b? |
| 12:53 | {blake} | amalloy: (clojure.string/split whatever #"\b") appears to return each individual space, all the newlines grouped together, etc. |
| 12:53 | amalloy | probably not each individual space, but each group-of-spaces between the words |
| 12:53 | amalloy | it splits on word boundaries, which occur at the beginning and end of every word |
| 12:54 | {blake} | That would make sense. And that would be fine but I don't want the non-word stuff. |
| 12:54 | gfredericks | {blake}: what's wrong with re-seq? |
| 12:55 | gfredericks | it sounds a lot more like what you're describing than split does |
| 12:56 | {blake} | gfredericks: Nothing per se. I'm trying to introduce Clojure to some folks and liked the idea of using the clojure.string library as much as possible. |
| 12:57 | amalloy | {blake}: re-seq and split both just delegate to java |
| 12:57 | amalloy | one happens ot be in core and the other in string |
| 12:58 | justin_smith | ,(re-seq #"[\w]+" "good news, everyone!") |
| 12:58 | {blake} | amalloy: Sure. It's not a big deal, I just thought I had it (with split) and then...lost it. =P |
| 12:58 | clojurebot | ("good" "news" "everyone") |
| 13:00 | {blake} | justin_smith: I'm using (re-seq #"\w+"). |
| 13:00 | sdegutis | No I mean why isn't he in here. |
| 13:00 | justin_smith | oh, of course, that's a silly usage of [] |
| 13:00 | sdegutis | justin_smith: happens all the time don't sweat it |
| 13:01 | sdegutis | ##(group-by identity [:a :b :b :a :c :a]) |
| 13:01 | lazybot | ⇒ {:a [:a :a :a], :b [:b :b], :c [:c]} |
| 13:01 | gfredericks | sdegutis: my guess is he'd rather be doing other things, not to mention I assume it's the middle of the night at the moment |
| 13:03 | sdegutis | What's the most majestic way to get the count of every unique element in a seq like [:a :b :b :a :c :a] => {:a 3, :b 2, :c 1}? |
| 13:03 | gfredericks | frequencies |
| 13:03 | sdegutis | gfredericks: The second reason doesn't explain why he's not on here when it's nighttime for us. The first reason doesn't explain why the rest of you are in here. |
| 13:03 | sdegutis | ##(frequencies identity [:a :b :b :a :c :a]) |
| 13:03 | lazybot | clojure.lang.ArityException: Wrong number of args (2) passed to: core/frequencies |
| 13:03 | sdegutis | ##(frequencies [:a :b :b :a :c :a]) |
| 13:03 | lazybot | ⇒ {:a 3, :b 2, :c 1} |
| 13:04 | sdegutis | gfredericks: Very majestic thank you. |
| 13:04 | gfredericks | sdegutis: it wasn't clear if you were asking about "right now" or not |
| 13:10 | {blake} | ,(clojure.string/split "1234\r\n5678\r\n" #"\n") |
| 13:10 | clojurebot | ["1234\r" "5678\r"] |
| 13:11 | {blake} | ,(clojure.string/split "1234\r\n5678\r\n" #"\r\n") |
| 13:11 | clojurebot | ["1234" "5678"] |
| 13:12 | {blake} | Hmmm. But...if we use a reader and line-seq, we don't have to worry whether we've got "\r"s or "\r\n"s. |
| 13:12 | justin_smith | ,(line-seq (java.io.BufferedReader. (java.io.StringReader. "hello\nworld\r\nOK"))) |
| 13:12 | clojurebot | ("hello" "world" "OK") |
| 13:13 | justin_smith | next question - do I really type that fast, or am I basically psychic? |
| 13:13 | sdegutis | gfredericks: a deviant moron once told me "embrace ambiguity" |
| 13:13 | pandeiro | anyone else having issues with calling `clojure-mode` with most recent (melpa) cider/clojure-mode packages? |
| 13:14 | pandeiro | I get a File mode specification error: (void-variable defun) |
| 13:14 | {blake} | justin_smith: Psychic. |
| 13:14 | justin_smith | pandeiro: my voodoo approach is to try deleting all elc files |
| 13:15 | pandeiro | justin_smith: good call, i'll try that i guess |
| 13:15 | justin_smith | pandeiro: when two releases of an emacs lib are not api compatible, weird things can happen |
| 13:15 | pandeiro | i'm using cask so i've already tried deleting .emacs.d/.cask but... |
| 13:15 | justin_smith | and clojure-mode / cider often break api |
| 13:16 | kwladyka | hmm when reflections (http://clojuredocs.org/clojure.core/*warn-on-reflection*) appear? In one moment i stop need ^long in my code and don't have any idea how it is possible |
| 13:16 | justin_smith | kwladyka: the warnings happen during compilation |
| 13:16 | justin_smith | that is, when the definitions are created (defn form, etc.) |
| 13:18 | kwladyka | justin_smith, yes but.... i didin't change anything important in code from that time |
| 13:18 | kwladyka | i guess |
| 13:18 | kwladyka | and now i don't need ^long in functions |
| 13:19 | kwladyka | i try figure out what changed that |
| 13:19 | justin_smith | kwladyka: it could be that the compiler picked up the type from another hint |
| 13:19 | kwladyka | but even if i remove all ^long in code... |
| 13:20 | sdegutis | Is there a built in Clojure function to generate an evenly distributed list of random elements based on a set of choices for each element? |
| 13:20 | justin_smith | were you only warning on reflection, or also warning on numeric boxing? |
| 13:20 | hiredman | gfredericks: if you are using anyone else's libraries, your generative testing ends up testing their edge cases too |
| 13:20 | sdegutis | Like, if I have [#{:a :b}, #{:a :b :c}, #{:a :c}] then it will choose [:a :b :c]? |
| 13:20 | kwladyka | justin_smith, numbering boxing? only on reflection |
| 13:21 | sdegutis | I have no idea what this concept is called. |
| 13:21 | justin_smith | kwladyka: heres a post about it from puredanger http://insideclojure.org/2014/12/15/warn-on-boxed/ |
| 13:21 | kwladyka | sdegutis, not really sure what you want to achieve |
| 13:22 | kwladyka | sdegutis, maybe there you will find something interesting https://github.com/clojure/math.combinatorics |
| 13:22 | hiredman | isn't a problem per se, just a sea of pain |
| 13:28 | sdegutis | kwladyka: Honestly I don't know either. Thanks for the link. |
| 13:29 | sdegutis | Given a list of sets of choices, I need to pick each choice such that overall it's as evenly distributed as possible. |
| 13:31 | sdegutis | I think I know how I could do this imperatively with mutable state. Reorder the sets of choices, most restrictive first. Iterate the list, choosing from each set, and adding to a list. Each choice should be random but biased towards what's least available in the set already. The bias should start out weak but grow stronger over time. |
| 13:31 | sdegutis | Now, reduce could probably replace the mutable state and imperativeness. |
| 13:31 | kwladyka | justin_smith, i don't understand it. I reset commit to the time when i had warnings about reflections and i don't have them now....... |
| 13:32 | sdegutis | So I guess all I'm left with are hard math problems that I don't understand. |
| 13:32 | kwladyka | justin_smith, how is it possible? |
| 13:35 | justin_smith | kwladyka: are you sure reflection warnings are turned on properly? try adding something to your project that is guaranteed to cause a reflection warning |
| 13:35 | justin_smith | (defn date->long [d] (.getTime d)) ; for example |
| 13:51 | kwladyka | justin_smith, yes i get a warning |
| 13:52 | kwladyka | justin_smith, i did lein clean but is it possible it is cached somewhere? |
| 13:54 | kwladyka | so magic... |
| 13:57 | shiranaihito | can i extend a protocol to another protocol? :/ |
| 14:15 | gfredericks | not really |
| 14:17 | gfredericks | hiredman: the pain is because you have to weed out their edge cases in the generators? or because you find bugs in their code? |
| 14:48 | sdegutis | ##(shuffle #{:a :b :c}) |
| 14:48 | lazybot | ⇒ [:b :c :a] |
| 14:48 | hiredman | gfredericks: both, either |
| 14:49 | hiredman | gfredericks: the machine doing the generating doesn't understand or care about your notions of logical separation and api boundaries |
| 14:50 | hiredman | which can be very brutal when you depend on lots of 3rd parties |
| 14:50 | sdegutis | ##(dissoc #{:a :b :c} :b) |
| 14:50 | lazybot | java.lang.ClassCastException: clojure.lang.PersistentHashSet cannot be cast to clojure.lang.IPersistentMap |
| 14:51 | gfredericks | sdegutis: disj |
| 14:51 | sdegutis | Ahh. But why! |
| 14:51 | gfredericks | hiredman: I wonder if you're using it in a moderately different style than I do |
| 14:51 | sdegutis | Clojure seems so inconsistent. Sometimes it considers sets just like maps, where the key is a key to itself. |
| 14:51 | sdegutis | But sometimes they're not considered like maps, like here. |
| 14:51 | gfredericks | you can't use assoc with them either |
| 14:52 | gfredericks | ,(get #{:a :b :c} :b) |
| 14:52 | clojurebot | :b |
| 14:52 | gfredericks | ,(find #{:a :b :c} :b) |
| 14:52 | clojurebot | #error {\n :cause "clojure.lang.PersistentHashSet cannot be cast to java.util.Map"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentHashSet cannot be cast to java.util.Map"\n :at [clojure.lang.RT find "RT.java" 816]}]\n :trace\n [[clojure.lang.RT find "RT.java" 816]\n [clojure.core$find invokeStatic "core.clj" 1470]\n [clojure.core$find invoke "core.clj" -1]\n... |
| 14:52 | sdegutis | ##[(contains? {:a 1} :a) (contains? #{:a}) :a] |
| 14:52 | lazybot | clojure.lang.ArityException: Wrong number of args (1) passed to: core/contains? |
| 14:52 | sdegutis | ##[(contains? {:a 1} :a) (contains? #{:a} :a)] |
| 14:52 | lazybot | ⇒ [true true] |
| 14:52 | hiredman | gfredericks: could be |
| 14:53 | hiredman | I suspect a lot of it has to do with sort of the granularity of testing too |
| 14:54 | gfredericks | hiredman: I often find myself using generators to describe whatever part of the external world is creating inputs to the system |
| 14:54 | hiredman | gfredericks: sure |
| 14:54 | gfredericks | which often coincides with high-level testing |
| 14:55 | hiredman | a better way to phrase the tweet might be something like "generative testing exposes all the ambiguity in the apis you use" |
| 14:55 | Bronsa | sdegutis: how does clojure considers set maps? |
| 14:56 | sdegutis | Bronsa: I mean sometimes they are both grouped together as similarly functioning things, and sometimes not. Like `contains?` works on both. |
| 14:56 | gfredericks | Bronsa: and get |
| 14:56 | Bronsa | sdegutis: contains? works on a lot of collections |
| 14:56 | sdegutis | ##[(get {:a 1} :a) (get #{:a} :a)] |
| 14:56 | lazybot | ⇒ [1 :a] |
| 14:57 | gfredericks | hiredman: for me it also forces being explicit about what assumptions are being made |
| 14:57 | hiredman | like, I might generating a bunch of data, run it through some kind of analysis, stick the results in some database, then do the same thing with data in memory and compare the results |
| 14:57 | hiredman | to verify the analysis and the database stuff |
| 14:57 | sdegutis | ##(for [coll [{:a 1} #{:a}]] (juxt #(get % :a))) |
| 14:57 | lazybot | ⇒ (#<core$juxt$fn__4302 clojure.core$juxt$fn__4302@32607988> #<core$juxt$fn__4302 clojure.core$juxt$fn__4302@5bcae98e>) |
| 14:57 | hiredman | but of course databases |
| 14:57 | Bronsa | ah, you're complaining about dissoc/disj? |
| 14:58 | sdegutis | ##(for [coll [{:a 1} #{:a}]] (get coll :a)) |
| 14:58 | lazybot | ⇒ (1 :a) |
| 14:58 | hiredman | gfredericks: yeah |
| 14:58 | sdegutis | Apparently I'm drunk today. |
| 14:59 | gfredericks | hiredman: databases are ambiguous about what kind of data they accept? I'm having a hard time imagining where this gets hairy |
| 14:59 | sdegutis | Bronsa: It seems like dissoc should work on sets yeah. |
| 15:00 | hiredman | gfredericks: well, once you are dealing with databases you are generally doing network traffice, and some databases are clustered and replicate data in weird ways, and some datbases are inexact in vague ways about things like counts |
| 15:01 | hiredman | so right, there can be assumptions in the model that just are not valid |
| 15:01 | gfredericks | hiredman: is nondeterminism a big part of it? |
| 15:01 | hiredman | sure |
| 15:01 | gfredericks | yeah that's probably the biggest barrier I see to more elaborate setups |
| 15:02 | Bronsa | sdegutis: I think the rationale for it not to work is to maintain the parallel with assoc |
| 15:02 | gfredericks | I can't say I've had issues that I felt were inherently related to 3rd-party library use though |
| 15:02 | Bronsa | sdegutis: assoc can't work on sets |
| 15:02 | hiredman | you have to incorporate the nondeterminism in to the model checking, which gets more complicated |
| 15:04 | gfredericks | yeah |
| 15:05 | hiredman | well, anytime your code is tested via test.check (or similar), and you are calling code that isn't, you are effectively fuzzing that 3rd party code |
| 15:05 | hiredman | it can get weird |
| 15:06 | gfredericks | I found two bugs in goog.math.Integer that way |
| 15:07 | gfredericks | which I thought of as a good thing |
| 15:08 | hiredman | it depends on the extent of the bug, your relationship with the 3rd party, if you can even decide where the "fault" lies etc |
| 15:09 | gfredericks | I suppose whether you consider it a good thing or not depends on the probability that you would have found it in production otherwise |
| 15:10 | hiredman | don't get me wrong, generative testing is great, I want it all the time everywhere |
| 15:11 | hiredman | there is just a hint of bitter with the sweet |
| 15:13 | gfredericks | :D |
| 15:13 | gfredericks | yeah I think I agree with that |
| 15:20 | sdegutis | Bronsa: Maybe it could but just take one fewer arg? |
| 15:20 | sdegutis | So that (assoc #{} :a) would give #{:a} |
| 15:20 | Bronsa | that's conj |
| 15:20 | Bronsa | and thus disj |
| 15:20 | Bronsa | It'd make more sense to make disj work on maps than dissoc on sets |
| 15:20 | sdegutis | Right, but it makes sense with the other terminology more. |
| 15:21 | sdegutis | It's just starting to seem like most of the naming and conventions in Clojure were randomly picked out of a hat. |
| 15:22 | Bronsa | Most would disagree |
| 15:23 | {blake} | I rarely find things that don't make sense. I think "contains?" is a boo-boo, even though it makes perfect sense. That's about it. |
| 15:23 | J_A_Work | sdegutis: I do find it frustrating sometimes. It seems like I get ‘surprises’ sometimes. I think it’s partly being used to other Lisps and FP languages. Clojure diverges from convention in seemingly random places (like, assoc is technically wrong in traditional Lisp/Scheme terms) |
| 15:23 | clojurebot | Alles klar |
| 15:24 | sdegutis | ,(select-keys {} [:a :b :c]) |
| 15:24 | clojurebot | {} |
| 15:25 | Bronsa | J_A_Work: how so? |
| 15:25 | sdegutis | ,(get {} :a) |
| 15:25 | clojurebot | nil |
| 15:25 | Bronsa | sdegutis: select-keys returns a map, get returns a mapped value, nothing surprising |
| 15:26 | sdegutis | welp |
| 15:26 | J_A_Work | Bronsa: traditional assoc in other lists is a search of an associative list structure, not an add like it is in clj. compare: http://docs.racket-lang.org/reference/pairs.html?q=assoc#%28def._%28%28lib._racket%2Fprivate%2Flist..rkt%29._assoc%29%29 |
| 15:26 | J_A_Work | *other Lisps |
| 15:26 | {blake} | Oh, I have one of those. |
| 15:27 | {blake} | Not lisps, but situations that are sort of surprising. |
| 15:27 | {blake} | filter vs. keep |
| 15:27 | Bronsa | J_A_Work: well I don't think it's fair to claim that because a name already has a meaning, all other languages using that name must mean the same thing :) |
| 15:28 | kwladyka | justin_smith, another mysterious solved. I have warning about reflection only if i use (require). If i use function without require i don't have this warnings |
| 15:28 | kwladyka | justin_smith, but why it works in that way.... |
| 15:28 | Bronsa | J_A_Work: I actually thing assoc makes much more sense as `associate` than as what it means in racket |
| 15:28 | {blake} | You end up with languages imitating C's horrible switch/case logic when you copy slavishly. =P |
| 15:28 | Bronsa | think* |
| 15:28 | J_A_Work | Bronsa: perhaps, but it’s odd if you come from an existing Lisp background. It’s like map or filter, it would be similarly odd for most FP people to find those renamed to something else in a language. I started in CL and then Racket, so the differences can be jarring. |
| 15:29 | J_A_Work | (already it gets messy from language to another whether it’s reduce or fold and whether there’s both foldl and foldr and … blegh) |
| 15:29 | sdegutis | J_A_Work: I haven't really used other Lisps so differences from them are fine with me. I've used Ruby and Python and Haskell more than Lisps. |
| 15:30 | sdegutis | I completely forgot about keep. |
| 15:31 | J_A_Work | I didn’t know about keep. |
| 15:31 | gfredericks | ,(keep next '((1 2 3) (1 2) (1) ())) |
| 15:31 | clojurebot | ((2 3) (2)) |
| 15:33 | J_A_Work | One I still get wrong though, and not because it’s named, is actually filter. XD I often manage to forget that it keeps *true*. Somehow the name always makes me think it’s for ‘filtering something out’ which is what I use it more often for, and then screw up because I forget to negate my fn to get the expected result. XD |
| 15:35 | {blake} | Yep. Heh. |
| 15:35 | stuartsierra | kwladyka: Reflection warnings are a feature of the compiler, they are printed when you load code, not when you call a function. |
| 15:36 | kwladyka | justin_smith, oh i know exactly why. The problem was i used :reload-all (require 'chess-challenge.pieces :reload-all) |
| 15:36 | kwladyka | this problem appear only with :reload-all |
| 15:36 | kwladyka | without :reload-all i don't have reflections problem |
| 15:37 | kwladyka | it looks like some kind of bug or i don't know about something |
| 15:37 | justin_smith | kwladyka: without :reload-all require isn't doing anything |
| 15:37 | kwladyka | hmm |
| 15:37 | justin_smith | require does nothing and returns nil if you have already defined the namespace |
| 15:37 | justin_smith | (doc require) |
| 15:37 | clojurebot | "([& args]); Loads libs, skipping any that are already loaded. Each argument is either a libspec that identifies a lib, a prefix list that identifies multiple libs whose names share a common prefix, or a flag that modifies how all the identified libs are loaded. Use :require in the ns macro in preference to calling this directly. Libs A 'lib' is a named set of resources in classpath whose contents define a library of Clojure code. Lib |
| 15:38 | justin_smith | "skipping any that are already loaded" |
| 15:38 | kwladyka | justin_smith, so if i run "lein repl" is chess-challenge.pieces already loaded? |
| 15:40 | justin_smith | kwladyka: if you have a :main set up in your project.clj, lein auotmatically requires it, yes |
| 15:40 | justin_smith | kwladyka: but it does depend on your project setup, you can turn on reflection warnings via project.clj btw |
| 15:40 | kwladyka | justin_smith, oh so it is because i added :main ^:skip-aot chess-challenge.handler to project.clj ? |
| 15:41 | justin_smith | yes, that would do it |
| 15:41 | justin_smith | kwladyka: here's how you can set up warnings via project.clj as well https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L253 |
| 15:41 | kwladyka | but anyway how is that when loaded by repl it works without reflections (i know because it is fast), but if i use require :reload-all the problem appear? |
| 15:42 | justin_smith | kwladyka: oops, lein I linked to is deprecated, but the one right blow it shows the right way |
| 15:42 | justin_smith | kwladyka: I suspect that's not how it is happening at all. I think you fixed your main reflection bottle necks, and the remaining warnings are ones that don't slow down your code as much. |
| 15:44 | kwladyka | justin_smith, hmm i feel magic :) |
| 15:45 | sdegutis | What's a prestigious way to sort a map by its keys? ##(sort-by {:a 1 :b 2 :c 3} second) ? |
| 15:45 | lazybot | java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.core$second |
| 15:45 | sdegutis | Oops ##(sort-by second {:a 1 :b 2 :c 3}) |
| 15:45 | lazybot | ⇒ ([:a 1] [:b 2] [:c 3]) |
| 15:46 | sdegutis | Is that a fair assessment? |
| 15:46 | gfredericks | you're sorting by values there |
| 15:46 | sdegutis | Sorry I meant values. |
| 15:46 | sdegutis | Communicating is hard. |
| 15:46 | gfredericks | well that definitely works, yeah |
| 15:46 | sdegutis | Feels like cheating thou. |
| 15:46 | gfredericks | why? |
| 15:46 | clojurebot | http://clojure.org/rationale |
| 15:47 | sdegutis | It relies on how iterating a map turns each pair them into a vector of [k v] |
| 15:47 | sdegutis | Which feels like a weird thing to rely on. |
| 15:47 | sdegutis | I'd much rather it work like (sort-by key m) |
| 15:47 | gfredericks | use val then |
| 15:47 | gfredericks | ,(sort-by val {:a 1 :b 2 :c 3}) |
| 15:47 | sdegutis | I don't think val will work in that case. |
| 15:47 | clojurebot | ([:a 1] [:b 2] [:c 3]) |
| 15:47 | gfredericks | it's even shorter |
| 15:47 | sdegutis | Use ## , is too slow |
| 15:48 | sdegutis | I'm surprised that worked. I guess it's not really a vector after all? |
| 15:48 | sdegutis | Just looks like one? |
| 15:48 | gfredericks | it's both a vector and a mapentry |
| 15:48 | sdegutis | (val [:a 1]) |
| 15:48 | sdegutis | ##(val [:a 1]) |
| 15:48 | lazybot | java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.util.Map$Entry |
| 15:48 | justin_smith | (vector? (first {:a 0})) |
| 15:48 | sdegutis | ah |
| 15:48 | justin_smith | ,(vector? (first {:a 0})) |
| 15:48 | clojurebot | true |
| 15:48 | sdegutis | Haha Map$Entry |
| 15:48 | sdegutis | what is this javascript haha |
| 15:48 | gfredericks | it's a java inner class |
| 15:49 | sdegutis | Right but still |
| 15:49 | sdegutis | Is there a way to give a 'weight' to shuffling a seq? |
| 15:49 | gfredericks | what would it mean? |
| 15:50 | sdegutis | Like, don't shuffle things too far away from each other. |
| 15:51 | kangarooo | shocking video about islamic state, must watch: https://www.youtube.com/watch?v=df4KB30K0UU |
| 15:51 | gfredericks | sdegutis: you could shuffle by swapping pairs, and vary how many swaps you do |
| 15:52 | kwladyka | justin_smith, but i am afraid you are right |
| 15:52 | gfredericks | swapping adjacent elements I mean |
| 15:52 | kwladyka | justin_smith, perhaps i fixed it in the same time and didn't know about that :) |
| 15:55 | kwladyka | oh so great library https://github.com/gtrak/no.disassemble what is the pitty i didn't know about that before |
| 15:56 | sdegutis | Wow that is shocking. |
| 15:57 | justin_smith | kwladyka: did you find that via the puredanger blog post I linked you to? |
| 15:58 | kwladyka | justin_smith, yes |
| 16:18 | {blake} | Repeating a string--is it possible without the join/apply stuff? |
| 16:18 | {blake} | It used to be. clojure.contrib.string had its own repeat. |
| 16:19 | justin_smith | {blake}: you could do it yourself with a StringBuilder |
| 16:20 | {blake} | Sure. Just wondering if clojure.contrib.string/repeat still exists. Doesn't look like it. |
| 16:23 | justin_smith | doing it with join or apply str shouldn't be so bad, both will use a StringBuilder come to think of it |
| 16:23 | {blake} | justin_smith: Oh, it's not a matter of "bad". It's a matter of sipping from the firehose. I'm trying to introduce people to Clojure, but gently. =P |
| 16:26 | gfredericks | I think repeat and apply str are pretty gentle |
| 16:26 | gfredericks | you can show the intermediate seq |
| 16:26 | gfredericks | ,(repeat 5 "HOOHA") |
| 16:26 | clojurebot | ("HOOHA" "HOOHA" "HOOHA" "HOOHA" "HOOHA") |
| 16:26 | gfredericks | ,(apply str (repeat 5 "HOOHA")) |
| 16:26 | clojurebot | "HOOHAHOOHAHOOHAHOOHAHOOHA" |
| 16:26 | {blake} | gfredericks: Yeah, I like that better than join, thanks! |
| 16:27 | {blake} | Especially because I've already gone over apply. |
| 16:29 | justin_smith | ,(str (repeat 5 "HOOHA")) |
| 16:29 | clojurebot | "(\"HOOHA\" \"HOOHA\" \"HOOHA\" \"HOOHA\" \"HOOHA\")" |
| 16:29 | justin_smith | the difference between that and the apply version should be a nice lesson too |
| 16:29 | sdegutis | hahaha |
| 16:29 | sdegutis | ##(get {Double/NaN 2} Double/NaN) |
| 16:29 | lazybot | ⇒ nil |
| 16:30 | sdegutis | Why is that. |
| 16:30 | {blake} | NaN's aren't equal to anything, including themselves, I believe. |
| 16:31 | {blake} | ##(= Double/NaN Double/NaN) |
| 16:31 | lazybot | ⇒ false |
| 16:33 | sdegutis | What is that necessary for? |
| 16:34 | gfredericks | I think that's part of the spec for doubles? |
| 16:34 | gfredericks | would be interested if there's any language with IEEE doubles that doesn't do that |
| 16:34 | sdegutis | What Java code cannot be expressed in a reasonable way except that this rule exists? |
| 16:35 | t0by | I suppose they wouldn't be ieee doubles. |
| 16:35 | t0by | There is a pretty fixed algebra for that. |
| 16:35 | t0by | Including NaN != NaN |
| 16:36 | sdegutis | Given a set #{:a :b} and a list [:c :a :b] what's an amazing way to get the first element in the list which exists in the set? |
| 16:36 | sdegutis | Just some? |
| 16:36 | t0by | an "amazing" way? :P |
| 16:36 | sdegutis | Yes please. |
| 16:36 | sdegutis | t0by: it's a meme that's expected of me, I have to use weird adjectives when asking for help or nobody answers |
| 16:37 | t0by | Must be fun being you :) |
| 16:38 | sdegutis | Goodness no. It's a nightmare. |
| 16:38 | sdegutis | Most days I wake up hoping yesterday was all just a bad dream. |
| 16:38 | sdegutis | Hmm some didn't work. |
| 16:38 | t0by | There was a guy like that in the village I grew up in, as well. He had to use weird adjectives. Then he was committed. |
| 16:38 | gfredericks | ,(some #{:a :b} [:c :a :b]) |
| 16:38 | clojurebot | :a |
| 16:38 | sdegutis | Oh wait I think it worked. |
| 16:39 | sdegutis | Had the args backwards. |
| 16:39 | sdegutis | Thanks gfredericks you're the best person. |
| 16:40 | sdegutis | I think this is the first time I've ever used the return value of some more than just for a truthy check. |
| 16:41 | sdegutis | t0by: that sounds like the beginning of one of my stories at /u/-sdegutis- |
| 16:42 | sdegutis | What's a fantastic way to turn [:a :b :c :d] into [:b :c :d :a] ? |
| 16:43 | sdegutis | I can't think of a way to do it without giving it a name. |
| 16:43 | gfredericks | (->> coll cycle rest (take (count coll))) |
| 16:43 | sdegutis | ##(let [coll [:a :b :c :d]] (->> coll (cycle) (rest) (take (count coll))) |
| 16:43 | sdegutis | Yeah that's the only way I could think of. It requires it to be named though. |
| 16:44 | sdegutis | ##(let [coll [:a :b :c :d]] (->> coll (cycle) (rest) (take (count coll)))) |
| 16:44 | lazybot | ⇒ (:b :c :d :a) |
| 16:44 | gfredericks | you could put any expression in there it doesn't have to be named |
| 16:44 | gfredericks | &(->> (range 5) cycle rest (take (count coll))) |
| 16:44 | lazybot | java.lang.RuntimeException: Unable to resolve symbol: coll in this context |
| 16:44 | sdegutis | No I mean coll. |
| 16:44 | gfredericks | oh for the count, yeah |
| 16:44 | sdegutis | Right. |
| 16:44 | sdegutis | I was hoping for some kind of weird queue solution. |
| 16:44 | gfredericks | well you *can* use a queue if you really want to |
| 16:45 | sdegutis | Like this pseudo-code: (->> [:a :b :c :d] (queue) (pop) (push)) |
| 16:49 | justin_smith | gfredericks: you can queue if you want to .... 'cause your friends don't queue and if they don't queue they aint no friends of mine |
| 17:02 | sdegutis | you can leave your queue.. behind? |
| 17:16 | numberten | does clojure have a min/max function that uses .compareTo ? |
| 17:17 | sdegutis | Is sort-by stable? |
| 17:21 | domokato | I'm using an anonymous fn as a Runnable; is there a way to refer to itself from inside the fn? (i.e. "this" in java) |
| 17:23 | sdegutis | domokato: letfn |
| 17:24 | domokato | sdegutis: oo thx, let wouldn't work, huh? |
| 17:24 | sdegutis | (doc letfn) |
| 17:24 | clojurebot | "([fnspecs & body]); fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+) Takes a vector of function specs and a body, and generates a set of bindings of functions to their names. All of the names are available in all of the definitions of the functions, as well as the body." |
| 17:28 | sdegutis | (clojuredocs letfn) |
| 17:28 | sdegutis | clojurebot: WAKE UP |
| 17:28 | clojurebot | It's greek to me. |
| 17:30 | justin_smith | domokato: the easy way is (fn some-name [blah] ....) |
| 17:30 | justin_smith | ,((fn my-name [] my-name)) |
| 17:30 | clojurebot | #object[sandbox$eval47$my_name__48 0x42f33dae "sandbox$eval47$my_name__48@42f33dae"] |
| 17:31 | justin_smith | returns itself |
| 17:31 | domokato | ohhh, i forgot you could do that |
| 17:31 | justin_smith | ,(((fn my-name [] my-name))) |
| 17:31 | clojurebot | #object[sandbox$eval73$my_name__74 0x1ff66d7d "sandbox$eval73$my_name__74@1ff66d7d"] |
| 17:31 | justin_smith | heh, it's a fixed point |
| 17:31 | justin_smith | ,(((((fn my-name [] my-name))))) |
| 17:31 | clojurebot | #object[sandbox$eval99$my_name__100 0x7146e77a "sandbox$eval99$my_name__100@7146e77a"] |
| 17:44 | sdegutis | justin_smith: oh right |
| 17:44 | sdegutis | you win |
| 17:44 | sdegutis | i always forget that |
| 17:45 | sdegutis | hmm mine says: #<main$eval1015$my_name__1016 cleancoders.web.main$eval1015$my_name__1016@2c34b4e> |
| 17:45 | sdegutis | hmm your says: #object[sandbox$eval73$my_name__74 0x1ff66d7d "sandbox$eval73$my_name__74@1ff66d7d"] |
| 17:45 | sdegutis | broken? |
| 17:45 | justin_smith | ,(nth (iterate #(%) (fn me-me-me-me [] me-me-me-me)) 1000000) |
| 17:45 | clojurebot | #object[sandbox$eval26$me_me_me_me__29 0x2d082452 "sandbox$eval26$me_me_me_me__29@2d082452"] |
| 17:55 | cljnoob2438 | hey everyone, just starting clojure. What is the most clojurey way to loop over user input for a command line application? Currently I just have a lein app project that i'd like to run (via lein run or lein trampoline run) and I'd like to be able to interact with user input. Any suggestions? Googling hasn't helped a ton |
| 17:56 | justin_smith | cljnoob2438: loop/recur would be a natural choice, using the args to carry any changed state that would come from user input |
| 17:57 | justin_smith | you can get user input via *in* |
| 17:59 | sdegutis | cljnoob2438: the most Clojure thing to do would be to not write a command line application in Clojure |
| 18:00 | sdegutis | cljnoob2438: check out https://github.com/pixie-lang/pixie |
| 18:00 | cljnoob2438 | Yeah. I was trying to recur an if-let on read-line, but I couldn't get it to work right =/ Still working on it |
| 18:01 | cljnoob2438 | Haha no room for scripting in clojure? |
| 18:01 | sdegutis | cljnoob2438: the JVM startup time is a killer |
| 18:02 | cljnoob2438 | Yeah I heard about cljs with node as an option for command line stuff. I guess I should check out that avenue. I'm still gonna try it until I get it to work. It's just for a little programming challenge, but it'd be nice even for a long running systems application that listens for calls from other applications. |
| 18:03 | cljnoob2438 | Like a log responder that tails files and runs some function if a certain regex match is hit (using the file as input instead of STDIN) |
| 18:09 | justin_smith | cljnoob2438: well, the normal cli thing would be to use *in*, and use piping right? |
| 18:09 | justin_smith | but I guess you could open files for tailing too, checkout out java.io.* |
| 18:10 | justin_smith | clojure's slow startup time shouldn't be a problem at all for a utility like that (and btw it has nothing to do with the jvm, it's a clojure problem) |
| 18:11 | cljnoob2438 | justin_smith: ok yeah I could try piping and just pipe echo'd input to it haha thanks |
| 18:11 | justin_smith | during development you could use eg. a StringReader |
| 18:12 | justin_smith | ,(line-seq (java.io.BufferedReader. (java.io.StringReader. "hello\nworld\r\nOK"))) ; reusing an example from earlier |
| 18:12 | clojurebot | ("hello" "world" "OK") |
| 18:12 | justin_smith | once you have a line-seq, you can just do a loop/recur calling rest, or even a reduce over all lines |
| 18:13 | justin_smith | ,(reduce #(conj % (first %2)) [] (line-seq (java.io.BufferedReader. (java.io.StringReader. "hello\nworld\r\nOK")))) |
| 18:13 | clojurebot | [\h \w \O] |
| 18:16 | sdegutis | If you change a defmulti's arity, YOU MUST RESTART THE JVM. |
| 18:16 | sdegutis | Just FWI. |
| 18:19 | justin_smith | sdegutis: or you can just run (def mymulti nil) followed by redefining the defmulti |
| 18:19 | sdegutis | now you tell me |
| 18:19 | sdegutis | you'd think defmulti would know to do this itself |
| 18:19 | justin_smith | sdegutis: that would fuck up a bunch of other things |
| 18:20 | justin_smith | the defmulti carries all its methods, imagine what a pain it would be if all your methods disappeared every time a multi was redefined |
| 18:20 | justin_smith | just incidentally because you reloaded a file and were not even trying to redefine the multimethod |
| 18:20 | sdegutis | justin_smith: presumably if it was redefined so would also be its definitions |
| 18:21 | justin_smith | sdegutis: they are in other namespaces |
| 18:21 | sdegutis | it should know to reload them |
| 18:21 | justin_smith | it should cause namespaces that are upstream on the dep graph to reload? that's just stupid |
| 18:21 | sdegutis | I was promised pain-free dynamic changes at runtime and OP did not deliver |
| 19:30 | kristof | Common Lisp does not have this problem. |
| 19:39 | TEttinger | Lua does not have this |
| 19:39 | TEttinger | (it isn't a keyword) |
| 21:06 | TEttinger | $seen akeep |
| 21:06 | lazybot | I have never seen akeep. |
| 21:06 | TEttinger | hm |
| 21:06 | TEttinger | he presented something rather neat at a conj |
| 21:43 | monsta | Good night |
| 21:44 | monsta | I having a hard time trying to translate this javascript function to clojurescript, can any body help? http://pastebin.com/S6ndkY21 |
| 21:45 | gcommer | Whats the issue you're having? |
| 21:46 | monsta | Not enough knowledge to write the clojurescript equivalent |
| 21:47 | gcommer | To what extent? |
| 21:47 | monsta | all |
| 21:47 | monsta | weel just the loop |
| 21:48 | gcommer | Which part of the loop? requestAnimationFrame? |
| 21:48 | monsta | I don't know how to write without braking my browser :8 |
| 21:48 | monsta | yes |
| 21:48 | gcommer | oh, so you've tried it and had it break your browser |
| 21:48 | gcommer | can you post what you have? and/or error messages you're getting |
| 21:49 | gcommer | (in a pastebin ofc) |
| 21:49 | monsta | give me a minute |
| 21:52 | monsta | Here is what I got so far http://pastebin.com/RfcdBui2, not really know what I am doing ;( |
| 21:53 | justin_smith | monsta: that's close |
| 21:53 | monsta | not enough |
| 21:54 | gcommer | is the code you pasted all in another function? |
| 21:54 | gcommer | i presume not |
| 21:54 | justin_smith | a couple simple things - you should be updating delta inside a call to recur, and to call fun, you need to wrap it in parens (fun) |
| 21:54 | monsta | ummmm |
| 21:54 | justin_smith | monsta: loop does not repeat anything unless you call recur |
| 21:55 | gcommer | are you sure you wanna use loop/recur in the cljs version? requestAnimationFrame in the JS |
| 21:55 | justin_smith | monsta: and delta should be changing on each step through the loop, so it needs to be reset on each call to recur |
| 21:55 | justin_smith | gcommer: oh, good point |
| 21:55 | monsta | Oh, I think that in the clojure doc or in a blog post long time ago I saw a example of loop with recur, I though it would work :( |
| 21:56 | gcommer | loop/recur is a good strategy for doing loops in clojure |
| 21:56 | gcommer | in general |
| 21:56 | justin_smith | monsta: the thing is, your js doesn't have a loop |
| 21:56 | gcommer | but requestAnimationFrame is special and should be used for what you're doing in browser-based code |
| 21:56 | monsta | ok |
| 21:56 | monsta | How do a make it a proper loop |
| 21:57 | monsta | I am connected to figwheel right now |
| 21:57 | justin_smith | monsta: just use requestAnimationFrame just like you do in the js version |
| 21:57 | monsta | My mind is not a good parser ;( |
| 21:57 | justin_smith | monsta: gcommer is right, that would be the way to do a loop, but this code shouldn't be a loop |
| 21:57 | monsta | Ok atleas I know that the loop does not suppose to work that way |
| 21:58 | justin_smith | ,(loop [i 0] (if (> i 10) i (recur (* 2 i)))) |
| 21:58 | justin_smith | oops! |
| 21:58 | clojurebot | eval service is offline |
| 21:58 | justin_smith | ,(loop [i 1] (if (> i 10) i (recur (* 2 i)))) |
| 21:58 | clojurebot | 16 |
| 21:58 | monsta | but where the requestAnimation is left? |
| 21:59 | justin_smith | monsta: you want something like (fn lp [time] (js/requestAnimationFrame lp) ...) |
| 21:59 | justin_smith | I intentionally did not use the name loop, since that is its own thing in clojure |
| 21:59 | monsta | what is lp? |
| 22:00 | monsta | o ok |
| 22:00 | monsta | immmm |
| 22:00 | justin_smith | monsta: a name, you can replace it with any name you'd like to use |
| 22:00 | gcommer | such as monstaLoopIsAwesome |
| 22:00 | justin_smith | monsta: I changed the name from loop since loop is special in cljs |
| 22:00 | justin_smith | sure |
| 22:00 | monsta | Ok hmmmmmmmmmmmmm |
| 22:01 | monsta | I will keep trying, but the insight helped a lot, thanks |
| 22:02 | justin_smith | monsta: are you reading a book or doing any simpler exercises? |
| 22:02 | justin_smith | because otherwise, this might be a daunting place to start |
| 22:02 | monsta | Yes, is a book about game with js |
| 22:02 | justin_smith | I mean a cljs book, or some simpler cljs exercises |
| 22:03 | monsta | Well no, only the docs |
| 22:03 | monsta | and blogpost |
| 22:03 | monsta | s |
| 22:05 | justin_smith | monsta: it's entirely up to your judgment, of course, but just be aware it would be a lot easier if you find some good intro cljs materials |
| 22:06 | justin_smith | monsta: for example there's the book "clojurescript up and running" from o'reilly |
| 22:06 | monsta | Not many around, most of then use Om or some funky libraries that I am not really interested baout |
| 22:06 | monsta | I will check on that |
| 22:07 | justin_smith | monsta: also these tutorials are worth checking out https://github.com/magomimmo/modern-cljs |
| 22:07 | monsta | That too |
| 23:00 | WickedShell | I have warn on reflection on, and outside of some reflections in dependencies (particularly clj-complete (which I don't even know how it is in the dependency tree)) I'm seeing very large number of java.lang.reflect.Method's build up slowly eating all available memory. Is there a way to track what is causing these at runtime? |
| 23:00 | amalloy | lein repl includes clojure-complete |
| 23:01 | amalloy | and tools.nrepl |
| 23:02 | WickedShell | Alright, so I can probably safely ignore it, I'm using the lein repl so I shouldn't actually see its effects in builds then. (all though builds do slowly climb to 4million+ instances of java.lang.reflect.Method) |
| 23:02 | amalloy | and this persists between GC cycles? |
| 23:03 | WickedShell | it's reset between GC cycles, but its causing the GC to run far more often, and problematically on JDK8 on windows I'm seeing total heap size for the JVM grow at every GC until it crashes eventually |
| 23:04 | WickedShell | which seems somewhat like an error in the JVM since theres always still 500MB free at the time... |
| 23:05 | amalloy | i mean 4M+ seems like a lot to me, but who knows. lots of garbage gets generated by clojure. if you're seeing the heap size grow higher than you want it to go, set a max heap size in the vm parameters |
| 23:05 | amalloy | as long as all the garbage is transient it is likely not worth worrying about |
| 23:06 | WickedShell | probably... I'm somewhat worried about performance on low end devices but you're probably right... Can you control VM settings from within java/clojure code? I've only ever set them as launch options... |
| 23:07 | amalloy | no |
| 23:07 | WickedShell | It just seems to me like I should be able to chase down all the sources of reflcetion fairly easily since its allocating 1MB+ per second (nothing else grows anywhere near as fast) |
| 23:08 | amalloy | i presume you could inspect one of the Method values from a heap snapshot to see what method it represents |
| 23:08 | amalloy | well. i guess i assumed you were using a profiler |
| 23:08 | amalloy | if you're not, then you should do that |
| 23:09 | WickedShell | I'm using the jvisualvm as the profiler |
| 23:09 | WickedShell | took a snapshot from the sampler and I can't inspect... maybe if I attach in profile mode... That's worth checking out |
| 23:11 | WickedShell | All it wants to tell me is that no source was found for the class? |
| 23:12 | amalloy | you should be able to inspect its members. visualvm isn't the profiler i use, but that information is certainly available |
| 23:13 | WickedShell | I'm open to suggestions on other profilers, its just the first one I found (that was free) |
| 23:14 | WickedShell | ah, heapdump not snapshot |