#clojure log - Nov 13 2013

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

0:00 tbaldridge: I'll try duplicating that and see how it goes

0:00 dnolen: tbaldridge: since macroexpand-1 hands the form to you the CLJS hasn't even touched what we got from the reader yet.

0:00 CLJs compiler

0:11 grncdr: yay :D

0:13 egghead: wow, core.async has gotten a lot cooler with this new api

0:14 (->> (spool source-seq) (map< transform1) (map< transform2...))

0:15 nonuby: with immutant is there a way to use immutant session store without the web app code taking a direct dependency on immutant.

0:20 tbaldridge: egghead: spool is in the core.async now, called "to-chan"

0:20 *is in core.async

0:22 swarthy: after I call line-seq is there a way to rewind the reader?

0:24 reframed: how do I make the following work, https://www.refheap.com/20792

0:24 right now total2 is 0, should match total

0:25 egghead: oh, thanks tbaldridge

0:26 justin_smith: swarthy: line-seq consumes the whole file if you realize it

0:26 you need to reopen or rewind the file to read it again

0:26 but if the file is not altered, just reuse the first line-seq?

0:27 *consumes the whole stream

0:27 swarthy: justin_smith: the example was trivial, in reality i first consume it all to get the full count. Then filter the line-seq on the second pass to count only lines that match a regex.

0:27 I guess I need to loop/recur maybe and do both at once.

0:28 justin_smith: why not just save the output of line-seq and then iterate it as many times as you need?

0:28 ie, suck the whole thing into a binding, then iterate on the binding

0:28 swarthy: hmm. Its a million line file, still do that?

0:28 justin_smith: oh, never mind

0:28 rewind or recreate the reader :)

0:29 well, million line may be OK, but may as well check

0:29 there is a .reset method on some input streams

0:29 swarthy: yeah. I guess a less idiomatic but better way would be to loop/recur and count all + count matches yes?

0:29 yeah BufferedReader ie: line-seq doesn't have reset

0:29 so I suppose I have to just recreate it if I take that method

0:29 justin_smith: yeah I think so

0:30 if you need the whole count from the beginning

0:30 also, if you just need the line count, there are faster ways to do that without turning every line into a java.lang.String

0:30 swarthy: Yeah that is likely true

0:31 I need a total line count, and then lines that contain some regex match.

0:31 So I can come up with a percentage.

0:31 justin_smith: something that just searches the inputstream for the bytes matching a newline, not creating any objects just incrementing a counter, would be much much faster for huge files

0:32 so you can't do the count and count matching regex in parallel?

0:32 if you just need a percentage, just build up two counters

0:32 bitemyapp: justin_smith: you know https://github.com/caribou/caribou-frontend/blob/master/src/caribou/app/request.clj isn't async-safe right?

0:32 swarthy: http://stackoverflow.com/questions/1277880/how-can-i-get-the-count-of-line-in-a-file-in-an-efficient-way

0:33 bitemyapp: and that it's pretty icky to write code that relies on having a dynamic var like that in scope?

0:33 `cbp: ggs.

0:33 `cbp: :-)

0:33 lpvb: is there a function to make a vector of bits from a numeric type

0:33 or should I write it myself

0:33 bitemyapp: I miss hoogle

0:34 justin_smith: swarthy: (reduce (fn [[total matching] line] ...) (line-seq input))

0:34 bitemyapp: lpvb: sigh, yeah...me too.

0:34 justin_smith: bitemyapp: thanks for that suggestion, I don't know why that is being done that way

0:34 bitemyapp: each request should have just one thread while being handled - but of course we cannot take that for granted

0:35 bitemyapp: justin_smith: you can't and the current async models for Ring don't guarantee that.

0:35 justin_smith: rather the opposite, http-kit doesn't use thread affinity or do anything to thread locals, so you have to write clean code.

0:35 `cbp: lpvb: maybe in java.nio

0:35 justin_smith: I don't even use wrap-request-map myself - is it in the default caribou template's core handler?

0:35 bitemyapp: I've been trying to nuke uses of dynamic vars in Ring libraries.

0:35 justin_smith: cool

0:36 `cbp: lpvb: make a byte array then put an integer in it

0:36 a ByteBuffer

0:37 justin_smith: bitemyapp: the real problem is likely wrap-caribou, which is used to create the config context that should surround all the request handlers (for db connection, s3 auth, etc.), I think that is a dynamic var :(

0:37 `cbp: I meant

0:37 bitemyapp: justin_smith: yeah that's not kosher at all outside of Jetty.

0:37 / tomcat.

0:37 justin_smith: gotcha, thanks

0:37 we will do some workshopping of this issue, we do want to get this stuff right

0:38 bitemyapp: justin_smith: you want to plan ahead for async safety, the moment you need websockets or long polling for something, you have to be able to pick up and drop thread context at will, static globals only, local argument passing and closures otherwise.

0:39 justin_smith: right, that is going to be a mess of a rewrite in caribou.model, but it will be needed

0:43 coventry: Is there a way to package a third-party jar into my jar? Is this what lein uberjar does, and if so, is there a way to do it selectively?

0:45 I've built my app off [tools.reader "0.8.0-SNAPSHOT"]. Somehow, I got a jar for this, but "lein deps" from a fresh maven repository doesn't find it anymore.

0:45 I'm depending on a feature which is in that but not in 0.7.10, the latest version, namely metadata giving the end-positions of forms.

0:46 justin_smith: bitemyapp: wait, if we want a binding of a variable to be per-thread, isn't that an apropriate usage of a dynamic var?

0:46 swarthy: justin_smith: thanks for the input. I'm about 3 months into my clojure journey and your recommendation to use reduce blew my mind a bit, but it works great!

0:47 bitemyapp: justin_smith: thread scope isn't a meaningful scope in async applications.

0:47 justin_smith: ahh, yeah

0:47 bitemyapp: justin_smith: don't abuse it as such. There are proper FP ways to form a real scope that doesn't rely on an implementation detail that will blow up in your face later.

0:48 justin_smith: yeah, so everything that needs the db config needs to be wrapped so it can be created in scope of that config

0:48 in order to capture it

0:48 bitemyapp: justin_smith: database stuff shouldn't be global, let alone thread scoped.

0:48 justin_smith: maybe promises would help that be less of a mess to change

0:48 bitemyapp: :|

0:48 no. stop.

0:49 justin_smith: ?

0:49 lpvb: why are the latest clojuredocs.org only 1.3

0:49 bitemyapp: lpvb: *sigh* long story...

0:49 lpvb: it's a rails app, un-maintained by somebody that went AWOL

0:49 lpvb: he owns the domain?

0:49 logic_prog: is there any clojurescript web rtc demo?

0:50 bitemyapp: justin_smith: for one thing, db config implies a few things to me. One that sticks out is that you're assuming a global singleton database.

0:50 that is deeply troubling.

0:50 lpvb: shouldn't there be a place to download the docs like scala

0:51 * bitemyapp growls and rants in the background

0:51 justin_smith: bitemyapp: it is reentrant, I can use multiple db configs in a repl in one running app

0:51 but we are maybe doing the re-entrance wrong

0:52 I mean db-config as one of the ones available

0:52 bitemyapp: the database should be a resource you just pass to the dependent functions

0:52 as an argument

0:52 coventry: How evil is it to deploy an uberjar to clojars?

0:52 bitemyapp: coventry: do it, and an angry mob will burn your house down, with you in it.

0:53 coventry: Oh, I know, I'll deploy the version of tools.reader I need.

0:53 bitemyapp: coventry: that's the ticket.

0:55 justin_smith: making a generator that takes a config and makes a configured version of each function would be less extreme a rewrite

0:55 then populating the functions we need from the generator

0:55 bitemyapp: I generally just pass a db conn or value to the dependent functions, depending on the semantics of what they're doing.

0:56 I don't find I need the generator pattern for this particular case.

0:56 I do use let over lambda, but not for that.

0:56 justin_smith: the issue is the db namespaces are huge

0:57 and the rewrites needed to change every function that calls a db function to take that extra arg would be pretty extreme

0:57 hmm... maybe it's not as bad as I think

0:57 it will need some pondering

0:58 coventry: Hmm, it appears that 0.8.0 is available, but lein is not seeing it. https://oss.sonatype.org/content/groups/public/org/clojure/tools.reader/0.8.0-SNAPSHOT/

0:59 justin_smith: coventry: have you added that repo to your config? you may need to do that manually for sonatype

0:59 coventry: justin_smith: How would I do that. I don't recall doing so.

1:00 justin_smith: https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L74

1:00 linked line, 74

1:00 coventry: I don't have that in the context where I got the 0.8.0 jar, but I'll try it out. Thanks.

1:03 bitemyapp: arrdem: http://i.imgur.com/ixhJfW8.jpg

1:05 coventry: I'm still getting "could not find in clojars", with the following in my profiles.clj. Am I doing it right?

1:05 {:user {:repositories [["sonatype" {:url "http://oss.sonatype.org/content/repositories/releases"}]]}}

1:06 justin_smith: coventry: yeah, that looks right

1:07 arrdem: bitemyapp: lolz

1:08 justin_smith: bitemyapp: so by that same reasoning shouldn't *out* be an explicit arg to every function that prints?

1:09 bitemyapp: justin_smith: stdout is global because of POSIX

1:09 justin_smith: take ownership for the design choices that are actually a choice

1:10 don't try to use something like that as an excuse.

1:10 arrdem: bitemyapp: there are people who want to live with me next year. that is why I won't be.

1:10 bitemyapp: arrdem: *snorts* what?

1:10 arrdem: I live with 12 people.

1:15 arrdem: bitemyapp: see.... that is why I'll never live bay/valey area if I can help it.

1:16 bitemyapp: COL is just friggin stupid

1:20 bitemyapp: arrdem: I'm plotting my escape already. I'm figuring out if remote working with my company is possible.

1:20 arrdem: even thinking of visiting Austin to see what it's like there

1:20 mostly thinking of Austin, Seattle, and Portland.

1:21 justin_smith: Portland is nice, especially if you don't like driving a car or needing to own one

1:22 arrdem: just got back from a seattle visit, I could see myself in seattle or austin for the long haul. never been to portlandia tho.

1:23 bitemyapp: justin_smith: I like cars and motorcycles.

1:23 and beef. I'm not very environmentally friendly.

1:31 bill610: I'm using luminus. From the repl, I run (start-server), which starts the server and opens a browser tab. Cool. When I make a change to the route function and run (use 'mynamespace :reload-all) in the repl, I go back to the browser and see that my changes have not taken affect. Should that work?

1:32 justin_smith: bill610: the handler is being used as a value by ring, not resolved from a var

1:32 you can use #' to pass in a var instead of its value

1:32 there is a wrap-reload middleware that helps with this stuff too

1:34 bill610: justin_smith: so, reload-all won't do what I'm expecting when running the out-of-the-box luminus template?

1:34 bitemyapp: bill610: it depends, but Luminus should be reloading for you.

1:35 bill610: you need to understand that the handler is one big rolled up "value" of composed functions into a single function.

1:35 bill610: that blob value doesn't get reloaded unless again, you add the indirection of a var

1:35 then you're just pointing to a nominative place to *get* the value

1:36 bill610: but yeah, Luminus should be doing this for you, unless you did something weird.

1:36 yogthos: ^^ ahem

1:37 bill610: bitemyapp: I *tried* not to do anything weird

1:46 justin_smith: bitemyapp: wrap-request was a relic that was no longer used, just got deleted, thanks for catching that

1:47 muhoo: is there a way to add my clojars username to my profiles.clj so it stops asking me for it all the time?

1:47 coventry: I'm releasing some very simple emacs integration with clojure.tools.trace. If anyone has time to smoke-test the README at https://github.com/coventry/troncle I'd be grateful for any feedback.

1:49 muhoo: Yes, e.g. :auth {:repository-auth {:username "coventry" :password "XXX"}} in :user

1:50 muhoo: there's a way to do it with an encrypted file, too, described at https://github.com/technomancy/leiningen/blob/master/doc/DEPLOY.md#authentication but I haven't gotten that working yet.

1:50 muhoo: coventry: really? :auth is not documented in sample-profile.clj

1:50 sorry, sample.project.clj from leiningen

1:50 coventry: muhoo: It's working for me. Probably not recommended because it's insecure.

1:51 muhoo: i don't need the password in a file. just the username

1:51 i'm concerned that it's not mentioned at all in the docs afaict

1:51 coventry: I'm not an expert and could be wrong. I only just got this together this evening.

1:54 Actually, I'm probably wrong. "lein deploy" keeps hitting gpg-agent, so I guess it must be accessing the credentials.clj.gpg I created, even though I have no configuration specifying that.

1:56 egghead: huh, my core.async program just keeps exiting without doing any work :/

1:56 muhoo: coventry: troncle looks interesting. i've been annoyed by having to type (comment (require 'clojure.tools.trace) (clojure.tools.trace/trace-vars sometihng.i.need.to/trace))

1:56 and then untrace-vars it when done

1:56 bitemyapp: justin_smith: np

1:57 coventry: muhoo: Actually, nrepl-discover has that functionality already. (M-x nrepl-toggle-trace after running M-x nrepl-discover.)

1:58 nid1: Hey folks. Is anyone in here using the https://github.com/stuarth/clj-oauth2 library? We're having a bit of trouble with the code which checks if the request is on the callback url… it seems like it will unavoidably throw an exception, but perhaps we're misunderstanding how it's supposed to be used (the documentation is wrong/ambiguous in a few places, so we might be putting too much faith in that as well).

1:58 muhoo: coventry: really? i thought that was only in cider?

1:59 nid1: @stuarth's fork is one of many, so we'd love to talk to anyone else who's using clj-oauth2 from any source. :)

1:59 bitemyapp: muhoo: dude, I use a macro for that.

1:59 coventry: muhoo: Nope, it's working for me with standard nrepl. Didn't know nrepl-discover was going in cider.

1:59 muhoo: coventry: also i have to insteall nrepl-discover

1:59 bitemyapp: muhoo: "c-c c t r o" and c-c c t r f

1:59 "Trace On" and "Trace oFf"

1:59 muhoo: off i go to marmalade then

2:00 sure enough, nrepl-discover. will try

2:00 coventry: muhoo: The nrepl-discover on marmalade doesn't work with troncle, FWIW.

2:00 muhoo: Note that the nrepl-discover.el package requires you to get nrepl.discover into your jvm first.

2:00 (See the first few lines of troncle.el)

2:09 egghead: re: core.async -- am I doing something wrong here? https://www.refheap.com/20795

2:09 I just want to have a lil' async pipeline and drain it until the lazy-seq is exhausted

2:10 echo-area: Must method names of a protocol be strictly confirmed to Java specifications, if such a protocol is supposed to be used with `proxy'?

2:11 I tried, and UnsupportedOperationException was thrown if I didn't name them that way.

2:11 egghead: if you implement an interface... :p

2:11 echo-area: E.g. names like `get-v' won't work, but names like `get_v' will

2:12 egghead: ya echo-area in the same way that if you make a clojure protocol you can't use get_v where the protocol expects get-v

2:12 echo-area: Although in both cases the proxy object declares a .get_v method

2:12 *declare

2:14 amalloy: echo-area: name munge-ing to and from java is a rather wonky topic, and i wouldn't be surprised to hear that something as old as proxy has issues with it

2:14 echo-area: Is proxy very old?

2:15 amalloy: it predates protocols, reify, and deftype by a long way

2:15 if you're defining a protocol, i can't imagine a reason to proxy it rather than reify it

2:16 echo-area: It's not a real program. I'm constructing a small program to understand another behavior I'm confused with

2:16 I just didn't want to write a .clj file and a .java file for this program

2:17 I should have said "a program for real use"

2:18 amalloy: still, why proxy? any use of proxy should be looked at with great skepticism; and if this is just a toy project i don't expect you need it

2:19 echo-area: The feature I'm experimenting with is something involving proxy, in a real project where a Java interface is used.

2:20 I need simplified code

2:21 amalloy: java interfaces should be reified too, not proxied

2:21 the only excuse for proxy is if you need to extend a concrete class

2:21 echo-area: Hmm, are you saying that proxies are deprecated?

2:21 For most cases?

2:21 amalloy: yes

2:22 i mean, i'm sure rich hasn't officially used a DEPRECATED rubber stamp

2:22 muhoo: egghead: " I just want to have a lil' async pipeline and drain it until the lazy-seq is exhausted" now there's a song lyric

2:22 amalloy: but you should always use reify instead

2:22 only if reify is impossible should you consider proxy

2:26 muhoo: the nmemonic i've used is: proxy means "extends", reify means "implements" and gen-class means "i really wish i didn't have to deal with java so much"

2:26 egghead: muhoo: I still haven't gotten it to work :(

2:26 Guest73040: muhoo: thanks. that clears things up.

2:27 muhoo: egghead: sorry, i know a lot more about song lyrics than i do about core.async

2:28 echo-area: amalloy: I see. But I'll finish my experiment anyway, as it will teach me another thing I'm confused with :)

