#clojure log - Jun 07 2015

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

3:34 cfleming: So I'm surprised to discover that the inferred type of the initialiser isn't propagated to :tag with plain def

3:35 So (def x "Hello") (.length x) is a reflective call.

4:01 amalloy: cfleming: there was probably a time when :tag on vars was only for "function returning Foo", not actually "Foo"

4:02 cfleming: amalloy: Could be, yeah

4:02 amalloy: BTW you asked a while ago about the type-inference augmented completion

4:03 amalloy: i remember

4:03 cfleming: amalloy: By far the most useful change turns out to be that on completion of something that looks like a field or method, I walk the local variables in scope and add completions from their classes.

4:04 That gives you the completions you want 95% of the time

4:04 clojurebot: Huh?

4:04 amalloy: yeah, i bet

4:04 cfleming: I'm still going to add the order-swapping completion but I'm not sure it'll be as useful after this change

4:04 amalloy: but i imagine locals often aren't hinted well wnough to help?

4:05 cfleming: I'm not sure in general, mine are because I make sure I have no reflective calls

4:05 But I'm the only one using this right now

4:08 It does work very well for when you have chained calls, which is very common: https://twitter.com/CursiveClojure/status/606387674052575232

4:09 (i.e. I obey the inferred types, not just the tagged ones)

4:14 amalloy: sure, of course

4:34 H4ns: does anyone remember the relatively recent blog post that showed the dramatic effects that missing type hints can have on performance? i'm unable to find it.

4:35 also, can anyone recommend a intermediate level clojure book? i've tried two from packt only to get reminded that packt usually publishes crap.

5:06 cfleming: H4ns: Have you read Joy of Clojure?

5:06 H4ns: I'd recommend that if you haven't.

5:06 H4ns: cfleming: thanks, i'll grab that!

5:27 anti-freeze: Hi everyone. I'm having issues with multimethods. I want to create a multimethod with a default value, depending on the argument provided. For example (create :users {:username "someone"}), if a :users create is defined, it should call that. Now thats standard multimethod behaviour, though I want to be able to define a default method, so in the case that :users method isn't defined, create is called on the :users collec

5:27 tion. Any ideas?

5:29 TEttinger: cfleming was around recently, amalloy before that, and they're both pros. and now here's tbaldridge!

5:30 cfleming: Thanks for the vote of confidence TEttinger, but sadly I almost never use multimethods

5:30 TEttinger: same here

5:30 anti-freeze: Is there a better way to do this. Clojure noob here

5:31 ?*

5:32 TEttinger: anti-freeze, it's odd, multimethods are powerful but rarely written by many clojure users

5:32 I've never written one

5:33 anti-freeze: I feel like I'm taking a completely wrong approach. How do I handle default behaviour then?

5:33 TEttinger: I think there probably is a simple way, and it may involve multimethods

5:34 cfleming: anti-freeze: I actually seem to recall that multimethods allow you to use a :default dispatch

5:34 anti-freeze: Yeah, they do: http://clojure.org/multimethods

5:34 anti-freeze: cfleming: Yea, they do, but I don't think they allow you to get the type the method was dispatched with

