#clojure log - Aug 17 2015

The Joy of Clojure
Main Clojure site
Google Group
IRC
List of all logged dates

0:00 TEttinger: ,(map inc [1 2 3])

0:00 clojurebot: (2 3 4)

0:00 TEttinger: ,(map first {:a 1 :b 2 :c 3})

0:00 clojurebot: (:a :b :c)

0:00 TEttinger: ,(map inc #{1 2 3})

0:00 clojurebot: (2 4 3)

0:01 TEttinger: important stuff real fast! the set is not in the order it came in for a reason!

0:01 slaterr: set is a binary tree with just a key I guess

0:02 palinkas: justin_smith: the only problem I can see with the sandboxing is that it won't even allow to create namespaces

0:02 justin_smith: palinkas: ahh, you should check out which sanbox clojurebot uses

0: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

0:02 that's why there are sorted-map and sorted-set

0:03 ,(map inc (sorted-set 1 2 3))

0:03 clojurebot: (2 3 4)

0:03 TEttinger: 1 2 3 is already sorted, this actually sorts it again

0:03 ,(map inc (sorted-set 1 2 3 0 -1))

0:03 clojurebot: (0 1 2 3 4)

0:03 slaterr: sorted-set = binary tree, set = hash table?

0: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.

0:05 sets ensure uniqueness, not ordering

0:05 that's their most important attribute

0:06 slaterr: yeah

0:06 TEttinger: sorted-sets ensure uniqueness and ordering by sorting (you can specify how to sort them too, so not limited to ascending order)

0:06 justin_smith: hash-sets use a fancy kind of tree optimized for immutable sets that do structural sharing

0:06 TEttinger: radix 32 hash-array-mapped trie?

0:07 "now you know why we don't talk about the internals"

0: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

0: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.

0:11 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.

0:11 otherwise, those are not commonly used, because you lose the advantages of immutable code for reasoning about what something will have as its value

0:13 (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)

0:15 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 :)

0:15 justin_smith: haha

0:16 * justin_smith sets up shop with his SMAASH business.

0:16 justin_smith: small macros as a service h-something

0: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.

0:17 hey Olajyd!

0:21 palinkas: ,(ns test)

0:21 clojurebot: nil

0:22 palinkas: ,(def a "something")

0:22 clojurebot: #'sandbox/a

0:22 justin_smith: palinkas: any two commands are not in the same eval context

0:22 palinkas: maybe try using do

0:22 ,(do (ns 'test) (def a "OK"))

0: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...

0:22 justin_smith: hmm

0:22 ,(do (ns test) (def a "OK"))

0:22 clojurebot: #'test/a

0:23 palinkas: and also I guess once the request finished, the sandbox is destroyed

0:24 justin_smith: ,test/a

0:24 clojurebot: "OK"

0:24 justin_smith: palinkas: it has a set lifetime, but it isn't immediately destroyed

0:25 palinkas: the question is: can I run two sandbox side-by-side, without conflicting with each other?

0:26 justin_smith: as far as I know, yes

0:26 I have not personally tried it though

0:27 palinkas: any way to try it out?

0:27 I assume that clojurebot here has only a single sandbox

0:28 justin_smith: palinkas: I thought that it was using a sandbox lib, but maybe it has one in its source...

0:28 palinkas: https://github.com/hiredman/clojurebot

0:28 justin_smith: palinkas: here's the subproject https://github.com/hiredman/clojurebot/tree/master/clojurebot-eval

0:29 Bronsa: lazybot uses clojail, clojurebot uses an internal one AFAIK

0:29 justin_smith: Bronsa: yeah, he was looking at clojail but found it too restrictive

0:30 slaterr: TEttinger appreciate all the pointers

0:32 TEttinger: no prob

1:16 weebz: I'm trying to do the following typecast in Clojure, but I can't get it to actually cast

1:16 ((JavascriptExecutor)driver).executeScript("return $('.cheese')[0]")

1:16 (cast JavascriptExecutor driver) returns a FirefoxDriver and not a JavascriptExecutor

1:28 hiredman: that is not how casting works

1:29 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

1:30 so for dynamic langues (like clojure) casting doesn't really do anything

1:31 and, even if does do something, it can't / won't change the dynamic type of an object

2: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?

2:37 the doc of gen/one-of says "Shrinks toward choosing an earlier generator...", but I'm not seeing it

2:37 clojurebot: Huh?

2: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}

2:43 Olajyd: Hi TEttinger :)