2:31 amalloy: sensible

2:35 andyfingerhut: Chas Emerick's flowchart from his book is available on-line and seems helpful for choosing between several Clojure choices: https://github.com/cemerick/clojure-type-selection-flowchart

2:38 sm0ke: in postal how do i send mail by a particular name?

2:39 hmm i should try "Someone <someone@mail.com>"

3:03 how do i destructure a function argument if its a map with string keys like {"a" 1} for funciton like (defn f [{:keys [a]}])

3:03 {:a 1} works fine

3:06 opqdonut: ,(let [f (fn [{a "a"}] a)] (f {"a" 1 :a 2}))

3:06 clojurebot: 1

3:06 opqdonut: sm0ke: ^

3:06 egghead: hmm, the current release of core.async seems a bit broken

3:06 opqdonut: :keys only works for keyword args

3:06 err, keyword keys

3:07 egghead: putting a range into a channel and getting less than the range out... :/

3:08 mebbe it just a bug in my code tho

3:09 sm0ke: opqdonut: thanks

3:19 egghead: shouldn't this core.async program write out 100 lines to output.txt? https://gist.github.com/eggsby/7445491

3:37 jballanc: opqdonut: use :strs

3:37 ,(defn foo [{:strs [a]}] (println a)) (foo {"a" "Hello"})

3:37 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

3:37 jballanc: bah

3:38 well...like that

3:39 ,(letfn [(foo [{:strs [a]}] (println a))] (foo {"a" "Hello" :a "Goodbye"}))

3:39 clojurebot: Hello\n

3:40 jballanc: there we go

3:42 sm0ke: nice

3:45 if my map has a key :type and i do [{:keys [type]}] how does it works

3:45 does type resolves to core/type ?

3:45 how do i fix that

3:47 logic_prog: given the existence of core.async, is there still any need for clj-kilim ?

3:49 opqdonut: oh, :strs is just not documented

3:49 oh, no it is, I just can't read

3:57 jballanc: :)

4:28 Fraz1: morning all

4:29 I am having some trouble with my leiningen which I hoped someone could help me debug

4:29 I do this in one tab

4:29 lein repl :headless :port 2888

4:29 then in another tab

4:29 amalloy: sm0ke: it's important to understand that :keys, :strs, and :syms are all just short hand for the general map-destructuring syntax

4:29 Fraz1: lein repl :connect 2888

4:30 (require '[clojure.tools.namespace.repl :refer :all])

4:30 (refresh)

4:30 then I disconnect the repl session with ctrl+d

4:30 and re-issue the connect command

4:30 lein repl :connect 2888

4:30 amalloy: eg, if you have the map {[:age 20] 1}, you can destructure it with (let [{twenty-year-olds [:age 20]} m] ...)

4:30 Fraz1: at this point I see errors

4:31 CompilerException java.lang.RuntimeException: Unable to resolve symbol: defmacro in this context, compiling:(NO_SOURCE_PATH:1:5)

4:31 I realise this is most likely due to a bug in the code (mine) loaded by (refresh)

4:31 but is there any way for me to get context about what the error actually is?

4:57 muhoo: oh am i going to have some fun tomorrow with peridot

5:00 llasram: At the Conj?

5:04 muhoo: no, on my own here

5:05 llasram: Ah

5:05 muhoo: if i were at the conj i'd be having fun watchign talks

5:05 llasram: Well, enjoy the peace and quiet in the channel :-)

5:07 clgv: the conference attendees seem to often hang around here during the breaks, though ;)

5:12 je: Does it make sense to use core.async (timeout) to insert a pause between polling a webservice?

5:15 WWWest: Hi all!

5:16 I'm trying to workaround using the final method on nodejs' crypto stuff. when cljs sends the code to closure, it will fail because final is a reserved key word in ES 3

5:18 I tried something like this ((aget crypto "final") crypto), but I get "cannot call method final of undefined"

5:18 how can I execute the result of the aget on the crypto object?

5:20 Apage43: maybe.. (.apply (aget crypt "final") crypto)

5:20 rather (.apply (aget crypto "final") crypto)

5:21 (need to use apply as crypto needs to be bound to 'this' for the call)

5:23 WWWest: haha! .apply worked

5:24 thanks!

5:33 sm0ke: hey guys i have this really annoygin problem with ring request

5:33 i can see :body #<BytesInputStream BytesInputStream[len=5]> in my req map

5:33 but when i do (slurp (:body req)) i get nothing

5:35 i am using curl -XPOST "localhost:9000/service" -d "12345"

5:36 Apage43: sm0ke: you don't have other middleware that might be reading it before you do you?

5:36 sm0ke: no i just have (run-server (handler/site #'routes) {:port server-port})

5:37 Apage43: sm0ke: hm. And if you put a (.reset (:body req)) just before the slurp its still empty?

5:37 sm0ke: let me try

5:38 Apage43: it works

5:38 whats that?

5:38 Apage43: handler/site is from compojure?

5:38 sm0ke: yes

5:38 Apage43: that adds several middleware, one of which is probably reading your body

5:39 sm0ke: hmm weird

5:39 Apage43: https://github.com/weavejester/compojure/blob/master/src/compojure/handler.clj#L28-L38

5:39 sm0ke: but i have been using the same code since some time

5:39 never faced this before

5:39 Apage43: probably wrap-multipart-params

5:40 sm0ke: and yes i am using http-kit

5:41 Apage43: inputstreams are stateful and have an internal position

5:41 some of them actually *can't* be rewound, so it's tricky

5:42 sm0ke: but i still dont get what makes my code behave like so

5:42 i have no extra middleware

5:43 Apage43: yeah, multipart-params shouldn't touch the body unless the content type is set to multipart/form-data

5:43 hmm

5:44 sm0ke: what if you just (run-server #'routes) ...

5:44 (without wrapping in handler/site)

5:45 if that works it indicates that http-kit hands the thing to you already seeked to the end

5:45 sm0ke: yeah that works

5:45 Apage43: okay, if that works then it must be one of the middleware that handler/site attaches

5:46 sm0ke: this is sad

5:47 Apage43: sm0ke: paste the whole request map on refheap?

5:48 sm0ke: with site middleware?

5:49 Apage43: yeah

5:49 i mean

5:49 the request map as printed should be the same with or without

5:49 well.. the original part

5:49 the middleware will do param decoding and stuff

5:50 but yeah, post middleware processing

5:54 sm0ke: ok this took me forever

5:54 Apage43: another thing might be handy

5:54 sm0ke: just couldnt get formatting right https://www.refheap.com/20804

5:55 Apage43: (proxy [java.io.ByteArrayInputStream] [(byte-array [])] (read [& _] (throw (ex-info "Somebody read me!" {})))) ;; this returns an input stream that will throw an exception if anything reads it

5:55 you could try taking your captured request, but associng that as :body

5:55 and seeing where the exception gets thrown from

5:56 sm0ke: got it

5:56 the params middleware sees the content-type set to application/x-www-form-urlencoded and tries to read params out of the body

5:57 try adding -H 'Content-Type: text/plain' to your curl

5:58 or application/octet-stream

5:58 sm0ke: How on earth did you figure that out?

5:58 Apage43: reading the ring source and educated guessing; https://github.com/ring-clojure/ring/blob/master/ring-core/src/ring/middleware/params.clj#L22

5:58 sm0ke: this seems to explain everything on why it was working before

5:59 before i was testing from browser with jquery and its seems to set text/plain

5:59 Apage43: kudos

5:59 Apage43: sure :)

6:00 sm0ke: if you have a special type of data for your application, perhaps come up with a content-type for it

6:01 sm0ke: yeah makes sense

6:01 Apage43: that way you can be sure other middleware doesn't fire

6:02 inputstreams are one of those unfortunately side-effectful things :/

6:41 ticking: Tuim: telling everybody an artificially pricey part (the hiwin rails) so that you gain market advantage kinda looses my trust, he could at least explicitly said (part I use withheld)

6:41 whops sorry, I

6:42 disconnected and my client changed the channel :(

7:22 je: Any thoughts on how I can poll a http resource wihtout having the wait times between the polls consume an entire thread (polling multiple things): ask http for result, if result final return it, else wait and ask again

7:27 asteve: how do you guys debug running clojure processes?

7:27 CookedGryphon: je: http-kit allows you to do asynchronous requests with a callback

7:28 je: and then if you want to wait for several in a single thread perhaps core.async and an alts! statement

7:29 je: CookedGryphon: I don't think I'm interested in a callback... I get the answer fairly fast, its the wait time in between

7:30 CookedGryphon: I've looked a core.async for a few hours now (go blocks is totally new to me), I can't seem to bend it to my needs :)

7:30 CookedGryphon: I know what you mean, I haven't quite got around to it yet myself, but my colleague did a thing with it which is almost exactly what you describe

7:31 he's pulling multiple web pages which might take indeterminate amounts of time

7:31 set up http-kit with a callback which puts the result into a channel

7:31 and then does alts on the resultant channels so whatever comes back first gets dealt with and nothing blocks

7:37 pyr: hi

7:37 I'm trying to implement a class that "extends" another from java lang, and which requires the "Local" annotation

7:37 in java the classes look like:

7:38 @Local(value=Something.class)

7:38 class SomethingElse extends Something { ...

7:38 (I hate myself for having to do that, but oh-well)

7:39 CookedGryphon: is there any reason you can't just do it in java and call into clojure/use the resulting class directly

7:39 pyr: nope

7:40 CookedGryphon: I find that's usually less headache when dealing with naff java stuff - otherwise you just end up with ugly clojure anyway

7:40 pyr: makes sense

7:40 why it isn't an interface in the first place is what beats me, but I can't work around that

7:41 CookedGryphon: If you're working with beans, I don't know if there's anything in clojure/java.data which might be useful to you

7:42 nDuff: pyr: adding annotations means you need to use gen-class

7:42 pyr: nDuff: yup, already the case

7:44 nDuff: pyr: can you show what you're doing now?

7:44 pyr: nDuff: I currently have (:gen-class :name ^{Local {Value Superclass.class}} Subclass :prefix foo- :methods [...])

7:44 nDuff: I tried several variations on the the metadata for adding the "Local" annotation

7:45 but the java app that loads the class consistently fails with Unable to find Local annotation for class

7:45 je: CookedGryphon: I will take another swing at it :)

7:46 nDuff: pyr: what you gave there doesn't look right to me, but I'm trying to find my own code that uses annotations right now.

7:46 pyr: nDuff: I took hints from: https://github.com/clojure/clojure/blob/master/test/clojure/test_clojure/genclass/examples.clj

7:47 nDuff: pyr: when I've done it successfully, I didn't attach the annotation info to the :gen-class in my ns macro.

7:47 pyr: nDuff: where then ?

7:47 nDuff: pyr: ...but rather did it as part of an explicit (gen-class) form later.

7:47 pyr: ah

7:51 \o/

7:51 turns out it was the path to Local which was wrong

7:51 thanks for the pointers

8:16 guns: Good morning. In CLJS, is (:refer-clojure :only […]) always preferred over (:require [cljs.core :refer […])?

8:16 It seems to me that cljs.core is mostly an implementation detail

8:30 wakeup: hi

8:31 can I work my way around a cyclic dependency?

8:31 mdrogalis: wakeup: Namespaces or functions?

8:31 wakeup: namespaces

8:32 I just thought of using :only

8:32 trying that now

8:32 mdrogalis: You're definitely going to want to regroup.

8:33 wakeup: what do you mean by regroup?

8:33 mdrogalis: Reorganize your functions to break the cyclicness.

8:33 wakeup: hmm :only doesn't do it.

8:33 the functions arent cyclic

8:33 just the namespaces

8:34 I have two categories of functions, some of the use each other but

8:34 that's it.

8:34 mdrogalis: Right, but I mean, you're going to need to shuffle the location of the functions around.

8:34 guns: wakeup: extract the common set of functionality from namespaces 'a and 'b into a third ns 'c

8:34 wakeup: hmm

8:34 guns: good point.

8:35 guns: clojure is more restrictive on this point than many other langs, but it helps avoid making spaghetti

9:15 bfarah: leave

9:19 dnolen: guns: the first one is only for core since everything is implicitly referred. The :require is for everything else.

9:19 guns: dnolen: So users should never explicitly require from cljs.core?

9:20 dnolen: guns: everything is implicitly referred, there's no point

9:20 guns: or rather, exclude

9:20 sorry

9:21 e.g. (:refer-clojure :exclude [defn]) is always preferred over (:use [cljs.core :exclude [defn]))

9:29 pyr: still on the interop side of things, lets say i have a class that extends another (which I successfully built with the correct annotations with gen-class)

9:29 is there a way to call super.something from the clj code ?

9:30 dnolen: guns: the second one is not valid in CLJS

9:31 guns: dnolen: ty; this is in the context of slamhound and ns-form rewriting. (:require [cljs.core …]) was being produced as a consequence of the algorithm

9:32 dnolen: guns: slamhound probably doesn't support CLJS

9:32 guns: dnolen: yes, but it finds vars in cljs.core if it exists on the classpath

9:32 dnolen: guns: sure but I wouldn't use slamhound w/ CLJS period

9:34 mdrogalis: Just remembered the pseudonym Leon Repl. What a terrific alias.

9:36 guns: dnolen: yes, I agree. My question didn't make much sense from the perspective of a CLJS user

9:43 tufflax: I have a design (code) problem. Please take a look if you have the time: https://www.refheap.com/20811

9:45 mdrogalis: Heya tufflax. I worked on two things that might be of interest to you..

9:45 justin_smith: tufflax: one thing to consider: break game state into instances / rooms so that most updates only matter to others in the same instance and the same "room" (which can be an arbitrary radius in open space)

9:46 mdrogalis: I tried a small scale MMO last spring. I got bored, but there's a few ideas you can pilfer. https://github.com/MichaelDrogalis/maple

9:47 justin_smith: mdrogalis: would that be an morpg, or maybe just orpg?

9:47 mdrogalis: justin_smith is right though, that advice is sound

9:47 .. I guess it would in fact be an orpg :P

9:47 justin_smith: my first "coding job" was volunteering as a C coder for a foss mud

9:48 tufflax: justin_smith yes but still, sending changes is the most efficient, and the problem is still there

9:49 justin_smith: true - don't think about functions with output types, think about streams with polymorphic messages, and subscribers that can handle each kind of message in the right way

9:49 ie. (:event actor target {...})

9:50 so it starts with a keyword used for dispatch, gets sent on a go channel

9:50 or over a websocket

9:50 tufflax: that is kind of what I was talking about with the queue idea, is it not?

9:50 justin_smith: dispatch as in what it does (which determines args) not target

9:50 tufflax: or similar to it

9:51 justin_smith: yeah, async go blocks are a nice way to do queues

9:53 if you break up state into "near" state, "region" state, and "map" state, a vast majority of data only needs to be shared with others in the same "near" state, a smaller amount (like shouts or big explosions) need to be shared in a "region", and nearly nothing (global chat? auctions?) needs to be distributed globally

9:54 so your mmorpg with thousands of players, is really hundreds of 10 player games

9:54 that can enter and exit one another :)

9:55 tufflax: Are you suggesting that then I just send the whole state for every little room? That's can still be like 10 times more data than just updates.

9:55 justin_smith: no, that just helps state be more managable

9:55 if you narrow scope

9:56 full resend of state on big ticks, updates on little ticks

9:56 also send state when transitioning between region

9:57 big ticks and little ticks being async regular callbacks (think seconds and minutes, but on a smaller scale) that propagate synchronization and trigger automated mob events etc.

9:57 tufflax: Yes, yes, but what about generating events/deciding what to send (deciding what has been updated)? That is my problenm

9:57 mdrogalis: I'll take a look btw

9:57 thanks

9:57 justin_smith: every actor (mob or player) publishes actions, and is implictly subscribed to the room they are in

9:58 CookedGryphon: tufflax: I'm writing a game at the moment, and I've found this talk really really useful: http://www.youtube.com/watch?v=V1Eu9vZaDYw

9:58 tufflax: CookedGryphon: thanks ill take a look

9:59 CookedGryphon: nicely separates behaviour from state from the code to actually do stuff and observe

9:59 justin_smith: yes

9:59 CookedGryphon: then in terms of implementation i've been playing with ova (ref to a list of refs with nice selectors)

10:00 and something i like the look of but haven't yet played with is http://blog.paralleluniverse.co/post/44146699200/spaceships

10:00 which is a spacial database specifically designed for large simulations

10:00 tufflax: justin_smith: Ideally I would like this oracle that can just look at the game state and decide what has been updated, or something that would require me to care about publishing actions/generating events just as little as if I had the oracle

10:00 Yp

10:00 CookedGryphon: which lets you quickly query based on distance and areas

10:00 tufflax: :p

10:01 justin_smith: tufflax: why not qualify actions in terms of how wide their consequence scope is, and just send to everyone who subscribes to that scope

10:02 so your internal concept of state, and each client, are parallel subscribers

10:02 until, of course, someone switches context by entering/leaving a room, then they get a full push

10:03 CookedGryphon: if you have the component entity system and this spacial database, you can subscribe/request all the entities in a given space and have some mapping over the entities if you want to filter out secret internal state

10:03 should be fairly trivial

10:03 tufflax: justin_smith: the problem is not about who gets it, the problem is to not have to be explicit about these updates at all

10:03 CookedGryphon: seperate out observing the state from changing it

10:03 justin_smith: tufflax: just declare a subscription and let each actor publish

10:03 it is mostly implicit

10:04 ie. you don't loop over subscribers, let core.async do that

10:04 just declare who is listening

10:04 tufflax: yeah maybe. I'll think about it, and look at CookedGryphon and mdrogalis stuff too

10:04 thank you

10:06 mdrogalis: Good luck & have fun, tufflax :)

10:07 tufflax: thanks ;)

