#clojure log - Apr 22 2014

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

0:41 patrickod: I'm trying to use cemerick/friend for the first time to protect a small set of resources, specifically using it's interactive-form workflow

0:43 I have a map of users in the form that friend expects, but when friend/authenticated runs it gives an error: clojure.lang.PersistentVector cannot be cast to java.lang.String

0:43 in the interactive-form-redirect method

0:44 s/interactive-form/interactive-login

0:46 dbasch: patrickod: can you refheap your code?

0:47 patrickod: refheap? new to clojure so unsure what this means.

0:47 dbasch: https://www.refheap.com/

0:49 patrickod: cool. I'll get that in a second

0:56 https://gist.github.com/anonymous/c68214623cb1ae122f1c

0:59 dbasch: I meant the code, otherwise who knows what’s going on :)

1:01 beamso: hsa the login-uri been configured as a vector rather than a string?

1:01 *has

1:02 patrickod: login-uri is a string.

1:07 https://gist.github.com/anonymous/aa3cd2c198200d6e79e9

1:08 admins-for-login gives back a map of {"username" {:username "username" :password "bcrypted-password"}}

1:11 dbasch: why are you passing (admins-for-login) instead of admins-for-login ?

1:11 never mind

1:20 I would wrap everything in a handler that prints the requests and responses for debugging

1:38 john_s: does anyone else find the behavior of core.async channel filters counterintuitive? every time i create a filtered channel, it consumes everything up to and including the first item for which the predicate is true.

1:40 e.g. https://gist.github.com/johnswanson/11166363

1:42 i guess that is just the way channels work, you can't see if a value passes without pulling it off.

1:43 trap_exit: what's a good profiler for javascript code generated by cljs?

1:59 haole: is there an easy way to compare two lists discarding a few items? like:

2:00 one list has '(1 1 0 1) and the other '(1 1 1 1)

2:00 I want them to be considered the same, as if I could have a wildcard in the = function

2:00 '(1 1 _ 1)

2:01 dbasch: haole: how do you decide what items to discard?

2:01 haole: or how many?

2:03 haole: dbasch: that's what I'm trying to figure out... using a format string, maybe, or some other way

2:03 luxbock: is there any way to get a string value out of a java.io.PrintWriter without first writing it to a file?

2:04 beamso: StringWriter?

2:05 luxbock: sorry I'm not very good with Java, how would I use that?

2:06 beamso: actually, it was a bit of a silly suggestion. you don't instantiate the printwriter, correct?

2:06 luxbock: yeah

2:06 I have a Java class that's meant to be used as a CLI app, so the public method it offers (main), outputs to PrintWriter(System.out) and then exits, and I'd like to use its output without having my program exit

2:07 which I guess I could do by using java.sh, but I discovered ironh for Clojure which allows me to call private methods/constructors via reflection

2:07 beamso: can you change the java class?

2:08 luxbock: but the method I need to call still uses PrintWriter

2:08 hmm, I suppose I could, it's a class file in a .jar

2:08 that I'm peeking into through a decompiler

2:09 so yeah I think it would be possible but probably not the easiest thing to do

2:09 beamso: you can use system.out to set a printstream

2:10 but that sets it for everything, which may or may not be nasty

2:11 luxbock: I could just give it a PrintWriter and a temp file that I then read and destroy, since this is just a personal project

2:12 beamso: you can instantiate the printwriter with a bytearrayoutputstream, then call tostring on the bytearrayoutputstream

2:13 luxbock: ah, that sounds great, I'll try it out

2:17 dbasch: haole: if you care about the number of equal values but not the position, it’s trivial

2:17 haole: and if not, it’s still pretty easy

2:17 ,(map = [1 2 3 4] [1 2 3 5])

2:17 clojurebot: (true true true false)

2:18 dbasch: haole: you’d need a “mask” list to compare that output

2:18 luxbock: beamso: works fine, thanks :)

2:18 beamso: not a problem

2:48 bitemyapp: zerokarmaleft: yo

2:48 nevermind, tracked you down

2:50 devn: anyone have an example of using map<, map>, etc. in core.async?

2:50 I can't seem to find anything outside of the docs

2:55 danlamanna: for some reason my compiled jar (lein uberjar) doesn't recognize command line arguments (using tools.cli) as lein run does.

3:49 nonuby: if there a way to (easily) test if such namespace exists when doing something like (doseq [plugin plugins] (require (symbol plugin)))? rather than a filenotfoundexception

3:52 guns: nonuby: It's not a bad way to do it; you'd have to search the classpath yourself otherwise. Just wrap in a try/catch

4:02 dbasch: ,(all-ns)

4:02 clojurebot: (#<Namespace clojure.uuid> #<Namespace user> #<Namespace clojure.core> #<Namespace sandbox> #<Namespace clojure.repl> ...)

4:02 dbasch: ,(count (all-ns))

4:02 clojurebot: 9

4:45 nonuby: is there anyway to emulate http://nodejs.org/api/domain.html when using clojure 1.6/core.async/http-kit rather than explicitly passing the context along

4:51 ddellacosta: nonuby: I'm having a hard time understanding what that does--does it directly map to the url domain?

4:52 nonuby: if a problem occurs in any given route matching a domain, you can perform the same action, is that it?

4:54 nonuby: no. essentially it allows you to pass context along a chain of async operations (without explicitly passing it into a callback each time), kind of like a thread-locals that work across multiple threads - so if you have a web request that calls a database that then calls a url you have a the original details of the request (if you stuffed it in a domain on entry)

4:55 ddellacosta: nonuby: huh, and are you using ring in Clojure?

4:56 nonuby: just thinking out loud at the moment, but probably not ring as will have a thread hanging about whilst any other dependent async operations complete, http-kit server maybe

4:57 ddellacosta: nonuby: I see, so tell me if this is wrong: you're building something that has asynchronous processing based on a request, but you need to hold onto the original request for various reasons

4:58 nonuby: ...and get it back at some point during the asynchronous processing thread's lifespan

4:58 nonuby: ddellacosta, very close, i want to hold a map of the original request, because as part of high level error handler and logging middleware (json logging), I want to pluck the request context out as that what makes any errors/warning relevant

5:00 ddellacosta: nonuby: so, is the request going to get handled asynchronously, or do you just want your high-level error handler/logger to be asynchronous? I don't quite follow

5:00 AeroNotix: ring-middleware?

5:01 nonuby: if using thread per request I would just write (myapi/set-context! { :req ring req }) at the entry point of the request and then shove it into a thread local var, do my database stuff and other IO, and then in the error handler / logging middleware I could do (my-api/get-context) but if I say scrape a URL on a request using http-kit and the exception occur in the http-kit client callback this on a different thread thus get-context would be nil

5:03 ddellacosta: ah, sorry, I thought you were using http-kit server, not client, my mistake

6:13 antelocm: hi

6:14 I'm looking for help developing Clojure GUIs

6:15 anything like React/Om, but with JavaFX components

6:15 clgv: antelocm: in swing? do you know "seesaw"?

6:15 antelocm: any ideas?

6:15 clgv: oh ok

6:15 antelocm: based on FRP, if possible

6:15 clgv: I think some people started clojure libs for javafx but I dont recall the named.

6:16 *names

6:16 antelocm: yeah, had a look at them

6:16 but they are not very idiomatic

6:18 clgv: you need javafx for legacy reasons or since there are existing components for specialized tasks?

6:20 antelocm: actually, I'm learning Clojure, so I thought JavaFX is the best for trying a modern UI

6:22 but I'd like to try FRP too

6:23 and there's clojurescript's Om

6:24 so I'm looking for something Om-like, but with JavaFX components

6:25 clgv: ok. I didnt here of any library trying that combination on the mailing list so far...

6:30 locks: maybe start with Om ;P

6:30 clgv: *hear

6:32 antelocm: ok, will try that, thx ;)

6:33 bye :)

6:36 khushildep: Hey chaps - I’m trying to follow the guide at http://marmalade-repo.org but when I package-list-packages it can’t seem to find the repo? I can browse to it normally...

6:47 phillord: @khushildep what are you expecting to see? You should just got a longer list of packages

6:48 khushildep: Yeah I did but the it doesn’t seem to want to connec to marmalade

6:50 phillord: did you do M-x package-refresh-package

6:51 M-x package-refresh-package-contents sorry

6:51 what does C-hv package-archives show you?

6:58 khushildep: [No Match]

6:58 I’m sorry I’m an emacs noob - what does C mean?

6:59 Bronsa: khushildep: ctrl

6:59 phillord: Ctrl

7:00 clgv: does "quil" support scrollbars for drawings that do not fit the screen?

7:00 phillord: You can do "help->Describe->Describe Variable" instead if you prefer

