#clojure log - Feb 17 2015

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

0:14 justin_smith: does this look like a cromulent way to do a timeout without core.async? https://www.refheap.com/97344

0:14 if definitely behaves properly, but it feels very low level

0:19 on my machine (timeout 1 #(apply *' (range 1 1000)))

0:19 returns nil sometimes, and a huge number spanning about 50 lines others

0:26 updated with frequencies for repeated usage https://www.refheap.com/97344

0:28 l1x: yeah this looks good to

0:28 justin_smith: l1x: your issue reminded me of this thing I brainstormed

0:28 I think it's decent, but wanted to get second opinions

0:35 l1x: yep, i might even use your code if you dont mind

0:35 justin_smith: oh, please do

0:36 l1x: thanks!

0:36 justin_smith: it might be handy as a macro, which would allow an arbitrary body instead of a function

0:36 but I don't think having to pass a lambda is too ugly

0:39 l1x: nah its fine

0:53 justin_smith: l1x: one caveat is that cancelling futures / threads is tricky in the jvm, some actions aren't guaranteed interruptable

0:53 but in general polling for some result should be

0:54 but eg. a long running system call may keep going even if it had ben cancelled

0:55 http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#interrupt() details on that

0:56 l1x: I think for your usage it hinges on whether the input you are reading on is interruptable or blocked on a Selector

0:57 worst case though is I guess that some thread hangs around waiting for a result that your main flow of logic gave up on

0:59 l1x: yeah i am going to test these

0:59 see what happens

1:00 justin_smith: easiest is to add a print after the data is fully received

1:00 but if you (or the lib that does your async http request) is using nio, the cancel should do it's thing

1:01 l1x: for example if you use this lib, cancelling will make the request process stop https://github.com/neotyk/http.async.client

1:01 some other libs, it may not

1:03 l1x: actually, http.async.client has a :timeout option built in, even better :)

1:04 documented here https://github.com/neotyk/http.async.client/blob/development/docs.org#timeout

2:21 vas: how do I make sure a symbol is bound ? is (resolve ) the preferred approach?

3:06 amalloy: vas: it is a fairly weird thing to want to do (in addition to being not specific enough to give a real answer). what makes you think you need to do that?

3:08 vas: amalloy: middleware that checks the :session values to make sure someone is logged in. if :session is not set yet, i get a null pointer exception. how can I check if it's set? i'm looking at if-let currently

4:03 dm3: hey

4:03 zacts: hi

4:04 vas: hola

4:04 dm3: does anyone know if it's possible to compile a small clojurescript fragment to javascript

4:04 like "(fn [x] x)" -> "function(x) { return x;}"

4:04 without any google closure machinery

4:05 ro_st: pretty sure it's not possible

4:20 * dysfun will be deploying his first clojure site that someone else paid for today

4:20 dysfun: very exciting

4:23 jballanc: dysfun: congrats!

4:24 dysfun: it doesn't do much (it's a one page site with some template interpolation and serving static files), but it's clojure

4:24 and that seems worth a drink or two

4:24 <3 clients who don't impose a tech stack

4:25 besides, it's all going to get cached behind nginx anyway, so it's only the admin panel that it'll be serving

4:26 jballanc: Eh, my first paid Clojure project was little more than a REST API in front of a HornetQ queue, but getting that first wedge in the tech stack is important

4:30 dysfun: well, the client doesn't care and i'm going to end up open-sourcing the cms

4:30 it needs making a bit more flexible, but it'll be great

4:33 is there a way to express this as a destructuring bind in the defn (currently bound to r)? (let [{:keys [username password]} (:params r)]

4:34 i feel like it's doable but i'm having a thinko

4:36 Glenjamin: [{{:keys [username password]} :params} r]

4:36 dysfun: perfect, thanks

4:36 Glenjamin: ,(let [r {:params {:username "u" :password "p"}} {{:keys [username password]} :params} r] [username password])

4:37 clojurebot: ["u" "p"]

4:37 Glenjamin: yeah, that's the one

4:38 dysfun: ,(defn foo [{{:keys [username password]} :params :as r}] [username password r])

4:38 clojurebot: #'sandbox/foo

4:39 dysfun: , (foo {:params {:username :u :password :p}})

4:39 clojurebot: [:u :p {:params {:password :p, :username :u}}]

4:39 dysfun: thanks Glenjamin

4:39 (inc Glenjamin)

4:39 lazybot: ⇒ 14

4:49 zot: any suggestions for debugging a dependency (lein-repack) that isn't in my project.clj, and doesn't appear with lein deps :tree? it appears to be responsible for breaking my deps (exclusion suggestion when running midje), but i can't see its origin.

4:50 Glenjamin: zot: try lein deps :plugin-tree

4:51 or possibly some variation of with-profile

4:51 some plugins add deps for you, which is magical and confusing

4:51 zot: Glenjamin: tnx, that's what i was just trying to figure out

4:51 plugin-tree didn't do it, so it must be a magical profile-based dep

4:52 Glenjamin: well, even in that case plugin-tree should show it i think

4:52 zot: sadly, not.

4:52 Glenjamin: what command are you running that shows the error?

4:53 zot: lein midje :autotest :filter foo

4:53 https://gist.github.com/anonymous/f39978d608f64ba6bbe5

4:54 i found the "now fixed" bits about cider-nrepl and cljfmt / rewrite-clj, but even with latest snaps, i'm still tracking down origin

4:54 (go away for 12 day vacation, come back to non-building code. not fun.)

4:55 Glenjamin: dependencies are hard

4:56 i was once told it wasn't a problem in clojure because "everyone keeps stuff up-to-date". I think that's less true now

4:56 zot: lol

4:56 Glenjamin: that was well over a year ago, to be fair

4:56 maybe over 2 years

4:57 zot: i think people try. but the system appears (from a relative novice) to have its share of flaws. and i get that packaging is hard. as in H-a-r-d. but that doesn't make it suck less, especially when learning.

4:57 Glenjamin: afaik the flaws are inherited from java packaging

4:57 noncom|2: does anyone have experience with raynes conch?

4:58 Glenjamin: there's nothing particularly different that clojure does, or tries to do

4:58 noncom|2: how do i enter the password for sudo with it?

4:58 zot: the worst part here is that it's ultimately emacs+repl; but since emacs packaging won't let me revert to cider-repl 0.8.2 without going to stable, i'm screwed either way.

4:58 noncom|2: i can do (let-programs [sudo "sudo"] (sudo "lalala")) but first it wants password then

4:58 Glenjamin: noncom|2: you probably need a user with passwordless sudo enabled

4:59 i'm not aware of any good systems for entering a sudo password automatically

5:00 noncom|2: Glenjamin: will this advice work? http://osxdaily.com/2014/02/06/add-user-sudoers-file-mac/

5:00 hyPiRion: you probably shouldn't do this for security reasons

5:00 Glenjamin: entering the password, or setting nopasswd ?

5:00 noncom|2: Glenjamin: setting nopassword

5:00 Glenjamin: probably both tbh, why do you need to sudo?

5:01 noncom|2: hyPiRion: in this situation i think security is not an issue, the computer is hardly accessible from network anyway

5:02 hyPiRion: noncom|2: heh, hence my "probably" – what you can do in that case, is to run the clojure program as root

5:02 noncom|2: Glenjamin: i need to change the current user of java clojure process. in other words, i have to exec a command as another user

5:03 hyPiRion: yes, running as a more enabled user is the best option.. but the script starts under TeamCity CI agent and it is configured to run as a lesser user.. I will have to wait for people that configure TeamCity to come back from vacation to do that...

5:03 dysfun: inherently if you're using sudo, you will have to nopasswd at least that

5:03 you might also try setuid

5:04 i think setuid only works for binaries, so you might have to knock together a quick c program to exec

5:04 Integralist: Hi, I'm running the following basic example clojure app (http://goo.gl/hRn0Gq) and I'm getting the following error "Unable to resolve symbol: app-source in this context". I'm not sure why this would be, because when I look at my lib where that's defined (http://goo.gl/f3QcwT) it works when running via lein repl. It's only when I load it within the example application that this error occurs?

5:05 slipset: noncom|2: isn't it great working in a place where you can't get work done because people are not there and you yourself are not authorized?

5:05 dysfun: setuid is the mechanism sudo uses, it's just that sudo is setuid root and then does the checks itself. which is why people read the source of it trying to discover new exploits a lot

5:06 noncom|2: dysfun: strange, but it says that setuid is not found

5:06 dysfun: there used to be a good bug where trampolining sudo as sudo sudo sudo would let you in as root :)

5:06 setuid is a file flag

5:06 noncom|2: ah

5:07 dysfun: there's also setgid

5:07 you are now in the realms of unix, not the jvm

5:08 noncom|2: slipset: well, actually that sucks. but in the big picture, if i am helpless and have to wait, i just go doing my own pet projects and feel fine with that :)

5:08 dysfun: heh. i spent several months going crazy with a client who would hold up all attempts to get things done

5:09 being paid well for my time did not make it worth it

5:09 nor did personal projects

5:09 Glenjamin: anyone know how to google for stack overflow errors?

5:09 dysfun: :)

5:10 can you -site:stackoverflow.com ?

5:10 Glenjamin: i dunno, i do want answers from there as well >.<

5:11 dysfun: the similar problem i have a lot is products that have ungooglable names

5:11 slipset: go?

5:11 as in go-lang

5:12 dysfun: kudos to the symfony project for telling all their devs to call it 'symfony2' rather than 'symfony' when they made huge breaking api changes

5:12 go i always google as 'go lang'. but at least they tried

5:13 googling for scheme things is tedious sometimes, because a lot of things in the real world have schemes

5:15 Raynes: noncom|2: You can work with processes interactively.

5:16 noncom|2: Raynes: you mean i can get the stdin for the process from the returned map and write there?

5:16 Raynes: All ya gots to do is wait for the password prompt to pop up in stdout and then throw a password at stdin.

5:17 You don't even have to wait

5:18 noncom|2: https://github.com/raynes/conch#piping

5:18 See the first example

5:18 You can pass a string to :in and it goes to stdin.

5:18 The first thing it asks for is a password prompt, right? If so, all you gotta do is push it :in there.

5:19 noncom|2: well, i tried this: (let-programs [sudo "sudo"] (sudo "lalal" {:in "my-password"})) but it looks like it did not work

5:19 or it hanged up there

5:19 for some other reason

5:19 script execution never continued after that..

5:20 hyPiRion: noncom|2: use `sudo -S`, sudo by default reads from the terminal, not stdin

5:20 (Also, the password has to be followed by a newline)

5:21 noncom|2: ah, that is a valuable piece of info

5:23 Raynes: Yup, what hyPiRion said.

5:25 swi: Hello. What lib can i use for tcp/udp socket operations ? Can't see something like this on toolbox

5:26 noncom|2: swi: i used aleph https://github.com/ztellman/aleph and http://paulosuzart.github.io/blog/2012/07/09/tcp-server-with-clojure-aleph-and-gloss/

5:26 swi: but surely you can use any java loib

5:26 *lib

5:27 swi: noncom|2: oh, thanks. )

5:28 Raynes: noncom|2: (sh/with-programs [sudo] (sudo "-S" "ls" {:in "pass\n"}))

5:29 Tested this

5:29 It works

5:29 Though I'm not sure how I feel about helping you sudo from a Clojure program :P

5:29 noncom|2: Raynes: wow, cool! :) already getting to the same edge

5:30 hahaha, that is for the Greater Good :)

5:32 Raynes: I fixed some Python code recently that, rather than just import another piece of code, it instead invoked a Python interpreter and ran the file as a script. Better yet, it invoked it with sudo because that script was writing to a root owned location... rather than just changing the permissions...

5:32 * Raynes guzzles his gin & tonic

5:34 noncom|2: i totally understand that. besides, everybody knows that machines invented the restricted access to control humans...

5:35 they're being passively-aggressive with that: "if you do not protect me with a password, all your important and personal data is compromised..".. while truly it rises barriers among people, but not among machines.

5:36 hyPiRion: I thought the lizard people was behind those things

5:39 noncom|2: well lizard people are the ones who nurish certain kind of ambitions and techology here (all that security stuff). so yes, that particular thing is a part of their plan, afaik.