10:07 justin_smith: yeah, good luck and have fun

10:07 if you are lucky, you may even have to worry about griefers and people exploiting bugs in your code

10:08 that's when you know you've succeeded - people actually care :)

10:08 tufflax: hehe yeah

10:08 CookedGryphon: I think I have seen this. He talks about how he did not use persistent data structures in his code, right?

10:09 CookedGryphon: don't remember that

10:09 mdrogalis: I've taken to the advice of Richard Feynman. Always have some piece of work that you're just playing with and not trying to make money off of.

10:09 tufflax: hehe

10:09 CookedGryphon: i took what he said about keeping all the state and behavioural definitions as data with systems acting on them

10:09 and probably did my own interpretation

10:10 but i've found it to be really powerful

10:10 allowing me to do things like add features while people are playing :P

10:10 which always gives an awesome "how teh hell did you just do that" moment

10:10 tufflax: hehe ok ill watch this anyway ;)

10:10 CookedGryphon: especially if the people aren't used to clojure at all

10:10 tufflax: hehe

10:11 CookedGryphon: it also makes it ridiculously easy to test features in isolation

10:11 because you don't have to build actors and interactions between them

10:11 you just have the elements you need of the entity before and after

10:11 and as long as you don't clash namespaces, you're golden

10:13 llasram: /Clash of the Namespaces/ would make a good title for something

10:14 justin_smith: relaease the Garbage Collector!

10:14 much scarier than a little kraken

10:18 CookedGryphon: is there a HOF which would do the same as (reduce (fn [acc f] (f acc)) coll) ?

10:18 i have a vector of ring middlewares that I want to make into the appropriate function

10:19 justin_smith: ((apply comp fn-collection) initial)

10:19 ?

10:19 you may need to reverse the fn-collection

10:20 onthestairs: am i right in thinking there is a function f in clojure.core such that (f g x) = [x g(x) g(g(x)) g(g(g(x))) ...]?

10:20 cant think of the name of it

10:20 justin_smith: onthestairs: iterate

10:20 onthestairs: justin_smith: thanks

10:21 justin_smith: ,((apply comp [float inc inc inc]) 1)

10:21 clojurebot: 4.0

10:23 CookedGryphon: hmm

10:23 justin_smith: comp is like -> except of course not a macro, and opposite argument order

10:23 CookedGryphon: yeah, just wondering which is more evident

10:23 justin_smith: so if any of the middleware take multiple args, you need to make a lambda to put the prev result in the right position

10:24 mklappstuhl: is this still ‘the thing’ to have some simple math stuff in clojure: https://github.com/clojure/math.numeric-tower

10:24 ?

10:24 justin_smith: I usually just use -> to build my middleware, but maybe you have an advantage to having them in a sequence

10:25 mklappstuhl: there is also jvm interop if you are OK with jvm native types

10:25 ,(Math/pow 2.0 (/ 1.0 12.0))

10:25 clojurebot: 1.0594630943592953

10:25 justin_smith: the ratio from one note on a piano to the next

10:26 mklappstuhl: justin_smith: know about that but I want to show someone else how to do some simple stochastics in a programming language so that'd be just additional complexity

10:27 CookedGryphon: justin_smith: so my concept is, to build up a middleware stack much like a multimethod

10:27 justin_smith: if your concern is idiomatic clojure semantics more than the performance you would get from native types, yeah, go with numeric-tower I think

10:27 CookedGryphon: as in different requests would get different middlewares?

10:28 CookedGryphon: nope, that would just be a multimethod

10:28 as in different namespaces can add in their own stages

10:28 justin_smith: ahh

10:28 CookedGryphon: with dependencies on others to establish the order

10:28 mklappstuhl: justin_smith: it's super simple stuff so perf is not a concern :)

10:28 justin_smith: so the definition would be spread

10:28 CookedGryphon: yeah, rather than having one god namespace that has to know about all the things that will get added in

10:29 and also to be able to add in debugging, remove things at runtime

10:30 justin_smith: CookedGryphon: for that I use a "when-staging" function, takes a middleware as an argument - if environment is :staging it acts like that middleware, if environment is not :staging it is a noop middleware

10:30 you could also make that a macro of course

10:31 CookedGryphon: yeah, that was a bad example

10:31 justin_smith: I use this for things like verbose profiling, or controlling reload

10:31 CookedGryphon: really i want to avoid unecessary namespace dependencies

10:32 because as long as you're strict and enforce only adding namespaced keywords, there's no risk of getting into a mess allowing other namespaces to tweak the map on its way through

10:32 justin_smith: I am very fond of middleware as a design because it simplifies the composition of functionality of libraries

10:33 my worry as I hear you describe this is that it would reduce some namespace complexity by adding complexity to the middleware model

10:33 CookedGryphon: the only complexity it's going to add is the order dependency

10:33 which is currently something you do manually

10:34 and quite often have to think hard about and examine what your middlewares are doing

10:34 justin_smith: right

10:34 CookedGryphon: and waht needs what information

10:34 justin_smith: I should shower and leave for work, be back later

10:34 but interested in what you are doing here

10:34 CookedGryphon: well if it works nicely i'll no doubt make a little library

10:35 jcromartie: what's the difference between a class with a single method and a closure?

10:35 (rhetorical question)

10:47 TimMc: jcromartie: Objects are the poor man's closure; closures are the poor man's object.

10:51 tbaldridge: jcromartie: well, if you build closures the wrong way (like Python), with mutable closed over values, then there really isn't much of a difference.

10:53 jcromartie: well, let

10:54 well let's say you properly separate the concept of state and value :)

10:54 TimMc: Objects can be final.

10:54 tbaldridge: so the difference between closures and deftype. There really isn't much of a difference, imo.

10:55 TimMc: Either way, you're bundling up some context with a function.

10:55 and you can bundle that function with different values if you want to.

10:56 I could create a "biclosure" that has two invocation points and it would look like an object with two methods.

10:56 jcromartie: I was just working with a library in an ostensibly OO language, where there were lots of classes like that. They only served to define an interface for a single method over some state. Kingdom of Nouns, you know...

10:56 TimMc: two invocation points?

10:56 TimMc: Yes, those are closures.

10:57 like .invokeA and invokeB

10:57 It would be weird. :-)

10:58 jcromartie: googling "biclosure" yields lots of extremely dense math papers

10:58 TimMc: I made it up just now.

10:58 mdrogalis: Genius.

10:59 TimMc: Imagine if you could write (fn (invokeA [x] (+ x 4)) (invokeB [x y] (* x y))) and then call it like (foo 6) or [foo 7 8] to invoke one endpoint or the other.

11:00 (If you really wanted that in Clojure, you'd just use different arities or have a dispatch argument.)

11:00 jcromartie: yeah

11:01 TimMc: So java.lang.Integer is like a closure with a distinguished dispatch argument (the method name).

11:01 jcromartie: you can actually define multiple arities for anonymous fns

11:02 #(((fn ([x] x) ([x y] (+ x y))) 1)

11:02 I mean

11:02 ,((fn ([x] x) ([x y] (+ x y))) 1)

11:02 clojurebot: 1

11:02 jcromartie: ,((fn ([x] x) ([x y] (+ x y))) 1 2)

11:02 clojurebot: 3

11:02 TimMc: Instead of calling (5 :compareTo 6) you say (.compareTo 5 6)

11:08 jcromartie: immediately-invoked self-referential multi-arity anonymous functions have great potential for obfuscation

11:09 but you can't recur with different arity :| so it's impossible

11:09 aw

11:10 AimHere: Can't you fake a multi-arity recur though?

11:11 Have a macro that wraps all the arguments in a data structure and then unpacks them as requred

11:14 pyr: re: interop jungle

11:15 I was able to create everything I needed from clojure, except a small thing

11:16 The class I need to build extends on a previous one and in one of its methods does: ComponentLocator.getLocator(SomeClass.name)

11:16 S11001001: ,(doall 1)

11:16 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

11:16 pyr: I can't see to find that "name" property in clojure

11:17 TimMc: ,(doall "hello")

11:17 clojurebot: "hello"

11:18 TimMc: pyr: Is that a static field?

11:18 pyr: TimMc: nope (as in SomeClass/name)

11:19 to be honest there is so much DI hell in this project, I have no idea where it comes from :)

11:21 jcromartie: pyr: why can't you just use (.name x) and not worry about it? or is the reflection penalty too big in this case?

11:24 pyr: jcromartie: cause it doesn't work

11:25 jcromartie: https://github.com/apache/cloudstack/blob/4.0.2/plugins/user-authenticators/md5/src/com/cloud/server/auth/MD5UserAuthenticator.java#L86

11:25 that's the code in java

11:25 in clj, i can't access that property

11:26 weird

11:26 TimMc: pyr: case

11:26 Or is that a subclass?

11:26 * nDuff is tempted to try to repro with lein-try

11:26 pyr: TimMc: case ?

11:26 nDuff: pyr: what are the maven coordinates to get that dependency?

11:26 TimMc: ManagementServer$Name or (.Name ManagementServer)

11:27 pyr: Name, not name

11:27 pyr: ah

11:27 llasram: I was going to say, looks like an inner class

11:27 muhoo: ManagementServer$Name ?

11:27 nDuff: muhoo: that's the syntax for referring to inner clrasses

11:27 pyr: nDuff: there are none

11:27 nDuff: has to be locally built in maven

11:28 TimMc: nDuff: Or rather, the way the Java compiler fakes inner classes.

11:28 nDuff: *nod*.

11:29 muhoo: fwiw, i use this tool (org.timmc.handy.repl/show SomeWeirdJavaThingWTF {:inherit :true} )

11:29 to see what's really going on.

11:29 when dealing with crazy java stuff

11:29 nDuff: muhoo: ...oooh, nice.

11:30 muhoo: i should make an nrepl plugin for it

11:31 or, somene who knows more about nrepl should.

11:31 pyr: in 3.5 years of clojure i hadn't done that much interop: now i know why :)

11:31 well, can't find a way to call it, too bd

11:31 bad

11:32 TimMc: pyr: Can you find ManagementServer.java?

11:32 nDuff: pyr: I'd be very, _very_ surprised if it can't be done.

11:32 justin_smith: this may be obvious, but clojure.reflect helps with this stuff too

11:32 nDuff: pyr: ...and if you're at the point of giving up, I'd be happy to take a shot at it. If there aren't published binaries for that code, where would I find the source?

11:33 pyr: TimMc: it is there https://github.com/apache/cloudstack/blob/4.0.2/server/src/com/cloud/server/ManagementServer.java

11:33 nDuff: it's a monster

11:33 jcromartie: pyr: ComponentLocator.getLocator(ManagementServer.Name);

11:33 pyr: nDuff: https://github.com/apache/cloudstack (against tag 4.0.2)

11:33 jcromartie: pyr: in Clojure would be (.getLocator ComponentLocator ManagementServer/Name)

11:33 * seangrove is excited about Clojure/West this year

11:34 seangrove: I think I can actually go.

11:34 pyr: jcromartie: except this doesn't compile, ManagementServer/Name is not a static field

11:34 muhoo: justin_smith: i'm pretty sure that the timmc.handy.repl stuff is mostly nice formatting around clojure.reflect

11:35 pyr: TimMc: https://github.com/apache/cloudstack/blob/4.0.2/api/src/com/cloud/server/ManagementService.java

11:35 TimMc: looks like Name comes from here

11:35 justin_smith: muhoo: so its more about display, where clojure.reflect just gives you datastructures?

