#clojure log - Jul 21 2015

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

0:02 crocket: I just looked at lazybot code, and it doesn't provide a sandboxed environment for plugins.

0:02 justin_smith: crocket: it has a sandboxed eval

0:03 &(System/exit 0)

0:03 lazybot: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "exitVM.0")

0:03 crocket: However, developers will only accept plugins in the 'core' if it doesn't go beyond the boundary of a plugin.

0:23 kavkaz: After using the REPL I feel like putting a right bracket after every sentence I type

0:23 whether it be IRC or SMS on my phone

0:27 rhg135: (like this)

0:29 kavkaz: rhg135: yes

0:30 In some example code in a book about clojure, I'm seeing the character & being used like this: &{}

0:30 rhg135: (not (ready-for? world this))

0:30 kavkaz: what does this mean?

0:30 I know #{} is a set literal

0:30 but what does & mean in this context?

0:30 I couldn't find the character on the clojure cheat sheet.

0:31 rhg135: De structuring

0:31 justin_smith: kavkaz: ##((fn [&{a :a}] (inc a)) :a 1)

0:31 lazybot: ⇒ 2

0:31 justin_smith: & indicates that all following arguments are collected

0:31 lazybot: java.lang.RuntimeException: Unable to resolve symbol: indicates in this context

0:31 justin_smith: :P

0:32 and &{ ... } means it will be collected into a key/value hash map

0:32 rhg135: lazybot: disappointed

0:32 justin_smith: most people advise against using &{} actually

0:34 crocket: clojure 1.7 has new features like transducers, reader conditionals, warn on boxed math, update, and run!.

0:36 rhg135: I'm excited for 1.8

0:41 kavkaz: justin_smith: Thank you, I'm starting to get it

0:41 I've started clojure and functional programming a couple days ago, so it's taking some careful looking at

0:41 justin_smith: Why do most people advise against it?

0:42 It's just a map right?

0:42 justin_smith: kavkaz: a common thing to do in clojure is write a function that takes the same args, does some work, then calls the original function

0:42 kavkaz: sorry hashmap

0:42 justin_smith: this is harder to do with & {}

0:43 so, unless the usual usage of & (where you can use apply), you are stuck building the call by hand, or writing "mapply" or something

0:43 it's inconvenient

0:44 kavkaz: justin_smith: How would you do the example code you showed me without &{}

0:44 ?

0:44 I'm just curious because I'm new to clojure

0:45 justin_smith: ,((fn [{a :a}] (inc a)) {:a 41})

0:45 clojurebot: 42

0:45 justin_smith: in this case, the args are in an actual explicit hash-map

0:46 which means that you can use the hash-map to modify the args before calling the original (if you were extending it somehow)

0:48 kavkaz: justin_smith: Okay, I see, thank you

0:48 I'll just have to keep coding and reading this book and the documentation lol

0:54 justin_smith: Oh actually, I've been looking at & in the context of the parameter vector

0:54 justin_smith: kavkaz: yes. That's where it is used.

0:55 kavkaz: Oh true

0:57 crocket: http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming

0:57 kavkaz: well in the example it was [a b & { <map> }

0:57 crocket: justin_smith, Can you tell me more about sandboxed eval?

0:58 kavkaz: [a b & { <map> }]

0:58 justin_smith: kavkaz: sure, same as the other examples, except the a b part

0:58 crocket: I'm about to turn in for the night actually

0:59 kavkaz: After reading some documentation i thought the use of the ampersand in this case was [a b & more]

0:59 crocket: clojail

0:59 justin_smith: kavkaz: the a and b are optional

0:59 kavkaz: where more would be Nil if the passed parameters were only a and b

0:59 crocket: It uses clojail.

0:59 kavkaz: but anyways I'll keep looking into it

0:59 thank you justin_smith

0:59 justin_smith: and "more" is handled differently if it's a hash-map

1:03 kavkaz: good night guys

1:04 crocket: clojail is messy.

1:04 It requires ~/.java.policy

1:07 tolstoy: Is there an implementation of the ~ operator in Clojure somewhere?

1:08 bit-complement?

1:10 TEttinger: tolstoy: the bit-??? fns do pretty much everything bit-related. Do you mean ~ in... which language?

1:10 tolstoy: Python.

1:10 TEttinger: what does it do in Python? I'm not a python guy

1:10 tolstoy: Basically, swap all 1 bits for 0 bits.

1:10 TEttinger: ah

1:10 uh

1:10 hang on

1:11 tolstoy: I'm porting some code, so that's what's catching me up.

1:11 TEttinger: that seems not very handy, unless it takes more than one arg

1:11 tolstoy: If I knew the exact size of the integer, I could just use bit-flip.

1:11 TEttinger: ,(bit-and 0 15)

1:11 clojurebot: 0

1:11 tolstoy: seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B)

1:12 TEttinger: does it also swap all 0 bits for 1 bits?

1:12 tolstoy: I think so.

1:12 http://stackoverflow.com/questions/791328/how-does-the-bitwise-complement-operator-work

1:13 Oh. bit-not, maybe?

1:13 TEttinger: bit-not yeah

1:13 ,(bit-not 8)

1:13 clojurebot: -9

1:14 tolstoy: Python: ~2 -> -3

1:14 TEttinger: ,(bit-not -2r1000)

1:14 clojurebot: 7

1:14 tolstoy: Clojure: (bit-not 2) -> -3

1:14 ,(bit-not 2)

1:14 clojurebot: -3

1:14 TEttinger: woo

1:14 tolstoy: Good enough to continue the struggle.

1:14 TEttinger: the 2r thing is handy in case you haven't used it

1:15 tolstoy: What is it?

1:15 TEttinger: r for radix, it's base 2 literal

1:15 you can actually use any radix from 2 to 36

1:15 ,2r101101

1:15 clojurebot: 45

1:15 TEttinger: ,36rFUNZILLA

1:15 clojurebot: 1242216307918

1:16 tolstoy: So, give me the base 2 number 101101?

1:16 And then the printer prints it in base 10.

1:17 That is very handy.

1:17 ,16rFFF0

1:17 clojurebot: 65520

1:18 crocket: It feels like a huge mistake to make namespace mutable.

1:20 TEttinger: tolstoy: if you want to print in base (2 to 36), do ##(Long/toString 1242216307918 36)

1:20 lazybot: ⇒ "funzilla"

1:20 TEttinger: tolstoy: if you want to print in base 2, do ##(Long/toBinaryString 1242216307918)

1:20 lazybot: ⇒ "10010000100111001110111001001110011001110"

1:23 crocket: ,(println "say bitch")

1:23 clojurebot: say bitch\n

1:25 crocket: How do I sandbox arbitrary code without ~/.java.policy?

1:27 TEttinger: I think the contents of java.policy can be added programmatically

1:36 crocket: Is into lazy by default?

1:39 Listen to one of rich hickey's greatest videos. https://www.youtube.com/watch?v=6mTbuzafcII

1:58 bja: into is strict

2:00 err, eager

2:36 namra: someone using metrics-clojure-ring and can tell me what the rates mean for handling-time.METHOD events?

2:36 the rate of requests/s for that method over 1/5/15min?

4:42 crocket: It feels as if eduction is similar to sequence.

5:14 Man, it is difficult to understand transducers...

5:18 kungi: Deraen: Ping! Could you help me for a second with my compojure.api code. I upgraded to compojure api 0.22.1 and tried the upload. But now I get the following error: No method in multimethod 'restructure-param' for dispatch value: :multipart-params

5:19 Deraen: For some reason the multimethod definition from compojure.api.meta is not loaded?

5:29 crocket: Does anyone know a decent transducer learning material?

5:52 Ok, map returns a transducer. A transducer is passed another transducer or a reducing function to create another reducing function.

5:52 fn in fn in fn

5:55 This is a brain massage.

6:05 sandbags: Is there anyone who can help me with lein-wsimport (yes may god have mercy on my soul, SOAP) and a problem I am having enabling external scheme (error 'chema_reference: Failed to read schema document 'xjc.xsd', because 'file' access is not allowed due to restriction set by the accessExternalSchema property'). I've tried specifying :jvm-opts ["-Djavax.xml.accessExternalSchema=all"] in my project.clj which is - i think - the right way

