2015-08-05
| 00:01 | lsdfajklsd | test |
| 00:01 | lsdfajklsd | rhaywood: yt? |
| 00:01 | justin_smith | ran 0 tests with 0 assertions, 0 fails, 0 errors |
| 00:02 | lsdfajklsd | rhaywood: (+ 1 1) |
| 02:54 | tdammers | hi... is this the right place for questions about clojurescript and figwheel? |
| 02:56 | Empperi | ok place, but #clojurescript is better |
| 02:57 | tdammers | aight |
| 08:35 | tgoossens | How do I typehint a 2d array? |
| 08:37 | justin_smith | , (into-array [(into-array [5])]) |
| 08:37 | clojurebot | #object["[[Ljava.lang.Long;" 0x5d642c1f "[[Ljava.lang.Long;@5d642c1f"] |
| 08:37 | justin_smith | "[[Ljava.lang.Long;", though the java.lang.Long part is variable of course |
| 08:38 | justin_smith | "[[Lfoo'\;" |
| 08:38 | justin_smith | you can use the string where normally you would provide a class or keyword |
| 08:42 | tgoossens | justin_smith, again my hero of the day thanks! |
| 08:53 | snowell | (inc justin_smith) |
| 08:53 | lazybot | ⇒ 284 |
| 08:54 | hellofunk | what is easiest way to build binary number of arbitrary length with all bits turned on? |
| 08:54 | hellofunk | i.e. if i need length it builds 2r11111 |
| 08:54 | hellofunk | length 5 |
| 08:56 | chouser | ,(Long/toBinaryString (- (bit-shift-left 1 5) 1)) |
| 08:57 | clojurebot | "11111" |
| 09:00 | justin_smith | ,(read-string (apply str "2r" (repeat 5 1))) ; less elegant |
| 09:00 | clojurebot | 31 |
| 09:00 | justin_smith | err |
| 09:01 | hellofunk | justin_smith: that is the correct result |
| 09:01 | hellofunk | just not printing as binary |
| 09:01 | hellofunk | which is fine |
| 09:01 | justin_smith | hellofunk: ahh, right |
| 09:01 | justin_smith | the bit-shift is probably two orders of magnitude faster :) |
| 09:01 | hellofunk | i suspect there is still a clever elegant option to using xor |
| 09:02 | hellofunk | I was thinking that 2r100000... xor with 0 will always be 2r011111.... |
| 09:02 | hellofunk | wait |
| 09:02 | hellofunk | i mean bit-not, not xor |
| 09:03 | hellofunk | i should not think out loud |
| 09:04 | blackbird_ | I have a line like (def tmc (client/text-connection (env :cache-endpoint))) When doing like `lein ring uberwar`, this fails because the env variable doesn't exist there and it attempts to create a connection to nil. Is there a general patterin for dealing with this type of thing? |
| 09:05 | hellofunk | i think i'll go with the chouser offering |
| 09:05 | chouser | Don't be too hasty. There may be benefits to the string-manipulation version that we haven't thought of yet. ;-) |
| 09:06 | justin_smith | blackbird_: the easy way is (def tmc (delay (clien/text-connection ...))) and then use @tmc where you would use tmc |
| 09:06 | justin_smith | blackbird_: the super proper way is to use stuartsierra/component for resources that are stateful |
| 09:06 | chouser | ,(nth (iterate #(+ 1 (* 10 %)) 1) 5) |
| 09:06 | clojurebot | 111111 |
| 09:07 | chouser | oh, whoops, that's base 10 |
| 09:07 | chouser | (Long/toBinaryString (nth (iterate #(+ 1 (* 2 %)) 1) 5)) |
| 09:07 | chouser | ,(Long/toBinaryString (nth (iterate #(+ 1 (* 2 %)) 1) 5)) |
| 09:07 | clojurebot | "111111" |
| 09:08 | blackbird_ | justin_smith: ahh cool. component way seems like overkill for one def, thanks for the tip |
| 09:09 | chouser | ,(Long/toBinaryString (eval (read-string (nth (iterate #(str "(+ 1 (* 2 " % "))") 1) 5)))) |
| 09:09 | clojurebot | "111111" |
| 09:09 | opqdonut | ,(Long/toBinaryString (dec (bit-shift-left 1 6))) |
| 09:09 | clojurebot | "111111" |
| 09:10 | opqdonut | oh that was mentioned already ages ago |
| 09:10 | justin_smith | the bit-shift/dec combo is the best though |
| 09:10 | chouser | opqdonut: dec, of course! |
| 09:10 | chouser | nicely done |
| 09:10 | opqdonut | well it's actually the same number of characters as - 1 :) |
| 09:11 | chouser | hm, true. I prefer dec. |
| 09:15 | opqdonut | me too |
| 09:16 | opqdonut | I even use it on floats, but feel a bit dirty afterwards |
| 09:17 | justin_smith | ,(dec (/ 131 7)) |
| 09:17 | clojurebot | 124/7 |
| 09:20 | justin_smith | ,(inc (/ 17 7)) ; how I rock it |
| 09:20 | clojurebot | 24/7 |
| 09:34 | tgoossens | How (using leiningen) can I compile java and clojure code AND have a java class use a class generated by clojure gen-class. |
| 09:34 | tgoossens | This is a problem since java is compiled first and then clojure |
| 09:34 | tgoossens | but in this particular case, clojure should be compiled before this one class |
| 09:34 | tgoossens | can I express such things in leiningen? |
| 09:35 | gfredericks | tgoossens: do you know for sure that you have to structure it that way? there are other ways of calling clojure code from java code |
| 09:35 | gfredericks | that don't require that order of compilation |
| 09:35 | hyPiRion | tgoossens: https://github.com/hyPiRion/multicompile-example |
| 09:36 | hyPiRion | essentially just do prep-task modifications |
| 09:39 | chouser | or move the gen-class code to another "project" and bring it in as a lein dep |
| 09:42 | TimMc | or use make |
| 09:47 | tgoossens | I added it as a Junit test (which in the end made more sense) |
| 09:54 | TimMc | fascinating |
| 09:54 | TimMc | Was it in fact a test? |
| 10:01 | wes_ | hello. I've got a question if you've got time. |
| 10:02 | justin_smith | wes_: on IRC you don't need to ask, you can just ask |
| 10:02 | namra | wes_: just ask ^^ |
| 10:02 | namra | ^^ |
| 10:04 | wes__ | I want to apply a function to a seq with an init value and use the result of the function as the init value for the following iterations. |
| 10:04 | justin_smith | wes_: that's reduce |
| 10:05 | justin_smith | ,(reduce + 2 [3 4 5]) |
| 10:05 | clojurebot | 14 |
| 10:05 | gfredericks | ,(reduce str 2 [3 4 5]) |
| 10:05 | clojurebot | "2345" |
| 10:05 | gfredericks | ,(reduce - 2 [3 4 5]) |
| 10:05 | clojurebot | -10 |
| 10:05 | gfredericks | ,(reduce / 2 [3 4 5]) |
| 10:05 | clojurebot | 1/30 |
| 10:05 | justin_smith | ,(reduce conj [] [7 8 9]) |
| 10:05 | clojurebot | [7 8 9] |
| 10:05 | gfredericks | ,(reduce vector 2 [3 4 5]) |
| 10:05 | clojurebot | [[[2 3] 4] 5] |
| 10:06 | justin_smith | ,(reduce conj () [7 8 9]) |
| 10:06 | clojurebot | (9 8 7) |
| 10:06 | gfredericks | ,(reduce hash-set 2 [3 4 5]) |
| 10:06 | clojurebot | #{#{4 #{3 2}} 5} |
| 10:06 | justin_smith | yeah, reduce is the greatest |
| 10:06 | gfredericks | (reduce reduce ? [? ? ?]) ;; ← make this work |
| 10:06 | wes__ | (defn move-up [map vec-of-maps index] ...) -> new vec-of-maps with item moved to index |
| 10:07 | wes__ | (reduce move-up vec-of-maps seq-of-maps) <---- this turns some of my maps into vectors of [k v] |
| 10:07 | gfredericks | ,(reduce reduce conj [[1 2 3] [4 5 6] [7 8 9]]) |
| 10:07 | clojurebot | #error {\n :cause "java.lang.Long cannot be cast to clojure.lang.IPersistentCollection"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Long cannot be cast to clojure.lang.IPersistentCollection"\n :at [clojure.core$conj__4104 invokeStatic "core.clj" 82]}]\n :trace\n [[clojure.core$conj__4104 invokeStatic "core.clj" 82]\n [clojure.core$conj__4104 invoke "core.clj" -1]\n [c... |
| 10:07 | gfredericks | dangit |
| 10:08 | gfredericks | ,(reduce reduce + [[1 2 3] [4 5 6] [7 8 9]]) |
| 10:08 | clojurebot | #error {\n :cause "java.lang.Long cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Long cannot be cast to clojure.lang.IFn"\n :at [clojure.core$reduce invokeStatic "core.clj" 6516]}]\n :trace\n [[clojure.core$reduce invokeStatic "core.clj" 6516]\n [clojure.core$reduce invoke "core.clj" -1]\n [clojure.lang.PersistentVector reduce "Persist... |
| 10:08 | justin_smith | wes__: it would do that if seq-of-maps was actually a map |
| 10:08 | gfredericks | welp I give up |
| 10:08 | justin_smith | wes__: also, how are you giving a three-arg function to reduce? |
| 10:09 | wes__ | woops. move-up takes two args [item coll] and uses (.indexOf coll item) to call insert-at.... |
| 10:11 | justin_smith | so you have a vector of maps, and a seq of maps, and your reduce is to take each item in the seq of maps and find its position in the vector and then... |
| 10:12 | tgoossens | in leiningen with ':aot' how do I set two values? |
| 10:13 | justin_smith | tgoossens: so you have two totally unrelated namespaces that should be aot compiled? aot is transitive, so aot compiling an ns also aot compiles all its deps |
| 10:13 | wes__ | move-up takes a single map and a vector of maps, finds the index of the item in the vector and produces a new vector of maps in which the item resides at (dec index) |
| 10:13 | hyPiRion | tgoossens: what do you mean by two values? :aot [myns.first myns.second] will compile both namespaces, regardless of their dependency to one or another |
| 10:13 | tgoossens | hyPiRion, |
| 10:14 | justin_smith | wes__: OK, that should totally work |
| 10:14 | tgoossens | hyPiRion, That is what i mean |
| 10:14 | hyPiRion | ah, nice |
| 10:14 | tgoossens | thanks :) |
| 10:14 | wes__ | so, (reduce move-up seq-of-items vec-of-maps) ?? |
| 10:14 | lazybot | wes__: Uh, no. Why would you even ask? |
| 10:15 | justin_smith | wes__: the vec should come before the seq |
| 10:15 | justin_smith | since you can't update a seq by index |
| 10:16 | wes__ | ok, i'll give it a go. |
| 10:16 | justin_smith | and more generally, reduce takes its accumulator before the sequence it walks |
| 10:20 | Olajyd_ | Please how can I compare date-values in clojure to determine which is greater? |
| 10:20 | justin_smith | Olajyd_: compare |
| 10:20 | justin_smith | ,(java.util.Date. 0) |
| 10:20 | clojurebot | #inst "1970-01-01T00:00:00.000-00:00" |
| 10:20 | justin_smith | ,(java.util.Date.) |
| 10:20 | clojurebot | #inst "2015-08-05T14:21:01.504-00:00" |
| 10:21 | justin_smith | ,(compare (java.util.Date.) (java.util.Date. 0)) |
| 10:21 | clojurebot | 1 |
| 10:21 | pbx | nice demo justin_smith |
| 10:21 | justin_smith | heh, thanks |
| 10:23 | gfredericks | $google gfredericks compare |
| 10:23 | lazybot | [gfredericks (Gary Fredericks) · GitHub] https://github.com/gfredericks |
| 10:23 | gfredericks | well https://github.com/gfredericks/compare |
| 10:24 | gfredericks | if you don't like writing your own -1/0/1 logic |
| 10:24 | justin_smith | gfredericks: handy! |
| 10:24 | oddcully | and if you don't need it for sorting, there is also .before/.after |
| 10:24 | gfredericks | justin_smith: !!! |
| 10:25 | wes__ | So, I tried this and it gives a vector of vector of vector of maps |
| 10:26 | sdegutis | Given (defn foo [x y z] ...) and (defn bar [x y] (foo x y z)), how can I redefine bar so to remove the parameter redundancy? |
| 10:27 | sdegutis | Hi. |
| 10:29 | sdegutis | I thought it would have something to do with partial, but nope. |
| 10:29 | wes__ | (move-up 'b ['a 'b 'c]) => [b a c] |
| 10:29 | justin_smith | wes__: (defn move-up [v i] (let [pos (.indexOf v i)] (if (pos? pos) (-> v (assoc pos (v (dec pos))) (assoc (dec pos) i)) v))) |
| 10:29 | justin_smith | wes__: needed the if for cases where i is not in the vec, or i is already at position 0 |
| 10:30 | sdegutis | Clearer definitions are probably (defn foo [x y z] ...) and (defn bar [x y] (foo x y "some z")), |
| 10:30 | justin_smith | ,(defn move-up [v i] (let [pos (.indexOf v i)] (if (pos? pos) (-> v (assoc pos (v (dec pos))) (assoc (dec pos) i)) v))) |
| 10:30 | clojurebot | #'sandbox/move-up |
| 10:30 | justin_smith | ,(move-up 'b '[a b c]) |
| 10:30 | clojurebot | #error {\n :cause "No matching method found: indexOf for class clojure.lang.Symbol"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No matching method found: indexOf for class clojure.lang.Symbol"\n :at [clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 53]}]\n :trace\n [[clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 53]\n [clojure.lang.Reflector invo... |
| 10:30 | justin_smith | ,(move-up '[a b c] 'b) |
| 10:30 | clojurebot | [b a c] |
| 10:30 | justin_smith | oops I flibbed your args |
| 10:30 | justin_smith | but it works otherwise :) |
| 10:30 | perplexa | :D |
| 10:32 | justin_smith | shorter: (defn move-up [v i] (let [pos (.indexOf v i)] (if (pos? pos) (assoc v pos (v (dec pos)) (dec pos) i) v))) |
| 10:33 | justin_smith | wes__: I recommend that arg order, because the idiom in clojure is that the associative item comes first |
| 10:33 | justin_smith | wes__: and even more important, the rules of reduce says the accumulator (the vector) must be the first arg |
| 10:34 | perplexa | ,(move-up '[a b c] 'c) |
| 10:34 | clojurebot | #error {\n :cause "Unable to resolve symbol: move-up in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: move-up in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: move-up i... |
| 10:34 | justin_smith | ,(defn move-up [v i] (let [pos (.indexOf v i)] (if (pos? pos) (assoc v pos (v (dec pos)) (dec pos) i) v))) |
| 10:34 | clojurebot | #'sandbox/move-up |
| 10:34 | perplexa | ,(move-up '[a b c] 'c) |
| 10:34 | clojurebot | [a c b] |
| 10:34 | justin_smith | now try - clojurebot is forgetful :) |
| 10:34 | perplexa | hehe |
| 10:34 | perplexa | alzheimerbot ;p |
| 10:35 | wes__ | oh, so to write a function that is reducable, I've got to have the accumulator as the first argument? |
| 10:35 | justin_smith | yes, always |
| 10:35 | Olajyd | @justin_smith: How can i comapre date values in clojure? |
| 10:35 | wes__ | Thanks. That's a great help. |
| 10:35 | sdegutis | Wait! |
| 10:35 | sdegutis | Is this even possible!? |
| 10:35 | justin_smith | Olajyd: didn't I just show that above? |
| 10:36 | justin_smith | Olajyd: the compare function will return -1, 0, or 1 depending on how two dates compare |
| 10:36 | sdegutis | I actually have this: (defn change [db entity attr value] ...) and (defn change-text [db entity value] (change db entity :text value)) |
| 10:36 | sdegutis | Can I simplify the definition of change-text at all? |
| 10:37 | sdegutis | I tried using partial but I must be doing it wrong because that helps naught. |
| 10:37 | sdegutis | *not |
| 10:37 | justin_smith | sdegutis: maybe flatland/useful has some kind of flipped partial |
| 10:37 | justin_smith | sdegutis: partial works from the wrong direction for your code |
| 10:38 | sdegutis | Ahh right, I have to fill in the innards when I don't have them yet. |
| 10:38 | Olajyd | @justin_smith.. I’m sorry can’t find the compare function, is it the `move-up` function you wrote? |
| 10:38 | justin_smith | Olajyd: it's called "compare" |
| 10:38 | oddcully | ,(doc compare) |
| 10:38 | clojurebot | "([x y]); Comparator. Returns a negative number, zero, or a positive number when x is logically 'less than', 'equal to', or 'greater than' y. Same as Java x.compareTo(y) except it also works for nil, and compares numbers and collections in a type-independent manner. x must implement Comparable" |
| 10:38 | justin_smith | Olajyd: I literally showed how to use compare right after you asked the first time |
| 10:39 | justin_smith | ,(compare (java.util.Date.) (java.util.Date. 0)) |
| 10:39 | clojurebot | 1 |
| 10:39 | justin_smith | that result means the first one was greater |
| 10:39 | Olajyd | @justin_smith I’m sorry i got disconnected when I asked the first time :) |
| 10:39 | justin_smith | oh, OK |
| 10:40 | justin_smith | I have joins/parts/disconnects turned off on this channel, it's too noisy otherwise |
| 10:40 | oddcully | Olajyd: there is also a log: http://clojure-log.n01se.net/ |
| 10:41 | Olajyd | @oddcully Thanks for helping me out on saturday :) |
| 10:42 | oddcully | yw, but i forgot ;) |
| 10:43 | Olajyd | @oddcully : I have a vector of dates in the format (yyyy/MM/dd) and I want to be able to get the maximum date using `reduce` |
| 10:43 | justin_smith | Olajyd: you could also use max-key |
| 10:43 | gilliard | Olajyd: that date format will sort lexicographically, if they're strings. |
| 10:44 | justin_smith | , (apply max-key #(.getTime %) [(java.util.Date. 0) (java.util.Date. 1) (java.util.Date. 2)]) |
| 10:44 | Olajyd | really @gilliard |
| 10:44 | clojurebot | #inst "1970-01-01T00:00:00.002-00:00" |
| 10:44 | justin_smith | Olajyd: the above will always return the largest date in a sequence |
| 10:45 | oddcully | dates in the "formst X" are just strings right? |
| 10:45 | justin_smith | oh, I thought you meant you had real dates (as in java.util.Date.) |
| 10:45 | gilliard | ,(max ["2015/5/2" "2015/11/10" "2010/20/9"]) |
| 10:45 | clojurebot | ["2015/5/2" "2015/11/10" "2010/20/9"] |
| 10:45 | gilliard | ,(apply max ["2015/5/2" "2015/11/10" "2010/20/9"]) |
| 10:45 | clojurebot | #error {\n :cause "java.lang.String cannot be cast to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.String cannot be cast to java.lang.Number"\n :at [clojure.lang.Numbers gt "Numbers.java" 229]}]\n :trace\n [[clojure.lang.Numbers gt "Numbers.java" 229]\n [clojure.lang.Numbers max "Numbers.java" 4027]\n [clojure.core$max invokeStatic "core.clj" 1091]\n ... |
| 10:45 | justin_smith | gilliard: first of sort |
| 10:45 | oddcully | shouldn't this be just be the last of a string sort? |
| 10:45 | gilliard | justin_smith: you got it ;) |
| 10:45 | justin_smith | oddcully: oh right, or first of a reversed sort |
| 10:46 | justin_smith | or a reduce using compare (compare works on strings) |
| 10:46 | oddcully | at least of MM/dd is actually used (leading zeros) |
| 10:48 | justin_smith | ,(reduce #(case (compare % %2) 1 % -1 %2 0 %1) ["1970/02/11" "1914/03/01" "0000/00/00"]) |
| 10:48 | clojurebot | #error {\n :cause "No matching clause: 6"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No matching clause: 6"\n :at [sandbox$eval102$fn__103 invoke "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval102$fn__103 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.PersistentVector reduce "PersistentVector.java" 323]\n [clojure.core$reduce invokeStatic "core.clj" 6517]\n [clojure.core$re... |
| 10:48 | justin_smith | err |
| 10:48 | justin_smith | compare can return 6, OK |
| 10:49 | oddcully | `Returns a negative number, zero, or a positive number...` |
| 10:49 | gilliard | ye just 0, more than 0, or less than 0 |
| 10:49 | justin_smith | ,(reduce #(if (pos? (compare % %2)) %1 %2) ["1970/02/11" "1914/03/01" "0000/00/00"]) |
| 10:49 | clojurebot | "1970/02/11" |
| 10:49 | Olajyd | thanks @justin_smith :) |
| 10:52 | justin_smith | Olajyd: the funny part is that my initial answer still works even though I was wrong about your data type, because compare is just that general |
| 10:52 | Olajyd | @justin_smith the solution works for me |
| 10:52 | Olajyd | :) |
| 10:52 | oddcully | random fun wikipedia fact: on 1914-03-01 china joined the Universal Postal Union |
| 10:54 | justin_smith | haha |
| 10:58 | wes__ | justin_smith Using your move-up works (move-up [f1 f2 f3] f2) => [f2 f1 f3] but (reduce [f1 f2 f3] '(f2 f3)) => [f1 f2 f3] where I expect [f2 f3 f1] |
| 10:59 | justin_smith | wes__: hmm |
| 10:59 | justin_smith | wes__: it works? |
| 11:00 | justin_smith | , (defn move-up [v i] (let [pos (.indexOf v i)] (if (pos? pos) (assoc v pos (v (dec pos)) (dec pos) i) v))) |
| 11:00 | clojurebot | #'sandbox/move-up |
| 11:00 | justin_smith | , (reduce move-up '[f1 f2 f3] '(f2 f3)) |
| 11:00 | clojurebot | [f2 f3 f1] |
| 11:04 | wes__ | justin_smith yeah, it works thanks. I just learned that '(f2 f3) is not the same as (list f2 f3) |
| 11:05 | justin_smith | oh, yeah :) |
| 11:06 | justin_smith | [f2 f3] works too - reduce can accept vectors, anything that seq works on |
| 11:41 | wes__ | So, I got move-down working as well, but I discovered that the order of the items in the reduce function is important. How do I sort a seq by their index in a vector? |
| 11:44 | wes__ | (sort #(.indexOf '[f1 f2 f3 f4 f5] %) '(f3 f5 f1)) |
| 11:45 | justin_smith | ,(sort-by #(.indexOf '[f1 f2 f3 f4 f5] %) '(f3 f5 f1)) |
| 11:46 | clojurebot | (f1 f3 f5) |
| 11:46 | jonathanj | hrm, how would i write a function that wraps another function and logs its arguments to a file? i tried: (defn log-to [path f] (with-open [fd (writer path)] (fn [s] (spit fd s) (f s)))) |
| 11:46 | jonathanj | but i guess (with-open) closes as soon as log-to returns |
| 11:46 | justin_smith | jonathanj: yeah, only use with-open if you want to close the file in that block |
| 11:47 | justin_smith | jonathanj: otherwise you can use .write, and make your own arrangements to close the file... |
| 11:47 | wes__ | Missed it by `that` much. thanks |
| 11:47 | justin_smith | wes__: yes, you were quite close |
| 11:47 | jonathanj | okay, well as a crappy interim measure i can just open the file and write to it everytime the inner function is invoked, how do i open a file for appending? |
| 11:47 | justin_smith | wes__: do you ever look at http://conj.io ? |
| 11:48 | justin_smith | jonathanj: it's an optional arg to writer |
| 11:48 | justin_smith | ,(doc clojure.java.io/writer) |
| 11:48 | clojurebot | "([x & opts]); Attempts to coerce its argument into an open java.io.Writer. Default implementations always return a java.io.BufferedWriter. Default implementations are provided for Writer, BufferedWriter, OutputStream, File, URI, URL, Socket, and String. If the argument is a String, it tries to resolve it first as a URI, then as a local file name. URIs with a 'file' protocol are converted to local... |
| 11:48 | wes__ | justin_smith no. Thanks for showing it to me. |
| 11:49 | jonathanj | i'm reading the docs for writer but there is apparently no mention of what the arguments are? |
| 11:49 | justin_smith | wes__: I asked because with the way conj.io is layed out, you likely would have found sort-by :) |
| 11:49 | jonathanj | the optional arguments, i mean |
| 11:49 | justin_smith | jonathanj: hmm, I know they are around somewhere |
| 11:49 | jonathanj | looks like it's just :append |
| 11:49 | jonathanj | (looking at an example on conj.io) |
| 11:50 | justin_smith | jonathanj: source reveals it https://github.com/clojure/clojure/blob/master/src/clj/clojure/java/io.clj#L69 |
| 11:50 | jonathanj | :append true, at least |
| 11:50 | justin_smith | jonathanj: useful site :) |
| 11:51 | jonathanj | what are the differences between conj.io and clojuredocs? |
| 11:51 | justin_smith | jonathanj: different maintainers, conj.io is more ambitious |
| 11:51 | jonathanj | how so? |
| 11:52 | justin_smith | it wants to document libs outside of clojure itself eventually |
| 11:52 | jonathanj | ah, nice |
| 11:52 | justin_smith | jonathanj: arrdem and andyf could probably tell you about the differences in more detail (they maintain the two sites) |
| 12:00 | jonathanj | i remember some clojure library that implemented a grammar-based parser based on BNF (or something that was really close to it), but i can't remember the name of the library |
| 12:01 | jonathanj | oh instaparse |
| 12:01 | justin_smith | instaparse? |
| 12:01 | blkcat | instaparse? |
| 12:01 | clojurebot | instaparse is lovely |
| 12:01 | clojurebot | instaparse is lovely |
| 12:01 | justin_smith | hahaha |
| 12:01 | blkcat | i use instaparse and can confirm that it rocks |
| 12:01 | justin_smith | ^ the beginning of a musical about parsing |
| 12:01 | justin_smith | (to the tune of "monorail" of course) |
| 12:26 | jonathanj | so if i have an instaparse rule like `word = letter+ <letter> = #'[a-zA-Z]'` i end up with :word ["h" "e" "l" "l" "o"] |
| 12:27 | jonathanj | it looks like the preferred way to turn that into a string is `(transform {:word str} ...)`? |
| 12:27 | jonathanj | i can't indicate this in the grammar some how? |
| 12:28 | sdegutis | I just used clojure.data/diff |
| 12:28 | sdegutis | and clojure.set/map-invert, I bet you didn't even know it existed! |
| 12:30 | jonathanj | the problem i guess is that (transform {:word str} ...) turns [:word ["h" "i"]] into "hi", i'd prefer not to destroy the tag |
| 12:32 | alex_engelberg | jonathanj: I'm missing context (just joined channel) but I may be able to help with your instaparse problem |
| 12:32 | jonathanj | alex_engelberg: hello! |
| 12:32 | jonathanj | alex_engelberg: firstly, instaparse is a wonderful piece of software, thank you very much |
| 12:33 | alex_engelberg | thank you! and thank YOU for using it! :) |
| 12:33 | sdegutis | My task this week is to write a parser via a purely immutable state machine. |
| 12:34 | alex_engelberg | I'm an IRC noob, is there a way to look at previous messages before I joined? |
| 12:34 | alex_engelberg | Or is the solution to just always stay logged in? :) |
| 12:34 | sdegutis | alex_engelberg: neither |
| 12:34 | arohner | alex_engelberg: yes, stay logged in. There are also bot loggers |
| 12:34 | sdegutis | http://logs.lazybot.org/irc.freenode.net/%23clojure |
| 12:34 | sdegutis | alex_engelberg: just use that link. only works for here. |
| 12:34 | jonathanj | alex_engelberg: i'd like not to destroy the tag being transformed |
| 12:34 | arohner | http://clojure-log.n01se.net/ |
| 12:34 | oddcully | alex_engelberg: http://clojure-log.n01se.net/ |
| 12:34 | sdegutis | arohner: I prefer lazybot's |
| 12:34 | alex_engelberg | Thanks |
| 12:34 | oddcully | alex_engelberg: and instaparse is fscking awesome! |
| 12:35 | jonathanj | alex_engelberg: (insta/transform {:word str} [:word "h" "i"]) ends up losing the structure |
| 12:35 | sdegutis | oddcully: instaparse has nothing to do with checking or interactively repairing filesystem consistency |
| 12:35 | alex_engelberg | jonathanj: you want [:word "hi"]? |
| 12:35 | jonathanj | i realise i can probably do something like {:word (put-the-tag-back :word str)} but i'd like to avoid repeating myself if it's possible |
| 12:36 | jonathanj | alex_engelberg: yes |
| 12:36 | alex_engelberg | You could cleverly write your grammar with extra layers that are transformed in different ways |
| 12:36 | alex_engelberg | word = word2 |
| 12:36 | alex_engelberg | word2 = #'[a-z]+' |
| 12:36 | alex_engelberg | And just transform word2 |
| 12:36 | jonathanj | so produce something like [:word [:letters "h" "i"]] and transform letters with str? |
| 12:37 | alex_engelberg | yes. |
| 12:38 | alex_engelberg | I don't know enough about instaparse innards to know how much slower that would make the parser. The "put-the-tag-back" transformer would be the best place to do that work, efficiency-wise. I'd say it's probably a negligible difference though. |
| 12:39 | jonathanj | i guess that could work |
| 12:39 | jonathanj | thanks |
| 12:40 | alex_engelberg | jonathanj: no problem |
| 12:40 | alex_engelberg | I'm seeing a potential bug with clojure.tools.reader and cljs.tools.reader. |
| 12:41 | alex_engelberg | (clojure.tools.reader/read-string "018") => null pointer exception |
| 12:42 | alex_engelberg | Note that this is an invalid octal number, and throws a more user friendly number format exception in clojure.lang.LispReader. |
| 12:42 | alex_engelberg | On cljs (and I'm not sure this is a bug or a feature), (cljs.tools.reader/read-string "018") => 18 |
| 12:42 | alex_engelberg | In other words, invalid octal numbers are simply parsed as decimal. |
| 12:45 | alex_engelberg | For comparison, (clojure.tools.reader/read-string "017") => 15, and same with cljs |
| 13:25 | puredanger | you could use that as a really weird platform detector |
| 13:26 | Bronsa | alex_engelberg: definitely a bug |
| 13:29 | justin_smith | puredanger: heh, for when cljc is just too easy |
| 13:34 | Bronsa | alex_engelberg: fixed in tools.reader master |
| 13:57 | jonathanj | i know that ztellman's libraries aren't terribly popular here but can anyone suggest why i might want to use core.async over manifold streams? |
| 13:58 | justin_smith | jonathanj: what makes you think his libs are unpopular? |
| 13:58 | justin_smith | jonathanj: core.async is inherently "push", manifold can do push or pull |
| 13:58 | justin_smith | (that's one reason) |
| 13:58 | jonathanj | justin_smith: i just don't see a lot of conversation around them here |
| 13:59 | jonathanj | and the mailing lists are very low volume |
| 13:59 | jonathanj | well, the aleph list anyway, i don't even think there are lists for his other libraries |
| 13:59 | justin_smith | jonathanj: ztellman did a great talk at the last conj comparing manifold, core.async, and prismatic/graph that explains them all on a continuum of design |
| 13:59 | amalloy | jonathanj: higher volume than most other clojure libraries, which have no ML at all |
| 14:00 | jonathanj | justin_smith: oh that sounds pretty great, i don't suppose you have a link or title of the talk for me? |
| 14:00 | justin_smith | jonathanj: if you really want to understand how manifold relates to core.async, I'd check out that talk - it's on youtube |
| 14:00 | amalloy | justin_smith: i don't quite understand what you mean by core.async being push-only |
| 14:00 | justin_smith | $google ztellman manifold clojure conj |
| 14:00 | lazybot | [Clojure/conj 2014 Notes - Forays into simplicity] http://eigenhombre.com/clojure/2014/11/27/conj-notes/ |
| 14:00 | amalloy | like you can only push things into channels, and you can only pull things out, right? |
| 14:01 | jonathanj | justin_smith: i'm guessing that's not the one? |
| 14:01 | justin_smith | jonathanj: it's on youtube, one moment |
| 14:01 | jonathanj | https://www.youtube.com/watch?v=1bNOO3xxMc0 ? |
| 14:02 | justin_smith | nope, that's from clojure/west |
| 14:02 | justin_smith | jonathanj: this one https://www.youtube.com/watch?v=3oQTSP4FngY |
| 14:02 | jonathanj | justin_smith: thank you |
| 14:04 | justin_smith | amalloy: I wish I could remember the concrete details (I should have made a blog post about this), I was making an app where a lazy-seq was abstracting over input from a core.async channel, and it was "buffering" an item at a time |
| 14:05 | amalloy | as opposed to waiting until you seq to <! an item? |
| 14:05 | justin_smith | amalloy: I actually talked to ztellman about why this happened, and the explanation ended up being that lazy-seqs were a "pull" abstraction, and core.async is a "push" abstraction |
| 14:06 | amalloy | yes, that i agree with |
| 14:06 | justin_smith | and manifold is more flexible (I ended up going another route entirely in our app though) |
| 14:06 | justin_smith | now I want to make a minimal example (another thing on my "get around to it" list) |
| 14:08 | jonathanj | in the first 2 minutes of both of those talks, ztellman says "we don't just write software to raise the ambient temperature of the room"... haha |
| 14:44 | eriktjacobsen | Any critiques / improvements on a pattern that will take a list of maps, search for partial duplicates and remove them? So perhaps matching dupes on 2-3 keys, with option to customize which item is picked as the final de-duped one? |
| 14:44 | eriktjacobsen | This is what I came up with: (defn remove-dupes [key-fn sort-fn compare-fn items] |
| 14:44 | eriktjacobsen | (->> (group-by key-fn items) |
| 14:44 | eriktjacobsen | (map (fn [[_ entries]] |
| 14:44 | eriktjacobsen | (first (sort-by sort-fn compare-fn entries)))) |
| 14:44 | eriktjacobsen | (remove nil?) |
| 14:44 | eriktjacobsen | flatten)) |
| 14:44 | oddcully | first concern: not using refheap, pastebin, ... |
| 14:45 | eriktjacobsen | http://pastebin.com/EDpr1pHy |
| 14:45 | eriktjacobsen | Will remember |
| 14:45 | oddcully | cool |
| 14:46 | justin_smith | eriktjacobsen: you may want to use group-by, if you have a function that will return the same result for all maps that should be considered dups (maybe select-keys ?) |
| 14:47 | justin_smith | ,(group-by #(select-keys % [:a :b]) [{:a 0 :b 1 :c 2} {:a 1 :b 1 :c 2} {:a 0 :b 1 :c 42}]) |
| 14:47 | eriktjacobsen | group-by is the first call actually, I’m often passing in something like “#(clojure.string/join "-" ((juxt :partner :year :month) %))” |
| 14:47 | clojurebot | {{:a 0, :b 1} [{:a 0, :b 1, :c 2} {:a 0, :b 1, :c 42}], {:a 1, :b 1} [{:a 1, :b 1, :c 2}]} |
| 14:48 | eriktjacobsen | Oh I don’t have to string that / join do I… interesting right |
| 14:48 | amalloy | first of sort is not right in many scenarios; are you sure you can't use max-key? |
| 14:48 | justin_smith | right, you can use anything as a key in clojure |
| 14:48 | sdegutis | I'm back. |
| 14:49 | justin_smith | eriktjacobsen: also, use mapcat identity instead of remove nil / flatten |
| 14:49 | justin_smith | it replaces both, and is better behaved |
| 14:49 | eriktjacobsen | amalloy: I was intending to sometimes pass in something as simple as pulling an integer key and using < or > as compare, but also wanted to pass in ability to use a string or regex type compare to sort them…. so max-key would seem to force that |
| 14:51 | eriktjacobsen | I’ll look into that (actually the remove nil / flatten I think is un-needed since this one does first, which will always return a record) this was actually from separate version that instead of outputting list of de-duped, it instead gave list of stuff to REMOVE (so I did a (when (> (count %) 1) (rest items)) |
| 14:51 | eriktjacobsen | Will do that though since I need both version |
| 14:52 | hellofunk | are bitwise operations supported on 64bit integers in clojure |
| 14:53 | eriktjacobsen | justin_smith: I dont think I knew that… could you explain how mapcat identity removes nils ? isn’t (identity nil) = nil? I would expect a single nil in the output |
| 14:54 | hiredman | eriktjacobsen: it is, he meant apply concat |
| 14:55 | hiredman | or just turn the map in to a mapcat if the function returns nil or a collection |
| 14:56 | eriktjacobsen | hiredman it does actually work though… it flattens and removes the nils. I just dont understand why. http://pastebin.com/ArDbeyyW |
| 15:00 | eriktjacobsen | oh duh concat doesn’t concat nils…. totally forgot. that seems like odd behavior though. interesting though |
| 15:02 | eriktjacobsen | Thanks amalloy justin_smith. Learn something new everyday |
| 15:05 | TEttinger | hellofunk: yes. I think the default is to use long (64-bit signed) integers |
| 15:05 | kwladyka | REPL can affect memory usage in some way? |
| 15:05 | kwladyka | instead of running directly from jar file? |
| 15:05 | TEttinger | ,(bit-or (bit-shift-left 0xFFFFFFFF 15) 0xFFFFFFFF) |
| 15:05 | clojurebot | 140737488355327 |
| 15:06 | kwladyka | what i see yes, but i am not sure |
| 15:06 | TEttinger | kwladyka: yeah, the REPL has to store previous evaluated arguments as *1, *2, *3 etc. |
| 15:07 | kwladyka | is a way to test app usage memory without compile it to jar? |
| 15:08 | TEttinger | I think it also needs to compile code differently, but I'm not sure how. jar (or uberjar for executables, or whatever war/uberwar stuff EE webdev needs) should probably be the default when testing performance if you're deploying that way |
| 15:11 | TEttinger | (I think it's likely that running a jar with the right memory settings, -Xms64m to start small and garbage collect quickly if not using all of the allocated memory, -Xmx512m or whatever the max you might need and can support is, mess with GC options, make sure you're using --server if you need speed, --client may help with memory at the expense of speed...) |
| 15:11 | TEttinger | or is it -server |
| 15:12 | TEttinger | anyway, running a jar with the right memory settings is very different from running a jar with very wrong memory settings |
| 15:12 | TEttinger | -Xms16G |
| 15:12 | TEttinger | "why is my jarva using so much rams?" |
| 15:13 | kwladyka | TEttinger, i use profiler to check memory usage so i see not only how many is allocated, but how many is really used |
| 15:13 | kwladyka | but as i see REPL affect results as i see |
| 15:13 | kwladyka | but i am not sure, i am researching it now :) |
| 15:15 | kwladyka | it can be noob question, but.. if i will do lein compile can i run app without doing lein uberjar? |
| 15:15 | TEttinger | I'm guessing uberjar is pretty slow for your project? |
| 15:16 | TEttinger | $google leiningen faster |
| 15:16 | lazybot | [Faster · technomancy/leiningen Wiki · GitHub] https://github.com/technomancy/leiningen/wiki/Faster |
| 15:17 | TEttinger | clojurebot: slow |no| more! https://github.com/technomancy/leiningen/wiki/Faster |
| 15:17 | clojurebot | You don't have to tell me twice. |
| 15:17 | TEttinger | ~slow |
| 15:17 | clojurebot | slow no more! https://github.com/technomancy/leiningen/wiki/Faster |
| 15:17 | sdegutis | I'm back again. |
| 15:18 | TEttinger | your nick is an anagram for degu sits. degus are kinda cute little creatures. |
| 15:19 | Bronsa | sdegutis: you don't have to announce it everytime |
| 15:19 | sdegutis | Bronsa: Phew, thanks. |
| 15:20 | TEttinger | Bronsa: I'm here currently |
| 15:20 | oddcully | ~logs |
| 15:20 | clojurebot | logs is http://clojure-log.n01se.net/ |
| 15:21 | oddcully | ah i knew it |
| 15:21 | TEttinger | sdegutis: they're a pretty good thing to have in your name. https://en.wikipedia.org/wiki/Degu#/media/File:Octodon_degus_-Artis_Zoo,_Netherlands-8b.jpg |
| 15:21 | amalloy | sdegutis just needs like one more letter to have a lot of fun anagrams |
| 15:21 | amalloy | duet siege |
| 15:22 | sdegutis | Oh man. Do I need to go back to /nick sed-utils? |
| 15:22 | TEttinger | Degus are extremely intelligent and have a good ability to solve problems. well there you go! |
| 15:32 | sdegutis | Is there a way to check if every item in a collection is equal besides (apply = coll) ? |
| 15:33 | amalloy | sure, there are lots of worse ways |
| 15:33 | gfredericks | what don't you like about (apply = coll)? |
| 15:33 | kwladyka | something is wrong with my profile file? https://www.refheap.com/58124c0debd9118eb4c6e7ab3 Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method. |
| 15:33 | amalloy | gfredericks: i'll tell you what *i* don't like about (apply = coll) |
| 15:33 | amalloy | but i bet you already know: it doesn't work on empty colls |
| 15:34 | gfredericks | I didn't know that would be it |
| 15:34 | amalloy | (i regard this as a bug in = but nobody really cares) |
| 15:34 | gfredericks | but I think I might understand why it does |
| 15:34 | opqdonut | yeah (=) should be true |
| 15:34 | opqdonut | I agree |
| 15:34 | gfredericks | ,(<) |
| 15:34 | clojurebot | #error {\n :cause "Wrong number of args (0) passed to: core/<"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (0) passed to: core/<"\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" 399]\n [sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval25 i... |
| 15:34 | opqdonut | (<) is less well defined than (=) |
| 15:34 | gfredericks | why is that? |
| 15:35 | opqdonut | or that's my knee-jerk reaction anyway, let me think |
| 15:35 | amalloy | gfredericks: last time this came up somebody claimed it is a little bit awkward if you extend this to the < family of functions, because then < and (complement >=) are no longer the same |
| 15:35 | amalloy | but on reflection this is totally bunk, because they're already not the same on anything but 2 arguments |
| 15:36 | opqdonut | indeed |
| 15:36 | opqdonut | ok, I guess (=) and (<) are actually pretty symmetric. if you have the n-ary versions you should also have the 0-ary version |
| 15:36 | gfredericks | I've always thought of these arities as being related to recursive definitions of the functions |
| 15:37 | gfredericks | + and * can get all the way to 0 args because they are monoids |
| 15:37 | gfredericks | (in contrast with / and -) |
| 15:37 | sdegutis | What's the opposite of some |
| 15:38 | gfredericks | and and or are also monoids I think? |
| 15:38 | amalloy | gfredericks: yes, they are |
| 15:38 | gfredericks | so you can't get 0 args for = and < just by the monoid reasoning, it'd have to be something else |
| 15:38 | amalloy | gfredericks: the problem is that some and every? do extend down to empty collections, and (apply = coll) "should" be the same as (every? #(= % (first coll)) coll) |
| 15:38 | hiredman | well |
| 15:39 | gfredericks | in haskell that'd throw an exception |
| 15:39 | amalloy | gfredericks: i don't think so |
| 15:39 | gfredericks | for an empty list |
| 15:39 | amalloy | no, because every undefined [] = true |
| 15:39 | amalloy | True |
| 15:39 | gfredericks | well arguably that has more to do with how the code is structured |
| 15:40 | gfredericks | if you wrote it (let [x (first coll)] (every? #(= % x) coll)) |
| 15:40 | amalloy | gfredericks: still would work fine in haskell, because lazy |
| 15:40 | gfredericks | I feel like this is a meaningful point somehow |
| 15:40 | amalloy | you can't make that throw, because you can't possibly use the value if the list is empty |
| 15:40 | sdegutis | Is there a shorter way of (not (some f xs)) ? |
| 15:40 | gfredericks | amalloy: sure but the language being lazy is a side detail here |
| 15:41 | gfredericks | sdegutis: not-any? |
| 15:41 | sdegutis | Ahhh. |
| 15:41 | sdegutis | Silly lack of consistent naming. |
| 15:41 | amalloy | i don't think so. if you're claiming that my proposed equivalent would throw an exception in haskell, it seems like the way haskell behaves is pretty relevant |
| 15:41 | sdegutis | Earlier I looked for any? and couldn't find it. Turns out it was some. |
| 15:41 | kwladyka | seriously what am i doing wrong with lein uberjar, why am i gettign this error? All looks like is should in poject.clj https://www.refheap.com/58124c0debd9118eb4c6e7ab3 |
| 15:41 | opqdonut | sdegutis: because it returns non-booleans too |
| 15:41 | Bronsa | sdegutis: any? would imply a boolean return. |
| 15:41 | gfredericks | amalloy: I'm appealing to one part of the behavior of haskell and not the other part :P |
| 15:42 | opqdonut | but yeah it trips people up |
| 15:42 | sdegutis | Ahhh right, Clojure makes types multi-task. |
| 15:43 | amalloy | gfredericks: so your argument seems to be that in two consistently-defined languages, my suggested identity would hold, but in a theoretical bad language that's a mix of both, a restructured version of my identity would throw an exception |
| 15:43 | amalloy | (eg, in java you would be right) |
| 15:43 | gfredericks | so let's think about it recursively |
| 15:44 | gfredericks | if you add another element to an = expression, the expression is true if that element equals the "first" element in the expression and if the rest of them are equal |
| 15:44 | gfredericks | i.e. (= a b1 b2 ...) is (and (= a b1) (= b1 b2 ...)) |
| 15:44 | gfredericks | and the base case is that (= bn) is true |
| 15:44 | sdegutis | Thanks gfredericks. |
| 15:45 | gfredericks | my point is that the natural base case in this formulation is 1 arg |
| 15:45 | gfredericks | and this works for all the ordering predicates |
| 15:45 | sdegutis | What's a striking way to test if coll contains :a or :b (or both)? |
| 15:46 | gfredericks | so adding a 0-arg version feels like an unrelated "alternate base case" or something |
| 15:46 | gfredericks | sdegutis: (some #{:a :b} coll) |
| 15:46 | sdegutis | Amazing. |
| 15:46 | sdegutis | Thanks gfredericks. You won twice in a row. |
| 15:46 | kwladyka | oh i have to use :gen-class ... |
| 15:48 | amalloy | gfredericks: doesn't apply to not=, right? |
| 15:48 | gfredericks | ,(doc not=) |
| 15:48 | clojurebot | "([x] [x y] [x y & more]); Same as (not (= obj1 obj2))" |
| 15:49 | gfredericks | (not= a b1 b2 ...) is (or (not= a b1) (not= b1 b2 ...)) |
| 15:49 | gfredericks | ,(not= 42) |
| 15:49 | clojurebot | false |
| 15:49 | gfredericks | and the base case is (not= bn) is false |
| 15:49 | gfredericks | I just did that off the top of my head, hadn't thought about not= |
| 15:49 | gfredericks | so not sure if it makes sense |
| 15:50 | gfredericks | amalloy: I think a better approach to what I was trying to say w/ haskell would be "You can't formulate it that way mathematically" |
| 15:51 | gfredericks | e.g., with set theory |
| 15:58 | hiredman | isn't equivalence in math a binary operation? |
| 15:58 | hiredman | err |
| 15:58 | hiredman | relation |
| 15:58 | gfredericks | yeah |
| 15:59 | gfredericks | that doesn't stop you from making it variadic though |
| 15:59 | gfredericks | the question is does it make sense to have the (=) base case when you do |
| 15:59 | hiredman | does it make sense to have a base case (= b) ? |
| 15:59 | gfredericks | I think it makes as much sense as (+) |
| 16:00 | gfredericks | and I think (=) makes less sense |
| 16:00 | gfredericks | that's the side I'm arguing for anyhow |
| 16:00 | gfredericks | not gonna get in a fight about it |
| 16:00 | hiredman | and if (= b) makes sense even if = is a binary relation, then why doesn't (=) make as much sense? |
| 16:01 | gfredericks | well that's what I was trying to argue; in particular I think (+) => 0 is a "natural" base case for + and that (= b) => true is a "natural" base case for = |
| 16:01 | gfredericks | because they both have nice recursive definitions that use those base cases |
| 16:01 | gfredericks | I don't know of a recursive definition for = that uses (=) true as a base case |
| 16:04 | justin_smith | gfredericks: I guess there is (apply = c), which should return true if c is nil / empty |
| 16:05 | justin_smith | intuitively at least |
| 16:05 | amalloy | justin_smith: that was the base case of this discussion |
| 16:05 | justin_smith | amalloy: d'oh! shows me for replying before I catch up on the scrollback |
| 16:06 | amalloy | it seeems like gfredericks is arguing that the usual description of (apply = xs) as "are all the things in xs equal to each other" is incorrect |
| 16:06 | amalloy | because if you take that description it is obvious that (=) is true |
| 16:07 | hiredman | gfredericks: that is an interesting point |
| 16:07 | sdegutis | Thanks for all your help. |
| 16:07 | gfredericks | amalloy: I might argue that that english phrasing is a bit ambiguous about what the empty case means |
| 16:07 | gfredericks | dunno maybe not |
| 16:07 | gfredericks | english hard |
| 16:08 | kwladyka | used PS old gen <- if i have something like that in my app with 209 MB in profiler... what is it mean? Am i doing something wrong? |
| 16:08 | kwladyka | it is about memory |
| 16:09 | amalloy | i just realized i don't have to put up with this sass. i can just +b gfredericks |
| 16:09 | gfredericks | o_O |
| 16:09 | amalloy | it will be as foretold in the prophecies by andyf. amalloy will rule with an iron fist |
| 16:10 | hiredman | there exists an equivalence class E for all item x in list l where x is a member of E |
| 16:12 | gfredericks | hiredman: quoting from some formalization of something? |
| 16:12 | hiredman | no, trying to piece one together |
| 16:13 | hiredman | that seems to be a statement of equality which would allow for (=), but I forget all that stuff about which binders → existence of whatever |
| 16:13 | kwladyka | ech i totally don't know how to get conclusions from profiler :/ |
| 16:19 | justin_smith | kwladyka: you could see if the allocated size gets bigger if you run the code twice, you could profile subprograms to try and narrow down what is allocating |
| 16:19 | hiredman | the tricky thing is, I don't think any language has first class equivalence classes, but you can define one given at least one member of the equivalence class and some kind of equality operator |
| 16:20 | hiredman | (which of course is circular, we are trying to define equality) |
| 16:20 | hiredman | so you end up with recursion that bottoms out with a single element |
| 16:22 | kwladyka | justin_smith, https://www.dropbox.com/sh/fekagh9kp77f057/AAC0dCeunm2MDt0qWRw8f4lda?dl=0 look at clojure-jar char vs scala char |
| 16:23 | kwladyka | justin_smith, in both i did 10 sec sleep before |
| 16:23 | kwladyka | justin_smith, both do the same... |
| 16:23 | kwladyka | justin_smith, i totally stack with that, i dont know how to get conclusion what is wrong |
| 16:24 | kwladyka | just no idea what to do now to solve that :/ |
| 16:26 | justin_smith | ugh, what a terrible gallery |
| 16:26 | kwladyka | sorry, i dont know better to fast upload |
| 16:27 | oddcully | haha |
| 16:27 | justin_smith | kwladyka: it's OK, you didn't implement that gallery view, but it's terrible |
| 16:27 | kwladyka | justin_smith, :) |
| 16:28 | justin_smith | the biggest difference there is that with clojure you have the whole compiler and all its libs in heap, with scala you do not |
| 16:28 | kwladyka | why the same algorithm in scala is so fast and consume so less memory, it makes me sick |
| 16:28 | justin_smith | but that isn't going to cause your speed problem |
| 16:29 | kwladyka | justin_smith, but clojure-jar.png is for uberjar file |
| 16:29 | justin_smith | uberjar has the entirety of clojure in it |
| 16:29 | justin_smith | there is no standalone option with clojure, unlike scala |
| 16:29 | justin_smith | the feature simply doesn't exist |
| 16:29 | Bronsa | (inc puredanger) ;; thanks for CLJ-1093 |
| 16:29 | lazybot | ⇒ 62 |
| 16:30 | puredanger | did you catch the outcome? |
| 16:30 | justin_smith | but the extra ram used by clojure itself is not the cause of your speed difference, beyond the few seconds it takes clojure to bootstrap itself |
| 16:30 | kwladyka | justin_smith, do you know what used PS old gen can mean? maybe if you will see the code? |
| 16:30 | justin_smith | kwladyka: I've looked at your code already, it's complicated and I have my own hard debugging to do |
| 16:30 | justin_smith | sorry |
| 16:30 | kwladyka | justin_smith, because of about 10 sec sleep before counting it shouldnt affect the time |
| 16:31 | kwladyka | justin_smith, but didnt see any technical anti-performance code? :) |
| 16:32 | Bronsa | puredanger: yes. not exactly what I was hoping for but I'm fine with it, it's consistent with the doc and CLJ-1460 |
| 16:32 | puredanger | Bronsa: he also addressed your other question on the (defn ^{:tag foo} a []) |
| 16:32 | Bronsa | yup saw that too |
| 16:32 | kwladyka | justin_smith, any hints what more can i do t solve that? i dont have more ideas.... |
| 16:33 | justin_smith | kwladyka: I've looked at your code multiple times already, I suggested the things I thought might be issues, but I really can't fix this performance issue for you |
| 16:33 | kwladyka | is it possible it is because of Clojure, not my bug? Just Clojure do this longer or something like that? |
| 16:34 | TimMc | gfredericks: Regarding (=), I like the invariant that remving an element from the input never turns the output from true to false. |
| 16:34 | kwladyka | justin_smith, each time code was improved, i did big step, but now i stack totally what can i do more, i rewrited algorithm to work like this one in scala, but even now performance is much worst |
| 16:35 | justin_smith | kwladyka: if you switch some of your data from vanilla hash-maps to defrecords (which are in most ways identical in behavior to hash-maps, so it won't be a big change to your code) the profiler might give you easier to use data |
| 16:35 | TimMc | gfredericks: Or put more generally, "= returns true iff no two inputs are unequal" -- and if there are no two inputs, it is vaciously true. |
| 16:35 | TimMc | *vacuously |
| 16:35 | kwladyka | justin_smith, anyway thank you so much for trying help me with that problem. |
| 16:35 | puredanger | Bronsa: meaning it now has behavior prior to direct linking |
| 16:36 | kwladyka | justin_smith, defrecords performance is better? |
| 16:37 | justin_smith | kwladyka: it shows up as a different datatype in your profiler |
| 16:37 | justin_smith | thus you can see where all that ram is going |
| 16:37 | kwladyka | justin_smith, oh |
| 16:37 | justin_smith | like which kind of object is being created to such excess (if that is in fact the issue). Also try CPU profiling, see which methods are doing the most work. |
| 16:39 | kwladyka | it is hard to say what is the problem, but for sure it consume too much memory vs scala solution |
| 16:39 | hiredman | https://gist.github.com/hiredman/2aa99f1c24634e0fd9de |
| 16:39 | Bronsa | puredanger: I think there's still a difference but it's probably not meaningful |
| 16:40 | kwladyka | i mean if it is CPU problem, shouldnt be.... |
| 16:40 | kwladyka | CPU didnt cross 80% during all counting |
| 16:40 | justin_smith | kwladyka: I already told you why the ram usage is different, clojure loads the full compiler into your app at runtime, scala does not |
| 16:41 | sdegutis | For anyone here looking to practice Clojure or sharpen their Clojure skills, this is an excellent Java file for porting to pure Clojure using every Clojure technique in the book to shorten it by a huge degree: https://raw.githubusercontent.com/slagyr/latlngtz/master/src/latlngtz/TimezoneMapper.java |
| 16:41 | hiredman | so if any language had first class equivilance classes, it would be natural to define equality using them in a way where (=) would work, but having first class ecs seems very impractical, so what is left is the recursive definition of = which relies on (= b) working |
| 16:41 | hiredman | oops, deleted the wrong line (emacs repeats my inputs) |
| 16:42 | kwladyka | justin_smith, yes but anyway it consume too much memory, i am afraid it is connected with Used PS old gen, it can be some track, but i dont understand what it is :) |
| 16:42 | kwladyka | what can cause that |
| 16:43 | kwladyka | but maybe it is not my code but Clojure... |
| 16:43 | hiredman | and since you need a base case for (= b) adding another for (=) seems inelegant |
| 16:43 | Bronsa | puredanger: actually I'm not sure rettag is very useful right now? it seem to only accept stuff like (defn ^long x [] ..) which don't make sense at runtime since long is evaluated to #<clojure.core$long..> |
| 16:44 | Bronsa | I'll try to look into it if I have some time tomorrow and let you know |
| 16:45 | gfredericks | hiredman: "Do all these elements belong to one class?" ← doesn't make sense for no elements |
| 16:46 | hiredman | gfredericks: https://en.wikipedia.org/wiki/Universal_quantification#The_empty_set |
| 16:46 | justin_smith | kwladyka: if I start clojure.jar, with no other libs loaded (not even lein or nrepl) I see a vsz/rss of 7056368 86412 |
| 16:46 | justin_smith | that's a baseline, it won't go smaller |
| 16:47 | gfredericks | hiredman: I'm talking about (->> coll frequencies count (= 1)) |
| 16:47 | gfredericks | or group-by if you like |
| 16:48 | kwladyka | justin_smith, i am thinking more about maybe Clojure remember some outputs for some magic reasons |
| 16:48 | kwladyka | cash that for future for me :) |
| 16:49 | xificurC | hiccup, garden, sablono - all these are used to generate html/css on the fly? I thought the purpose is to have it defined in clojure, process the definitions and generate static files. Am I misinterpreting something here? |
| 16:50 | hiredman | sure, right, you can obviously write the code differently, and via church-turing and get something in some other logic that will do the same |
| 16:50 | justin_smith | xificurC: static is relative, you can make a compile time step that outputs your resources if there is no relevant run time input |
| 16:51 | kwladyka | xificurC, http://clojure.wladyka.eu/posts/2015-06-01-template-libraries.html you can read my opinion about template libraries |
| 16:52 | gfredericks | hiredman: maybe I'm just having trouble connecting (=) to equivalence classes; how do you phrase the question that (=) is asking in terms of equivalence classes? |
| 16:53 | hiredman | gfredericks: set theoretic notions of equality seem to be based on equivalence classes |
| 16:54 | hiredman | (seem to meaning I am not sure my understanding is correct, not casting doubt on the field) |
| 16:54 | xificurC | justin_smith: I see, although since there's no utility functions/macros written for this I take it it's not very common to do that |
| 16:55 | xificurC | doesn't computing the page hinder performance on the server? |
| 16:55 | xificurC | kwladyka: thanks, although it seems very biased |
| 16:56 | hiredman | so I guess I don't see the argument from some formalism that handling (= b) is valid but (=) is not |
| 16:56 | kwladyka | xificurC, because it is my opinion base on my own experience :) |
| 16:57 | amalloy | justin_smith: most of that vsize is mmapped files though, not taking up any real memory if other programs need it |
| 16:58 | amalloy | well, i don't know about "most". but a lot of |
| 16:58 | hiredman | structurally (= b) makes more sense, because it is a base case you need in this case, but why not handle a base case for (=) if it would make it easier for client code |
| 17:00 | gfredericks | hiredman: yeah I'm not saying clojure shouldn't change necessarily; though you might argue that all the theoretical hand-waving suggests that anybody calling (=) has a high probability of having done it by accident. but that's probably not true |
| 17:00 | gfredericks | should (not=) be false? |
| 17:01 | xificurC | impressive how 1 guy (weavejester) created so many well known web-related libraries, e.g. ring, compojure, hiccup |
| 17:01 | kwladyka | xificurC, yes but i guess he didnt do this alone |
| 17:02 | kwladyka | _guess_ |
| 17:02 | hiredman | gfredericks: I dunno |
| 17:02 | hiredman | I guess? is there a reason it shouldn't be the negation of =? |
| 17:03 | gfredericks | well the argument for (=) seems to be "well *I* think it's obvious what it means" so I wondered if not= was the same way |
| 17:03 | gfredericks | where *I* isn't anybody in particular |
| 17:03 | hellofunk | TEttinger: i get an int out of range error if i try to go beyond 32 bits |
| 17:04 | hiredman | equality is very problematic |
| 17:04 | hiredman | I taught clojurebot a factoid about scala years ago, that was a quote from someone in #scala saying something like "we are so screwed on =" |
| 17:04 | TEttinger | hellofunk: code please |
| 17:05 | hiredman | I must owe that guy a beer |
| 17:05 | slester | hmm, splitting up my code is proving a bit difficult |
| 17:05 | gfredericks | hiredman: haha |
| 17:05 | hellofunk | actually the error is java.lang.IllegalArgumentException: Value out of range for int: 4294967295 |
| 17:05 | TEttinger | cooooode please |
| 17:05 | TEttinger | are you calling int on a large number? |
| 17:06 | hiredman | ~scala |
| 17:06 | clojurebot | scala is val foo = bar ~-> 45 <~< "Fred" %% x |
| 17:06 | TEttinger | use long if you need a 64-bit signed integer |
| 17:06 | slester | Do a lot of people have just one giant file with all the functions in it? Seems bad, but I can't separate them into namespaces because basically all the functions call each other |
| 17:06 | TEttinger | ,(int 4294967295) |
| 17:06 | clojurebot | #error {\n :cause "Value out of range for int: 4294967295"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Value out of range for int: 4294967295"\n :at [clojure.lang.RT intCast "RT.java" 1198]}]\n :trace\n [[clojure.lang.RT intCast "RT.java" 1198]\n [sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "... |
| 17:06 | TEttinger | ,(long 4294967295) |
| 17:06 | clojurebot | 4294967295 |
| 17:07 | hellofunk | TEttinger: ah, i see the problem now. it's the API i'm using that is apparently limited to 32 bits under the hood. if i do it at the repl, no problem over 32 bits |
| 17:08 | hellofunk | the stack trace reveals an intCast right before the out of range error |
| 17:08 | TEttinger | slester: that's a pretty general architecture problem. from my experience, games are particularly susceptible to architecture issues because of the need to have so many things affect the inherently mutable graphics code. |
| 17:08 | hefesto | Hi. I am new at Clojure and irc... so I'm doing this the right way (if not, please say so). I am trying to use clj-antlr (https://github.com/aphyr/clj-antlr) on a project, but I keep getting java.io.FileNotFoundException: Could not locate clj_antlr__init.class or clj_antlr.clj on classpath: , compiling:(date.clj:1:1). On project.clj I add the [clj-antlr "0.2.2"] dependency and lein repl shows the previous error. ¿Does anyone see what I'm doing wro |
| 17:08 | hefesto | ng? |
| 17:08 | TEttinger | hey hefesto |
| 17:09 | hefesto | so *I hope* I'm doing this the right way |
| 17:09 | slester | TEttinger: yeah... :( I'm not sure what I can do about it though. |
| 17:09 | TEttinger | what are you requiring the clj-antlr dep as in your date.clj file? |
| 17:09 | hefesto | yes |
| 17:09 | hefesto | (ns com.bm.bmi.date |
| 17:09 | hefesto | "Parse dates using DateExpr.g4 grammar and ANTLR" |
| 17:09 | hefesto | (require ['clj-antlr.core :as 'antlr])) |
| 17:09 | xificurC | paste your date.clj into a pastebin |
| 17:10 | hefesto | (ns com.bm.bmi.date |
| 17:10 | hefesto | "Parse dates using DateExpr.g4 grammar and ANTLR" |
| 17:10 | hefesto | (require ['clj-antlr.core :as 'antlr])) |
| 17:10 | hefesto | (defn foo |
| 17:10 | hefesto | "I don't do a whole lot." |
| 17:10 | hefesto | [x] |
| 17:10 | hefesto | (println x "Hello, World!")) |
| 17:10 | xificurC | hefesto: you're new to IRC, don't do that :) |
| 17:10 | TEttinger | hefesto: |
| 17:10 | TEttinger | ~pastebin |
| 17:10 | clojurebot | pastebin how about refheap? https://www.refheap.com/ |
| 17:10 | hefesto | ok. |
| 17:10 | hefesto | sorry |
| 17:10 | xificurC | if you have more than 1 line of code use a site to paste your code |
| 17:11 | hefesto | okay, sorry. |
| 17:11 | TEttinger | your require is incorrect for an ns |
| 17:11 | TEttinger | within the ns form, (:require [clj-antlr.core :as antlr]) |
| 17:12 | TEttinger | you still need to have the parens match, I just did that one section of the 3rd line in the date |
| 17:12 | hefesto | I see |
| 17:12 | TEttinger | (require ['clj-antlr.core :as 'antlr]) ; this is correct if you're running it at the REPL, or in any part of a file that isn't the ns macro |
| 17:13 | xificurC | or (require '[clj-antlr.core :as antlr]) |
| 17:13 | TEttinger | there's an in-depth guide here, hefesto http://blog.8thlight.com/colin-jones/2010/12/05/clojure-libs-and-namespaces-require-use-import-and-ns.html |
| 17:14 | TEttinger | (inc xificurC) |
| 17:14 | lazybot | ⇒ 1 |
| 17:14 | hefesto | thank you very much!!! |
| 17:14 | TEttinger | no prob, is it working? |
| 17:14 | xificurC | seems like (bad joke ahead) I'm the One |
| 17:15 | TEttinger | maybe in the next life |
| 17:15 | hefesto | repl started to work |
| 17:15 | hefesto | which i've been trying to do for a while |
| 17:15 | hefesto | so it's a huge success for just now. |
| 17:16 | hefesto | :) |
| 17:16 | TEttinger | woo |
| 17:16 | TEttinger | you're using lein repl , right? |
| 17:16 | hefesto | emacs cider right now |
| 17:18 | TEttinger | I'm always kinda disappointed how the official docs don't really say "use lein, please, it's the best way right now" when talking about project management. I don't use emacs, but I think the clojure tools for it all use lein internally for projects and deps? |
| 17:18 | TEttinger | there's boot, which is really meant for larger projects it seems from their site |
| 17:24 | Bronsa | puredanger: yeah I looked into it and it doesn't seem like rettag makes sense the way it is implemented now. it will only accept (defn ^long x ..) or (defn ^double x ..) but those are invalid tags |
| 17:26 | hefesto | <TEttinger> : I dont know what emacs use internally. I've tried it out with the lein repl and the error disappeared too :) |
| 17:27 | TEttinger | woo |
| 17:29 | puredanger | Bronsa: thx |
| 17:31 | michaniskin__ | TEttinger: cider should work fine with boot btw |
| 17:32 | TEttinger | nice |
| 17:32 | michaniskin__ | but for beginners lein is probably a better alternative because there is a lot of stuff on stackoverflow to copy/paste from |
| 17:32 | michaniskin__ | which is pretty important if you're just learning the language |
| 17:32 | TEttinger | I just think boot makes sense as a thing to transition to if a project becomes unmanageable with lein. is boot able to produce uberjars? |
| 17:32 | michaniskin__ | sure |
| 17:33 | michaniskin__ | it can do all the things you need |
| 17:33 | TEttinger | (is it faster at compiling at lein? pretty please?) |
| 17:33 | michaniskin__ | haha no, boot is more about correctness and sanity |
| 17:33 | TEttinger | pfft |
| 17:33 | TEttinger | you know what I just wrote? |
| 17:33 | michaniskin__ | so aggressive caching isn't done unless we have a solid way to invalidate cache |
| 17:34 | TEttinger | [DllImport("xbrz.dll", EntryPoint = "scale")] internal static extern int scale(int factor, UIntPtr src, UIntPtr trg, int srcWidth, int srcHeight, int colFmt, IntPtr nil = default(IntPtr), int yFirst = 0, int yLast = int.MaxValue); |
| 17:35 | michaniskin__ | however, i think boot is a lot better for incremental compiles because of how it's organized, so that's what you generally use instead of persistent caches |
| 17:35 | justin_smith | ~. |
| 17:35 | clojurebot | Cool story bro. |
| 17:35 | TEttinger | justin_smith: ? |
| 17:36 | justin_smith | TEttinger: that's the magic key sequence that closes ssh when it hangs |
| 17:36 | TEttinger | ~~ |
| 17:36 | clojurebot | Titim gan éirí ort. |
| 17:36 | justin_smith | TEttinger: my ssh connection to my irc session hangs when I connect from work |
| 17:36 | TEttinger | clojurebot: ~ is how you get factoids from me |
| 17:36 | clojurebot | You don't have to tell me twice. |
| 17:37 | TEttinger | ~~ |
| 17:37 | clojurebot | ~ is how you get factoids from me |
| 17:37 | justin_smith | in this instance I had pushed page-up, and hit ~. because the page up was not scrolling. Turns out the ~. only works immediately after newlines |
| 17:37 | TEttinger | aw |
| 18:21 | sdegutis | Given [:a :b :c :d :e], what's a spectacular way to generate [[:a []], [:b [:a]], [:c [:a :b]], [:d [:a :b :c]], [:e [:a :b :c :d]]] ? |
| 18:26 | {blake} | sdegutis: Beat the CPU till it catches fire. Have the answers on a slip of flash paper in your pocket. |
| 18:27 | michaniskin__ | ,(reduce #(conj %1 (conj [%2 (vec (flatten (reverse (last %1))))])) [] [:a :b :c]) |
| 18:27 | clojurebot | [[:a []] [:b [:a]] [:c [:a :b]]] |
| 18:27 | sdegutis | Hmm we may have a tie. |
| 18:28 | sdegutis | Both very good answers so far. But none quite spectacular... yet! |
| 18:28 | {blake} | I'd probably use a for. |
| 18:28 | justin_smith | ,(first (reduce (fn [[acc prev] e] [(conj acc (vector e prev)) (conj prev e)]) [[][]] [:a :b :c :d])) |
| 18:28 | clojurebot | [[:a []] [:b [:a]] [:c [:a :b]] [:d [:a :b :c]]] |
| 18:29 | justin_smith | sdegutis: ^ |
| 18:29 | sdegutis | I like the [[][]] in justin_smith's solution. |
| 18:29 | sdegutis | But still not spectacular. |
| 18:29 | {blake} | Nice. |
| 18:30 | {blake} | Write a macro that, when you start typing [:a :b...] it responds with "I see where you're going with this." and gives the result. |
| 18:31 | justin_smith | ,(first (reduce (fn [[acc prev] e] [(conj acc [e prev]) (conj prev e)]) [[][]] [:a :b :c :d])) |
| 18:31 | clojurebot | [[:a []] [:b [:a]] [:c [:a :b]] [:d [:a :b :c]]] |
| 18:34 | sdegutis | {blake}: Haskell basically has that. |
| 18:34 | {blake} | heh |
| 18:34 | {blake} | (inc Haskell) |
| 18:34 | lazybot | ⇒ 2 |
| 18:36 | DerGuteMoritz | here's one without reduce: (let [x [:a :b :c :d :e]] (mapv vector x (map (comp vec drop-last) (range (count x) 0 -1) (repeat x)))) |
| 18:36 | sdegutis | take 10 $ ['a','b' ..] // => "abcdefghij" (inc Haskell) |
| 18:36 | sdegutis | DerGuteMoritz: ugh, that's the one I was working on |
| 18:37 | sdegutis | cept I got distracted by magNITED states of merica |
| 18:37 | sdegutis | that rant was priceless |
| 18:37 | {blake} | Eh. I like justin_smith's better. |
| 18:38 | sdegutis | I'm still trying to understand DerGuteMoritz -- that in itself is major points! |
| 18:38 | sdegutis | Anyway thanks for always doing the hard parts of my day job for me you guys. |
| 18:38 | sdegutis | Especially you justin_smith. |
| 18:38 | DerGuteMoritz | heh yeah it's not exactly what I would use in production code |
| 18:38 | sdegutis | DerGuteMoritz: you'd be surprised how much FP is in production code |
| 18:39 | michaniskin__ | ,((fn [x] (zipmap x (mapv #(vec (take-while (partial not= %) x)) x))) [:a :b :c :d]) |
| 18:39 | clojurebot | {:a [], :b [:a], :c [:a :b], :d [:a :b :c]} |
| 18:39 | DerGuteMoritz | just wanted to do one without reduce for a change |
| 18:39 | justin_smith | DerGuteMoritz: on a vector, never use drop-last, use pop instead |
| 18:39 | michaniskin__ | derp |
| 18:39 | justin_smith | DerGuteMoritz: oh wait, that isn't a vector coming in, neverm ind |
| 18:39 | sdegutis | I need to loop over each item in a coll while testing against all previous elements in the same coll each time. |
| 18:39 | sdegutis | This is the most spectacular way to do it. |
| 18:40 | {blake} | michaniskin__: Oh, also nice. |
| 18:40 | DerGuteMoritz | justin_smith: also, pop doesn't take an argument of how many elements to pop - but we could use subvec instead perhaps |
| 18:41 | DerGuteMoritz | (when first mapping to vectors, right) |
| 18:41 | sdegutis | Still struggling to figure out how in the world DerGuteMoritz's solution works. |
| 18:42 | DerGuteMoritz | sdegutis: try this as a first step: (map drop-last (range (count x) 0 -1) (repeat x)) |
| 18:43 | justin_smith | sdegutis: after you recall map is varargs, it's easy |
| 18:43 | DerGuteMoritz | the rest is just decoration ;-) |
| 18:43 | sdegutis | justin_smith: That's the fact I was planning to take advantage of actually. |
| 18:43 | sdegutis | In my try, all I got so far was ##(map vector (reverse coll) coll) |
| 18:43 | lazybot | java.lang.RuntimeException: Unable to resolve symbol: coll in this context |
| 18:44 | sdegutis | I mean ##(let [coll [:a :b :c :d :e]] (map vector (reverse coll) coll)) |
| 18:44 | lazybot | ⇒ ([:e :a] [:d :b] [:c :c] [:b :d] [:a :e]) |
| 18:44 | sdegutis | I was gonna work from there. |
| 18:44 | sdegutis | And that's when I found this: https://www.youtube.com/watch?v=1L3eeC2lJZs |
| 18:44 | michaniskin__ | iterate is the spectacularest |
| 18:45 | sdegutis | Which really slowed my progress down on the solution. |
| 18:49 | DerGuteMoritz | michaniskin__: hm nice idea |
| 18:50 | eblood | i have an uberjar that’s configured to start a main function that starts a backend process (started with java -jar dt-utils.jar).. i want to hop into a repl to use a function to test something, so using “java -cp dt-utils.jar clojure.main” I can get a repl, but none of the namespaces are initialized. what else do i need to do? |
| 18:50 | justin_smith | eblood: require your core namespace |
| 18:50 | justin_smith | eblood: remember that require from the repl is different from in ns forms |
| 18:51 | michaniskin__ | ,((comp (partial apply map vector) (juxt identity (comp reverse (partial take-while first) (partial iterate pop) pop))) [:a :b :c :d]) |
| 18:51 | clojurebot | ([:a [:a]] [:b [:a :b]] [:c [:a :b :c]]) |
| 18:51 | michaniskin__ | hehe |
| 18:51 | DerGuteMoritz | (let [x [:a :b :c :d :e]] (map vector x (cons [] (reverse (take (count x) (iterate pop x)))))) |
| 18:52 | justin_smith | (inc michaniskin__) |
| 18:52 | lazybot | ⇒ 1 |
| 18:52 | justin_smith | that's a nice one |
| 18:52 | justin_smith | (inc michaniskin) |
| 18:52 | lazybot | ⇒ 2 |
| 18:52 | michaniskin__ | i want my family coat of arms to have COMP JUXT PARTIAL APPLY in the crest |
| 18:52 | DerGuteMoritz | ,(let [x [:a :b :c :d :e]] (map vector x (cons [] (reverse (take (count x) (iterate pop x)))))) |
| 18:52 | clojurebot | ([:a []] [:b [:a]] [:c [:a :b]] [:d [:a :b :c]] [:e [:a :b :c :d]]) |
| 18:52 | sdegutis | My plan was to first turn [:a :b :c :d :e] into [[] [:a] [:a :b] [:a :b :c] ...] |
| 18:53 | sdegutis | Then I was just going to (partial mapv vector coll) that sucker. |
| 18:53 | DerGuteMoritz | ok that was fun, but now good night :-) |
| 18:53 | sdegutis | Dangit. I think DerGuteMoritz just did it again. |
| 18:57 | sdegutis | Aha! I knew it had something to do with repeatedly or repeat or iterate! |
| 18:57 | sdegutis | And yet, I feel oddly dissatisfied for not coming up with it myself. |
| 18:57 | sdegutis | I'm sorry #clojure. I'm sorry I asked you to do my day job for me. I just.. I had no idea that you would also get the /satisfaction/ from doing it. |
| 18:58 | sdegutis | Well, at the very least, I got to clean it up and make it beautiful: |
| 18:58 | sdegutis | ,(let [coll [:a :b :c :d :e]] (->> coll (iterate pop) (take (count coll)) (reverse) (cons []) (mapv vector coll))) |
| 18:58 | clojurebot | [[:a []] [:b [:a]] [:c [:a :b]] [:d [:a :b :c]] [:e [:a :b :c :d]]] |
| 18:59 | michaniskin__ | excellent |
| 19:03 | eblood | justin_smith: thanks.. that worked |
| 19:28 | slester | I'm struggling a bit with laying out my code; it seems bad to have to (declare) a bunch of functions at the beginning :( |
| 19:28 | gfredericks | TimMc: I missed your comments earlier |
| 19:28 | gfredericks | I do appreciate the "no two elements are unequal" formulation |
| 19:29 | gfredericks | but regarding your other one about removing elements, you have the flipside of "adding an element can always turn true to false", which wouldn't be true for (=) |
| 19:29 | slester | My code if someone is generous enough to given comments: https://github.com/slester/amiss/blob/master/src/amiss/core.clj -- always appreciated! I'll keep doing some searching to see what the Internet says |
| 19:30 | justin_smith | slester: I think the logic of your domain means that inherently each operation needs to conditionally invoke others |
| 19:31 | justin_smith | slester: you could use a big letfn or something, but it is cleaner to just declare them and let them mutually conditionally call one another |
| 19:35 | {blake} | Is there a "mapmerge" equivalent of "mapcat"? |
| 19:36 | justin_smith | {blake}: isn't that just (partial reduce merge) ? |
| 19:36 | justin_smith | oh no, you are doing some function to each element before merging |
| 19:36 | sdegutis | {blake}: How about (->> coll (map f) (apply merge)) |
| 19:36 | justin_smith | so it's (apply merge (map f coll)) |
| 19:37 | sdegutis | justin_smith: Oh reduce, clever. |
| 19:37 | sdegutis | I like how (partial) is implicit in Haskell and (comp) is just . |
| 19:37 | {blake} | justin_smith, sdegutis: Right. I was just looking at mapcat and it's (apply concat (apply map f colls))) so I figured there might be one for merge. |
| 19:37 | sdegutis | ,(source mapcat) |
| 19:37 | clojurebot | Source not found\n |
| 19:38 | sdegutis | Are you drunk clojurebot? |
| 19:38 | sdegutis | ##(source mapcat) |
| 19:38 | lazybot | java.lang.RuntimeException: Unable to resolve symbol: source in this context |
| 19:38 | sdegutis | Oh. |
| 19:38 | sdegutis | ,(clojure.repl/source mapcat) |
| 19:38 | clojurebot | Source not found\n |
| 19:38 | sdegutis | ##(clojure.repl/source mapcat) |
| 19:38 | lazybot | ⇒ Source not found nil |
| 19:38 | sdegutis | FINE, bots. |
| 19:39 | iamjarvo | is there a way for lein repl to load all the files in /src? ive been having to (load-file "file_path") |
| 19:39 | justin_smith | iamjarvo: you can specify :main in your project.clj |
| 19:40 | justin_smith | iamjarvo: https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L196 |
| 19:41 | amalloy | ~def mapcat |
| 19:42 | iamjarvo | justin_smith but thats one namespace, i guess the main namespace should require all the dependencies |
| 19:45 | iamjarvo | i was sort of hoping to load the repl and require a namespace or use a namespace as needed |
| 20:31 | hefesto | How do you concatenate two strings? |
| 20:32 | hefesto | something like: (+ "string 1" "string 2") |
| 20:32 | hefesto | clojure.string doesnt seem to have a function that does it. |
| 20:33 | gfredericks | ,(str "string 1" "string 2") |
| 20:33 | clojurebot | "string 1string 2" |
| 20:34 | hefesto | thank you! |
| 20:34 | hefesto | :) |
| 21:10 | TimMc | gfredericks: Interesting point about adding elements! |
| 21:13 | gfredericks | do any lisps evaluate (=)? |
| 21:20 | justin_smith | guile> (=) => #t |
| 21:20 | justin_smith | first one I tried |
| 21:21 | justin_smith | common lisps don't like it |
| 21:33 | gfredericks | I don't imagine the question even applies to any other popular languages |
| 21:34 | justin_smith | lush demands exactly two arguments |
| 21:34 | TimMc | =.apply([]) |
| 21:41 | kclawl | what makes clojure more functional than python? |
| 21:42 | gfredericks | immutable data structures? |
| 21:42 | kclawl | anything else? |
| 21:42 | justin_smith | kclawl: the core functions and data structures make side effects rare |
| 21:43 | justin_smith | kclawl: in python you can code functionally if you have a lot of self discipline and keep track of the gotchas (hidden or unexpected mutation) - in clojure it's the default, the easy way to code |
| 21:46 | kclawl | yeah I see |
| 22:18 | TimMc | You can opt out of it, of course, but it has to be somewhat explicit. |
| 22:20 | gfredericks | it's not just a language attribute it's a community/ecosystem thing too |
| 22:27 | sg2002 | kclawl: The semantics itself is more functional too. Python expressions are imperative. |
| 22:36 | kclawl | sg2002 hmm, what makes python expressions imperative? |
| 22:43 | gfredericks | do all python expressions return something? |
| 22:47 | sg2002 | kclawl: Lisp expressions are functional because they always return a value. Python expressions generally don't return a value. if a==b{ x} else{ y} in an imperative language like python means "DO x when a==b or DO y". In a lisp similar statement means "return value from doing x when a==b or value from doing y". |
| 22:52 | kclawl | ah ok.. python is if expression too, but it is kind of ugly and backwards |
| 22:52 | kclawl | 10 if True else 20 |
| 22:59 | sg2002 | kclawl: Python expressions are not backwards or ugly, but from the point of functional programming those expressions are a layer of accidential complexity. |
| 23:01 | kclawl | 10 if True else 20 is backward and ugly |
| 23:01 | kclawl | first a then value, then boolean check, then else |
| 23:29 | amalloy | gfredericks: i think expressions that don't return something get called statements |