7:01 khushildep: package-archives is a variable defined in `package.el'.

7:01 Its value is (("marmalade" . "http://marmalade-repo.org/packages/&quot;)

7:01 ("gnu" . "http://elpa.gnu.org/packages/&quot;))

7:03 phillord: Okay, now Options->Manage Emacs Packages

7:03 do you see a list of packages?

7:04 if so, then Package -> refresh package list

7:05 If you see things like "abl-mode, ac-geiser, ac-slime" then you have added marmalade and it's all working!

7:06 If it's not all working then you should have got a crash somewhere!

7:06 nbeloglazov: clgv: no, it doesn't

7:07 khushildep: how would I debug that crash?

7:09 clgv: nbeloglazov: :(

7:16 phillord: well, you need to describe it

7:16 do you have any thing inyour *messages* buffer -- that normally helps

7:17 nbeloglazov: clgv: you can implement your own "scrolling" by dragging mouse using translate function, I think.

7:18 clojurenoob: hey guys, I'm using assoc to add a value from one map to another map... when I do so, my keys/values lose their double quotes and I get 'Map literal must contain an even number of forms Util.java:221... any ideas ?

7:19 AimHere: clojurebot, you got a minimal code example exhibiting the bug?

7:19 clojurebot: Titim gan éirí ort.

7:20 AimHere: sorry, clojurenoob I mean

7:20 clojurenoob, Also, merge-with is a handy function for these kinds of problems

7:20 clojurenoob: AimHere: I will put something together and lookup your suggestion thx

7:20 AimHere: ,(merge-with + {:a 3 :b 4} {:a 10 :c 15})

7:20 clojurebot: {:c 15, :b 4, :a 13}

7:22 clgv: nbeloglazov: sure, but thats a lot of overhead to manage viewports myself. I wouldnt reimplement it in swing neither ;)

7:22 clojurenoob: completely different topic.. how do I add an item to the end of a list ? (it needs to be a list in this case)

7:24 AimHere: Thing about lists is that adding things to the end is not optimal. You could put it in a list and use concat

7:25 clojurenoob: oh right... so add either a list or vector using concat

7:26 AimHere: Yeah. If you're appending to the wrong end of a list a lot, then reconsider the data structures you're using

7:26 clojurenoob: AimHere: thanks, I've got to use list in this case as its a kind of code generation thing

7:32 clgv: clojurenoob: you can use a vector to create the code and call `seq` on it afterwards

7:32 ,(defmacro foo [] (seq [inc 1]))

7:32 clojurebot: #'sandbox/foo

7:32 clgv: ,(foo)

7:32 clojurebot: #<ExceptionInInitializerError java.lang.ExceptionInInitializerError>

7:32 clgv: damn bot. worked overhere...

7:33 clojurenoob: clgv: thanks, that may solve both problems will try it... was doing some code generation using '() etc all pver the place

7:33 gfredericks: ,foo

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

7:33 gfredericks: ,(foo)

7:33 clojurebot: #<ExceptionInInitializerError java.lang.ExceptionInInitializerError>

7:34 gfredericks: ,(defmacro bar [] (seq '[bar 1]))

7:34 clojurebot: #'sandbox/bar

7:34 gfredericks: ,(bar)

7:34 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox/bar>

7:34 gfredericks: ,(doc bar)

7:34 clojurebot: "([]); "

7:34 gfredericks: oh of course

7:34 ,(defmacro bar [] (seq '[inc 1]))

7:34 clojurebot: #'sandbox/bar

7:34 gfredericks: ,(bar)

7:34 clojurebot: 2

7:35 gfredericks: clgv: you were emitting a function instead of a symbol

7:35 that usually works though

7:36 clgv: gfredericks: oh right sorry ^^

7:37 ,(list? (seq []))

7:37 clojurebot: false

7:37 clgv: ,(list? (seq ['inc]))

7:37 clojurebot: false

7:39 clojurenoob: hmmm. its nicer now I'm using vectors and 'seq' at the end... but keys/values I pull out of maps are still losing the quotes ... unsure why

7:41 clgv: clojurenoob: provide a small example on refheap.com

7:41 clojurenoob: clgv: ok thanks I will try to make one

7:51 clgv: weird... finding it hard to re-create when working in REPL with data I specify manually... but using the output of prior calculations in my program I am getting this problem...

7:51 perhaps I am assuming the type of the output incorrectly... should be a sequence of maps

7:53 hmmm... its a LazySeq I am mapping over

8:00 Pate_: waht is the difference between doall, dorun and doseq?

8:02 clgv: Pate_: the first two are very similar. doall forces evaluation on the lazy seq and returns that evaluated seq. dorun is intended for sideeffects since it foreces the lazy seq but does not return the seq havin the advantage that it does not keep a reference to the head of the sequence.

8:02 Pate_: "doseq" is "for" for side-effects

8:04 Pate_: thanks. I'm finishing up Google Code Jam 2014 and I'm using "doall" to ->> solutions (map println) to write to stdout, otherwise I don't get output. Should I be using doseq instead so I don't hold on to the seq?

8:05 hmm no, looks like I should be using dorun.

8:06 clgv: Pate_: yes for minimal changes to your current impl you should use dorun. but usually it's more idiomatic to use doseq here

8:06 Pate_: (doseq [sol solutions] (println sol))

8:06 Pate_: excellent

8:06 clgv: Pate_: or (doseq [sol (->> what ever you need to do to create solutions)] (println sol))

8:07 Pate_: thx, clgv.

8:07 clgv: np

8:07 Pate_: parsing stdin with clojure took me a long time to get right in clojure

8:08 clgv: Pate_: are you doing the practice problems as preparation?

8:09 Pate_: yeah. was travelling during qualification round, so didn't get a chance to compete.

8:09 busy with minesweeper problem (C) now

8:09 will put on GitHub when done and paste link here for those interested

8:10 clgv: you got a link to that problem?

8:22 sm0ke: hmm weird om doesnt seem to work on ubuntu in chrome

8:22 this binary clock demo at least does not work

8:22 http://www.lexicallyscoped.com/demo/binclock/

8:27 Pate_: clgv, https://code.google.com/codejam/contest/2974486/dashboard#s=p2

8:44 certainty: hello everyone. I don't know much about Java but apparently I need to use a library that is in org.apache.commons.net. What does a dependency declaration for that look like in project.clj? How do I generally know what it looks like?

8:45 beamso: add [commons-net "3.3"] to your list of dependencies

8:46 certainty: beamso: thanks. How do I know that?

8:46 beamso: to quickly test it, use lein deps to download it

8:46 edit the project.clj

8:46 certainty: yepp i just did :)

8:47 beamso: so it worked?

8:47 certainty: at least it downloaded the dependencies. I'm currently trying it out at the repl.

8:48 alright, I can (import) the class I need. Thanks again :)

8:49 turbopape: I worked w java from clojure. Quite straight forward, but you have to master the different interop forms, etc....

8:49 but one you get it, it is rewarding:)

8:50 And setting a polyglot project with lein is quite easy too, you specify a java-source path and you can write your own java classes, quite cool !

8:52 certainty: turbopape: i try to avoid java as i don't know it well. At some point however it seems as if i will have to learn some more

8:53 turbopape: Actually I try to avoid it too certainty, but sometimes, you unfortunately must use some libraries...

8:53 for me, I wrote a couple simple binary file writers/readers, just for the sake of speed...

8:54 I'm not even sure that it makes sens with 1.6 using java.nio ?

8:54 certainty: hmm, if i only knew how to convert an ipaddress from dotted quad string representation to a long value in java

8:55 then I could ditch the dependency which would be great :)

8:56 turbopape: Well certainty, If there's already one efficient java class to do it, why bothering ?

8:56 certainty: because of the dependencies :)

8:56 DerGuteMoritz: certainty: see #chicken :-)

8:56 turbopape: I understand, but time to deliver outweight the deps right ?

8:57 besides, lein manages this for you , for free !

8:57 ah by the way, I didn't do any java before :)

8:57 I did it thanks to Clojure (strangely enough) ...

10:09 octe: is it possible to get a reference to the constructor of a class as a function?

10:09 to be able to do for example (apply Date. 1234)

10:11 apparently not

10:11 clgv: Pate_: nice problem. I heard that some variant of minesweeper is NP-hard but I am not 100% sure it is that one ;)

10:12 octe: wrap it in a function

10:12 octe: yes

10:12 clgv: octe: you could also have a function that returns such a constructor wrapper function via reflection

10:12 Pate_: I did not understand the problem at first (that the recursive revalation stops at a cell when it neighbours a mine), but finally realized it after careful reading.

10:13 octe: i wanted to make a function that could call a constructor of a class with any number of arguments

10:13 but that seems to require reflection

10:14 Pate_: when you think of some examples that work or not, it is easy to see that the solution must consist of overlaid rectangles of clear areas that are at least 2 high and 2 wide.

10:14 jwm: are there any mutable data libraries?

10:15 I find it hard working with maps/vectors

10:15 octe: though clojure should be doing this internally somewhere?

10:15 finding the correct constructor to call

10:15 jwm: seriously miss = sometimes

10:15 octe: based upon the type of parameters

10:15 jwm: hehe

10:16 clgv: octe: yes it is using reflection to determine that

10:17 octe: if it can not determine the matching constructor and you enabled relection warnings you'll get a warning

10:17 jwm: can you pass two alters to one dosync?

10:17 I thought dosync implies (do)

10:17 octe: clgv, is there any way to reuse that logic in my code?

10:18 clgv: octe: not without implementing several functions/macros to do that.

10:18 octe: what exactly is you use case?

10:19 octe: clgv, in the same class i'm juggling 4 different date-classes (ugh)

10:20 so i wanted to make cvonvience functions for creating instances of them

10:21 but if it's that painful i'll just do this instead:

10:21 http://pastebin.com/npz74GMN

10:21 for each class

10:21 unless you can alias java imports?

10:22 because the issue is having to write (net.fortuna.ical4j.model.Date.) due to namespace collisions

10:22 clgv: you cant

10:22 octe: then i'll settle for the simple solution i pasted :)

10:22 clgv: but you could write a macro to generate the functions so that you only need a macro call per class

10:23 llasram: You might also find symbol-macrolet useful https://github.com/clojure/tools.macro

10:23 clgv: octe: you then need that form: (new the-class param1 param2 ...)

10:23 llasram: NB that the example in the project README is pretty weird -- it shows of specially handling of special forms, not what symbol-macrolet generally does

10:24 s,shows of,shows off,

10:25 octe: hmm, thanks :)

10:27 gfredericks: is there really not a core.async function to create a lazy seq over a channel?

10:27 clgv: nbeloglazov: ping

10:27 nbeloglazov: clgv: pong

10:28 clgv: nbeloglazov: is there an easy way in quil to get an image of a sketch that I can use as return value of a ring request?

10:28 some imagestream or similar

10:28 mdrogalis: gfredericks: I think the problem with that is that you'd have to know the entirety of the contents of the channel.

10:28 There's not much a built-in concept of "end".

10:29 gfredericks: mdrogalis: what? the channel closes and it's done

10:29 once you get nil

10:29 (defn ch->lazy-seq [ch] (lazy-seq (when-let [x (a/<!! ch)] (cons x (ch->lazy-seq ch)))))

10:29 hlship: Yes, but it implies that the code reading the channel wants to block while the values are pushed into the channel.

10:30 mdrogalis: gfredericks: Yeah, I guess what I mean is, without closing it, you don't get that kind of behavior

10:30 gfredericks: hlship: yes, that's exactly what I want to use it for

10:30 mdrogalis: gfredericks: Nevermind, I thought you wanted a different use case.

10:30 nbeloglazov: clgv: not directly, but you can save image to a file via (save "myFile.png") function and then read it. Clunky, but should work.

10:31 clgv: nbeloglazov: thanks. not optimal. :/

10:31 gotta checkout the processing api

10:31 nbeloglazov: clgv: also you can get pixel array and turn it to an image, I suppose

10:37 kral: namaste

10:41 mmitchell: i'm working on a clojure web app, currently running "lein ring" in dev. Anyone know how I can get access to the :servlet-request key?

10:42 I've seen references to this key, but my request maps don't have it

10:59 nonuby: https://github.com/ptaoussanis/timbre/blob/master/src/taoensso/timbre.clj#L14 can someone explain why (filter identity xs) is necessary, wouldn't filter just return a lazy seq too, so what difference does it make vs just xs?

11:01 llasram: nonuby: Returns a new sequence containing only the truthy values from `xs`

11:02 gfredericks: nonuby: you might have been confusing that expr with (filter (constantly true) xs)?

11:07 nonuby: ah okay that makes sense..

11:09 https://github.com/ptaoussanis/timbre/blob/master/src/taoensso/timbre.clj#L250 okay what about this.. this goes on to a future but yet the thread blocks @p? until the value is delivered, what would be reason for taking this approach?

11:09 ahhh wait the comment is referring to the lookup not the future, so self documenting.. duh

11:28 jwm: (doall (remove)) is still returning a lazy seq is that normal>

11:29 bbloom: jwm: the type won't change, it will simply be cached internally

11:29 jwm: ohh ok

11:30 so I can't test on the type for nil.. just the content

11:38 Frozenlock: Is it just me, or cider-nrepl is broken? (No more autocomplete or eldoc)

11:43 hlprmnky: I’ve seen that on one project recently, but I assumed I had just done something wrong

11:43 mikerod: Frozenlock: it may have something to do with your mode hooks

11:44 I originally had some `add-hook` specified on `cider-mode-hook`

11:44 it seems that something here has changed, and you need to use `cider-repl-mode-hook` now

11:44 if this is a problem you are seeing with autocomplete/eldoc not working in the Cider REPL

11:45 I'm not sure Frozenlock is still in the IRC :P

11:45 Frozenlock: I'm back

11:45 I needed to restart to remove Cider and go back to nrepl :-p

11:45 mikerod: Frozenlock: did you see my response?

11:45 Frozenlock: No :-(

11:45 mikerod: :D

11:45 clgv: what is the easiest way to use a private java method of an object in clojure?

11:46 mikerod: Frozenlock: it may have something to do with your mode hooks

11:46 I originally had some `add-hook` specified on `cider-mode-hook`

11:46 it seems that something here has changed, and you need to use `cider-repl-mode-hook` now

11:46 if this is a problem you are seeing with autocomplete/eldoc not working in the Cider REPL

11:46 just a guess though

11:46 Frozenlock: Hmm.... I do have (add-hook 'cider-mode-hook 'cider-turn-on-eldoc-mode) in my .emacs

11:46 I'll leave a note

11:47 mikerod: Frozenlock: yes, that's likely the culprit

11:47 I think Cider changed that var name

11:48 In Emacs : `C-h v cider-mode-hook` doesn't seem to have it defined somewhere

11:48 `C-h v cider-repl-mode-hook`is however

11:49 Frozenlock: Thanks, I wrote it in my .emacs

11:49 nbeloglazov: clgv: I think it's not different from java way - get class, get method from the class object, set accessible to true and then invoke it.

11:50 clgv: nbeloglazov: yeah, I remember a particular succinct code snippet being posted either here or on the ML

11:57 jwm: is (dosync (somefunneedssynch) (doall (for [] (somefunneedssynch) ))) acceptable?

11:58 I want the first somefunneedsynch not to be executed in the for loop

11:59 dvasquez: Is there any magic to getting tools.logging going? I've got a log4j.properties in classpath 'src/' with a ConsoleAppender but I don't get anything...

11:59 clojurebot: No entiendo

12:13 Frozenlock: 'Warning: specified :main without including it in :aot.'

12:13 May I ask what it means?

12:13 (what are the implications?)

12:13 technomancy: Frozenlock: you should either add the namespace to :aot or add ^:skip-aot

12:14 future versions of lein won't aot :main automatically

12:14 Frozenlock: Do I need aot for uberjar to work?

12:15 jcromartie: what's the best way to get route URLs for my Compojure application?

12:15 there's nothing like Rails' url_for

12:15 I guess I need to get the base URL from the request

12:15 and I could have controllers

12:15 technomancy: Frozenlock: no, but it can be more convenient

12:15 jcromartie: that are just structures with child routes

12:16 technomancy: Frozenlock: I would recommend never putting :aot outside the :uberjar profile if that's all you need it for

12:16 Bronsa: is it just me or does the sonatype web UI not load?

12:17 Frozenlock: technomancy: Ok. Is there a quick summary of what the AOT does? like 'makes things faster'?

12:18 technomancy: Frozenlock: the main thing AOT does is cause difficult-to-debug problems during development, but it also improves boot time and allows you to generate a named java class

12:18 the latter of which is required for `java -jar ...`

12:19 rule of thumb: never AOT during development if you can avoid it, only do it during release.

12:19 Frozenlock: gotcha

12:22 arrdem: technomancy: lein clean && lein test

12:22 technomancy: =(

12:29 coventry: gfredericks: Have you gone any further with your schema -> test.check generator since https://gist.github.com/fredericksgary/9787803 ?

12:30 gfredericks: coventry: somebody started a proper project out of it at clojure/west

12:31 coventry: https://github.com/MichaelBlume/schema-gen

12:32 coventry: Cool, thanks.

12:34 jcromartie: the solution is always JFDI (at least at first)

12:44 devn: is there a good (closer to comprehensive) set of documentation for core.async?

12:52 bbloom: devn: the core.async.clj is 90% doc strings... what exactly are you looking for?

13:14 gfredericks: documentation doesn't count unless it's a website with its own domain name and lots of CSS

13:15 arrdem: false....

13:15 jwm: I just want examples

13:15 that is all I want from "docs"

13:15 then I can live with docs on just the api printed from the code

13:16 heck clojure is the first system I actually have gone to the code to see how something is done

13:16 llasram: gfredericks: ha!

13:16 jwm: seriously

13:16 gfredericks: hyPiRion: aren't all clojure's data structure classes final and thus unextendable?

13:16 hyPiRion: gfredericks: what no

13:16 justin_smith: justinholguin: I am using clj-rss, what are the chances you guys would accept a patch so that I could give a proper atom namespace in the feed? http://validator.w3.org/feed/docs/warning/MissingAtomSelfLink.html

13:17 hyPiRion: gfredericks: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentVector.java#L20 do you see a final there? :(

13:17 justin_smith: (plus the atom:link in the channel section)

13:17 hyPiRion: It should be

13:18 gfredericks: hyPiRion: every dang other clojure class is final

13:18 hyPiRion: in any case a check for (= (class ob) ...) should work right?

13:20 hyPiRion: gfredericks: I'd use identical? actually, but yes. Just wanted to indirectly warn them to not do `instance?`

13:20 Because that was my first thought

13:21 gfredericks: righto

13:27 coventry: jwm: Have you seen https://github.com/clojure/core.async/blob/master/examples/walkthrough.clj ?

13:31 hiredman: Keyword dropped the final at some point

13:31 for unknown reasons

13:34 pjstadig: hiredman: really? huh

13:37 oh right that was a while ago

13:41 llasram: Oooh -- now you can make keywords which are also maps, which when called as a 0-argument function look themselves up in themselves

13:42 hyPiRion: you can also make persistent vectors containing themslves

13:42 justin_smith: weirdness

13:43 arrdem: madness...

13:45 llasram: hyPiRion: Was that? -- ##(doto [0] (as-> x (-> x .-tail (aset 0 x))))

13:45 lazybot: java.lang.RuntimeException: Unable to resolve symbol: as-> in this context

13:45 llasram: Ha!

13:45 ,(doto [0] (as-> x (-> x .-tail (aset 0 x))))

13:45 clojurebot: [[[[[[[[[[#]]]]]]]]]]

13:45 llasram: The we go

13:45 hyPiRion: llasram: yeah

13:45 llasram: ~botsnack

13:45 clojurebot: thanks; that was delicious. (nom nom nom)

13:46 arrdem: wat

13:46 llasram: arrdem: Vectors are mutable. But it's a secret! -- don't tell anyone

13:47 hyPiRion: Well actually, it's just that java arrays cannot be immutable

13:47 arrdem: http://arrdem.com/i/maddog.gif

13:47 dang

13:47 hyPiRion: arrdem: that 404s

13:47 gfredericks: arrdem: that 404s

13:47 arrdem: hyPiRion: yeah. I forgot the trailing e.

13:47 http://arrdem.com/i/maddoge.gif

13:48 gfredericks: arrdem: I assumed it must be about http://en.wikipedia.org/wiki/Jon_Hall_%28programmer%29

13:48 arrdem: gfredericks: haha

13:48 bbloom: summary: rich hickey does not believe in encapsulation... at all

13:48 ~encapsulation

13:48 clojurebot: I don't understand.

13:49 llasram: Exactly

13:49 hyPiRion: haha

13:49 bbloom: clojurebot: encapsulation is "Doctor it hurts when I do this."

13:49 clojurebot: Ik begrijp

13:49 shdwprince: Hi there! Can't remember how properly drop nth element from sequence, can you help me?

13:49 bbloom: ~encapsulation

13:49 clojurebot: encapsulation is "Doctor it hurts when I do this."

13:49 arrdem: ~cheatsheet

13:50 llasram: A friend of mine recently confessed that he is "skeptical of the JVM." I assured him that it exists

13:50 gfredericks: bbloom: does that phrase simply mean "encapsulation is bad" or something more specific?

13:50 llasram: what does "exists" mean wrt software?

13:50 shdwprince: searched for drop or remove, but found nothing about that

13:50 bbloom: gfredericks: it means that if you depend on internals or violate public contracts, that's your own damn fault

13:51 llasram: gfredericks: Just a play on multiple meanings of being "skeptical of" something, intended to parallel different meanings of "believing in" something

13:51 gfredericks: llasram: right, I just thought the idea of a configuration bits "existing" was a bit amusing

13:51 s/bits/of bits/

13:51 llasram: Oh, fair enough :-)

13:51 agarman: data encapsulation is pointless when you're working with data structures that are immutable

13:51 shdwprince: I mean I can (concat (take ..) (take-last ..)) but it seems that there is a better way

13:52 Is it?

13:52 gfredericks: bbloom: clojure isn't exactly known for having a well defined separation between public contracts and internals

13:52 bbloom: agarman: not entirely pointless, just of such low utility that it does more harm than good

13:52 hyPiRion: shdwprince: There's nothing existing in the core library, but you could implement a drop-nth function yourself. Give me a sec

13:52 llasram: Do all finite sequences bits "exist" in the sense that they are all equally possible?

13:52 A question to ponder

13:52 bbloom: gfredericks: sure it does. if lots of ppl depend on it, rich probably won't change it :-P

13:53 gfredericks: hurray defacto definitions!

13:53 arrdem: bbloom: plz can has spec thnxbai

13:53 ANSI Clojure 1.0.0...

13:53 bbloom: arrdem: here you go: github.com/clojure/clojure

13:54 gfredericks: bbloom: "lots"

13:54 agarman: the only benefit of encapsulating immutable data is to simplify a consumers world view

13:54 hiredman: bbloom: I assume final classes assist the jit though, but maybe that is wrong

13:55 hyPiRion: shdwprince: https://www.refheap.com/78796 -- I think that's roughly it

13:55 AimHere: Isn't 'simplifying a world view' pretty much what all high level computer languages are designed to do. Also low level ones.

13:55 bbloom: hiredman: final members & locals, *definitely*... classes? i dunno...

13:55 shdwprince: hyPiRion: thanks, I got it. Its sad, becose I dont like implementing basic functions, I mean, yeah, you can implement it, but after you need to require it all the times. But for that cause, it seems, there is no better way

13:55 hiredman: bbloom: seems like they would simplify the class hierarchy analysis

13:55 agarman: there are better ways to simplify...

13:56 bbloom: hiredman: but you've either got some *object* of exactly type T or some virtual hierarchy rooted at T

13:56 hyPiRion: shdwprince: In many cases, those functions aren't there because they are very inefficient. In many cases, it's sort-of a hint that one should consider structuring the data in a different way

13:56 bbloom: hiredman: i'd imagine in 99% of the cases you've got a final class, then it's usages are either through an interface or directly concrete

13:56 hiredman: bbloom: actually cliff click has a series of blog posts about trying to optimize final memembers, and it being a pain because no one repects final fields

13:56 hyPiRion: Oh dang, started both sentences with "In many cases".

13:57 * hyPiRion needs rest from this C code.

13:57 bbloom: hiredman: you mean ppl use reflection to change final fields?

13:57 hiredman: bbloom: I forget the details, it may have been stuff like that

13:58 http://www.azulsystems.com/blog/cliff/2011-10-17-writing-to-final-fields-via-reflection http://www.azulsystems.com/blog/cliff/2011-10-27-final-fields-part-2

13:58 clojurebot: No entiendo

13:58 bbloom: hiredman: heh, generated byte codes

13:59 programmers can't be trusted not to hurt themselves...

13:59 llasram: I thought part of the effect of `final` was that the JVM was free to optimize away accesses to `final` fields

13:59 gtrak: llasram: think serialization libs

14:00 hiredman: you would have hoped

14:00 gtrak: sun.misc.unsafe can create objects without calling constructors

14:00 tbaldridge: final is pretty much useless these days IIRC

14:00 bbloom: constructors are kinda a bogus idea to begin with

14:00 gtrak: this is a really good article though: http://www.azulsystems.com/blog/cliff/2011-10-17-writing-to-final-fields-via-reflection

14:00 llasram: ugh

14:01 tbaldridge: final is removed or added by the JIT as needed

14:01 dbasch: ugh, commented code in a source. https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentVector.java#L348

14:01 gfredericks: clojure has a lot of commented code

14:02 hyPiRion: dbasch: you must be new to clojure.core

14:02 bbloom: dbasch: scroll down to the static public void main :-P

14:02 dbasch: and worse: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentVector.java#L723

14:03 arrdem: well at least we _have_ a benchmark in there somewhere...

14:03 tbaldridge: I found it interesting to find out that most of the people that hack on Clojure's guts use IDEs and just ignore most of that stuff.

14:03 if you have a sorted method list, do large comment blocks matter?

14:03 dbasch: bbloom: yes, that’s the second link

14:04 arrdem: tbaldridge: neither does our uniquely inconsistent whitespace convention...

14:09 gfredericks: ,(defmethod print-method :user/foo [x pw] (print-method "FOO" pw))

14:09 clojurebot: #<MultiFn clojure.lang.MultiFn@554210>

14:09 gfredericks: ,(alter-meta! #'first assoc :type :user/foo)

14:09 clojurebot: {:added "1.0", :ns #<Namespace clojure.core>, :name first, :file "clojure/core.clj", :static true, ...}

14:09 gfredericks: #'first

14:09 ,#'first

14:09 clojurebot: "FOO"

14:10 gfredericks: does anybody think the multimethod + clojure.core/type mechanism for customization of print-method etc. is regretable?

14:11 I ask because I think it's cool but never see anybody use this mechanism for anything else ever

14:11 arrdem: it's kinda hard to have meaningful domain specific prints...

14:11 tbaldridge: gfredericks: I think it simply predates protocols

14:12 gfredericks: tbaldridge: it's a lot more flexible than protocols though since I can change individual objects that are IMeta

14:13 arrdem: I think it's cool for interactive development to e.g. have atoms that print interesting stuff

14:13 bbloom: gfredericks: i prefer multimethods over protocols for every reason except perf & "markers"

14:13 hiredman: it might have been better to dispatch on :print/type, but I dunno, it rarely if ever gets used, so it is hard to regret

14:13 tbaldridge: gfredericks: interesting, I didn't know that about type....

14:14 technomancy: gfredericks: it may not surprise you to find that I think it's cool

14:14 gfredericks: technomancy: It's almost surprising how surprised I'm not

14:14 bbloom: markers?

14:14 tbaldridge: but yes, I find it odd that print-method isn't a protocol. It should be IMO.

14:14 bbloom: gfredericks: for use with satisfies?

14:14 gfredericks: bbloom: oh gotcha

14:15 hiredman: that makes me think a 2-arg version of clojure.core/type would be useful

14:15 (type :print/type obj)

14:16 yeah I think the whole multimethod + metadata + custom-hierarchies feature set is one of the most interesting ones that never gets used

14:16 AeroNotix: How about this for a feature? https://gist.github.com/AeroNotix/dcb26df5e85eb6c1ec40

14:17 kind of like Erlang's when guards

14:17 gfredericks: AeroNotix: predicate dispatch is the term you want I think

14:17 bbloom probably thinks something about that

14:17 tbaldridge: bbloom: things things about a lot of things

14:17 *thinks things

14:18 * bbloom is a thinker of things

14:18 llasram: He also thinks thinks about a lot of thinks

14:18 gfredericks: clojurebot: bbloom |thought| a thunk once

14:18 clojurebot: In Ordnung

14:18 bbloom: predicate dispatch is tricky b/c it's potentially ambiguous

14:18 gfredericks: bbloom: that's open predicate dispatch in particular, right? where ordering is ambiguous?

14:19 bbloom: gfredericks: right

14:19 gfredericks: but what good is closed predicate dispatch? booo

14:19 might as well just fucking use cond at that point :-P

14:19 gfredericks: Closed Predicate Dispatch: at least it exists

14:19 AeroNotix: take a look at this: https://gist.github.com/AeroNotix/e4b0f4382397e518fcb1

14:19 the alternative is a lot more verbose

14:20 bbloom: erlang's when guards (and haskell's views, scala's extractors, and a few other things)

14:20 AeroNotix: using predicates seems more declarative

14:20 bbloom: ... are interesting

14:20 BUT they operate in the context of ordered choice

14:20 even when closed, ordered choice is a bitch b/c it means that you have implicit dependencies between clauses that are not explicit

14:21 gfredericks: bbloom: let's just use ratios on every clause to indicate order

14:21 that way you can always wedge one thing between another two

14:21 AeroNotix: bbloom: Erlang helps this by allowing only a specific set of guard functions

14:21 technomancy: bbloom: I get what you're saying, but it's a terrible reason to leave pattern matching out of a language

14:21 it's like ... cond also has this problem

14:21 and yet somehow we survive

14:21 bbloom: technomancy: yeah, i'm not opposed to pattern matching. i'm opposed to ordered choice encoded in to the pattern matcher

14:22 take a look at mathematica for another interesting compromise

14:22 AeroNotix: bbloom: what's the alternative

14:22 gfredericks: technomancy: most of my production bugs are due to me running my cond-shuffling code transformation script accidentally

14:22 bbloom: mathematica has open predicate dispatch with pattern matching

14:22 tbaldridge: something dnolen mentioned years ago was that if something like core.match ever made it in as a "language feature" it would need to be order agnostic and extensible.

14:22 AeroNotix: gfredericks: you really have a script which does that?

14:22 gfredericks: AeroNotix: not at all

14:22 bbloom: it *falls back to* ordered choice when it can't automatically determine predicate implication

14:22 gfredericks: AeroNotix: at least I hope I don't

14:22 tbaldridge: core.match is order agnostic, IIRC. but not extensible.

14:23 bbloom: technomancy: it's neither of those things

14:23 hiredman: before I learned about unification I was using this system based on hierarchies to try and encode clojure's Numbers.java as a set of rules about types, but then I jsut rewrote it using core.logic

14:23 bbloom: technomancy: core.match tightly couples the optimizer to ordered choice

14:23 technomancy: it sucks to not have access to awesome stuff because something theoretically more awesome could exist

14:23 AeroNotix: "Worse is better"

14:23 hiredman: technomancy: but you have access, right?

14:24 gfredericks: technomancy: access is different from enshrining in core.clj

14:24 technomancy: hiredman: not really. I can't include core.match in lein, which is the only clojure I write. back when I wrote clojure daily, core.match wasn't suitable for use.

14:25 hiredman: but FSVO "you", then yes =)

14:25 tbaldridge: technomancy: why can't you include it in lein?

14:25 gfredericks: clojurebot: core.match is a pattern-matching library available for use by anybody but technomancy

14:25 clojurebot: Roger.

14:25 tbaldridge: rofl

14:26 technomancy: tbaldridge: it would mean no one could use a newer version in any lein plugins

14:26 hiredman: there was a website where you could have it generate a license "this project is usable by anyone but <named party>"

14:26 technomancy: this has been a problem with several other libs; just ask Bronsa

14:26 bbloom: technomancy: surely you need OSGI

14:26 * bbloom ducks

14:27 hyPiRion: hiredman: https://github.com/landondyer/kasm/blob/master/LICENSE

14:27 tbaldridge: actually, someone just needs to invent a decent plugin system for Clojure.

14:27 gfredericks: we should start using lib-cloning utilities until somebody solves dependency management

14:27 technomancy: bbloom: I was actually considering the idea of a compile-only dependency that could disappear at runtime

14:27 bbloom: technomancy: i'm actually thinking about exactly that right now

14:27 arrdem: I'm with TB here... a real plugin system for Clojure would be awesome

14:27 bbloom: technomancy: trying to bootstrap eclj.core

14:27 * gfredericks apparently doesn't know what a real plugin system is

14:27 bbloom: technomancy: i want to be able to define clojure constructs in terms of clojrue constructs, but re-defing vars is a bitch b/c it affects old defintions

14:28 hyPiRion: gfredericks: one which allows multiple versions of dependencies to live side by side I guess?

14:28 arrdem: hyPiRion: that's great

14:28 bbloom: technomancy: since i own both the evaluator and the first-class environment implementation, i'm considering creating a virtualized namespace w/ static vars

14:28 technomancy: having namespaces more first-class would help, but without being able to re-root java classes it feels like a lost cause

14:28 hyPiRion: arrdem: yeah, I love it

14:28 gfredericks: hyPiRion: I guess I would have thought of that as a general dependency goal

14:29 bbloom: technomancy: might be doable to re-root deftype and friends, but not java code directly

14:29 gfredericks: technomancy: to use core.match you have to first write a jvm in clojure

14:29 justin_smith: gfredericks: the difference between a plugin vs. a normal lib, to me, is that it is more modular (can live alongside multiple versions of itself) and its point of interface with the rest of what you build is very narrow and well defined

14:29 tbaldridge: I'd be tempted to try the Erlang model. You don't couple dependencies, you spin up a JVM and communicate via sockets and pipes.

14:29 hiredman: tbaldridge: too slow

14:30 justin_smith: so any feature it would provide would be returned from its initialization function, and the consumer could decide where and how to bind that functionality / those definitions

14:30 technomancy: relative require would be cool

14:30 shdwprince: Is there is something like (apply -> argument forms) ?

14:30 tbaldridge: hiredman: start up time or general performance?

14:30 hiredman: tbaldridge: having lein spin up two jvms is already slow

14:30 arrdem: technomancy: what.. (:require ..foo)?

14:30 tbaldridge: hiredman: well that's the problem, it starts them then kills them

14:30 gfredericks: I've been trying to figure out how to get around the problem of protocols/multimethods having global customization scope

14:30 and something like that would fix it I think

14:30 technomancy: arrdem: sure, and ./foo

14:30 tbaldridge: hiredman: cljsbuild auto is a great example of what plugins should begin to look like, imo.

14:31 hiredman: tbaldridge: cljsbuild is kind of terrible in my, admittedly, limited experience with it

14:32 arrdem: tbaldridge: oh while you're here. I note that two lean clojure projects were accepted by GSoC. Is there a coordination plan?

14:32 tbaldridge: arrdem: IIRC the plan was that one will handle Rich's views on lean runtimes, while the other (your's I think) will hit the "full program optimization" route

14:33 hiredman: gfredericks: https://twitter.com/richhickey/status/249560631164932096

14:33 arrdem: tbaldridge: =D

14:33 ToxicFrog: "lean runtimes"?

14:33 hyPiRion: ToxicFrog: faster startup

14:34 ToxicFrog: yesssssssss

14:34 hyPiRion: that's what I alias it to

14:34 tbaldridge: ToxicFrog: basically advanced compilation for CLJ on the JVM

14:34 ToxicFrog: startup time is my #2 complaint about clojure

14:34 And the reason I basically only use it for daemons

14:34 shdwprince: ToxicFrog: and the first?

14:35 ToxicFrog: (well, daemons or programs where IO will dominate the runtime so severely that no-one will care if it takes a while to start up)

14:35 shdwprince: error reporting

14:35 Particularly, in the compiler.

14:35 AeroNotix: oh yes

14:35 utterlly incomprehensible

14:35 gfredericks: hiredman: this is a classic example of a statement that presumably contains a value judgment but I can't for the life of me figure out what it is

14:35 nor can I figure out if it was intended to be obvious or not

14:36 hiredman: which statement?

14:36 gfredericks: hiredman: the toot you linked to

14:36 hiredman: gfredericks: well, multimethods are "global" to a clojure runtime, so if you want multiple runtimes...

14:37 gfredericks: hiredman: how easy do you think it would be to load a separate copy of cheshire with a classloader?

14:37 hiredman: gfredericks: the tricky part is communicating across classloader boundaries

14:37 arrdem: oooh boy guile+emacs got accepted to GSoC

14:38 gfredericks: hiredman: there'd be different instances of the RT class etc? or just the cheshire namespace objects and var objects?

14:38 technomancy: arrdem: they were accepted last year iirc

14:38 hiredman: at one point I had clojurebot loading clojure 1.2 in an insolated classloader to run fnparse, before I said screw it and spawed it out as a different process

14:39 bbloom: hyPiRion: i'm a bit late (opened the tab & got distracted) but ROFL @ the ABRMS license

14:39 hiredman: gfredericks: you really need everything to be isolated

14:39 arrdem: hiredman: you haven't upgraded to instaparse?!

14:39 bbloom: hyPiRion: that's fucking hilarious

14:39 gfredericks: hiredman: I'll call it impossible then

14:39 llasram: hiredman, gfredericks: I don't know if it does it the best way, but Alembic loads a Leiningen in a separate classloader and communicates with it

14:39 gfredericks: I wouldn't want to be cloning objects or anything wasteful like that

14:40 llasram: Ah

14:40 ToxicFrog: AeroNotix: once you get used to them, they aren't completely incomprehensible -- well, usually -- but that still does not excuse them.

14:40 The actual error is buried somewhere in the middle of the multiple pages of compiler stack trace vomit.

14:40 AeroNotix: I've been working with them for a while.

14:40 I know what to look for

14:40 hiredman: well, that is just a trade off of isolation

14:40 llasram: gfredericks: I'm not really sure how you'd avoid that, since they'd have distinct implementations of all the core classes

14:40 AeroNotix: I guess I meant: "Incomprehensible to the beginner"

14:41 hiredman: similar to sharing things between erlang processes

14:41 gfredericks: llasram: right, that's why I'm giving up

14:41 bbloom: llasram: gfredericks: need to have common interfaces at some point to communicate between class loader domains

14:41 it's basically impossible to modularize code from the outside

14:42 gfredericks: I'm just gonna fork cheshire & others and make them localizable

14:42 ToxicFrog: AeroNotix: oh, definitely.

14:43 AeroNotix: having the compiler spew internals at you when you misplaced a parens is just a tad unfriendly

14:44 gfredericks: having the compiler figure out that your only problem is you misplaced a paren is just a tad advanced

14:44 AeroNotix: gah I fucking hate the erlang riak client

14:45 ah wrong channel

14:45 sorry^

14:45 tbaldridge: AeroNotix: yeah, we only allow you to talk about Clojure and Haskell here...

14:45 AeroNotix: gfredericks: other languages seem to do a "good enough" job

14:45 gfredericks: AeroNotix: other lisps?

14:46 AeroNotix: gfredericks: clisp, sbcl seem to work fine enough

14:46 xpte: <arrdem> oooh boy guile+emacs got accepted to GSoC <-- again?

14:46 dakrone: gfredericks: what's the motive behind making it localizable?

14:46 gfredericks: AeroNotix: good to hear

14:46 xpte: i feel like it's gotten in at least three times, but there doesnt seem to be much to show for it

14:58 jwm: (-> :alerts (dateBasedKey))

14:58 the dateBasedKey is a function that returns (keyword date..)

14:58 doesnt loook like the key is getting expanded as a keyword in the macro though

14:59 gfredericks: jwm: that expression is identical to (dateBasedKey :alerts)

15:00 I'm not sure what your last statement means

15:01 jwm: I'm using a numerical string I wonder if that is what is making it not work

15:01 I just get the date string back

15:02 gfredericks: I'm still not understanding; but it sounds like the sort of thing where if you had a minimum example reproducing the problem we could figure it out quickly

15:02 jwm: ((dateBasedKey) (-> *data* :alerts)) works

15:02 gfredericks: oooeh

15:02 try (-> *data* :alerts ((dateBasedKey)))?

15:03 justin_smith: yeah, that looks right

15:03 in -> (foo) is the same as foo

15:03 jwm: well that just started working

15:03 crazy!

15:03 mayhbe it was lighttable

15:03 gfredericks: jwm: try (macroexpand-1 '(-> ...)) to see the difference

15:03 justin_smith: you need ((foo)) to get wrapping

15:03 jwm: I was doing () in the -> statement

15:04 justin_smith: yeah, that is the same as no parens

15:04 jwm: it just kept giving me back the actual keyword string

15:04 dbasch: jwm: (-> bar (foo)) is the same as (-> bar foo)

15:04 justin_smith: you need double to get one

15:04 sugar is weird

15:04 jwm: well now it works with just a single one

15:04 justin_smith: it shouldn't

15:05 jwm: (sqdata :alerts (FMdatekey))

15:05 gfredericks: that's different

15:05 jwm: sqdata is a macro that expands to do -> + args

15:05 gfredericks: the -> is the important difference

15:07 dbasch: ,(doc ->)

15:07 clojurebot: "([x & forms]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc."

15:08 jwm: yeah

15:08 I made macros for all of my ref data to alter

15:08 (defmacro sqdata ([& args] `(-> @*sqdata* ~@args)))