6:05 to solve this but no dice. Help!

6:06 project.clj & full error here https://gist.github.com/mmower/78a1b440ffce7035832b

6:10 i wonder if the problem is that wsimport is not being run with the jvm options... i've no idea how that bit works

6:17 * sandbags sighs

6:21 sandbags: lein-wsimport is calling WsImport#doMain so, presumably, will inherit JVM opts so this should work

6:30 frak... according to (System/getProperty "javax.xml.accessExternalSchema") it is set to "all" ... :-(

6:30 sorry for the stream of consciousness... obv nobody here with any insight into wsimport and probably (just as I would have been) little interest :)

6:31 crocket: Can anyone help me understand transducer step arity?

6:31 When is it called?

6:33 Ah

6:33 ok

6:33 Completion arity in transducer feels like a boiler plate, doesn't it?

6:43 I think I found a bug in completing.

6:43 completing doesn't add 0 arity to a reducing function.

6:44 sdg

6:44 -

6:50 Ouch

7:59 diyfupeco: Is there a way to automatically load new code when something changed on disk?

8:00 (using leiningen)

8:05 crocket: Is it ok to not define a 0 arity in a transducer?

8:06 wasamasa: diyfupeco: environments like figwheel do that kind of thing

8:06 crocket: ,(doc completing)

8:06 clojurebot: "([f] [f cf]); Takes a reducing function f of 2 args and returns a fn suitable for transduce by adding an arity-1 signature that calls cf (default - identity) on the result argument."

8:07 justin_smith: oh, that's very nice

8:07 crocket: completing is not going to work because a transducer requires a 0-arity signature.

8:08 I understand completing as a way to convert a reducing function into a transducer.

8:09 justin_smith: it addresses the common case where you have an accumulator that holds things other than your result, to simplify getting the part of the accumulator you actually want in the end

8:10 crocket: ???

8:10 lazybot: crocket: How could that be wrong?

8:11 justin_smith: crocket: often when I use reduce, the accumulator holds other values along with the actual result

8:11 so I end up needing another function which gets the part I actually want out of the accumulator at the end

8:14 crocket: What is the accumulator?

8:14 You mean the reducing function?

8:14 justin_smith: ,(reduce (fn [[runs run] v] (if (= v (peek run)) [runs (conj run v)] [(conj runs run) []])) [[] []] [:a :a :b :b :b :b :c :c :a :d :d])

8:14 clojurebot: [[[] [] [] [] [] ...] []]

8:14 justin_smith: err

8:15 crocket: the first arg to the reducing function is the accumulator

8:15 crocket: ok

8:15 initial value

8:15 Anyway, a transducer created by completing won't serve as a general transducer.

8:16 I am not sure when the 0-arity signature is used in a transducer.

8:16 justin_smith: ,(reduce (fn [[runs run] v] (if (= v (peek run)) [runs (conj run v)] [(conj runs run) [v]])) [[] []] [:a :a :b :b :b :b :c :c :a :d :d])

8:16 clojurebot: [[[] [:a :a] [:b :b :b :b] [:c :c] [:a]] [:d :d]]

8:17 justin_smith: that needs a final step, where [:d :d] is conj'd on the end

8:18 crocket: Your example is hard to read.

8:21 justin_smith, Can you tell me when the 0-arity signature is used in transducers?

8:35 justin_smith: crocket: it is mentioned by the doc string for transduce

8:36 ,(transduce identity (completing (fn [[runs run] v] (if (= v (peek run)) [runs (conj run v)] [(conj runs run) [v]]))) [[] []] [:a :a :b :b :b :b :c :c :a :d :d])

8:36 clojurebot: [[[] [:a :a] [:b :b :b :b] [:c :c] [:a]] [:d :d]]

8:38 justin_smith: completing adds a 1-arg arity

8:39 crocket: I don't know where this 0-arg is that you are talking about

8:39 crocket: ,(doc transduce)

8:39 clojurebot: "([xform f coll] [xform f init coll]); reduce with a transformation of f (xf). If init is not supplied, (f) will be called to produce it. f should be a reducing step function that accepts both 1 and 2 arguments, if it accepts only 2 you can add the arity-1 with 'completing'. Returns the result of applying (the transformed) xf to init and the first item in coll, then applying xf to that result and ...

8:39 crocket: transduce avoids using 0-arity signature.

8:39 justin_smith: where is the 0 arity signiture you keep mentioning?

8:39 crocket: By calling (f) directly.

8:40 justin_smith, http://clojure.org/transducers#toc8

8:41 justin_smith: crocket: OK. It's used to create an initial value for the transduce when none is explicitly supplied. Like it says.

8:41 crocket: justin_smith, https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L7323

8:42 kwladyka: What about sets performance vs vectors?

8:42 add/remove first/last positions

8:42 crocket: justin_smith, https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L6566

8:42 justin_smith: kwladyka: sets do not have a "first" or "last" position

8:42 kwladyka: they are not ordered

8:43 crocket: like I said, the docs are clear now that you link them, it creates the initial value for transduce