2:45 TEttinger, I’m a junior cloure dev, I hope u’ll be available for more problem solving :)

2:45 Hey justin_smith

2:46 TEttinger: all right, good stuff

2:55 nakiya: guys, any of you accessing Facebook graph api with clojure? What is your setup?

3:11 ,(doc get)

3:12 clojurebot: "([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present."

4: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 ?

4: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

4:43 gilliard: luxbock: I don't think there is http://dev.clojure.org/jira/browse/CLJ-1771

5:02 crocket: How do I create a simple standalone command line application in clojure without leiningen?

5:02 I want to use clojure as a replacement of bash.

5:04 schmir: crocket: better take a look at boot: https://github.com/boot-clj/boot/wiki/Scripts

5:05 crocket: schmir, Is that it?

5:06 luxbock: crocket: http://clojure.org/repl_and_main

5:14 crocket: "java -cp clojure.jar clojure.main /path/to/myscript.clj"

5:14 Does "java -cp clojure.jar clojure.main /path/to/myscript.clj" execute -main in myscript.clj?

5:15 luxbock: I think so but I have never tried it

5:15 crocket: It executes nothing.

5:17 I saved http://dpaste.com/00MPG39 as doit.clj, and "java -cp ~/Apps/clojure-1.7.0.jar clojure.main doit.clj" executes nothing.

5: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

5: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

5:33 crocket: TEttinger, I don't know a way

5:33 how do I call -main?

5:33 Ah shit

5:34 I guess I have to -main directly in the source code.

5:34 I was right.

5:35 TEttinger: (-main)

5:35 it's a fn you defined

5:36 crocket: How do I get access to the list of arguments?

5:37 Oh, there is *command-line-args*

5:37 Not cool

5:37 TEttinger: good find

5:37 -main is a lein thing I think, it sets up the java-like main method

5:38 crocket: Anyway, it is relatively fast to load a .clj file via clojure.jar

5:38 TEttinger: the plain clojure.main method is uh different

5:41 crocket: Is clojure.java.shell/sh synchronous or asynchronous?

5:45 kwladyka: ah... how it was called... functions which one the same input give always the same output?

5:45 oh pure functions

5:49 crocket: boot-clj seems reasonable

5:51 TEttinger, (apply -main *command-line-args*)

5:51 TEttinger: ah there you go!

5:52 Olajyd: HI, TEttinger

5:52 crocket: How do I iterate over two seqs of the same length?

5:52 or multiple seqs

5:52 Olajyd: TEttinger, how do I serach for a particular character in a string?

5:52 crocket: Oh, seqs sounds like "sex".

5:52 TEttinger: Olajyd: do you want first match?

5:53 Olajyd: Yup

5:53 oddcully: .indexOf

5:53 Olajyd: oh more of a global search in a string

5:53 TEttinger: the regex functions like re-find will tell you if the character has been found, but not where it is.

5:53 Olajyd: oh hi odcully :)

5:53 TEttinger: (inc oddcully)

5:53 lazybot: ⇒ 15

5:54 TEttinger: ,(.indexOf "alphabet" \p)

5: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...

5:54 TEttinger: ,(.indexOf "alphabet" "p")

5:54 clojurebot: 2

5:54 TEttinger: so that can take a single-letter string or a multiple-letter one

5:54 ,(.indexOf "alphabet" "bet")

5:54 clojurebot: 5

5:57 Olajyd: aite Tettinger, thanks

5:58 TEttinger: thanks to oddcully too!

5:58 crocket: Is (map list list-2 list-2) an ok way to zip several sequences?