15:08 so I could just do some tiny shorthand such as (sqdata :alerts :20140401)

15:09 I added the same form to my test code function and it also brought back the date but then I put it in double enclosures and it worked hehe

15:10 gfredericks: jwm: if you're just passing keys to lookup you don't need a macro for that

15:10 jwm: however the original statement now works even with single parenthesis

15:10 gfredericks: (defn sqdata [& keys] (get-in @*sqdata* keys))

15:10 jwm: which one would be faster to run

15:11 justin_smith: they should be nearly identical

15:11 criterium has the real answer though

15:12 jwm: the biggest thing that has slowed me down so far with clojure is learning the different forms of update-in

15:12 merge, into, assoc, conj with [], {}, () .. etc

15:13 justin_smith: but those things don't even exist in another language - it's a speedup!

15:13 gfredericks: java.jdbc's api that lets you put some options at the front of your statement vector is super gross

15:13 justin_smith: (once you know them)

15:13 llasram: jwm: You say it like `update-in` doesn't just take an arbitrary function

15:14 jcromartie: there's only one form of update-in

15:14 jwm: no, my problem isnt clojures

15:14 its the fact I go willy nilly when I pick my data structures

15:14 jcromartie: it's totally open ended

15:14 ah, yes, that can be an issue :P

15:14 jwm: I never use to even pay attention to it I'd just pick {} and be done with it :)