8:43 kwladyka: ,(first #{1 2})

8:43 clojurebot: 1

8:44 justin_smith: ,(first #{1 2 3 4 5 6 7 8 9 10})

8:44 clojurebot: 7

8:44 justin_smith: first will return a value, it will not return the first item, because there is no such thing

8:44 kwladyka: so when i will use it with loop and recur and use first and rest it will work or not?

8:44 justin_smith: definitely not, no

8:45 kwladyka: so bad

8:45 justin_smith: I mean maybe by accident, depending on what you are trying to do...

8:45 but you can't count on any particular item being the first without relying on implementation details

8:45 Wild_Cat: kwladyka: if you want to iterate on the entire contents of a set, use map

8:45 justin_smith: kwladyka: actually, first and rest should split one item off...

8:46 kwladyka: but... if first always return the same element (not exactly first) rest should return always the rest?

8:46 justin_smith: yes, that's true

8:46 crocket: The doc forgot to mention that completing also adds 0-arity signature.

8:46 justin_smith: the order is just weird and undefined

8:47 kwladyka: i don't care about order too much, but i guess performance of sets should be as good as vectors?

8:47 justin_smith: they are slower

8:47 crocket: I think completing should be used as (partial completing f) since cf is the reducing function.

8:47 kwladyka: do you know any statistic? I can't find information liek that

8:48 Wild_Cat: kwladyka: sets are O(1) for insertion, but with a higher constant than vectors

8:48 kwladyka: if you don't explicitly care about the uniqueness constraint, a set will be slower than a vector

8:49 kwladyka: anyway... i will do algorithm and if it will be to slow i will change data structure

8:49 justin_smith: kwladyka: runnint criterium now, will share the results when done

8:50 crocket: Now, completing doesn't seem to make a valid transducer.

8:50 Wild_Cat: that said, the fact that you struggle with understanding the very basic performance profiles of these data structures tells me that you're not writing something performance-critical enough to care about the difference. Just use whatever is the most logical for your use case and disregard the performance aspect.

8:51 kwladyka: Wild_Cat, but it is always good occasion to learn something more, like a basic performance :)

8:52 justin_smith: vectors are about 10x faster for appending https://www.refheap.com/106778

8:53 kwladyka: i also see very good side of not mutable data, all things should take less memory

8:53 justin_smith, thank you

8:56 justin_smith: it's really sad that I can tell from the noise floor on my monitors when criterium is done running

8:56 haha

8:56 when the CPU is not working as hard the timbre changes

8:58 kwladyka: paste updated, the ratio gets closer with smaller collections (because some of the shared constant time costs become a bigger part of the resulting runtime I guess) https://www.refheap.com/106778

9:37 crocket: justin_smith, I figured out that completing is not meant to produce a transducer.

9:37 https://groups.google.com/forum/#!topic/clojure/6cnVMUe5ALE

9:39 This is really ugly.

9:39 diyfupeco: thanks wasamasa

9:41 crocket: Is there a macro for writing a transducer concisely?

9:42 or a function for doing so?

9:43 snowell: crocket: Leaving out the final argument to a sequence function call (map, filter, etc) returns a transducer

9:43 You can comp transducers together to create one that does multiple things

9:46 crocket: snowell, Is there a transducer that drops key-val pairs with nil vals in a map?

9:47 snowell: I would think (remove #(nil? (val %))) should work

9:49 Heh, or even better… (filter val)

9:49 ,(filter val {:a 1 :b 2 :c nil :d 4 :e 5 :f nil})

9:49 clojurebot: ([:a 1] [:b 2] [:d 4] [:e 5])

9:50 snowell: If you want it to be a map, which of course you would, you could (comp (filter val) (into {}))

9:54 crocket: snowell, On https://www.refheap.com/106782 , I rewrote assoc-in-cond2 as assoc-in-cond with transduce.

9:57 snowell: And it's not working?

9:57 crocket: It does work.

9:57 Can you think of a more concise way to write assoc-in-cond?

9:58 snowell, ^^

9:59 I think the function in completing could be written more conscisely.

9:59 snowell: I'm a relative newb compared to others here, so no I can't :D

10:00 I doubt I'd have gotten it THAT concise to begin with!

10:07 crocket: Is there a function that detects non-sequential value and turns it into a sequence?

10:07 A transducer is even better.

10:07 Ah

10:08 map is a transducer.

10:08 like (seqify 3) == '(3)

10:08 (seqify '(3)) == '(3)

10:10 ,(seq :3)

10:11 clojurebot: #error {\n :cause "Don't know how to create ISeq from: clojure.lang.Keyword"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Don't know how to create ISeq from: clojure.lang.Keyword"\n :at [clojure.lang.RT seqFrom "RT.java" 528]}]\n :trace\n [[clojure.lang.RT seqFrom "RT.java" 528]\n [clojure.lang.RT seq "RT.java" 509]\n [clojure.core$seq__4126 invoke "core.clj" 135]\n [sand...

10:14 sveri: Hi, I want to insert something like {%if toread.done = 1 %}checked{% endif %} into a hiccup form, is there a way to do that?

10:16 hyPiRion: sveri: (if (= (:done toread) 1) "checked") ?

10:16 I have no idea what toread is, might want to use (.done toread) instead

10:17 sveri: hyPiRion: no, I mean the string: "{%if toread.done = 1 %}checked{% endif %}" into a hiccup form which generates <input ... {%if toread.done = 1 %}checked{% endif %} />

10:17 sorry for being unclear

10:17 justin_smith: sveri: hiccup forms are just clojure data structures, so there's as many ways to generate that as you like

10:18 sveri: so you have a post-processor over your hiccup output?

10:19 sveri: yea, I generate selmer html templates with hiccup

10:21 justin_smith: one way would be enough for me :D I am using hiccup like this now [:input {:key "val"} "string"] which generates <input "key"="val">string</input> but as "{%if toread.done = 1 %}checked{% endif %}" is no key value pair I am a bit stuck

10:22 justin_smith: sveri: yeah, when I said that I thought you were talking about generating html

10:22 and of course that's not html

10:23 crocket: Is there a way to map over only values in a map?

10:23 sveri: justin_smith: true

10:23 ok, so I generate selmer templates

10:23 crocket: ,(map #(update % 1 name) {:a :b :c :d})

10:23 clojurebot: ([:a "b"] [:c "d"])

10:23 justin_smith: sveri: my sad suspicion is you won't be able to do that because hiccup was never intended to be a general purpose renderer that could do non-html output

10:24 sveri: justin_smith: that's my assumption too after reading the docs, just wanted to make sure I am not missing anything

10:24 justin_smith: ,(map name (vals {:a :b :c :d :e :f})

10:24 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

10:24 hyPiRion: sveri: I've tried to unescape html into hiccup in the past without luck

10:24 justin_smith: ,(map name (vals {:a :b :c :d :e :f}))

10:24 clojurebot: ("b" "d" "f")

10:24 justin_smith: ,(into {} (map #(update % 1 name) {:a :b :c :d :e :f}))

10:25 clojurebot: {:a "b", :c "d", :e "f"}

10:25 crocket: ,(into {} (map #(update % 1 name)) {:a :b :c :d})

10:25 clojurebot: {:a "b", :c "d"}

10:26 crocket: I can't find a way to write it more concisely.

10:28 Is there a way to write https://www.refheap.com/106785 more concisely?

10:30 sveri: thanks everyone

10:39 crocket: ,(reduce #(+ %2) nil [1 2 3])

10:39 clojurebot: 3

10:39 crocket: How does it return nil?

10:39 oops

10:42 perplexa: ¯\_(ツ)_/¯

10:42 justin_smith: perplexa: I really wish it was possible to name a function that

10:42 perplexa: haha

10:42 isn't it?

10:43 oddcully: you cant?

10:43 justin_smith: it has parens in it

10:43 one moment, faking it

10:43 oddcully: there are for sure some utf-8 parens out there in the wild

10:43 perplexa: my repl strips the ツ :(

10:44 justin_smith: the harder part is the \ I think

10:45 I guess you could just fake the \ and the ( ) with unicodes

10:45 blkcat: #clojure, solving the important problems :P

10:45 justin_smith: the result should be (defmacro \_(ツ)_/¯ [& boxy] `(try ~@body (catch Throwable t :WHATEVER)))

10:46 err, body, whatever

10:47 kavkaz: hey justin_smith

10:48 justin_smith: yes?

10:50 kavkaz: just saying hello

10:50 justin_smith: oh, hi

10:53 wasamasa: justin_smith: now we know what's on your mind

11:04 justin_smith: ,(defmacro ¯\_❨ツ❩_/¯ [& bo `(try ~@body (catch Throwable t# :ok)))

11:04 clojurebot: justin_smith: Pardon?

11:04 justin_smith: :P

11:04 the unicode I used messes with my terminals

11:05 Bronsa: (defmacro (╯°□°)╯︵ ┻━┻ [& body] `(throw (Exception.)))

11:06 gfredericks`: ,(defmacro (╯°□°)╯︵ ┻━┻ [& body] `(throw (Exception. ~(pr-str &form))))

11:06 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

11:06 Bronsa: ah, the open paren :(

11:06 gfredericks`: the sideways one?

11:07 justin_smith: yeah, I used a doppleganger

11:07 Bronsa: ,(defmacro ❨╯°□°)╯︵ ┻━┻ [& body] `(throw (Exception. ~(pr-str &form))))

11:07 clojurebot: #error {\n :cause "Don't know how to create ISeq from: clojure.lang.Symbol"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol, compiling:(NO_SOURCE_FILE:0:0)"\n :at [clojure.lang.Compiler macroexpand1 "Compiler.java" 6644]}\n {:type java.lang.IllegalArgumentException\n :message "Do...

11:07 justin_smith: or are those already doppleganger parens?

11:07 Bronsa: ,(defmacro ❨╯°□°)╯︵┻━┻ [& body] `(throw (Exception. ~(pr-str &form))))

11:07 clojurebot: #'sandbox/❨╯°□°)╯︵┻━┻

11:07 Bronsa: there

11:08 gfredericks`: ,(❨╯°□°)╯︵┻━┻ whatever I don't even)

11:08 clojurebot: #error {\n :cause "(❨╯°□°)╯︵┻━┻ whatever I don't even)"\n :via\n [{:type java.lang.Exception\n :message "(❨╯°□°)╯︵┻━┻ whatever I don't even)"\n :at [sandbox$eval96 invoke "NO_SOURCE_FILE" -1]}]\n :trace\n [[sandbox$eval96 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 6792]\n [clojure.lang.Compiler eval "Compiler.java" 6755]\n [clojure.core$eval invoke "core.clj

11:08 gfredericks`: perfect

11:08 Bronsa: heh

11:08 justin_smith: sweet

11:08 gfredericks`: (clojure.string/join " " (map pr-str &form)) might be slightly better

11:23 crocket: Can anyone write https://www.refheap.com/106785 more concisely?

11:24 Can I write (fn [m [keys val]] (assoc-in m keys val)) more concisely?

11:31 #(apply assoc-in %1 %2) can be done, but this is confusing.

11:35 gfredericks`: I am using node with cljs and I don't know what I'm doing

11:35 debugging is hard

11:37 I don't know how to get a cljs repl

11:40 crocket: gfredericks`, Are you writing a command line app?

11:43 justin_smith: gfredericks`: you can get a cljs repl with the cljs standalone jar

11:45 gfredericks`: justin_smith: does that use rhino?

11:45 crocket: developing a library

11:45 it's not a webby library so I want to avoid browsers if I can

11:49 crocket: webby?

11:52 gfredericks`: has nothing to do with doms or ajax

11:55 justin_smith: gfredericks`: hmm, not sure actually

11:56 csd_: Hello-- If I have two successive calls to >! or >!! to the same channel, is order of delivery guaranteed?

11:56 justin_smith: gfredericks`: https://github.com/clojure/clojurescript/wiki/REPL-Options

11:57 csd_: in terms of control flow in your block of code, it will go start to end. I am not sure if there are strong guarantees of channels being ordered?

11:58 gfredericks`: yep looks like `lein test` can't find .cljc files

11:58 to the githubmobile!

11:59 justin_smith: gfredericks`: yeah, I ran into this a few times (same issue with eastwood)

11:59 csd_: justin_smith: yeah so if one >! is called before another, is it guaranteed to be delivered first too?

11:59 justin_smith: gfredericks`: I linked to the wrong page before, this is the right one https://github.com/clojure/clojurescript/wiki/Running-REPLs

11:59 csd_: curious about both >! and >!!

11:59 gfredericks`: justin_smith: no github issue for lein yet that you know of?

12:00 justin_smith: csd_: it will be delivered first because the next one won't be run until the first one is

12:00 gfredericks`: definitely an issue, I forget the details

12:00 something about bultitude?

12:00 csd_: ok thanks

12:01 justin_smith: gfredericks`: that wiki page shows separate config for node repl, rhino repl, etc.

12:01 Legendary_Linux: Hey so I'm entirely new to clojure and clojurescript, but I want to learn. Anyone know of some good tutorials to help me learn? A syntax guide would be awesome to start.

12:02 justin_smith: syntax? we don't need no stinking syntax!

12:02 Legendary_Linux: clojure.org has great docs for a start

12:02 for the super basic stuff

12:03 Legendary_Linux: I did find this, which was sort of helpful. http://clojurescriptkoans.com/

12:03 justin_smith: Legendary_Linux: for exercises, 4clojure is great too

12:03 http://www.4clojure.com/

12:03 Legendary_Linux: justin_smith: Thanks.

12:04 justin_smith: just be aware the difficulty is not all in numeric order, feel free to start skipping eventually

12:04 it will suggest "try X next" and X isn't always the best next puzzle to try

12:05 gfredericks`: justin_smith: this repl stuff looks promising, thanks

12:05 justin_smith: Legendary_Linux: depending on how much programming experience you have, there is also clojure from the ground up by aphyr, and clojure for the brave and true

12:05 gfredericks`: yeah, thankfully dnolen realized how tangled the world of cljs tooling got and prioritized making some (relatively) simple options available. Which is awesome.

12:05 (inc dnolen)

12:05 lazybot: ⇒ 23

12:08 Legendary_Linux: I have history with C, C++, and Java. That was a few years ago, though. More recently I've been doing PHP, JS, and Node.js

12:09 justin_smith: yeah, clojure from the ground up would likely be a bit too introductory then

12:10 though clojure for the brave and true might be OK, if you can handle how "twee" it can be sometimes

12:10 Legendary_Linux: Twee?

12:10 justin_smith: Legendary_Linux: kinda cute, silly

12:11 blkcat: i enjoyed clojure for the brave and true

12:11 Legendary_Linux: How much difference is there between Clojure and ClojureScript?

12:11 blkcat: but you definitely have to be OK with a great deal of levity :p

12:12 justin_smith: Legendary_Linux: they both use host interop a lot. Aside from the host interop they are very similar.

12:12 Legendary_Linux: I can deal with that. Thanks for the suggestions, all.

12:12 justin_smith: the host interop will be very familiar based on your java / javascript experience

12:12 though the syntax is different of course

12:19 dnolen: not sure of ATXers hang out here but https://twitter.com/swannodette/status/623527687932481536

12:29 crocket: Is there a build-in function for (map #(update % 1 fn) {:a :b ...})?

12:29 It is map-val.

12:35 gfredericks`: there is no built-in map-vals

12:35 the easiest is (into {} (for [[k v] m] [k (f v)]))

12:36 prismatic/plumbing has it; I'm sure other util libs do too

12:36 TimMc: crocket: clojure.algo.generic.functor/fmap

12:37 gfredericks`: oh dear

12:37 crocket: TimMc, Is it part of core?

12:37 TimMc: nope

12:37 No lie, we have pulled in that entire lib just for fmap on maps. It's kind of silly.

12:37 crocket: I have (into {} (map #(update % 1 name) m))

12:37 TimMc: [org.clojure/algo.generic "0.1.2"]

12:38 gfredericks`: TimMc: that's kind of silly

12:38 TimMc: crocket: (zipmap (keys m) (map f (vals m)))

12:38 there are so many ways to write this

12:39 crocket: So many ways to confuse users

12:39 TimMc: fmap is written (into (empty m) (for [[k v] m] [k (f v)]))

12:39 but maybe for perf it should use transients?

12:48 justin_smith: TimMc: I thought into used transients

12:48 oh wait no it uses transducers, my bad

12:48 crocket: transducers win over transients

12:49 justin_smith: but trans* beats everything

12:49 crocket: Oh my god, iterate creates a recursive data structure!!!

12:50 justin_smith: um, it can

12:50 it doesn't have to

12:50 ,(iterate inc 0)

12:50 clojurebot: (0 1 2 3 4 ...)

12:50 blkcat: they were clearly overwhelmed by this revelation

12:50 justin_smith: nothing recursive about that data structure

13:08 xemdetia: and then they died

13:11 scriptor: wonder what they meant by recursive data structure

13:35 mmeix: short question:

13:35 I have in a let:

13:36 (let [sw1 (if (< s e) 1 0), sw2 (if (= 1 sw1) 0 1)])

13:36 there must be a more elegeant way to say this

13:37 gfredericks`: sw2 (- 1 sw1)

13:38 mmeix: ah, silly me ... thanks!

13:39 (inc gfredericks)

13:39 lazybot: ⇒ 142

13:44 gfredericks`: mmeix: there's also (bit-xor 1 sw1)

13:44 mmeix: wow

13:44 ok ...

13:45 would be much faster, I guess ...

13:45 gfredericks`: hypothetically

13:45 justin_smith: ,(bit-xor 1 1)

13:45 clojurebot: 0

13:45 justin_smith: ,(bit-xor 1 0)

13:45 clojurebot: 1

13:45 TimMc: blkcat: "My god, it's full of cons cells!"

13:45 mmeix: the wise are thinking alike :-)

13:47 aha, this is a function of clojure.lang.Numbers in source, interesting

13:47 scriptor: not sure if bit-xor would be that much faster

13:48 mmeix: (in my case speed doesn't matter much)

13:49 (just flipping a flag in a SVG path)

13:49 gfredericks`: yeah do whatever is the clearest to you

14:01 omg I think I have to implement bit-count for 64-bit integers in cljs

14:01 justin_smith: gfredericks`: how do you even do a 64 bit integer in cljs? where do you get the extra bits to make that work?

14:04 gfredericks`: justin_smith: gclosure has a Long

14:04 TimMc: justin_smith: Store them as properties on the number.

14:04 gfredericks`: lol

14:05 TimMc: (function(x) { x.foo = "bar"; console.log(x.foo); })(3)

14:05 ^ Prints undefined, but does not error.

14:05 gfredericks`: erroring would be hostile to developers

14:05 nobody likes to see error messages

14:08 TimMc: I think 3 is getting boxed as a Number, but I don't know why Number silently throws away property writes.

14:10 gfredericks`: what does it mean for a js number to be boxed?

14:11 amalloy: TimMc: (function(x) {console.log(x.foo="bar");})(3) // quick hack TODO figure out why this is needed

14:11 TimMc: amalloy: :-)

14:12 gfredericks`: new Number(3) + 5 //= 8

14:12 typeof new Number(3) //= "object"

14:13 typeof Number(3) //= "number"

14:14 amalloy: TimMc: actuall new Number(3) + 5 == 8 in my browser

14:14 but here is a funny thing i just found in the ecmascript spec: Number is the inverse of new Number

14:24 justin_smith: amalloy: did you see my hilarious destructuring pitfall the other day?

14:24 amalloy: uh

14:25 oh, the keyword and some sort of not-actually-space space?

14:25 justin_smith: ,(let [{:keys {a b c d}} {:a 0 :b 1 :c 2 :d 3}] [a b c d])

14:25 clojurebot: [nil nil nil nil]

14:25 amalloy: hah

14:25 justin_smith: of course the keys arg should have been a vector

14:25 but it just silently gives you nil

14:26 amalloy: led to a hilarious wild goose chase

14:26 amalloy: ,(let [{:keys #{a b c d}} {:a 1 :b 2 :c 3 :d 4}] [a b c d])

14:26 clojurebot: [1 2 3 4]

14:26 amalloy: ,(let [{:keys #{a b c d e f g h i}} {:a 1 :b 2 :c 3 :d 4}] [a b c d])

14:26 clojurebot: [1 2 3 4]

14:26 amalloy: hmmmph, i was hoping for some sort of rearrangement from the conversion to hashset

14:27 justin_smith: another fun one (which I found much faster) ##(let [{:keys [a b c :a all]} {:a 0 :b 1 :c 2}] all)

14:27 lazybot: ⇒ nil

14:27 justin_smith: of course the :as all needs to be moved out of the vector

14:27 err, I didn't even do the :as right this time

14:27 another fun one (which I found much faster) ##(let [{:keys [a b c :as all]} {:a 0 :b 1 :c 2}] all)

14:27 lazybot: ⇒ nil

14:28 Bronsa: c.c/destructure is just awful

14:29 unreadable, unmaintainable and accepts lots of bad inputs

14:29 amalloy: Bronsa: has anyone tried to rewrite it? it seems like it shouldn't be *that* hard to redo from scratch, even if reading the existing one is impossible

14:29 Bronsa: amalloy: have fun trying to get a refactoring commit into clojure

14:30 justin_smith: Bronsa: on top of that, also it can be slow, and it can undermine laziness

14:30 amalloy: oh, sure

14:30 justin_smith: those might be harder to fix

14:30 amalloy: justin_smith: you mean because of the nth calls?

14:30 justin_smith: amalloy: I think so, it's actually something that came to my attention via yourself. I just superstitiously avoid destructuring when I need maximal laziness now :P

14:31 Bronsa: amalloy: I think the big issue with the current version is that it tries too hard to be super generic and reuse one code-path to do all the nested destructuring

14:31 amalloy: oh, i meant the slowness. that's not what causes laziness issues

14:31 Bronsa: justin_smith: it can also mess with locals clearing!

14:31 justin_smith: ahh, I just know that from benchmarking. Probably the extra collection making and such? not sure

14:31 wow

14:31 Bronsa: (because of a bug in locals clearing though)

14:32 TimMc: amalloy: //= was supposed to be a comment followed by an equals sign, like ;;=

14:32 Bronsa: justin_smith: it will sometimes bind unused and unreachable locals which the compiler can't clear. I have a ticket w/ patch in jira but..

14:32 amalloy: justin_smith: well because it calls nth a lot

14:33 ,(#'clojure.core/destructure '[_ _ _ _ _ _ _ _ _ _ x])

14:33 clojurebot: [_ _ _ _ _ ...]

14:33 amalloy: ,(#'clojure.core/destructure '[[_ _ _ _ _ _ _ _ _ _ x] y])

14:33 clojurebot: [vec__128 y _ (clojure.core/nth vec__128 0 nil) _ ...]

14:33 justin_smith: ahh

14:33 amalloy: so if y is a seq it calls nth 0, nth 1, nth 2...

14:33 justin_smith: nice

14:33 amalloy: where instead it could be using nthnext and first

14:35 Bronsa: amalloy: uh, are you saying walking a seq of a vector is faster than accessing each element?

14:36 amalloy: Bronsa: for a vector it's not, and for a seq itis

14:36 TimMc: &(let [{:keys {AAAAA BBBBB}} {(keyword "[AAAAA BBBBB]") [5 6]}] AAAAA) ;; amalloy, another result from justin_smith's discovery

14:36 lazybot: ⇒ 5

14:36 kwladyka_: How to transform (1 2 3 4) into (4 1 2 3)?

14:36 in elegant way

14:36 Bronsa: amalloy: right, I guess vector destructuring is optimized for vector access

14:36 TimMc: kwladyka_: (constantly (list 4 1 2 3))

14:36 amalloy: right, but an awful lot of the time we actually have lists

14:37 hiredman: no, it is sequential destructuring

14:37 Bronsa: ah

14:37 amalloy: and it's not hard to check whether the thing you're destructuring supports nth via whatever interface

14:37 Bronsa: yeah, true that

14:37 kwladyka_: TimMc, ?

14:37 amalloy: or to make nthnext and first be fast on vectors (like subvec)

14:37 TimMc: kwladyka_: (cons (last xs) (butlast xs)) perhaps

14:37 kwladyka_: You didn't explain the relationship between the two, so I had to guess.

14:38 Maybe you want all inputs to become (4 1 2 3), for example!

14:38 amalloy: TimMc: that was the one i guessed when he asked me

14:38 kwladyka_: TimMc, you have strange intuition :)

14:38 TimMc, anyway thx for solution

14:38 amalloy: although since i wasn't reading it at the time i mis-guessed the cause

14:38 chouser: (->> xs cycle (drop 3) (take 4))

14:39 TimMc: kwladyka_: Did I guess right, then?

14:39 kwladyka_: TimMc, (cons (last xs) (butlast xs))

14:40 chouser: kwladyka_: depending on the other operations you intend to do, a persistent queue might work well

14:41 kwladyka_: chouser, can you give me an example?

14:43 chouser: a persistent queue is fast for conj'ing on one end and peek/pop'ing from the other, so you could efficiently take an item (4) from one end and put it back on the other end.

14:44 if you do that a lot, or on a large collection, it might be more efficient than a vector or list which has to be rebuilt every time you do that "rotate" operation you asked about

14:44 on the other hand, it may then be hard to access the full contents of the collection in the order you want for whatever else you're doing with it.

14:45 kwladyka_: chouser, are you talking about http://clojuredocs.org/clojure.core/persistent! ?

14:45 chouser: nope.

14:46 ,(-> clojure.lang.PersistentQueue/EMPTY (into [1 2 3 4]))

14:46 clojurebot: #object[clojure.lang.PersistentQueue 0x22125a58 "clojure.lang.PersistentQueue@e93c3"]

14:47 kwladyka: oh... thx

14:47 chouser: ,(let [q (into clojure.lang.PersistentQueue/EMPTY [1 2 3 4])] (-> q (conj (peek q)) pop seq))

14:47 clojurebot: (2 3 4 1)

14:48 gfredericks`: conj-peek-pop-seq would be a good name for *something*

14:48 kwladyka: generally i need do from (1 2 3 4 2 3 53 23 932 2) all possible configurations

14:48 chouser: ,(let [q (into clojure.lang.PersistentQueue/EMPTY (reverse [1 2 3 4]))] (-> q (conj (peek q)) pop reverse))

14:48 clojurebot: (4 1 2 3)

14:48 kwladyka: *all possible unique configurations

14:49 chouser: so, those 'reverse' operations are relatively expensive, but if you can do the things you need to in-between them, or figure out how to never need them, you'd be winning.

14:50 amalloy: "all possible configurations?"

14:50 you are looking for the function named permutations, or what?

14:51 kwladyka: amalloy, i have chess pieces and i have to try them in all possible unique configurations from first to the last one

14:51 amalloy: what is a unique configuration?

14:52 this is getting back to TimMc's answer

14:52 kwladyka: so (:king :king :queen) (:king :queen :king) (:queen :king :king:) <- this is easy one.

14:52 gfredericks`: sounds like permutations

14:52 kwladyka: as you can see :king is 2 times there

14:53 but i am not doing (:king :queen :king) twice because it doesn't make sense

14:53 gfredericks`, but there is no function like permutation in Clojure as i seee

14:55 hmm but maybe http://clojure.github.io/math.combinatorics/#clojure.math.combinatorics/permutations

14:56 gfredericks`: ,(defn unique-permutations [xs] (let [m (frequencies xs)] ((fn self [m] (if (empty? m) [[]] (mapcat (fn [[x n]] (map #(cons x %) (self (if (= 1 n) (dissoc m x) (update m x dec))))) m))))))

14:56 clojurebot: #'sandbox/unique-permutations

14:56 gfredericks`: ,(unique-permutations [:king :king :queen])

14:56 clojurebot: #error {\n :cause "Unable to resolve symbol: unique-permutations in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: unique-permutations in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "Unable to r...

14:56 gfredericks`: what

14:56 ,sandbox/unique-permutations

14:56 clojurebot: #error {\n :cause "No such var: sandbox/unique-permutations"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: No such var: sandbox/unique-permutations, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "No such var: sandbox/unique-permutations"\n :at [cl...

14:56 gfredericks`: ,(defn unique-permutations [xs] (let [m (frequencies xs)] ((fn self [m] (if (empty? m) [[]] (mapcat (fn [[x n]] (map #(cons x %) (self (if (= 1 n) (dissoc m x) (update m x dec))))) m))))))

14:56 clojurebot: #'sandbox/unique-permutations

14:56 gfredericks`: ,(unique-permutations [:king :king :queen])

14:56 clojurebot: #error {\n :cause "Wrong number of args (0) passed to: sandbox/unique-permutations/self--71"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (0) passed to: sandbox/unique-permutations/self--71"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 28]\n [sandbox$unique_...

14:57 kwladyka: gfredericks`, i guess clojurebot doesn't remember function from query before

14:57 gfredericks`: ,(defn unique-permutations [xs] (let [m (frequencies xs)] ((fn self [m] (if (empty? m) [[]] (mapcat (fn [[x n]] (map #(cons x %) (self (if (= 1 n) (dissoc m x) (update m x dec))))) m))) m)))

14:57 clojurebot: #'sandbox/unique-permutations

14:57 gfredericks`: ,(unique-permutations [:king :king :queen])

14:57 clojurebot: ((:king :king :queen) (:king :queen :king) (:queen :king :king))

14:57 gfredericks`: hey yay

14:57 only two tries

14:57 ,(unique-permutations [:king :rook :queen])

14:57 clojurebot: ((:king :rook :queen) (:king :queen :rook) (:rook :king :queen) (:rook :queen :king) (:queen :king :rook) ...)

14:57 gfredericks`: ,(unique-permutations [:king :king])

14:57 clojurebot: ((:king :king))

14:58 amalloy: that's a cute way to handle duplicates, gfredericks`

14:58 gfredericks`: amalloy: thanks!

14:58 kwladyka: gfredericks`, respect

14:58 gfredericks`: I like to think of frequencies as returning a multiset

15:07 TimMc: clojurebot: I like to think |of| frequencies

15:07 clojurebot: 'Sea, mhuise.

15:09 snowell: Just when I think I understand these bots...

15:11 rhg135: Heh

15:14 kwladyka: damn... i killed intellij using permutation in REPL

15:18 gfredericks`: hey snapchat I just successfully ported the immutable RNG to cljs

15:18 it gives identical results

15:19 dnolen: gfredericks`: cool did you end up using goog.math.Long for this?

15:19 gfredericks`: dnolen: oh absolutely

15:19 dnolen: gfredericks`: cool!

15:19 gfredericks`: dnolen: I had to write bit-count myself but everything else was there

15:19 dnolen: gfredericks`: excellent

15:19 gfredericks`: dnolen: next comes the part where I find out it's unsalvageably slow

15:20 dnolen: gfredericks`: haha, I suspect it will be OK, I think test.check would dominate not goog.math.Long ops

15:20 gfredericks`: I hope so

15:20 dnolen: gfredericks`: last I checked it as something like 4X perf hit over regular arithmetic

15:21 and the biggest time sink in test.check is GC

15:21 kwladyka: oh god... it produce so many results from so small collection

15:21 gfredericks`: dnolen: makes me want to rewrite the generators with transducers

15:21 kwladyka: the maybe good news is that it's lazy

15:21 dnolen: gfredericks`: def

15:22 justin_smith: ,(defn get-name [] (->> 'clojure.core ns-publics keys shuffle (take 3) (clojure.string/join \-) symbol))

15:22 clojurebot: #'sandbox/get-name

15:22 justin_smith: ,(repeatedly get-name) ; gfredericks`

15:22 clojurebot: (spit-nnext-*command-line-args* char?-subs-dissoc! comment-completing-read-string apply-keys-int print-method-case-drop ...)

15:23 gfredericks`: (inc justin_smith)

15:23 lazybot: ⇒ 279

15:23 kwladyka: gfredericks`, yes but i am scare of time needed to run whole algorithm from start to the end

15:24 gfredericks`: kwladyka: yeah combinatorial stuff can be tricky that way

15:24 kwladyka: which each permutation i need check all possible configuration on chess

15:24 *with

15:25 gfredericks`: kwladyka: is it a permutation of 8 pieces?

15:25 kwladyka: hmm but as i see 99% of time it was time to show me text on screen not counting

15:25 gfredericks`: ,(defn unique-permutations [xs] (let [m (frequencies xs)] ((fn self [m] (if (empty? m) [[]] (mapcat (fn [[x n]] (map #(cons x %) (self (if (= 1 n) (dissoc m x) (update m x dec))))) m))) m)))

15:25 clojurebot: #'sandbox/unique-permutations

15:25 gfredericks`: ,(count (unique-permutations '(R N B K Q B N R)))

15:25 clojurebot: 5040

15:25 kwladyka: gfredericks`, no... as many as user want on board size as user want

15:25 justin_smith: ,defn get-name [] (->> 'clojure.core ns-publics keys (mapcat (fn [s] (clojure.string/split (name s) #"-"))) shuffle (take 3) (clojure.string/join \-) symbol))

15:25 clojurebot: #error {\n :cause "Can't take value of a macro: #'clojure.core/defn"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/defn, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "Can't take value of a macro: #'clojur...

15:25 justin_smith: ,(defn get-name [] (->> 'clojure.core ns-publics keys (mapcat (fn [s] (clojure.string/split (name s) #"-"))) shuffle (take 3) (clojure.string/join \-) symbol))

15:25 clojurebot: #'sandbox/get-name

15:26 justin_smith: ,(repeatedly get-name)

15:26 clojurebot: (update-count-seq *1-min-ctor condp-with-*print byte-chars-history boolean-vector-vary ...)

15:26 kwladyka: anyway... i have to finish algorithm and we will see how long it will take

15:26 there is no other way :)

15:34 TimMc: (inc justin_smith)

15:34 lazybot: ⇒ 280

15:35 TimMc: ,(meta #'completing)

15:35 clojurebot: {:arglists ([f] [f cf]), :doc "Takes a reducing function f of 2 args and returns a fn suitable for\n transduce by adding an arity-1 signature that calls cf (default -\n identity) on the result argument.", :added "1.7", :line 6560, :column 1, ...}

15:35 gfredericks`: heck yeah it generates identical doubles as well

15:35 TimMc: that's great!

16:39 riogr: In my program, I have the state in a variable I call `current-buffer`. It has an atom, that is swap!-ed and reset!-ed at certain times. Should you in clojure *earmuff* such variables? They never change (always point to the atom) but the value from deref-ing the atom _is_ changing. To *earmuff* or not to earmuff?

16:42 justin_smith: riogr: in clojure earmuffs are for dynamic bindings, not atoms

16:43 riogr: I see. Thank you justin_smith for clearing it up! Back to the hacking...

16:43 justin_smith: riogr: there's even a message about it

16:43 ,(def *foo* (atom nil))

16:43 clojurebot: #error {\n :cause "denied"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6740]}\n {:type java.lang.SecurityException\n :message "denied"\n :at [clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]}]\n :trace\n [[clojureb...

16:43 riogr: justin_smith: saw that, but didn't really understand..

16:43 justin_smith: err... that's not the usual message

16:44 riogr: OK. there's a good section on dynamic bindings on clojure.org where vars are documented

17:12 DocSolver: Hi all! I'm trying to teach myself clojure with a book and the REPL and I have two questions:

17:13 My first question: when I start a REPL outside a project I get an outdated Clojure version (1.6.0), even though I made a project.clj in the ~/.lein folder with a dependency on 1.7.0. Am I doing something wrong?

17:14 ('m on MacOSX)

17:17 justin_smith: DocSolver: lein doesn't use a project.clj from .lein

17:18 DocSolver: you'll need to wait for a newer lein version before non-project repls use the brand new clojure version (it's only been official for a few weeks at most)

17:18 DocSolver: ok, then I must have misread that somewhere.

17:18 thank you for the clarification!

17:18 justin_smith: np

17:19 DocSolver: in practice it's not so hard to just use projects

17:19 since they are so easy to generate

17:19 DocSolver: k, will do

17:20 also, another thing I was wondering is about the syntax: it is mostly quite clear but I am confused by the cases where a keyword has a specific meaning. For example the :keys speical keyword to destructure a hashmap. Why is this a keyword and not a function?

17:20 justin_smith: I have a "just experimenting" project that pulls in clojure 1.7 plus some of my favorite libs like core.async (which I use often, but not ubiquitously to put in my profiles.clj)

17:20 DocSolver: because that keyword is handled specially by that reader - you can think of it like command line args on a *nix system

17:21 DocSolver: the function is clojure.core/destructure

17:21 and it uses things like :keys and :as to guide its execution

17:21 DocSolver: does that mean that these keywords are reserved? Or only in that specific context?

17:21 justin_smith: there's a macro that grabs that binding vector, then feeds it to destructure, then uses the result

17:22 no, they are not reserved, they just have a special meaning in that context, similar to command line switches

17:22 DocSolver: really it's not much different than how a vector is used by defn / fn

17:23 it's not that the vector is special, it's that fn / defn treat a vector in that position in a special manner

17:23 DocSolver: but it does matter that the keyword is named :keys right?

17:23 justin_smith: DocSolver: sure, other keywords mean other things in that context

17:23 DocSolver: like :strs

17:24 DocSolver: I haven't stumbled upon that one in the book I'm reading yet... but I will keep it in mind

17:24 Thanks for the clarifications Justin, really appreciate!

17:24 justin_smith: DocSolver: yeah, :strs is practically secret, it gets used so rarely :)

17:24 np

17:25 ,(let [{:strs [a]} {"a" 41}] (inc a))

17:25 clojurebot: 42

17:27 DocSolver: justin_smith: so what is the added value of using :strs ?

17:27 justin_smith: DocSolver: same as for keys, avoids repetition when destructuring

17:28 DocSolver: often a hash-map coming from a database or an http API will come back with strings as keys rather than keywords

17:29 what most people do is do a tree-walk converting the strings to keywords (or at least walking and converting the top level, or converting while parsing with a json parser). Really you can just use the strings.

17:30 DocSolver: You managed to confuse me a bit with the :str :-) I don't really see the difference with :keys. I assume it's not an alias?

17:30 justin_smith: DocSolver: :keys works with keywords, :strs works with strings

17:31 these are different datatypes, they are not equivalent when used as hash-map keys

17:31 ,(get {"a" 0} :a)

17:31 clojurebot: nil

17:31 justin_smith: ,(get {"a" 0} "a")

17:31 clojurebot: 0

17:31 DocSolver: The example about :keys in the book I'm reading is:

17:31 ,(let [{:keys [flower1 flower2]} {:flower1 "red" :flower2 "blue"}] (str "The flowers are " flower1 " and " flower2))

17:31 clojurebot: "The flowers are red and blue"

17:32 DocSolver: It obviously doesnt work if I replace :keys with :strs but your example seems really similar

17:32 justin_smith: DocSolver: I bet you could translate that to use :strs, by changing the keys in the map

17:32 DocSolver: Is it because you're extracting only one key?

17:32 justin_smith: DocSolver: it is because :a is not equal to "a"

17:32 they are different data types

17:32 DocSolver: Aaaah, now I see: your key is a string

17:32 justin_smith: :a is not a special syntax for map keys, it is a type of data

17:33 DocSolver: Okay, it's good that you point that out because I practically only see :keys being used as... erm... keys in objects

17:33 justin_smith: DocSolver: objects != hash-maps

17:33 hash-maps are one class of objects

17:34 but we have Objects via the jvm too, entirely different beast usually...

17:34 DocSolver: but stick to hash-maps now, and use them as you would usually use objects, and you can sort out the rest when you are more experienced

17:35 DocSolver: Okay; I did mean hash maps but I'm still too much in Javascript lingo...

17:36 Actually the :keywords system in Clojure kind of reminds me of symbols in the new Ecmascript 6 which are provided as a means to avoid collisions that might occur with string keys. Or is this not a good comparison?

17:36 justin_smith: DocSolver: heh, if you ever use cljs, you can use js Objects and cljs hash-maps (which are a kind of js object...)

17:36 DocSolver: well, keywords can be namespaced, and we use the namespacing to avoid collisions

17:37 DocSolver: but what is the added value of keywords, as opposed to using strings instead?

17:37 justin_smith: but we also use keywords in literal source code because it helps differentiate a string used as a data type representing human readable text, as opposed to keys in a map or other usage of tokens

17:37 also keywords can be called like functions, they look up a value in a hash-map

17:38 ,(:foo {:foo 0})

17:38 clojurebot: 0

17:39 DocSolver: okay, that's clear.

17:40 So it's actually other languages which use strings for both purposes and clojure separates these uses by creating a separate data type...

17:41 justin_smith: DocSolver: right. I saw a comical version of this the other day from a haskell user on twitter: "should the type be string? I dunno, would the complete works of shakespeare translated to mandarin be a valid value?"

17:42 DocSolver: :two_households_both_alike_in_dignity_In_fair_Verona_... no that doesn't feel right :-)

17:42 justin_smith: haha

17:43 DocSolver: actually, the fact that a leyword can't contain spaces is a clear indicator of what you wrotr

17:43 justin_smith: DocSolver: right. Well a literal can't. As you learn more clojure you find out all kinds of evil terrible bad things you shouldn't do that are actually quite easy.

17:44 DocSolver: I don't wanna know :-)

17:45 Alright Justin, you helped me a lot. Now I'm returning to the book and the REPL :-) This was a nice first experience with the Clojure community!

17:45 justin_smith: ,(keyword "OK I won't tell you how.")

17:45 clojurebot: :OK I won't tell you how.

17:46 justin_smith: DocSolver: awesome, thanks

17:47 DocSolver: ,(keyword "Two households, both alike in dignity, In fair Verona, where we lay our scene, From ancient grudge break to new mutiny, Where civil blood makes civil hands unclean. From forth the fatal loins of these two foes A pair of star-cross'd lovers take their life; Whose misadventured piteous overthrows Do with their death bury their parents' strife. The fearful passage of their death-mark'd love, And the continuance of their p

17:47 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading string>

17:47 DocSolver: even romeo and julia doesnt fit...

17:48 justin_smith: it's an irc limitation, lol

18:05 sdegutis: Help.

18:06 This works from `lein run`, but not from inside a jar: (->> (resource "public/assets") (file) (file-seq))

18:06 It complains with an illegal argument exception saying "not a file".

18:07 So in Clojure, whether in a .jar or not, how do you get a list of files in a directory within your ./resources/ dir?

18:10 justin_smith: sdegutis: things inside jars are not files

18:10 sdegutis: if you want to access things inside jars, don't use file, use resource

18:10 sdegutis: jars do not contain directories

18:11 sdegutis: Okay.

18:11 So then, in Clojure, whether in a .jar or not, how do you get a list of "files" in a "directory" within your ./resources/ dir?

18:13 justin_smith: well, "resources" itself won't be in the jar

18:14 Cr8: there's not really a good way to do it it -- (resource) will pull a file out of any jar on the classpath

18:14 justin_smith: best you can do is list things under some relative path on the classpath

18:14 Cr8: so you have to use the ZIP apis to check every jar on the classpath

18:14 justin_smith: answer to that, I am working on

18:14 hiredman: there is a large assumption there

18:14 that things can only come out of jars on the classpath

18:15 Cr8: also dirs on classpath

18:15 hiredman: resource, and resources actually load things from classloaders

18:15 which can, for example, magic up stuff out of no where, or load things from random urls, etc

18:15 Cr8: yeah, could have a magic classloader that you can't actually ask for a list

18:15 like some http server you dont control -- you cant necessarily get a listing

18:17 amalloy: justin_smith, Bronsa: in case anyone is interested i wrote up a version of destructure that isn't just one giant function, and uses first/next on vectors instead of nth: https://www.refheap.com/de3767810a33dd855f0bc803e

18:17 sdegutis: Thanks. I'll do this outside Closure.

18:17 justin_smith: amalloy: cool

18:17 sdegutis: Appreciated much.

18:18 amalloy: doesn't have all the error handling but i think it has all the features

18:44 justin_smith: just found an apt quote from a 20th century music composer: "now that things are simple, there's so much to do"

18:44 (Morton Feldman)

21:47 slaterr: map returns a lazy sequence. what does a lazy sequence mean exactly? is it like iterators in C++? or sequence in python

21:49 amalloy: it is a thing you can get an iterator on. but it stays valid when you do, and future calls cache the already-computed values. it's not like an iterator that gets mutated as you request elements from it and can only use once

21:49 slaterr: yeah I see

21:50 what if I only iterate it once? how much memory will it use

21:52 celwell: Hello, does anything like this already exist? (defmacro unless [pred x y] `(if (not (~pred ~x)) ~x ~y))

21:52 Ex. usage: (unless Double/isNaN (Double. "0.75") 0)

21:52 Or, is there a better pattern?

21:53 amalloy: celwell: why would that be better than using when-not?

21:53 oh, you're not returning nil, but rather y

21:54 celwell: Yeah, it's an if but i don't want to rewrite 'x'

21:55 My name unless is kind of misnomer

21:56 amalloy: i don't think there's anything very good built-in. with flatland/useful you could write (-> x (fix pred y))

21:56 slaterr: or, to repharse, if I iterate through a lazy sequence with a million elements only once will they all be stored in memory or will it just use memory required to store a single element?

21:56 amalloy: slaterr: i mean the GC is nondeterministic so it could run whenever, but when the GC *does* run, only one element wll be kept

21:58 celwell: amalloy: huh... seems like it would be a common pattern for data validation w/ defaults

21:58 slaterr: i thought maybe clojure compiler is smart enough to notice that it does not need to cache all those results, since they are not used again

21:59 amalloy: actually maybe cond-> does that now. i don't remember how that works

21:59 ,(doc cond->)

21:59 clojurebot: "([expr & clauses]); Takes an expression and a set of test/form pairs. Threads expr (via ->) through each form for which the corresponding test expression is true. Note that, unlike cond branching, cond-> threading does not short circuit after the first true test expression."

21:59 amalloy: ,(cond-> 2 even? inc)

21:59 clojurebot: 3

21:59 amalloy: ,(cond-> 2 odd? inc)

21:59 clojurebot: 3

22:00 amalloy: right, thought so. it wants a bool, not a predicate, so it doesn't help you avoid repeating x

22:03 celwell: Thanks a cool function though, might be useful for other things. Thanks

22:39 namra: hm is there no way to ask leiningen for verbose output

22:39 cause it's kinda frustrating when compilling something and it just hangs somewhere

22:39 without ever finishing

22:46 justin_smith: namra: that's caused by top level side effects

22:47 namra: all your namespaces get run at the top level when compiling, the only way to make it not hang is to have no side effects at the top level of the file

22:47 anything that "does anything" should be in functions called by your -main

22:48 namra: you can use jstack (it's a command line tool that comes with the jdk) to see where the clojure process is hanging

22:49 namra: justin_smith: thanks

22:50 currently i solved it by removing :aot :all from the uberjar profile

22:50 but like to know why it doesn't work on the new dev machine cause on the old one the compiliation works

22:50 justin_smith: oh, that's interesting

22:51 in my experience a hanging compile is almost always some small thing I didn't notice, like launching a core.async go block in a def

22:52 (which means the core.async threads spin up, which means the compiling vm does not exit)

22:55 namra: justin_smith: thanks that was the issue

22:55 justin_smith: core.async?

22:55 clojurebot: core.async is 100% imperative

22:57 namra: had code that connected to a server outside of main

22:57 justin_smith: ahh

23:27 namra: ah how i'd like to do more with clojure :/

23:28 blkcat: i'm dreadfully tempted to use om for an upcoming work project

23:28 namra: om?

23:29 justin_smith: namra: clojurescript library that uses react.js (but actually performs better thanks to immutable data structures last I heard)

23:29 namra: from the brilliant dnolen

23:29 ~om

23:29 clojurebot: Titim gan éirí ort.

23:29 namra: ah thanks

23:30 blkcat: it looks absolutely brilliant

23:30 TEttinger: clojurebot: om is a clojurescript library that uses react.js . Om is so hot right now!

23:30 clojurebot: Ik begrijp

23:31 justin_smith: TEttinger: I improved my clojure.core name generator

23:31 TEttinger: oh?

23:33 justin_smith: TEttinger: digging it up

23:33 ,(defn get-name [] (->> 'clojure.core ns-publics keys (mapcat (fn [s] (clojure.string/split (name s) #"-"))) shuffle (take (inc (rand-int 3))) (clojure.string/join \-) symbol))

23:33 clojurebot: #'sandbox/get-name

23:34 justin_smith: (repeatedly get-name)

23:34 ,(repeatedly get-name)

23:34 clojurebot: (re send-dorun object-with-drop defmulti-keep-aset >Vec-key-dec' ...)

23:34 justin_smith: ,(repeatedly get-name)

23:34 clojurebot: (sig-make class?-run! read->>-memfn var?--inc filter ...)

23:34 justin_smith: oh wait

23:34 amalloy: read->>-memfn

23:34 solid name

23:34 var?--inc

23:34 justin_smith: ,(defn get-name [] (->> 'clojure.core ns-publics keys (mapcat (fn [s] (clojure.string/split (name s) #"-"))) shuffle (take (+ 2 (rand-int 3))) (clojure.string/join \-) symbol))

23:34 clojurebot: #'sandbox/get-name

23:34 justin_smith: ,(repeatedly get-name)

23:34 clojurebot: (identity-at-defprotocol biginteger-remove eval-min macroexpand-class-coll-complement map?-unreduced-int ...)

23:35 justin_smith: amalloy: one I just got in my repl here - >Vec-vec->>

23:35 ,(repeatedly get-name)

23:35 clojurebot: (pop-ref-next-repeat >=-ctor find-bit-find-method set->-matcher-array proxy-reader ...)

23:36 amalloy: computer-generated babble is always strangely compelling

23:37 justin_smith: for me I think it's cathartic because I have spent so much time cramming things made of those tokens into my brain already

23:38 ,(repeatedly get-name)

23:38 clojurebot: (error-transient list-set-unsigned-errors deref-groups not-biginteger subtract-re-int-underive ...)

23:39 amalloy: not-biginteger. a useful function indeed

23:39 justin_smith: indeed, should be a predicate, of course

23:40 ,(repeatedly get-name)

23:40 clojurebot: (unchecked-in-set-send type-min-in fn*-filterv string-create->map-not satisfies?-shift-aset-with ...)

23:41 tmtwd: is there something like hiccup for css?

23:42 justin_smith: tmtwd: garden

23:42 tmtwd: justin_smith, is it often used by clojure developers?

23:42 justin_smith: tmtwd: the only reason I haven't used it is designers would rather just use regular css, or maybe sass/less

23:43 amalloy: that's true of hiccup too

23:44 justin_smith: amalloy: yeah, we have an unusual division of labor now, which lets us use reagent stuff which is basically hiccup syntax, but before we had to use a more conventional templating engine

Logging service provided by n01se.net