5:59 (map list list-1 list-2 ...)

5:59 TEttinger: yeah, or mapcat, crocket

5:59 crocket: ,(doc mapcat)

5:59 TEttinger: depending on what you want for output

5: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"

5:59 TEttinger: ,(mapcat list (range 10) (range 20))

5:59 clojurebot: (0 0 1 1 2 ...)

6:00 TEttinger: ,(mapcat list (range 10) (range 10 20))

6:00 crocket: This is not ideal

6:00 clojurebot: (0 10 1 11 2 ...)

6:00 TEttinger: ,(map list (range 10) (range 10 20))

6:00 clojurebot: ((0 10) (1 11) (2 12) (3 13) (4 14) ...)

6:00 crocket: ,(doc zipmap)

6:00 clojurebot: "([keys vals]); Returns a map with the keys mapped to the corresponding vals."

6:02 TEttinger: ,(zipmap (range 5) (range 10 15))

6:02 clojurebot: {0 10, 1 11, 2 12, 3 13, 4 14}

6:03 crocket: zipmap doesn't scale beyond 2

6:03 ,(map list [1 2 3] [4 5 6] [7 8 9])

6:03 clojurebot: ((1 4 7) (2 5 8) (3 6 9))

6:03 TEttinger: yeah

6:03 crocket: ,(doc vector)

6:03 clojurebot: "([] [a] [a b] [a b c] [a b c d] ...); Creates a new vector containing the args."

6:03 crocket: ,(map vector [1 2 3] [4 5 6] [7 8 9])

6:03 clojurebot: ([1 4 7] [2 5 8] [3 6 9])

6:03 TEttinger: ,(mapv vector [1 2 3] [4 5 6] [7 8 9])

6:03 crocket: ,(map seq [1 2 3] [4 5 6] [7 8 9])

6:03 clojurebot: [[1 4 7] [2 5 8] [3 6 9]]

6:03 #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: core/seq--4116>

6:04 TEttinger: list is the fn used to create seqs, oddly -- seq converts a collection to a seq if non-empty, returns nil otherwise

6:10 crocket: http://dpaste.com/1R82TJ9 hangs

6:10 http://dpaste.com/1R82TJ9 hangs on line 15.

6:10 why?

6:10 clojurebot: because that's not how macros work

6:15 Olajyd: TEttinger, say after getting the index of the character in the string, we want to replace that character with another character?

6:15 TEttinger: crocket: http://clojuredocs.org/clojure.java.shell/sh#example-542692d6c026201cdc3270e7

6:15 Olajyd: off the top of my head, I don't have an answer, but there is likely something in the Java String API.

6: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")

6:17 TEttinger: that sounds like a better fit for regexes.

6:17 ,(clojure.string/replace "alphabet" #"p" "s")

6:17 clojurebot: "alshabet"

6:18 TEttinger: that does all of the occurences though.

6:18 ,(clojure.string/replace "alphabet" #"a" "o")

6:18 clojurebot: "olphobet"

6:18 TEttinger: ,(.replaceFirst "alphabet" "a" "o")

6:18 clojurebot: "olphabet"

6: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)

6:19 crocket: TEttinger, My code hangs and does nothing.

6:19 TEttinger: crocket: for 1 minute after when it may have exited?

6:20 if that's the case, it's related to using futures without calling a specific function to shutdown agents

6:21 (I also don't know if ffmpeg is getting the args it wants)

6:21 http://clojuredocs.org/clojure.core/future#example-542692c9c026201cdc326a7b

6:22 crocket: TEttinger, If I execute shell/sh in REPL, it works fine.

6: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"

6:25 crocket: what

6:25 TEttinger: wondering if ffmpeg is, in the program version, receiving the wrong args

6:26 crocket: As you can see on https://github.com/clojure/clojure/blob/master/src/clj/clojure/java/shell.clj#L128 , futures are resolved.

6:26 TEttinger: try printing *command-line-args*

6:26 crocket: *command-line-args* is not used yet.

6:27 TEttinger: you saw the line above that, right?

6:27 exit-code (.waitFor proc)

6:28 crocket: Somehow shell/sh just hangs.

6:28 TEttinger: if ffmpeg isn't returning, it will hang

6:29 3:30 AM. g'night

6:29 crocket: ok

6:32 You're right

6:32 shell/sh hangs for some reason.

6:32 ffmpeg returns

6:43 drwin: I have defined a defrecord, and I want to implement my own IPrintWithWriter, how to override defrecord's default one?

6:44 crocket: TEttinger2, shutdown-agents solves the waiting problem.

6:56 oh

6:56 ^"[Ljava.lang.String;" (into-array cmd)

6:56 What is this?

6:56 A type hinting?

7:10 opqdonut: crocket: yes

7:11 [Ljava.lang.String; is to the jvm what java.lang.String[] is to java, i.e. an array of Strings

7:11 crocket: How confusing

7:12 opqdonut: yeah the syntax could be better

7:28 varnie: good day.

7:29 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.

7:31 it gives me "CompilerException java.io.FileNotFoundException: Could not locate ..." error

7: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

7: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 ...)

7:43 well, here're two samples, the first one works, the second one does not:

7:43 1) http://pastebin.com/xQZtxFnG

7:43 2) http://pastebin.com/aJdYku9n