15:14 jcromartie: (it's totally open ended)

15:14 jwm: now I've got 31 flavors with my data

15:14 I spent 8 hours on a 6 line routine because of it lol

15:15 jcromartie: routing?

15:15 oh routine

15:15 sorry

15:15 (tiny fonts)

15:15 jwm: sorry should've said function anyway :)

15:15 jcromartie: I know the feeling

15:15 justin_smith: clojure is more concise so you need to re-evaluate your time per line of code heuristics

15:16 jcromartie: clojure is like a 4-cylinder race engine

15:16 mmitchell: has anyone ever used this for security in a clojure web app? http://www.picketlink.org/

15:16 jwm: yeah I noticed clojure makes me think while I program

15:16 justin_smith: jwm: regarding your above time question, -> is faster. https://www.refheap.com/78799

15:16 jwm: dunno if I like that part about it yet :)

15:16 arrdem: justin_smith: -> can use transients :D

15:16 or should..

15:16 jcromartie: sophisticated, compact, powerful, and insanely difficult/expensive to diagnose when something goes wrong

15:17 justin_smith: arrdem: that would explain it, if that were the case

15:17 jwm: I started writing test cases which is the first time in my life because of clojure

15:17 gtrak: jwm: it gets better

15:17 gfredericks: arrdem: waat?

