#clojure log - Mar 08 2015

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

14:09 noncom|2: does clojure support multilevel destructuring?

14:10 like (defn f [x {:keys [m {:keys [n] :as A}] :as B} ) ?

14:10 justin_smith: ,(let [[[[a]]] [[[42 43 44]]]] a)

14:10 clojurebot: 42

14:10 noncom|2: hmmm

14:10 justin_smith: nested :keys isn't going to work like that

14:10 noncom|2: that's what..

14:11 sad..

14:11 justin_smith: ,(let [{{n :n} :m} {:m {:n 42}}] n)

14:11 clojurebot: 42

14:11 justin_smith: you just can't use :keys that way

14:12 the destructuring still works nested

14:12 :keys tells the destructuring that everything in the vector is a keyword

14:12 putting a map inside makes no sense

14:13 noncom|2: yes, i know what you mean

14:13 justin_smith: ,(let [{{:keys [n]} :m} {:m {:n 42}}] n)

14:14 clojurebot: 42

14:14 justin_smith: a compromise

14:16 noncom|2: heh :)

14:16 justin_smith: to me, :keys isn't even worth it until you have more than two items from the same map

14:26 turtl3: ’allo all

14:26 gfredericks: hellooo

14:26 turtl3: newb to core.typed & confused

14:26 justin_smith: ,(rest "hello")

14:26 clojurebot: (\e \l \l \o)

14:26 gfredericks: justin_smith: I kind of like it just for calling out the key & the name being the same

14:27 ~newb to confused |would be| not the worst band name

14:27 clojurebot: Ack. Ack.

14:27 turtl3: Can’t get typed to grok expressions using partition with strings, e.g. (partition 2 (String. "ABCD"))

14:27 gfredericks: hah

14:27 gfredericks: turtl3: you want it to infer a seq of seqs of chars?

14:28 turtl3: gfredericks: yep, can’t seem to make “String” fit “(t/Coll a)”

14:28 gfredericks: yeah it's not really a collection

14:29 does partition require a t/Coll?

14:29 does (partition 2 (seq (String. "ABCD"))) typecheck the way you want?

14:29 turtl3: indeed. Domains:

14:29 java.lang.Number (t/Coll a)

14:29 Arguments:

14:29 (t/Val 2) String

14:29 justin_smith: turtl3: why (String. "ABCD") instead of "ABCD" ?

14:30 turtl3: justin_smith: doesn’t matter much in this case, t/Val vs String. String is closer to my “real” code

14:30 justin_smith: I guess what I don't get here is that (partition 2 "ABCD") is exactly the same as (parititon 2 (seq (String. "ABCD")))

14:30 and I don't understand when you would want the latter

14:31 gfredericks: because type systems

14:31 justin_smith: OK.

14:31 gfredericks: static type checkers, more precisely

14:32 the more precise cause of this exact thing is that partition is not accurately typed

14:32 turtl3: of couse seq was the first tool i pulled out, but ASeq != Coll

14:32 gfredericks: which may be due to laziness or maybe some limitation of the type system I don't know about

14:32 noncom|2: how do i change space between lines in lighttable?

14:32 gfredericks: I expect Seqable is closer than t/Coll

14:32 noncom|2: does anyone use lighttable for real dev?

14:33 turtl3: gfredericks: and i thought it was just me

14:33 gfredericks: or whatever is core.typed's terminology for things that clojure.core/seq accepts

14:34 turtl3: gfredericks: actually i suspect it is String weirdness

14:34 https://github.com/clojure/core.typed/wiki/Strings

14:35 some discussion there i don’t understand about Strings not be Seqable

14:35 gfredericks: Seqable is an interface

14:35 ,'clojure.lang.Seqable

14:35 clojurebot: clojure.lang.Seqable

14:35 gfredericks: anything that implements it can be converted to a seq

14:36 justin_smith: gfredericks: that was a keyword, not an interface

14:36 ,clojure.lang.Seqable

14:36 clojurebot: clojure.lang.Seqable

14:36 gfredericks: hey I do what I want

14:36 justin_smith: err, symbol I mean

14:36 heh

14:36 gfredericks: anyhow there are a few hard-coded extra things that can be converted to seqs as well, all of them native JVM types

14:36 and on the JVM you can't take a builtin or 3rd-party type and have it implement your interface

14:36 which is the reason they are hard-coded extras

14:37 strings, arrays, other generic jvm collections

14:37 ,(seq "foo")

14:37 clojurebot: (\f \o \o)

14:37 gfredericks: it's talking about the reason ^that works