7:44 snowell: Honestly I've never used (load-file)

7:44 varnie: huh, okay. ;)

7:46 snowell: What if you try this: http://pastebin.com/daE0VCDv

7:46 varnie: then I have the same error

7:46 snowell: Taking :require out of the ns and having it as its own statement

7:46 varnie: wait, I'll rerun lein repl and try again...

7:47 same problem.

7:48 schmir: varnie: why don't you use require instead of load-file?

7:48 snowell: I find it hard to believe that specifying the full namespace of the function works but having a (require) doesn't

7:49 Not saying I don't believe you :)

7:49 varnie: schmir, what do you mean?

7:49 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?

7:50 I suppose it would be sane to require them in that file.

7:50 why not?

7: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

7:50 varnie: schmir, ah, I didn't know. Thank you.

7:52 schmir, can you please show how should my code snippet look then?

7: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)

7:55 in your REPL, you can then (require 'foo) and either call foo/print-extension or switch to the namespace with (in-ns 'foo)

7:55 varnie: are you using an IDE?

7:56 varnie: no, I do not.

7:56 FileNotFoundException Could not locate foo__init.class or foo.clj on classpath: clojure.lang.RT.load (RT.java:443)

7:56 I should run lein repl in the directory where my clj file is?

7:56 schmir: where your project.clj is

7:56 varnie: did you create a project?

7:56 varnie: I have only one file, get-extension.clj.

7:56 no

7:57 schmir: ok. that explains a lot!

7:57 varnie: that's exactly what I am trying to understand ;)

7:57 is it possible to have a single clj file without project?

7:58 schmir: yes, you can then use load-file to load the file from the REPL :)

7:58 but you shouldn't do that

7:58 varnie: okay, then why the second example does not work: http://pastebin.com/aJdYku9n ?

7:58 schmir: (at least not now, since you said your a beginner)

7:59 I think load-file doesn't like the namespace declaration

7: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

7:59 schmir: varnie: you really should set up a project

7:59 varnie: is there any way I can use "short cut/alias" for that long library name in my second example?

8:00 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...