15:17 jwm: and my test cases were altering data in a way that made my normal code go bad hah

15:17 gtrak: a hardship worth pursuing :-)

15:18 arrdem: test generative next up...

15:18 justin_smith: jwm: when you have pure functions and immutible data, tests become much more useful and informative

15:18 jwm: yeah I know I am progressing as a developer

15:18 TimMc: justin_smith: I'll admit, I stopped reading at "Java EE".

15:18 gtrak: I've noticed that my java code-reading skills have improved immensely just by this process.

15:18 TimMc: right or wrong

15:18 gfredericks: arrdem: what on earth does "-> can use transients" mean?

15:18 justin_smith: TimMc: ?

15:19 jwm: justin_smith: I'll get there but this project has a deadline which I already sort of missed :)

15:19 jcromartie: you can use -> with transient mutator functions

15:19 jwm: at least I am separating my side effect functions from my non

15:19 arrdem: gfredericks: I'm derping at the moment... jira ticket I read yesterday and didn't recall correctly.

15:19 gfredericks: but jcromartie got it right

15:19 jwm: I use to use functions like they were namespaces

15:19 justin_smith: TimMc: wait where did you read Java EE?

15:20 stuartsierra: How is `cljr-add-require-to-ns` supposed to work? I get stuck in the snippet.

15:20 gfredericks: arrdem: jcromartie: we were just comparing -> to get-in, which doesn't update anything

15:20 did I miss a separate topic?

15:20 arrdem: gfredericks: nope.

15:20 gfredericks: this is unrelated

15:20 gfredericks: oh phew

15:22 TimMc: justin_smith: Oh whoops, that was mmitchell.

15:23 jcromartie: jwm: IMHO Clojure is a language for the long run. I think there are plenty of languages better suited for many purposes, but Clojure brings a better return on investment in the long run.

15:23 jwm: I would hate to learn it while on a project with a deadline, though.

15:24 jwm: that is the only way I learn stuff

15:24 if I have some fire to put out

15:24 justin_smith: especially if it is one's first lisp (or worse yet, first non procedural/oo language)

15:24 jwm: I'm already 5 times more productive in clojure than nodejs heh

15:24 I studied lisp (10!) years ago

15:24 justin_smith: jwm: in self education I have become a semi-expert in starting small fires on a daily basis :)

15:25 jwm: I went from asm coding and osdev straight to webdev possibly after repainting my jeep without a face mask on

15:25 justin_smith: inhalents are a hell of a drug

15:25 jcromartie: if I didn't know Lisp or JavaScript, I'd prefer to learn Clojure over Node.js

15:26 Clojure has quirks, but nothing like the whoppers in JS

15:26 jwm: node-webkit is a nice model

15:26 devn: tips for reporting and handling exceptions in core.async?

15:26 dbasch: jcromartie: you made me remember https://www.destroyallsoftware.com/talks/wat

15:26 gtrak: "Effective Javascript" was a really fun and quick read, cascading horrors made me lol.

15:27 jwm: its kind of ironic I am using a nodejs based system to get off of nodejs (lighttable)

15:27 jcromartie: <3 Gary Bernhardt

15:28 akhudek: devn: make sure you dont’ pass lazy sequences into put!

15:28 arrdem: ah the "wat" talk..

15:28 justin_smith: mmitchell: regarding your question above, immutant is a clojure utility based on jboss, and it may be helpful if you want to use picketlink with clojure?

15:28 akhudek: that way exceptions will not occur inside the put!

15:29 probably want to catch them within a go block too, not outside of it

15:32 jwm: anyone else use (cond) to make themselves a nice/po man test runner

15:33 (defn FMtests [tsttype tst] (cond

15:33 llasram: what? no

15:33 Just use clojure.test

15:33 jwm: I still use that its just this way I can pass a nice long string

15:34 BobSchack: devn http://swannodette.github.io/2013/08/31/asynchronous-error-handling/

15:34 jcromartie: jwm: I think everybody is confused

15:34 jwm: (FMtests "alerts" "merge test email and destroy report spool")

15:34 llasram: status unchanged :-)

15:35 jwm: I just check for condition tsttype = alerts and then check what tst= wants to run and then do my test code

15:36 I was wondering what patterns pros use

15:36 tcrawley: mmitchell: don't use picketlink unless you absolutely have to. like, someone is going to shoot you in the head if you don't use it

15:36 gfredericks: clojure.test

15:37 mmitchell: tcrawley: lol - advice, straight up! I have no requirements, just looking for a good lib that handles authentication/authorization and pluggable backends (ldap, custom etc.)

15:43 dbasch: mmitchell: technically you can plug your backend into friend

15:43 mmitchell: in fact you really have no choice

15:45 mmitchell: dbasch: yes, been playing with friend today also. Slowly starting to understand how it works.

15:52 dbasch: what do you mean "no choice"?

15:53 dbasch: mmitchell: well, you do have a choice in that you can use openid, otherwise you have to plug in your own authentication mechanism

15:54 mmitchell: dbasch: ahh, right. I understand!

15:55 mikerod: I had an interesting discovery on clj 1.6 today. The newer version of ASM lib being brought it now fails faster when a method size is too large

15:55 Previously, I didn't see "too large" method size errors until the ClassLoader failed when loading the byte code

15:55 https://github.com/clojure/clojure/blob/master/src/jvm/clojure/asm/MethodWriter.java#L1871

15:55 looks like they added some explicit checking during bytecode generation now

15:56 jcromartie: that's a nice improvement

15:56 mikerod: So previously, I could run something like clojure-maven-plugin compile phase "compile to temp" output to ensure that the compiler didn't throw errors. We knew some methods were too large, but it didn't matter since we weren't loading up from the AOT __init files. Now it fails during the compilation though.

15:57 jcromartie: I agree that it is a good improvement to fail-fast on this, as ASM does now

15:57 Just snuck up on me.

15:59 mmitchell: tcrawley: curious... what was your experience with picketlink, and do you have any recommendations?

16:01 tcrawley: mmitchell: I don't have any recommendations, and I've never used picketlink. I have friends that have had to integrate with picketlink (via java), and had a very difficult time.

16:01 so, I'm basically talking out of my ass

16:01 akhudek: ooh, picketlink has SAML

16:01 mmitchell: ha well that's ok.

16:01 tcrawley: but it does embrace the complexity of JavaEE, which can be daunting

16:02 mmitchell: right, it looks HUGE too

16:02 I've also been looking at Apache/Shiro

16:02 akhudek: mmitchell: I’ve used shiro

16:02 it’s “ok"

16:02 mmitchell: oh really? any feedback?

16:02 ok

16:02 akhudek: have you used friend?

16:03 akhudek: mmitchell: only on a small utility project, it didn’t exist when we started so we have our own authentication system

16:03 we use shiro for authorization

16:04 mmitchell: akhudek: do you have various/different methods for auth or just use 1?

16:05 akhudek: mmitchell: just one, but one day I’d like to support saml too

16:07 mmitchell: akhudek: ok cool, thanks for your feedback. I'll have another look at shiro too

16:08 akhudek: mmitchell: the nice thing about it is that you can fairly easily customize the storage for your authorization roles

16:09 mmitchell: that's definitely important for what we're building

16:10 akhudek: does it require that your app be a proper servlet app? I think I saw some clojure code using Shiro that said you can't (for example) use something like http-kit's server

16:12 akhudek: mmitchell: It may depend on how much of it you use. But if you just want to use authorization then you can simply intantiate the right objects and store them in the user’s session.

16:13 mmitchell: interesting ok

16:14 amalloy: forge before jack to shuffle stuff in?

16:14 whoops, wrong window

16:15 tvanhens: is there a way to execute "load-string" in a namespace other than the one you are currently in? I am trying to dynamically load functions from specific files through a defn function that wraps load-string. The funciton works when I call it from the namespace I am in, however when I try to call that function from other namespaces that I have required it into, I get unable to resolve symbol errors

16:15 gtrak: you can bind *ns*

16:15 though that's for eval, not read-string

16:16 hiredman: namespaces are not things that things happen in

16:16 gtrak: except eval :-)

16:17 tvanhens: I thought that load string was a combination of eval and read-string

16:17 gtrak: http://stackoverflow.com/questions/7684656/clojure-eval-code-in-different-namespace

16:17 I don't know load-string

16:17 hiredman: sure, but a namespace isn't a think that things happen in, a namespace is a big map you look up values from

16:18 the compiler uses *ns* by default to look things up

16:18 gtrak: what's it mean to have a thing happen in a thing?

16:18 hiredman: but at execution time, *ns* can be bound to any random thing