5:36 cfleming: anti-freeze: Sorry, that's all I've got :-(

5:36 anti-freeze: cfleming: Should I send you the sauce, maybe you can tell me why I can't seem to be able to clean this code up

5:37 cfleming: anti-freeze: Ok, refheap it up. I don't have long, but I'll take a look

5:39 anti-freeze: cfleming: https://www.refheap.com/102234 This is how I'm using stuff currently. I have for example a (defn all-* [coll] (...)) method that I make in to a partial. Seems like a shitload of duplication for pretty standard operations

5:41 cfleming: So "projects" is the name of a data store in mongo?

5:41 Like a table or something?

5:41 And you're doing this so you don't have to call (create-* "projects" ....)

5:41 ?

5:42 anti-freeze: ^ ?

5:42 anti-freeze: cfleming: Pretty much

5:43 cfleming: Its the same for every collection at the moment. The exact same copy-pasta for the users collection.

5:44 cfleming: anti-freeze: yeah, I don't think that's gaining you much. I'd just rename all-*, create-* etc to just add and create, and then use (create :projects ...)

5:44 anti-freeze: The code reads the same, and you don't have that duplication

5:44 anti-freeze: cfleming: Yup... Alright, I just spent 2 days wasting my time. Thanks wunderhacker

5:46 cfleming: anti-freeze: Generally I'm a huge fan of keeping things as simple as possible. I almost never use partial, I'd rather have a little duplication and see what's going on.

5:46 anti-freeze: Functional programming sometimes seems like a race to ultimate conciseness, but I'm not a fan

5:47 TEttinger: I am a fan though

5:47 440 chars or less

5:47 anti-freeze: TEttinger: do you have any ideas on the matter?

5:48 Actually no, cfleming's argument is really valid

5:48 TEttinger: yes

5:48 I mostly make small laughably terse clojure snippets for IRC

5:48 ,(let[a #(apply str(flatten %))r repeatedly p partition N rand-nth n #(a(N(concat(repeat %"")(mapcat p[1 2 3]%&))))v #(n 0"aioeu""iaai")w(fn[](let[b(n 6"!.""""...")s[(n 0"STKNYPKLG""GlThShNyFt""ZvrCth")(r(N[1 2])#(do[(v)(n 9(map str"'-"(r 2 v)))(n 0(concat"lpstnkgx"[(N["h""gl""gr""nd"])(v)])"rlthggghtsltrkkhshng")]))]][b(if(seq b)[" "s][(n 3",")" "(.(a s)toLowerCase)])]))](re-find #"[A-Z].+"(a[(r 500 w)"."])))

5:48 clojurebot: "Thirle'ong! Pagh piagek! Kauia-ond ying. Tholtiagg nyirk yurl shoggu'ong! Kaipult fti'agh tughia'ekh. Pegh... Thakhes tux sil, pok! Shasaig pugh. Ftiao ge-aitsai'egg! Lagh, gekhorl, sek, tais... Cthaioep, tasix, kugia'ol, pai-ughits. Zvrelt goguth gikh shang... Piashul kiats, nu-ap guth ftupep cthiag ftangiagr kot kax nyia-akhung, kughilt tun! Kiath ftotix ftosh goltait. Kiltugr koltash, yundailt...

5:48 TEttinger: &(let[a #(apply str(flatten %))r repeatedly p partition N rand-nth n #(a(N(concat(repeat %"")(mapcat p[1 2 3]%&))))v #(n 0"aioeu""iaai")w(fn[](let[b(n 6"!.""""...")s[(n 0"STKNYPKLG""GlThShNyFt""ZvrCth")(r(N[1 2])#(do[(v)(n 9(map str"'-"(r 2 v)))(n 0(concat"lpstnkgx"[(N["h""gl""gr""nd"])(v)])"rlthggghtsltrkkhshng")]))]][b(if(seq b)[" "s][(n 3",")" "(.(a s)toLowerCase)])]))](re-find #"[A-Z].+"(a[(r 500 w)"."])))

5:48 lazybot: ⇒ "Gash cthailtoth, nyuth, gerlo'ogg! Shap gaipi-ait... Nox ctha'iand. Cthelt... Ftunilt, kug, na'iakh. No'ulus, kea! Kiarl! Thath... Nyerl, pia-eltaigg, laggol, piats! Tek ftel... Korl, kukha-osh thogg nyus lalog ftogh, te-ukh... Nyiang shaixog. Cthund... Nasoth gang... https://www.refheap.com/102235

5:48 TEttinger: to the refheap!

5:49 anti-freeze: I was going to define a macro and do a DSL to define operation groups and the use the (use-operations :default) to generate the methods

5:51 oddcully: you don't try to chant us an elder one?

5:52 anti-freeze: It's how the came up with the dragon word thingies in skyrim

5:52 Clojure was used for skyrim

5:57 TEttinger: my favorite one-liner, srsly

5:57 lots of clojure features once you start being able to read that terse code

5:58 #(mapcat partition [1 2 3]%&)

5:58 that's a key one

5:59 (#(mapcat partition [1 2 3]%&) "ABCD" "ThChPhWh" "CthSprZvr")

5:59 &(#(mapcat partition [1 2 3]%&) "ABCD" "ThChPhWh" "CthSprZvr")

5:59 lazybot: ⇒ ((\A) (\B) (\C) (\D) (\T \h) (\C \h) (\P \h) (\W \h) (\C \t \h) (\S \p \r) (\Z \v \r))

5:59 TEttinger: that's used throughout the snippet to get appropriate lengths of random letter sequences

6:00 never a Qj in there

6:28 H4ns: am i right in assuming that a type tag does not imply a cast in the java sense? i.e. if i have, say, a SQLConnection object which I know is a PGConnection, I need to both cast it and type tag it? (.getNotifications ^PGConnection (cast PGConnection conn))

6:30 TEttinger: H4ns, correct, a type hints are really just telling the compiler "this is currently this type, not a variable that could be any type" so the compiler knows what to do with it. but if the type hint doesn't match the actual type, it's ignored

6:31 H4ns: TEttinger: thanks!

6:32 TEttinger: i wonder why the compiler does not know the type from the cast, though.

6:32 (from the explicit cast, that is)

6:32 TEttinger: (doc cast)

6:32 clojurebot: "([c x]); Throws a ClassCastException if x is not a c, else returns x."

6:32 TEttinger: that would be why :)

6:34 H4ns: well, that implies that the returned value always has the class given as argument to cast, doesn't it?

7:05 cfleming: H4ns: In your example, you don't need the cast

7:05 H4ns: In that case, the hint is effectively a cast

7:09 H4ns: TEttinger is correct that type hints really just tell the compiler what the type of an expression is, but in your case the compiler will then use that hint to look up the method at compile time, and will cast the object automatically to invoke it.

7:10 sobel: TEttinger2: is that Klingon?

7:11 or Lovecraftian

7:11 H4ns: cfleming: thanks!

7:12 cfleming: H4ns: I do interop all day, and I've literally never used cast

7:13 H4ns: ok - i'll avoid it

7:13 is there a way to access a record's field so that the type tag is preserved? if i use keyword lookup, it seems that the type tag that i established with defrecord is not seen by the compiler.

7:14 supersym: that shouldnt happen

7:14 H4ns: ah, ok, right. my fault, sorry

7:14 supersym: the use of 'type',

7:15 Bronsa: H4ns: there's no way to preserve it, the type tag is compiled away

7:15 supersym: or 'name' or whatever doesn't matter as those are bound in local scope, their meaning doesnt apply anymore

7:15 unlike other languages where use of 'class' or 'type' indeed causes problems

7:15 Bronsa: defrecord/deftype fields are stored in `Object` fields, no matter what you type hint them with

7:16 supersym: ah... type HINT .. different one

8:04 mearnsh: hi all! looking for some workflow advice: i'm working on a clj/cljs proj (via chestnut) w CIDER. right now i've got two nrepl connections going so i can eval my cljs in one (via weasel) and clj in the other. but CIDER doesn't play too nice with this since the default shortcuts send everything to just one of the repls (hence i can only eval my clj code successfully)

8:12 kwladyka: what is the difference in compojure between X-CSRF-Token and X-XSRF-Token? X-XSRF-Token is encrypted?

8:14 or there is no difference?

8:19 noncom: mearnsh: also try #clojurescript

8:19 mearnsh: yeah, thx

8:20 noncom: is it possible to make clojure map destructuring to work with string keys?

8:21 mearnsh: ,(let [{:strs [k1 k2]} {"k1" 1 "k2" 2}] (prn k1 k2))

8:21 clojurebot: 1 2\n

8:21 noncom: wow!

8:21 mearnsh: ,(let [{:syms [k1 k2]} {'k1 1 'k2 2}] (prn k1 k2))

8:21 clojurebot: 1 2\n

8:22 mearnsh: also

8:22 :)

8:22 noncom: wow, never really knew that!

8:24 mmeix: where would I find doc for :strs and :syms?

8:24 (special forms?)

8:25 noncom: mmeix: i haven't seen the doc, hence i did not know.. but i guiess if you look at the source or the destructuring fn in clojure.core, they're there..

8:25 oddcully: mmeix: yes. section `Map binding destructuring`

8:25 noncom: *of the destructuring fn

8:25 mmeix: just found it: http://clojure.org/special_forms

8:25 noncom: is that a new feature or is it present already for a long time?

8:26 Bronsa: been there as long as :keys has

8:29 mmeix: I just made me a helper function, which puts vals of a map into vectors. {:foo 1} => {:foo [1]}, for using it with merge-with into afterwards ... is this reinventing some wheel. or does it exist in core? didn't find something so far ...

8:29 ,(defn vals->vector [m] (into {} (map (juxt key (comp vector val)) m)))

8:29 clojurebot: #'sandbox/vals->vector

8:30 mmeix: ,(vals->vector {:foo 1})

8:30 clojurebot: {:foo [1]}

8:30 noncom: i think this is a kind of a deep merge

8:30 afaik people invent their own wheels for that

8:30 mmeix: ,(apply merge-with into (map vals->vector {:foo 1} {:foo 2}))

8:30 clojurebot: #error {\n :cause "Wrong number of args (2) passed to: sandbox/vals->vector"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (2) passed to: sandbox/vals->vector"\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" 36]\n [clojure.core$map$fn__4555 invoke "core.clj" 262...

8:31 mmeix: ,,(apply merge-with into (map vals->vector [{:foo 1} {:foo 2}]))

8:31 clojurebot: {:foo [1 2]}

8:31 noncom: yes, like this..

8:31 mmeix: ok

8:32 goes into toolbox

8:33 ah, ok: http://dev.clojure.org/jira/browse/CLJ-1468

8:34 (what's better: building the own toolbox, using other's, or compiling other's?)

8:34 noncom: yeah, too many particularities.. many different possible usecases where you need slightly different behavior.. very hard to generalize..

8:34 mmeix: I see

8:35 kwladyka: toolbox is not up to date - dont use that

8:35 mmeix: flatland/useful seems to be ...

8:35 kwladyka: oh, i read that too fast - you are not talking about toolbox website :)

8:35 mmeix: no

8:35 noncom: in my toolbox i have many methods adviced by people on this channel, so you may say, that it is half-compiled from others and half my own

8:36 flatland is popular, yes

8:36 mmeix: ok - besides being a learning opportunity, each time :-)

8:40 ah, flatland's merge-in looks great ... though I don't (yet) understand the (letfn [(merge-in* ...)] (defn merge-in ...)) construction there - homework for this evening, I guess

8:42 a function can be defn-ed inside a (letfn ...) and is visible outside?

8:43 arkh: mmeix: you wouldn't want to do that though

8:43 mmeix: https://www.refheap.com/102239

8:44 it's at least counertintuitive to me

8:44 I thought everthing inside a local binding is invisible ...?

8:45 arkh: oh, ok. I guess they did it for the purpose of defining the function, as opposed to 'as an additional thing I'm doing inside a let'

8:45 def and defn create global bindings, even inside something lexically nested

8:45 dhardison: what's the difference in the syntax of using [] and a "do" or maybe nothing?

8:46 i'm looking at some code that has [(if true) ...]

8:46 mmeix: so this is sort of very clever and self contained

8:46 arkh: mmeix: yes

8:47 mmeix: other way would have been to (defn merge-in* ..) and then using that in (defn merge-in ...) ?

8:47 arkh: dhardison: what you just wrote is creating a vector of something with contents that depend on the if condition

8:48 dhardison: arkh: makes sense, thank you

8:48 mmeix: arkh thanks for pointing out the global thing there

8:49 arkh: mmeix: what I would have done (which seems more boring me but I don't know if it's better or worse) is, instead of creating a function with letfn, I would have done a normal defn and used an anonymous function in place of merge-in*

8:49 mmeix: ah

8:49 arkh: ^ *boring to me but I don't know if it's better or worse

8:49 mmeix: yes, that sounds more understandable/readable, at least for me

8:50 arkh: the upside with what they did is they gave an otherwise anonymous function a name, so maybe that's more readable

8:50 mmeix: aha!

8:51 arkh: but then I don't expect something lexically nested to be part of global scope, so maybe it's less readable for that reason

8:51 *shrug* : )

8:51 mmeix: this is what I didn't get when reading it first

8:51 thanks for explanations!

8:52 arkh: you bet : )

8:56 dhardison: is there an easy way for me to print a list to the js console? doing js/console.log list prints some kind of clojure object -- i just want to see the contents

8:56 mmeix: flatland/useful is a learning ressource, I just found

8:56 gfredericks: dhardison: does prn work?

8:59 arkh: dhardison: if you put (enable-console-print!) before any print statements then those statements will send their output to the js console

8:59 dhardison: gfredericks: that did work - thank you. arkh i'll look at that too thank you.

9:06 mmeix: follow-up question: if I used a lib like flatland/useful in a clojurescript-project, using only few bits out of it, then the Google Closure compiler in advanced mode would remove unused functions as dead code, and so there would be no size penalty - is this correct?

9:06 (maybe should ask this in #clojurescript)

9:07 arkh: mmeix: that is correct

9:07 mmeix: great

9:07 thanx again

9:20 profil: is there a more clojury solution to this problem? (re-find #"(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z" "20150606T180000Z")

9:20 a simple way to parse basic iso8601 dates

9:21 wink: I'd use joda time, maybe with a wrapper if there's one

9:22 arkh: I've always like clj-time

9:22 *liked

9:23 wink: and yes, it may sound like overkill to pull a lib for that.. but regarding time and date, I think it's usually worth it

9:24 profil: hmm, I wondering if it's worth it, the datestring _will_ always look like that

9:25 arkh: if you're not going to deal with more dates than that, re-find is still 'clojury' : )

9:27 profil: okay, thanks for the suggestions. Will stick with it for now, and change it when I need more in the future :)

9:28 oddcully: SimpleDateFormat?

9:32 ,(import 'java.text.SimpleDateFormat)

9:33 clojurebot: java.text.SimpleDateFormat

9:33 oddcully: ,(.. (SimpleDateFormat. "yyyyMMdd'T'HHmmss'Z'") (parse "20150606T180000Z"))

9:33 clojurebot: #inst "2015-06-06T18:00:00.000-00:00"

9:34 arkh: nice

9:47 mmeix: flatland/useful.fn.annotate ... that's really useful! just wanted to express some spontanous happyness :)

9:52 arkh: I've used comp a number of times; never found a compelling reason to use juxt

9:53 it probably means I'm missing out

9:55 mmeix: I do find this useful:

9:55 ,(map (juxt :step :acc) [{:step 2 :acc :sharp :d "foo"} {:step 3 :d "foo"}])

9:55 clojurebot: ([2 :sharp] [3 nil])

9:55 mmeix: pulling out relevant data from maps

9:56 arkh: I can see that

9:56 mmeix: just having learned about juxt a few days ago though ...

9:57 arkh: (hopefully what I wrote doesn't sound snarky - didn't mean it that way)

9:57 mmeix: no ... I'm always looking for education here for myself, being a beginner still

10:16 profil: oddcully: I am using clojurescript

10:16 gfredericks: why would I see a boxed math warning when loading a namespace in cider but not when running `lein do clean, test`?

10:18 jtmarmon: anyone know why compiling a 36 line compojure route would cause a stack overflow (compilation, not runtime)?

10:18 gfredericks: jtmarmon: nope; have you tried minimizing it to see what part causes the overflow?

10:20 jtmarmon: yeah i'm working on it & getting closer. one sec

10:28 gfredericks: so there are two clauses in this let statement that seem to cause it. if i uncomment either i get the exception again. one is a datomic query, the other is a threading macro w/ 7 args

10:35 gfredericks: jtmarmon: welp maybe sharing some code would help

12:10 iamjarvo: i deleted a template from ~/.m2 and now lein wont fetch it automatically. I get "Failed to resolve version for"

12:19 justin_smith: iamjarvo: odd - did you only delete the template, or the template and pom etc.

12:19 iamjarvo: justin_smith i figured it out. I was typoing the template name using ctrl-r

12:19 *sad-face*

12:20 justin_smith: aha, OK

12:20 iamjarvo: justin_smith but is that the right way to uninstall something? just delete it from ~/.m2

12:21 justin_smith: there isn't really a concept of "install" - but if you want to reduce the disk usage you may want to remove things you are not going to use again

12:21 I mean yeah there is a command "lein install" that puts something in your m2 cache, but it is more about caching things than installing them

12:25 iamjarvo: o ok, thank you

12:37 ionthas_: Why I cannot use (use 'midje.repl) from another namespace?

12:38 CompilerException java.lang.RuntimeException: Unable to resolve symbol

12:38 justin_smith: ionthas_: hmm, I would expect that error if you forgot to quote it

12:38 ,(use foo.bar)

12:38 clojurebot: #error {\n :cause "foo.bar"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassNotFoundException: foo.bar, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.ClassNotFoundException\n :message "foo.bar"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net.URLClass...

12:39 justin_smith: oh, no, that's a different error

12:39 kwladyka: https://www.refheap.com/102256 - what this code do and how to get this variable from other places?

12:39 justin_smith: what symbol can't it resolve?

12:39 kwladyka: it is from https://github.com/ring-clojure/ring-anti-forgery

12:39 ionthas_: justin_smit: It cannot resolve the function use.

12:40 justin_smith: ionthas_: did you use in-ns?

12:40 ionthas_: yes

12:40 justin_smith: (clojure.core/refer-clojure)

12:40 the problem is that in-ns doesn't load code

12:40 it simply creates an unusable empty namespace

12:40 kwladyka: ionthas_, http://clojuredocs.org/clojure.core/use

12:40 justin_smith: (unless the namespace was properly created before)

12:40 kwladyka: that's not the issue

12:41 kwladyka: he used in-ns, which leads to clojure.core not being referred properly

12:41 kwladyka: oh, sorry

12:41 just tried help :)

12:41 justin_smith: so he needs to explicitly spell out clojure.core in order to do anything useful

12:41 ionthas_: justin_smit: I didn't know that. Thanks :)

12:42 kwladyka: Also thanks to tou :P.

12:42 kwladyka: ;)

12:42 justin_smith: ionthas_: for future reference, you probably want require in order to load your namespace, to make sure it exists before using in-ns

12:42 ionthas_: you can fix the broken ns (after refer-clojure) by doing (require 'some.ns :reload) which loads the ns file even though the ns already exists

12:43 ionthas_: thanks!

12:43 justin_smith: kwladyka: like any other var, you can access *anti-forgery-token* via the namespace it is in

12:43 kwladyka: of course it's special, because it is a dynamic bar with a per-thread binding

12:44 kwladyka: justin_smith, but how is it working? It is just (def *anti-forgery-token*) with extra metadata

12:44 justin_smith: ,(def ^:dynamic *foo*)

12:44 clojurebot: #'sandbox/*foo*

12:44 justin_smith: ,*foo*

12:44 clojurebot: #object[clojure.lang.Var$Unbound 0x1a6b32a1 "Unbound: #'sandbox/*foo*"]

12:45 justin_smith: that creates a var, with no value bound to it

12:45 ,(binding [*foo* 1] (+ *foo* *foo*))

12:45 clojurebot: 2

12:45 justin_smith: there, foo has a value

12:45 ,*foo*

12:45 clojurebot: #object[clojure.lang.Var$Unbound 0x1a6b32a1 "Unbound: #'sandbox/*foo*"]

12:45 kwladyka: hmm so it is something like * (indicator) in C++?

12:45 justin_smith: but notice that the root of *foo* is still unbound

12:45 no

12:45 kwladyka: each thread has a different value for *foo*

12:46 unbound if it has not been bound yet, or whatever local binding is established

12:47 kwladyka: so the idea here is that ring-anti-forgery can let your app's handler know the token to render into the html via dynamic binding, and then it checks for that same dynamically found var coming back on the client's request

12:47 it prevents replay attacks

12:49 kwladyka: mmm still i feel a little magic :) In which moment in the code the value is generated?

12:49 (binding ...) ?

12:49 justin_smith: kwladyka: hidden somewhere in the anti-forgery middleware

12:50 kwladyka: oh.... right :)

12:50 justin_smith: kwladyka: https://github.com/weavejester/ring-anti-forgery/blob/master/src/ring/middleware/anti_forgery.clj#L67

12:50 that's where it happens

12:51 and I showed above how binding works (creates a value for a def that is only valid for one block of code, in one thread)

12:51 kwladyka: binding / dynamic vars is still kind of magic, and many people have convincing args that they should be avoided

12:52 eg. http://stuartsierra.com/2013/03/29/perils-of-dynamic-scope

12:55 kwladyka: ok, i added this to bookmark to read in free time, thank you

12:56 justin_smith: the important part for understanding that anti-forgery code is that via dynamic binding a symbol var can be used to represent different tokens in each thread

13:01 kwladyka: so use this var should looks like that (:require [ring.middleware.anti-forgery :refer *anti-forgery-token*]) ? i guess not, because it doesnt work :)

13:01 justin_smith: kwladyka: that's not how refer works

13:01 you need a vector

13:01 kwladyka: ?

13:02 justin_smith: ,(require '[clojure.string :refer join])

13:02 clojurebot: #error {\n :cause ":only/:refer value must be a sequential collection of symbols"\n :via\n [{:type java.lang.Exception\n :message ":only/:refer value must be a sequential collection of symbols"\n :at [clojure.core$refer doInvoke "core.clj" 4086]}]\n :trace\n [[clojure.core$refer doInvoke "core.clj" 4086]\n [clojure.lang.RestFn applyTo "RestFn.java" 139]\n [clojure.core$apply invoke "core.clj...

13:02 justin_smith: that's the version that fails

13:02 ,(require '[clojure.string :refer [join]])

13:02 clojurebot: nil

13:02 justin_smith: it works with a vector

13:02 kwladyka: oh true.... sorry, i am learning a lot and sometimes i forgot about basic things...

13:03 justin_smith: (join ", " ["hello" "world"])

13:03 ,(join ", " ["hello" "world"])

13:03 clojurebot: "hello, world"

13:03 kwladyka: yeah, it works :)

13:16 mmeix: building a function, which creates a run between two numbers, but inclusive the higher num, and self-sorting:

13:16 ,(let [range-incl (fn [a b] (apply range (map + ((juxt min max) a b) [0 1])))] (range-incl 11 -3))

13:16 clojurebot: (-3 -2 -1 0 1 ...)

13:16 mmeix: good solution?

13:18 ,(defn range-incl [a b] (apply range (map + ((juxt min max) a b) [0 1])))

13:18 clojurebot: #'sandbox/range-incl

13:18 mmeix: ,(range-incl 5 -2)

13:18 clojurebot: (-2 -1 0 1 2 ...)

13:24 kwladyka: ,(range-incl 5 5)

13:24 clojurebot: (5)

13:25 mmeix: which is ok

13:25 for my use-case

13:27 kwladyka: mmeix, (range (min -2 5) (inc (max -2 5))) - maybe something in that style?

13:27 should be more readable?

13:27 mmeix: right you are

13:58 dhardison: what's the best way to look up browser dom elements using clojure?

13:59 justin_smith: dhardison: you'll likely get more help in #clojurescript, but you can use any method that works in js, in my experience it's better to use react so you don't have to look up elements

13:59 (well, reagent or om, which use react)

13:59 dhardison: i see - i'll take a look thank you

15:18 can i store a keyword into a variable using let (e.g. (let [keyword :black] ... ) i'm geting a compile error atm but maybe it's not related to that

15:21 farhaven: ,(let [foo :bar])

15:21 clojurebot: nil

15:21 farhaven: seems to work

15:21 ,(let [foo :bar] foo)

15:21 clojurebot: :bar

15:22 j-pb: hu?

15:23 farhaven: that was in reply to dhardison

15:23 j-pb: ah sorry, I missed the top part, and was wondering if you had a question :)

15:37 sy: when working with leiningen and the cider nrepl i notice that if i modify a .clj file that provides a required namespace in another file, the file containing the required nmespace isn't re-loaded and re-compiled by lein or cider

15:37 should i expect it be re-loaded ?

15:40 justin_smith: sy: what are you doing to make reload happen?

15:44 sy: if file1.clj requires a namespace in file2.clj, file2.clj gets compiled when i start cider, if i (load ...) the namespace in file1 again, file1 gets compiled but required namespace in file2 isn't re-compiled, i am missing a clue about this simple project management

15:45 justin_smith: sy: the point of require is that it does nothing if the file you required is already loaded

15:46 sy: instead of (load ...) use (require ... :reload-all) to cause it and all it's dependencies to be reloaded

15:46 there is no way to force reload of namespaces that require a given namespace though

15:51 sy: ah... i knew there was a way, reminds me of lisp and ASDF, there is syntactic wizardy required :)

15:51 Recognized flags: :reload, :reload-all, :verbose

16:22 verma_: not sure if this is the right channel for this, but what controls the indentation of methods defined under defrecord?

16:23 I want them to indent like defn, but the first statement indents right under the parameter list

16:23 tried the clojure-backtracking-indent stuff, but no luck so far

16:28 justin_smith: verma_: indentation by whom?

16:29 verma_: oh sorry, didn't realize I never mentioned the context, clojure-mode under emacs.

16:29 justin_smith: ^

16:31 sy: this is interesting about namespaces and multiple sources files and the jvm --> https://github.com/clojure/tools.namespace#reloading-code-motivation

16:32 justin_smith: verma_: the default indent rules are all defined in clojure-mode.el

16:34 verma_: justin_smith: yeah I am trying to change them, it seems the computer I am on has a more recent version of clojure-mode, so its doing the indentation differently, can't really understand what the clojure-backtracking stuff means :(

16:44 amalloy: verma_: are you writing your defrecords incorrectly?

16:45 clojure-mode indents correct code correctly, but if you write illegal code it won't understand how to indent

16:50 verma_: amalloy: could be the reason, things have stopped working :(

16:50 amalloy: checking ..

16:53 dhardison: can i do an if statement within a let variable declaration similar to what you can do with a list?

16:56 H4ns: dhardison: you mean (let [a (if foo 1 2)] ...) ? or what?

16:56 dhardison: H4ns: yes

16:56 H4ns: dhardison: yes. `if` is not a statement, and an if form is just an expression.

16:57 dhardison: there are no statements in clojure, for what it is worth.

16:58 sy: binding-form init-expr

16:58 exprs are meant for evaluation

17:04 j-pb: and thats just what they'll do

17:31 gfredericks: hello

17:34 m1dnight_: Is there an up to date guide on clojure SQL?

17:34 I cant seem to get it working anymore. Been a while since I tinkered with this code.

17:35 verma_: justin_smith, amalloy: this is the indentation I get: https://gist.github.com/verma/69c407f9621154288d6a

17:35 m1dnight_: I was trying the basics like creating and reading but I can only seem to create a database. Reading always returns nil.

17:35 verma_: the method bodies are aligned with arguments :(

17:35 gfredericks: m1dnight_: what's "clojure SQL"?

17:35 verma_: looking at some of the examples on clojuredocs, it seems that's what its supposed to be?

17:36 amalloy: verma_: weird. do you have backtracking indent turned on?

17:36 m1dnight_: oh, right. I'm talking about jdbc here. (clojure.java.jdbc)

17:36 Im trying to play with a postgresdb

17:36 amalloy: that's the feature that's supposed to make it indent defrecord sensibly

17:37 gfredericks: m1dnight_: (jdbc/query conn ["SELECT 1"])?

17:37 m1dnight_: all nil :p

17:37 I dont get it. Queries to create tables work though..

17:37 I must be missing something stupid here..

17:38 verma_: amalloy: I am trying to set it up so that it doesn't do that, with no success, seems to me like its a recent change, since the version of clojure-mode I have on my notebook isn't doing this

17:38 gfredericks: m1dnight_: my guess is there's some weird other problem

17:38 m1dnight_: Also, I checked in pgadmin and there is actual data in the database.

17:38 gfredericks: m1dnight_: because SELECT 1 should not return nil under like any dang circumstances

17:39 verma_: going to take a look at what the nodebook version is doing to clojure-backtracking-indent

17:39 m1dnight_: But when I execute the following (on an existing db): (sql/insert! (read-db-config) "testing" {:data "fobar"})

17:39 ClassCastException clojure.core$identity cannot be cast to clojure.lang.Named clojure.core/name (core.clj:1518)

17:39 that happens. (Yes, the (read-db-config) function returns valid credentials, otherwise the create table wouldnt work, I assume)

17:40 Ill give sqlite a shot perhaps.

17:55 verma_: amalloy: ok, so the version installed on my notebook seems to be behaving correctly, I upgraded it, and it started doing the unwanted indentation again, guess I will just revert to an older version and carry on, no changes to any backtracking indentation, but seems like there was a change to backtracking regexs to account for namespace names.

17:55 I think that's why people freeze versions of packages they use, to avoid unnecessary problems :(

17:56 amalloy: yes. i run clojure-mode off a very old git checkout plus some changes i made, just because i'm not really interested in whatever new stuff comes out

20:14 gfredericks: okay so I've evolved into this workflow where I run my clj repl process with docker, and connect to it with cider

20:14 I'm not sure if the docker part is important, but one way or another I find myself restarting the repl a few times a day at least

20:15 maybe more often if I debugging something where processes hang

20:15 and cider seems to make it very difficult to reconnect

20:15 I have to manually close the buffer of the disconnected process to keep cider from nagging me about existing connections when I try to reconnect

20:15 does anybody else do this better?

20:25 I think the best option would be some way to get it to reconnect when the repl becomes available, reusing the buffer

21:06 okay big mystery here um

21:06 I'm using a lib and a var is mysteriously not defined

21:06 I can open the jar and see its defn there

21:06 I can also verify from the repl other changes unique to that jar so I can't imagine anything else running

21:07 I rm -rf'd the target before starting the repl

21:07 this is all physically impossible

21:07 amalloy: gfredericks: are you actually running the jar you have inspected, and not some other jar? are you ssh'd into a different machine accidentally?

21:09 gfredericks: now I'm looking at line metadata on the vars to see if that correlates with the file I'm looking at

21:11 the pom.properties file on the classpath says everything is normal

21:11 the line numbers are super weird though o_O

21:12 they don't correspond to any reasonable version of the lib

21:12 hold up gonna try this on a totally different computer via `lein try`

21:13 amalloy: gfredericks: have you checked that lein classpath points at the jar you think it does?

21:13 some dependency may be pulling in a different version

21:14 gfredericks: that wouldn't explain "pom.properties" though no?

21:14 amalloy: man i dunno what this pom.properties nonsense is

21:15 gfredericks: okay

21:16 everything works fine with `lein try` so I guess it's specific to this project and not the lib

21:16 now for `lein classpath`

21:16 yes indeed there is a dumber version of the project earlier in the classpath wtf.

21:17 oh I see yep yep

21:18 it's cuz I'm using a fork with a different group id

21:18 so my explicit declaration didn't override the indirect dep with the normal group id, and an older version

21:18 justin_smith: gfredericks: which is a good argument against namespaces that don't include the group

21:18 gfredericks: physics is working correctly

21:19 justin_smith: gfredericks: that's a releif

21:19 gfredericks: justin_smith: it's a temporary fork

21:19 I wouldn't want to renamespace anything

21:19 justin_smith: gfredericks: oh, OK

21:19 I was thinking of when I did some work I component

21:19 I moved it from com.stuartsierra.component to org.noisesmith.component

Logging service provided by n01se.net