2015-08-17
| 00:00 | TEttinger | ,(map inc [1 2 3]) |
| 00:00 | clojurebot | (2 3 4) |
| 00:00 | TEttinger | ,(map first {:a 1 :b 2 :c 3}) |
| 00:00 | clojurebot | (:a :b :c) |
| 00:00 | TEttinger | ,(map inc #{1 2 3}) |
| 00:00 | clojurebot | (2 4 3) |
| 00:01 | TEttinger | important stuff real fast! the set is not in the order it came in for a reason! |
| 00:01 | slaterr | set is a binary tree with just a key I guess |
| 00:02 | palinkas | justin_smith: the only problem I can see with the sandboxing is that it won't even allow to create namespaces |
| 00:02 | justin_smith | palinkas: ahh, you should check out which sanbox clojurebot uses |
| 00:02 | TEttinger | sets and hash-maps are unordered by default. the order you get stuff out when you convert them to seqs, as map does and as most fns in clojure that work with collections do, is determined by a lot of factors but can't be relied on |
| 00:02 | TEttinger | that's why there are sorted-map and sorted-set |
| 00:03 | TEttinger | ,(map inc (sorted-set 1 2 3)) |
| 00:03 | clojurebot | (2 3 4) |
| 00:03 | TEttinger | 1 2 3 is already sorted, this actually sorts it again |
| 00:03 | TEttinger | ,(map inc (sorted-set 1 2 3 0 -1)) |
| 00:03 | clojurebot | (0 1 2 3 4) |
| 00:03 | slaterr | sorted-set = binary tree, set = hash table? |
| 00:05 | TEttinger | fairly close. sorted data structures use a (not sure if binary) tree for the sorting. I'll be perfectly honest, I have never used a hashtable. |
| 00:05 | TEttinger | sets ensure uniqueness, not ordering |
| 00:05 | TEttinger | that's their most important attribute |
| 00:06 | slaterr | yeah |
| 00:06 | TEttinger | sorted-sets ensure uniqueness and ordering by sorting (you can specify how to sort them too, so not limited to ascending order) |
| 00:06 | justin_smith | hash-sets use a fancy kind of tree optimized for immutable sets that do structural sharing |
| 00:06 | TEttinger | radix 32 hash-array-mapped trie? |
| 00:07 | TEttinger | "now you know why we don't talk about the internals" |
| 00:07 | justin_smith | TEttinger: the gotcha is that you can use an arbitrary sorting key, but if two things sort as equal by your function, then one of them will disappear |
| 00:08 | TEttinger | occasionally when you see stuff that draws from clojure, but isn't written in clojure, you may find people implementing HAMTs. I think we're all thankful that it's been done for us in clojure. |
| 00:11 | TEttinger | good thing to point out early on: you also have access to mutable, fixed-length, single-typed arrays and java's mutable data types in clojure. typically you only reach for those tools in the toolbox if you need to call java code that expects them, or if you have found a particular spot in your code that drastically needs performance and is a good fit for a mutable algorithm. |
| 00:11 | TEttinger | otherwise, those are not commonly used, because you lose the advantages of immutable code for reasoning about what something will have as its value |
| 00:13 | TEttinger | (also, even in the latter case, there are tools clojure has that let you create a temporarily mutable copy of a clojure data structure, mutate away, and return the mutated copy. don't worry about that stuff yet, but just know that clojure probably has the tools you need) |
| 00:15 | TEttinger | macros can be super useful but also can be hard to write. I think I have written between 2 and 3 macros total, you can go really far without needing them, and when you do need them, justin_smith loves writing small ones :) |
| 00:15 | justin_smith | haha |
| 00:16 | justin_smith | small macros as a service h-something |
| 00:17 | TEttinger | probably the most important thing you can do to learn clojure is to keep experimenting. it helps to learn more and more of the standard lib, which has a huge amount of useful functions for many, many common needs. |
| 00:17 | TEttinger | hey Olajyd! |
| 00:21 | palinkas | ,(ns test) |
| 00:21 | clojurebot | nil |
| 00:22 | palinkas | ,(def a "something") |
| 00:22 | clojurebot | #'sandbox/a |
| 00:22 | justin_smith | palinkas: any two commands are not in the same eval context |
| 00:22 | justin_smith | palinkas: maybe try using do |
| 00:22 | justin_smith | ,(do (ns 'test) (def a "OK")) |
| 00:22 | clojurebot | #error {\n :cause "clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol"\n :at [clojure.lang.RT$1 invoke "RT.java" 239]}]\n :trace\n [[clojure.lang.RT$1 invoke "RT.java" 239]\n [sandbox$eval79 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval79 invoke "NO_S... |
| 00:22 | justin_smith | hmm |
| 00:22 | justin_smith | ,(do (ns test) (def a "OK")) |
| 00:22 | clojurebot | #'test/a |
| 00:23 | palinkas | and also I guess once the request finished, the sandbox is destroyed |
| 00:24 | justin_smith | ,test/a |
| 00:24 | clojurebot | "OK" |
| 00:24 | justin_smith | palinkas: it has a set lifetime, but it isn't immediately destroyed |
| 00:25 | palinkas | the question is: can I run two sandbox side-by-side, without conflicting with each other? |
| 00:26 | justin_smith | as far as I know, yes |
| 00:26 | justin_smith | I have not personally tried it though |
| 00:27 | palinkas | any way to try it out? |
| 00:27 | palinkas | I assume that clojurebot here has only a single sandbox |
| 00:28 | justin_smith | palinkas: I thought that it was using a sandbox lib, but maybe it has one in its source... |
| 00:28 | palinkas | https://github.com/hiredman/clojurebot |
| 00:28 | justin_smith | palinkas: here's the subproject https://github.com/hiredman/clojurebot/tree/master/clojurebot-eval |
| 00:29 | Bronsa | lazybot uses clojail, clojurebot uses an internal one AFAIK |
| 00:29 | justin_smith | Bronsa: yeah, he was looking at clojail but found it too restrictive |
| 00:30 | slaterr | TEttinger appreciate all the pointers |
| 00:32 | TEttinger | no prob |
| 01:16 | weebz | I'm trying to do the following typecast in Clojure, but I can't get it to actually cast |
| 01:16 | weebz | ((JavascriptExecutor)driver).executeScript("return $('.cheese')[0]") |
| 01:16 | weebz | (cast JavascriptExecutor driver) returns a FirefoxDriver and not a JavascriptExecutor |
| 01:28 | hiredman | that is not how casting works |
| 01:29 | hiredman | casting (for java, and pretty much everywhere) isn't an operation that changes the value being cast, it just tells the compiler to treat the object differently |
| 01:30 | hiredman | so for dynamic langues (like clojure) casting doesn't really do anything |
| 01:31 | hiredman | and, even if does do something, it can't / won't change the dynamic type of an object |
| 02:37 | luxbock | how do I define a test.check generator that chooses elements from a collection I provide while shrinking so that it chooses the earlier elements more often? |
| 02:37 | luxbock | the doc of gen/one-of says "Shrinks toward choosing an earlier generator...", but I'm not seeing it |
| 02:37 | clojurebot | Huh? |
| 02:38 | luxbock | (frequencies (gen/sample (gen/one-of [(gen/return 1) (gen/return 2) (gen/return 3)]) 10000)) returns {3 3362, 2 3296, 1 3342} |
| 02:43 | Olajyd | Hi TEttinger :) |
| 02:45 | Olajyd | TEttinger, I’m a junior cloure dev, I hope u’ll be available for more problem solving :) |
| 02:45 | Olajyd | Hey justin_smith |
| 02:46 | TEttinger | all right, good stuff |
| 02:55 | nakiya | guys, any of you accessing Facebook graph api with clojure? What is your setup? |
| 03:11 | nakiya | ,(doc get) |
| 03:12 | clojurebot | "([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present." |
| 04:01 | clj123 | jdbc hive parameterized queries like ["create table as select col1, col2 from table1 where col1=?" "blah"] don't work. Is there any issue with jdbc.clj or hive ? |
| 04:39 | luxbock | I wonder if there's a reason for why assoc-in shouldn't take arbitrary amount of key-vectors and values instead of just one pair |
| 04:43 | gilliard | luxbock: I don't think there is http://dev.clojure.org/jira/browse/CLJ-1771 |
| 05:02 | crocket | How do I create a simple standalone command line application in clojure without leiningen? |
| 05:02 | crocket | I want to use clojure as a replacement of bash. |
| 05:04 | schmir | crocket: better take a look at boot: https://github.com/boot-clj/boot/wiki/Scripts |
| 05:05 | crocket | schmir, Is that it? |
| 05:06 | luxbock | crocket: http://clojure.org/repl_and_main |
| 05:14 | crocket | "java -cp clojure.jar clojure.main /path/to/myscript.clj" |
| 05:14 | crocket | Does "java -cp clojure.jar clojure.main /path/to/myscript.clj" execute -main in myscript.clj? |
| 05:15 | luxbock | I think so but I have never tried it |
| 05:15 | crocket | It executes nothing. |
| 05:17 | crocket | I saved http://dpaste.com/00MPG39 as doit.clj, and "java -cp ~/Apps/clojure-1.7.0.jar clojure.main doit.clj" executes nothing. |
| 05:20 | TEttinger | crocket: -main is only used by lein I think. you would need a toplevel call to (-main) most likely? not sure how it handles additional command line args |
| 05:27 | d0ky | hello i would know how to make https communication i found less-awful-ssl and by readme i have done the first test-ssl done but next part is to create ssl-context and i dont know how to generate to ca.crt ... third certificate of ssl-context ... as you can see here https://github.com/aphyr/less-awful-ssl |
| 05:33 | crocket | TEttinger, I don't know a way |
| 05:33 | crocket | how do I call -main? |
| 05:33 | crocket | Ah shit |
| 05:34 | crocket | I guess I have to -main directly in the source code. |
| 05:34 | crocket | I was right. |
| 05:35 | TEttinger | (-main) |
| 05:35 | TEttinger | it's a fn you defined |
| 05:36 | crocket | How do I get access to the list of arguments? |
| 05:37 | crocket | Oh, there is *command-line-args* |
| 05:37 | crocket | Not cool |
| 05:37 | TEttinger | good find |
| 05:37 | TEttinger | -main is a lein thing I think, it sets up the java-like main method |
| 05:38 | crocket | Anyway, it is relatively fast to load a .clj file via clojure.jar |
| 05:38 | TEttinger | the plain clojure.main method is uh different |
| 05:41 | crocket | Is clojure.java.shell/sh synchronous or asynchronous? |
| 05:45 | kwladyka | ah... how it was called... functions which one the same input give always the same output? |
| 05:45 | kwladyka | oh pure functions |
| 05:49 | crocket | boot-clj seems reasonable |
| 05:51 | crocket | TEttinger, (apply -main *command-line-args*) |
| 05:51 | TEttinger | ah there you go! |
| 05:52 | Olajyd | HI, TEttinger |
| 05:52 | crocket | How do I iterate over two seqs of the same length? |
| 05:52 | crocket | or multiple seqs |
| 05:52 | Olajyd | TEttinger, how do I serach for a particular character in a string? |
| 05:52 | crocket | Oh, seqs sounds like "sex". |
| 05:52 | TEttinger | Olajyd: do you want first match? |
| 05:53 | Olajyd | Yup |
| 05:53 | oddcully | .indexOf |
| 05:53 | Olajyd | oh more of a global search in a string |
| 05:53 | TEttinger | the regex functions like re-find will tell you if the character has been found, but not where it is. |
| 05:53 | Olajyd | oh hi odcully :) |
| 05:53 | TEttinger | (inc oddcully) |
| 05:53 | lazybot | ⇒ 15 |
| 05:54 | TEttinger | ,(.indexOf "alphabet" \p) |
| 05:54 | clojurebot | #error {\n :cause "No matching method found: indexOf for class java.lang.String"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No matching method found: indexOf for class java.lang.String"\n :at [clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 80]}]\n :trace\n [[clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 80]\n [clojure.lang.Reflector invokeInst... |
| 05:54 | TEttinger | ,(.indexOf "alphabet" "p") |
| 05:54 | clojurebot | 2 |
| 05:54 | TEttinger | so that can take a single-letter string or a multiple-letter one |
| 05:54 | TEttinger | ,(.indexOf "alphabet" "bet") |
| 05:54 | clojurebot | 5 |
| 05:57 | Olajyd | aite Tettinger, thanks |
| 05:58 | TEttinger | thanks to oddcully too! |
| 05:58 | crocket | Is (map list list-2 list-2) an ok way to zip several sequences? |
| 05:59 | crocket | (map list list-1 list-2 ...) |
| 05:59 | TEttinger | yeah, or mapcat, crocket |
| 05:59 | crocket | ,(doc mapcat) |
| 05:59 | TEttinger | depending on what you want for output |
| 05:59 | clojurebot | "([f] [f & colls]); Returns the result of applying concat to the result of applying map to f and colls. Thus function f should return a collection. Returns a transducer when no collections are provided" |
| 05:59 | TEttinger | ,(mapcat list (range 10) (range 20)) |
| 05:59 | clojurebot | (0 0 1 1 2 ...) |
| 06:00 | TEttinger | ,(mapcat list (range 10) (range 10 20)) |
| 06:00 | crocket | This is not ideal |
| 06:00 | clojurebot | (0 10 1 11 2 ...) |
| 06:00 | TEttinger | ,(map list (range 10) (range 10 20)) |
| 06:00 | clojurebot | ((0 10) (1 11) (2 12) (3 13) (4 14) ...) |
| 06:00 | crocket | ,(doc zipmap) |
| 06:00 | clojurebot | "([keys vals]); Returns a map with the keys mapped to the corresponding vals." |
| 06:02 | TEttinger | ,(zipmap (range 5) (range 10 15)) |
| 06:02 | clojurebot | {0 10, 1 11, 2 12, 3 13, 4 14} |
| 06:03 | crocket | zipmap doesn't scale beyond 2 |
| 06:03 | crocket | ,(map list [1 2 3] [4 5 6] [7 8 9]) |
| 06:03 | clojurebot | ((1 4 7) (2 5 8) (3 6 9)) |
| 06:03 | TEttinger | yeah |
| 06:03 | crocket | ,(doc vector) |
| 06:03 | clojurebot | "([] [a] [a b] [a b c] [a b c d] ...); Creates a new vector containing the args." |
| 06:03 | crocket | ,(map vector [1 2 3] [4 5 6] [7 8 9]) |
| 06:03 | clojurebot | ([1 4 7] [2 5 8] [3 6 9]) |
| 06:03 | TEttinger | ,(mapv vector [1 2 3] [4 5 6] [7 8 9]) |
| 06:03 | crocket | ,(map seq [1 2 3] [4 5 6] [7 8 9]) |
| 06:03 | clojurebot | [[1 4 7] [2 5 8] [3 6 9]] |
| 06:03 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: core/seq--4116> |
| 06:04 | TEttinger | list is the fn used to create seqs, oddly -- seq converts a collection to a seq if non-empty, returns nil otherwise |
| 06:10 | crocket | http://dpaste.com/1R82TJ9 hangs |
| 06:10 | crocket | http://dpaste.com/1R82TJ9 hangs on line 15. |
| 06:10 | crocket | why? |
| 06:10 | clojurebot | because that's not how macros work |
| 06:15 | Olajyd | TEttinger, say after getting the index of the character in the string, we want to replace that character with another character? |
| 06:15 | TEttinger | crocket: http://clojuredocs.org/clojure.java.shell/sh#example-542692d6c026201cdc3270e7 |
| 06:15 | TEttinger | Olajyd: off the top of my head, I don't have an answer, but there is likely something in the Java String API. |
| 06:16 | Olajyd | I’m not sure it this is the right approach but this is what I have in mind (assoc "alphabet" (.indexOf "alphabet" “p”) "s") |
| 06:17 | TEttinger | that sounds like a better fit for regexes. |
| 06:17 | TEttinger | ,(clojure.string/replace "alphabet" #"p" "s") |
| 06:17 | clojurebot | "alshabet" |
| 06:18 | TEttinger | that does all of the occurences though. |
| 06:18 | TEttinger | ,(clojure.string/replace "alphabet" #"a" "o") |
| 06:18 | clojurebot | "olphobet" |
| 06:18 | TEttinger | ,(.replaceFirst "alphabet" "a" "o") |
| 06:18 | clojurebot | "olphabet" |
| 06:19 | TEttinger | here's that documentation https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replaceFirst(java.lang.String,%20java.lang.String) |
| 06:19 | crocket | TEttinger, My code hangs and does nothing. |
| 06:19 | TEttinger | crocket: for 1 minute after when it may have exited? |
| 06:20 | TEttinger | if that's the case, it's related to using futures without calling a specific function to shutdown agents |
| 06:21 | TEttinger | (I also don't know if ffmpeg is getting the args it wants) |
| 06:21 | TEttinger | http://clojuredocs.org/clojure.core/future#example-542692c9c026201cdc326a7b |
| 06:22 | crocket | TEttinger, If I execute shell/sh in REPL, it works fine. |
| 06:23 | TEttinger | I wonder if it's getting bad args somehow, like just "-" which some programs interpret as "read from stdin until you get an EOF" |
| 06:25 | crocket | what |
| 06:25 | TEttinger | wondering if ffmpeg is, in the program version, receiving the wrong args |
| 06:26 | crocket | As you can see on https://github.com/clojure/clojure/blob/master/src/clj/clojure/java/shell.clj#L128 , futures are resolved. |
| 06:26 | TEttinger | try printing *command-line-args* |
| 06:26 | crocket | *command-line-args* is not used yet. |
| 06:27 | TEttinger | you saw the line above that, right? |
| 06:27 | TEttinger | exit-code (.waitFor proc) |
| 06:28 | crocket | Somehow shell/sh just hangs. |
| 06:28 | TEttinger | if ffmpeg isn't returning, it will hang |
| 06:29 | TEttinger | 3:30 AM. g'night |
| 06:29 | crocket | ok |
| 06:32 | crocket | You're right |
| 06:32 | crocket | shell/sh hangs for some reason. |
| 06:32 | crocket | ffmpeg returns |
| 06:43 | drwin | I have defined a defrecord, and I want to implement my own IPrintWithWriter, how to override defrecord's default one? |
| 06:44 | crocket | TEttinger2, shutdown-agents solves the waiting problem. |
| 06:56 | crocket | oh |
| 06:56 | crocket | ^"[Ljava.lang.String;" (into-array cmd) |
| 06:56 | crocket | What is this? |
| 06:56 | crocket | A type hinting? |
| 07:10 | opqdonut | crocket: yes |
| 07:11 | opqdonut | [Ljava.lang.String; is to the jvm what java.lang.String[] is to java, i.e. an array of Strings |
| 07:11 | crocket | How confusing |
| 07:12 | opqdonut | yeah the syntax could be better |
| 07:28 | varnie | good day. |
| 07:29 | varnie | newbie here. can you help me to figure out why ":require some.lib" doesn't work in case I use it directly in myProgram.clj file and run it through lein repl using (load-file ...)? But it works if I put the whole library name into that file and remove that ":require"? I can provide a sample of code I am talking about. |
| 07:31 | varnie | it gives me "CompilerException java.io.FileNotFoundException: Could not locate ..." error |
| 07:36 | snowell | Are you running the lein repl from the directory that contains the project.clj? That's the way to ensure that dependencies are loaded on the classpath |
| 07:40 | varnie | hmm, no, but if I remove that :require it works fine. I provide the full path to the project.clj in (load-file ...) |
| 07:43 | varnie | well, here're two samples, the first one works, the second one does not: |
| 07:43 | varnie | 1) http://pastebin.com/xQZtxFnG |
| 07:43 | varnie | 2) http://pastebin.com/aJdYku9n |
| 07:44 | snowell | Honestly I've never used (load-file) |
| 07:44 | varnie | huh, okay. ;) |
| 07:46 | snowell | What if you try this: http://pastebin.com/daE0VCDv |
| 07:46 | varnie | then I have the same error |
| 07:46 | snowell | Taking :require out of the ns and having it as its own statement |
| 07:46 | varnie | wait, I'll rerun lein repl and try again... |
| 07:47 | varnie | same problem. |
| 07:48 | schmir | varnie: why don't you use require instead of load-file? |
| 07:48 | snowell | I find it hard to believe that specifying the full namespace of the function works but having a (require) doesn't |
| 07:49 | snowell | Not saying I don't believe you :) |
| 07:49 | varnie | schmir, what do you mean? |
| 07:49 | varnie | say, I want to test out my little function, which is written in foo.clj, it (that function) requires some libraries. where should I 'require' them? |
| 07:50 | varnie | I suppose it would be sane to require them in that file. |
| 07:50 | varnie | why not? |
| 07:50 | schmir | varnie: using load-file is unusual. normally you define your functions inside a .clj file for a single namespace and load that file with (require my-namespace.foo) instead of load-file |
| 07:50 | varnie | schmir, ah, I didn't know. Thank you. |
| 07:52 | varnie | schmir, can you please show how should my code snippet look then? |
| 07:54 | schmir | http://pastebin.com/aJdYku9n looks fine (besides the namespace should have at least 2 components...i.e. it should be something like foo.core) |
| 07:55 | schmir | in your REPL, you can then (require 'foo) and either call foo/print-extension or switch to the namespace with (in-ns 'foo) |
| 07:55 | schmir | varnie: are you using an IDE? |
| 07:56 | varnie | no, I do not. |
| 07:56 | varnie | FileNotFoundException Could not locate foo__init.class or foo.clj on classpath: clojure.lang.RT.load (RT.java:443) |
| 07:56 | varnie | I should run lein repl in the directory where my clj file is? |
| 07:56 | schmir | where your project.clj is |
| 07:56 | schmir | varnie: did you create a project? |
| 07:56 | varnie | I have only one file, get-extension.clj. |
| 07:56 | varnie | no |
| 07:57 | schmir | ok. that explains a lot! |
| 07:57 | varnie | that's exactly what I am trying to understand ;) |
| 07:57 | varnie | is it possible to have a single clj file without project? |
| 07:58 | schmir | yes, you can then use load-file to load the file from the REPL :) |
| 07:58 | schmir | but you shouldn't do that |
| 07:58 | varnie | okay, then why the second example does not work: http://pastebin.com/aJdYku9n ? |
| 07:58 | schmir | (at least not now, since you said your a beginner) |
| 07:59 | schmir | I think load-file doesn't like the namespace declaration |
| 07:59 | gjrig | varnie: for sure. The main reason people use fancy projects & build toold (if you ask me) is because the line to run a single .clj file looks ugly. http://stackoverflow.com/questions/7656523/how-can-i-run-a-clj-clojure-file-i-created has good answers |
| 07:59 | schmir | varnie: you really should set up a project |
| 07:59 | varnie | is there any way I can use "short cut/alias" for that long library name in my second example? |
| 08:00 | varnie | I understand what you guys say, but I find it a bit awkward that I have to create project only for testing some simple function... |
| 08:01 | schmir | varnie: without the namespace declaration the require looks like (require '[org.apache.commons.io.FilenameUtils :as FileNameUtils]) |
| 08:01 | gjrig | Hi! I'm writing a program where users will be able to add plugins, which are also written in Clojure. I would like to have some sort of security, so that users can't do bad things like write to disk, run a shell or call arbitrary Java code. Is there some way to ONLY expose functions that have no side effects? Then their plugins can be pure functions, and I can be sure no malicious code is run |
| 08:02 | varnie | schmir, then I have another error: "'Found lib name 'org.apache.commons.io.FilenameUtils' containing period with prefix 'quote'. lib names inside prefix lists must not contain periods" |
| 08:03 | varnie | oh, wait... |
| 08:03 | oddcully | wouln't an import here more appropriate? |
| 08:03 | oddcully | s/here/& be/ |
| 08:04 | varnie | no matter what I try, I end up with "CompilerException java.lang.ClassNotFoundException ..." |
| 08:05 | schmir | varnie: you really want a dedicated project, since you use apache commons |
| 08:05 | varnie | okay, thank you all. |
| 08:05 | schmir | varnie: boot scripts may be another option: https://github.com/boot-clj/boot/wiki/Scripts |
| 09:34 | justin_smith | varnie: that's not a namespace, that's a class |
| 09:35 | varnie | yup |
| 09:35 | justin_smith | so you've sorted it out then |
| 09:37 | justin_smith | varnie: the main reason to use lein or boot (or even maven) is to set up your class path, once your dependencies grow beyond a few items |
| 09:38 | varnie | justin_smith, do you agree that for my purpose I should create a new project? |
| 09:39 | justin_smith | varnie: it depends, if you only have the one dependency, you might be able to get by without a tool like lein, but the more deps you have, the easier it is to just use lein |
| 09:40 | varnie | I see. |
| 09:40 | justin_smith | just don't assume that "not having a project" is in any way simpler - it really isn't. It just means you have to do all the classpath and configuration stuff it could do for you, by hand. |
| 09:42 | varnie | yes, that was my initial misunderstanding. |
| 09:50 | d0ky | hello has anybody experience with https ? i try to setup it using less-awful-ssl but do not know to generate ca.crt used in this readme at ssl-context https://github.com/aphyr/less-awful-ssl any help please ? |
| 09:51 | xemdetia | d0ky, the idea of the ca.crt is you getting it signed from someone else |
| 09:51 | xemdetia | if you don't care about it being valid to your browser just use a self signed cert |
| 09:51 | xemdetia | (in that list of instructions) |
| 09:52 | tdammers | or, the middle ground, create your own CA and install its cert on all the devices you care about, via a trusted out-of-band channel |
| 09:52 | tdammers | then you can use that CA to sign your own certs |
| 09:52 | xemdetia | either way that instruction list is needlessly confusing for a one-off test |
| 09:52 | d0ky | but i did all what was in instructions and worked only test-ssl but ca.cert was not generated |
| 09:53 | xemdetia | I assume it is from that CA.pl file |
| 09:55 | d0ky | i so should i generate one more certificate as it is in that instructions ? because when i looked here http://immutant.org/documentation/current/apidoc/guide-web.html#h5315 there is also ca.crt but i have no experience with ssl and that library needs 3 files |
| 09:56 | d0ky | especially function ssl-context not that library |
| 09:59 | xemdetia | d0ky, do you need your certificates to be things you can validate |
| 09:59 | xemdetia | it's easier to just self-sign a cert from the keystore |
| 10:00 | xemdetia | keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass password -validity 360 -keysize 2048 |
| 10:00 | xemdetia | and just use the first option |
| 10:00 | d0ky | many thanks :) i will try it |
| 10:00 | xemdetia | (from the immutant docs) |
| 10:12 | Guest58141 | \quit |
| 10:58 | troydm | hey guys, can u guys sugest best book to start Clojure with? |
| 10:59 | timvisher | troydm: have you worked through Clojure for the Brave and True? |
| 10:59 | timvisher | so slf4j doesn't implement fatal. this faq implies that they don't think you need it because of the Marker interface. can i use that from clojure.tools.logging? http://www.slf4j.org/faq.html#fatal |
| 11:00 | troydm | timvisher: no, is this book game oriented? |
| 11:00 | timvisher | troydm: nope. http://www.braveclojure.com/ |
| 11:00 | timvisher | troydm: if you want a book on lisp and games, try The Land of Lisp |
| 11:01 | timvisher | you'll glean much from it despite it not being about clojure directly |
| 11:01 | troydm | timvisher: I mean is it something like Land of Lisp book |
| 11:01 | timvisher | troydm: oh, then no :) |
| 11:01 | timvisher | not at all |
| 11:01 | troydm | timvisher: ic, I was somehow confused |
| 11:01 | troydm | timvisher: I thought I've seen a book that describes Clojure from perspective of programming a game |
| 11:02 | troydm | timvisher: I guess I was confused because I though that Clojure for the brave and true was that book |
| 11:03 | troydm | timvisher: ahh, I know why I was confused because "Clojure for the Brave and True" on amazon has a title like a book describing games |
| 11:03 | troydm | I mean title cover |
| 11:05 | timvisher | troydm: so if you make it through CftBaT, i'd probably recommend Programming Clojure and then The Joy of Clojure after that. |
| 11:07 | troydm | timvisher: I though that if u'll read Joy of Clojure there is no need to read Programming Clojure |
| 11:08 | timvisher | troydm: imo, they're somewhat, but not entirely, orthogonal |
| 11:08 | timvisher | others may disagree |
| 11:09 | timvisher | certainly i found programming clojure to more approachable, but i think joy of clojure is the best book on the philosophy of clojure there is. |
| 11:09 | timvisher | programming clojure is more practical in that sense |
| 11:10 | troydm | timvisher: from what I see in Clojure for The brave, it's not too detailed, rather it's like beginners book, I was thinking of something more advanced that would describe how to use namespaces, lein and nrepl |
| 11:10 | tdammers | frankly, I found Clojure For The Brave annoyingly silly with all the hobbit examples and such |
| 11:10 | justin_smith | troydm: lein and nrepl are just tooling, a book shouldn't even be covering them |
| 11:11 | justin_smith | any more than a C book should have chapters on make and pkgconfig |
| 11:12 | troydm | justin_smith: yeah I know, but atleast a book about how to structure Clojure project and how to correctly use namespaces and concurrency or atleast something that is close to that |
| 11:12 | troydm | justin_smith: also tooling is also important aspect of using programming language, and I think it needs some more spotlight |
| 11:12 | justin_smith | troydm: I think Clojure Programming is the book you want |
| 11:13 | troydm | justin_smith: ic, okey thanks |
| 11:13 | justin_smith | troydm: the problem is that tooling moves too fast for books to be a good source - I doubt there's any books on boot yet, and if there are any about lein, I assure you they are out of date already |
| 11:14 | justin_smith | I guess this also reflects where clojure is in its lifecycle |
| 11:16 | troydm | justin_smith: ic, that's a good point |
| 11:25 | timvisher | troydm: no book will do a good job of covering the tooling |
| 11:25 | timvisher | the tooling's documentation barely does an adequate job of covering the tooling. :) |
| 11:25 | timvisher | best place to come for tooling questions is usually here, in all honesty |
| 11:26 | justin_smith | timvisher: the slack channel is becoming a better and better option I think, more's the pity because I like IRC a lot better and have been too lazy to set up slack via IRC |
| 11:26 | timvisher | justin_smith: wait, there's an official slack channel now? |
| 11:27 | justin_smith | #clojurians |
| 11:27 | justin_smith | quite active! |
| 11:27 | timvisher | suck :( |
| 11:27 | timvisher | slack is eating all that is beautiful. :) |
| 11:27 | timvisher | how does one sign up for said channel? |
| 11:27 | tdammers | question here: why is the default license for a new lein project the Eclipse Public License? Wouldn't "All Rights Reserved" make more sense? |
| 11:27 | justin_smith | timvisher: trying to recall how I did it, one moment... |
| 11:28 | justin_smith | timvisher: get your invite here http://clojurians.net/ |
| 11:28 | justin_smith | tdammers: because technomancy is a free-software-hippy |
| 11:29 | justin_smith | tdammers: in all seriousness, I think it's a subtle nudge to consider open sourcing your code (see also how well clojars works out of the box...) |
| 11:29 | tdammers | don't get me wrong, I'm pretty set on software freedom myself, but I still think this is wrong |
| 11:30 | tdammers | if you default to "All Rights Reserved", the worst that can happen is that you accidentally don't grant people a license |
| 11:30 | wamaral | and more people would complain about that |
| 11:30 | tdammers | no problem, just change the text, push, there you go, open source |
| 11:30 | tdammers | "All Rights Reserved" is the default anyway (legally speaking) |
| 11:31 | tdammers | but when you default to some other license, then it can (and probably does) happen that you accidentally grant licenses that you don't intend to grant |
| 11:31 | tdammers | and you can't really fix it either once someone has accepted such a license |
| 11:34 | amalloy | tdammers: feel free to release a build tool that expresses this opinion, or even just for lein. or add a new lein template |
| 11:34 | amalloy | *fork |
| 11:46 | tdammers | amalloy: "patches welcome"? |
| 11:46 | cored | justin_smith: thanks for the hint on clojurians |
| 11:46 | justin_smith | cored: np |
| 11:47 | cored | justin_smith: it wasn't that hard to st it with weechat and now I have everything in the same place |
| 11:47 | cored | the only downside of using Slack through irc is that you won't get all the magic as with their client |
| 11:47 | amalloy | well, that particular patch is probably not welcome. but technomancy has the right to do whatever he wants with leiningen, and you have the right to wish he would do something else |
| 11:47 | tdammers | amalloy: sure |
| 11:48 | justin_smith | cored: yeah, I use the client, I'm happy to live without the magic (except for eg. at work where I need the magic to get work done) |
| 11:48 | cored | I'm using the irc client for everyting |
| 11:48 | troydm | me too |
| 11:48 | cored | still can't think of a use case that I really need the magic soo bad |
| 11:48 | cored | I mean, I see annuncements in weechat too |
| 11:49 | justin_smith | cored: my team uses documents uploaded to slack for things like "help me debug this stack trace" |
| 11:49 | justin_smith | or is that something you can use via irc |
| 11:49 | cored | well |
| 11:49 | cored | you will see a link and when you follows that link you will get the file |
| 11:50 | cored | it works for me |
| 11:50 | justin_smith | what about creating documents? |
| 11:50 | tdammers | my team mainly communicates using reactiongifs served by a bot |
| 11:50 | tdammers | that doesn't quite work over IRC |
| 11:50 | justin_smith | tdammers: haha, yeah, good luck making that work on IRC yeah |
| 11:51 | tdammers | it "works", but it's extremely clumsy, because you're basically opening a browser tab for every message |
| 11:51 | cored | justin_smith: well, I don't do that normally I just sent a private gist |
| 11:51 | tdammers | might as well use it in the browser in the first place |
| 11:51 | cored | tdammers: what I see is stuffs like ::emoticon:: |
| 11:51 | justin_smith | cored: yeah, it's easier to just use the same flow, instead of being the one guy who does something the weird way |
| 11:51 | cored | and then again, I don't care about that too much, but I agree is not the same experience |
| 11:52 | justin_smith | my team uses the emoji-reactions for things like voting too (like how many people clicked smiley reaction vs. blow-everything-up reaction) |
| 11:52 | cored | justin_smith: sure, maybe I'll switch if everybody is doing stuffs through Slack entirely. The downside for me is having too many tabs opens for each Slack channel |
| 11:52 | justin_smith | right |
| 11:53 | justin_smith | cored: I'm sure I could make it all work, but in terms of playing nicely with the team, I don't want to be the one guy that forces you to do everything differently |
| 11:53 | justin_smith | humans have API conventions too :) |
| 11:54 | cored | yes |
| 11:54 | cored | I guess I'm waiting for that moment in which everything is getting done through Slack |
| 11:55 | cored | even coding itself ;-P which probably will happen at some point |
| 11:55 | cored | people love Slack's ui |
| 11:55 | justin_smith | "hey guys, good news! we're using slack instead of git now" |
| 11:55 | cored | hehe |
| 11:56 | cored | yes |
| 11:56 | cored | probably along those lines |
| 11:56 | tdammers | cored: yeah, no, those are doable, but people trigger the bot's plugins to have it serve reaction gifs |
| 11:57 | cored | oh yes |
| 11:57 | cored | that's one of the things that I can't do with irc |
| 11:57 | cored | like sending /commands |
| 11:57 | oddcully | dystopia... |
| 12:14 | pflanze | Hello. How do you turn a list holding 2*n items into a list holding n sublists of 2 items each? (a 1 b 2) -> ((a 1) (b 2)) or ([a 1] [b 2]) |
| 12:14 | justin_smith | pflanze: partition, or partition-all |
| 12:15 | justin_smith | depending on what you want to do with any potential remainder |
| 12:15 | justin_smith | ,(partition 2 '(a 1 b 2)) |
| 12:15 | clojurebot | ((a 1) (b 2)) |
| 12:15 | justin_smith | ,(partition-all 2 '(a 1 b 2 c)) |
| 12:15 | clojurebot | ((a 1) (b 2) (c)) |
| 12:15 | justin_smith | ,(partition 2 '(a 1 b 2 c)) |
| 12:15 | clojurebot | ((a 1) (b 2)) |
| 12:16 | pflanze | Thanks! What about the second case (which it seems is commonly needed for macros)? |
| 12:16 | justin_smith | if you need vectors? you'll likely have to map vec over the result |
| 12:17 | justin_smith | ,(map vec (partition 2 '(a 1 b 2 c))) |
| 12:17 | clojurebot | ([a 1] [b 2]) |
| 12:17 | pflanze | Alright. |
| 12:17 | justin_smith | you could also use transducers for this I think |
| 12:17 | justin_smith | ,(into [] (comp (partition 2) (map vec)) '(a 1 b 2 c)) |
| 12:17 | clojurebot | #error {\n :cause "Wrong number of args (1) passed to: core/partition"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: core/partition"\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$eval121 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbo... |
| 12:17 | justin_smith | I guess not |
| 12:18 | justin_smith | ,(into [] (comp (partition-all 2) (map vec)) '(a 1 b 2 c)) |
| 12:18 | clojurebot | [[a 1] [b 2] [c]] |
| 12:18 | justin_smith | interesting, partition-all has a transduce but partition does not. Makes sense, I guess. |
| 12:19 | pflanze | Why do you think it makes sense? |
| 12:20 | justin_smith | because handling the straggling items is the general case, and you can derive the dropping behavior from that. It's still a bit weird I guess. |
| 12:22 | justin_smith | also somewhat interesting, you can't access the step arg as a transducer |
| 12:22 | justin_smith | ,(partition 2 1 [:a 0 :b 1]) |
| 12:22 | clojurebot | ((:a 0) (0 :b) (:b 1)) |
| 12:23 | pflanze | BTW SRFI-1 from Scheme has "partition" for a different purpose: partition pred list -> [list list] |
| 12:23 | pflanze | People can never agree on such fundamentals. |
| 12:24 | justin_smith | pflanze: yeah, we call that split-with |
| 12:24 | justin_smith | (doc split-with) |
| 12:24 | clojurebot | "([pred coll]); Returns a vector of [(take-while pred coll) (drop-while pred coll)]" |
| 12:24 | amalloy | justin_smith: sure? i'd guess it's more like (juxt filter remove) |
| 12:25 | pflanze | http://srfi.schemers.org/srfi-1/srfi-1.html#FilteringPartitioning |
| 12:25 | pflanze | I think amalloy is right. |
| 12:25 | justin_smith | yeah |
| 12:26 | justin_smith | ((map (group-by pred l)) [true false]) |
| 12:26 | justin_smith | not quite |
| 12:26 | pflanze | Anyway, I'm finding myself needing the (partition 2) case so often, that I'm probably just going to write and name my own :o. |
| 12:26 | justin_smith | ,(map (group-by even? (range 20)) [true false]) |
| 12:26 | pflanze | Also, one that errors out when there is a superfluous item. |
| 12:26 | clojurebot | ([0 2 4 6 8 ...] [1 3 5 7 9 ...]) |
| 12:27 | pflanze | Now I just need a name that nobody agrees on. |
| 12:28 | pflanze | Perhaps just list->alist |
| 12:29 | justin_smith | oh man, alists |
| 12:30 | pflanze | Well, Clojure removes the ambiguity of whether the pairs are dotted ones or not! |
| 12:31 | pflanze | But I guess Clojurians just use maps instead? |
| 12:31 | pflanze | Are maps ordered? |
| 12:32 | {blake} | pflanze: Maps are not ordered, but that is a less meaningful statement than it might be in another language. |
| 12:33 | pflanze | Why? |
| 12:33 | clojurebot | Why is the ram gone is <reply>I blame UTF-16. http://www.tumblr.com/tagged/but-why-is-the-ram-gone |
| 12:41 | clojer | What's the best way to include in a Clojure project java files downloaded directly from github, ie. not from Maven? |
| 12:42 | {blake} | pflanze: Because the data is the thing, not the container. I mean, maps aren't sorted but you can sort maps. |
| 12:42 | {blake} | This is sort of the perversity of OO: It teaches you to value the container more than the data. |
| 12:43 | {blake} | (With all due respect to Alan Kay, who had nothing of the sort in mind when he coined the term "object oriented".) |
| 12:43 | pflanze | What does this have to do with containers or OO? |
| 12:44 | pflanze | Sometimes, e.g. argument parsing, it's important whether the same key appears again, and in which order. I want to maintain that. |
| 12:45 | {blake} | pflanze: You asked if a map was ordered. It's not. And it will have no duplicate keys. |
| 12:46 | pflanze | Yes, the duplicate keys really is a step beyond. |
| 12:47 | pflanze | Still not sure what you meant with the valuing of the container. |
| 12:47 | {blake} | Arguments come in as a vector, I believe, which is ordered. |
| 12:47 | {blake} | pflanze: Sorry, I'm in a "teaching beginners" headspace which also includes a "re-evaluating my own notions" headspace. |
| 12:47 | {blake} | When I started with Clojure, I was positively offended that I could pass in a vector and get back a list. |
| 12:48 | {blake} | Now I blithely flip between list, vector, set and map. |
| 12:48 | {blake} | I basically don't care, until I do. |
| 12:50 | pflanze | Okay. Well, as a Schemer, I'd agree that Clojure looks like having too many data types, which is more OO philosophy than lisps had. (But then I don't really care either.) |
| 12:50 | {blake} | So, e.g., I start with a list of words in a book. Then I maybe put it into a set to find the number of unique words, or roll back to a map of frequencies of words use. And if I sort my map, I get a list again. |
| 12:52 | pflanze | Ok. Sorting a map into a list is not the same as having a sorted map in the case where you need to add or remove items incrementally, complexity wise. |
| 12:52 | {blake} | Elucidate. |
| 12:52 | pflanze | (Unless Clojure goes crazy OO here and has SortedMap underneath really.) |
| 12:53 | pflanze | What I mean is that as long as a map is a map, you can add and remove items efficiently. Once you've sorted it, you lose that property. |
| 12:54 | pflanze | Unlike a sorted map implementation which stores the items sorted but efficiently addable/removable. |
| 12:55 | justin_smith | pflanze: we also have sorted-map |
| 12:56 | pflanze | Okay, fine. |
| 12:56 | justin_smith | pflanze: though I think what you are describing is just a sequence of two element vectors (since you want to preserve ordering and duplicates) |
| 12:56 | {blake} | justin_smith: It's not a data structure, though, right? |
| 12:56 | justin_smith | {blake}: it is a data structure |
| 12:56 | justin_smith | ,(type (sorted-map :a 0 :b 1)) |
| 12:56 | clojurebot | clojure.lang.PersistentTreeMap |
| 12:58 | {blake} | justin_smith: Oh! Interesting. |
| 13:00 | {blake} | ,(type (array-map [0 1 2] [3 4 5])) |
| 13:00 | clojurebot | clojure.lang.PersistentArrayMap |
| 13:00 | justin_smith | pflanze: I'd argue that even if clojure's proliferation of data structures is "oo nonsense", it's "oo nonsense" that effectively implements functional ends, since we have structures that can effectively share internal structure rather than doing deep copies on every operation |
| 13:01 | bcacc | clojer: try looking up lein-localrepo |
| 13:02 | clojer | bcacc: Thanks |
| 13:02 | {blake} | These are Java classes specifically created for Clojure. |
| 13:04 | pflanze | justin_smith, hey, I'm not claiming it's nonsense :). The unusual part for a Lisper/Schemer is really just that they are also used in the language syntax. |
| 13:05 | pflanze | Well, vec is. Not sure about the others. |
| 13:05 | justin_smith | ahh, right |
| 13:05 | pflanze | Also, missing dotted lists. |
| 13:05 | justin_smith | pflanze: yeah we have {} for maps, [] for vectors, #{} for sets |
| 13:06 | justin_smith | and in terms of syntax {} is used for metadata |
| 13:06 | pflanze | Ok. |
| 13:06 | justin_smith | trying to think of a language feature that uses #{} though... |
| 13:06 | justin_smith | oh, {} is also used for function preconditions and postconditions |
| 13:07 | amalloy | i don't really understand the idea of "missing" dotted lists. what do they give you semantically that just using a vector or a list doesn't? |
| 13:07 | justin_smith | amalloy: throwing an error if you try to conj onto it I guess? |
| 13:08 | justin_smith | maybe not even that |
| 13:08 | justin_smith | memory is fuzzy - errors for some list operations certainly |
| 13:11 | pflanze | amalloy, e.g. Scheme uses them for argument parsing: the dotted element slurps up the remaining arguments. |
| 13:11 | amalloy | sure, but that's just a syntactic thing, not data structures. (foo [x & xs]) serves just as well there |
| 13:12 | pflanze | amalloy, this is nicer than having special syntax for it; your code will work with them pretty much transparently. |
| 13:12 | pflanze | Well, data structures are syntax are data structures. |
| 13:14 | amalloy | that's true, but there are very different priorities for things that happen at runtime vs at compile time |
| 13:14 | amalloy | data structures that perform well matter at runtime, and convenient syntax matters at compile time |
| 13:15 | pflanze | It's not about speed, but about convenience/beauty. |
| 13:15 | pflanze | Since Lisp is about having compile time at run time, this arguably matters. |
| 13:18 | pflanze | Not even Schemers fully understand it though: the SRFI-1 library has comments about a discussion on this topic, and the decision was taken to ignore dotted lists for this library. |
| 13:18 | pflanze | Which is fair in some situations (better error reporting if dotted lists can't happen), but a hindrance in others (processing such syntax). |
| 13:19 | pflanze | So I guess over time, the use of dotted lists has been diluted increasingly, not only in Clojure, but already before. |
| 13:19 | pflanze | I think it's a pity. But whatever. |
| 13:20 | pflanze | The only thing I'm thinking is that if you're increasingly moving away from linked lists for syntax, you'll end up with ML/Haskell in the end. |
| 13:21 | pflanze | Which is fine, too, of course, but, again, "whatever". |
| 13:21 | sg2002 | Hi all. I've been playing around with cider debugger. It seems to be progressing well. And now I have the most obvoius idea ever - to make debug-on-exception work. Since it's so obvious there's probably someone here who already did this. So what would be the easiest way? |
| 13:21 | wasamasa | sg2002: you should prod its author, you know |
| 13:22 | wasamasa | sg2002: and no, that line of reasoning is faulty |
| 13:23 | justin_smith | sg2002: iirc the debugger only works if you have a separate debugging vm that connects and controls the process. The extra step I guess would be a global exception handler in the debugged vm that invokes some procedure in the debugging one? |
| 13:25 | expez | how does core.test change the metadata of a namespace? |
| 13:26 | expez | alter-meta! ? |
| 13:29 | justin_smith | expez: do you mean clojure.test? and how does it alter namespaces? I know it uses metadata on functions to find tests... |
| 13:29 | {blake} | So, if sorted-map gets you speed when dealing with ordered data, what does array-map get you? |
| 13:29 | justin_smith | faster lookup and insertion |
| 13:29 | expez | justin_smith: I was just wondering what function to use to mutate metadata in place. alter-meta! seems to do the trick to simulate what core.test does |
| 13:30 | justin_smith | expez: again, do you mean clojure.test? |
| 13:30 | expez | justin_smith: yes, sorry |
| 13:31 | {blake} | justin_smith: OK. At what cost? |
| 13:31 | justin_smith | expez: I think this is it https://github.com/clojure/clojure/blob/master/src/clj/clojure/test.clj#L649 |
| 13:32 | justin_smith | {blake}: I am not sure, I guess you could benchmark them? my naive assumption is that since both ordered and unordered maps / sets work, that the unordered ones must be fastest for insertion / removal and perhaps also lookup, but the ordered versions might be faster than repeatedly sorting the contents by hand |
| 13:33 | {blake} | justin_smith: Yeah. They must have some tradeoff or we'd just always use array-map. I notice that Mongo returns array-maps. |
| 13:33 | justin_smith | {blake}: also array-maps are an impl detail - they auto-promote to hash-maps when they have enough items in them |
| 13:33 | pflanze | {blake}, also, trees are O(log n), whereas hash tables are O(1). Although Clojure's hashtables will also have a O(log n) subcomponent due to them using trees to implement arrays. |
| 13:34 | justin_smith | pflanze: yeah, that was my question mark about lookup - though I bet in practice that's the smallest perf difference of the ones present |
| 13:35 | {blake} | Yeah, I thought all was trees, and that's how immutability works. =P |
| 13:37 | sg2002 | justin_smith: Since we need the stack frame, just a global exception handler won't work, I was thinking more towards wrapping every function call be it with changes to the reader, or maybe iterating over visible functions and replacing them with a debuggable versions. |
| 13:37 | pflanze | {blake}, there's a paper about the vectors that Clojure uses, it should give the reasoning. Something like "better amortized" than in normal trees I suppose. |
| 13:37 | justin_smith | sg2002: on yeah that's messy |
| 13:38 | pflanze | {blake}, probably trading memory for speed |
| 13:41 | {blake} | pflanze: That'd be my guess, too. |
| 13:46 | pflanze | {blake}, it might also be feasible to use generation counters and mutation and only allocate new tree elements once the existing ones have run out of space, which should be more practical to implement with hashtables than normal trees. |
| 13:46 | pflanze | I'm sure that paper could be found again, I'm just a bit too lazy. |
| 13:46 | justin_smith | pflanze: hyPiRion 's series of blog posts on clojure's vector impl is great |
| 13:48 | firevolt | does anyone have any good resources for learning clojurescript/om? |
| 13:48 | justin_smith | firevolt: have you checked out "modern cljs" on github? |
| 14:01 | {blake} | firevolt: I don't, but I'd be interested in same. |
| 14:06 | sdegutis | Good news everyone, I upgraded to Clojure 1.7 successfully. Only had to rename our function `update` to `update-attrs`. |
| 14:07 | sg2002 | Debug-on-exception got me thinking how awesome it would be if clojure had a reachable generic exception handler hook. For example we have an obscure state-related bug somewhere in our app that happens when calling (fn val-a val-b). In our handler we expand variables to their states, pack the expanded form into exception info and then pass it up. |
| 14:07 | {blake} | sdegutis: I just ignore those messages. |
| 14:08 | sdegutis | {blake}: that's one optino |
| 14:08 | sdegutis | *OPTION |
| 14:08 | sdegutis | Okay reading Datomic changelog now. |
| 14:15 | sdegutis | Only 565 lines to read. |
| 14:17 | amalloy | sg2002: more than ex-info/ex-data? |
| 14:19 | sg2002 | amalloy: That's what I meant when I said "exception info". |
| 14:22 | seangrove | Hey all, getting this warning re: nrepl stuff, and not understanding why https://www.refheap.com/108381 |
| 14:23 | seangrove | I have cider-nrepl 0.9.1 in my project.clj, as well as refactor-nrepl 1.0.5 |
| 14:40 | expez | seangrove: usually these deps are added in profiles.clj and you have to add them as plugins, not dependencies. |
| 14:41 | expez | seangrove: so a minimal profiles.clj for cider would be {:user {:plugins [[cider/cider-nrepl "0.9.1"]]}} |
| 14:42 | expez | There are instructions for boot in the readme too, if that's how you roll |
| 15:08 | sdegutis | Cognitect is pretty brave in putting their Datomic changelog out there so plainly like that. |
| 15:08 | sdegutis | Lot of bug fixes in there that horrify me. |
| 15:09 | Bronsa | I take you never read any other changelog then |
| 15:10 | sdegutis | Only on common third party Clojure libraries like Compojure etc. |
| 15:11 | sdegutis | ... none of which are maintained by highly profitable corporations like Cognitect/Relevance |
| 15:12 | Bronsa | http://www.postgresql.org/docs/9.4/static/release-9-4-4.html https://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-26.html https://raw.githubusercontent.com/antirez/redis/3.0/00-RELEASENOTES https://docs.mongodb.org/v3.0/release-notes/2.6-changelog/ |
| 15:13 | Bronsa | breaking news: software requires bug fixes |
| 15:13 | sdegutis | Bronsa: Those are all free (gratis) open source projects. Huge difference. |
| 15:13 | sdegutis | Bronsa: Datomic is financially supported |
| 15:13 | sdegutis | and closed-source |
| 15:13 | preyalone | How do I install specific Clojure versions with Leiningen, so that clj is added to $PATH? |
| 15:14 | Bronsa | right, and mysql is developed by volunteers |
| 15:14 | preyalone | I want to use leiningen like rvm |
| 15:14 | sdegutis | preyalone: Just put the Clojure version as a dependency |
| 15:14 | Bronsa | wtf are you talking about sdegutis |
| 15:14 | sdegutis | preyalone: it won't put anything in your $PATH though, you'd still use Clojure via `lein` |
| 15:14 | preyalone | there's no project, just leiningen and random scripts |
| 15:14 | sdegutis | Bronsa: never mind, you can't understand |
| 15:14 | Bronsa | what has being open source or not have anything to do with bug fixes? |
| 15:14 | sdegutis | preyalone: maybe you're looking for lein-exec? |
| 15:14 | Bronsa | sdegutis: fuck off. |
| 15:14 | sdegutis | Bronsa: ok |
| 15:15 | justin_smith | preyalone: that's not what leiningen is intended for - it's a build tool and dependency manager |
| 15:15 | preyalone | thanks all |
| 15:15 | sdegutis | Bronsa: I don't mean to insult you. You just aren't understanding what I'm saying, and I suck at explaining what I'm thinking. |
| 15:15 | hiredman | Bronsa: I'd suggest using /ignore |
| 15:15 | sdegutis | Bronsa: So there's no use trying to communicate it further. |
| 15:15 | justin_smith | preyalone: if you know the exact jar you want to use, java -cp clojure-version.jar clojure.main |
| 15:16 | justin_smith | preyalone: bonus, that will start faster than lein |
| 15:17 | sdegutis | Bronsa: sure or you can go hiredman's route and ignore me I guess |
| 15:17 | sdegutis | I've been /ignore'd by hundreds of people on IRC over the past 15 years, who dismiss me as a troll. What's one more? |
| 15:19 | preyalone | i don't always organize my code into well-defined projects. sometimes i just have random shell scripts, and it would be nice to have an equivalent to rvm for quickly switching between clj versions in the current shell / process |
| 15:19 | justin_smith | preyalone: there's nothing to switch |
| 15:19 | justin_smith | preyalone: just tell the java command which clojure jar to use |
| 15:19 | sdegutis | That's the nice thing about Clojure compared to Ruby: it's not a global command, it's just a Java library. |
| 15:20 | sdegutis | That said, you may run into problems if you need different versions of Java JDK. |
| 15:20 | sdegutis | (I think?) |
| 15:20 | justin_smith | sdegutis: I have like 6 different jvms installed |
| 15:20 | sdegutis | Haha I didn't know you could do that. |
| 15:21 | justin_smith | of course only one is mapped in my default shell to "java" |
| 15:21 | justin_smith | but they are all there and ready to use |
| 15:22 | sdegutis | Maybe I have more than one also then. |
| 15:23 | sdegutis | I really don't understand the JVM ecosystem at all. |
| 15:24 | justin_smith | sdegutis: ls -l $(which java) may be informative |
| 15:24 | sdegutis | Heh, "/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java" |
| 15:25 | justin_smith | sdegutis: and I assume you can guess what may or may not be found under that Versions/ directory in the middle there |
| 15:25 | sdegutis | Yeah it's only 1.6 but a bunch of symlinks to 1.6 for things like 1.4, 1.3, 1.5, etc |
| 15:25 | sdegutis | weird |
| 15:26 | justin_smith | if you went and installed 1.7 and 1.8 they would likely end up neighbors |
| 15:27 | sdegutis | Well `lein repl` says I have 1.8 installed right now and it's using it. |
| 15:27 | preyalone | cool, just pushed a simple docker container with leiningen installed. https://github.com/mcandre/docker-leiningen |
| 15:27 | sdegutis | preyalone: Docker scares me. |
| 15:27 | sdegutis | We just use shell scripts to update stuff. |
| 15:28 | justin_smith | preyalone: making build machines? ideally your app servers would not have leiningen installed - it's a build tool |
| 15:29 | preyalone | justin_smith: aye, only jvm and the specific clojure / jar deps would be on the app servers |
| 15:29 | sdegutis | Right use `lein uberjar` instead it's super useful. |
| 15:29 | justin_smith | preyalone: you don't even need the deps, if you use an uberjar |
| 15:29 | justin_smith | preyalone: the app is a single jar containing clojure and all needed libs along with the app |
| 15:29 | sdegutis | Anyone know if Clojure 1.8 is going to have those big performance improvements based on optimizing pre-loading of clojure.core vars or whatever that was? |
| 15:30 | preyalone | neat |
| 15:30 | sdegutis | Because I'd really enjoy always having a faster start-up Clojure time. |
| 15:33 | puredanger | The downside of delayed var loading is that every var invocation for the rest of your runtime is 50% slower |
| 15:34 | sdegutis | puredanger: can't it memoize it after the first run, so that it's only the first access? |
| 15:34 | sdegutis | But obviously if that was a good idea, you guys alread y thought of it. |
| 15:35 | puredanger | How do you know it's the first time? That implies a condition and conditions have a cost and hurt inlining |
| 15:36 | puredanger | Invokedynamic actually does have a guard condition that does this |
| 15:36 | sdegutis | Ah. |
| 15:36 | sdegutis | cool |
| 15:37 | puredanger | I do not know if Rich has any plans to work on this for 1.8 |
| 15:37 | sdegutis | ok |
| 15:37 | sdegutis | Well if Clojure's dynamic nature inherently requires this slowness and no optimizations can be done, then so be it. |
| 15:38 | sdegutis | IT WORKS! Just upgraded Clojure 1.5.1 -> 1.7, and Datomic 0.8.4218 -> 0.9.5206 ... and it seems to work!! |
| 15:38 | puredanger | Why wouldn't it? :) |
| 15:39 | sdegutis | Haha good point. |
| 15:48 | donbonif_ | in what way is (map inc) different from (partial map inc) ? |
| 15:49 | sdegutis | donbonif_: I wondered the same thing yesterday. The answer I was given was to read the entire Transducers page on the official website. |
| 15:49 | sdegutis | donbonif_: I could be misremembering though -- there might be nothing relevant on that page. |
| 15:50 | hiredman | (map inc) returns a function that transforms a reducing function, (partial map inc) returns a function that takes a collection and returns a seq |
| 15:54 | donbonif_ | so a transducer never operates on a function directly? only trough transduce/into/etc ? |
| 15:55 | hiredman | ,(reduce ((map inc) conj) [] (range 10)) |
| 15:55 | clojurebot | [1 2 3 4 5 ...] |
| 15:56 | justin_smith | ,(into [] (map inc) (range 10)) |
| 15:56 | clojurebot | [1 2 3 4 5 ...] |
| 15:57 | hiredman | the terminology around transducers (like reducers before them) is not super clear, because there isn't a clojure.lang.Transducer, just a bunch of stuff delivered as "transudcers" |
| 15:57 | donbonif_ | ok, I understand that. I guess I have yet to find somewhere to properly apply transducers |
| 15:58 | donbonif_ | to fully use understand and use them |
| 15:58 | sdegutis | Yeah I don't fully understand the use-case of them either. |
| 15:58 | hiredman | so which things in the collection of code that is called "transducers" get the name Transducers isn't obvious, so people refer to different parts of the machine as transducers |
| 15:59 | hiredman | which makes it hard to have an exact conversation about |
| 16:16 | sdegutis | Is there a way to show your dependency graph via Leiningen? |
| 16:17 | sdegutis | Ah, lein deps :tree |
| 16:57 | BinaryResult | Hi Guys, just in case anyone missed it we are currently hiring remote full-stack clojure developers. See the full description here http://discomelee.com/jobs/ Hope to hear from you! |
| 17:10 | ed-g | It looks like when I call (ring.util.response.redirect "/") it redirects to the absolute location of the server on localhost:5000, rather than the Location that the client is accessing it by. Is there a way to change that setting? |
| 17:30 | rhg135 | is there a constant time way to get a random key from a map, usually I'd use (comp rand-nth keys), but that's O(n). |
| 17:32 | gfredericks | rhg135: I doubt it |
| 17:32 | rhg135 | I thought so. sadness |
| 17:33 | gfredericks | rhg135: I'm sure the impl could support such a thing if it wanted to |
| 17:33 | rhg135 | I think so too |
| 17:34 | rhg135 | I'll keep a pair of vector of keys and a map |
| 17:35 | rhg135 | persistent structures mean little wasted memory |
| 17:35 | rhg135 | just all the nodes |
| 17:38 | amalloy | rhg135: and how would you efficiently maintain that vector of keys? |
| 17:39 | gfredericks | I'm guessing it's static |
| 17:39 | amalloy | what, all maps are static? rhg135 is asking for a random key from a map |
| 17:39 | rhg135 | amalloy: generally I couldn't. but in this domain the map is not changed |
| 17:40 | gfredericks | I'm guessing based on the fact that that solution was suggested at all :) |
| 17:40 | amalloy | oh, you said "i'll" |
| 17:40 | amalloy | i thought we were talking about how the impl could support such a thing still, and read "i'd" |
| 17:40 | gfredericks | now all of our reactions make sense |
| 17:41 | rhg135 | On a vector rand-nth is O(1), right? |
| 17:43 | gfredericks | ,(let [v (vec (range 1000000))] (time (rand-nth v))) |
| 17:44 | clojurebot | #error {\n :cause "Java heap space"\n :via\n [{:type java.lang.OutOfMemoryError\n :message "Java heap space"\n :at [java.lang.Long valueOf "Long.java" 577]}]\n :trace\n [[java.lang.Long valueOf "Long.java" 577]\n [clojure.lang.LongRange reduce "LongRange.java" 233]\n [clojure.lang.PersistentVector create "PersistentVector.java" 65]\n [clojure.lang.LazilyPersistentVector create "LazilyPersis... |
| 17:44 | gfredericks | &(let [v (vec (range 1000000))] (time (rand-nth v))) |
| 17:44 | lazybot | ⇒ "Elapsed time: 4.866386 msecs" 828650 |
| 17:44 | gfredericks | seems like a lot of milliseconds |
| 17:44 | gfredericks | I'm guess you'll want to write your own rand-nth |
| 17:44 | gfredericks | rand-nthv |
| 17:45 | rhg135 | ,(source rand-nth) |
| 17:45 | clojurebot | Source not found\n |
| 17:45 | rhg135 | meh! |
| 17:45 | justin_smith | https://github.com/clojure/clojure/blob/clojure-1.7.0/src/clj/clojure/core.clj#L6938 |
| 17:46 | feijja | What is the opposite of map? I have a value (in this case a char), and I want to run it thru every function in a list. |
| 17:46 | rhg135 | seems legit |
| 17:46 | gfredericks | feijja: (map #(% v) fns) |
| 17:47 | rhg135 | that's still map |
| 17:47 | amalloy | feijja: alternatively, you have a list of functions, and you want to run each of them over a value (in this case a char- |
| 17:47 | sdegutis | How do you work around cyclical dependencies in your own namespaces? |
| 17:47 | rhg135 | (map #(% v) ..) |
| 17:47 | feijja | gfredericks: that was simple! Thank you >.> |
| 17:47 | rhg135 | require |
| 17:47 | amalloy | as O(1) as anything else on a vector, rhg135 |
| 17:48 | gfredericks | amalloy: why did your lazybot take four whooole milliseconds to retrieve an item |
| 17:48 | sdegutis | Is the convention to just require the namespace inside the function call that requires it? |
| 17:48 | amalloy | cosmic rays |
| 17:48 | gfredericks | sdegutis: I think most people restructure namespaces |
| 17:48 | gfredericks | &(let [v (vec (range 1000000))] (time (rand-nth v))) |
| 17:48 | lazybot | ⇒ "Elapsed time: 4.655652 msecs" 699246 |
| 17:49 | rhg135 | yes |
| 17:49 | gfredericks | amalloy: two cosmic rays! |
| 17:49 | sdegutis | gfredericks: I'll keep trying that. Been at it for 10 minutes though and not seeing a clear solution. |
| 17:49 | amalloy | gfredericks: seriously though rand-nth is as fast as it can be, afaik |
| 17:49 | rhg135 | cyclycal deps are usually a warning |
| 17:49 | amalloy | ~def rand-nth |
| 17:49 | gfredericks | amalloy: I looked at the impl so I believe you, but 4msecs is pretty weird |
| 17:49 | gfredericks | my repl did it in 0.05 msecs |
| 17:50 | gfredericks | maybe lazybot uses Really Slow Vectors |
| 17:50 | amalloy | sandboxing? i dunno |
| 17:50 | gfredericks | ~mystery |
| 17:50 | clojurebot | mystery is http://p.hagelb.org/mystery.gif |
| 17:50 | Bronsa | &(time 1) |
| 17:50 | lazybot | ⇒ "Elapsed time: 4.441412 msecs" 1 |
| 17:50 | gfredericks | haha |
| 17:51 | gfredericks | ,(let [t1 (System/nanoTime) t2 (System/nanoTime)] [t1 t2]) |
| 17:51 | rhg135 | what |
| 17:51 | clojurebot | [20961776023440845 20961776023441278] |
| 17:51 | gfredericks | ,(let [t1 (System/nanoTime) t2 (System/nanoTime)] (- t2 t1)) |
| 17:51 | clojurebot | 473 |
| 17:52 | gfredericks | weerd |
| 17:52 | amalloy | gfredericks: my guess is, lazybot is doing i/o during that time, because it is saving *out* to put it in a stringwriter |
| 17:52 | rhg135 | clojail isn't time sensitive is it? |
| 17:52 | rhg135 | or that |
| 17:52 | sdegutis | db.connect requires db.schema for setup-schema, db.schema requires db.helpers for create-attribute, so db.helpers can't require db.connect for the live-connection |
| 17:52 | rhg135 | either way timing things in a sandbox is a bad idea |
| 17:53 | rhg135 | db.state ? |
| 17:53 | justin_smith | ,(reductions - (repeatedly #(System/nanoTime))) |
| 17:53 | clojurebot | (20961916921858597 -489693 -20961916922987536 -41923833845509226 -62885750768060913 ...) |
| 17:53 | sdegutis | Maybe the schema shouldn't be a gigantic def inside a single file? |
| 17:53 | sdegutis | Maybe each file should add to the schema itself instead. |
| 17:54 | gfredericks | sdegutis: what does create-attribute do? |
| 17:54 | sdegutis | Mutability! |
| 17:54 | rhg135 | oh dear |
| 17:54 | sdegutis | gfredericks: forget that, a better reason is that db.schema requires tons of files that export database attributes, which use db.helpers to set up those attributes |
| 17:54 | sdegutis | db attributes are basically like table definitions if this were sql |
| 17:55 | sdegutis | and who wants to hand-write sql? |
| 17:55 | rhg135 | me |
| 17:55 | sdegutis | Maybe mutability is the answer? |
| 17:55 | rhg135 | no |
| 17:55 | rhg135 | it hardly ever is |
| 17:56 | amalloy | &(map (partial apply -) (partition 2 1 (repeatedly 10 #(System/nanoTime)))) |
| 17:56 | lazybot | ⇒ (-2627774 -2575106 -2567565 -2959637 -2595812 -2377417 -2389713 -2383616 -2446741) |
| 17:56 | amalloy | ,(map (partial apply -) (partition 2 1 (repeatedly 10 #(System/nanoTime)))) |
| 17:56 | clojurebot | (-98835 -155731 -130121 -60025 -57765 ...) |
| 17:56 | sdegutis | It seems strange to have the schema namespace require every namespace it needs for building the schema itself. |
| 17:56 | sdegutis | Doesn't it? |
| 17:56 | amalloy | oh i bet i remember |
| 17:56 | amalloy | lazybot does really slow sandboxing around interop calls |
| 17:56 | amalloy | and time macroexpands to such a call |
| 17:57 | rhg135 | ,(map (fn [_] (Thread/currentThread))) (repeat 10 nil)) |
| 17:57 | clojurebot | #object[clojure.core$map$fn__4537 0x676641fb "clojure.core$map$fn__4537@676641fb"] |
| 17:57 | rhg135 | eh |
| 17:58 | hiredman | someone should write an interpreter over tools.analyzer's ast |
| 17:58 | sdegutis | ##(map (partial apply -) (partition 2 1 (repeatedly 10 #(System/nanoTime)))) |
| 17:58 | lazybot | ⇒ (-2151029 -2107115 -6504619 -2099165 -2079598 -2091383 -2063970 -2106716 -2094827) |
| 17:58 | sdegutis | &(map (partial apply -) (partition 2 1 (repeatedly 10 #(System/nanoTime)))) |
| 17:58 | lazybot | ⇒ (-2183474 -2074782 -2074559 -2051653 -2126746 -2092625 -2066550 -2101132 -2103594) |
| 17:58 | sdegutis | wha |
| 17:59 | rhg135 | tej? |
| 18:00 | gfredericks | now that CLJS is self-hosted does that mean it'd be easy to write a browser repl that can format values as arbitrary html? |
| 18:00 | sdegutis | Schema setup probably shouldn't be responsible for building the schema by searching the entire application. |
| 18:00 | sdegutis | gfredericks: it is?? |
| 18:00 | lazybot | sdegutis: Definitely not. |
| 18:00 | hiredman | (because interpreters are generally more reusable and easier to retarget to do other things, like analysis or sandboxing than compilers) |
| 18:00 | gfredericks | sdegutis: sorta |
| 18:00 | amalloy | hiredman: but then we'd have to edit all those blog posts that say "clojures is NOT an interpreted language" |
| 18:01 | rhg135 | compiling should be a optimization iirc |
| 18:01 | sdegutis | sure it is |
| 18:01 | hiredman | amalloy: an interpreter can be turned in to a compiler :) |
| 18:02 | rhg135 | otoh clojure the language is very much wed to the jvm imo |
| 18:02 | rhg135 | thats why clj /= cljs, ever |
| 18:07 | {blake} | Oh, that's interesting. I'd say Clojure uses the JVM for convenience and acceptance, and it'd be just as home...anywhere. |
| 18:11 | rhg135 | you're right. it's only slightly. |
| 18:15 | {blake} | We have a large library we're looking to port to CLJS, and it doesn't seem like there's much reliance on the JVM. |
| 18:20 | sdegutis | Is ClojureScript on Node.js a reasonable option for web apps now? |
| 18:23 | rhg135 | somewhat |
| 18:24 | feijja | sdegutis: Yes, I'd say so. But why would you do that, rather than JVM Clojure? |
| 18:24 | rhg135 | ^ |
| 18:25 | sdegutis | The tooling around Node/Io.js feel a little more refined and loved. |
| 18:25 | rhg135 | you COULD, but why |
| 18:25 | sdegutis | For all that sucks about JavaScript, those guys sure do like having good tools. |
| 18:25 | feijja | Very true. Go ahead :). If you wrap JS libs in CLJS, make sure to share your libs! |
| 18:26 | slaterr | ,((1 2 3)(4 5 6)) |
| 18:26 | 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 [sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 6943]... |
| 18:26 | slaterr | why doesn't that work? |
| 18:27 | rhg135 | ,(1) |
| 18:27 | 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 [sandbox$eval145 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval145 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval145 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 69... |
| 18:27 | sdegutis | feijja: will do :) |
| 18:27 | hiredman | a literal list is function application in lisps |
| 18:28 | feijja | sdegutis: just remember that JS is single-threaded, and Clojure is pretty neat when doing concurrent stuff. |
| 18:28 | hiredman | if (+ 1 2) is appling the + function 1 and 2, and (- 1 2) is appling the - function to 1 and 2, what function is (1 2 3) applying? |
| 18:28 | rappaport | feijja: like what? |
| 18:29 | feijja | I'm writing a function that will return a vector of functions. Every call to (fn [] ()) returns a new function, with a new 'id'. How can I use `=` in my unit tests, to compare my list-of-functions-returning function against a predefined list? |
| 18:29 | feijja | The function returns [(fn [x] (x)) (fn [y] (y))], and each fn gets a new 'id' |
| 18:29 | slaterr | yeah I got confused by the error message. I thought it was related to nested lists, and not missing ' by mistake |
| 18:30 | slaterr | which i didn't even notice |
| 18:30 | feijja | rappaport: Clojures core.async has very nice ways to do concurrency - it's available in CLJS too. But in Clojure things will run at the same time in different threads. In CLJS things will never be able to run at the same point in time |
| 18:30 | rappaport | I'm not Rappaport. |
| 18:31 | amalloy | feijja: you can't really compare functions for anything but pointer equality. if you want to test that you get back a function that behaves a certain way, all you can do is call it with some inputs and verify you get the output you wanted |
| 18:31 | rhg135 | on node, you could get threads |
| 18:31 | rappaport | feijja: Ahhh i see |
| 18:31 | feijja | amalloy: I see... Was afraid of that. |
| 18:31 | rappaport | On io.js too I bet |
| 18:31 | rhg135 | but thats hacky |
| 18:32 | rappaport | I've been caring less and less whether something's hacky lately as long as it gets the job done long-term |
| 18:32 | rappaport | granted, most "hacky" things won't, but I think that's just a coincidence |
| 18:32 | rhg135 | s/hack/not pre done/ |
| 18:32 | rhg135 | laziness |
| 18:33 | rappaport | It's thundering and it smells wonderful outside. |
| 18:34 | rhg135 | core.async does have a pluggable executor |
| 18:49 | rhg135 | KeySeq is unfortunately linear it seems |
| 19:34 | domokato | What is the clojuresque way of implementing a function that, given an integer, returns an infinite list of integers sorted by distance from that integer. For example, given 5, returns (5 6 4 7 3 8 2 9 1 10 0 11 -1 12 -2 13 ...)? |
| 19:37 | domokato | i noticed the pattern of +1, -2, +3, -4, +5, etc., in the output, leading me to consider loop/recur, but that's not lazy |
| 19:37 | amalloy | ,((fn [x] (map #(+ % x) (rest (mapcat (juxt + -) (range))))) 5) |
| 19:37 | clojurebot | (5 6 4 7 3 ...) |
| 19:37 | amalloy | would be my first effort |
| 19:40 | domokato | juxt, i was not aware of that function, thx! |
| 19:40 | domokato | i gtg for the moment, but will read the logs when i get back |
| 19:41 | domokato | another wrinkle in my problem is that i want to omit values that are above a specific number or below another specific number |
| 19:41 | domokato | brb |
| 20:01 | slaterr | how to do this? "one two three" => "one - two - three" |
| 20:02 | slaterr | what do I do after (str/split "one two three" #" ")? |
| 20:02 | slaterr | to insert " - " in between each element and then concat them all together |
| 20:03 | amalloy | &(doc clojure.string/join) |
| 20:03 | lazybot | ⇒ "([coll] [separator coll]); Returns a string of all elements in coll, as returned by (seq coll), separated by an optional separator." |
| 20:05 | rfmind | slaterr: I think you should use replace to replace " " with " - " |
| 20:05 | slaterr | there could be more than one space |
| 20:11 | rfmind | slaterr: (clojure.string/replace "one two three" #" +" "-") |
| 20:15 | slaterr | what does putting # in front of string literal do btw? it makes a regex literal? |
| 20:15 | rfmind | yes |
| 20:16 | rfmind | #" +" basically says => one or more space(s) |
| 20:16 | rhg135 | \s+ |
| 20:17 | rfmind | rhg135: thanks :D |
| 20:18 | rhg135 | np |
| 21:03 | domokato | amalloy: ah, I should be able to just surround your code with filter to get the job done |
| 21:04 | amalloy | domokato: wellllll, kinda. eventually all values will be either above the first number or below the second, and your filter will be discarding all elements |
| 21:04 | justin_smith | yeah, a take-while might be helpful there? |
| 21:05 | amalloy | justin_smith: it's a little complicated though, if you want to take-while at least one condition is true but filter items where either condition is false |
| 21:07 | domokato | oh, filter causes infinite loop when you try to access later elements, huh |
| 21:08 | justin_smith | domokato: well it's looking for the next item meeting your predicate |
| 21:08 | justin_smith | domokato: which is why I suggested take-while |
| 21:08 | justin_smith | but as amalloy mentions that's still not simple |
| 21:08 | domokato | ah yes |
| 21:10 | domokato | couldn't i filter between top and bottom and then take top minus bottom? |
| 21:11 | justin_smith | well, I think you want something that avoids looking for the next element meeting your condition once you know no element can... |
| 21:11 | justin_smith | because the filter is too stupid |
| 21:19 | domokato | justin_smith: doesn't that do it, though? For example, if my bottom is 0, my top is 5, and my x is 3, then it would take 5, resulting in (3 4 2 1 0), and no other elements meet the conditions |
| 21:19 | justin_smith | domokato: why does filter know that "no other elements meet the conditions |
| 21:19 | justin_smith | " |
| 21:20 | domokato | it doesn't, but i know, which is why i take only that many |
| 21:20 | justin_smith | ahh, which means you can use take or take-while |
| 21:20 | domokato | hm, what would my condition be for take-while, though? |
| 21:22 | amalloy | domokato: you provably can't solve this with a pure predicate to take-while, because it only gets to look at one element at a time and you need to know about two different items at once in order to make the decision to stop |
| 21:23 | domokato | yeah, that's my understanding |
| 21:39 | gfredericks | luxbock: your test.check question is just gen/elements I think |
| 21:43 | amalloy | gfredericks: the difference being that gen/elements grows towards selecting later elements and shrinks towards earlier ones, where gen/one-of doesn't grow with size but does shrink? |
| 21:43 | gfredericks | uhms |
| 21:43 | amalloy | also gen/one-of requires a generator instead of a value, but he had already made that |
| 21:44 | gfredericks | yeah looks like one-of does not grow through the list |
| 21:44 | gfredericks | but.... |
| 21:44 | gfredericks | neither does elements |
| 21:44 | gfredericks | maybe I didn't examine the question closely enough, was growth a requirement? |
| 21:45 | gfredericks | reading the question closer it isn't clear if luxbock is intentionally distinguishing growth from shrinking or not |
| 21:45 | amalloy | gfredericks: well no, the question was about shrinking, but he wasn't testing shrinking at all |
| 21:45 | gfredericks | right |
| 21:46 | gfredericks | it's never occurred to me to use the word "growth" w.r.t. generators but it makes sense |
| 21:46 | amalloy | gfredericks: i just made it up now. do you want a license? |
| 21:46 | gfredericks | yes thanks |
| 21:51 | gfredericks | I think the most surprising misconception I encountered when talking to people at clojure/west about test.check was they assumed growth and shrinking were related |
| 21:51 | gfredericks | only surprising to me because I had been living in the impl for a while |
| 21:51 | gfredericks | otherwise is a totally reasonable thing to guess |
| 21:56 | amalloy | if you caught me unaware and asked me i would probably say that they are |
| 21:56 | seangrove | Can't seem to figure out how to get clj-time to work with a #inst literal |
| 21:56 | gfredericks | it takes effort |
| 21:57 | gfredericks | let me think |
| 21:57 | seangrove | I suppose I need to coerce it with from-date |
| 21:57 | gfredericks | to print it? |
| 21:57 | gfredericks | if you want everything to be awesome you have to do both printing and reading |
| 21:57 | seangrove | Yeah, just want to print it. Probably should have just looked up the Java methods |
| 21:58 | gfredericks | I'll find how I do it |
| 21:59 | gfredericks | seangrove: https://www.refheap.com/108392 |
| 21:59 | gfredericks | now that I look at it there's probably a less wasteful way to do it |
| 21:59 | gfredericks | but that at least works |
| 22:00 | gfredericks | the i prefix there clojure.instant |
| 22:00 | gfredericks | is* |
| 22:36 | sdegutis | What's a good way to run swap! only once for a given atom with the given args? |
| 22:36 | sdegutis | I assume something to do with memoize right? |
| 22:39 | crocket | Why is it faster to load a script via clojure.jar than to load it as part of a leiningen uberjar? |
| 22:39 | gfredericks | sdegutis: I'm pretty sure if you want to do that it means you shouldn't be using an atom; what about agents? |
| 22:40 | sdegutis | crocket: Leiningen loads the JVM a few times usually. |
| 22:40 | crocket | leiningen uberjar takes 4 seconds to load. |
| 22:40 | sdegutis | crocket: there are some hacks to avoid it, like trampoline, but they come at their own costs and caveats |
| 22:40 | sdegutis | gfredericks: Both are probably the wrong way actually. |
| 22:40 | gfredericks | sdegutis: it doesn't sound like leiningen is part of the startup here, the question is about running jars |
| 22:40 | sdegutis | gfredericks: I'm trying to load my schema in reverse-dependency order. |
| 22:40 | crocket | sdegutis : Do you know what an uberjar is? |
| 22:40 | justin_smith | crocket: the time spent by lein uberjar is mostly spent putting all the stuff in a file on disk, or do you mean the time running the resulting jar? |
| 22:41 | gfredericks | sdegutis: why is your schema spread around your project? |
| 22:41 | crocket | loading a simple script |
| 22:41 | sdegutis | gfredericks: Before, I'd have the schema namespace require a declarative var out of every single namespace that declares one, manually, and build the schema that way. It's stupid though. |
| 22:41 | sdegutis | gfredericks: Why? Hmm. Because I want the user attributes in the user.clj file, etc. |
| 22:42 | sdegutis | gfredericks: It allows me to keep things organized a little nicer. |
| 22:42 | crocket | I mean the startup time of a simple script is faster as a standalone than in an uberjar. |
| 22:42 | justin_smith | sdegutis: I use an agent instead of an atom for the top level component in my system, because I don't want retries between start / stop, I want a linear sequence |
| 22:42 | sdegutis | justin_smith, gfredericks: hmm I'll refresh my memory on what agents are again thanks |
| 22:42 | gfredericks | justin_smith: I think he's just trying to organize his code in cyclic sorts of ways |
| 22:43 | justin_smith | well that's just silly |
| 22:43 | sdegutis | But I think what I probably want is to declare partial schemas like this: (def ^:schema users-attributes [...]) |
| 22:43 | sdegutis | And then just search my codebase for vars with :schema in the metadata, and use those. |
| 22:43 | sdegutis | justin_smith, gfredericks: Actually I don't think that's what I'm trying to do. |
| 22:44 | sdegutis | justin_smith: I'm trying to make it so that my schema is declarative while still being push-onto rather than pull-onto, if that makes sense. |
| 22:44 | justin_smith | sdegutis: can a schema specify that elements need to implement some protocol? if so the schema and protocol definition can be at the very bottom of your dependency stack |
| 22:44 | sdegutis | justin_smith, gfredericks: In other words, I don't want some centralized location having to require the entire codebase just to build a schema. I'd rather have each part build up anonymously, in a decentralized manner. |
| 22:45 | sdegutis | justin_smith: Sorry which way is bottom/top again? |
| 22:45 | justin_smith | sdegutis: the bottom is required by others but requires nothing |
| 22:45 | justin_smith | the top requires others, required by nothing |
| 22:45 | sdegutis | Ah. |
| 22:45 | sdegutis | Hmm let me think. |
| 22:46 | justin_smith | sdegutis: the idea would be, the schema specifies "things that implement such and such protocol go here", and then users of the schema could go ahead and implement protocol as they like |
| 22:46 | sdegutis | justin_smith: I'd like my partial-schemas to live in the middle of the stack, i.e. within the context of the code which makes use of it, like users.clj and account.clj etc |
| 22:46 | tmtwd | (defn divisble [x n] (if (= (mod x n) 0) true false)) : how come this function doesn't work? |
| 22:46 | justin_smith | or write code that calls methods of that protocol, using the instances some other code filled in |
| 22:47 | tmtwd | user> (divisible 40 10) => nil |
| 22:47 | justin_smith | sdegutis: middle is a weird place to put your fundamental definitions |
| 22:47 | amalloy | tmtwd: as written that function looks fine. are you sure you're not calling some other function? |
| 22:47 | amalloy | like, re-paste the definition and eval it again |
| 22:47 | sdegutis | justin_smith: they're not quite fundamental... they're a level undernearth the web interface, but a step up above the helper functions which they use |
| 22:48 | tmtwd | oops |
| 22:49 | sdegutis | justin_smith: the circle I was encountering earlier is that the db.helpers namespace (where db helper functions live) were building the schema and requiring the mid-level namespaces containing schema-attributes, but these mid-level namespaces were requiring the db.helpers namespace for the functions that help build up a schema |
| 22:50 | justin_smith | I think it's weird for schema definitions to use db helpers |
| 22:50 | sdegutis | I suppose they could be mere data that I could translate later. |
| 22:50 | justin_smith | I think a schema should be a shape with no implementation details |
| 22:50 | sdegutis | That's not a terrible idea. |
| 22:50 | sdegutis | Right now I have like (make-one-attr :foo/bar :db.type/string) turn into a full-fledged Datomic install-attribute line suitable for putting into a transaction. |
| 22:51 | sdegutis | I guess I could turn that into [:make-one-attr :foo/bar :string] and transform that at consume-time. |
| 22:51 | sdegutis | But that still doesn't quite solve the bigger issue, which is where this is stored, and how to get it into the schma. |
| 22:52 | sdegutis | What I want to move away from, is where db.schema requires [features.user :refer [user-attributes]] and so on, x20, since that's backwards. |
| 22:53 | sdegutis | What I'm trying to figure out how to move towards, is where features.user tells db.schema that he has some user-attributes to add to what's already there (but only once of course). |
| 22:53 | sdegutis | The stupid solution I have, and justin_smith you will probably hate this, is (swap! db.schema/schema concat user-attributes) |
| 22:54 | sdegutis | But it's usable for the most part. Just need to turn it into assoc :user-attributes user-attributes and it fixes the reloading problem. |
| 22:55 | sdegutis | It's just... mutable. That feels gross. |
| 22:55 | justin_smith | *slightly* more sane would be a promise - at least that can only be realized once |
| 22:55 | justin_smith | but I've already voted for what I think the real solution is |
| 22:56 | sdegutis | Thanks justin_smith for your feedback. |
| 22:56 | sdegutis | I guess in order to maintain my (crazy?) stack order, I have to do it this way. |
| 22:56 | sdegutis | Otherwise I like your idea best. |
| 23:43 | sdegutis | ,(->> [] (conj 2) (atom) (def foo)) |
| 23:43 | sdegutis | ,foo |
| 23:43 | clojurebot | #error {\n :cause "java.lang.Long cannot be cast to clojure.lang.IPersistentCollection"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IPersistentCollection, compiling:(NO_SOURCE_FILE:0:0)"\n :at [clojure.lang.Compiler$InvokeExpr eval "Compiler.java" 3661]}\n {:type java.lang.ClassCastException\n... |
| 23:43 | clojurebot | #object[clojure.lang.Var$Unbound 0x33ffc978 "Unbound: #'sandbox/foo"] |
| 23:43 | sdegutis | That should have worked right? |
| 23:43 | sdegutis | What am I doing wrong? |
| 23:43 | justin_smith | nope |
| 23:43 | sdegutis | Is def super-special and won't allow that or something? |
| 23:43 | Bronsa | ,(macroexpand '(->> [] (conj 2))) |
| 23:43 | clojurebot | (conj 2 []) |
| 23:43 | rhg135 | the answer to a lot of things seems to be "data it" |
| 23:43 | sdegutis | Oops. |
| 23:43 | justin_smith | ,(-> [] (conj 2) atom (->> (def foo))) |
| 23:43 | clojurebot | #'sandbox/foo |
| 23:43 | sdegutis | ,(->> [] (cons 2) (atom) (def foo)) |
| 23:43 | clojurebot | #'sandbox/foo |
| 23:43 | sdegutis | foo |
| 23:44 | sdegutis | ,foo |
| 23:44 | clojurebot | #object[clojure.lang.Atom 0x21cdeae0 {:status :ready, :val (2)}] |
| 23:44 | justin_smith | cheater, that makes it a list |
| 23:44 | sdegutis | hahahaha |
| 23:44 | sdegutis | :D |
| 23:44 | justin_smith | my version made it still a vector |
| 23:44 | sdegutis | The main thing was (def foo) at the end of a ->> |
| 23:44 | sdegutis | I think I'll do all my defs that way from now on. |
| 23:45 | rhg135 | it certainly helps in a repl |
| 23:45 | sdegutis | Never considered that! Good idea rhg135 |
| 23:46 | rhg135 | neither had I till a month ago |
| 23:46 | rhg135 | it was a joyous day |
| 23:46 | sdegutis | :D |
| 23:46 | sdegutis | You should have put it in /r/lifeprotips for me |
| 23:46 | sdegutis | *us |
| 23:47 | rhg135 | I should use reddit first of all lol |
| 23:48 | sdegutis | Yeah I just found it the other day. |
| 23:48 | sdegutis | It's absolutely terrible. |
| 23:48 | justin_smith | (->> reddit (.com) :r/clojure (map upvote)) |
| 23:48 | sdegutis | justin_smith: nice touch with the .com metho |
| 23:48 | sdegutis | d |
| 23:48 | rhg135 | so java interop |
| 23:48 | sdegutis | and the :r/ namespace! |
| 23:49 | sdegutis | I bet all the people who have me on ignore are really confused why justin_smith wrote that lol |
| 23:49 | sdegutis | What's better for in a test, with-redefs or binding? |
| 23:49 | rhg135 | if this chan was a namespace what would it be? |
| 23:49 | justin_smith | sdegutis: I like to spew really random stupid stuff on here, and assume most people will just think I am responding to someone they ignore |
| 23:49 | sdegutis | justin_smith: haha |
| 23:49 | rhg135 | binding or neither |
| 23:50 | Bronsa | they don't do the same thing |
| 23:50 | sdegutis | rhg135: why not with-redefs? |
| 23:50 | justin_smith | rhg135: :freenode/#clojure obviously |
| 23:50 | sdegutis | Bronsa: oh? |
| 23:50 | rhg135 | race conditions |
| 23:50 | sdegutis | justin_smith: is that legal!? |
| 23:50 | sdegutis | justin_smith: I think it's not cuz # |
| 23:50 | sdegutis | reader-hinter thing |
| 23:50 | justin_smith | ,:foo/#bar |
| 23:50 | clojurebot | :foo/#bar |
| 23:50 | sdegutis | ! |
| 23:50 | rhg135 | justin_smith: I would think ::stuff is :freenode.clojure/stuff |
| 23:50 | justin_smith | sdegutis: so many stupid keywords that should not be legal, are anyway |
| 23:51 | Bronsa | ,:a/1 |
| 23:51 | clojurebot | #<RuntimeException java.lang.RuntimeException: Invalid token: :a/1> |
| 23:51 | Bronsa | ,:1/a |
| 23:51 | clojurebot | :1/a |
| 23:51 | justin_smith | ,:f''ooo/#b'#'ar |
| 23:51 | clojurebot | :f''ooo/#b'#'ar |
| 23:51 | rhg135 | ,:freenode.#clojure/a |
| 23:51 | clojurebot | :freenode.#clojure/a |
| 23:51 | rhg135 | huh |
| 23:51 | sdegutis | justin_smith: like this? ##(keyword "") |
| 23:51 | lazybot | ⇒ : |
| 23:51 | sdegutis | ##: |
| 23:51 | rhg135 | live and learn they say |
| 23:51 | sdegutis | ##(do :) |
| 23:52 | sdegutis | haha I broke lazybot |
| 23:52 | justin_smith | ,((juxt namespace name) (keyword "well that's cheating, but this keyword / is worse")) |
| 23:52 | clojurebot | ["well that's cheating, but this keyword " " is worse"] |
| 23:52 | rhg135 | oh dear |
| 23:52 | Bronsa | &*clojure-version* |
| 23:52 | lazybot | ⇒ {:major 1, :minor 7, :incremental 0, :qualifier "alpha1"} |
| 23:52 | rhg135 | imagine it as a literal |
| 23:52 | Bronsa | uff |
| 23:53 | Bronsa | ,:foo/bar/baz |
| 23:53 | clojurebot | :foo/bar/baz |
| 23:53 | Bronsa | IIRC (name :foo/bar/baz) returned something in 1.5 and something different in 1.6 |
| 23:54 | rhg135 | :this.is.a.very.very.very.very.very.very.very.very.long/keyword |
| 23:54 | sdegutis | Would it be bad on performance to swap a ref's value every 1 second? |
| 23:54 | rhg135 | probably |
| 23:54 | sdegutis | Hmm. |
| 23:54 | sdegutis | I was planning on doing that with my database value. |
| 23:54 | rhg135 | if you're doing so odds are it's not an efficient alogrithm |
| 23:55 | sdegutis | Was gonna put (swap! database constantly new-database) inside my insert and update functions. |
| 23:55 | sdegutis | Er, (reset! database new-database) |
| 23:55 | justin_smith | sdegutis in real life: http://gfycat.com/SecondAdmiredKilldeer |
| 23:56 | sdegutis | Wow. so accurate |
| 23:56 | rhg135 | you program on a surface?? |
| 23:56 | lazybot | rhg135: Uh, no. Why would you even ask? |
| 23:56 | justin_smith | it's the flapping paddle-hands that really captures his essence |
| 23:56 | Bronsa | surprisingly accurate indeed. |
| 23:57 | rhg135 | that reminds me of me when I'm tired |
| 23:57 | rhg135 | "no thinking, just type faster!" |
| 23:57 | sdegutis | Bronsa: it was funny when justin_smith said it because he was being friendly and fun; you're just insulting and that kind of ruins the humor |
| 23:58 | sdegutis | justin_smith: do you seriously recommend against doing that tho? |
| 23:58 | justin_smith | so you actually meant an atom not a ref I guess |
| 23:59 | sdegutis | I haven't determined which one yet. |
| 23:59 | sdegutis | The main point is a thing that I can swap out within the context of Compojure handlers (but deeper in the call stack, since it's inside my update/insert functions). |
| 23:59 | justin_smith | if you had something wrapping a connection, and each interaction with the db returned a new one, I would consider something like that I guess |