11:35 muhoo: justin_smith: i vaguely remember that, it's been a while since i looked at the code for it.

11:36 jcromartie: hm, that's tricky huh

11:36 justin_smith: "static final String Name"

11:36 muhoo: static? ManagementServer/Name then ?

11:36 nDuff: pyr: use ManagementService/Name rather than ManagementServer/Name

11:36 pyr: yup will do that

11:36 * nDuff is guessing here -- still running checkout, much less build.

11:37 pyr: nDuff: build on 4.0.2 needs to bypass awsapi

11:37 justin_smith: pyr - this may help http://stackoverflow.com/questions/850148/accessing-java-static-final-ivar-value-through-reflection

11:37 or it may not

11:38 pyr: one last thing, is there anyway from clj to call super (outside of proxies, which have proxy-super)

11:38 justin_smith: pyr: have you seen this? http://stackoverflow.com/questions/2572312/how-do-i-pull-static-final-constants-from-a-java-class-into-a-clojure-namespac

11:38 jcromartie: pyr: where would you call super other than a proxy?

11:39 mdrogalis: seangrove: Where/when is it this year?

11:39 pyr: jcromartie: in a class that extends another

11:39 jcromartie: class Foo extends Bar

11:40 just out of curiosity, I've seen java code do that, fortunately i don't need to in my extensions

11:40 jcromartie: pyr: I'm afraid the question doesn't really make sense. The only way to declare a subclass in Clojure is with `proxy'.

11:40 muhoo: jcromartie: or genclass, i think, too?

11:40 pyr: jcromartie: nope (:gen-class :name Foo :extends Bar)

11:41 jcromartie: ah, yes

11:41 pyr: jcromartie: which is what I have to go through to build my extension for cloudstack, since they didn't seem to think interfaces would be a good idea...

11:41 cloudstack is a really great example of a project that would be an order of magnitude simpler & smaller in clj

11:41 justin_smith: "gen-class will actually override and implement all interface and superclass methods by default with implementations that try to forward to specially named functions in your generated class (if they exist). These functions are named with the method name and types of their args." http://tech.puredanger.com/2011/08/12/subclassing-in-clojure/

11:42 jcromartie: http://stackoverflow.com/questions/9060127/how-to-invoke-superclass-method-in-a-clojure-gen-class-method

11:42 so you need to alias the superclass methods

11:42 interesting

11:42 pyr: ah, fun

11:42 jcromartie: sorry :) I've only ever had to create subclasses using proxy because most APIs expect you to pass them an object, rather than specify an AOT-compiled class :)

11:43 justin_smith: jcromartie: my link claims that they are implemented by default (have not tried it myself)

11:43 llasram: When you start needing to do that sort of thing, I usually find it's easier to implement a tiny stub Java class which calls into Clojure for the actual implementations

11:43 pyr: jcromartie: np, today was a fun expirement

11:43 jcromartie: I would'nt spend my days in interop land though

11:43 jcromartie: I'm much more comfortable sticking to clojure

11:43 llasram: The way I see it, Java is a pretty reasonable DSL for implementing Java classes

11:43 pyr: apache cassandra has a much nicer design

11:44 it relies on interfaces for extensions so you can just deftype away

11:44 jcromartie: justin_smith: they are overridden by default

11:44 pyr: llasram: agreed, but who doesn't like a challenge

11:46 thanks a lot for the hand-holding guys !

11:46 and sorry about being brain-dead about these issues

11:46 s,about,for

11:59 seangrove: mdrogalis: Not sure, I assume similar time as last year

12:00 So, March-ish 2014?

12:00 mdrogalis: Ah, nice

12:00 TimMc: justin_smith, muhoo: o.t.h.repl/show is actually a display wrapper around ot.h.reflect -- I was fed up with clojure.reflect for some reason.

12:02 sritchie: if any friend users are around,

12:02 do you guys have any good recs for granting route-based permissions?

12:17 justin_smith: sritchie: shot in the dark - give a sub-path and children needing separate auth their own handler / workflow? I am still looking at friend but have not integrated it yet

12:19 sritchie: justin_smith: I'm thinking of, say, authenticating a post's author

12:19 you're an ::author, but only of this blog or post

12:22 rurumate: ,(.indexOf [1 2] 2)

12:22 clojurebot: 1

12:22 rurumate: how to do that in clojurescript?

12:22 justin_smith: sritchie: what about creating a map like {::author [article1 article5] ::admin [page-X]} when the auth happens?

12:23 then attaching map to session, and checking that

12:23 sritchie: justin_smith: friend will only accept either a set of roles or a func that returns a set of roles -

12:24 so I could check a dynamically bound session, I guess

12:25 justin_smith: sritchie: typically I have a permission table in the db, each has a role and a model, and each user has a set of permissions

12:26 so a query can check if the user's role contains a permission for that model

12:26 but to do article by article is even a finer granularity than that

12:26 grncdr: rurumate: that should work in clojurescript

12:26 sritchie: the site I'm working on lets users create these athletic races,

12:27 justin_smith: so what this is trying to get at is, are you the admin for this particular race that you're on

12:27 justin_smith: sritchie: what about a table that assigns a set of races to each user, and just check that?

12:27 sritchie: justin_smith: and to find out what race the server's trying to fetch, just use a dynamic var holding the current request?

12:28 rurumate: grncdr: sorry, should have try it before :~)

12:28 justin_smith: friend for authentication (it tells you who they are), then your own schema for authorization

12:28 sritchie: I use a controller that is a function from request to rendered template

12:29 so no need for a dynamic, it knows the info for the template it is rendering, and can do the appropriate checks based on request

12:29 sritchie: okay, that was the rub

12:29 I want to also use friend for authorization,

12:29 which constrains the checks I can do

12:29 but yeah, what you're saying is what I'm doing now, and it works

12:30 so maybe I'll just stick with that :)

12:30 justin_smith: I only mention it because it is what I do

12:30 there may be something better that leverages friend that is better for all I know

12:30 but really using args is better than dynamic vars, in general

12:31 sritchie: agreed

12:32 muhoo: sritchie: i wrote my own rbac :-/

12:32 there really wasn't any other way. it's not complete, and it's specific to this app, but it kinda sucked to have to do that.

12:33 sritchie: I think friend would be nice if it just allowed a user's roles to be a function from request -> roles

12:34 muhoo: i wrote some ugly crap to turn reqs into authed userids

12:34 based on friend's :identity

12:35 sritchie: muhoo: ah, you were using friend and still wrote your own rbac?

12:35 justin_smith: an advantage to resolving authorization in the controller rather than at authentication, is it fixes the problem of long sessions and changed permissions

12:35 muhoo: friend doesn't do rbac. it'll let you assign users roles, yeah, and it makes that a lot easier. but then to actually assign activities in the app to those roles, that i had to do myself.

12:36 so it's like, user->role friend will do. but role->funtionality-in-the-app i had to do, and there wasn't any ready-made framework for that

12:36 justin_smith: even the user-> role thing is cleaner if resolved for each request rather than once at authorization

12:36 because you can change roles

12:36 muhoo: good point. hmm.

12:36 sritchie: yup

12:36 justin_smith: muhoo: functionalit-in-the-app is turing complete :)

12:37 so better to let a programmer do that themselves

12:37 muhoo: no, there are cms'es that do a lot of that for you.

12:37 and there are rbac systems that provide some kind of utilities to make it a bit easier.

12:37 justin_smith: there are, but they are also a cms so they know you are using their model

12:37 muhoo: just not in clojure afaict

12:38 justin_smith: caribou has a cms by default, which has roles/permissions, but some of the final steps (web UI for permissions etc.) are still in progress

12:38 also, permissions are per-data-model, not per-instance

12:38 muhoo: i looked at that a bit last night, didnt' see the cms stuff.

12:38 i should see what pedestal does

12:38 justin_smith: muhoo: default page has a link to the admin

12:39 start up the app, go to the page, click the admin link

12:39 muhoo: is there a demo app up somewhere, like on heroku?

12:39 justin_smith: muhoo: lein new caribou is the demo app

12:39 muhoo: for the lazy who don't want to install the thing :-)

12:39 justin_smith: we aren't going to let you access the admin on our machine, sorry :)

12:40 muhoo: naw, i meant on heroku or something. like the friend auth demos.

12:40 justin_smith: putting it on something like heroku is an idea, true

12:40 we have heroku install out of the box

12:41 but really it isn't much of an "install" lein new caribou myapp; cd myapp; lein caribou migrate; lein ring server

12:41 then you can rm -rf myapp if you don't want it any more

12:41 swarthy: justin_smith: I think he is saying, demo app : try new project :: screenshots : try new video game

12:41 I don't know if I agree or not.

12:42 muhoo: justin_smith: clojure.lang.ArityException: Wrong number of args (1) passed to: migrate$migrate

12:42 justin_smith: I am considering putting up a heroku demo

12:42 just saying the current situation is not a super high barrier of entry

12:42 muhoo: following your instructions above

12:42 justin_smith: heh

12:42 oops!

12:42 muhoo: swarthy: so, that actually is what i'm saying :-)

12:42 that's 30 seconds of my life i'll never get back

12:42 justin_smith: lein caribou migrate resources/config/development.clj

12:42 I always forget that arg

12:42 lol

12:43 swarthy: muhoo: lol, yeah I see your point.

12:43 muhoo: httpkit, eh?

12:43 and leiningen-2.0.0

12:44 and now all of jboss is downloading, so that's really why a web demo is nice: frictionless demo

12:44 justin_smith: jboss?

12:44 wtf

12:44 I'll have to talk to patchwork about that

12:44 muhoo: yep, migrations pulled in all of jboss and immutant

12:44 justin_smith: must be the immutant thing;

12:44 I was just gonna say

12:44 I have been trying to ditch that dep

12:45 muhoo: ooh pretty

12:45 did you do the design in-house or hire a designer?

12:45 justin_smith: we are mostly a design shop

12:45 us monkeys just make the designs real :)

12:46 glad you like it

12:46 muhoo: ah, it's MVC

12:46 justin_smith: yeah

12:46 it's a migration of a php system that got reimplemented in ruby - but reimplemented very smartly, if I may compliment my coworkers

12:47 from ruby to clojure, of course

12:47 rurumate: grncdr: finally got round to trying it; not working

12:47 Uncaught TypeError: Object [object Object] has no method 'indexOf'

12:47 grncdr: oh, that's annoying.

12:48 I (wrongly) assumed that the vector implementation would have indexOf

12:48 muhoo: justin_smith: it's very slick. the gui for adding models feels very ruby-ish. nice.

12:48 justin_smith: thanks

12:48 grncdr: in that case, you can always do it manually

12:49 rurumate: yeah, I'm already digging out (loop)

12:49 justin_smith: the deal is, if clojure makes us faster, they don't increase our workload, they let us put more work into improving the libs - so we have lots of incentive to make the libs work well (so dev time is shorter) and much time to make things slick

12:49 grncdr: ,(first (filter #(= % 2) [1 2 3]))

12:49 clojurebot: 2

12:49 swarthy: justin_smith: so what is the design goal of Caribou? Is it a rails-y type thing. You guys likely do a lot of client work so Caribou tries to solve the issue of making CRUD after CRUD app for clients?

12:49 grncdr: oh wait, that get's the value, not the index :|

12:49 rurumate: exactly

12:49 justin_smith: swarthy: yeah, client work: make a web app or web site with short turnover and a cms so producers and frontend can do as much of the work as possible

12:50 grncdr: ,(map-indexed vector [1 2 3])

12:50 clojurebot: ([0 1] [1 2] [2 3])

12:51 swarthy: cool

12:51 grncdr: ,(first (filter #(= (second %) 2) (map-indexed [1 2 3])))

12:51 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$map-indexed>

12:51 grncdr: ,(first (filter #(= (second %) 2) (map-indexed vector [1 2 3])))

12:51 clojurebot: [1 2]

12:51 grncdr: hah, closer, but getting uglier :P

12:51 swarthy: justin_smith: I think clojure as a community needs a railsy all-in-one type environment to grow with/from.

12:51 grncdr: ,(first (first (filter #(= (second %) 2) (map-indexed vector [1 2 3]))))

12:51 clojurebot: 1

12:52 mdrogalis: I kind of felt that Pedestal was supposed to be that, swarthy.

12:52 grncdr: rurumate: that works ^^ but is ugly

12:52 mdrogalis: Then again, I don't use it.

12:52 rurumate: still shorter than a loop, thanks

12:53 swarthy: mdrogalis: Doesn't pedestal aim to make single page javascript heavy apps easier. Not the standard CMS type stuff, I could be very wrong.

12:53 mdrogalis: swarthy: I could be very wrong too :) *Shrug*

12:54 grncdr: ,(first (clojure.contrib.seq/positions #{2} [1 2 3]))

12:54 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.contrib.seq>

12:55 grncdr: poop

12:55 muhoo: justin_smith: well it's very cool, will have to poke around at it some more. it looks like you put a lot of work in to it, especially making the front end very polished

12:57 rurumate: ,(some (fn [[idx v]] (when (= 2 v) idx)) (map-indexed vector [1 2 3]))

12:57 clojurebot: 1

12:57 swarthy: mdrogalis: yeah if you check this out: http://pedestal.io/documentation/application-overview/ I feel like there goal is to be the rails of the future when everything goes single page.

12:57 muhoo: justin_smith: interesting. why is the cljs source in resources instead of src or src-cljs or similar?

12:58 justin_smith: muhoo: not sure, patchwork would be able to tell you when he logs in I think

12:58 mdrogalis: swarthy: Understood :)

12:59 swarthy: mdrogalis: that said pedestal looks really cool

12:59 justin_smith: one difference between pedastal and caribou is caribou assumes frontend isn't a clojure programmer

12:59 realistically, that is what we have seen

12:59 quile: muhoo: justin_smith: it might have to do with the browser needing to access the cljs source for debugging

13:00 seangrove: swarthy: pedestal is unlikely to be the framework of the masses - possible, but unlikely. It's such a different approach that there's a very large up-front investment required.

13:01 grncdr: rurumate: FWIW I found a nicer approach here on SO http://stackoverflow.com/a/4831170/446634

13:01 swarthy: seangrove: wouldn't you say that is a bit true of clojure as well though?

13:01 seangrove: swarthy: Yeup.

13:02 muhoo: i'll bet the datomic console was built in pedestal

13:02 as an example SPA

13:05 danneu: anyone know of standard ways to add randomness to SecureRandom?

13:05 even conceptually

13:06 justin_smith: danneu: you can use a adc (sound card input) as an entropy source

13:06 or even better if you have radio input

13:07 https://www.cigital.com/justice-league-blog/2009/08/14/proper-use-of-javas-securerandom/

13:07 TimMc: danneu: On Linux, I think telling the user to use their computer normally for a few minutes is good. Timing information is juiced into the main entropy pool, and I think SecureRandom is seeded from that.

13:07 justin_smith: yeah, it farms out to OS entropy sources

13:07 which in turn can use user activity, devices with analog input, whatever

13:09 muhoo: /dev/urandom

13:09 i let the system do it.

13:10 justin_smith: muhoo: yeah, it is using the same kernel functionality that generates the urandom interface

13:10 danneu: What if /dev/random is compromised?

13:10 justin_smith: so actually you don't need to do that, the jvm will access that in an OS appropriate way when seeding (as described in my link above)

13:11 danneu: the jvm will not help you fix the fact your hardware or OS is compromised

13:11 totally not in its scope of design

13:11 compromised box is compromised box, they could compromise the jvm implementation itself at that point

13:13 danneu: haha, right. so does it make sense to attempt to bolster securerandom at all?

13:13 muhoo: by the way, peridot is awesome.

13:16 justin_smith: this peridot: https://github.com/xeqi/peridot

13:16 danneu: basically, i have an application that derives bitcoin keypairs from a master seed. i'm not cocky enough to think anyone will ever use it - so it's merely a thought exercise

13:16 justin_smith: ?

13:16 `cbp: no template by the name login.html