14:39 turtl3: gfredericks: the result of a "(seq x)" on such a thing seems not to be compatible t/Coll. but making a copy with e.g. vec sidesteps the problem, but that seems so wrong

14:40 gfredericks: you could write a ^:no-check helper function :/

14:40 (t/ann string-seq [String -> (t/Seq Char)]) (defn ^:no-check string-seq [s] (seq s))

14:40 ;; or whatever

14:40 * turtl3 cries

14:40 gfredericks: this is my experience with core.typed

14:41 most of the times I try to do something with it it ends with ambrose asking me to file a bug

14:41 turtl3: i guess that’s what they mean when they say it’s not ready for prime time

14:41 gfredericks: well I mean the thing you're describing isn't going to prevent you from doing something

14:41 it just feels gross

14:41 but sometimes having the type checker around to give you a thumbs up is worth feeling gross about a few bits

14:42 turtl3: gfredericks: perhaps. i may have chosen an unfortunate place to start

14:42 gfredericks: there's generally a tension between core.typed and common clojure style

14:43 which might be unavoidable

14:43 justin_smith: ,(map #(.charAt "hello" %) (range (count "hello")))

14:43 clojurebot: (\h \e \l \l \o)

14:44 gfredericks: Core Dot Typed: You Are Going To Have To Write Your Code A Bit Different And Some Things Won't Be Checkable At All™

14:44 justin_smith: dunno if that is actually helpful

14:44 turtl3: justin_smith: thanks, another way of building a copy

14:45 justin_smith: right

14:45 does the seq version not build a copy?

14:45 AeroNotix: https://gist.github.com/AeroNotix/1d71a81b03e08e8c5f0e the WebSocketClient constructor here is being called with an array, right? Or am I just misunderstanding the error?

14:46 gfredericks: justin_smith: nothing that partition doesn't already do

14:46 justin_smith: gotcha

14:47 AeroNotix: oh wait, I was returning the wrong type in a ctor.

14:47 gfredericks: turtl3: I would often find myself writing copies of certain functions with more specific types

14:47 so e.g. another option is to write your own partition

14:50 turtl3: gfredericks: i don’t think i’m that hellbent on type checking today. this started out with a colleague asking for some documentation on the types a few functions were written for. i figured, what the heck, i might as well document it in a way that a compiler can understand

14:50 gfredericks: ACK

14:50 justin_smith: turtl3: if it's mostly about argument / return value types I find prismatic/schema to be a nice option

14:51 it's got a different rationale, but it also allows type annotations (instead of verifying at compile time, it is optionally tested on runtime input)

14:53 turtl3: justin_smith: that’s interesting, i’ll take a look

14:58 AeroNotix: lipstick on a pig

16:50 fortruce: Why doesn't ring-json wrap-json-response set the content-type to application/json?

16:57 godd2: How do I force an infinite loop to break in lein repl?

16:57 Ctrl-C doesn't work

17:10 AeroNotix: godd2: C-b usually works for me

17:13 godd2: I tried C-b and C-c C-c and C-c C-b, none of them

18:18 lodin: gfredericks, justin_smith: Thanks. How do I adapt the code to make unchecked-multiply use * and not multiply?

18:22 gfredericks: lodin: what does your code look like?

18:22 ,(unchecked-multiply (identity 25214902975) 0x5DEECE66D)

18:22 clojurebot: #<ArithmeticException java.lang.ArithmeticException: integer overflow>

18:22 gfredericks: ,(unchecked-multiply ^long (identity 25214902975) 0x5DEECE66D)

18:22 clojurebot: 8602057284977698131

18:23 gfredericks: ^ that I guess

18:27 godd2: ,(*' 25214902975 0x5DEECE66D) ;; do you want the result of the overflow or the mathematically correct answer?

18:27 clojurebot: 635791355791102453075N

18:27 lodin: Excellent.

18:27 godd2: Overflow.

18:28 (inc gfredericks)

18:28 lazybot: ⇒ 120

18:29 gfredericks: ,(* 2 2 2 3 5)

18:29 clojurebot: 120

18:29 justin_smith: ,(bit-and Long/MAX_VALUE (*' 25214902975 0x5DEECE66D))

18:29 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: bit operation not supported for: class clojure.lang.BigInt>

18:29 godd2: it's a pretty nice number

18:29 justin_smith: :P

18:31 lodin: ,(apply * (range 1 (inc 5)))

18:31 clojurebot: 120

18:32 gfredericks: nice

18:32 hyPiRion: ,(bit-and Long/MAX_VALUE ('* 25214902975 0x5DEECE66D)) ;; totally fixed that for you, justin_smith

18:32 clojurebot: 25214903917

18:32 gfredericks: ,(->> 5 inc (range 1) (apply *))

18:32 clojurebot: 120

18:33 lodin: gfredericks: Which is better, a factorial or a square?

18:33 gfredericks: factorials are rarer

18:33 godd2: factorials are recursiver

18:33 lodin: gfredericks: Make sure you're not inc:ed then. :-)

18:33 gfredericks: oh hey a square is next isn't it

18:33 lodin: ,(* 11 11)

18:33 clojurebot: 121

18:36 godd2: ,(apply * (take 2 (repeat 11)))

18:36 clojurebot: 121

18:40 gfredericks: ,(* 2 61)

18:40 clojurebot: 122

18:44 brkpnt: hi, why this is not tail recursive? http://pastebin.com/VvhQemcc. If i use huge numbers a Stackoverflow happends.

18:45 justin_smith: brkpnt: there is no automatic tail recursion in Clojure, period

18:45 if you didn't call recur or trampoline, it's guranteed to not be a tail recursion

18:46 splunk: is there a protocol for "returns a map" like there's a protocol for "returns a seq"?

18:46 justin_smith: err, s/tail recursion/optimized tail recursion/ in both those places, obviously

18:46 spearofsolomon: hi everyone

18:47 gfredericks: it's going to be so awkward when the jvm gets TCO

18:47 justin_smith: gfredericks: heh

18:47 spearofsolomon: I have a question about maps. If I store a number in a map, when I pull it out and try to number things with it, clojure tells me that it can't cast a mapentry to a number

18:47 gfredericks: I guess java devs will be in the same position

18:47 justin_smith: spearofsolomon: use get instead of find

18:48 spearofsolomon: Ok

18:48 justin_smith: ,(find {:a 0} :a)

18:48 clojurebot: [:a 0]

18:48 justin_smith: ,(get {:a 0} :a)

18:48 clojurebot: 0

18:48 spearofsolomon: I couldn't quite understand from the documentation what the difference between get and find is

18:48 justin_smith: there is also val

18:48 spearofsolomon: except that get has an optional not-found

18:48 justin_smith: ,(val (find {:a 0} :a))

18:48 clojurebot: 0

18:49 justin_smith: spearofsolomon: get also works on sets and vectors (by identity or index, respectively)

18:52 nicferrier: I've found a slightly strange problem... if I try and read a particular structure with a key like :a1:b1 in it clojure barfs.

18:52 justin_smith: :a1:b1 is not valid

18:52 ,:a1:b1

18:52 clojurebot: :a1:b1

18:53 justin_smith: err...

18:53 wait...

18:53 gfredericks: I think hiccup has been using that for a while?

18:53 justin_smith: everything I know is wrong

18:53 gfredericks: or something

18:53 justin_smith: don't mind me

18:53 gfredericks: but I do think the official docs don't say you can do that

18:53 nicferrier: yesh. it is valid. but clojure barfs... but only in particular circumstances.

18:53 gfredericks: what are they?

18:53 nicferrier: hiccup is a bit of a pita

18:55 well I can't copy the exact sequence .... but some thing like [:a1 {:a2 "blah} [:a3 {:ac3:b2 "blah"} "str"] [:ac4 "blah"]]

18:55 and I note the elisp reader is struggling with that as well

18:55 gfredericks: and just typing that in your repl gives an exception?

18:55 nicferrier: yep.

18:55 gfredericks: ,[:a1 {:a2 "blah} [:a3 {:ac3:b2 "blah"} "str"] [:ac4 "blah"]]

18:55 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading string>

18:55 nicferrier: oh whoops.missed a quote

18:56 off the first blah

18:56 it's not that

18:56 gfredericks: ,[:a1 {:a2 "blah"} [:a3 {:ac3:b2 "blah"} "str"] [:ac4 "blah"]]

18:56 clojurebot: [:a1 {:a2 "blah"} [:a3 {:ac3:b2 "blah"} "str"] [:ac4 "blah"]]

18:56 nicferrier: that was just me retyping it

18:56 gfredericks: well if you can't show us one that fails then I'm not sure how else we'll be able to help

18:56 nicferrier: yes. as I say, it's something like that.

18:56 yes. :-(

18:56 gfredericks: how do you know it has to do with these keywords?

18:56 clojurebot: It's greek to me.

18:57 nicferrier: gfredericks: because I've got quite a simple form and I've normalized the kw and it's fine

18:57 justin_smith: nicferrier: what isthe specific exception you get?

18:57 nicferrier: and non-normalized it dies

18:57 I get an EOF

18:58 gfredericks: nicferrier: why can't you share the actual form?

18:58 nicferrier: gfredericks: it's locked inside a bank

18:59 I should really make a tool to make it easier to open a scratch session with clojure from inside emacs.

18:59 my workflow is too tied to lein atm

19:01 re-creating it is a struggle

19:01 justin_smith: java -jar path/to/clojure.jar

19:01 though adding other deps is a pain

19:01 nicferrier: yeah... but I want it in emacs. s'alright. I'll get it done.

19:02 all my clojure tools are locked inside the same stupid bank.

19:02 kwladyka: (#{\a} \a) <- what exatly is this doing? i don't understand this line

19:02 justin_smith: nicferrier: C-u m-x inferior-lisp<ret>java -jar path/to/clojure.jar

19:02 nicferrier: justin_smith: I KNOW :-)

19:02 justin_smith: kwladyka: it looks up \a in a set

19:03 kwladyka: justin_smith but how to know that? where can i some hints to discover that myself?

19:04 http://clojure.org/cheatsheet <- example i am there and i cant find hints to understand this line, what i miss?

19:04 gfredericks: there are some things that are hard to look up

19:04 like "what things are functions?"

19:05 justin_smith: kwladyka: gfredericks: there is a page in the official clojure docs about readable forms that includes sets, macros, anonymous function shorthand, etc.

19:05 kwladyka: i have big problem to undestand when use what :)

19:05 justin_smith: I am looking for it at the moment

19:06 amalloy: i think it's clojure.orc/reader

19:06 *org

19:06 gfredericks: those damn orcs got icann to give them a tld?

19:07 justin_smith: yup http://clojure.org/reader <- kwladyka that's your link

19:07 nicferrier: well. I can't recreate it. I guess it might be a windows thing.

19:07 justin_smith: gfredericks: it's for orchestras

19:07 (inc amalloy)

19:07 lazybot: ⇒ 234

19:08 justin_smith: right when I was about to find it, too :)

19:08 amalloy: if only i could sell licenses to amalloydb

19:08 justin_smith: haha

19:08 kwladyka: justin_smith thx\

19:08 uh i think its too late... its time to go sleep :)

19:09 goodnight all!

19:09 shafire: Hi, I am trying to call Clojure from JRuby

19:09 what is wrong with this code? https://gist.github.com/anonymous/42b8f165e22cf2910206

19:10 the .class file does not contain the "bar" function :(

19:10 justin_smith: shafire: no, it wouldn't. it would contain a -bar function

19:10 that would be a .bar method on the Foo0 class

19:10 nicferrier: if I have cr's in it, it won't be read

19:10 gfredericks: shafire: you might have more luck with clojure's dynamic interface class

19:11 I forget what it's called

19:11 clojure.lang.api.Clojure or something

19:11 amalloy: clojure.java.api.Clojure

19:11 shafire: justin_smith: there is no .bar methid on the Foo0 class

19:11 justin_smith: shafire: that's weird, the -bar definition should hve created one I thought

19:12 shafire: I am using clojure 1.6.0

19:12 amalloy: do you need to declare the methods you want to create in the :gen-class with :methods? i do'nt gen-class much

19:13 nicferrier: right - something like '([:a1 \n {:ac:b1 "hello"} \n [:anything]])

19:13 does not work. can someone do me a favour and confirm?

19:13 amalloy: ,'([:a1 \n {:ac:b1 "hello"} \n [:anything]])

19:13 clojurebot: ([:a1 \n {:ac:b1 "hello"} \n [:anything]])

19:13 nicferrier: of course the \n there are real cr's in the source

19:13 no, not the same thing.

19:14 justin_smith: ,(read-string "([:a1 \n {:ac:b1 "hello"} \n [:anything]])")

19:14 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: hello in this context, compiling:(NO_SOURCE_PATH:0:0)>

19:14 gfredericks: ,(read-string "([:a1 \r {:ac:b1 \"hello\"} \r [:anything]])")

19:14 clojurebot: ([:a1 {:ac:b1 "hello"} [:anything]])

19:14 justin_smith: oops

19:14 gfredericks: ,(read-string "([:a1 \n {:ac:b1 \"hello\"} \n [:anything]])")

19:14 clojurebot: ([:a1 {:ac:b1 "hello"} [:anything]])

19:14 nicferrier: ooo. good call. I'll try that

19:14 amalloy: i mean like, of course it works

19:15 have you checked the string you are copy-pasting for mysterious invisible unicode characters or something?

19:15 nicferrier: amalloy: I've retyped it.

19:15 shafire: is this for me?

19:16 nicferrier: amalloy: I've put it into a different computer with a different operating system.

19:16 gfredericks: shafire: is there any reason you can't use clojure.java.api.Clojure instead?

19:16 TEttinger: ,(defn boms? [s] (re-find #"\ufeff" s))

19:16 clojurebot: #'sandbox/boms?

19:16 TEttinger: ,(boms? "whee")

19:16 clojurebot: nil

19:16 TEttinger: ,(boms? "wh\ufeff\ouch")

19:16 clojurebot: #<RuntimeException java.lang.RuntimeException: Unsupported escape character: \o>

19:16 shafire: gfredericks: do you have an example, how to use clojure.java.api.Clojure?

19:16 TEttinger: ,(boms? "wh\ufeffouch")

19:16 clojurebot: ""

19:17 justin_smith: haha, I like how it returns a string with a bom in it

19:17 cheeky bom monkey

19:17 TEttinger: heh

19:17 gfredericks: shafire: http://clojure.github.io/clojure/javadoc/clojure/java/api/package-summary.html

19:17 TEttinger: but that string is non-nil and so would count for a condition check

19:17 justin_smith: that's true

19:19 TEttinger: I actually somehow had a BOM in one of my C# game's config files. of course the library I used wasn't meant to parse characters outside of ASCII, and was acting very strange

19:20 nicferrier: can someone try pasting it in to a clojure repl?

19:20 '([:a1

19:20 {:ac:b1 "hello"}

19:20 [:anything]])

19:20 not the one here... that's doing way too much conversion.

19:21 justin_smith: nicferrier: yeah, I get an eof in the middle of the form if I do it line by line like that

19:21 nicferrier: if I paste it in to lein repl just in a term, I get end of form after the }

19:21 yep. exactly what I get.

19:21 justin_smith: second line gives me an eof instead of a prompt for more input

19:21 nicferrier: yep.

19:21 gfredericks: waaaaaaht

19:21 nicferrier: so there's a bug in the repl.

19:22 justin_smith: nicferrier: maybe, or it could be the answer is :ac:b1 is not a supported keyword syntax

19:22 and in other cases it only works accidentally

19:22 nicferrier: well I don't think so.

19:22 ok.

19:22 I ought to change parser. hiccup is annoying.

19:22 justin_smith: but good chance we are looking at one of the two

19:23 nicferrier: but I couldn't find another parser that would deal with shitty html.

19:23 I've got confluence here that I'm trying to parse.

19:23 sigh.

19:23 justin_smith: I've typically used envlice

19:23 *enlive

19:24 nicferrier: ok. will try that tmrw then.

19:25 justin_smith: that's definitely a weird reader behavior though (I replicated it in a 1.6.0 repl)

19:25 nicferrier: yeah. am using 1.6 too.

19:25 take the cr out and all is well :-(

19:27 shafire: it works now with gen-class, it was the missing :methods, thanks to amalloy

19:27 thanks to gfredericks too

19:27 nicferrier: enlive looks more of a templating engine than a parser.

19:27 justin_smith: in my experience it parses well

19:29 nicferrier: I'm sure. if you can find the docs.

19:29 oh woe. everything is not perfect.

19:35 tagsoup no good either. meh. I am going to bed disappointed.

19:45 justin_smith: nicferrier: with enlive I use (-> text StringReader. enlive/html-resource)

19:45 though there might be something simpler

19:45 where enlive/ is net.cgrand.enlive-html/

19:48 nicferrier: cheers justin_smith. will try it.

19:49 justin_smith: and that's java.io.StringReader, natch

19:50 nicferrier: got a bad namespace with a bad namespace. not good. :-)

19:51 justin_smith: oh, yuck

19:51 sorry to hear

19:51 nicferrier: oh. no. clojure ns. not xml one :-)

19:51 must go to bed.

19:51 night.

20:26 enn`: Is it possible to see the watches that are set on an instance of a reference type?

20:26 gfredericks: probably

20:44 ,(clojure.repl/apropos "watch")

20:44 clojurebot: (clojure.core/add-watch clojure.core/remove-watch)

20:45 gfredericks: ,(.getWatches (atom 0))

20:45 clojurebot: {}

20:45 gfredericks: enn`: ^

20:46 it's pretty basic; each reference has a persistent map from keys to functions

20:46 see clojure/lang/ARef.java if you're interested

23:35 jack0: Hi, are there any mentors for gsoc here?

Logging service provided by n01se.net