16:18 tvanhens: gotcha

16:18 gtrak: that's kind of a pedantic distinction.. does something actually happen in a thread?

16:19 as a straw man, I guess

16:19 tvanhens: so eval by default uses whatever namespace is most recently called?

16:19 hiredman: namespaces are a compile time environment, the only time *ns* is for sure the namespace your function is defined is, is when it is being compiled

16:19 namespaces are not called

16:19 tvanhens: I don't know the correct terminology I just mean the context its in

16:20 hiredman: eval uses *ns*

16:20 gtrak: I'm guessing load-string would use the same stuff, from a cursory look

16:24 tvanhens: it's possible (but-nasty) to change the ns mid-flight to redefine stuff

16:24 I forget what library had that :-)

16:26 tvanhens: so say I want to dynamically run functions contained in strings from a database. And the functions that call load-string to evaluate them are all contained in the same namespace. But I want to be able to call those functions from a different namespace. How would I prevent eval from using the latter?

16:27 gtrak: why not just fully-qualify the functions?

16:27 this sounds like X-Y problem

16:28 also, eval's a massive security hole when used like that, maybe a multi-method DSL would be better.

16:29 tvanhens: the database is behind a firewall and only used internally so I'm not too worried about that too much

16:30 justin_smith: tvanhens: is this some kind of expert system or genetic algo?

16:31 tvanhens: not at the present point in time, just a spaghetti of code. But thats what I'm working on trying to put together

16:32 gtrak: tvanhens: anyway you can mess with *ns*, it's a dynamic var, so it's thread-local.

16:33 tvanhens: thanks I'll give that a go

16:33 justin_smith: tvanhens: storing code in a db is not a way to avoid spaghetti...

16:33 gtrak: candidate for inclusion into footgun :-)

16:34 tvanhens: Well aware of that :) trying to figure out a smart way of doing that

16:34 justin_smith: tvanhens: I'm trying to picture a scenario where that would improve on the normal fs mapping of namespaces, and if you aren't doing genetic algos I don't know how it would help

16:34 is there some pragmatic need for not having normal files of code?

16:36 tvanhens: business requirement. Not the biggest fan of it, but trying to figure out a way to make it work. They want to put most of the codebase into datomic in small applet forms that are executed in the time context they were created in

16:37 gtrak: quite the trippy manager

16:37 tvanhens: Yeah, its definitely an interesting challenge

16:39 well thanks for the input. Going to try some things out

16:48 devn: tbaldridge: Could you or anyone else give me the gist of what ioc-alts! does?

16:49 tbaldridge: devn: sure

16:50 * devn claps for irc

16:51 tbaldridge: do-alts handles the mechanics of alts!. It takes a callback (to be handed to the dispatcher if the alt is parked), and a set of channels. It returns nil if the action is parked, or a value box if the operation succeeded without needing a dispatch

16:51 the function ioc/run-state-machine-wrapped is what ends up calling this function, and it expects :recur if execution should continue, or nil if the execution of the state machine should pause

16:52 so you can probably see that if do-alts returns nil, then the inner callback will handle the continuation of execution, otherwise execution continues inside the caller of ioc-alts!

16:52 the ioc/aset-all! stuff is record keeping for the next state to jump to and tracking the value returned by alts!

16:52 https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L344

16:55 devn: ahhh

16:55 thank you tbaldridge

16:57 ive been reading and re-reading the API docs to get leveled on core.async-fu. do-alt and ioc-alts! stuck out to me because they didn't have docstrings. i was searching in the file for ioc-alts! and didn't see any callers in clojure.core.async, so thought I'd reach out and ask since I saw you were active

16:58 tbaldridge: maybe this is contrary to the whole point of core.async, but I was wondering: Is there a way to count the number of items currently put onto a channel?

17:03 tbaldridge: devn: not really, one could write a custom buffer with count mechanics, but that leads to all sorts of race conditions.

17:05 devn: tbaldridge: yeah, i figured as much, this was more for me to just tinker with some ideas -- to ask some questions about a particular channel.

17:06 tbaldridge: you could also write something like async/pipe that stores the current count in an atom

17:06 it takes as many items as it can and stores them somewhere and keeps track of the count

17:06 putting them into the output as it can

17:07 ToBeReplaced: i wonder if you could write a function to accept a channel and then reify something implementing ReadPort, WritePort, Channel... on write/read swap! an atom

17:10 devn: here's a giant, loaded question for you :) -- i am working on something where i have a set of URLS in a CSV file with some other metadata about them. Once it is fetched, it has a few CPU-bound transforms applied to it. These transforms also eat up a bunch of memory. Finally, they are uploaded to S3. Failed items at each step need to be logged to a CSV file. Successful items which are uploaded also need to be logged.

17:13 The question(s) is/are: 1) Any ideas for dynamically arriving at the max connections a particular host can take? 2) How would you handle the logging? 3) Any other general observations or thoughts?

17:13 tbaldridge: ^

17:14 jwm: sounds like a good introspective app

17:14 I plan to incorporate that kind of coding into my dev process

17:15 tbaldridge: devn: I really recommend a pipeline approach for this, each task is a go and takes from one channel and writes to another. Make a constructor for each task that takes a param for the number of gos for each app.

17:15 then configure the entire thing off a large hashmap that takes the sizes of each buffer and the number of gos, tweak until you're happy

17:15 *gos for each task.

17:16 I mean, you could also implement an auto balancing system for this, but I've found those things hard to get right

17:16 devn: heh, yes

17:16 hiredman: https://gist.github.com/hiredman/11194485

17:16 tbaldridge: it can often just be easier to give yourself an easy way to configure it by hand or via a config file.