13:17 TimMc: danneu: No, just grab (SecureRandom/getInstance "SHA1PRNG")) and call it good.

13:17 mtp: why not dual-ec!

13:17 /s

13:17 TimMc: :-P

13:18 danneu: Where are you needing to generate your own randoms?

13:18 I would expect you'd be able to call into an existing crypto lib for anything at this level.

13:19 danneu: TimMc: the app generates the seed for the user

13:19 TimMc: Ah, so this isn't really the crypto part, just a master secret.

13:19 danneu: yeah, beyond that i lean on bouncycastle

13:21 ill see if i can find some gimmicks to add to the seeding process. like justin_smith's soundcard idea

13:21 give it a nice CSI gui

13:22 muhoo: in other words, <3 : https://www.refheap.com/20814

13:23 justin_smith: danneu: if you can dip into the noisy analog realm, you can get shitloads of entropy real cheap

13:24 rasmusto: heh, dip

13:24 justin_smith: hell, checkout out how many bits of resolution you have on CPU temperature readings, and if you have enough, do some munging of the least significant bits

13:25 danneu: justin_smith: cool, gave me some google terms to search for. would even be fun to have enduser turn on their webcam

13:25 and dance for their seed

13:25 muhoo: the idea of hand-rolling crypto seems dangerous to me. i prefer to leave it to the OS (if the OS is good) and well-tested mature open source libraries

13:25 llasram: Context is everything

13:26 muhoo: i figure if the java crypto libs use system's PNRG, and system is linux, i'm fine there.

13:26 justin_smith: danneu: http://hackaday.com/2010/02/06/hardware-based-randomness-for-linux/

13:27 muhoo: not hand rolling crypto, but getting a good input to a known good off the shelf algorithm

13:27 cYmen: hm...just wanted to start reading noir tutorials and it tells me it is deprecated

13:27 danneu: cYmen: check out compojure

13:27 cYmen: Does it have good tutorials?

13:28 I need an easy start. :)

13:28 danneu: compojure is easy

13:28 lein new compojure myapp

13:28 noir was extracted into a library https://github.com/noir-clojure/lib-noir

13:28 cYmen: hmhm

13:28 okay ...any particular compojure introduction or tutorial I could read?

13:29 danneu: well, what do you want to do?

13:29 cYmen: uh.. make a website :)

13:30 Or, webapp as they like to call it theses days...

13:31 danneu: cYmen: start off with the lein template. then `lein ring server` from it to boot it and open the browser.

13:31 cYmen: Yeah, I already played with ring but now I don't feel like just starting with my own templates and stuff.

13:32 danneu: ?

13:32 cYmen: I'll just read https://github.com/weavejester/compojure/wiki

13:32 danneu: cYmen: sure, but i meant that the lein-template sets up the barebones in a way that it's easy to figure things out from there

13:33 cYmen: I'll just give it a go then...

13:33 justin_smith: cYmen: by templates and stuff do you mean templates for rendering pages?

13:33 there are a huge number of templating engines for clojure

13:33 cYmen: justin_smith: yes

13:33 rkz: are clojurescript questions ok in here or should I be asking #clojurescript?

13:33 danneu: for html, i like https://github.com/weavejester/hiccup - Just write the html in the same file

13:33 rkz: they here

13:34 justin_smith: yeah, if the person making the templates is the same one writing clojure code, something like hiccup or enlive is great

13:34 augustl: how do you write a map as edn?

13:34 clojure.edn only has reading it seems

13:34 justin_smith: augustl: pr-str

13:34 in general

13:34 cYmen: hiccup...will look at it soon

13:35 rkz: I'm trying to figure out how to do: 'webkitMatchesSelector' in Element.prototype in cljs. (contains? "webkitMatchesSelector" (.-prototype js/Element)) doesn't seem to work

13:35 justin_smith: for anything to output to edn

13:35 augustl: justin_smith: ah, cool

13:35 justin_smith: or pr

13:35 danneu: cYmen: yeah, hiccup(html) + compojure(routing) is the simplest stack of all the surrogates (sinatra, flask, express, etc)

13:36 cYmen: excellent I hope it will also be easy ;)

13:36 rkz: I can get the function out by doing (.-webkitMatchesSelector (.-prototype js/Element)) but not sure what the cljs translation of the js 'in' operator is

13:36 danneu: cYmen: i actually got in to clojure from the webdev angle, so lemme know if you need help

13:36 seangrove: rkz: indexOf?

13:37 cYmen: danneu: thanks!

13:38 TimMc: rkz: Yeah, contains? checks for a key, not a value.

13:38 Or wait, that's what you want, isn't it?

13:38 rkz: TimMc: that's what I think i'm trying to do

13:38 check if a key 'blah' is in object foo

13:38 TimMc: I think you have the args backwards.

13:39 rkz: (contains? foo 'blah') instead of the otherway... I'll try it