6:03 Raynes: is it possible to pipe more that 1 command with conch?

6:03 Raynes: ?

6:04 Oh

6:04 noncom|2: using (proc) i guess..

6:04 is a possible solution

6:04 Raynes: lol noooooo

6:04 u silly

6:04 swi: hm.. how can i ask lein to update/install all deps in project ?

6:05 noncom|2: swi: afaik there is no auto-update feature..

6:05 Raynes: noncom|2: So, by pipe more than one command, do you mean `foo | bar | baz` vs `foo | bar`?

6:06 swi: noncom|2: well, i mean afair lein must download those deps i'v added to project.clj, no ?

6:06 noncom|2: Raynes: yes

6:06 swi: try "lein deps"

6:06 Raynes: noncom|2: Once again, see first example here: https://github.com/raynes/conch#piping :P

6:07 You should be able to :in chain forever, presumably.

6:07 noncom|2: Raynes: oh :) rrrright, just add one more :in to the inner command..

6:07 Raynes: That could be improved.

6:07 I'd like to make it work with ->.

6:07 =D

6:09 swi: noncom|2: it shows nothing, with :tree it shows aleph and i see it in .m2/repository

6:10 noncom|2: swi: "lein deps" often shows no ouput, afair.. did not use it from a command line for long time (i am using an IDE)

6:10 swi: i would suppose that the library is already available from within your project

6:11 swi: try "lein repl" and then "(require '[aleph.http :as http])"

6:11 if there is no error, all is intact

6:12 swi: noncom|2: damn.. require was a mistake. i writen (require '[aleph])

6:12 noncom|2: swi: also, libraries do not get copied to your project or something. they just reside in the .m2/repository folder.

6:13 swi: i suggest you getting an ide of sorts.. :) developing in bare cli repl is something rough i think

6:13 swi: noncom|2: yes, i know about m2, but seems dont' get about require correctly

6:13 * swi use cider :)

6:14 noncom|2: ok, so what does "(require '[aleph.http :as http])" say ?

6:14 swi: noncom|2: nothing :) i mean no errors :)

6:14 noncom|2: swi: you must require particular namespaces of a library. not a library itself

6:15 swi: nothing is fine. it means you have required the lib ok

6:15 now all what is inside the namespace is available to you..

6:15 is it your first experience with clojure?

6:15 swi: so i can't require whole lib anduse it like lib.foo.func ?

6:16 noncom|2: swi: correct. you can't. only exact namespaces can be required.

6:16 swi: well, i'v read a basic intro to clojure about 4-5 month ago.

6:17 seems like need to reread some book again :)

6:17 noncom|2: swi: well, don't worry, the concepts are rather simple and once you get some experience, you'll have a firm grasp.

6:18 swi: noncom|2: practice - mother of mastership :)

6:18 noncom|2: swi: also, (require) is a function that is to be executed from a repl

6:18 swi: all can be executed from repl the almighty :)

6:19 noncom|2: i can't use require in src ?

6:19 noncom|2: swi: i just want to mention that when you create your own namespace with (ns..) and have (ns mynamepsace (:require [aaa.bbb :as b])) then it is different

6:19 in src you mainly use the (ns) form

6:19 Integral1st: Hi, I'm running the following basic example clojure app (http://goo.gl/hRn0Gq) and I'm getting the following error "Unable to resolve symbol: app-source in this context". I'm not sure why this would be, because when I look at my lib where that's defined (http://goo.gl/f3QcwT) it works when running via lein repl. It's only when I load it within the example application that this error occurs?

6:19 noncom|2: that (ns) form declares and creates a ns, and all your requires and imports should be declared there

6:19 just look at some existing sources..

6:20 (require) can be used in src, but it is not a usual practice

6:24 Integral1st: ummm.. where is it referenced in your first source at all?

6:24 whats the stack trace?

6:24 swi: noncom|2: hm. thanks for explanation :)

6:25 noncom|2: swi: yeah, (ns) calls (require) implicitly for all things listed in your (:require ...) list inside the (ns) call :)

6:26 swi: noncom|2: funny, (require) and (:require) in (ns) are both works :)

6:26 Bronsa: Integral1st: eval is definitely not the way to go there

6:27 noncom|2: swi: that is because (require) gets evaluated anyway, effectively returnin "nil" in its place, and (:require) undergoes the usual procedure

6:27 a bit strange that (ns) tolerates nils but what we could do about that..

6:27 maybe there is even a reason for that

6:32 dysfun: the (ns) just expands to a simple binding form ultimately

6:32 well, that bit of it does

6:34 iirc it macroexpands to (in-ns 'namespace-symbol)

6:34 under the hood that sets *ns*

6:34 * swi get something... from udp, actualy nothing

7:23 aaaaaaaaarrrr: How do I figure out if a certain (aribtrarily deep) list/vector structure is a sub-structure of another?

7:24 I tried doing something like (->> (postwalk (partial = a) b) flatten (every? false?) not)

7:24 but that won't work, since postwalk will iteratively replace the innermost values of the structure it's walking

7:25 AeroNotix: aaaaaaaaarrrr: what's the larger problem you're trying to solve?

7:25 hyPiRion: what do you mean by sub-structure in the first place?

7:25 aaaaaaaaarrrr: AeroNotix: does a hiccup template contain a certain piece of data anywhere?

7:26 AeroNotix: Why don't you know where it is?

7:26 aaaaaaaaarrrr: hyPiRion: [a [b]] is a sub-structure of [a [b]], [[a [b]] c], etc, but not of [a b]

7:27 AeroNotix: I don't care where it is. I'm writig tests

7:30 AeroNotix: aaaaaaaaarrrr: could use walk with someting that sets an atom if it's just for tests

7:30 swi: `(+ 2 2)

7:31 AeroNotix: aaaaaaaaarrrr: https://gist.github.com/AeroNotix/83e1e4d88f8d96e46ad2

7:32 aaaaaaaaarrrr: AeroNotix: cool, thanks

7:38 hyPiRion: why not just something like

7:38 (defn deep-contains? [coll x] (or (if (sequential? coll) (some #(deep-contains? % x) coll)) (= coll x)))

7:39 AeroNotix: same difference really

7:39 you still traverse the entire thing, no?

7:39 hyPiRion: well, it short-circuits if you find the thing you're looking for

7:40 but yeah, gives you the same result

7:42 scottj: opps, sorry if I just sent something to channel, I was fiddling with my irc client.

7:55 TimMc: scottj: You did! The message was: "opps, sorry if I just sent something to channel, I was fiddling with my irc client."

7:56 scottj: TimMc: ahh. I thought /notice would display me a notice, but I guess it sends one to the channel, but I probably don't have permissions to do that.

7:57 Integral1st: noncom|2: Bronsa apologies, I was pulled into a meeting.

7:57 TEttinger: did you want /msg ?

7:58 noncom|2: Integral1st: don't worry, this is irc.. people may appear and disappear and then reappear or not randomly :D

7:59 Integral1st: noncom|2: when I execute `lein ring server` from my `spurious-clojure-example` app I get the following stack trace error https://gist.github.com/Integralist/e3a92c4d93d83a385a7a

7:59 Glenjamin: scottj: i saw the notice

8:01 noncom|2: Integral1st: so, the eval does not eval in that namespace that you expect

8:01 Bronsa: Integral1st: using eval that way is also a terrible idea

8:02 noncom|2: Integral1st: a simple workaround would be (binding [*ns* (find-ns 'spurious-aws-sdk-helper.utils)] (eval ...))

8:02 Integral1st: but as Bronsa says, this be descouraged

8:03 better store all your data in a map, so it can be accessed by a key which can be coined

8:09 Integral1st: noncom|2: ok so eval is happening in some top level ns. What's an alternative way of achieving this without eval?

8:56 maio: when I define anon function as (fn xyz [] ...) can I somehow get is't name later on? (xyz)

9:03 dnolen: maio: xyz in that case is a local name only available to the body of that fn

9:16 noncom|2: Integral1st: try (ns-resolve ...)

9:17 Integral1st: although I would *strongly* recommend against a similar approach

9:17 guessing symbols defined in a namespace is a very bad practice usually, this case included

9:17 better create a {} of your settings and pick keys from it

9:28 Integral1st: noncom|2: ok, so effectively have a map defined in the initial namespace that can be globally available is what's being suggested. I'll have to google that as I didn't think Clojure had a global scope access (I thought everything was scoped to namespaces)

9:28 noncom: Integral1st: clojure does not have a global scope, all is indeed scoped to namespaces

9:28 Integral1st: what i meant by saying what i said is

9:29 Integral1st: prefer this: (def my-data {:data-key-a whatever-data-a :data-key-b whatever-data-b ...}) to (def data-key-a whatever-data-a) ...

9:29 or, if you want dynamism, (def my-data (atom {...}))

9:30 just avoid guessing variables names

9:30 that is sometimes needed, but only in hardcore metaprogramming, which your case is apparently not

9:32 when you do (def my-data {:data-key-a whatever-data-a ...}) and you get a string "data-key-a" from somewhere, you can ((keyword key-string) my-data)

9:32 Integral1st: and it'll get you whatever-data-a

9:33 you could even do string keys instead of keyword keys and just (get my-data "some-string-key")

9:34 Integral1st: also, in your case the data and the function that uses it are defined in one namespace, so why complicate things? :)

9:41 Integral1st: noncom: ok thanks, I'll have a think about how best to refactor this :-)

9:44 gfredericks: btest

9:44 whoops

10:33 zot: is there a portable way to instantiate a record with 0 args? (defrecord Foo [bar baz]) … (map->Foo {}) works, but using map + {} seems inelegant.

10:34 although i suppose it is explicit, in that the keys are (presumably) instantiated w/ nil, instead of not present

10:49 justin_smith: zot: yeah, (Foo. nil nil)

10:50 zot: the above is equivalent to (map->Foo {})

10:50 ,(defrecord Foo [bar baz])

10:50 clojurebot: sandbox.Foo

10:50 justin_smith: ,(= (map->Foo {}) (Foo. nil nil))

10:50 clojurebot: true

10:51 dmbennett: interesting

10:51 justin_smith: ,(= (->Foo nil nil) (map->Foo {}) (Foo. nil nil))

10:51 clojurebot: true

10:51 zot: justin_smith: tnx; i figured as much, but wanted something that works for instantiating an empty 'root' object for later merges :)

10:52 and in several places, with differing underlying records

10:52 justin_smith: zot: right, all of those produce equivalent records

10:52 underlying records?

10:52 zot: different record types

10:52 justin_smith: ahh, OK, then you likely want the map->Foo form then

10:52 zot: exactly :)

11:03 rodnaph: i'm trying to do some java interop and when calling a constructor (PdfReader. "file.pdf") I'm getting InvocationTargetException - can anyone tell me if there is a general cause for this error? (like not being able to find a constrctor with matching types or something...)

11:05 justin_smith: rodnaph: I don't know what lib that is, but I would expect PdfReader to take a file or InputStream, and not a file name

11:05 rodnaph: just based on other classes / APIs in the java world

11:06 rodnaph: justin_smith: yeah i don't expect you to know the library, i just thought this error was coming from clojure doing the interop, and not the library

11:07 justin_smith: rodnaph: I have never seen that exception from clojure, but it's an exception that constructors should throw if there is something wrong with an argument

11:07 (or methods... but since we are talking about a constructor here...)

11:08 rodnaph: justin_smith: you are correct sir! my assumption was mistaken (just grepped the clojure codebase to be sure as well)

11:08 justin_smith: thanks!

11:09 justin_smith: rodnaph: which pdfreader class is it anyway?

11:10 rodnaph: justin_smith: com.itextpdf.text.pdf.PdfReader from iText - i was given it an invalid path to the file :E

11:10 justin_smith: aha!

11:10 that would do it then

11:10 rodnaph: when you're looking at the stars, make sure you don't trip on the pavement ;)

11:13 djames: l1x: I saw some of your messages from yesterday. Looks like you are open to various kind of timeout options and aren't necessarily using core.async.

11:14 Which, of course, broadens the discussion quite a bit. :)

11:14 l1x: ;)

11:14 djames: You found something you are happy with now?

11:14 justin_smith: l1x: yeah, I hope you saw that async client that has a timeout arg in the request function

11:15 * djames is startled by the sudden omnipresence of justin

11:15 justin_smith: haha

11:15 sudden?

11:15 djames: ever-present is more like it!

11:15 l1x: justin_smith: i haven't

11:16 djames: l1x: what are your constraints?

11:16 You want to make an HTTP call with a timeout perhaps?

11:16 Trying to figure out what pieces you have.

11:16 justin_smith: l1x: "documented here https://github.com/neotyk/http.async.client/blob/development/docs.org#timeout "

11:17 djames: Because I have this terrible tendency to point out that NIO.2 is actually pretty cool.

11:17 Though it is low-level and not necessarily useful if you are just doing HTTP.

11:17 justin_smith: l1x: what led me to that was realizing that timeout doesn't do as much to help you if the http request isn't cancellation friendly - which led me to "which http lib is friendly to having request cancelled" which led me to the fact that http.async.client has a :timeout arg built in

11:17 l1x: justin_smith: i am working on a http server not a client

11:18 justin_smith: l1x: so you are a server, timing out the client?

11:18 l1x: a server timing out on writing to a message q

11:18 djames: l1x: how is your http server different? why not use something off the shelf?

11:18 justin_smith: aha, I misunderstood that bit

11:19 l1x: yeah, the timeout function I shared before should work if you are blocked on writing to a queue

11:26 sdegutis: Can anyone give recommendations on how to quickly become proficient at Clojure? Thanks in advance, best regards.

11:27 vas: sdegutis: i am just a novice myself, but there are 2 books I have found very useful: The Joy of Clojure , and Clojure Programming

11:27 sdegutis: vas: is the second one by cemerick?

11:28 vas: sdegutis: yeah, cemerick, cgrand, and brian carper

11:28 sdegutis: thanks

11:29 I know there's two books with nearly the same name.

11:29 justin_smith: ,(shuffle '[clojure programming])

11:29 clojurebot: [clojure programming]

11:29 justin_smith: ,(shuffle '[clojure programming])

11:29 clojurebot: [clojure programming]

11:29 justin_smith: ,(shuffle '[clojure programming])

11:29 clojurebot: [programming clojure]

11:29 vas: From a newbie's perspective I think Joy of Clojure is superb. I'm mostly using Clojure Programming for reference

11:30 lol justin

11:30 justin_smith: ,(repeatedly 8 #(shuffle '[clojure programming]))

11:30 clojurebot: ([clojure programming] [programming clojure] [programming clojure] [clojure programming] [programming clojure] ...)

11:32 sdegutis: ,(distinct (repeatedly 3 #(shuffle [:clojure :programming])))

11:32 clojurebot: ([:programming :clojure] [:clojure :programming])

11:32 sdegutis: ,(distinct (repeatedly 2 #(shuffle [:clojure :programming])))

11:32 clojurebot: ([:clojure :programming] [:programming :clojure])

11:32 sdegutis: "random" lol

11:33 michaelr`: cfleming: kudos for let binding alignment, I might get used to such luxury :)