8:01 schmir: varnie: without the namespace declaration the require looks like (require '[org.apache.commons.io.FilenameUtils :as FileNameUtils])

8: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

8: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"

8:03 oh, wait...

8:03 oddcully: wouln't an import here more appropriate?

8:03 s/here/& be/

8:04 varnie: no matter what I try, I end up with "CompilerException java.lang.ClassNotFoundException ..."

8:05 schmir: varnie: you really want a dedicated project, since you use apache commons

8:05 varnie: okay, thank you all.

8:05 schmir: varnie: boot scripts may be another option: https://github.com/boot-clj/boot/wiki/Scripts

9:34 justin_smith: varnie: that's not a namespace, that's a class

9:35 varnie: yup

9:35 justin_smith: so you've sorted it out then

9:37 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

9:38 varnie: justin_smith, do you agree that for my purpose I should create a new project?

9: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

9:40 varnie: I see.

9: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.

9:42 varnie: yes, that was my initial misunderstanding.

9: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 ?

9:51 xemdetia: d0ky, the idea of the ca.crt is you getting it signed from someone else

9:51 if you don't care about it being valid to your browser just use a self signed cert

9:51 (in that list of instructions)

9: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

9:52 then you can use that CA to sign your own certs

9:52 xemdetia: either way that instruction list is needlessly confusing for a one-off test

9:52 d0ky: but i did all what was in instructions and worked only test-ssl but ca.cert was not generated

9:53 xemdetia: I assume it is from that CA.pl file

9: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

9:56 especially function ssl-context not that library

9:59 xemdetia: d0ky, do you need your certificates to be things you can validate

9:59 it's easier to just self-sign a cert from the keystore

10:00 keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass password -validity 360 -keysize 2048

10:00 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 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 troydm: if you want a book on lisp and games, try The Land of Lisp

11:01 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 not at all

11:01 troydm: timvisher: ic, I was somehow confused

11:01 timvisher: I thought I've seen a book that describes Clojure from perspective of programming a game

11:02 timvisher: I guess I was confused because I though that Clojure for the brave and true was that book

11:03 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 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 others may disagree

11:09 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 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 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 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 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 the tooling's documentation barely does an adequate job of covering the tooling. :)

11:25 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 quite active!

11:27 timvisher: suck :(

11:27 slack is eating all that is beautiful. :)

11:27 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 timvisher: get your invite here http://clojurians.net/

11:28 tdammers: because technomancy is a free-software-hippy

11:29 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 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 "All Rights Reserved" is the default anyway (legally speaking)

11:31 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 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 *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 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 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 or is that something you can use via irc

11:49 cored: well

11:49 you will see a link and when you follows that link you will get the file

11:50 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 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 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 humans have API conventions too :)

11:54 cored: yes

11:54 I guess I'm waiting for that moment in which everything is getting done through Slack

11:55 even coding itself ;-P which probably will happen at some point

11:55 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 yes

11:56 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 that's one of the things that I can't do with irc

11:57 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 depending on what you want to do with any potential remainder