13:40 TimMc: (It's rare to see someone asking about contains? and actually needing that fn instead of a value-finder.)

13:41 justin_smith: yeah, lol

13:43 danneu: cYmen: https://www.refheap.com/20817

13:43 rkz: TimMc: you were right, I am using it the wrong way around but it still doesnt work when I've got the args in the right order...

13:43 acb_ok: message for operator

13:43 -----BEGIN PGP MESSAGE-----

13:43 Version: GnuPG v1.4.11 (GNU/Linux)

13:43 hQEMA2AZRvNf4fCzAQgAhM9fhO9y1VJ4lQ75vgYklLogRubPF4EZI8owcEtgzoYF

13:43 W0+hipJCBxJR7x0SXV6SpzCWqpGYibBHT/3HVwDHwxdMWBjutOtNknFRkQeT6c1F

13:43 ojsUPjn2+sBTrCjnUap4XmCsUe82o0bFxQ4qkhLNRVpklbgmMIKnkB9yDj1f19dQ

13:43 EW+JG7boP10usXz+m3KC0fpFxIILcZEnmOSizHuijUGh5TcfUCgouI4mLYyEEol8

13:43 HnEAOsP5w+4SpwJERUWXBkHdQGUNrjpnKxz5q2WbTi61jqt3I2JsY4Zbz6s4yzGR

13:43 Svq38b0v1Toc/LaHZU1jQlZJC8oujEDsRUbLkUCZONLpAazkDJX/WzA355RAt8l8

13:43 7Iq76W9BfqvOabOF7rVzvxzC9TIdthjWJKoGDRdUXxIQ0goMuJYo9GbBurzePgtN

13:43 sXYeeNhDapZv35+v5tU3IicjekEsF0X3iVZecgrbI94DNuOf51XqtP6YxBEmrEck

13:43 4GkQ4uJHGXRWQsqO1yMSZulFdLequ/OS0rm+EksPBsyd7OyXEy7GC67DNtr6Trz+

13:43 kIr3LOeFjRb0QfyfLqXKrCmzimsBEXFmyTEhdE1EAOrsn9Z8nSFQkJ+v55hNFM+T

13:43 nCJbUzv/hpFExbDAADNABkNb+SKf2CYYPS1ys4JbfEQDvTTeHM5AqTXmTe3O85oP

13:44 danneu: ^_^

13:44 llasram: Huh

13:45 cYmen: danneu: thanks...trying to figure out routes right now, looks great, though

13:45 seangrove: rkz: Does contains? work with native js objects?

13:47 swarthy: rkz: you might want to read this http://stackoverflow.com/questions/135448/how-do-i-check-to-see-if-an-object-has-a-property-in-javascript

13:47 then find out if contains? does that for a javascript object

13:48 to my knowledge JSON doesn't have the concept of 'index' because it is purely associative

13:48 and contains? is index based isn't it?

13:48 justin_smith: ,(contains? {:a 0 :b 1 :c 2} :b)

13:48 clojurebot: true

13:48 justin_smith: is that index based?

13:48 swarthy: yes, but that isn't a json object

13:51 this is why clojure + cljs is so hard to get started with. Because that hosted platform benefit means you are learn 1+N stacks at a time.

13:53 rkz: swarthy: thanks reading now, I made a cljsfiddle of what I'm trying to do

13:53 http://cljsfiddle.net/fiddle/r4vi.cljsfiddle

13:54 swarthy: rkz: I'm no expert I was just messing with Harp.js and ran into a similar issue where my lack of JavaScript knowledge about how json objects work was frustrating.

13:54 seangrove: rkz: You can't do (keys js/window), so I don't think contains? will work

13:55 justin_smith: is this where you want .hasOwnProperty? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty

13:57 rkz: justin_smith: hasOwnProperty would work, (so would just accessing it and checking for nil) but I guess I'm trying to figure out how to do 'foo' in obj in cljs for future reference

13:57 seangrove: rkz: We'll find you a solution, don't worry, but it's worth looking at the source here: https://github.com/clojure/clojurescript/blob/master/src/cljs/cljs/core.cljs#L1219

13:57 Not that it calls (get coll ...) rather than aget

13:58 rkz: See http://cljsfiddle.net/fiddle/sgrove.r4vi.cljsfiddle

13:59 swarthy: justin_smith and my article seems to work to: (print (.hasOwnProperty js/window "foo")) ;; should be true

13:59 that prints true

13:59 justin_smith: cool

14:00 rkz: yeah hasOwnProp would work, maybe that's what the in operator calls

14:03 seangrove: rkz: Finally, you can do (some #{"foo"} (.keys js/Object js/window))

14:03 muhoo: is there some way in nrepl.el to copy the output of an exec to the kill ring so i can paste it?

14:04 seangrove: rkz: Depending on what you're trying to do, I'd write a function called aget-own and use it with (if-let [foo (aget-own js/window "foo")] ...)

14:13 rkz: seangrove: yep that's what I'll do thanks! but this is an interesting problem I'm going to update the fiddle with a few edge cases

14:14 bitemyapp: swarthy: at least as far as CLJS goes, you were never going to avoid having to learn the DOM

14:15 you are *kidding* yourself if you think you can get away with that in a client-side context.

14:15 swarthy: i never said I was

14:15 bitemyapp: swarthy: server-side has a higher likelihood of having a "common core" interface to the host.

14:15 swarthy: yeah

14:15 muhoo: cljs means learning dom. clojure means learning java and jvm. these are hosted languages.

14:15 seangrove: rkz: With some more understanding of what's happening here, it's useful to see how lynaghk extends ILookup to js objects: http://keminglabs.com/blog/angular-cljs-weather-app/

14:16 Then you can use destructuring and whatnot like they're native objects - you just have to decide how to handle inherited properties, etc.

14:16 bitemyapp: muhoo: it's easier to avoid the Java bits than it is the DOM bits though.

14:17 justin_smith: muhoo: I am playing around in the ielm repl with nrepl-send-string - it takes a string and a callback but I am clearly doing something wrong

14:17 theoretically 'kill-new as the callback would put the output in the yank ring

14:18 swarthy: bitemyapp: muhoo: are there any good resources that explain the JVM/Java as a platform that you would recommend. What I really want is 'The JVM for People Who Get Unix'

14:19 bitemyapp: swarthy: I came to it from the same background, I don't think there's much to learn if you're a Clojurian.

14:19 muhoo: swarthy: not that i know of. i'm a unix guy too.

14:19 oh there is a lot to learn. know what -Xmx means? what about permgenspace? what's in your ~./m2 ? etc etc

14:20 bitemyapp: swarthy: maven is hiding underneath Leiningen, the classpath is where the JVM finds...classes (-cp) and you want to pay attention to how much heap you're providing for your JVM (-Xms -Xmx)

14:20 justin_smith: muhoo: (kill-new (second (nrepl-send-string-sync ":hello")))

14:20 bitemyapp: swarthy: there's honestly not that much to it unless you get specific.

14:20 swarthy: yeah

14:21 muhoo: the problem is when things break or act unexpectedly, then you are looking at something and goign WTF

14:21 some exposed underlying java or js thing in the host language. it's inevitable, eventually.

14:21 swarthy: bitemyapp: for me it is mostly about structuring work and building web applications with Clojure \ JVM as the platform where it used to be unix.

14:21 mercwithamouth: =P

14:21 swarthy: bitemyapp: muhoo: like, how do I replace crontab with a cljoure app? message-queue? there is a lot of ambiguity for me now.

14:22 seangrove: bitemyapp: Missed a good talk last night, was pretty interesting the hear some of the insights from StaplesLab

14:23 muhoo: swarthy: wow. well raynes wrote a library to do cron pretty well. i'm about to start using it. there's core.async for messsaging inside the app, and libraris for using AQMP and such.

14:23 seangrove: I personally appreciated the differences between code and data

14:23 swarthy: that is mostly what I'm speaking about, but I realize that I didn't know anything about Unix either until I did.

14:23 muhoo: yeah, cool.

14:25 justin_smith: muhoo: better example (kill-new (second (nrepl-send-string-sync "(zipmap (map (comp keyword str char) (range 97 256)) (range 26))")))

14:25 swarthy: muhoo: I'll have to look into that crontab thing. I guess if I use ruby or python even if I don't understand what is happening I understand unix below it. Now I am just terrified because I learning clojure and learning the JVM is like learning to drive: only the car is a flying car.

14:25 but its fun though

14:27 ToxicFrog: swarthy: wait, are you writing a cron replacement in clojure?

14:27 swarthy: ToxicFrog: no

14:27 justin_smith: ToxicFrog: I think he means more that he once relied on being able to use cron, but that is not part of the jvm, and he is trying to do everything within the jvm as an ecosystem

14:28 though yeah, you can still use cron

14:28 swarthy: justin_smith: yeah that is mostly it. Not so much that I don't want to use it. But that the tools I once had don't make sense in this strange new land.

14:28 So its a fun thing learning the new ways.

14:28 bitemyapp: seangrove: there was a talk last night?

14:29 seangrove: dammit, meetup.com has failed me.

14:29 justin_smith: you could totally make cron send a request to your webapp

14:29 for example

14:29 egghead: gosh core.async is just so cool

14:29 swarthy: justin_smith: yeah like hit an api endpoint with curl?

14:29 justin_smith: right

14:29 patchwork: egghead: Agreed. It is so natural I don't know how I lived without it

14:29 clojurebot: You don't have to tell me twice.

14:29 bitemyapp: seangrove: yeah the SM meetup is on the 21st...what are you talking about?

14:30 ToxicFrog: I am now completely lost~

14:30 bitemyapp: seangrove: or are you at the conj?

14:30 swarthy: justin_smith: Yeah its just a very different platform and I'll have to learn to use it instead of the machine it's running on, and whatever patterns that brings about.

14:31 seangrove: bitemyapp: Nah, the QCon clojure talk

14:31 http://www.meetup.com/The-Bay-Area-Clojure-User-Group/events/146268902

14:32 muhoo: swarthy: take your time and read things first: code, books, etc. jumping in to a project under pressure with a new language on a new-to-you vm might not be the easiest way.

14:32 bitemyapp: swarthy: if thousands of people have done something, you can probably do it too.

14:32 swarthy: bitemyapp: ahaha. thanks.

14:32 bitemyapp: might take you a little more time or a little less time, but everything is doable.

14:32 except for proving P==NP

14:33 that's not really doable for most people.

14:33 swarthy: heisenberg uncertainty?

14:33 isn't that what that is? Or am I off?

14:33 bitemyapp: swarthy: I'm serious though, people put their goals/desires on a pedestal when most of what they want for themselves has been done many times before. World is your oyster yo.

14:33 no, but it's not the point

14:33 swarthy: bitemyapp: yeah I got you. I'm not saying I can't do it and I appreciate the pep talk.

14:34 muhoo: I have been going slow. I wanted to learn clojure but needed to learn Lisp first. So I started with SICP a few months ago.

14:34 trying to learn the platform itself now

14:34 bitemyapp: swarthy: don't worry, there's a bamboo cane to go with the pep talk if you slack off.

14:34 swarthy: bitemyapp: ahahah

14:34 bitemyapp: ^^ he thinks I'm kidding.

14:35 swarthy: bitemyapp: You were talking about seriously functional stuff the other day and possibly haskell if I remember correctly?

14:35 bitemyapp: swarthy: da

14:35 kinda, anyway.

14:36 swarthy: bitemyapp: how do you view haskell as a clojurist as well?

14:36 bitemyapp: I was talking about applicative functors as a more general alternative to ML-style modules.

14:36 swarthy: i've played with it a little.

14:36 bitemyapp: I'm not familiar with ML.

14:36 bitemyapp: swarthy: Haskell-esque type systems and languages are the future even if Haskell itself isn't.

14:36 core.typed is interesting.

14:37 swarthy: bitemyapp: In what way?

14:37 bitemyapp: we can't really "build upwards" unless we can trust the code underneath us to "just work"

14:37 that can't really happen with pure code, equational reasoning, and a useful type system.

14:37 without*

14:38 swarthy: have you every see gary bernhardt talk about functional core imperative shell?

14:38 bitemyapp: swarthy: I really enjoy Clojure, it's very practical.

14:38 swarthy: seen*

14:38 bitemyapp: swarthy: gary bernhardt is a self-important prick.

14:38 swarthy: bitemyapp: ahahah

14:39 I'll take that as a yes then.

14:40 You don't think that purely functional systems run into the same issues as purely object oriented. Ie: monads could be seen as a pattern in the way java design patterns are, trying to resolve a conflict brought about by extreme-ness.

14:40 bitemyapp: no, for several reasons

14:40 although it's a good question

14:40 swarthy: love the hear the counter argument

14:40 love to*

14:40 bitemyapp: for one thing, OOP design patterns are verbose and not composable. They're also typically not type system enforceable.

14:40 Monads are concise, mathematically clear, composable, and can be enforced by the type system.

14:41 I wouldn't say the two are comparable at all even if they solve *vaguely* similar problems

14:41 but they're vaguely similar problems arising from very different approaches.

14:41 OOP is DOA.

14:41 there's no hope without purity, OOP is too stateful. You just can't get very far with that.

14:41 some components of OOP are useful and Clojure intelligently ripped those parts off.

14:41 mdrogalis: strangemonad disagrees. He's out.

14:41 swarthy: mdrogalis: lol

14:42 mdrogalis: Leon Repl should make an appearance soon.

14:42 If I ever get in trouble with the authorities, I'm going with that as my name.

14:43 swarthy: bitemyapp: so if haskell is the start of the future, how does that reconcile with clojure's take on the future? or are they compatible in some ways?

14:43 muhoo: THE FUTURE

14:43 swarthy: muhoo: indeed

14:43 bitemyapp: swarthy: there are differences. Clojure is making the bare bare basics of FP more accessible to current programmers. That's extremely useful.

14:44 mdrogalis: ~future

14:44 clojurebot: mdrogalis: the fn created by future (like all fns) doesn't close over dynamicly scoped stuff

14:44 swarthy: bitemyapp: do you think that a person would benefit from learning in a more strict environment though? where purity is enforced like clojure and you can't rely on old ways as in clojure?

14:44 bitemyapp: On the negative side, Clojure seems to be optimized for people with perfect knowledge of their system, design, and dependencies.

14:44 swarthy: don't use the word strict, it's not descriptive here.

14:45 swarthy: sure, pure then

14:45 bitemyapp: swarthy: Haskell will teach you "more FP" than Clojure, but Clojure is a real pleasure to hack in. porque no los dos?

14:45 swarthy: you have to be functionall all the time

14:45 bitemyapp: Haskell has a lot of escape hatches, don't kid yourself.

14:45 you just shouldn't use them while learning.

14:45 swarthy: sure, and you can have both. I'm just quizzing you because you know more and are quickly filling gaps in my understanding.

14:45 justin_smith: swarthy: haskell has peek and poke

14:45 gf3: technomancy: I just wanted to say that leiningen is a pleasure to use

14:45 bitemyapp: swarthy: the rabbit hole goes deeper than Haskell too, if desired.

14:45 TT languages exist

14:46 swarthy: TT <- don't know that one

14:46 bitemyapp: type theoretic

14:46 Coq, Agda, Idris are good examples.

14:46 swarthy: Idris, love the name.

14:47 bitemyapp: swarthy: one of the key lessons of Haskell, Coq, Agda, and Idris is that the more power you give up, and the more declarative you are when you describe your needs to the computer, the more help you get from the computer.

14:47 swarthy: Yeah this is all cool stuff. After learning Lisp it lead to this FP revolution, and I find it all far more exciting than anything from python, or other OOP stuff.

14:47 bitemyapp: swarthy: eschewing turing completeness when it's unnecessary, for example.

14:47 or in a parsing context, shifting from a context sensitive to a context free grammar, or from a CFG to a regular grammar.

14:47 swarthy: bitemyapp: interesting on the power == reduction. did you see uncle bob's talk on Clojure as the last programming language?

14:48 bitemyapp: swarthy: I did. I disagree but it was flattering to Clojure anyway.

14:48 there will not be a "last" programming language

14:48 swarthy: bitemyapp: yeah, he conveys the: things get better the more we restrict ourselves which I find in line with a lot of what Hickey says as well.

14:49 AimHere: There will be. It's called 'Javascript'

14:49 TimMc: bitemyapp: There will, but not soon.

14:49 bitemyapp: AimHere: go to hell and die.

14:49 swarthy: bitemyapp: ahahha

14:49 TimMc: hahaha

14:49 swarthy: ahahha

14:49 wow I am truly LoLing.

14:49 that hurt

14:49 TimMc: bitemyapp: "How may entropy be reversed?"

14:49 danneu: i dont think it's easy to rely on old ways in clojure. now scala though, you can write it just like you'd write java

14:50 bitemyapp: which is one of the things I don't like about Java

14:50 er, Scala.

14:50 danneu: yeah, same

14:50 bitemyapp: Freudian slip, ended up coming out right anyway.

14:50 I would only agree to Scala if I could attach a taser equipped to fire upon typing "var" to my coworkers.

14:50 flatMap or fuck off.

14:51 rasmusto: bitemyapp: val ok w/ you?

14:51 danneu: hoping that coworkers opt in to FP in scala is like hoping they opt in to documentation

14:51 i dont like being hopeful

14:52 bitemyapp: rasmusto: not like point-free is nice in Scala.

14:54 OlegYch4: danneu: https://github.com/puffnfresh/wartremover

14:55 danneu: oh cute

14:55 cYmen: danneu: You get to do Scala at work? I envy you.

14:55 danneu: i dont

14:56 i dont work with scala*

14:56 swarthy: bitemyapp: so one last question, why is haskell the template for the last programming language but not the last language itself?

14:56 muhoo: bitemyapp will write a book one day. it'll be called "coding with ATTITUDE" and a taser will be included in the hardcopy book.

14:57 lumafi: cYmen, at my current company, i've only worked with scala and clojure 8)

14:57 cYmen: muhoo: or maybe the cover will have really pointy edges

14:57 muhoo: chapter 3 will be called "flatMap or fuck off"

14:57 cYmen: lumafi: Is that a one man company?

14:57 muhoo: chaper 4 will be "javascript go to hell and die"

14:57 lumafi: not even

14:57 cYmen: Do you hire? :p

14:57 muhoo: the cd companion will include death metal bands

14:57 lumafi: sure, you willing to relocate?

14:57 bitemyapp: swarthy: People have needs that vary too much for a single implementation to be the answer.

14:57 cYmen: lumafi: Where?

14:58 lumafi: finland ;)

14:58 bitemyapp: swarthy: and again, I think Haskell is *headed* in the right direction, it's not the final state at all.

14:58 swarthy: I would reiterate that things like Idris and Agda exist...

14:58 swarthy: bitemyapp: i see, and what idris and agda provide haskell is missing?

14:58 cYmen: lumafi: Have considered it but my gf is afraid the winter will make her too depressed.

14:58 bitemyapp: swarthy: dependent typing, for one.

14:58 danneu: Is there a way to sponge up all the non-nil-return calls in typed-clojure?

14:59 that's really been my only pain point so far

14:59 muhoo: cYmen: they get like 6 weeks paid vacation in europe, don't they? summers in sicily, south of france, ibizia, etc, must be nice

14:59 lumafi: muhoo, yep

14:59 4-6 weeks depending of the country

14:59 cYmen: muhoo: I'm in Germany and get 6 weeks of vacation and a mild, bright winter compared to Finland.

15:00 I once thought about going home from a bar in Helsinki because it was so late. It turned out to be about 8 PM.

15:01 isaacsanders: hell

15:01 hello

15:01 muhoo: huh, it was pitch dark out at 6pm here, in san francisco last night IIRC

15:01 damn PST8PDT

15:02 isaacsanders: Does anyone know how to access a logarithm function in clojure?

15:02 `cbp: Math/log

15:02 isaacsanders: I am fairly new, and I have not been able to use Math/log

15:02 danneu: when in doubt just google for the java answer

15:03 isaacsanders: I get "CompilerException java.lang.RuntimeException: Unable to find static field: log in class java.lang.Math"

15:03 `cbp: ,(Math/log 2.7)

15:03 clojurebot: 0.9932517730102834

15:03 swarthy: bitemyapp: cool. googled dependent types. Thanks for the FP brain dump! Learned a lot.

15:03 ,(Math/log10 1000)

15:03 clojurebot: 3.0

15:03 TimMc: bitemyapp: Misread that as "despondent typing". I guess that goes with Abject-Oriented Programming?

15:04 bitemyapp: swarthy: np

15:04 TimMc: totes. Match made in Hell.

15:04 isaacsanders: ,(print "my clojure doesn't work with it, does anyone have any ideas as to why?")

15:04 clojurebot: my clojure doesn't work with it, does anyone have any ideas as to why?

15:04 TimMc: http://typicalprogrammer.com/abject-oriented/

15:04 swarthy: isaacsanders: What do you mean by doesn't work? What is the error?

15:05 `cbp: isaacsanders: maybe you're forgetting the parenthesis?

15:05 isaacsanders: :P

15:05 it doesn't appear to exist as a value...

15:05 I feel dumb.

15:05 TimMc: isaacsanders: Math/log is a method, you can't pass it around like a function.

15:05 isaacsanders: ok

15:05 back to the code.

15:05 thanks

15:06 TimMc: If you want to map it across a collection, use #(Math/log %) or soemthing.

15:06 swarthy: TimMc: he left

15:06 TimMc: :-(

15:06 swarthy: very wham bam thank you mam of him

15:06 He should have at least stayed for a cuddle.

15:07 TimMc: Yeah, what kind of IRC user does e take me for?

15:07 swarthy: lol

15:16 mdrogalis: lol TimMc

15:21 pbostrom: does 'lein trampoline repl' not start an nREPL server?

15:27 clintnewsom: phostram: can't you just do lein repl :headless

15:27 then connect to that repl>

15:28 pbostrom: clintnewsom: I'll look into that; lein trampoline does some trickery so that only one JVM instance gets started, not sure if :headless does the same thing

15:30 TimMc: pbostrom: There are still 2 JVM invocations. trampoline writes out the invocation to a shell script, then launches it and dies.

15:31 IIRC there's a LEIN_FAST_TRAMPOLINE env var that caches those invocations so the first JVM launch can be skipped the next time around.

15:32 cYmen: Is there a way to write dependency entries like [ring/ring-jetty-adapter "1.2.0"] without the explicit version number? I am usually fine with the newest version...

15:32 guns: LEIN_FAST_TRAMPOLINE is great; just have to remember to bust the cache after restarts

15:34 pbostrom: TimMc: ah, right; in any case, I can't tell if lein trampoline repl starts the nREPL server, and if so, what port

15:35 edbond: cYmen, afaik version is required. Take a look a lein ancient plugin

15:36 TimMc: guns: Restarts?

15:36 guns: cYmen: I use "LATEST" for plugins in my profiles.clj; I wouldn't recommend for an actual project however

15:37 TimMc: /tmp/ is typically wiped on restarts

15:37 cYmen: guns: Yeah, I'm not doing anything productiony so far.

15:37 guns: machine reboot I mean

15:37 cYmen: guns: Thanks!

15:43 TimMc: guns: It doesn't handle that gracefully? Sounds like a bug.

15:43 guns: TimMc: I believe it's mentioned in the docs

15:45 cYmen: If I want to check for the presence of a session variable, can I use compojure routes for that?

15:50 swarthy: cYmen: you may want to look into lib-noir. I'm not very experienced with it myself but it wraps your route handles and provides session management.

15:50 cYmen: noooo

15:51 swarthy: sorry, just ...so many libs to learn

15:51 swarthy: its not really more than say rails. Its just they aren't all in one 'thing'.

15:52 cYmen: this book is worth it http://pragprog.com/book/dswdcloj/web-development-with-clojure

15:53 cYmen: hm...not sure if I should read that now, just after chapter 1 of "joy of clojure" :)

15:53 swarthy: well... if you are trying to make web apps in clojure that is the way to learn about it.

15:53 keep it in mind

15:54 cYmen: So it is actually a good book?

15:54 swarthy: i have joy of clojure as well and like that book

15:54 i think so, the guy who wrote it goes by yogthos, he is usually in this channel

15:55 you could ping him and ask questions if you need to.

15:55 cYmen: yogthos: Should I buy your book? O_o

15:55 bitemyapp: swarthy: joy of clojure wasn't written by yogthos.

15:55 swarthy: yogthos wrote Clojure Web Development.

15:55 swarthy: that is what I meant

15:55 we are talking about both

15:55 bitemyapp: Joy of Clojure is good, but it's not an intro book.

15:55 cYmen: Yeah, I got that.

15:55 yogthos: cYmen: yes? :)

15:55 swarthy: lol

15:55 bitemyapp: Clojure Web Development is a good way to learn idiomatic Clojure web dev with Ring.

15:56 it will not teach you alternative and less common stacks like Pedestal though.

15:56 yogthos: also it's a general intro to the language in the context of making web apps

15:56 bitemyapp: arohner: I'm allocating time at work to improve brambling.

15:56 arohner: cool!

15:56 bitemyapp: arohner: if you have requests other than the obvious need for incremental migrations, speak up!

15:56 cYmen: The Brambling (Fringilla montifringilla) is a small passerine bird in the finch family Fringillidae.

15:56 arohner: I haven't used datomic in anger yet

15:56 bitemyapp: cYmen: ding ding ding. that's it.

15:57 arohner: damn, well I'd better say something in #datomic then.

15:57 `cbp: anyone need some help with their open source

15:57 cYmen: yogthos: Thanks!

15:57 arohner: just a few demo projects, but I'm planning on using it in prod soon

15:57 yogthos: cYmen: np :)

