2016-02-10
| 00:24 | tolstoy | Interesting. You can't use core.async inside the Electron main thread, it seems. goog.global.setTimeout is not a function. |
| 00:49 | yuung | hey all, how can i load code outside of src/ with lein? i have a folder named db/my_proj in the root of my project folder that I'd like to add to the path |
| 00:50 | hiredman | tolstoy: that sounds like a compilation issue with clojurescript |
| 00:51 | hiredman | goog.* is the prefix used by the google closure libraries |
| 00:57 | tolstoy | hiredman: I agree. When I'm not so crunched, I'll investigate. It doesn't really make sense to me. |
| 01:25 | tolstoy | hiredman: I wonder if it's because I used :optimizations :simple for an app that runs on node. |
| 01:29 | neoncontrails | binjured: did you figure out an answer to your question earlier about generating a type-hinted function? |
| 01:48 | tolstoy | hiredman: If I do this, (set! js/goog.global js/global), things work. ;) http://dev.clojure.org/jira/browse/ASYNC-110 |
| 04:19 | visof | hi guys |
| 04:19 | visof | ,(conj (vec (drop-last [1 2 3 4])) (inc (last [1 2 3 4]))) |
| 04:19 | clojurebot | [1 2 3 5] |
| 04:19 | visof | is this good way to change the last element only in list? |
| 04:20 | visof | ,(conj (vec (drop-last [1 2 3 4])) (let [l (last [1 2 3 4])] (* l l l))) |
| 04:20 | clojurebot | [1 2 3 64] |
| 04:21 | luma | ,(update [1 2 3 4] 3 inc) ; if you have a vector |
| 04:21 | clojurebot | [1 2 3 5] |
| 04:21 | luma | ,(update [1 2 3 4] 3 #(* % % %)) |
| 04:21 | clojurebot | [1 2 3 64] |
| 04:22 | visof | luma: what if i don't know index? |
| 04:22 | visof | .indexOf ? |
| 04:22 | visof | what if there are multiple same elements? |
| 04:23 | luma | ,(update [12 13 14 15] 3 inc) ; this doesn't care about the values, the "3" is the index |
| 04:23 | clojurebot | [12 13 14 16] |
| 04:59 | jonathanj | ,(use 'com.rpl.specter) |
| 04:59 | clojurebot | #error {\n :cause "Could not locate com/rpl/specter__init.class or com/rpl/specter.clj on classpath."\n :via\n [{:type java.io.FileNotFoundException\n :message "Could not locate com/rpl/specter__init.class or com/rpl/specter.clj on classpath."\n :at [clojure.lang.RT load "RT.java" 456]}]\n :trace\n [[clojure.lang.RT load "RT.java" 456]\n [clojure.lang.RT load "RT.java" 419]\n [clojure.core$l... |
| 04:59 | jonathanj | :| |
| 04:59 | jonathanj | not sure if (specter/transform [LAST] inc [1 2 3 4]) is overkill or a good idea |
| 05:00 | MJB47 | if you are already using specter i dont see a problem |
| 05:00 | MJB47 | but i wouldnt include it to the ns just for that |
| 05:00 | geirby | yep, the snippet is quite readable |
| 05:01 | geirby | so go for it if you're already using specter |
| 05:16 | jonathanj | MJB47: thing is that once you have it included, you find ways to use it |
| 05:16 | MJB47 | if you have enough cases where it would be useful, then whats wrong with including it? |
| 05:17 | jonathanj | i don't know, you were the one suggesting not including it |
| 05:17 | MJB47 | the only tradeoffs i can think of is anyoen else working on the project will need to learn it, and its an extra dependency (with all that entails) |
| 05:17 | jonathanj | all i'm saying is that if you include it for "just that" you will almost certainly find a way to use it for other cases |
| 05:17 | MJB47 | this is true, but you can always refactor later to do this with the original case |
| 05:18 | MJB47 | idk, its up to you |
| 05:18 | MJB47 | personally i think the library is awesome and worth including in most projects |
| 05:18 | MJB47 | but that varies between people |
| 05:18 | jonathanj | my personal preference is to do it the other way, once your code is more mature and you only have a few uses of something then perhaps rewrite your code so you don't need it |
| 05:19 | MJB47 | that wounds backwards to me |
| 05:19 | MJB47 | idk |
| 05:19 | MJB47 | sounds* |
| 05:19 | jonathanj | but in terms of getting things done, including specter and writing the code would have taken less time than the IRC conversation |
| 06:28 | jonathanj | Using ring-jetty-adapter, how does one specify what certificate to use for SSL connections? |
| 06:29 | jonathanj | (I have a keystore with several certificates in it.) |
| 06:34 | hillbillie | test |
| 07:16 | justin_smith | ,(let [v [1 2 3 4]] (conj (pop v) (inc (peek v)))) ; visof |
| 07:16 | clojurebot | [1 2 3 5] |
| 07:17 | justin_smith | that only works for a vector though |
| 07:17 | clojurebot | Cool story bro. |
| 07:17 | justin_smith | ,(let [v '(1 2 3 4)] (conj (pop v) (inc (peek v)))) ; visof |
| 07:17 | clojurebot | (2 2 3 4) |
| 10:53 | fuuduCoder | what would be the best way to get last but one element in a sequence. |
| 10:54 | fuuduCoder | last of butlast? |
| 10:55 | MJB47 | depends on the type of sequence |
| 10:56 | MJB47 | nvm no it doesnt |
| 10:56 | MJB47 | probably (last (butlast ...)) yes |
| 10:56 | aurelian | ,(map #(nth [1 2 3] %) [0 2]) |
| 10:56 | clojurebot | (1 3) |
| 10:57 | aurelian | is there a nicer way to do that? ^^ |
| 10:57 | aurelian | select from a coll a list of indexes |
| 10:57 | MJB47 | are you trying to retrieve the first and last elements? or the even indexed elements? or remove the second element? |
| 10:58 | fuuduCoder | just get the last but one element if it exists |
| 10:58 | aurelian | no, sorry, I have a list and I need to select elements at index 0, 2, 5 and anotherone |
| 10:58 | aurelian | I thought there's a built in |
| 10:58 | MJB47 | select-keys is close |
| 10:58 | MJB47 | but |
| 10:59 | MJB47 | ,(vals (select-keys [1 2 3] [0 2])) |
| 10:59 | clojurebot | (1 3) |
| 10:59 | MJB47 | you judge if its nicer |
| 10:59 | averagehat | ,(map( [1 2 3] ) [0 2]) |
| 10:59 | clojurebot | #error {\n :cause "Wrong number of args (0) passed to: PersistentVector"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (0) passed to: PersistentVector"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 28]\n [sandbox$eval76 invokeStatic "NO_SOURCE_FILE" 0]\n [san... |
| 10:59 | averagehat | ,(map( [1 2 3] [0 2]) |
| 10:59 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 10:59 | aurelian | oh, ok, I thought select-keys is for maps only |
| 10:59 | averagehat | oops sorry clojurebot |
| 10:59 | averagehat | ,(map( [1 2 3] [0 2]) |
| 10:59 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 11:00 | averagehat | ,(map [1 2 3] [0 2]) |
| 11:00 | clojurebot | (1 3) |
| 11:00 | averagehat | sorry fail |
| 11:01 | aurelian | ,(map #(nth (:a :x 3 :q "foo" :tcp) %) [0 2 5]) |
| 11:01 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :a> |
| 11:01 | aurelian | grr |
| 11:02 | aurelian | ,(map #(nth '(:a :x 3 :q "foo" :tcp) %) [0 2 5]) |
| 11:02 | clojurebot | (:a 3 :tcp) |
| 11:03 | jonathanj | (specter/select [[0 2]] [1 2 3]) |
| 11:03 | jonathanj | sorry, i'm not trying to be that guy who recommends one tool for everything but there seem to be quite a few applicable cases today |
| 12:24 | novak` | is there standard way in clojure to print warnings in console applications? |
| 12:26 | justin_smith | novak`: you can print to *err* |
| 12:28 | justin_smith | novak`: for example this works java -jar ~/bin/clojure.jar -e '(binding [*out* *err*] (println "err"))' > /dev/null |
| 12:28 | justin_smith | since only stdout and not stderr was redirected, "err" prints |
| 12:29 | bitsynthesis | hello! is it possible to run leiningen tasks and override a given project property without with-profiles? i'd like to pass in an argument dynamically at the time a task is run |
| 12:31 | justin_smith | bitsynthesis: if I were doing this I would define multiple profiles and use with-profile on the command line to select one |
| 12:31 | justin_smith | I don't know of a way to get freeform config into lein from the cli |
| 12:31 | hyPiRion | bitsynthesis: `lein help update-in` |
| 12:35 | justin_smith | hyPiRion: oh, that's a cool one |
| 12:36 | bitsynthesis | justin_smith: thank you! |
| 12:45 | novak` | justin_smith: Yep, I've already seen it before somewhere... :D Thank you! |
| 12:55 | novak` | I have one more question - Is there any clojure function that returns platform independent line separator or to use (System/lineSeparator)? |
| 12:56 | justin_smith | ,(newline) |
| 12:56 | clojurebot | \n |
| 12:56 | justin_smith | that outputs it... |
| 12:57 | justin_smith | ,@#'clojure.core/system-newline ; var deref since it is private |
| 12:57 | clojurebot | "\n" |
| 12:57 | justin_smith | ,System/lineSeparator ; no need for the parens I think |
| 12:57 | clojurebot | #error {\n :cause "Unable to find static field: lineSeparator in class java.lang.System"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to find static field: lineSeparator in class java.lang.System, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :messag... |
| 12:58 | justin_smith | err... |
| 12:58 | justin_smith | ,(System/lineSeparator) |
| 12:58 | clojurebot | "\n" |
| 12:58 | justin_smith | OK then |
| 12:58 | justin_smith | odd that wouldn't be a static field |
| 13:03 | novak` | justin_smith: lineSeparator is method actually |
| 13:04 | novak` | justin_smith: (newline) returns nil, it immediately print newline to *out* |
| 13:07 | justin_smith | novak`: right, I was surprised lineSeparator was a method not a static field, and as I showed clojure does have a var holding the system-newline, but it's private |
| 13:11 | novak` | justin_smith: So OK, (System/lineSeparator) is good enough. :) |
| 13:12 | justin_smith | ,[(Math/PI) Math/PI] ; static methods are slightly weird for hysterical raisins |
| 13:12 | clojurebot | [3.141592653589793 3.141592653589793] |
| 13:13 | justin_smith | it's one of very few places where parens are optional |
| 13:13 | justin_smith | along with the threading macros, case... anything else? |
| 13:14 | justin_smith | well case in the special circumstance where you match a single value |
| 13:17 | novak` | \exit |
| 14:12 | WorldsEndless | What's wrong here? |
| 14:12 | WorldsEndless | ,(for [[n x] (interleave [1 2] ["keywords.csv" "topics.csv"])] (println n x)) |
| 14:12 | clojurebot | #<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: Long> |
| 14:13 | WorldsEndless | For some reason for is choking, since the interleave works in isolation |
| 14:13 | chouser | Something is trying to call 'nth' on a long. Destructuring uses 'nth', so look for a place where destructuring is being unintentionally applied to a number. |
| 14:14 | WorldsEndless | Obviously that would have to be the [[n x]], but I'm not sure why it has a problem here |
| 14:14 | chouser | ,(for [[n x] [1 2 3 4]] n) |
| 14:14 | clojurebot | #<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: Long> |
| 14:14 | chouser | ,(for [[n x] [[1 2] [3 4]]] n) |
| 14:14 | clojurebot | (1 3) |
| 14:14 | WorldsEndless | Ah. That's it. |
| 14:15 | WorldsEndless | so, since I want each interleaved item to be an isolated vector pair, what function am I looking for? Maybe not interleave? |
| 14:16 | WorldsEndless | A nested for loop? |
| 14:16 | chouser | You might like (map list ...) or (map-indexed list ...) |
| 14:16 | chouser | ,(map-indexed list "abcd") |
| 14:16 | clojurebot | ((0 \a) (1 \b) (2 \c) (3 \d)) |
| 14:16 | WorldsEndless | So I don't actually want numbers in the real use case, so maybe some kind of map |
| 14:17 | chouser | ,(map list "abcd" "wxyz") |
| 14:17 | clojurebot | ((\a \w) (\b \x) (\c \y) (\d \z)) |
| 14:17 | WorldsEndless | yuck |
| 14:17 | chouser | ? |
| 14:17 | WorldsEndless | Sorry. I just mean the character iteration surprised me |
| 14:17 | chouser | oh, sorry. |
| 14:17 | chouser | ,(map list '[a b c] '[d e f]) |
| 14:17 | clojurebot | ((a d) (b e) (c f)) |
| 14:17 | chouser | better? :-) |
| 14:18 | WorldsEndless | yuep :) |
| 14:18 | chouser | You may also consider replacing your 'for' with 'map' and save the building and then destructuring of the list. |
| 14:19 | WorldsEndless | Is there any important difference in this case between map list and map vector? |
| 14:19 | chouser | ,(map (fn [x y] (println x y)) '[a b c] '[d e f]) |
| 14:19 | clojurebot | (a d\nb e\nnil c f\nnil nil) |
| 14:19 | chouser | bleh. that printed badly. |
| 14:19 | chouser | WorldsEndless: No important difference in this case. |
| 14:19 | WorldsEndless | I think map is the answer. Thanks! |
| 14:20 | justin_smith | WorldsEndless: for something that's going to be exactly length of 2, list might be slightly better, but it really depends what you plan on using it for |
| 14:20 | kwladyka | WorldsEndless more like you thinking. If you do something for every position in collection use map. With for you can use :let :when etc. and skip some values |
| 14:21 | chouser | ha! I snuck an answer in while justin_smith was away! I'll have to go back to lurking now, since I can't actually compete. |
| 14:21 | justin_smith | chouser: hahaha |
| 14:21 | kwladyka | chouser yes you was faster this time :P |
| 14:22 | kwladyka | it is some kind of achievement ;) |
| 14:45 | binjured | is there a way to create a var reference that can be used during macro expansion? i keep getting "Can't embed object in code" |
| 14:47 | justin_smith | binjured: that sounds like you tried to use the var itself instead of its value |
| 14:47 | justin_smith | or the symbol that would look it up |
| 14:49 | binjured | justin_smith: yeah, i can't figure out how to give that symbol to the macro in a way that it actually gets used as a var value. |
| 14:49 | justin_smith | ,(defmacro silly [] 'foo) |
| 14:49 | clojurebot | #'sandbox/silly |
| 14:50 | justin_smith | ,(def foo 1) |
| 14:50 | clojurebot | #'sandbox/foo |
| 14:50 | justin_smith | ,(silly) |
| 14:50 | clojurebot | 1 |
| 14:50 | justin_smith | binjured: it's that simple |
| 14:50 | justin_smith | or you want the var... |
| 14:50 | justin_smith | ,(defmacro silly [] '(var foo)) |
| 14:50 | clojurebot | #'sandbox/silly |
| 14:50 | binjured | how can i do that without the '? like, programatically. (something-here "foo") |
| 14:50 | justin_smith | ,(silly) |
| 14:50 | clojurebot | #'sandbox/foo |
| 14:51 | binjured | ah |
| 14:51 | justin_smith | so you want to take the string, turn it into a symbol, and get the var for that symbol? |
| 14:52 | binjured | yeah. reason being is earlier in the macro I'm doing (declare (symbol some-string)) |
| 14:52 | justin_smith | ,(defmacro silly [x] `(var (symbol ~x))) |
| 14:52 | clojurebot | #'sandbox/silly |
| 14:52 | justin_smith | ,(silly "foo") |
| 14:52 | clojurebot | #error {\n :cause "clojure.lang.Cons cannot be cast to clojure.lang.Symbol"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.Symbol, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.ClassCastException\n :message "clojure.lang.Con... |
| 14:52 | justin_smith | ergh |
| 14:52 | binjured | yeah, that's what i get too |
| 14:52 | justin_smith | ,(defmacro silly [x] `(var ~(symbol x))) |
| 14:52 | clojurebot | #'sandbox/silly |
| 14:52 | justin_smith | ,(silly "foo") |
| 14:52 | clojurebot | #'sandbox/foo |
| 14:52 | justin_smith | ~quoting |
| 14:52 | clojurebot | quoting is quote |
| 14:53 | justin_smith | ~quote |
| 14:53 | clojurebot | http://en.wikipedia.org/wiki/Lisp_%28programming_language%29#Self-evaluating_forms_and_quoting |
| 14:53 | justin_smith | I wanted clojurebot to have something clever to say about how stupid quoting always is |
| 14:53 | binjured | haha |
| 15:38 | adis | svasta..nidje zive duse |
| 16:01 | kwladyka | what convention for naming do you have in situation like that: (:require [foo.uuid :as uuid]) (let [bar uuid/create!] ...) <- how you will call bar in this case? |
| 16:02 | kwladyka | the best would be uuid but, uuid is reserved in that situation |
| 16:09 | kwladyka | as i discover i need use uuid in more then one place as name of parameter... maybe in convention better is do require [foo.uuid :as ns-uuid] or something like that? |
| 16:27 | octe | i get this "CIDER's version (0.11.0-snapshot) does not match cider-nrepl's version (0.10.0-snapshot). Things will break!" even though i specified "0.11.0-SNAPSHOT" for cider/cider-nrepl plugin in the repl profile in my project.clj |
| 16:27 | octe | what could i be doing wrong? |
| 16:28 | octe | nevermind, i had it my user profile in profiles.clj |
| 16:44 | kwladyka | i have strange situation and not sure what is happening, all the time i get expection IllegalArgumentException No matching field found: getSQLState for class java.lang.ClassCastException clojure.lang.Reflector.getInstanceField (Reflector.java:271) <- i am using data from clojure jdbc query and whenever i pass them i have problem like that |
| 16:45 | kwladyka | for example if i pass this data to postal/send-message i get this error, but if i pprint them it is ok. |
| 16:45 | kwladyka | this error totally say mi nothing and is very confuse |
| 16:46 | kwladyka | what getSQLState have to do with pass data to another function like postal? |
| 16:47 | kwladyka | hmm i see whatever i pass to postal it gives me this error.... mmm |
| 16:48 | kwladyka | but i also get this error in not postal, in selmer |
| 16:48 | kwladyka | that is so strange |
| 16:51 | kwladyka | ok that was error from postal (as i guess) |
| 16:59 | patham9 | hi! why cant clojure automatically detect if a recursion happens at tail position and use recur? |
| 17:00 | justin_smith | patham9: it totally could and does not. What this avoids is a common bug in other lisps where people do a self call that they assume is optimized but isn't actually tail recursive. |
| 17:01 | justin_smith | patham9: by requiring you to explicitly say "this must tail recur" you get a compilation error that it is not tail, instead of a sneaky stack overflow later |
| 17:02 | patham9 | which is nice yes |
| 17:02 | patham9 | then the IDE could be smarter, and insert recur where the recursive call happens in case that it succeeds there ^^ |
| 17:03 | justin_smith | patham9: this would be an awesome editor feature, yes! |
| 17:05 | patham9 | another question: it wasn't until Clojure where I really realized the importance of tail recursion |
| 17:06 | patham9 | Are there no mechanisms, which can transform a non-tail-recursive formulation into tail recursive ones? |
| 17:06 | patham9 | Often not-tail-recursive formulations are a lot more elegant |
| 17:06 | amalloy | not all functions are amenable to such a transformation |
| 17:07 | amalloy | eg, consider doing a depth-first walk of a tree |
| 17:07 | patham9 | i see hm |
| 17:07 | patham9 | but many could be |
| 17:08 | kwladyka | How to with-redefs correctly here https://www.refheap.com/114683 ? |
| 17:09 | amalloy | put the with-redefs inside the deftest |
| 17:09 | kwladyka | it still call original |
| 17:09 | kwladyka | hmm why it doesn't work outside testing? |
| 17:09 | justin_smith | kwladyka: the with-redefs needs to surround your code, right now it only surrounds the def |
| 17:10 | justin_smith | when your code runs, it is outside that block |
| 17:10 | justin_smith | the with-redefs has already exited |
| 17:10 | justin_smith | so you need with-redefs to be inside the deftest |
| 17:10 | amalloy | (with-redefs [...] (deftest ...)) redefines this function, defines a test, and then puts the original function back |
| 17:10 | kwladyka | ok i think i undrestand |
| 17:11 | justin_smith | kwladyka: with-redefs is not a lexical binding like let, it is a dynamic one like binding |
| 17:11 | patham9 | think about this one: (defn factorial [n] (if (= n 1) 1 (* n (factorial (- n 1) )))) |
| 17:11 | kwladyka | ok thank you for explanation |
| 17:11 | patham9 | its nearly the most intiutive way how to see it |
| 17:11 | patham9 | how to define it |
| 17:12 | justin_smith | patham9: that one can be tail recursive if you add an arg |
| 17:12 | justin_smith | but as amalloy mentions some algos can't be recursive that way |
| 17:12 | patham9 | if I add an arg? |
| 17:12 | patham9 | factorial only has 1 arg ^^ |
| 17:12 | justin_smith | right, an accumulator representing an accumulated state |
| 17:12 | patham9 | you mean a nested function (loop usually in clojure) |
| 17:13 | justin_smith | patham9: * has two args, if you want to tail recur both need to be passed to the next call |
| 17:13 | justin_smith | patham9: no |
| 17:13 | patham9 | which has an additional accumulator |
| 17:13 | justin_smith | patham9: ok sure, an extra arity, a loop, whatever, but hte point is the algo can be tail recursive if you add an argument |
| 17:14 | justin_smith | that's the general thing - many primitive recursions become tail recursions by adding arguments, but only if you can commute on the accumulator |
| 17:14 | patham9 | by using a loop which is quite unelegant, thats what i want to avoid |
| 17:14 | justin_smith | you can commut * but you cannot commute a tree walk |
| 17:14 | justin_smith | patham9: then don't use a loop, define a second arity to the same function |
| 17:14 | kwladyka | how do you make function to do nothing with with-redefs: [advertisements.email.handler/send-email! (fn [& _] nil)] <- something like that or can i do it simpler? |
| 17:14 | patham9 | can you give an example? |
| 17:15 | justin_smith | (defn factorial ([n] (factorial n 1)) ([n acc] ...)) |
| 17:15 | justin_smith | that way you can update the accumlator on each call, instead of leaving a multiply hanging for later |
| 17:16 | justin_smith | ,(defn factorial ([n] (factorial n 1)) ([n acc] (if (= n 1) acc (factorial (dec n) (* acc n))))) |
| 17:16 | clojurebot | #'sandbox/factorial |
| 17:17 | justin_smith | ,(factorial 6) |
| 17:17 | clojurebot | 720 |
| 17:17 | patham9 | this works? nice :D |
| 17:18 | justin_smith | only if your state is commutative, but yes |
| 17:18 | justin_smith | or am I wrong about that? puzzling it out now... |
| 17:18 | patham9 | what does it mean to the state to be commutative? |
| 17:19 | kwladyka | anyway for better performance you should use recur |
| 17:19 | justin_smith | patham9: multiplication commutes, so you don't need to save up all the multiplications for later, you can do them as you go |
| 17:19 | ptisnovs | ,(defn factorial ([n] (factorial n 1M)) ([n acc] (if (= n 1) acc (factorial (dec n) (* acc n))))) |
| 17:19 | clojurebot | #'sandbox/factorial |
| 17:19 | ptisnovs | its better, not overflow ;) |
| 17:19 | ptisnovs | ,(factorial 100) |
| 17:19 | clojurebot | 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000M |
| 17:19 | justin_smith | ptisnovs: you want *' |
| 17:19 | patham9 | this multi arg is extremely nice in that language!! |
| 17:19 | justin_smith | or maybe not? |
| 17:19 | justin_smith | patham9: yeah, it works nicely in clojure |
| 17:19 | ptisnovs | justin_smith: yeah, it's even better |
| 17:19 | patham9 | haskell doesnt have sth like this? |
| 17:19 | kwladyka | patham9 http://clojuredocs.org/clojure.core/recur |
| 17:20 | justin_smith | ptisnovs: instead of 1M you can use *' which means it auto-promotes but only as needed |
| 17:20 | kwladyka | there is even example with factorial ;) |
| 17:20 | justin_smith | patham9: haskell only allows functions of a single argument, of course |
| 17:20 | justin_smith | kwladyka: it is the classic, after all |
| 17:20 | patham9 | @kwladyka: loop is not that beautiful ^^ |
| 17:22 | kwladyka | patham9 you don't have to use loop |
| 17:22 | patham9 | in java i would also use the loop ^^ |
| 17:22 | kwladyka | ,(defn foo [n] (if (zero? n) "end" (recur (dec n)))) |
| 17:22 | clojurebot | #'sandbox/foo |
| 17:22 | kwladyka | ,(foo 3) |
| 17:22 | clojurebot | "end" |
| 17:23 | kwladyka | patham9 recur matter for performance |
| 17:24 | patham9 | i know |
| 17:24 | patham9 | recur is fine |
| 17:24 | patham9 | having to create virtual accumulator variables to make sth tail recursive, not so |
| 17:24 | justin_smith | patham9: it's just moving data from the stack into the heap |
| 17:25 | patham9 | the beauty of the representation is the key difference for me |
| 17:25 | patham9 | sth beautiful turning ugly to be efficient |
| 17:25 | ptisnovs | patham9: IMHO only primitive recursive functions could be written by using recur + accumulator. for not primitive recursive functions, stack or other data structure would be needed |
| 17:26 | patham9 | hm |
| 17:26 | ptisnovs | patham9: https://en.wikipedia.org/wiki/Primitive_recursive_function if you are interested |
| 17:26 | rcassidy | accumulators aren't ugly :) |
| 17:29 | patham9 | interesting |
| 17:29 | patham9 | they should be inferred by the compiler not complicating my recursive formulations ^^ |
| 17:30 | justin_smith | patham9: as the page above mentions, it's impossible to solve the general "is this primitively recursive?" quesiton. But it is straightforward to build a function that is guaranteed to be primitive-recursive |
| 17:31 | patham9 | maybe in general its hard, for most practical cases though it might be possible |
| 17:32 | patham9 | maybe in general its impossible i meant |
| 17:32 | patham9 | but this doesnt say that much |
| 17:33 | patham9 | as with the halting problem: sure its impossible to decide whether a TM halts. but still its impossible to identify a lot of very interesting infinite classes of TM's where it can indeed be decided |
| 17:33 | patham9 | (whether a TM halts in general I meant) |
| 17:33 | patham9 | but still its possible to identify... argh ^^ |
| 17:34 | patham9 | too long day already ^^ |
| 17:36 | patham9 | but i see I want too much :D |
| 17:37 | ptisnovs | patham9: ackermann's function is pretty good to study: http://rosettacode.org/wiki/Ackermann_function#Clojure |
| 17:37 | ptisnovs | patham9: impossible to avoid the recursion AND not using stack (or vector or so as accumulator) |
| 17:38 | patham9 | i know that such functions exist, but most practical recursions are primitive recursive |
| 17:38 | patham9 | as occurring in practical programs |
| 17:38 | patham9 | but still the compiler wont identify this property and leaves it to the programmer |
| 17:38 | ptisnovs | patham9: yeah (with the exception of traversing trees) |
| 17:40 | patham9 | or IDE feature: Primitive recursive function detected, click to rewrite to tail recursive version ^^ |
| 17:41 | patham9 | this is what i want ^^ |
| 17:42 | ptisnovs | lisp and scheme could detect some (almost all?) such cases, so it might be possible to implement it |
| 17:44 | justin_smith | well that's just detecting tail position, not something like "this thing could become an accumulator..." |
| 17:45 | patham9 | indeed, it should do the hard work: creating the tail recursive formulation by its own after finding out that the function is primitive recursive ^^ |
| 17:48 | amalloy | there are tools that will do that |
| 17:49 | patham9 | there are? |
| 17:49 | amalloy | well, i'm thinking of CPS transformers |
| 17:49 | amalloy | which i think is similar/related |
| 17:52 | kwladyka | Why in many modules like for example https://github.com/juxt/bidi i see people use vectors instead of map. Like here (def my-routes ["/" {"index.html" :index "article.html" :article}]) <- why not {"/" {...}} ? |
| 17:54 | justin_smith | kwladyka: because the order decides which wildcards could shadow other routes |
| 17:54 | justin_smith | and maps are not ordered |
| 17:55 | kwladyka | justin_smith thx! |
| 17:55 | justin_smith | kwladyka: I figured this out when I helped write a routing lib... |
| 17:58 | kwladyka | it was mysterious for me, i saw that many times for different code and always asked myself... but why? |
| 18:06 | arkh | any thoughts on why this doesn't work?: (apply assoc {:a 1} (interpose 0 [:b :c :d])) |
| 18:07 | justin_smith | arkh: interpose only puts items in between |
| 18:07 | justin_smith | ,(interpose 0 [:b :c :d]) |
| 18:07 | clojurebot | (:b 0 :c 0 :d) |
| 18:07 | arkh | ohh ... thank you |
| 18:07 | justin_smith | ,(interleave (repeat 0) [:b :c :d]) |
| 18:07 | clojurebot | (0 :b 0 :c 0 ...) |
| 18:08 | justin_smith | err |
| 18:08 | justin_smith | ,(interleave [:b :c] (repeat 0)) |
| 18:08 | clojurebot | (:b 0 :c 0) |
| 18:08 | justin_smith | that's the one you want |
| 18:08 | arkh | boom - thank you |
| 18:12 | amalloy | (into {:a 1} (zipmap [:b :c :d] (repeat 0))) |
| 18:13 | amalloy | (into {:a 1} (for [k [:b :c :d]] [k 0])) |
| 18:16 | arkh | now see, that's where my lengthy but insular clojure experience needs more flavor. I always reach for e.g. apply instead of into and there's probably a bunch of other habits I have like that |
| 18:17 | arkh | it's good to see the different ways |
| 18:21 | code-ape | Quick question, I have a lazy-seq of numbers that does terminate. I want to count how many are even. What's the best way to do this? Thank you! |
| 18:24 | arkh | code-ape: assuming you don't have memory concerns, (count (filter even? lazyseq)) will do it |
| 18:24 | arkh | ,(count (filter even? (range 10))) |
| 18:24 | clojurebot | 5 |
| 18:25 | code-ape | arkh: Cool! ... but I do have memory concerns sadly :/ |
| 18:25 | code-ape | Sorry, should have specified. |
| 18:30 | arkh | unfortunately I have to take off but in general I would recommend using (loop ...) and iterate through the lazy seq while keeping a tally of even numbers |
| 18:30 | code-ape | Thought as much! Thank you. |
| 18:30 | arkh | you wouldn't need to hold on to the head of the seq or generate an intermediate seq to count over that way |
| 18:31 | justin_smith | arkh: you can use reduce instead of loop for less boilerplate |
| 18:31 | justin_smith | arkh: this holds true with any loop that has exactly one sequence as input and always walks the sequence end to end |
| 18:32 | justin_smith | nb. I am differentiating input from accumulator here |
| 18:33 | justin_smith | ,(reduce (fn [n e] (if (even? e) (inc n) n)) 0 [0 1 2 3 4]) |
| 18:33 | clojurebot | 3 |
| 18:34 | code-ape | Perfect! Thank you justin_smith :) |
| 18:34 | amalloy | (count (filter even? (range 5))) |
| 18:34 | amalloy | oh i see that's there already, except for some reason you said that memory is a problem? |
| 18:35 | amalloy | it's obviously not |
| 18:35 | justin_smith | amalloy: that doesn't actually do the head holding arkh was talking about does it? right. |
| 18:35 | justin_smith | code-ape: yeah, the count/filter version is actually fine |
| 18:36 | code-ape | Oh, alright, good to know! |
| 18:36 | justin_smith | ,(transduce (filter even?) + 0 [0 1 2 3 4 5]) ; fancy-ass transducer version |
| 18:37 | clojurebot | 6 |
| 18:37 | justin_smith | wait, that adds the items not counting them |
| 18:46 | amalloy | justin_smith: you need to map constantly 1 |
| 18:46 | justin_smith | ahh, right |
| 18:46 | justin_smith | ,(transduce (comp (filter even?) (map (constantly 1))) + 0 [0 1 2 3 4 5]) |
| 18:46 | amalloy | ,(transduce (comp (filter even?) (map (constantly 1)) + 0 (range 6))) |
| 18:46 | clojurebot | 3 |
| 18:46 | clojurebot | #error {\n :cause "Wrong number of args (1) passed to: core/transduce"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: core/transduce"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 32]\n [sandbox$eval73 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox... |
| 18:46 | amalloy | whoops |
| 18:48 | justin_smith | parens are so sneaky |
| 18:48 | amalloy | my success rate of typing stuff into #clojure without paredit is high enough i'm willing to accept the occasional disaster |
| 19:46 | amalloy | hey, speaking of counting the number of items in a collection that satisfy a predicate, i just found this (anonymized) in a codebase at work: (reduce (fn [agg x] (if (pred x) (+ agg 1) agg)) 0 xs) |
| 19:47 | justin_smith | amalloy: it's more general because you could swap out 1 for another number |
| 19:47 | amalloy | nice |
| 19:47 | amalloy | multiplication is too expensive for sure |
| 19:53 | TEttinger | amalloy: ... is that a count on a filter, obfuscated? |
| 19:53 | amalloy | naturally |
| 19:54 | TEttinger | it makes me sad |
| 19:54 | amalloy | we were talking about that in here earlier, and someone proposed exactly the same bad solution |
| 20:09 | TEttinger | only reason I can think of that being useful, amalloy , is if (pred x) could return non-boolean results, so it might add different numbers based on x's value |
| 20:13 | amalloy | sure, and then you'd use (apply + (keep #(...) xs)) |
| 20:13 | amalloy | you still wouldn't write it yourself as a reduce |
| 20:35 | rhg135 | doesn't apply fail with really long seqs? |
| 20:37 | amalloy | no |
| 20:37 | amalloy | ,(apply +' (range 100000)) |
| 20:37 | clojurebot | 4999950000 |
| 20:37 | rhg135 | ,(apply +' (range 1e100)) |
| 20:38 | clojurebot | eval service is offline |
| 20:38 | amalloy | 1e100? you know how big that is? |
| 20:38 | rhg135 | hmm, maybe I had forgotten the +' |
| 20:38 | rhg135 | very big |
| 20:39 | rhg135 | I doubt I'll ever get a seq over 1e100 long, so all is good |
| 20:42 | rhg135 | ,(do (def count-with-pred (comp count filter)) (count-with-pred even? (range 1e10))) |
| 20:42 | clojurebot | eval service is offline |
| 20:42 | amalloy | 1e10 is also really big |
| 20:43 | amalloy | that's why i picked 1e5 |
| 20:43 | rhg135 | ,(do (def count-with-pred (comp count filter)) (count-with-pred even? (range 1e4))) |
| 20:43 | clojurebot | 5000 |
| 20:43 | rhg135 | I need to pick smaller numbers... |
| 20:45 | rhg135 | the factorial function is ridiculously easy in clojure |
| 20:45 | amalloy | yeah, the first one you picked is only like...many quintillions of times too big |
| 20:46 | lambda-11235 | amalloy, rhg135: (range 1e100) would easily take up all the memory on a supercomputer. |
| 20:47 | rhg135 | 1e10 isn't even that big though |
| 20:47 | amalloy | no, 1e10 is fine |
| 20:47 | amalloy | but clojurebot doesn't give you that much time |
| 20:47 | amalloy | adding up all the numbers between 1 and 10 billion |
| 20:47 | amalloy | takes more than a couple seconds |
| 20:48 | rhg135 | ,(iterate (partial * 2) (iterate inc 1)) |
| 20:48 | clojurebot | #<ClassCastException java.lang.ClassCastException: clojure.lang.Iterate cannot be cast to java.lang.Number> |
| 20:48 | rhg135 | oh' duh |
| 20:49 | rhg135 | yeah, I see how that could take a long time |
| 20:52 | rhg135 | I actually calculate the powers of 2 as a inefficient space-heater |
| 22:20 | binjured | gah, no matter what i try i can't manage to write a macro that generates this: https://gist.github.com/tdavis/d21ac8579e59d9f5049e except where "thing"/"Thing" is dynamic. i can't get a working IDeref to pass to the `recursive` function. it either ends up as a Var object (can't embed object) or a useless Symbol. |
| 22:22 | amalloy | okay, so what are you trying? |
| 22:23 | binjured | amalloy: i've tried a bunch of stuff. latest attempt is `(intern *ns* ~(symbol name))`, tried that with deref too |
| 22:25 | amalloy | ,((fn [vname] `#'~vname) 'thing) |
| 22:25 | clojurebot | (var thing) |
| 22:27 | binjured | the problem is building up the contents of that vector requires evaluation (or whatever ~ is called), so i end up with something like [other :- ... #<Var@...> ...] |
| 22:28 | TEttinger | `#'~ of course! how beautifully clear! |
| 22:28 | TEttinger | I'm glad amalloy understands this stuff! |
| 22:28 | amalloy | i mean, you can write (list `var thing) if you prefer |
| 22:29 | amalloy | it's really the same as any other syntax-quoted thing. you start with `, and then write the stuff you want to appear verbatim (here, #'), and then you put a ~ and the stuff you want to be variable |
| 22:31 | binjured | tried that, it ends up being a PersistentList |
| 22:33 | amalloy | binjured: just like with your question earlier this week, it will be easy to answer once you show me code you are actually running. if you take the things i say, interpret them, apply them, and report results, i have no idea how to help you, because i have no idea how you've interpreted my suggestions, or what context you've put them into |
| 22:33 | binjured | amalloy: yeah, i'll try to reproduce with a simple example. |
| 22:33 | amalloy | even a complicated example. if you pasted your entire macro i could fix it in thirty seconds |
| 22:33 | amalloy | i just can't debug guesses |
| 22:52 | binjured | amalloy: here we go. https://gist.github.com/tdavis/9d8b0f704f1a05f22d0b |
| 22:56 | amalloy | https://gist.github.com/amalloy/e2a4edeb7c22b33a9ed5 |
| 23:01 | amalloy | binjured: any good? |
| 23:01 | binjured | amalloy: testing! |
| 23:04 | binjured | amalloy: goddamn you, i think it worked... |
| 23:04 | amalloy | well i did tell you i knew the answer :P |
| 23:04 | binjured | <3 <3 <3 |