12:15 ,(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 ,(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 ,(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 ,(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 also somewhat interesting, you can't access the step arg as a transducer

12:22 ,(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 People can never agree on such fundamentals.

12:24 justin_smith: pflanze: yeah, we call that split-with

12:24 (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 I think amalloy is right.

12:25 justin_smith: yeah

12:26 ((map (group-by pred l)) [true false])

12:26 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 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 But I guess Clojurians just use maps instead?

12:31 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 This is sort of the perversity of OO: It teaches you to value the container more than the data.

12:43 (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 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 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 pflanze: Sorry, I'm in a "teaching beginners" headspace which also includes a "re-evaluating my own notions" headspace.

12:47 When I started with Clojure, I was positively offended that I could pass in a vector and get back a list.

12:48 Now I blithely flip between list, vector, set and map.

12:48 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 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 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 ,(type (sorted-map :a 0 :b 1))

12:56 clojurebot: clojure.lang.PersistentTreeMap

12:58 {blake}: justin_smith: Oh! Interesting.

13:00 ,(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 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 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 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 maybe not even that

13:08 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 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 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 Since Lisp is about having compile time at run time, this arguably matters.

13:18 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 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 So I guess over time, the use of dotted lists has been diluted increasingly, not only in Clojure, but already before.

13:19 I think it's a pity. But whatever.

13:20 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 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 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 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 {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 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 *OPTION

14:08 Okay reading Datomic changelog now.

14:15 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 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 seangrove: so a minimal profiles.clj for cider would be {:user {:plugins [[cider/cider-nrepl "0.9.1"]]}}

14:42 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 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 ... 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 breaking news: software requires bug fixes

15:13 sdegutis: Bronsa: Those are all free (gratis) open source projects. Huge difference.

15:13 Bronsa: Datomic is financially supported

15:13 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 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 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 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 That said, you may run into problems if you need different versions of Java JDK.

15:20 (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 but they are all there and ready to use

15:22 sdegutis: Maybe I have more than one also then.

15:23 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 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 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 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 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 Invokedynamic actually does have a guard condition that does this

15:36 sdegutis: Ah.

15:36 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 Well if Clojure's dynamic nature inherently requires this slowness and no optimizations can be done, then so be it.

15:38 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 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 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 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 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 I'll keep a pair of vector of keys and a map

17:35 persistent structures mean little wasted memory

17:35 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 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 I'm guess you'll want to write your own rand-nth

17:44 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 &(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 my repl did it in 0.05 msecs

17:50 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 ,(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 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 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 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 db attributes are basically like table definitions if this were sql

17:55 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 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 Doesn't it?

17:56 amalloy: oh i bet i remember

17:56 lazybot does really slow sandboxing around interop calls

17:56 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 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 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 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 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 granted, most "hacky" things won't, but I think that's just a coincidence

18:32 rhg135: s/hack/not pre done/

18:32 laziness

18:33 rappaport: It's thundering and it smells wonderful outside.

18:34 rhg135: core.async does have a pluggable executor

18:49 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 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 i gtg for the moment, but will read the logs when i get back

19:41 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 brb

20:01 slaterr: how to do this? "one two three" => "one - two - three"

20:02 what do I do after (str/split "one two three" #" ")?

20:02 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 #" +" 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 domokato: which is why I suggested take-while

21:08 but as amalloy mentions that's still not simple

21:08 domokato: ah yes

21:10 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 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 "

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 but....

21:44 neither does elements

21:44 maybe I didn't examine the question closely enough, was growth a requirement?

21:45 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 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 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 only surprising to me because I had been living in the impl for a while

21:51 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 let me think

21:57 seangrove: I suppose I need to coerce it with from-date

21:57 gfredericks: to print it?

21:57 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 seangrove: https://www.refheap.com/108392

21:59 now that I look at it there's probably a less wasteful way to do it

21:59 but that at least works

22:00 the i prefix there clojure.instant

22:00 is*

22:36 sdegutis: What's a good way to run swap! only once for a given atom with the given args?

22:36 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 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 gfredericks: Why? Hmm. Because I want the user attributes in the user.clj file, etc.

22:42 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 And then just search my codebase for vars with :schema in the metadata, and use those.

22:43 justin_smith, gfredericks: Actually I don't think that's what I'm trying to do.

22:44 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 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 the top requires others, required by nothing

22:45 sdegutis: Ah.

22:45 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 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 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 I guess I could turn that into [:make-one-attr :foo/bar :string] and transform that at consume-time.

22:51 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 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 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 The stupid solution I have, and justin_smith you will probably hate this, is (swap! db.schema/schema concat user-attributes)

22:54 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 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 but I've already voted for what I think the real solution is

22:56 sdegutis: Thanks justin_smith for your feedback.

22:56 I guess in order to maintain my (crazy?) stack order, I have to do it this way.

22:56 Otherwise I like your idea best.

23:43 ,(->> [] (conj 2) (atom) (def foo))

23:43 ,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 #object[clojure.lang.Var$Unbound 0x33ffc978 "Unbound: #'sandbox/foo"]

23:43 sdegutis: That should have worked right?

23:43 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 ,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 :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 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 it was a joyous day

23:46 sdegutis: :D

23:46 You should have put it in /r/lifeprotips for me

23:46 *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 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 d

23:48 rhg135: so java interop

23:48 sdegutis: and the :r/ namespace!

23:49 I bet all the people who have me on ignore are really confused why justin_smith wrote that lol

23:49 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 justin_smith: I think it's not cuz #

23:50 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 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 ,: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 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 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 "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 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 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

Logging service provided by n01se.net