15:57 bitemyapp: `cbp: you need another project? lol.

15:57 `cbp: want one off my list?

15:58 `cbp: bitemyapp: always moving on

15:58 bitemyapp: `cbp: https://dataset.readthedocs.org/en/latest/ for Clojure (or a stripped down Korma).

15:58 help me improve https://github.com/bitemyapp/brambling (if you care about Datomic)

15:58 `cbp: never used datomic

15:58 on the list of clojure things i need to try out :(

16:00 a korma with less macros? :-D

16:00 bitemyapp: `cbp: well either of those projects are options, the first one plays into your strengths nicely since you did a really good job on Revise.

16:00 `cbp: thanks

16:00 bitemyapp: `cbp: yeah a stripped down Korma with less macros, no complection with connection pooling.

16:01 `cbp: the python project I showed you is slightly different, I can explain it on Skype/voice if you want.

16:01 yogthos: speaking of korma, any plans on adding a way to initialize it with a given connection? :)

16:02 `cbp: bitemyapp: alright sure itll have to be at night though

16:02 bitemyapp: yogthos: sigh, that's kinda the micro-Korma I'm talking about.

16:02 * `cbp leaves to eat for an hour

16:02 bitemyapp: yogthos: it's going to be simpler to just have a clean break, refactor the API, and remove the direct dependency on things like c3p0

16:02 `cbp: catch me anytime that works for you.

16:03 indigo: Ooh, micro-Korma

16:03 lumafi: that reminds me, i need to file a bug report for korma when i get back to work

16:03 yogthos: it would be nice to modularize it a bit :)

16:04 bitemyapp: lumafi: please do :)

16:04 yogthos: you're telling me... *grumble grumble*

16:04 indigo: bitemyapp: You should call it Couscous, since it's tiny :P

16:04 yogthos: :)

16:04 lol

16:05 bitemyapp: indigo: not bad, but if it's `cbp's project on which I merely consult or assist, it's his to name.

16:05 indigo: he was asking me for ideas. I'll be working on Brambling at work and I really...REALLY need to work on Simonides.

16:05 pbostrom: if anyone here has a Twitter account and wants to try something fun, I wrote a Twitter REPL, just tweet some Clojure to @cwoio, the return value will show up as an @mention reply

16:05 bitemyapp: I'll help on something he does if it's interesting, but I *NEEEEEED* to launch Simonides.

16:05 indigo: bitemyapp: Good luck