17:17 hiredman: (it uses futures, because you can future-cancel, and it assumes you'll be doing side effects)

17:18 devn: tbaldridge: yeah, the only thing is, in some cases the set of hosts I have to get things from varies. some hosts might allow 100 connections, others 25, maybe another will only allow 2. knowing this up front is hard.

17:18 hiredman: thanks i'll give it a long

17:18 look*

17:18 tbaldridge: you can shutdown this pipeline as well via closing the input/output channels, this has the added plus of only shutting down once a given item is processed

17:19 future-cancel can kill in the middle of something important.

17:19 hiredman: tbaldridge: sure, but some times you don't care

17:19 tbaldridge: agree

17:19 *agreed

17:19 devn: how do you know how many connections is "too many"?

17:19 hiredman: the pipeline function returns a data structure containing all the input and output channels which is nice too

17:20 devn: tbaldridge: things start failing. unfortunately, it can also fail because the resource simply is not there.

17:20 i've inadvertantly taken down one of these hosts

17:20 so it makes me want to be extra careful, because if it goes down, I'm hosed until someone gets around to flipping the lights back on

17:21 tbaldridge: devn: my point being, if you don't have a reliable feedback system, having a self tuning system doesn't help much

17:22 devn: tbaldridge: i imagine something like accelerating per-host -- the reliability of the feedback system is bad, yes, but over 1,000,000 items for a particular host, it seems doable to arrive at a reasonable "speed limit" for that host

17:22 but with over 1,000,000 items*

17:23 tbaldridge: in any case, i think you're right, but it does pain me a bit to have to settle. I'd love to build this so it can try to tune itself.

17:24 hiredman: this is pretty cool

17:32 hiredman: how would i pass this something like source-csv -> fn-which-processes-a-single-row -> next-step-fn?

17:33 tbaldridge: devn: and something else to mention for hiredman's approach, I think we're too quick sometimes to reach for 'go'. If you're creating a static pipeline, use thread or future

17:40 devn: hiredman: also, where do you pull results off? I tried to (<!! (:out (pipeline [10 (comp list inc) ...]))) for instance

17:44 mmitchell: ok i have a (kind of) working friend workflow. The problem is, I don't want to redirect after a successful login, I just want to render a 201 (session created) - anyone know how to disable that redirect? hmm.

17:50 rasmusto: devn: (<!! out) seemed to work for me, did you write to in?

17:52 devn: rasmusto: like (go (>! (:in (pipeline [...])) 1) ?

17:52 coventry: In sablono, how do you get an attribute without a value (like autofocus) into a tag?

17:55 devn: rasmusto: ah, nevermind, i mixed something up

17:55 dbasch_: hyPiRion: why?

17:55 hyPiRion: dbasch_: why what?

17:55 dbasch_: hyPiRion: why do you think it should be final

17:56 zeeshanlakhani: reiddraper: around for a quick, but dumb question on test.check?

17:57 rasmusto: devn: oh, I did it with a single blocking write (trying to learn async stuff myself)

17:57 reiddraper: zeeshanlakhani: shoot

17:57 jcromartie: what's the better type to dispatch on: clojure.lang.IPersistentMap or clojure.lang.APersistentMap

17:57 devn: rasmusto: as in (>!! (:in (pipeline [...])))?

17:57 jcromartie: same question for sets and vectors, too

17:57 zeeshanlakhani: how can i tap into :max-size for running a tc/qc test via clojure.test (defspec)?

17:58 rasmusto: devn: yeah, though make sure you have a reference to out available to read from

17:58 reiddraper: zeeshanlakhani: unfrotunately thats' an outsanding issue at the moment: you can't with defspec

17:59 zeeshanlakhani: reiddraper: ah, ok. is there a link to the issue? just to keep tabs or possibly contribute?

18:00 hyPiRion: dbasch_: because if you want to conform to the Persistent Vector implementation, it is better to extend APersistentVector instead

18:01 reiddraper: zeeshanlakhani: lemme check

18:01 zeeshanlakhani: http://dev.clojure.org/jira/browse/TCHECK-10

18:03 zeeshanlakhani: reiddraper: thanks!

18:03 reiddraper: zeeshanlakhani: np

18:03 dbasch_: hyPiRion: that’s not reason enough to make it final

18:06 amalloy: dbasch_: what are you arguing should not be final? c.l.Persistentvector?

18:07 hyPiRion: amalloy: yeah

18:07 amalloy: that'd be really bad; for the same reason String has to be final

18:07 ie, if you give someone a String, they know it can't ever mutate

18:08 if i extend String to SneakyMutableString, you have a String which suddenly can change out from under you

18:08 devn: rasmusto: why do you say to "make sure"

18:08 rasmusto: does it change underneath you or something?

18:09 rasmusto: well, it'll make a new network each time you call (pipeline), right?

18:10 dbasch_: amalloy: it’s not final right now

18:13 devn: rasmusto: heh, im trying to figure it out

18:13 rasmusto: I tried pushing a hash-map onto it, and i got it out as a collection of map entries

18:15 well, it did say it took "things" and not "thing" :)

18:17 rasmusto: well, it'll partition the pieces if they're passed in a different way

18:18 devn: rasmusto: heh, if you're running in the repl beware

18:18 i found out i had 2,000 threads running

18:18 rasmusto: I know, had to restart it a few times

18:19 created a network of 100 threads and held down ctrl+enter in lighttable

18:25 amalloy: jcromartie: you should never dispatch on APersistentWhatever

18:25 interfaces, not implementations based on abstract classes, are what you care about

18:42 sir: What's that Clojure trick?

18:42 gfredericks: clojurebot: you |should never dispatch on| APersistentWhatever

18:42 clojurebot: Ack. Ack.

18:42 sir: Like, ((juxt remove get) {:foo 2} :foo) or something.

18:47 justin_smith: ,((juxt dissoc get) {:a 0 :b 1 :c 2} :b)

18:47 clojurebot: [{:c 2, :a 0} 1]

18:47 TEttinger: ~you

18:47 clojurebot: you should never dispatch on APersistentWhatever

18:47 TEttinger: see what you did gfredericks

18:49 sir: Ah yes, dissoc! Thanks.

18:54 gfredericks: TEttinger: yes indeed I do

18:55 * gfredericks has no regrets

18:55 gfredericks: ATransientSubHashTree$EMPTY$Seq

18:56 TEttinger: clojurebot: you |are| in the Clojure IRC channel. Good work.

18:56 clojurebot: You don't have to tell me twice.

18:56 gfredericks: clojurebot: you |don't have to tell| me twice

18:56 clojurebot: Roger.

18:57 gfredericks: I should find hiredman's csv file and uniq the verbs to see what the weirdest ones are

18:57 amalloy: gfredericks is a menace to bots everywhere

18:58 TEttinger: clojurebot: gfredericks |is| a menace to bots everywhere

18:58 clojurebot: In Ordnung

18:58 gfredericks: botmenace is gonna be my new internet handle once I turn 15

19:07 justin_smith: he's not the user input they were designed for, but he is the user input they need

19:13 rasmusto: ~menace

19:13 clojurebot: I don't understand.

19:13 rasmusto: doesn't clojurebot have some sort of search/pattern matching stuff?

19:21 justin_smith: ,(re-seq #"ab.a" "abracadabracadabra")

19:21 clojurebot: ("abra" "abra" "abra")

19:27 gfredericks: ,(re-seq #"(cad)?abra" "this string has abracadabra in it")

19:27 clojurebot: (["abra" nil] ["cadabra" "cad"])

19:28 gfredericks: ,(re-seq #"(?:cad)?abra" "this string has abracadabra in it")

19:28 clojurebot: ("abra" "cadabra")

19:37 rasmusto: ,(doc cadabra)

19:37 clojurebot: No entiendo

19:40 devn: rasmusto: get it figured out?

19:40 rasmusto: which part specifically?

19:40 devn: idk, just curious if you got it working to your satisfaction

19:41 I have a couple of functions which expect a map as input

19:41 rasmusto: devn: ah, I was really just messing about, didn't have an end goal really

19:41 did you get some maps to flow through it?

19:43 devn: i am going to play with it in a bit. i just got home

19:45 rasmusto: it doesn't seem to be runnning my functions

19:46 Glenjamin: Hi guys, is there a difference between alter-var-root and def ?

19:46 specifically if I'm not using the previous value

19:46 rasmusto: devn: did you (comp list yourfunc) ?

19:46 devn: rasmusto: no, is that really required?

19:46 rasmusto: devn: I think so, my brain didn't wrap around those inner loops though

19:47 devn: yeah, all that does is give me [{...}] as my out

19:47 where {...} has not had my fns applied to it

19:47 rasmusto: devn: got a paste? or an example of one of the fns + input

19:49 devn: rasmusto: ill have to do some cleaning, but sure

19:50 rasmusto: devn: (comp list #(assoc % :foo (rand-int 10))) was what I tested it with

19:50 devn: oh, maybe i just need another wrapper around my fn

19:52 now im just getting all nils -- weird

19:54 rasmusto: eval'ing in the file gives me nil as a result

19:54 rasmusto: devn: https://www.refheap.com/78833

19:54 devn: eval'ing in the repl gives me a different result

19:54 rasmusto: hm, that's weird

20:01 devn: rasmusto: got it working now -- not sure totally what is going on

20:01 storme: Hello, is there a way to specify (inc) to incream by two rather than one? i.e (inc(2) 1) = 3?

20:01 increase*

20:02 Bronsa: storme: just use +

20:02 hyPiRion: storme: (#(+ % 2) 1) ?

20:03 justin_smith: or partial can work

20:03 amalloy: ,(let [incrementor (fn [x] (fn [y] (+ x y))), inc2 (incrementor 2)] (inc2 1))

20:03 clojurebot: 3

20:03 storme: Bronsa: was hoping there was a more clojurey idiomatic way

20:03 amalloy: storme: addition is pretty idiomatic

20:03 storme: lol

20:03 amalloy: when you want to add two numbers, it's hard to be more idiomatic than +

20:04 storme: amolloy++

20:04 :)

20:04 justin_smith: ,(let [frob (partial + 42)] (map frob (range 4)))

20:04 clojurebot: (42 43 44 45)

20:04 amalloy: storme: your IRC client probably lets you tab-complete usernames

20:06 devn: rasmusto: bah, this is weird

20:06 rasmusto: devn: whats that

20:07 devn: it was calling my fn, now it's not

20:07 i have logging in it, so i should see it

20:10 gfredericks: amalloy: NumberManagerAwarenessBean.getAdditionMaker()

20:11 devn: rasmusto: if i remove the second function in the pipeline it works

20:11 or rather, it appears to actually call my fn

20:12 gfredericks: amalloy: I know enterprise OO jokes have been around awhile but mine is a creative reimagining of a classic

20:12 amalloy: gfredericks: http://java.metagno.me/ is a recent one

20:12 gfredericks: amalloy: oh this is a great idea

20:13 amalloy: i did slightly worse than chance

20:13 hyPiRion: gfredericks: ConcreteStatelessNumberMethodFactory.getAdditionMethod(3) ?

20:13 beamso: java.metagno.me is both brilliant and scary

20:14 justin_smith: they don't check whether the algorithm accidentally makes real class names

20:14 gfredericks: hyPiRion: it should probably be getAdditionCallable

20:14 hyPiRion: gfredericks: yeah, sorry. I'll show myself out.

20:14 justin_smith: so sometimes you know one of the classes is real, but it is not marked by the game as "real"

20:15 rasmusto: devn: hm, seems to work for me with a second function in there

20:15 devn: really?

20:15 can you paste for me?

20:15 justin_smith: Mathematics.Numbers.Operations.Linear.Commutative.AdditionBy(4)

20:16 gfredericks: org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver

20:16 ^ real

20:16 rasmusto: devn: https://www.refheap.com/78833

20:16 gfredericks: it has a subclass called ExceptionHandlerExceptionResolver (??)

20:18 Glenjamin: Hi guys, is there a difference between alter-var-root and def ?

20:18 gfredericks: yes

20:18 Glenjamin: if i'm not using the previous value, that is

20:19 bbloom: rasmusto: i am very bad at this game.

20:19 rasmusto: bbloom: sup?

20:19 justin_smith: I do worse than chance at the java.metagno.me game

20:19 hyPiRion: justin_smith: me too.

20:19 bbloom: rasmusto: whoops, i meant beamso

20:20 Si_: anyone here have any experience with caribou?

20:20 gfredericks: that means < 1/3 correct?

20:20 justin_smith: yes, I am at 0/6 at the moment

20:20 rasmusto: bbloom: :)

20:20 bbloom: rasmusto: i scrolled up & saw beamso's java class name game, then i saw you posted a refheap link and my brain barfed out your name on the tab complete

20:20 justin_smith: 1/8

20:20 rasmusto: bbloom: tab complete from the nick ending or something

20:20 fuzzy-find-nick

20:21 bbloom: rasmusto: nah just brain failure

20:21 rasmusto: fuzzy-brain-failure

20:21 bbloom: very.

20:23 devn: rasmusto: omg

20:23 rasmusto: devn: <! me

20:23 devn: rasmusto: somehow I rewrote the pipeline output map {:in (:in (first x)) ...} to be (last x)

20:23 rasmusto: >! your pants on

20:23 >!!*

20:24 rasmusto: okay, this works beautifully now. *sigh*

20:24 this is a sign i'm supposed to take a break

20:24 rasmusto: ah, that would explain it, were you trying to read and write from the same channel or something?

20:31 kras: HI, how do I get the quotient part of a division?

20:31 gfredericks: ,(quot 7 5)

20:31 clojurebot: 1

20:31 kras: ,(/ 856 100)

20:31 clojurebot: 214/25

20:31 justin_smith: the jvm does not let you do the division and quotient in one op sadly

20:32 if that is what you mean

20:32 devn: ,((juxt numerator denominator) 1/12)

20:32 clojurebot: [1 12]

20:32 justin_smith: I guess someone could make a machine level binding that makes the appropriate call to the underlying cpu

20:32 devn: is that what you mean?

20:32 bbloom: i wouldn't be surprised if there was a div/mod peephole optimization for x86 at least

20:32 in hotspot, anyway

20:32 justin_smith: bbloom: how would you bind to it? would the jit just do it?

20:33 kras: quot would do just fine for my case

20:33 bbloom: justin_smith: you'd probably just have to do division & quotation right next to each other with the same variables as inputs & have them be primitives

20:33 justin_smith: but i'm just guessing

20:34 justin_smith: still, probably unlikely to be accomplished via a var in clojure. would need a java method

20:34 kras: thanks guys

20:34 gfredericks: bbloom: quotation? is this a word?

20:34 bbloom: gfredericks: er, quotient

20:34 quotations on the brain :-P

20:34 amalloy: quotientation

20:34 bbloom: if you haven't noticed by now, my brain is totally not a brain at the moment

20:34 justin_smith: gfredericks: it is a word, but wrong domain

20:35 ,''''''quote

20:35 clojurebot: (quote (quote (quote (quote (quote quote)))))

20:35 devn: rasmusto: damn, this is really nice now that it's working.

20:35 hiredman: thanks again for that gist. very cool.

20:36 arrdem: ,''

20:36 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

20:36 devn: ,`':>

20:36 clojurebot: (quote :>)

20:36 justin_smith: ,''''''(unquote "brain")

20:36 clojurebot: (quote (quote (quote (quote (quote (unquote "brain"))))))

20:36 gfredericks: ,'etouq

20:36 clojurebot: etouq

20:36 devn: ,`'~:>

20:36 clojurebot: (quote :>)

20:36 gfredericks: ,''etouq

20:36 clojurebot: (quote etouq)

20:36 bbloom: ,(defrecord Hold [x])

20:36 clojurebot: sandbox.Hold

20:36 devn: ,(Hold. x)

20:36 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:0:0)>

20:36 devn: ,(Hold. 1)

20:36 clojurebot: #sandbox.Hold{:x 1}

20:36 bbloom: ,#sandbox.Hold (inc 5)

20:36 clojurebot: #<RuntimeException java.lang.RuntimeException: Record construction syntax can only be used when *read-eval* == true>

20:37 bbloom: ,#sandbox.Hold {:x (inc 5)}

20:37 clojurebot: #<RuntimeException java.lang.RuntimeException: Record construction syntax can only be used when *read-eval* == true>

20:37 bbloom: blah

20:37 arrdem: bbloom: oh god why

20:37 devn: ,(binding [*real-eval* true] #sandbox.Hold {:x (inc 5)})

20:37 clojurebot: #<RuntimeException java.lang.RuntimeException: Record construction syntax can only be used when *read-eval* == true>

20:37 devn: worth a try

20:37 bbloom: ,(eval (Hold. '(inc 5)))

20:37 clojurebot: #sandbox.Hold{:x (inc 5)}

20:37 arrdem: (inc devn)

20:37 lazybot: ⇒ 17

20:37 gfredericks: ,#=(set! *read-eval* true)

20:37 clojurebot: #<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.>

20:38 devn: heh, Ye Olde #=

20:38 For some reason this reminds me of when #^ was the metadata syntax

20:38 gfredericks: what should #~ do

20:38 devn: and i have no idea why

20:39 gfredericks: do a load-string

20:39 lemonodor: ,(binding [clojure.core/*real-eval* true] #sandbox.Hold {:x (inc 5)})

20:39 clojurebot: #<RuntimeException java.lang.RuntimeException: Record construction syntax can only be used when *read-eval* == true>

20:39 devn: ,*read-eval*

20:39 clojurebot: false

20:40 gfredericks: guys you gotta actually call the reader if you want that sort of thing to work

20:40 justin_smith: ,(= 'real 'read)

20:40 clojurebot: false

20:40 devn: ,(read-string "(binding [clojure.core/*read-eval* true] #sandbox.Hold {:x (inc 5)})")

20:40 clojurebot: #<RuntimeException java.lang.RuntimeException: Record construction syntax can only be used when *read-eval* == true>

20:40 gfredericks: not like that either

20:40 you do the binding outside the read

20:41 devn: show me

20:41 tough guy

20:41 gfredericks: it's not going to work of course

20:41 but it's the only way that even *could* work

20:41 ,(binding [*read-eval* true] (read-string "#sandbox.Hold {:x (inc 5)}"))

20:41 clojurebot: #sandbox.Hold{:x (inc 5)}

20:41 gfredericks: omg omg omg omg omg omg

20:41 devn: bahahahahahahahahahahaha

20:42 * devn kicks gfredericks in the shin

20:42 bbloom: awesome

20:42 justin_smith: wait what?

20:42 devn: ,(binding [*read-eval* true] (read-string "(defn foo [x] (inc x))"))

20:42 clojurebot: (defn foo [x] (inc x))

20:42 devn: ,(binding [*read-eval* true] (eval (read-string "(defn foo [x] (inc x))")))

20:42 clojurebot: #'sandbox/foo

20:43 gfredericks: ,(set! *read-eval* true)

20:43 clojurebot: true

20:43 gfredericks: ,#=(inc 54)

20:43 clojurebot: #<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.>

20:43 gfredericks: ,(read-string "#=(inc 54)")

20:43 devn: ,*read-eval*

20:43 clojurebot: #<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.>

20:43 false

20:43 devn: ,(binding [*read-eval* true] (eval (read-string "#=(inc 54)")))

20:43 clojurebot: 55

20:43 justin_smith: gfredericks: I think it has to do with the fact clojurebot puts eat eval in a new thread

20:44 gfredericks: devn: you didn't need the eval there

20:44 devn: right, 'cause hash equals

20:44 ,(binding [*read-eval* true] (read-string "#=(inc 54)"))

20:44 clojurebot: 55

20:44 gfredericks: now let's try to do something forbidden

20:44 ,(try 42)

20:44 clojurebot: 42

20:44 devn: :X

20:44 amalloy: since when does clojurebot allow eval? i thought it didn't used to do that

20:44 gfredericks: ,(try 42 (catch Throwable t t))

20:44 clojurebot: gfredericks: Gabh mo leithscéal?

20:44 gfredericks: ,(identity "catch")

20:44 clojurebot: gfredericks: Pardon?

20:45 gfredericks: well that'll be tough

20:45 devn: ,(binding [*read-eval* true] (read-string "#=(try 42 (catch Throwable t t))"))

20:45 clojurebot: devn: Gabh mo leithscéal?

20:45 devn: :(

20:45 ,(inc 1)

20:45 clojurebot: 2

20:45 gfredericks: amalloy: maybe my nagging about bots & eval from a year ago paid off

20:46 kras: ,(partition 1 (str 999))

20:46 clojurebot: ((\9) (\9) (\9))

20:46 kras: does \9 here mean a char?

20:46 gfredericks: yep

20:46 bbloom: ,(intern 'clojure.core 'push-thread-bindings (fn [bindings] (clojure.lang.Var/pushThreadBindings (assoc bindings #'clojure.core/*read-eval* true))))

20:46 clojurebot: #'clojure.core/push-thread-bindings

20:46 gfredericks: ,(type \9)

20:46 clojurebot: java.lang.Character

20:46 gfredericks: kras ^

20:46 bbloom: , #=(inc 54)

20:46 clojurebot: 55

20:46 bbloom: boom.

20:47 ,(intern 'clojure.core 'push-thread-bindings (fn [bindings] (clojure.lang.Var/pushThreadBindings (assoc bindings #'clojure.core/*read-eval* false))))

20:47 clojurebot: #'clojure.core/push-thread-bindings

20:47 bbloom: , #=(inc 54)

20:47 clojurebot: #<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.>

20:47 bbloom: ,(intern 'clojure.core 'push-thread-bindings (fn [bindings] (clojure.lang.Var/pushThreadBindings (assoc bindings #'clojure.core/*read-eval* true))))

20:47 clojurebot: #'clojure.core/push-thread-bindings

20:47 bbloom: , #=(inc 54)

20:47 clojurebot: 55

20:47 bbloom: i win.

20:47 security. how does it work?

20:47 kras: gfredericks: thanks, I keep forgetting about type

20:47 gfredericks: clojurebot: bbloom is a read evaluator

20:47 clojurebot: 'Sea, mhuise.

20:48 devn: ,(binding [*read-eval* true] (read-string "#=(.listFiles (java.io.File. \"/\"))"))

20:48 clojurebot: #<RuntimeException java.lang.RuntimeException: Can't resolve .listFiles>

20:49 gfredericks: I don't think #= supports most expressions

20:49 ,#=(+ 1 2)

20:49 clojurebot: 3

20:49 gfredericks: ,#=((identity +) 1 2)

20:49 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol>

20:49 gfredericks: ^ see

20:50 bbloom: ,#=(apply (identity +) [1 2])

20:50 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn>

20:50 bbloom: ,#=(apply + [1 2])

20:50 clojurebot: 2

20:50 bbloom: heh

20:50 gfredericks: prollably just literals for argsies

20:51 kras: ,(map Integer. ("9" "9" "9"))

20:51 clojurebot: #<CompilerException java.lang.ClassNotFoundException: Integer., compiling:(NO_SOURCE_PATH:0:0)>

20:51 kras: I guess I can;t do this

20:51 gfredericks: ,(map #(Integer. %) ["9" "9" "9"])

20:51 clojurebot: (9 9 9)

20:52 kras: ,(type #(Integer. %))

20:53 clojurebot: sandbox$eval26$fn__27

20:53 kras: what is the type of Integer.

20:53 gfredericks: ,(map (fn [s] (Integer. s)) ["9" "9" "9"])

20:53 clojurebot: (9 9 9)

20:53 kras: it is a constructor

20:53 gfredericks: yes constructors aren't proper objects

20:53 amalloy: kras: it has no type, because it's not a value

20:53 devn: i wonder if we could get clojurebot to read in the code for serializable fns

20:54 and then serialize a fn it wouldn't normally allow

20:54 and read it

20:55 kras: so what can we classify this as, this is definitely a specail form since it understands (Integer. "9')

20:56 gfredericks: yes it's a special form

20:56 kras: special form for Java interop

20:56 gfredericks: right

20:57 kras: Okay got it, thanks a lot

21:11 jwm: can you use use at runtime after compiling?

21:11 hehe -after compiling since it is runtime :)

21:12 justin_smith: jwm: can you use what at runtime? interop?

21:13 yes, you can do interop at runtime

21:14 jwm: well I am trying to use "use" from a function I am calling from -main

21:14 its not going so well when I run it with lein run

21:17 is there something different about -main

21:17 like, can I not use do?

21:17 I forget what the docs mentioned about -main

21:23 gfredericks: you're running use inside a function?

21:26 jwm: yeah

21:28 gfredericks: why would you need to do that?

21:29 jwm: configurable code/module loading

21:29 gfredericks: so what do you mean by "it's not going so well"?

21:32 jwm: the function call completes and so do the use statements but they dont get sucked into my current namespace

21:33 gfredericks: how can you tell they don't?

21:33 the actual structure of your code is important here because use is only going to affect code compiled in the future

21:34 e.g. (defn f [] (use 'clojure.string) (split ...)) does not work

21:35 jwm: when I do lein run it runs the println statements in main and makes the function calls but nothing is actually run (I have a few init functions called also in the same functions)

21:36 gfredericks: you don't get any exceptions? are you sure the problem is with use?

21:36 jwm: I dont get any exceptions

21:36 well I call the function directly outside of -main from the repl and it works

21:36 gfredericks: might be a red herring; are you running something that returns a lazy seq?

21:37 jwm: yeah, I run for loop

21:37 beamso: it's something lazy that is being run in the repl but not at the command line

21:37 i think you have to use doseq instead of run

21:37 *for

21:37 gfredericks: jwm: for is not for looping

21:38 it's for list comprehension and it's lazy

21:40 jwm: I stradle everything with dos

21:41 I'm making another language called do ;)

21:44 Frozenlo`: that `for' problem has bitten me more than it should

21:45 jwm: yeah, I knew it was lazy too

21:45 Frozenlo`: I always test in the repl first, so I don't notice it until I've coded quite a few functions on top;

21:45 jwm: I moved my (do earlier

21:45 yeah I am 100% repl coding

21:46 gfredericks: somehow I got to a point where putting side effects in a for just feels completely unnatural

21:46 I think I'm just usually aware of whether I'm writing side-effect code or functional code

21:47 Frozenlock: Oh I'm aware of that. I just can't get in my head that `for' won't cut it.

21:49 jwm: we should have a lor and a normal for

21:49 lor, lazy, for, not lazy :)

21:53 that fixed it

21:53 nice to see doseq has :let also :)

21:53 gfredericks: yeah they're pretty much the same

21:54 jwm: I hadn't used doseq because it looked shitty to me based on the examples

21:54 seangrove: bbloom: How would your layout system handle dynamic resizing? i can see changing the top-level slot width, but how do nested components calculate their sizes?

21:59 gfredericks: nrepl middleware must be the one thing that's easier to test via `lein test` than at the repl

22:00 well probably also anything to do with repls at all

22:19 kras: Is String/join same as java.lang.String/join?

22:20 arrdem: ,(use 'clojure.string)

22:20 clojurebot: #<SecurityException java.lang.SecurityException: denied>

22:20 arrdem: ,(require 'clojure.string)

22:20 clojurebot: nil

22:20 arrdem: ,(source clojure.string/join)

22:20 clojurebot: #<SecurityException java.lang.SecurityException: denied>

22:21 right1: ,((defn a [] (a)))

22:21 clojurebot: #<StackOverflowError java.lang.StackOverflowError>

22:23 kras: looks like all the java.lang.* are available in the default namespace 'user'

22:31 zcaudate: Does anyone know any good meta programming books for lisp?

22:32 lurker: zcaudate: Let Over Lambda, many chapters available online

22:33 zcaudate: @lurker... Something a bit easier??

22:33 lazybot: zcaudate: What are you, crazy? Of course not!

22:36 arrdem: that.... was freakishly appropriate

22:36 Frozenlock: zcaudate: https://www.youtube.com/watch?v=2Op3QLzMgSY

22:36 zcaudate: I'm looking at doing some type coercing stuff with reflection

22:38 arrdem: Frozenlock: oooh. Read SCIP, loved it, didn't know there were lectures :D

22:38 (inc Frozenlock)

22:38 lazybot: ⇒ 4

22:38 Frozenlock: Yeah, by the masters themselves :p

22:38 (starts a little slow... but good nonetheless)

22:40 lurker: zcaudate: more specifically?

22:43 arrdem: "we are going to conjure our spirits in a magical language called LISP".

22:43 priceless

22:46 zcaudate: Haha. Yeah I love that series

23:03 bbloom: seangrove: you looking at the old or new code?

23:04 seangrove: both are old / hacked up, but i mean the one file or the repo i shared?

23:23 amalloy: let over lambda isn't really great for clojure anyway

23:25 arrdem: not for idiomatic clojure certainly... the techique of using closure'd mutable state to impact successive function invocations is kinda cute and the tricks played with macros are interesting.

23:25 but I've never seen anyone else write or condone code written that way..

23:27 tbaldridge: arrdem: sadly I've seen codebases like that

23:27 where every static value inside the defn is defined in a outer let

23:27 arrdem: that's unfortunate....

23:27 tbaldridge: (let [x {:a :foo}] (defn myfunc [m] (merge m x)))

23:27 that sort of stuff ^^

23:28 arrdem: was there a reason for this style? from a code gen point of view it doesn't buy you anything..

23:28 tbaldridge: from what I understand there was some thoughts that it might be faster. IDK, I'd rather write "normal" code and then hire some guy to devote his summer to making the compiler emit better code.

23:29 arrdem: =

23:29 tbaldridge: :-P

23:29 arrdem: =D

23:29 talked to some grad students today about my plots for making clojure run fast, and it sounds like I've got enough interesting ideas that I can get my undergrad thesis out of this project. soooo.....

23:30 tbaldridge: nice

23:30 Yeah, I'll be interested in seeing where this all goes. I mean HotSpot is pretty darn good, but that doesn't mean we have to lean on it quite as much as we do.

23:32 cddr: zcaudate: The Art of the Metaobject Protocol is another classic

23:32 arrdem: After talking about ideas with my TA for about an hour today I've got kind a 6 point list of "obvious" whole program operations and tweaks to bytecode generation that should make an appreciable difference. Of course how much is gonna be half the object of the ideal final paper 'cause I have to justify that this work is unique compared to other JVM DCE and compression tools.

23:35 cddr: Has anyone thought of applying stuartsierra's component lifecycle model to docker containers?

23:35 https://github.com/stuartsierra/component

23:37 zcaudate: Oh thats really cool... thats kinda the ultimate for optimization... but i just want to be able to treat objects as maps... And to be able to coerce data between them.

23:38 Thanks @cddr.. are there any with clojure source code as examples?

23:40 @cddr.. Are you using docker with pallet?

23:40 cddr: I was thinking of something more like flynn

23:44 lurker: zcaudate: Treat objects like maps? A bit like http://stackoverflow.com/questions/23110132/factor-clojure-code-setting-many-different-fields-in-a-java-object-using-a-param ?

23:54 zcaudate: Oh okay.. https://flynn.io/ but wouldn't you use docker as a container for clojure rather than the other way around?

23:55 beamso: flynn lives!

23:56 cddr: I was thinking of building something like flynn but controlled by clojure (though in reality, that's probably too ambitious for the likes of me)

23:58 beamso: forgive my ignorance but what is the point of flynn?

Logging service provided by n01se.net