11:35 mmitchell: I have a leiningen project and have added cider-nrepl to my :user :plugins profile. Whenever I cider-connect in emacs, I get a warning "Please, install (or update) cider-nrepl 0.9.0-SNAPSHOT and restart CIDER" -- but that's the version of cider-nrepl I have in my :user :plugins.

11:35 If I start the repl (lein repl) in a different directory and re-connect, I don't get the warning.

11:35 TEttinger: sdegutis: yeah IIRC the RNG java uses by default is not great

11:35 mmitchell: any ideas on what's going on there?

11:35 justin_smith: mmitchell: not plugins

11:35 mmitchell: it's runtime, it needs to be in dependencies

11:35 TEttinger: or dev-dependencies

11:35 justin_smith: plugins is for tooling that isn't available in the runtime

11:35 mmitchell: oh! man, thanks for that. Makes sense

11:35 justin_smith: TEttinger: good point

11:36 mmitchell: I usually put it in profiles.clj

11:36 since you want the same dep for all your local clojure dev

11:36 but not in anything you deploy

11:37 TimMc: ,(let [things ["cooking" "painting" "sex" "clojure"]] (str "the joy of " (rand-nth things)))

11:37 clojurebot: "the joy of clojure"

11:37 justin_smith: other good things to put in your profiles.clj :user :dependencies are criterium and pallet/alembic

11:37 (inc TimMc)

11:37 lazybot: ⇒ 92