16:06 mattmoss: If I have (filter pred2 (filter pred1 coll)), I can rewrite as (filter #(and (pred1 %) (pred2 %)) coll)... but wondering if there is a point-free way to combine pred1, pred2 and 'and' to make that new predicate.

16:06 bitemyapp: mattmoss: that's a Monoid!

16:07 mattmoss: and the way to do that is partial.

16:07 S11001001: bitemyapp: what does that look like?

16:07 bitemyapp: point-free isn't...great in Clojure.

16:07 S11001001: mattmoss: there's a variant of all in clojure.core that takes a list of predicates

16:08 mattmoss: Well, I realize that the point-free version might be more complicated than the #(...) version. Was wondering what it would look like tho.

16:08 S11001001: mattmoss: I forget what it's called, every-pred maybe? anyway that should do it

16:08 amalloy: every-pred, in fact

16:08 indigo: Bleh, libusb has no Clojure bindings

16:08 S11001001: ,(doc every-pred)

16:08 clojurebot: "([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps]); Takes a set of predicates and returns a function f that returns true if all of its composing predicates return a logical true value against all of its arguments, else it returns false. Note that f is short-circuiting in that it will stop execution on the first argument that triggers a logical false result against the original predicates."

16:08 bitemyapp: mattmoss: you'd have to go to some trouble to make it work, clojure functions aren't written with currying in mind, let alone point-free.

16:09 S11001001: ^^ mattmoss

16:10 bitemyapp: and a pain without types anyway, if you aren't using core.typed

16:10 mattmoss: Sure, understand that.

16:10 bitemyapp: S11001001: right.

16:10 cYmen: What does point-free mean in this context? Where is the point in #(and (pred1 %) (pred2 %)) and why does it matter?

16:11 S11001001: the %

16:11 bitemyapp: too bad 'and is a macro.

16:11 S11001001: no matter, every-pred is there

16:11 mattmoss: It's times when I see things like (filter... (filter... )) etc that I think there needs to be a nice way to compose those without getting all weird, and every-pred seems to be that,

16:12 bitemyapp: mattmoss: that's the idiomatic way, yes.

16:12 S11001001: conversely some-fn plays the same role for `or', mattmoss

16:12 mgaare_: every-pred has written the unattractive code, so you don't have to

16:12 TimMc: mattmoss: Put it all in a clojure.core/for :-D

16:12 S11001001: TimMc: ii eee

16:12 mattmoss: TimMc: Hmmmm.

16:13 bitemyapp: TimMc: that's like those python programmers that do everything in a list comprehension, ugh.

16:13 TimMc: It's not a *real* program unless you've got at least 3 :where and 2 :while clauses in a for.

16:13 Foxboron: bitemyapp: butbutbutbut...they are so cleane and easy to read

16:13 mattmoss: lol

16:14 S11001001: heh

16:14 bitemyapp: Foxboron: this is the same BDFL that killed off reduce.

16:14 Foxboron: bitemyapp: butbutbutbut, we got list comps!

16:14 we dont need map, nor filter, nor reduce!

16:15 S11001001: Foxboron: also have loops, no need for tail recursion

16:15 bitemyapp: have you ever tried to do a non-trivial fold in a list comp?

16:15 shit's insane.

16:15 Foxboron: S11001001: hahaha

16:15 bitemyapp: no i havent

16:15 bitemyapp: Foxboron: it's annoying.

16:15 mattmoss: Just someone explain to me how to break out of an outer loop from within an inner loop and there'll be no violence. KTHXBYE

16:16 S11001001: mattmoss: anyway, because every-pred and some-fn in a sense are mconcat for different monoids over the same type, it's easy to nest them arbitrarily

16:16 * bitemyapp high fives S11001001

16:16 bitemyapp: like I said, 'tis a Monoid. :D

16:17 mattmoss: Is a monoid a cool monad?

16:17 (inc bitemyapp)

16:17 lazybot: ⇒ 11

16:17 mattmoss: (inc S11001001)

16:17 lazybot: ⇒ 5

16:33 mikerod: ,(true? (Boolean. "true"))

16:33 clojurebot: false

16:33 mikerod: but why :(

16:34 opqdonut: because that's java for you

16:34 S11001001: ,(if (Boolean. false) 'yes 'no)

16:34 clojurebot: yes

16:34 mikerod: I know it is *bad*

16:34 S11001001: whatcha want

16:34 opqdonut: just don't use the Boolean constructor

16:34 mikerod: well yes

16:34 opqdonut: there was a Boolean/valueOf or something

16:35 mikerod: I think I am having an issue related to this, when doing java interop

16:35 What is the *reason* (true? (Boolean. "true")) is false ?

16:35 opqdonut: ,(if (Boolean/getBoolean "false") :true :false)

16:35 clojurebot: #<SecurityException java.lang.SecurityException: denied>

16:35 opqdonut: wow

16:35 mikerod: not sure I have figured that out yet

16:35 hah hmm

16:36 opqdonut: true? is defined as (clojure.lang.Util/identical x true)

16:36 nDuff: mikerod: Boolean/TRUE is a singleton. If someone follows the rules, checking for truthiness is an identity check.

16:36 mikerod: whereas a value check is slower / more expensive.

16:36 mikerod: oh

16:36 duh, it uses `identical`

16:36 I didn't notice that before

16:37 opqdonut: and what nDuff said

16:37 ,(true? (.booleanValue (Boolean. "true")))

16:37 clojurebot: true

16:37 opqdonut: if somebody is passing you weird Booleans, just sprinkle .booleanValue everywhere :)

16:38 nDuff: ...or go find them with a clue-by-four. :P

16:38 mikerod: so if I'm handed some java object, that doesn't use the Boolean/TRUE singleton and I call true? on it; I'm out of luck right?

16:38 well, .booleanValue

16:38 nDuff: mikerod: meaning you need to either fix their code or use .booleanValue.

16:39 mikerod: sounds good! :)

16:39 nDuff: mikerod: I'd call "fix their code" to be by far the preferable approach. Constructing new booleans is considered an antipattern in the Java world -- it's not just a pitfall when interacting with Clojure.

16:39 mikerod: nDuff: oh, I know. I think it is very stupid to have multiple instances of a boolean value.

16:41 indigo: Antipatterns, eh

16:42 ,@@@(atom (atom (atom "antipatterns, eh")))

16:42 clojurebot: "antipatterns, eh"

16:42 amalloy: TimMc: i went looking for the crazy pit of :when/:while/:let that i wrote a while ago, only to discover that ninjudd removed it

16:43 nDuff: don't forget java.io.ObjectInputStream, which deserializes to (Boolean. "true") and (Boolean. "false")

16:44 you can't really fix that one, sadly

16:44 nDuff: amalloy: thank you kindly -- I didn't need that faith in humanity, really.

16:44 danneu: I have a macro that almost works, but I can't figure out how to unroll it: https://www.refheap.com/20825

16:44 TimMc: amalloy: D-:

16:45 amalloy: danneu: there is simply no way to make one form expand to multiple forms

16:46 you could expand to (do (non-nil-return ...) ...), if that's sufficient

16:46 danneu: oh yeah, that's it

16:46 amalloy: also: klass is just gross. clojure doesn't have reserved words; you can name your classes class

16:47 danneu: habit -_-

16:47 amalloy: anyway, you want something like `(do ~@(for [[k & m] things :let [f whatever] method methods] (let ...)))

16:48 mikerod: So when you have a primitive boolean and you pass it to a method taking an Object, it is auto-boxed to one of the boolean singleton TRUE/FALSE?

16:48 amalloy: yes

16:48 mikerod: that is good

16:50 but ObjectInputStream sounds like a fail

16:50 danneu: amalloy: how could i unnest them once more? https://www.refheap.com/20825

16:50 amalloy: you could do literally what i just pasted

16:51 well, not pasted. typed

16:51 danneu: oh, i see

16:51 roll it into one for

16:51 thanks

16:51 amalloy: danneu: alternatively, if a complicated for is not to your taste, you can always flatten a list by one level with using (apply concat nested-lists)

16:52 TimMc: &(let [baos (java.io.ByteArrayOutputStream.) _ (doto (java.io.ObjectOutputStream. baos) (.writeBoolean false)) o (doto (java.io.ObjectInputStream. (java.io.ByteArrayInputStream. (.toByteArray baos))) (.readObject))] o)

16:52 lazybot: java.lang.SecurityException: You tripped the alarm! class java.io.ObjectInputStream is bad!

16:52 amalloy: TimMc: clojurebot will let you get away with it, i think

16:53 TimMc: I messed it up anyhow.

16:53 amalloy: yeah, it looks a bit confused

16:54 TimMc: I wrote a prim bool and read an object...

16:56 ,(let [baos (java.io.ByteArrayOutputStream.) _ (doto (java.io.ObjectOutputStream. baos) (.writeObject Boolean/FALSE)) ois (java.io.ObjectInputStream. (java.io.ByteArrayInputStream. (.toByteArray baos))) o (.readObject ois)] [o (if o "yes" "no")])

16:56 clojurebot: #<CompilerException java.lang.ExceptionInInitializerError, compiling:(NO_SOURCE_PATH:0:0)>

16:56 TimMc: ;;= [false "yes"]

16:56 Yeah, that's good times right there.

16:59 mikerod: good to know

17:00 wonder where the decision to allow booleans to be constructed as separate instances came from

17:00 I mean Booleans

17:02 mercwithamouth: is the oreilly clojurescript book worth purchasing?

17:03 i'm playing with enlive at the moment...which is 'cool' so far...but it seems if i want to do any client side work with clojurescript then enfocus is what I should take a look at?

17:07 seangrove: mercwithamouth: Well, one of them runs server-side, the other client-side, so presumably you'll have to pick the appropriate one

17:07 Is there a way to bulk-insert rows in postgres/sql/korma/jdbc?

17:08 mercwithamouth: seangrove: yeah i suppose anything else would be 'messy'. at first i thought the basics I would push some html from server side but to be realistic that's just a nasty mess waiting to be made.

17:08 nDuff: seangrove: yes, JDBC supports that.

17:09 mercwithamouth: at first i was sort of happy because it reminded me of what I saw when I played with liftweb for a few months...

17:10 nDuff: seangrove: ...though the JDBC method (which basically builds a prepared statement and executes it a lot) is going to be slower than whatever native bulk loader your database provides.

17:10 seangrove: That's something of a universal constant -- everyone all the way up to Oracle has a bulk loader that plays fast and loose on consistency checking, defers indexes, etc.

17:11 seangrove: ...but anyhow, the JDBC approach will be faster (by a lot) than inserting one statement at a time.

17:11 swarthy: seangrove: I was curious and google gave me this: http://viralpatel.net/blogs/batch-insert-in-java-jdbc/

17:12 seangrove: nDuff: Interesting, checking it out now. Wonder if it's smarter to just serially insert a few thousand rows

17:12 hadronzoo: Is there a standard way to find common default paths for different OSes (for example, ~/Documents for the documents directory on OS X, \User\My Documents on Windows)?

17:12 nDuff: seangrove: for just a few thousand, the JDBC interface for passing in a vector of argument lists with your query will be fine.

17:13 seangrove: it's when you're in the millions where you want to use the native bulk loader.

17:13 hadronzoo: In other words, is there a path abstraction library?

17:13 seangrove: nDuff: So you mean using the JDBC batch/prepared-statement interface is the way to go for ~10-100k rows at a time?

17:14 nDuff: seangrove: yup.

17:14 ...well, maybe not when you're closer to 100k.

17:14 seangrove: nDuff: Great, thank you.

17:14 nDuff: *shrug*. Would have to test at that phase.

17:15 seangrove: Yeah, that's completely fair, happy to run with it

17:15 nDuff: seangrove: anyhow, if you're using clojure.java.jdbc, see insert!

17:16 * nDuff is firmly in the Korma-considered-evil camp, and can't speak to it.

17:18 brehaut: nDuff: evil is pretty strong; i prefer half-baked

17:18 seangrove: nDuff: I prefer to avoid such hyperbolic statements at all costs; they're one of the worst things in the world.

17:18 swarthy: hadronzoo: http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#getProperties()

17:18 mattmoss: I just wrong #(% %2) in some code and feel weird.

17:18 *wrote

17:19 nDuff: s/evil/harmful/

17:19 bitemyapp: mattmoss: that's a little odd.

17:19 nDuff: seangrove: *grin*.

17:20 mattmoss: (condp #(% %2) expr pred1? (foo ...) pred2? (bar ...) :default)

17:20 swarthy: hadronzoo: so you could do (let [props (System/getProperties)] ...)

17:20 hadronzoo: if you wanted them all

17:20 hadronzoo: typically if you can't find something search for how to do that thing in java, then see if that answer has a lib\wrapper. If not then use the java interop.

17:21 hadronzoo: swarthy: Thanks you--very helpful. I have a database that I would normally place in /var/db or /usr/local/var/db on a *nix system. Do you know where would it normally be placed on a Windows system?

17:22 justin_smith: ,(System/getenv "HOME") ; a useful one hadronzoo

17:22 clojurebot: #<AccessControlException java.security.AccessControlException: access denied (java.lang.RuntimePermission getenv.HOME)>

17:22 swarthy: Sorry I don't know windows very well at all.

17:22 justin_smith: generalizing anything to windows is a pain

17:22 it wants to be "special"

17:23 hadronzoo: justin_smith: yes, that seems to be the way to go. Thanks.

17:23 justin_smith: also, (System/getenv) may give you other useful stuff if you run it on a Windows box to see what they set for you

17:25 hadronzoo: justin_smith: Yeah, I'll try that

17:25 justin_smith: ,(clojure.pprint/pprint (into {} (System/getenv))) ; more readable

17:25 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.pprint>

17:26 mercwithamouth: help?? i tried starting a clojurescript project with the 'mies' template but it fails https://www.refheap.com/20827

17:28 justin_smith: technomancy: does grenchman not have a windows binary because nobody built one yet, or because it just isn't windows compatible? I don't run windows myself but someone was looking for such a tool on stackoverflow (and I assume others are too)

17:28 hadronzoo: mercwithamouth: Try including [org.clojure/tools.reader "0.7.10"] in your project

17:28 mercwithamouth: hadronzoo: gotcha

17:29 hadronzoo: hrmm still no go

17:31 cYmen: How do I output stuff to the shell (probably stdout) from my compojure route function?

17:31 hadronzoo: mercwithamouth: I remember having that same problem and I thought that fixed it. What does your cljs file look like?

17:32 mercwithamouth: hadronzoo: core.cljs?

17:33 hadronzoo: https://www.refheap.com/20829

17:35 hadronzoo: mercwithamouth: try (.log js/console "Hello world!")

17:36 mercwithamouth: not sure why it's crashing, though

17:37 justin_smith: yeah, because of the way the . macro works (log "hi") does not get expanded into a macro invocation, log needs to be moved up a level (I think (. js/console log "hi") would work too)

17:37 mercwithamouth: harpreet_: still a no go

17:38 swarthy: justin_smith: yep that one worked in a fiddle as well

17:38 harpreet_: mercwithamouth: you surely didn't mean me. I am a lurker here with not enough chops to be a regular :-/

17:39 hadronzoo: mercwithamouth: try "lein cljsbuild clean && lein cljsbuild once"?

17:39 mercwithamouth: harpreet_: oops, sorry =P

17:39 hadronzoo: mercwithamouth: can you post you project.clj, too?

17:39 mercwithamouth: hadronzoo: ok

17:40 =( nope same error

17:43 swarthy: cYmen: you could do this https://www.refheap.com/20831

17:43 amalloy: justin_smith: (.log js/console "hi") macroexpands to (. js/console (log "hi")), so the advice to try switching between them can't be right

17:45 justin_smith: amalloy: my suggestion was differnet though, or maybe I misunderstand you

17:46 cYmen: swarthy: I suppose that was satiric, right?

17:47 amalloy: (. js/console log "hi") is exactly the same too, justin_smith. if you were suggesting something that isn't any one of those things, i can't tell what it was

17:47 justin_smith: ok, I did misunderstand, thanks for clarifying

17:48 brainproxy: suppose an s-expr in namespace A invokes a macro in namespace-B, and in the form passed to the macro there is a symbol c/d

17:48 cYmen: swarthy: I take it back, it actually works I must have screwed something up when I tried that earlier. Thanks!

17:49 brainproxy: when c is an alias per A, is it possible to resolve c/d to a var in the context of the macro

17:49 swarthy: cYmen: order is important. (do) evaluates everything inside but only returns the last item. So if your (layout/common) wasn't last you would have gotten a blank page or maybe a 404

17:49 TimMc: brainproxy: Then it will already have been expanded to my.namespace.ccc/d

17:50 brainproxy: TimMc: i find that is not the case

17:50 but the monkey wrench may be that that A is a cljs namespace while B is a clojure namespace

17:50 TimMc: Oh, well, who knows then? :-P

17:51 brainproxy: if c is not an alias, I can get to the var in the manner I want, namely to see if it points at another macro

17:51 but it's when c is an alias, that I'm stuck

17:51 TimMc: Oh wait, no, it's not already expanded -- that's done after macroexpansion happens.

17:52 Does resolve do it?

17:53 jamiei_: Any incanter pros resident this evening?

17:55 TimMc: brainproxy: Calling resolve on the symbol seems to work.

17:59 brainproxy: TimMc: I found it wasn't working

17:59 but are both namespaces normal clj in your case?

18:14 seangrove: Hrm, having a hard time getting the right call form to insert multiple rows in clojure.java.jdbc.sql/insert

18:16 amalloy: if both namespaces were clj-jvm, resolve would be the ticket. if A is cljs, god only knows

18:18 `cbp: seangrove: (insert! db :foos [:foo :bar] [1 1] [2 2] [3 3]..)

18:23 seangrove: `cbp: Looks like that works, was trying to use the new clojure.java.jdbc.sql/insert fn rather than the old insert! one, but maybe that's the problem

18:23 Thanks for the hint

18:55 _scape: in core.async what is (chan buffer-size) referencing? bytes?

18:58 guns: _scape: Queue size in items

18:58 _scape: https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async/impl/channels.clj#L31

18:59 scape: dang irc client pooped out

18:59 guns: scape: https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async/impl/channels.clj#L31 if you missed it

18:59 scape: thx, i did

19:14 guns ok, i got it. so specifying a buffer size of 0 holds 1 element, since it's like an array/queue; correct?

19:14 guns: scape: I guess it depends on what you mean by "hold"

19:15 scape: blocks :D

19:18 guns: yes, IIRC (chan 0) acts like a TransferQueue

19:18 you might want to test that

19:19 scape: ok

19:19 thx

19:20 size 0 and no size specified seem to act the same.

19:20 if using <!! in a regular thread

19:23 swarthy: is dotimes roughly equivalent to (let [...] (do ...)) ?

19:24 hmm, does not appear so.

19:25 guns: scape: Did you want the producer thread to block after put?

19:27 scape: I think I figured out what I was looking for. Basically I want to spin off a thread to do IO, then block while putting on a channel. in the main thread I want to periodically check the channel to see if the other thread is done, checking while not blocking itself.

19:27 guns: for what I am doing it's important for the main thread to not block but to also be able to basically do a callback to itself

19:28 ambrosebs: danneu: do you want to add all non-nil-return calls to the checker?

19:28 guns: scape: and you want a bounded queue for rate limiting I suppose

19:39 danneu: ambrosebs: i wrote a macro to clean up my non-nil-return calls. i don't know yet if i'm just Doing It Wrong but it works for now

19:45 I have no java experience, but i imagine non-nil-return is necessary because looking up the java method indicate that it can return null

19:46 so that must be why the checker expects (U Thing nil), but it so happens that the java method never actually should be nil in my code, so i have a stack of non-nil-returns

19:46 lynaghk: ping: hugod

19:47 scape: guns: i do not want it to block the main thread.

19:48 danneu: ambrosebs: https://www.refheap.com/20837 i couldnt seem to find a simple way to express this so i wrote a macro

19:48 ambrosebs: danneu: yep that's the right way to do it

19:50 danneu: although it could be more hygienic. Use `non-nil-return

19:50 mattmoss: Is one of these preferred, when expr1 could be nil? (or (expr1 ...) (expr2 ...)) vs. (if-let [v1 (expr1 ...)] v1 (expr2 ...))

19:51 Hmm, seems that's basically what "or" does.

19:54 danneu: mattmoss: yeah, 'or' is clearer if that's your intention

20:06 Is (Class/forName "[B") the best we've got for defmethod byte-array dispatch

20:07 I'm still cruising with the first stackoverflow answer i found a year ago

20:07 but it seems to cause trouble with typed clojure

20:09 richo: I've got an app that starts a bunch of threads inside another clojure app via it's nrepl interface. The problem is that when I ctrl-c that container app, it doesn't die (because I'm calling starting a bunch of threads, then joining them, I think). Is there a better way to structure this/how can I make sure that ctrl-c kills all the threads?

20:10 justin_smith: richo: you could run (System/exit 0) rather than sending a control-c

20:10 richo: From the process that pokes at it's repl you mean? Right now I've got a script that lights up a dev environment in a bunch of tmux panes

20:11 and you can kill everything by just mashing ctrl-c except the riemann instance, which refuses to die

20:11 but if I don't do the "jack in and start threads" part it dies fine, so I'm pretty sure that's where the problem is

20:11 justin_smith: how are you starting the threads?

20:12 richo: justin_smith: https://gist.github.com/7459554

20:12 justin_smith: if you are using agents, you may need to call shutdown-agents

20:12 richo: I think they're just java threads under the hood

20:12 justin_smith: yeah, you are just making Thread. calls, so shutdown-agents is not needed

20:13 are you doing any aggressive try/catch that may catch the control-c signal and keep going rather than exiting?

20:13 richo: I don't think there's a single try/catch in my entire codebas

20:13 justin_smith: aggressive as in catch on Exception or Throwable rather than a subclass

20:14 richo: and yeah, if I don't call that mainloop fn then riemann just dies on the ctrl-c so I'm like 99% sure that's where the issue lies (does that sound right?)

20:14 Sorry, pretty new to clojure and super new to the jvm

20:16 justin_smith: do you have a repl open in that vm? if so, see if evaluating (System/exit 0) in that thread exits

20:17 richo: I can start one. One sec

20:17 Yeah, it does.

20:18 I'm reading through riemann's source and the only signal I can see it explicitly handling is HUP, but I can duplicate what it does to co it and arrange for INT to call System/exit

20:18 Thanks, if this doesn't work out I'll probably be back with more questions soon

20:23 Actually, the other option is to just define exit! somewhere and document that you should poke at that from the repl

21:17 muhoo: clojure.tools.trace saves my ass yet again

21:27 bitemyapp: muhoo: see? :)

21:29 Raynes: bitemyapp: Oh, he sees. He seems.

21:29 sees*

21:30 I've been working with dictionaries so much today that I forgot how to spell 4 letter words.

22:25 echo-area: Meta data prepending a macro calling form is discarded after the macro is expanded, right?

22:26 I.e. the meta data is set to the macro calling form

22:26 Not the result of the macro expansion

22:31 TimMc: echo-area: I seem to recall that the meta data is supposed to be attached, but that some macros ended up discarding it, and that this was considered a bug.

22:32 S11001001: TimMc: I went and found the place in Compiler.java that discards this, once; I don't think it would be hard to put it back

22:32 echo-area: Meta data seems to be only hints to compiler with this respect

22:32 S11001001: TimMc: except for deciding what parts to put back

22:33 echo-area: For example, (let [m 4, n ^{:abc String} m])

22:33 TimMc: http://dev.clojure.org/jira/browse/CLJ-865

22:34 echo-area: Here meta data is attached to the symbol `m' read by the reader, not the value of `m' (which is of course not able to have meta data attached)

22:35 TimMc: Ah that's exactly what I was talking about :)

22:37 And it has a recent update (less than a month from now). Maybe it'll be merged into upstream in the next version :)

22:39 Wait, the last comments indicate that it has already been merged

22:39 ... or not

22:53 blr: is there a reason why domina's listen! doesn't take a map of events?

22:55 that would seem like a more natural api

23:02 bitemyapp: `cbp: DotA2?

23:02 john2x: how do I let `lein repl` show a full stacktrace on exceptions?

23:03 `cbp: bitemyapp: sorry a little to tired >_<

23:03 too*

23:03 bitemyapp: `cbp: aw it's okay :)

23:03 seangrove: blr: Probably worthwhile to look at dommy and its listen methods

23:03 `cbp: bitemyapp: new revise version, pretty easy to compose the api into new helper fns

23:03 :p

23:03 clojurebot: excusez-moi

23:05 blr: seangrove: thanks, will have a look, have only looked at domina at this point

23:07 bitemyapp: `cbp: awesome. :)

23:08 `cbp: bitemyapp: now to figure out how to implement an efficient `let` query

23:08 bitemyapp: `cbp: that's recursive queries.

23:09 `cbp: we'd probably want to ask Slava and crew at RethinkDB if they had any plans for that.

23:09 `cbp: oh

23:10 bitemyapp: `cbp: it wouldn't be substantially different than the "inefficient" version you're likely thinking of, but it would at least execute on their end instead.

23:11 and could be processed lazily.

23:11 `cbp: lazyness is another issue

23:11 bitemyapp: `cbp: I take it we're not right now?

23:11 seangrove: Slava should be contributing to Clojure by now, what with his lispy nature

23:12 bitemyapp: seangrove: oh you know him too?

23:12 `cbp: bitemyapp: nope

23:12 bitemyapp: I guess I shouldn't be surprised.

23:12 seangrove: bitemyapp: Just a few mutual friends ;)

23:12 bitemyapp: `cbp: run-lazy? :P

23:12 seangrove: I knew of him through CL, then I talked to him about Revise awhile back.

23:12 he doesn't really know who I am though.

23:13 `cbp: I am not entirely sure how to leverage the rdb api to implement that though

23:13 some sort of pagination?

23:13 bitemyapp: `cbp: oh yeah, pagination.

23:13 possibly with chunking for efficiency :\

23:13 which...is...ow.

23:14 `cbp: split an insert/update/select into multiple queries hm

23:14 multiple runs i mean

23:14 TimMc: john2x: *e contains the last exception; (pst) will pretty-print the stack trace for *e

23:16 john2x: TimMc: Thanks. Hmm, the stacktrace isn't as helpful as I'd hoped.

23:16 bitemyapp: `cbp: if you're serious about that, it'd be a good time to think about how Clojure's laziness is implemented, especially chunking.

23:17 john2x: I'm getting "ClassCastException java.lang.String cannot be cast to clojure.lang.IPersistentCollection", apparently from a conj, but I'm not using conj anywhere in my code. And the stacktrace is all from clojure.core/ so I can't track down where it's going wrong

23:17 `cbp: heh yeah gotta read up on that

23:17 bitemyapp: I wonder if pagination + a lazy-seq wrapper might work as a first pass though.

23:19 swarthy: what is the best way to destructure the key/val pairs of a hash, while using map, reduce, etc.?

23:19 I wrote an anon func to do it, but is there something more built-in?

23:19 or idiomatic rather

23:20 S11001001: swarthy: depends on whether you're writing lambdas

23:21 swarthy: ;(map <lambda-here> the-hash) is how I did it now. I was wondering if there was a better way, or a built-in function that does it better.

23:21 because I want to use the key and val for the return

23:22 Basically taking a hash and making a table with hiccup.

23:29 TimMc: john2x: Sounds like you're passing in a string *somewhere* where you should be putting in a collection. I'm guessing you have some args swapped.

23:29 &(into "foo" [1 2 3])

23:29 lazybot: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IPersistentCollection

23:30 TimMc: ^ like that

23:31 S11001001: swarthy: it's perfectly fine to just use map on hashes, like, whatever

23:32 swarthy: there isn't really anything to do to make it more convenient

23:36 swarthy: S11001001: cool thanks. I just wondered if there was a better way to use the key and val in the lambda instead of (fn [[key val]] ...) when you know you want both.

23:37 S11001001: i'm probably just over thinking it, thanks for your help

23:48 john2x: TimMc: Thanks. I'll take a look

Logging service provided by n01se.net