11:37 TimMc: ,(repeatedly 5 #(rand-nth (range 10)))

11:37 clojurebot: (9 9 9 9 9)

11:38 justin_smith: woah...

11:38 * TimMc whistles innocently

11:38 justin_smith: did you rebind rand-nth?

11:38 TimMc: maaaybe

11:38 but for a good cause

11:38 justin_smith: ,(rand-nth (range 100000))

11:38 clojurebot: 99999

11:38 mmitchell: thanks justin_smith / TEttinger - going to try now

11:38 sdegutis: ,(random)

11:38 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: random in this context, compiling:(NO_SOURCE_PATH:0:0)>

11:38 sdegutis: ,(rand)

11:38 clojurebot: 0.7762006921209322

11:39 TimMc: ,(let [things ["cooking" "painting" "sex" "clojure"]] (str "the joy of " (rand-nth things)))

11:39 clojurebot: "the joy of cats"

11:39 justin_smith: lol

11:39 TimMc: ,(repeatedly 5 #(rand-nth (range 10)))

11:39 sdegutis: ,(with-redefs [rand (constantly 4)] (repeatedly 5 rand))

11:39 clojurebot: ("cats" "cats" "cats" "cats" "cats")

11:39 (4 4 4 4 4)

11:39 TimMc: Cats are statistically likely.

11:41 sdegutis: ,(alter-var-root #'clojure.core/rand (constantly (constantly 4)))

11:41 clojurebot: #<core$constantly$fn__4346 clojure.core$constantly$fn__4346@17e9b369>

11:41 sdegutis: ,(rand)

11:41 clojurebot: 4

11:41 sdegutis: ,(repeatedly 10 rand)

11:41 clojurebot: (4 4 4 4 4 ...)

11:42 sdegutis: welp, my work here is done

11:42 justin_smith: ,(repeatedly (rand) rand)

11:42 clojurebot: (4 4 4 4)

11:42 TimMc: ,(rand-int 10)

11:42 clojurebot: 4

11:42 TimMc: hmm

11:42 ,(shuffle (range 10))

11:42 clojurebot: [2 3 4 5 8 ...]

11:42 TEttinger: ,(rand-nth "abcdefg")

11:42 clojurebot: \e

11:43 TEttinger: ,(rand-nth "abcdefghijklmnop")

11:43 clojurebot: \e

11:43 TimMc: Why not cats?

11:43 mmitchell: justin_smith: sorry, i didn't describe my problem accurately. I'm using tools.nrepl to spawn a repl in dev. It's when I connect that _that_ repl server the cider warning is displayed in emacs.

11:44 justin_smith: mmitchell: if you add the cider-nrepl dep to profiles.clj, or to the appropriate project's dependencies, it should clear that up

11:44 mmitchell: unless cider has a bug where it reports the wrong string for the required cider-nrepl version (which wouldn't be a huge surprise)

11:45 mmitchell: justin_smith: i tried it yeah, and same message is displayed

11:45 justin_smith: mmitchell: does lein deps :tree show the cider-nrepl dep?

11:46 mmitchell: justin_smith: yeah it's there

11:50 justin_smith: mmitchell: what's the cider-version it goes with?

11:51 mmitchell: deps :tree shows this - cider/cider-nrepl "0.9.0-20150216.224738-8"

11:51 oh you mean cider?

11:51 justin_smith: mmitchell: I mean in elisp / emacs the cider version

11:51 mmitchell: justin_smith: .emacs.d/elpa/cider-20150215.730/

11:52 justin_smith: ugh, melpa really messes up the version strings doesn't it...

11:53 sdegutis: ,(rand)

11:53 clojurebot: 0.7207220370066598

11:53 sdegutis: Wait, how did it get fixed?

11:53 justin_smith: it resets automatically

11:54 sdegutis: aw

11:54 TimMc: Evry 15 minutes or so.

11:58 mmitchell: justin_smith: installing from marmalade yields this: .emacs.d/elpa/cider-0.8.2/

11:59 justin_smith: OK - yeah, but that's a different version than you had before - but anyway, if that's properly installed, you would want the cider-nrepl with the matching version

12:00 but beware that changing cider versions usually requires deleting all your elc files and doing a full emacs restart

12:00 mmitchell: justin_smith: how do i specify a set version for a package?

12:01 justin_smith: emacs doesn't really support that sadly, as it doesn't have declarative dep resolution

12:01 mmitchell: or if you mean setting a version of cider-nrepl on the clojure side, that's a matter of changing your version string, of course

12:02 mmitchell: oh i see. Yeah, I'll try that

12:07 justin_smith: ~map

12:07 clojurebot: map is hard

12:07 justin_smith: ~lazy

12:07 clojurebot: lazy is what will save us all

12:07 justin_smith: ~for

12:07 clojurebot: for is Lua

12:08 justin_smith: clojurebot: clojurebot is weird

12:08 clojurebot: In Ordnung

12:08 cddr`: Speaking of cider-nrepl, I'm wondering about the edit/test cycle of people who work on that. Do you have any tricks to avoid lein install after each change?

12:09 justin_smith: cddr`: hypothetically you can test it out within it's own repo, right?

12:09 *its

12:10 cddr`: but when a user uses it, they use it as a plugin

12:10 justin_smith: cddr`: no, it won't work as a plugin

12:10 it needs to be present at runtime

12:10 which means a dependency

12:11 err... wait

12:11 I'm wrong

12:11 how the hell does it work then?

12:12 ahh, the plugin inserts itself in deps... https://github.com/clojure-emacs/cider-nrepl/blob/master/src/cider_nrepl/plugin.clj#L20

12:12 mmitchell: hey, I was wrong, you can actually use cider-nrepl as a plugin, it then magically inserts itself into your deps vector

12:13 mmitchell: ah ok, i guess my unchanged result makes sense then

12:15 * justin_smith resolves to no longer attempt to apply common sense to cider.

12:16 mmitchell: justin_smith: so cider-nrepl is at 0.9.0-SNAPSHOT - does that mean there is no compatible cider package for that (cider is at 0.8.2)

12:16 justin_smith: mmitchell: if cider is 0.8.2, that should be your cider-nrepl version too

12:16 {blake}: cfleming: No problem, I get babies.

12:17 justin_smith: {blake}: I think there's a pill for that

12:17 anildigital: lol java.io.FileNotFoundException: Could not locate recursion__init.class or recursion.clj on classpath:

12:17 java.io.FileNotFoundException: Could not locate count__init.class or count.clj on classpath:

12:17 justin_smith: /rimshot

12:17 anildigital: Exception in thread "main" java.io.FileNotFoundException: Could not locate time__init.class or time.clj on classpath:

12:17 3 different errors while deploying to heroku

12:17 {blake}: justin_smith: Go on, recommend the veal.

12:17 anildigital: error changes when tried to deploy each itme

12:18 justin_smith: anildigital: sounds like something that would happen with corrupted require clauses

12:18 anildigital: And now lists java.io.FileNotFoundException: Could not locate lists__init.class or lists.clj on classpath:

12:18 justin_smith: okay

12:19 mmitchell: justin_smith: ugh ok, so the problem is that cider is installed from melpa at version cider-20150216.2223 - if I can't control what version is getting installed, and cider-nrepl needs to be the same version, it would seem that there's no way to sync the two :(

12:19 justin_smith: anildigital: are these similar to anything you are trying to require in your namespaces?

12:19 anildigital: justin_smith: https://gist.github.com/anildigital/3b911e40b2fa99c66b27

12:19 justin_smith: anildigital: weird...

12:20 llasram: mmitchell: melpa-stable

12:20 anildigital: justin_smith: hmm

12:21 Glenjamin: would nrepl clients be capable of installing their own middleware after connecting?

12:21 it seems like it should work in theory, it's just evalling some code

12:21 justin_smith: Glenjamin: using pomegranate, it would be possible

12:21 Glenjamin: even without, just send the forms over

12:21 justin_smith: Glenjamin: and that would be a lot cleaner than requiring that the user have two projects installed in compatible versions

12:22 Glenjamin: i think so, yeah

12:22 anildigital: justin_smith: ah.. noticed why is it happening.. there are clojure files in

12:22 https://github.com/anildigital/clojurebyexample/tree/master/src/clojurebyexample/code

12:22 and those are trying to get compiled

12:22 justin_smith: Glenjamin: but would cider accept a change that so radically alters their api? /s

12:22 cddr`: I just cloned the cider repo and put it on my elisp path.

12:22 anildigital: I don't want those to get compiled.

12:23 justin_smith: anildigital: OK, yeah, because they have invalid namespaces relative to your classpath

12:23 so yeah, that would cause that error

12:23 so I think you need some exclusion, or to make sure they are not in the src-paths

12:23 anildigital: justin_smith: hmm yes

12:23 justin_smith: anildigital: maybe move them from source to resources?

12:23 since they aren't normal namespaces

12:23 anildigital: justin_smith: do you know any such rule

12:24 justin_smith: anildigital: the rule is that a namespace must reflect the file path relative to the classpath

12:24 anildigital: justin_smith: can I add something in project.clj to tell that don't compile code folder

12:24 justin_smith: anildigital: but if you put it under resources rather than src you'll have no such problem

12:25 anildigital: you could alter source-paths to not include src, or put those files under a dir other than src

12:26 anildigital: if it was my project, I would move src/clojurebyexample/cope/ to resources/code/

12:26 anildigital: justin_smith: hmm

12:26 justin_smith: since it's not code used by your project (the namespaces aren't even valid for such), it's a resource that has demonstration code

12:26 and you can still use eg. load to load the files since resources/ is on the classpath

12:27 but putting it under resources/code makes sure the packaging process does not try to compile those files

12:27 which would fail, because they have invalid namespaces relative to their classpath

12:28 anildigital: justin_smith: okay

12:28 justin_smith: also, I think it just makes sense to segregate the code you use as examples of clojure code from the code that runs your app

12:29 anildigital: okay done.. fingers crossed for heroku

12:30 justin_smith: to see different error each time was something for me

12:30 and simple classes like lists, count etc

12:30 justin_smith: right

12:30 anildigital: until I realized the issue

12:30 sweet http://clojurebyexample.com/

12:31 justin_smith: nice

12:31 so moving the code/ folder did it

12:32 anildigital: justin_smith: yep

12:32 I wish I could remove the docs for dependencies in the page

12:33 justin_smith: ahh - will marginalia still work with the moved code dir?

12:33 maybe you should have a "sub project" rooted under resources where you can run marginalia

12:33 anildigital: justin_smith: I generate that myself

12:33 justin_smith: OK

12:33 anildigital: justin_smith: these are actually simple code snippets

12:34 justin_smith: right

12:34 but from what I remember "lein marg" doesn't have many options

12:40 anildigital: justin_smith: yeah

12:40 I am hoping lein marg becomes good

12:51 mmitchell: llasram: thanks for the melpa-stable tip :)

12:52 I now have cider 0.8.2 installed and cider-nrepk too. And now after doing a cider-connect I get: "Please, install (or update) cider-nrepl 0.8.2 and restart CIDER" lol

12:52 must be related to it being an embedded nrepl via tools.nrepl

12:55 gfredericks: mmitchell: if you're starting up the nrepl server yourself you have to specify the middleware explicitly

12:56 mmitchell: gfredericks: is that cider-nrepl middleware?

12:56 gfredericks: yeah

13:01 anildigital: What's your-handler here https://github.com/ring-clojure/ring/wiki/Static-Resources

13:01 I just dont' have that..

13:01 and want to serve static resources only

13:01 noonian: a ring handler is just a function from request to response maps

13:01 anildigital: noonian: but what if I don't want to write that..

13:02 I just want to serve static resources

13:03 mmitchell: is cider and cider-nrepl compatible with lein ring and its repl options?

13:03 noonian: i think compojure has some helpers for returning handlers that serve static resources

13:03 anildigital: noonian: I just want to skip handler.. may be return true or something so that it will always fall back to resources

13:04 noonian: yeah should be able to do something like: (cc/defroutes my-app (compojure.route/resources "/"))

13:04 anildigital: noonian: I am not using compojust

13:04 compojure

13:05 noonian: since you are serving from a webserver you need to create a handler that does the job of serving the static assets, the other option would be to use something like nginx to serve the resources

13:05 anildigital: I am restricted to ring

13:05 noonian: hmm can't use nginx

13:05 what's simple empty handler.. which doesn't do anything

13:05 something harmful

13:06 noonian: (ring.util.response/not-found "we just serve resources here")

13:07 adgtl: like no-op handler

13:07 noonian: (constantly (ring.util.response/not-found "not-found message")) you can probably use that as your handler

13:07 should return static resources and not found if a resource wasn't requested

13:08 when wrapped with the wrap-resource middleware

13:08 adgtl: noonian: actually when / is hit. I want to return index.html

13:08 index.html is static resource..

13:09 mmitchell: OK the only way i can get cider / nrepl happy is through lein repl -- lein ring server (with repl options) doesn't work. both cider and cider-nrepl are at 0.8.2

13:09 adgtl: I could add 302 and Location "/index.html"

13:09 but instead want to return 200 and index.html

13:12 noonian: i'd definitely recommend using something like compojure or clout at least then so you dont have to do routing yourself

13:14 adgtl: then you should get everything you want with something like this: https://www.refheap.com/97372

13:14 missing a couple refers in the require statement

13:14 adgtl: noonian: yep.. but can't use compojure

13:14 noonian: can you use any library?

13:17 otherwise you will need to write a handler that inspects the request map and does its own dispatching based on the request url; i don't have time to help you with that though especially when there are tons of libs that do it (might checkout compojure's src to see how it does it)

13:19 adgtl: :body (java.io.FileInputStream. "resources/output/toc.html")})

13:19 :)

13:23 justin_smith: adgtl: that will fail if you deploy a jar

13:23 adgtl: hmm

13:23 justin_smith: adgtl: consider instead (clojure.java.io/resource "output/toc.html")

13:23 same contents, works from a jar

13:23 adgtl: justin_smith: how about (file-response "resources/output/toc.html")

13:23 justin_smith: no

13:23 because it isn't a file

13:23 (in a jar that is)

13:24 there might be a resource-response I guess

13:24 yeah, resource-response exists

13:24 https://github.com/ring-clojure/ring/blob/1.3.1/ring-core/src/ring/util/response.clj#L204

13:25 adgtl: justin_smith: thanks :)

13:26 mikerod: Is it reliable behavior that this works?

13:26 ,(keys (filter identity {:a 1 :b 2}))

13:26 clojurebot: (:b :a)

13:26 mikerod: The point being that `keys` accepts a seq-view of a map rather than needing to be an actual map

13:26 I understand that it works due to the impl of `keys` calling seq on the input coll anyways

13:27 However, that seems to just be an impl detail- not something I should rely on in the contract

13:27 so perhaps I should be doing:

13:27 ,(keys (into {} (filter identity {:a 1 :b 2})))

13:27 clojurebot: (:b :a)

13:28 justin_smith: mikerod: wait, what does filter identity even do for you here? or is that a placeholder for a real filter you would actually do?

13:28 mikerod: justin_smith: placeholder

13:28 oh sorry

13:28 (keys (seq {:a 1 :b 2}))

13:28 I should have kept it at a minimal, that was carry over

13:30 justin_smith: OK

13:32 noonian: seems like an implementation detail, can't even see that its calling seq since it delegates to RT but it implies it saying that they will be in the same order as (seq map)

13:33 mikerod: noonian: yeah...

13:33 I guess the doc string says the word "map"

13:33 so its probably best to only pass it a map..

13:34 there are plenty of places where a seq of MapEntry fails when map is expected

13:34 justin_smith: it's been mention by Hickey that seq, keys, and vals will use the same underlying ordering from a map

13:34 mikerod: justin_smith: yes, I've read those posts

13:34 justin_smith: OK

13:34 mikerod: I mean, I interpreted that that's just concerning the order. I didn't take away that that implied that keys and vals will accept seq's of maps instead of maps

13:35 I was just worried that the behavior (keys (seq {:a 1})) is not reliable and that I should do (keys (into {} (seq {:a 1})))

13:35 However, I'm guessing it is just a gray area. Wanted to know if anyone knew specifically that this was a good or bad idea.

13:36 noonian: yeah, just pass it a map to preserve warm and fuzzy feelings about your code

13:36 mikerod: I appreciate the feedback on the topic though.

13:36 justin_smith: I can't think of many ways "keys" could be implemented that wouldn't call seq on the map as its first step

13:36 s/many/any

13:37 mikerod: noonian: I try to shoot for writing something that will not be busted in a newer version of clj. So I worry when it comes down to just the RT impl of a function

13:37 justin_smith: yeah, that is true

13:37 it is "natural"

13:57 gfredericks: ,(def foo '''foo)

13:57 clojurebot: #'sandbox/foo

13:57 gfredericks: ,(nth (iterate eval foo) 42)

13:57 clojurebot: (quote (quote foo))

13:58 tbaldrid_: mikerod: I've heard it mentioned that (zipmap (keys mp) (vals mp)) is common enough that changing the seq order of keys vs vals would break a ton of code

13:58 I can't think of a reason that will change soon. It doesn't make sense from a language development standpoint, or from a technical standpoint.

13:59 So I'd say you're just fine doing (keys mp) and assuming that as long as mp doesn't change, the order of keys will stay the same

13:59 justin_smith: tbaldrid_: his issue was more specifically if keys would always work in the case of (keys (seq {:a 0})) which is a bit more esoteric a thing

13:59 gfredericks: hmm

13:59 tbaldrid_: that works at all?

13:59 triss: hi all. If I do a clojure.data/diff on something is there an easy way to get the paths to the locations in that something that have changed?

13:59 tbaldrid_: ,(keys (seq {1 2 3 4}))

13:59 clojurebot: (1 3)

13:59 gfredericks: what about a map with some internal mutability for performance (e.g., a lazy map)

13:59 tbaldrid_: eh...interesting

13:59 justin_smith: tbaldrid_: of course, because how would keys work without calling seq, or the equivalent, internally?

14:00 gfredericks: could conceivably change its ordering incidentally

14:00 now I'm curious if that lazy-map impl does this

14:00 tbaldrid_: gfredericks: sure, I'm only talking about the standard clojure impls. Other impls will have different characteristics

14:01 gfredericks: I just hadn't thought of this possibility before

14:01 tbaldrid_: justin_smith: yeah, I know it calls seq internall, I just didn't know it accepted a seq as well. That's interesting

14:01 justin_smith: tbaldrid_: well (seq (seq x)) will always work :)

14:01 if you know it calls seq, then passing a seq should work

14:02 but it is a bit uglier a thing to assume, of course

14:02 hiredman: tbaldrid_: the first time I heard rich say the keys order will always match the vals was sometime around '08 or '09, and he has repeatedly said that whenever someone (often stuart) jumps on someone for assuming that (zipmap (keys m) (vals m)) is safe

14:02 tbaldrid_: (inc hiredman)

14:02 lazybot: ⇒ 70

14:02 tbaldrid_: agreed

14:03 hiredman: so, like, I don't work with the man, but it seems pretty clear what his intentions are there at this point

14:04 tbaldrid_: mikerod: hiredman: here's what I'd consider the authoritative word, see 2nd to last comment by Rich http://dev.clojure.org/jira/browse/CLJ-1302

14:05 and as mentioned by hiredman the thread contains a bit of hand slapping by Stuart, followed by a bit of hand slapping by Rich ;-)

14:06 and I assume this is now in the docs?

14:06 ,(doc keys)

14:06 clojurebot: "([map]); Returns a sequence of the map's keys, in the same order as (seq map)."

14:14 mikerod: tbaldrid_: yes, the surprise to me was that (keys (seq {:a 1})) works

14:14 specifically because I passed it a seq, not a map

14:15 I understand the impl and why it works. I just wanted to know if it was intentionally accepting seq's or just an internal detail where we get lucky

14:15 I also have followed that seq == keys == vals

14:15 and I think that is an important property that I hope doesn't change since it is nice to use in zipmap etc

14:15 My concerns were just that most functions that are meant for maps do not interchangeably accept maps-as-seqs

14:16 but due to keys and vals impl, they do accept this

14:16 it was mostly a curiosity thing. I thought I should have gotten some sort of cast exception when I did a (keys (filter ... {:a 1})) earlier and I was surprised to see that it Just Works.

14:20 gfredericks: that stuff is all over clojure

14:20 ,(deliver +)

14:20 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core/deliver>

14:20 gfredericks: ,(deliver + 42)

14:20 clojurebot: 42

14:21 gfredericks: I wish I knew how rich felt about that sort of thing

14:21 difficilt to tell what's intentional and what's accidental

14:21 justin_smith: ,(deliver (get get get get) get)

14:21 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core/get>

14:22 justin_smith: oops!

14:22 hiredman: rich likes to call behavior undefined, but it is hard to tell where that line is

14:22 gfredericks: but that certainly seems like "undefined" behaviour

14:24 gfredericks: seems like a weird thing to value

14:25 like I'm not sure if the goal is simplest-possible-impl (where checks are clutterful) or fastest-possible (where checks are expensive) or preserving current behavior or ...

14:27 amalloy: gfredericks: i actually mentioned the fact that (deliver f x) is just (f x) at clojure/west, talking to reiddraper and rich at dinner, and he said if you rely on that working you deserve what you get, or something to that effect

14:27 hiredman: "undefined"

14:27 gfredericks: that doesn't make it not worth changing though

14:27 it's not just a question of relying on it working it's a question of how mistakes manifest

14:28 and when stuff is implemented in this style, failure behavior is a lot messier

14:29 justin_smith: yeah, I am sure I have code that "works by accident"

14:29 amalloy: gfredericks: like what?

14:30 gfredericks: amalloy: like if I pass a function to deliver instead of the promise I meant to, the function gets called and something weirder happens rather than the straightforward "can't deliver a not-a-promise" exception

14:30 where "something weirder" could be virtually anything

14:30 clojure.lang.CannotDeliverANotAPromiseException

14:31 justin_smith: amalloy: gfredericks: or a practical example, someone not long ago had (:or x y) - which is kind of like or, but it always picks why

14:31 err, always pick y, that is

14:31 gfredericks: clojure.lang.problems.concurrency.promises.impl.NotOneException

14:31 justin_smith: which is a simple typo, but it can pass unit tests

14:31 amalloy: gfredericks: you just made me think of something. java.lang.IllegalStateException is cool, but clojure needs a clojure.lang.StateIllegalException because state is illegal

14:32 justin_smith: haha

14:32 andyf: gfredericks: Dynalint ?

14:32 gfredericks: thrown when you do (atom (agent nil))

14:32 hiredman: what are you, some kind of crypto ml loving type fetishist?

14:32 gfredericks: andyf: yeah that's a reasonable approach

14:33 ,(nth (iterate agent nil) 10)

14:33 andyf: Not sure how big dynalint's performance overhead is

14:33 clojurebot: #<Agent@31443ae7: #<Agent@76772cf5: #<Agent@a28c596: #<Agent@7ac4000f: #<Agent@59e017c0: #<Agent@7376c59: #<Agent@47aa4ac2: #<Agent@7d122b4f: #<Agent@33d98faf: #<Agent@106844c1: nil>>>>>>>>>>

14:33 amalloy: gfredericks: or (filter #(zero? (swap! some-atom + %)) xs)

14:34 mikerod: I definitely agree I'd like to hear thoughts from Rich on these weird behaviors due to impl issues

14:34 I often wonder why a little sanity checking isn't done by functions - if it doesn't cost a lot in terms of performance

14:35 amalloy: mikerod: i imagine it's because it does cost a lot

14:35 gfredericks: would be cool if it were standard to add metadata to vars about things that could be dynalinted

14:35 amalloy: the core language functions get called all the time, including in implementing other core functions

14:35 gfredericks: and then just turn those on in tests or whatevs

14:35 mikerod: A related question, does anyone know why it'd be a Good Thing to have keywords look themselves up in anything - returning nil if it doesn't make sense?

14:35 amalloy: I suppose that's fair

14:35 gfredericks: ,(:mikerod-like-this? 42)

14:35 clojurebot: nil

14:36 mikerod: gfredericks: yes

14:36 that is a great way to hide a bug

14:36 justin_smith: mikerod: it's just invoking get

14:36 andyf: gfredericks: Create a technique that becomes de facto standard?

14:36 justin_smith: and get is just super easy going about args

14:36 mikerod: justin_smith: oh good point I forgot it is get to blame

14:36 justin_smith: ,((get get get get) {get get} get)

14:36 clojurebot: #<core$get clojure.core$get@4f478df8>

14:37 mikerod: :P

14:37 amalloy: justin_smith: it actually doesn't call get unless it has to

14:37 justin_smith: amalloy: oh?

14:37 amalloy: it prefers to call (.valAt obj this) when possible

14:37 if obj is an instance of ILookup

14:38 justin_smith: ok - but we can still blame get for the fallback

14:38 gfredericks: andyf: just a :dynalint key in the metadata could be interesting

14:38 mikerod: yeah

14:38 amalloy: i guess that's true

14:38 gfredericks: :dynalint/pre, :dynalint/post

14:39 andyf: Alter-var-root is calling ...

14:39 mikerod: what about this

14:39 ,(let [x nil] (x))

14:39 clojurebot: #<NullPointerException java.lang.NullPointerException>

14:39 mikerod: What is not being checked there

14:39 amalloy: i mean, i hear you guys talking about all these checks for various different kinds of errors that could happen at runtime and clojure makes weird choices about what happens in situations that shouldn't happen, and it's like...wouldn't it be great if we had static types?

14:39 mikerod: huh? what else could happen besides a NPE? a wrapper around NPE that says "you tried to call a function, dummy"?

14:39 andyf: ~guards

14:39 clojurebot: SEIZE HIM!

14:39 amalloy: er, tried to call nil as a function

14:40 gfredericks: amalloy: ##(nil)

14:40 lazybot: java.lang.IllegalArgumentException: Can't call nil

14:40 amalloy: andyf: i *am* the guards

14:40 hiredman: clojurebot: static types is <reply>what are you, some kind of crypto ml loving type fetishist?

14:40 clojurebot: Gabh mo leithscéal?

14:40 hiredman: clojurebot: static types is <reply>what are you, some kind of crypto ml loving type fetishist

14:40 clojurebot: c'est bon!

14:40 andyf: I know :)

14:40 mikerod: amalloy: yeah, I know. I'm not really necessarily "complaining", I just am always curious when stumbling across these weird behaviors that tend to be trouble.

14:40 gfredericks: yes

14:40 amalloy: i know you know, et cetera

14:40 mikerod: gfredericks: I like how it catches a direct call to nil, but not an indirect call. Nil checks are highly performant I believe?

14:40 amalloy: gfredericks: (nil) is just the weirdest special case in the world. i don't know why you'd bother

14:40 mikerod: not as performant as omitting them

14:41 andyf: ~amalloy

14:41 clojurebot: amalloy only uses locally sourced, free range electrons

14:41 mikerod: amalloy: haha fair enough..

14:41 amalloy: and if you checked for nil on *every* function call the language would slow down by like, jeez i dunno, 100%

14:42 mikerod: Java code tends to nil check about 50% of the codebase

14:42 amalloy: more realistically it's probably like 20%, but that is still a lot

14:42 mikerod: I mean spend 50% nil checking

14:42 *of lines of code* - so lots of them is the point

14:43 I do like how clj code rarely has to be worried about nil, so I shouldn't complain

14:43 gfredericks: amalloy: I bet it bothers with (nil) because it might have to be a special case in the compiler regardless

14:43 mikerod: just don't try to call it as a function :)

14:43 TMA: and -- by my experience -- testing for nils is faster than catching the NPE

14:44 amalloy: TMA: the idea is that if you're calling nil as a function you are pretty much screwed anyway, whether you check it or not, so performance in that case isn't terribly important

14:44 TMA: ,((:foo 42))

14:44 amalloy: might as well optimize for the non-mistake

14:44 clojurebot: #<NullPointerException java.lang.NullPointerException>

14:44 hiredman: gfredericks: I bet someone was writing a macro that emitted (nil) and they complained very loudly when they couldn't figure out why their macro was being dumb

14:45 amalloy: gfredericks: nope

14:45 Bronsa: ,(.invoke nil)

14:45 clojurebot: #<NullPointerException java.lang.NullPointerException>

14:46 amalloy: https://github.com/clojure/clojure/commit/a4f923670d89fd7f4d72f39ec85ec8f46ea43bdc#diff-f17f860d14163523f1e1308ece478ddbL4063

14:46 is the only time in the entire codebase that "can't call nil" was touched, and it really does not look to me like a special case that needed to be handled anyway

14:47 justin_smith: everyone's all like "damn clojure doesn't static check any of this" and amalloy's like "hey that one thing it does check - it really shouldn't need to"

14:47 amalloy: justin_smith: man i wish it would check a ton of things

14:47 but this is the dumbest thing to check

14:49 mikerod: I've had it thrown on me a few times before, and I was like "wow, that was surprisingly descriptive of an error message"

14:49 Where is my NPE at

14:54 TMA: ,(defmacro foo-macro [] `(~(:foo 42) 1 2)))

14:54 clojurebot: #'sandbox/foo-macro

14:54 TMA: ,(macroexpand '(foo-macro))

14:54 clojurebot: (foo-macro)

14:54 TMA: ,(macroexpand '(sandbox/foo-macro))

14:54 clojurebot: (sandbox/foo-macro)

14:55 TMA: (fn [] (foo-macro))

14:55 ,(fn [] (foo-macro))

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

14:59 TEttinger: ,(defmacro foo-macro [] `(~(:foo 42) 1 2)))

14:59 clojurebot: #'sandbox/foo-macro

14:59 TEttinger: ,(fn [] (foo-macro))

14:59 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Can't call nil, compiling:(NO_SOURCE_PATH:0:0)>

15:00 TEttinger: ,(macroexpand-1 foo-macro)

15:00 clojurebot: #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'sandbox/foo-macro, compiling:(NO_SOURCE_PATH:0:0)>

15:00 TEttinger: ,(macroexpand-1 'foo-macro)

15:00 clojurebot: foo-macro

15:00 TEttinger: gah

15:00 ,(macroexpand-1 #'foo-macro)

15:00 clojurebot: #'sandbox/foo-macro

15:01 Bronsa: TEttinger what'd you expect that to do?

15:01 TEttinger: ,(macroexpand-1 (foo-macro))

15:01 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Can't call nil, compiling:(NO_SOURCE_PATH:0:0)>

15:01 TEttinger: I have no idea how macros work Bronsa

15:01 TMA: ,(macroexpand-1 '(foo-macro))

15:01 clojurebot: (nil 1 2)

15:01 TEttinger: ah!

15:02 kaplan: I still don't understand macros

15:04 TMA: based on the conversation with clojurebot, the check could be for the benefit of macros -- a buggy macro might easily place nil into function position

15:05 TimMc: kaplan: Macros are just functions that the compiler calls.

15:06 When the compiler sees the name of a macro in call position, it calls the macro and hands it the pile of lists and symbols and whatnot that are in the arg positions.

15:06 The function returns replacement code and things go on from there.

15:17 gfredericks: andyf: you made me try dynalint and I discovered that lein-dynalint has been broken for probably a year at least

15:17 these are exciting times we live in

15:21 running dynalint on my work project yielded 7 warnings, 2 of them caused by leiningen code and the other five by pomegranate (which is called by leiningen)

15:21 actually that makes me suspect it's only linting leiningen and not my project

15:22 justin_smith: gfredericks: is it meant to be called as a plugin or from within your project as a dep?

15:23 gfredericks: lein-dynalint claims you should put lein-dynalint and dynalint as plugins in your project and then call `lein dynalint test`

15:23 looking at the source code it does indeed look like it just lints the leiningen jvm and then runs your tests

15:24 I swear it must be nobody has ever used this before

15:24 justin_smith: haha

15:24 andyf: gfredericks: I haven't used dynalint's for about that long, and it was only an experiment on my part then. Haven't followed it closely.

15:26 gfredericks: no wonder it claimed you should add dynalint as a plugin dep instead of a normal dep

15:41 vas: so I have a (GET "/session" [ req ] (str "request map is " req))

15:42 in a defroutes.. it was working earlier, but suddenly it no longer spits out the request map

15:42 any ideas?

15:42 justin_smith: vas: what does it give you instead?

15:42 vas: just the leading text, in that example "request map is "

15:43 as if req was a blank

15:43 justin_smith: perhaps some middleware is messing with the request? but clearly enough was there to lead to your handler function

15:43 try replacing req above with (pr-str req)

15:43 that may print nil, or ""

15:44 bdruth: Good afternoon

15:45 I'm having a strange issue with destructuring a map

15:45 it's a data structure returned from another component

15:45 and the first key looks like this: :us-east-1/i-824af2e4

15:46 justin_smith: and how do you destructure that?

15:46 JimKet: anybody here know anything about octopushub?

15:46 amalloy: ~anyone

15:46 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

15:46 bdruth: well, it seems like it's not wanting to use this in get-in or (<map> key) forms

15:46 hold on though, I just noticed something with the level of the key

15:46 sec

15:46 justin_smith: bdruth: can you use refheap to show us the results of (keys m) (where m is the data you get)

15:47 bdruth: oh, damn - yeah - I'm good

15:47 vas: justin_smith: thanks for the suggestion for pr-str. it now returns the lead up string followed by ... nil

15:47 bdruth: it was doubly nested, sorry for the noise

15:47 I latched on to the '/' in the key and thought there would be a problem with that

15:47 justin_smith: vas: maybe a broken middleware is swallowing the actual request? perhaps an if with only one branch in a custom middleware?

15:48 JimKet: hrmmm, well in that case, octopushub seems to be logging one of my channels, and looks as though it's logging yours as well

15:48 curiosity is getting the better of me and I was wondering if anybody had details regarding the site

15:49 justin_smith: JimKet: I have noticed that before - I don't know what their deal is

15:50 they are scraping irc channels and putting it in hidden pages

15:50 TimMc: amalloy: This is that weird-ass site you pointed out the other day, it's not a clojure lib. :-P

15:50 justin_smith: JimKet: my guess is SEO for their frequent updates

15:50 JimKet: yeah, our nicks are showing up all over google searches

15:50 justin_smith: oh, yeah, amalloy pointed that site out

15:51 octopushub.org, not to be confused with octopushub.com (a tennis shop)

15:53 JimKet: their whois shows a valid email address you could contact

15:53 TimMc: JimKet: Is it actively adding to any entries?

15:54 If you can predict who it will log, you could poison its log with an entry that would kill its SEO.

15:54 justin_smith: it was first created the 23rd of january

15:54 vas: justin_smith: hey i got it working again checking my git diffs (thank gitness)... although I don't know why it works

15:54 justin_smith: TimMc: oh, excellent point

15:54 vas: can you describe the difference?

15:54 TimMc: I haven't looked into it, but there should be documentation on what Google really hates to find on sites.

15:55 vas: (GET "/session" [ ph-auth-token :as req ] (str "the request map looks like " req))

15:55 justin_smith: TimMc: links to known crappy sites

15:55 TimMc: I think it's robust enough not to render HTML, though.

15:55 vas: i was under the impression that using :as just made the whole argument vector into whatever you name it... i guess pulling one value out of it does some sort of magic?

15:56 justin_smith: vas: compojure destructuring sometimes confuses me

15:56 TimMc: hmm

15:56 ,(let [[:as n] 6] n)

15:56 clojurebot: 6

15:56 vas: oh right. it's compojure stuff.

15:57 justin_smith: vas: (GET "/session" [req] ...) looks for a key called req in the request

15:57 vas: well, i'll have to remember that trick in case someone else needs it in the future

15:57 Ahaaaa. makes sense

15:57 justin_smith: vas: well, not to me, but OK :)

15:57 vas: haha SE

15:57 :D*

15:57 programmer dvorak lol

15:57 Bronsa: ,(let [[:as [:as [:as [:as n]]]] 6] n)

15:57 clojurebot: 6

15:57 justin_smith: if you instead specify {{token :ph-auth-token} :as request} that should bind token to your token, and also allow access to the whole thing as "request"

15:58 Bronsa: what got me here was that [foo] would mean {:keys [foo]}

15:59 (in compojure-land)

15:59 TimMc: Bronsa: :-D

15:59 justin_smith: well - actually [foo] means {{foo :foo} :params} I guess?

16:00 vas: https://github.com/weavejester/compojure/wiki/Destructuring-Syntax

16:01 Bronsa: also, that is wacky

16:01 (inc Bronsa)

16:01 lazybot: ⇒ 93

16:02 TimMc: ,(let [{:keys [a] :as {:keys [b] :as {:keys [c]}}} {:a 1 :b 2 :c 3}] [a b c])

16:02 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Bad binding form, expected symbol, got: {:keys [b], :as {:keys [c]}}, compiling:(NO_SOURCE_PATH:0:0)>

16:29 arrdem: hyPiRion: ping

17:25 atratus: theres no way to run clojure on squawk right? gotta have reflection?

17:26 I just left a debug session with a FIRST robotics team....felt so bad for those kids geez

17:27 TimMc: Oh hey, FIRST.

17:28 I did that in... 2000-ish?

17:28 atratus: well the code hasnt changed lol

17:30 TimMc: I somehow ended up with our second-place medal. I should find out if there's still a Charlottesville/Albemarle Robotics Team to return it to.

17:32 Oh yeah, there they are! http://www.carobotics.org/

17:32 team 619

17:38 or maybe each team member got a medal, and there was a lexan award thingum for the whole team?

17:40 turbofail: ha. i was in team 192

17:41 i wasn't a programmer back then though, i used a hacksaw and various machine tools

17:41 noonian: hacksaw programming

17:41 TimMc: I didn't do any of the programming, just design and strategy.

17:41 It worked out pretty well.

17:42 atratus: wasn't on team, but wish I was. didnt get programming bug until college. volunteering now though

17:43 http://first.wpi.edu/Images/CMS/First/Getting_Started_with_Java_for_FRC.pdf

17:44 based on java 1.3 so probably screwed

17:47 TimMc: Ours was a forklift design that could cantilever its battery and control board out the back as a counterweight.

17:50 "2001 - Diabolical Dynamics"

18:05 hyPiRion: arrdem: pong

18:10 hiredman: tbaldrid_: pixie doesn't have chunked seqs, does it?

18:11 tbaldrid_: hiredman: no, mostly because I think I can optimize seqs away via the JIT. If I fail in that area, I may add chunked seqs in

18:11 I really don't like chunked seqs, so I hope to keep them out

18:12 hiredman: good on you

18:15 TimMc: &(map (comp count #(`[{~@%~@%}](+))) (map range (range 20)))

18:15 lazybot: ⇒ (0 1 1 3 2 5 3 7 4 9 5 11 6 13 7 15 8 17 9 19)

18:20 TimMc: &(apply map vector (partition 2 (map (comp count #(`[{~@%~@%}](+))) (map range (range 20)))))

18:20 lazybot: ⇒ ([0 1 2 3 4 5 6 7 8 9] [1 3 5 7 9 11 13 15 17 19])

18:21 amalloy: TimMc: that first one was a real fibonacci disappointment

18:22 0 1 1 3 2 5 too cruel

18:22 __number5__: what '#(`[{~@%~@%}](+))' supposed to do?

18:23 amalloy: __number5__: supposed to look confusing

18:23 __number5__: @_@

18:23 &(doc apply)

18:24 lazybot: ⇒ "([f args] [f x args] [f x y args] [f x y z args] [f a b c d & args]); Applies fn f to the argument list formed by prepending intervening arguments to args."

18:24 TimMc: __number5__: In normal Clojure, that would be (fn [& args] (apply hash-map (concat args args))) which is already pretty useless.

18:24 amalloy: yeah i was trying to figure out why you were making that map

18:24 it looks like a way to get to second

18:25 justin_smith: ,'#(`[{~@%~@%}](+))

18:25 clojurebot: (fn* [p1__25#] ((clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list (clojure.core/apply clojure.core/hash-map (clojure.core/seq (clojure.core/concat p1__25# p1__25#))))))) (+)))

18:25 TimMc: __number5__: Basically I'm just playing around with obfuscated code. http://hypirion.com/swearjure

18:26 __number5__: TimMc: cool. nice name btw

18:27 AeroNotix: what are people using for a clojurescript repl?

18:27 justin_smith: __number5__: also, there's a #clojure-beginners channel, which can be useful when everyone here is distracted with compiler stuff or weird parts of the language that are hardly ever used

18:28 srruby: I've got a small web service I'm writing in Clojure/compojure. It has to run on port 80. Can anyone recommend how to configure nginx ?

18:28 justin_smith: srruby: should be the same as any other reverse-proxy scenario - you have nginx run on port 80, and forward the port that the clojure process serves on

18:29 AeroNotix: Do you need nginx?

18:29 justin_smith: AeroNotix: better than running the jvm as root

18:29 __number5__: justin_smith: thanks, guess the beginner channel suits me better :P

18:30 justin_smith: AeroNotix: normal user processes can't serve on port 80

18:30 AeroNotix: justin_smith: I know

18:30 justin_smith: __number5__: not saying you aren't welcome here though

18:30 AeroNotix: justin_smith: depends what you're doing. I typically just run stuff behind an ELB on EC2.

18:30 justin_smith: AeroNotix: also, nginx has security stuff that most of the jvm web servers lack

18:30 AeroNotix: but that's cause I'm not paying :)

18:30 justin_smith: :)

18:30 srruby: justin_smith: Thanks

18:33 {blake}: Crap...there's a #clojure-beginners channel? heh

18:35 justin_smith: {blake}: it's a fairly recent invention

18:35 brainproxy: justin_smith: you could run it non-root in a docker container and map 80 to the non-priv'd port

18:35 i.e. as an alternative to putting nginx in front of it

18:35 justin_smith: brainproxy: but you'd want nginx for security reasons anyway

18:36 brainproxy: sure, it's generally a good idea to put a hardened http proxy in front of jvm, node, etc.

18:37 nginx, varnish, haproxy, traffic server -- lots of options

18:37 {blake}: justin_smith: Oh. Wait, like last week recent? =P

18:38 justin_smith: {blake}: yeah, seancorfield set it up iirc

18:39 {blake}: justin_smith: OK. *phew*

18:47 ambrosebs: sanity check: it's impossible to construct a value with `new` that is false?

18:48 TimMc: ,(remove #(re-find #"[a-zA-Z0-9]" (name %)) (keys (ns-publics 'clojure.core)))

18:48 clojurebot: (+' = < .. <= ...)

18:49 noonian: I hope so. Rich Hickey made a comment in one of his talks about new Boolean being wrong but still having to check for it because some java classes do it.

18:49 TimMc: ambrosebs: No. :-(

18:49 Well... let's see.

18:50 ,(boolean (Boolean. false))

18:50 clojurebot: false

18:50 amalloy: well. (new Boolean "false") evaluates as truthy

18:50 doesn' it? i thought it did

18:50 Bronsa: ambrosebs: if you mean that (if (new ..) 1 2) will _never_ return 2, that's correct

18:50 ambrosebs: the invariant I'm claiming is (if (new ...) 1 2) always returns 1

18:50 noonian: (or (Boolean. false) true)

18:50 ,(or (Boolean. false) true)

18:50 clojurebot: false

18:50 ambrosebs: :)

18:50 Bronsa: yes that's it.

18:50 AeroNotix: ,(Boolean false)

18:50 clojurebot: #<RuntimeException java.lang.RuntimeException: Expecting var, but Boolean is mapped to class java.lang.Boolean>

18:51 amalloy: ambrosebs: yes, i believe that invariant holds

18:51 TimMc: ,(if (new Boolean false) 1 2)

18:51 clojurebot: 1

18:51 noonian: ,(Boolean. false)

18:51 clojurebot: false

18:51 noonian: ,(identical? (Boolean. false) false)

18:51 clojurebot: false

18:51 ambrosebs: amalloy: thanks

18:51 noonian: ,(= (Boolean. false) false)

18:51 clojurebot: true

18:51 TimMc: Ah, so if does not use the same coercion.

18:52 amalloy: TimMc: right, (if x y z) doesn't call boolean

18:52 TimMc: ,(identical? (boolean (Boolean. false)) false)

18:52 clojurebot: true

18:52 AeroNotix: ,(Boolean. false)

18:52 clojurebot: false

18:52 amalloy: it compares to nil and to Boolean/FALSE

18:52 AeroNotix: I feel like this comes up every week or so

18:52 TimMc: Interesting choice.

18:52 AeroNotix: should be in the tpic

18:53 topic

18:53 amalloy: well actually i guess that's not the relevant point

18:53 the point is that the return value of RT/booleanCast is autoboxed for you, when you call boolean, and that uses the canonical boxing method

18:56 TimMc: &(filter #(re-find #"'$" (name %)) (keys (ns-publics 'clojure.core)))

18:56 lazybot: java.lang.SecurityException: You tripped the alarm! ns-publics is bad!

18:56 TimMc: ,(filter #(re-find #"'$" (name %)) (keys (ns-publics 'clojure.core)))

18:56 clojurebot: (+' dec' inc' -' *')

18:57 TimMc: Is it unreasonable that I am annoyed at /' not existing?

19:05 justin_smith: ,(/ 1 (/ 1 1000000000))

19:05 clojurebot: 1000000000N

19:06 justin_smith: it already auto-promotes

19:06 in some contexts at least

19:15 TimMc: Funky.

19:16 Did someone make a mistake and forget to make it not autopromote?

19:16 justin_smith: I think it's down to the fact that rational would auto-promote

19:16 hehe

19:16 TimMc: Oh, I see.

19:16 justin_smith: it's already anti-optimized due to rationals, so yeah

19:17 oh, I didn't even need to try a "large" number ##(/ 1 (/ 1 2))

19:17 amalloy: justin_smith: pessimized

19:17 lazybot: ⇒ 2N

19:17 justin_smith: amalloy: of course

19:18 (inc amalloy)

19:18 lazybot: ⇒ 227

19:24 TimMc: (I'm still trying to figure out if we can get floats in swearjure.)

19:48 hlprmnky: is it a known/expected thing that running 'lein uberjar' in a project that's using tools.namespace to have a reloaded-ized REPL experience, breaks said REPL experience until you run 'lein clean'?

19:49 amalloy: ~aot

19:49 clojurebot: http://i.qkme.me/3vb225.jpg

19:49 amalloy: well, not what i was expecting, but pretty on-topic i guess

19:49 ~aot

19:49 clojurebot: aot was so ahead of its time

19:50 hlprmnky: so the fact that some things are being aot-compiled by the uberjar profile leaves stuff in a state that (reset) doesn't like

19:50 ?

19:50 amalloy: probably

19:50 hlprmnky: I can live with that as long as it's not Something Bad I Did™

19:51 amalloy: i am not a big fan of either clojure.tools.namespace's reload mechanism or of AOT, but i am pretty sure that using them both together would cause issues

19:51 hlprmnky: and I thought I'd ask, after Googling to little effect and before trying to build a pastebin-able test case

20:03 zacts: xb

20:08 amalloy: zacts: TooMuchEmacsException

20:10 zacts: lol

20:14 SegFaultAX: Is it possible to exclude a single dependency from your uberjar?

20:15 (That dependency will already be on the cp of the target system)

20:15 justin_smith: SegFaultAX: https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L388

20:15 SegFaultAX: that document is the Holy Scripture that answers all lein questions that can be answered

20:16 amalloy: hm, is that really the way to do it? i'd try to find an equivalent to mvn's scope=provided

20:16 justin_smith: hmm

20:16 SegFaultAX: justin_smith: Sure, but I'm not clear how to do that for a dependency. #"foodependency.*.jar"

20:17 amalloy: it looks like lein knows something about :provided

20:17 justin_smith: SegFaultAX: maybe put the dep under your :dev profile but not your main profile?

20:17 SegFaultAX: The actual problem is: Storm ensures that the storm libraries will be on the CP for each worker, and expects you to use that rather than bundling it yourself.

20:17 amalloy: justin_smith: that's another plausible solution

20:17 justin_smith: amalloy: woah, if it does, that is missing from the sample project.clj and should be added

20:17 SegFaultAX: Oh, that's a good one.

20:18 :dev would be sufficient probably.

20:18 amalloy: looking through lein source, it looks like you want a profile named :provided

20:18 justin_smith: amalloy: SegFaultAX: yeah, having it under :dev only would match how we handle eg. the embedded jetty server when deploying a war file

20:19 amalloy: interesting, if that really works we should add it to the sample project.clj

20:19 SegFaultAX: amalloy: Mind sharing where you found that?

20:19 amalloy: SegFaultAX: cd leiningen && find . -name '*.clj' -type f -exec grep -nH -Pie 'provided' {} +

20:21 that puts it into the pom as provided, but i'm not sure yet whether that's actually what you want

20:22 SegFaultAX: amalloy: Thanks.

20:22 amalloy: it seems to put it on the classpath when in dev and not when in uberjar context

20:22 so probably yes

20:24 SegFaultAX: TIL: pom-scope

20:27 (Which is the only interesting configuration that profile has)

20:33 gfredericks: I think I might be in macro hell.

20:35 * gfredericks tries to figure out what he can do with the vals of &env

20:35 justin_smith: gfredericks: sure way to check - are there demons throwing ` / ~ / ~@ at the sexprs of the damned?

20:35 gfredericks: oh yeah lots of that

20:36 {blake}: The & is the universal sign of the demon. At least in the Nethack universe.

20:36 justin_smith: "sexprs of the damned" is my next band name, btw

20:36 {blake}: it's true

20:36 &env is a major demon, hanging out with an eye, a nymph, and a vortex

20:36 lazybot: java.lang.RuntimeException: Unable to resolve symbol: env in this context

20:36 amalloy: gfredericks: do nothing with the vals of &env srsly

20:36 justin_smith: haha

20:37 e / v are usually easy to deal with, but an &n gangup can be bad bad news

20:37 amalloy: justin_smith: pandemonium lord, elf, uh...necrophage i guess, and an insubstantial wisp

20:38 gfredericks: amalloy: man all I wanna know is what kind of locals get introduced by a thing :/

20:38 amalloy: <3 DCSS

20:38 justin_smith: amalloy: stone soup?

20:38 amalloy: gfredericks: isn't that just keys of &env? do you need their types?

20:38 gfredericks: amalloy: ideally would detect shadowing

20:39 amalloy: justin_smith: yeah, i've been playing since august-ish

20:40 gfredericks: I could make a macro that stores some thread local state and expands to another macro that reads it. That would only be completely awful, right?

20:40 SegFaultAX: justin_smith: I've been playing for 2 weeks!

20:40 amalloy: gfredericks: what on earth are you doing

20:41 TimMc: Trying to write fizzbuzz, no doubt.

20:41 justin_smith: gfredericks: wait, &env is locals? I thought it was a map you had to explicitly access

20:41 amalloy: justin_smith: &env is the lexical environment into which the macro is being expanded

20:42 justin_smith: amalloy: oh, OK then, I thought it was more limited than that

20:42 amalloy: ,(defmacro m [] `(list ~@(keys &env)))

20:42 clojurebot: #'sandbox/m

20:42 amalloy: ,(let [x 1 y 2] (m))

20:42 clojurebot: (2 1)

20:42 TimMc: (defmacro n [] `(list ~@(m)))

20:43 ,(defmacro n [] `(list ~@(m)))

20:43 clojurebot: #'sandbox/n

20:43 TimMc: ,(n)

20:43 clojurebot: #<CompilerException java.lang.StackOverflowError, compiling:(NO_SOURCE_PATH:0:0)>

20:43 TimMc: uh... OK.

20:44 amalloy: ,(defmacro m' [] (into {} (for [k (keys &env)] `['~k ~k])))

20:44 clojurebot: #'sandbox/m'

20:44 amalloy: ,(let [x 1 y 2] (m'))

20:44 clojurebot: {y 2, x 1}

20:49 gfredericks: amalloy: https://github.com/gfredericks/test.chuck/pull/7

20:49 trying to find an alternative to filtering symbols based on whether or not they look like gensyms

20:52 the only other idea is basically reimplementing all the destructuring logic

20:52 amalloy: gfredericks: are you sure you want to be calling destructure by hand? like, can't you just bind once per non-keyword and then use let?

20:52 gfredericks: do what per who?

20:53 amalloy: gfredericks: this is for something like (for-all [x xs, [a b c] x] ...)?

20:53 gfredericks: I don't *want* to be calling destructure by hand that's for sure

20:53 yeah

20:53 amalloy: and at some point do you have need to access a, other than for making it available to the body of the for-all?

20:53 the answer to that seems like it ought to be no

20:53 gfredericks: except that it's yes

20:54 this is for reporting what things were generated

20:54 and maybe your example is bad

20:54 (for-all [x (gen-an-x), [a b c] (gen-something-with x)] ...)

20:55 so both x and a b c are relevant to reporting a test failure

20:55 you might argue that I should just report [a b c] as an atomic value

20:55 amalloy: yes

20:55 i was just typing that

20:55 gfredericks: but the allowable syntax gets more complicated

20:55 this strategy works for test.check's builtin for-all

20:56 the failure gets reported as [x [a b c]], and it's easy to figure out what's what

20:56 but test.chuck's for-all can e.g., have clauses like (for-all [:parallel [x1 (gen-an-x), x2 (gen-an-x)], [a b c] (gen-some-abcs-with x1 x2)])

20:57 and then the positionality starts to be more confusing

20:57 that's the most complicated element at the moment but I've been noodling another feature that would have similar issues

20:58 amalloy: what is this parallel baloney?

20:58 gfredericks: sugar for gen/tuple

20:58 amalloy: that looks like vinegar, not sugar

20:58 but i guess it's a matter of taste, har har

20:59 gfredericks: (for-all [[x1 x2] (gen/tuple (gen-an-x) (gen-an-x)), ...] ...)

20:59 cfleming: I'm having a problem with thread-local bindings after upgrading from 1.5.1 to 1.7.0-alpha5

20:59 gfredericks: ^ you don't have the bindings next to the generators that way

20:59 so in all but the simplest cases it can be a lot harder to read

20:59 cfleming: This is for the Cursive Leiningen integration

20:59 amalloy: gfredericks: mmm, okay, i can see how that might be nice. i would address it by writing [x1 x2] [(gen-x1) RET (gen-x2)] but okay

21:00 cfleming: When lein loads wagon plugins, it calls eval on a file that it fishes out of the wagon jar

21:00 gfredericks: amalloy: that looks like syntactic hot dogs

21:01 cfleming: I bind the thread local classloader and Compiler/LOCAL to a new DynamicClassLoader before calling into lein, and that's always worked until now.

21:01 Now it can't find one of the classes that should be present in that classloader, and indeed the classloader bound to LOADER is switched at some point.

21:02 Does anyone know of any changes in recent clojure versions that might affect this?

21:03 I think eval creates a new classloader for each evaluation, but I assume it did that in 1.5.1 too.

21:10 TimMc: ,(defmacro env [] (vec (map name (keys &env))))

21:10 clojurebot: #'sandbox/env

21:10 TimMc: ,(defmacro subject [] (env))

21:10 clojurebot: #'sandbox/subject

21:10 TimMc: ,(subject)

21:10 clojurebot: ["&env" "&form"]

21:10 gfredericks: welp it works https://www.refheap.com/97457 TimMc amalloy justin_smith

21:11 I made it anaphoric because while you're writing a side-effecting macro you might as well also do that

21:11 I guess this will fail if you use let' in the binding expressions, but I just thought of a way to fix that

21:12 I probably won't bother because I can't imagine I will actually use this

21:12 julianleviston: for cursive do I need to have the .idea/workspace.xml file checked in to my CVS?

21:12 cfleming: julianleviston: No, it's better not to - that changes all the time and contains things like window placement and so on.

21:13 amalloy: gfredericks: ThreadLocal has a constructor where you can pass it a thunk to use to generate a fresh copy

21:13 or something like that

21:13 gfredericks: amalloy: is that useful here?

21:13 julianleviston: cfleming: Cool. I looked at its contents before and it seemed that that was what it was for. I’ll gitignore it. Ta!

21:13 amalloy: gfredericks: well you'd never have to worry about the-env being nil and then setting it to {}

21:13 gfredericks: that's not why {} is there

21:14 I *want* it to be nil normally that's how I can tell the macro is being called the first time versus the second time

21:14 julianleviston: cfleming: might be a good idea to add this to the website. I had a look there first, but didn’t find it.

21:14 gfredericks: {} is there because &env is nil apparently instead of {}

21:14 which ruins my flag

21:14 cfleming: julianleviston: Good idea, I'll do that

21:14 gfredericks: I mean I could set the-env to default to something else like ::nope, either way

21:15 julianleviston: cfleming: one more thing for your extremely light workload ;-)

21:15 cfleming: julianleviston: I'll add it to a list somewhere :)

21:16 amalloy: gfredericks: so wait, you still get the vec__x thing here. how is this better than using destructure, then?

21:16 gfredericks: amalloy: in fact if I were to solve the called-in-the-bindings-expr-as-well problem I'd probably just quit using a ThreadLocal and make a global atom

21:16 amalloy: with destructure I get a totally different gensym and compile fails

21:16 this time it's the right gensym

21:17 amalloy: huh? what do you mean, a different gensym?

21:17 gfredericks: I'm calling it and the compiler is calling it

21:17 amalloy: no, don't let the compiler call it

21:17 * gfredericks hmms a lot

21:18 amalloy: just let the destructured stuff yourself

21:18 gfredericks: that sounds best if I can make it fit in this macro, gotta think it through

21:19 it's definitely possible but it's not as trivial is you'd suspect

21:19 to the point where I'm still wanting something cleaner

21:20 amalloy: gfredericks: https://www.refheap.com/2e4a14d4331ea0918bfb57e4a

21:20 (let' [[a b] (range)] &lettings) ;=> (vec__2198 a b)

21:21 gfredericks: amalloy: yeah it works fine for just let I'm saying for for-all it's harder

21:21 due to things like :parallel

21:22 I'm starting to think just encoding a sufficient amount of destructuring logic actually isn't bad

21:25 yeah I can do this in like 20 lines

21:25 and this avoids the gensyms too, which is a secondary goal

21:28 here it is and there are absolutely no bugs: https://www.refheap.com/97466

21:30 amalloy: gfredericks: :(

21:30 want me to tell you some bugs?

21:30 gfredericks: yes

21:30 amalloy: oh well actually i didn't really read it. maybe it's fine

21:30 justin_smith: haha

21:31 gfredericks: ;; amalloy says maybe this is fine

21:31 actually there is one bug

21:32 ,(let [{:keys [a/b]} {:a/b 12}] b)

21:32 clojurebot: 12

21:32 gfredericks: ^ that nonsense

21:32 ,(let [{:syms [a/b]} {'a/b 12}] b)

21:32 clojurebot: 12

21:32 gfredericks: ,(let [{:strs [a/b]} {"a/b" 12}] b)

21:32 clojurebot: 12

21:32 gfredericks: omg

21:32 amalloy: bahahaha

21:32 feature unlocked

21:32 justin_smith: that reminds me - this code seems good so far, but I am suspicous, any obvious issues? https://www.refheap.com/97344

21:32 gfredericks: that is hilarious

21:33 gfredericks: woulda bet $10 against that

21:33 hey it makes my code easier cause it's consistent

21:34 numberten: does clojure have a way to compare strings (or better yet keywords) lexicographically?

21:34 justin_smith: ,(comp "hello" "world")

21:34 clojurebot: #<core$comp$fn__4458 clojure.core$comp$fn__4458@66df3220>

21:34 amalloy: justin_smith: why are you using this at all instead of like (deref (future (f) time alternate))?

21:34 justin_smith: err

21:34 ,(compare "hello" "world")

21:34 amalloy: er

21:34 clojurebot: -15

21:34 amalloy: (deref (future (f)) time alternate)

21:35 justin_smith: amalloy: hmm... does that cancel the future after the timeout?

21:35 numberten: justin_smith: thanks :)

21:35 gfredericks: numberten: github.com/gfredericks/compare if you want better syntax

21:35 julianleviston: numberten: what’s your expected output?

21:36 justin_smith: amalloy: that doesn't cancel the future

21:36 amalloy: justin_smith: no, but future-cancel is a best-effort thing anyway

21:36 justin_smith: amalloy: right, but I intended for this to be used with things that are cancellable

21:37 amalloy: excellent point about the extra args on deref though, I totally forgot about that

21:37 amalloy: justin_smith: well, you can write the function much more easily with deref than your version, even if you want to ensure it gets cancelled

21:37 justin_smith: amalloy: yeah, that is a good point

21:37 (inc amalloy)

21:37 lazybot: ⇒ 228

21:37 numberten: justin_smith: just wanting to compare things

21:38 amalloy: (let [ret (deref (future (f)) time ::time)] (if (= ret ::time) alternate ret))

21:38 justin_smith: numberten: julianleviston was the one who asked

21:38 numberten: s/justin_smith/julianleviston

21:38 yeah

21:38 amalloy: but cancelling where appropriate

21:38 justin_smith: numberten: yeah, compare uses the underlying comparable interface, which strings (among many many other things) implement

21:38 numberten: so it should do everything you like

21:38 numberten: ideally i'd like to be able to use a comparable key for maps

21:39 and write a function that can return the next lowest key

21:39 gfredericks: sorted-map-by

21:39 amalloy: and then subseq/rsubseq

21:39 gfredericks: I used those in my test.chuck code and it was way overkill O_O

21:40 like it a context where collections would almost never have more than ten elements but *you never know*

21:42 numberten: do subseq/rsubseq returns sorted collections?

21:43 can you be sure that the first one is the least/most less/more than the key?

21:43 the documentation is unclear

21:43 justin_smith: numberten: they do if they are derived from a sorted collection

21:43 numberten: that makes sense, just from an implementation pov I guess

21:43 thank you :)

21:43 clojurebot: Huh?

21:48 julianleviston: ,(sorted-map :x 1 :a 3 :d 5)

21:48 clojurebot: {:a 3, :d 5, :x 1}

21:48 julianleviston: numberten: I’m guessing your answer is… sorted map just does what you want, so pick that collection?

21:51 justin_smith: (subseq (sorted-map :a 0 :b 1 :c 2 :d 3 :e 4) < :d)

21:51 ,(subseq (sorted-map :a 0 :b 1 :c 2 :d 3 :e 4) < :d)

21:51 clojurebot: ([:a 0] [:b 1] [:c 2])

21:52 justin_smith: sadly it doesn't hand you back another sorted-map

21:53 julianleviston: can’t you just into sorted-map filter or something?

21:54 gfredericks: yeah but that's linear time now

21:54 justin_smith: well, you don't need the filter part if you have subseq, but sure

21:54 (inc gfredericks)

21:54 lazybot: ⇒ 118

21:54 numberten: is subseq/rsubseq lazy?

21:54 justin_smith: ,(type (subseq (sorted-map :a 0 :b 1 :c 2 :d 3 :e 4) < :d))

21:54 clojurebot: clojure.lang.LazySeq

21:55 justin_smith: I'm surprised, but yes

21:55 numberten: very cool

21:55 so then

21:55 julianleviston: I’m not really sure what he’s trying to do anymore… I thought he was just trying to have a sorted map?

21:55 justin_smith: julianleviston: he wants a subsequence by some key

21:55 julianleviston: subseq can give you that directly without walking every item preceding it

21:55 since vectors / sorted maps are associative

21:56 julianleviston: justin_smith: sorry, I thought he just wanted to sort a map. All good.

21:56 numberten: #(first (rsubseq %1) < %2) should give you the first element less than some key

21:56 in a sorted map

21:56 justin_smith: numberten: subseq also has an extra arity for for an end-test / end-key

21:56 numberten: interesting

21:57 justin_smith: if you want a "slice"

21:57 numberten: yeah

21:57 that's pretty nifty

21:57 many thanks

21:58 amalloy: justin_smith: checking whether its type is LazySeq doesn't really tell you anything about whether it's lazy

21:59 i can compute a result eagerly and then just by coincidencey wrap it in a lazyseq

21:59 justin_smith: amalloy: that's a good point

21:59 amalloy: as it happens subseq *is* lazy

21:59 because like, why wouldn't it be

22:00 justin_smith: amalloy: I guess I trusted the clojure devs to pick lazy-seq if and when laziness would actually be exploited, and pick something else otherwise. It payed off this time I guess.

22:00 numberten: i hadn't thought of that

22:00 good to note though

22:01 amalloy: PS if you are looking for a way to get confused, try to call subseq on (sorted-map-by > 1 :a 2 :b)

22:01 (or well a larger version of this map, because for 2 elements it's not so bad)

22:01 justin_smith: amalloy: shouldn't the comparator provided to subseq agree with the one provided to sorted-map-by?

22:02 or are you talking about something trickier than that

22:03 amalloy: justin_smith: i mean, that sorted-map-by is just a map sorted backwards, right, you can easily imagine saying "i want to find the first number greater than 6 in this map"

22:04 which if you made a (sorted-map 1 :a 2 :b) is just (key (first (subseq m > 6)))

22:04 the other way it's < instead of >

22:05 justin_smith: mirror-reality

22:06 we could rename it to bizarro-map-by

22:08 gfredericks: I released it :/ https://github.com/gfredericks/test.chuck/blob/master/src/com/gfredericks/test/chuck/properties.clj#L8-48

22:09 At Least It's Not A Macro That Shoves &env Into A ThreadLocal™

22:10 amalloy: gfredericks: you decided not to fix the a/b issue?

22:11 gfredericks: it's fixed

22:11 I mean I didn't test it but

22:11 that's why it calls symbol-name

22:12 amalloy: oh, i figured you would just do that in the symbol? case. i didn't look at the map case

22:12 gfredericks: ,(let [a/b 12] b)

22:12 clojurebot: #<CompilerException java.lang.RuntimeException: Can't let qualified name: a/b, compiling:(NO_SOURCE_PATH:0:0)>

22:12 gfredericks: phew

22:15 ,(let [{:keys [a/b b]} {:a/b 12 b 13}] b)

22:15 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: b in this context, compiling:(NO_SOURCE_PATH:0:0)>

22:15 gfredericks: ,(let [{:keys [a/b b]} {:a/b 12 :b 13}] b)

22:15 clojurebot: 12

22:15 gfredericks: surewhynot

22:25 justin_smith: amalloy_: yeah, this is kind of weird ##(subseq (sorted-map-by (comp #(* -1 %) compare) :a 0 :b 1 :c 2 :d 3 :e 4 :f 5) < :e < :b)

22:25 lazybot: ⇒ ([:d 3] [:c 2])

22:26 justin_smith: usually the conditions would want to be opposites

22:26 but with the reverse map, they actually want to agree

22:26 reverse-sorted

22:29 equavalent sorted map, with opposing tests ##(subseq (sorted-map :a 0 :b 1 :c 2 :d 3 :e 4 :f 5) > :b < :e)

22:29 lazybot: ⇒ ([:c 2] [:d 3])

22:29 tvanhens: anyone ever have trouble with wrap-cors library? All my other middleware are functioning properly but when I add it to my chain and allow #".*" I don't see any allow headers on my response headers

23:01 amalloy: justin_smith: now remember to ask whether you mean subseq or rsubseq in that reversed map...

23:01 justin_smith: heh

23:54 emaczen: which emacs clojure mode should I use with Cider?

23:54 Clojure-mode or clj-mode?

23:55 Or does Cider use one of those by default?

23:55 justin_smith: emaczen: clojure-mode

Logging service provided by n01se.net