#clojure log - Jun 22 2013

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

0:00 hiredman: I played with a lisp that did the source to source thing to go

0:00 bbloom: hiredman: 1) it's more mature, if that's what you mean and 2) the hotspot JIT really helps dynamic languages, which go's runtime likely won't

0:00 hiredman: way to static, and not enough of a platform to really leverage

0:00 no dynamic code loading

0:01 Qortzniv: callen, how did you know it was i?

0:01 bbloom: hiredman: which is essentially true of cljs when deploying too

0:01 technomancy: dynamic code loading is a pretty important prerequisite for any platform I'd touch with a ten-foot pole

0:02 hiredman: the reflection facilities in go are super primitive

0:02 anyway, I did not care for it

0:04 bbloom: i think you just need to use a slightly different strategy: you can do incremental compilation in memory & then communicate via channels. in production builds, you can statically link, like in cljs

0:05 i really love the incremental work flow in clojure, but i fully appreciate the static-everything approach for deployments

0:05 but still, you're right, it probably wouldn't be great for a dynamic language at all

0:05 not without a lot more work

0:06 hiredman: bbloom: you would have to write an interpreter, but the interpreter would not be able to call go functions that where not already used in the executable

0:06 bbloom: hiredman: the interpreter would surely be compiled with a full list of stubs in a dev build, so there would be no dead code to remove

0:07 hiredman: bbloom: gross

0:07 bbloom: anyway, let me retract my statement about me wishing golang was the compilation target of choice

0:07 you're right

0:07 tomjack: is 'dynamic language' about more than the type system?

0:07 hiredman: bbloom: and what about interoping with go libraries outside of the standard lib?

0:07 bbloom: where i was really coming from was this: i wish every java (the language) shop magically became a go (the language) shop

0:07 :-P

0:08 hiredman: I started on this, and it sucked, with exactly that a list of stubs for the interpreter to use, etc

0:08 cneira: is there any roadmap for clojure the future features in clojure , like continuations ?

0:08 bbloom: tomjack: if you care about performance, you need a runtime that is defined for dynamic call sites and stuff

0:09 cneira: you can assume that full continuations will never happen & that delimited continuations are mildly unlikely

0:09 Pupnik_: clojure on luajit!

0:10 tomjack: speaking of that, shouldn't it be pretty easy to build delimited continuations using ioc-macros?

0:10 hiredman: https://github.com/hiredman/qwerty/blob/master/src/qwerty/lisp/golib.q

0:11 it is kind of gross because I was waiting to get the interpreter working to add macros

0:13 tomjack: bbloom: so could you have a 'dynamic' language with a type system more like what we expect from a 'static' language?

0:14 or are they conflated for a good reason

0:14 bbloom: tomjack: maybe it's this delicious gin, but i'm going to ignore your question and instead say that it's kinda a false dichotomy to describe dynamic vs static

0:15 everything is always some shade of gray

0:15 there are things you know statically and things you don't know statically

0:16 go has interface{} which is basically the same as "object" in java, which is essentially dynamic typing

0:16 tomjack: ok, 'false dichotomy' is sort of the answer I was hoping for anyway :)

0:17 jimrthy: It seems like Qi at least sort-of takes that approach: common lisp with static typing.

0:18 But I've never gone any further than skimming its web page a few years back.

0:19 bbloom: tomjack: consider (pop 1 2) for example.

0:19 tomjack: in clj that throws an error at runtime, but there isn't really any strong reason that can't be an error at compile time

0:19 tomjack: module re-defining vars :-/

0:20 tomjack: but in clojurescript! lol you know what var values are, so if you know you have a var, you can look at it's arities. and in fact, cljs does

0:20 tomjack: if IPersistentStack were a protocol like it wants to be..

0:20 bbloom: tomjack: cljs will emit direct dispatch to a particular arity

0:20 tomjack: ignore protocols, it could be (defn f [x] ...)

0:20 tomjack: in cljs, if you call (f 5) we emit f._some_magic_thing_for_arity_1

0:20 tomjack: oh yeah, missed that that was the error

0:21 bbloom: the point is that we know, statically, some stuff, so we can use that to optimize

0:21 the difference between "static" and "dynamic" languages is one of philosophy

0:21 a static language tries to prevent as many errors as possible at compile time and to perform as many optimizations as possible then too

0:22 a dynamic language tries to stay out of your way at compile time

0:22 and as such, needs to recover error detection and performance at runtime

0:22 this is why i'm a big believer in pluggable type systems

0:22 and extensible compilers

0:23 in theory, if my app is too slow, i want to be able to make it faster by adding static information

0:23 and in fact, clojure does precisely this with type hints

0:23 however, there are non-type related examples of things that you can use as static hints

0:24 like consider the old C macros for LIKELY and UNLIKELY

0:24 tomjack: I hope someday your dreams about the cljs analyzer/compiler come true

0:24 callen: clojure -> asm.js?

0:24 bbloom: callen: you wanna write a garbage collector & compile it to asm.js? :-P

0:24 callen: clojure -> emscripten JVM implementation?

0:25 bbloom: callen: honestly, i think it makes much more sense to compile to js directly for a dynamic language. for a static language, sure, compile to asm.js

0:25 callen: borrow that 30 petaflop chinese supercomputer. should get 30 fps on Minecraft.

0:25 (30 fps'ish)

0:25 bbloom: tomjack: check out my little secret project here: https://github.com/brandonbloom/ascribe/blob/cljs/test/ascribe/cljs/attrs/clj.clj

0:26 tomjack: basically finished macro expansion, starting on primitive analysis

0:27 tomjack: my goal is no more than twice as slow as CLJS (without the google closure step) but 100X easier to extend w/ new analysis, better errors, etc

0:28 tomjack: anyway, are you familiar with likely and unlikely?

0:28 http://stackoverflow.com/questions/109710/likely-unlikely-macros-in-the-linux-kernel

0:28 tomjack: nope

0:28 bbloom: that's non-type-related static info used for optimization

0:28 tomjack: makes sense though

0:29 bbloom: i'm also not a believer that type systems need to be complete/sound/whatever

0:29 i think it's totally fine if a type system runs a core.logic style search & just gives up after some amount of time & compiles the best code it can with the info it gathered in the time it had

0:30 tomjack: in that case, nothing is non-type-related :)

0:31 bbloom: sure

0:32 tomjack: reading ekman now, ascribe looks very interesting

0:32 don't understand it at all but the code you linked looks very clean, especially compared to the macroexpansion code I'm writing

0:33 bbloom: tomjack: clean is the goal :-)

0:35 tomjack: holy shit 151 pages

0:36 * tomjack puts ekman down, trusts you'll write some nice docs someday :)

0:36 bbloom: haha

0:36 yeah, it's a full thesis, lots of individual papers

0:37 tomjack: https://code.google.com/p/racr/ is probably a pretty short intro to the bag of ideas

0:38 tomjack: I wonder if it's a coincidence that the first paragraph ends with "DADA"

1:35 ouch, nrepl.el doesn't yet support previous-error/next-error?

1:41 Raynes: tomjack: sofixit

2:15 spoon16: anyone know if it's possible with compojure to have a set of middleware applied only to the routes defined within a given (context) expression?

2:19 SegFaultAX: spoon16: Routes and middleware are just functions.

2:20 You can wrap the middleware around the route directly (my-middleware (GET ...))

2:39 spoon16: thanks SegFault

2:46 snake-john: how do I do in emacs "select whole s-expr under cursor" … I've got clojure mode and paredit on…

2:48 tomjack: I think you probably want expand-region

2:49 "whole s-expr under cursor" is ambiguous, right?

2:49 if you mean point is on/before the opening paren, C-M-SPC

2:51 snake-john: yes that is what I meant! But when I hit continuously C-M-SPC I would like the selection to expand to the parent s-exp.

2:52 tomjack: yeah that's expand-region I believe

2:52 it's not bundled with emacs

2:52 https://github.com/magnars/expand-region.el

2:53 snake-john: thanks a lot just give me 5 minutes I will try it out

2:53 tomjack: I've never used it, just heard about it

2:53 hopefully it actually does what you want..

3:13 callen: https://github.com/bgschiller/latex-therefore

3:13 dnolen_: technomancy ^^

3:13 snake-john: @tomjack ha great it works thanks a lot again. One minor thing : I tried to bind it with (global-set-key "\M-C-SPC" 'er/expand-region) in my init.el. but unfortunately when I restart and do a c-h k M-C-SPC I see "C-M-SPC runs the command mark-sexp"

3:16 tomjack: I'd try (global-set-key (kbd "C-M-SPC") ...)

3:17 no need to restart, just put point on that and do C-M-x

3:18 snake-john: thank you so much it works now!

3:21 francis_wolke: has anyone worked with three.js and clojurescript

3:21 ? I'm having some issues, but no errors or anything to work from to tell me what I'm doing wrong

3:22 the #clojurescript channel is dead - else I'd ask there.

3:24 murtaza52: hi I need help with creating a leiningen plugin

3:25 I have created a plugin which watches for any changes in a dir, thus the thread needs to keep on running, and not exit.

3:26 The main thread actually creates futures which watch for changes.

3:26 When i execute the code from repl ( not lein $task), it works well.

3:26 However when I run it from another project as lein $task, it doesnt work.

3:27 First question how do I get a long running blocking process, like lein cljsbuild :auto ?

3:43 got it to work (when true) did the trick !

3:43 callen: http://prog21.dadgum.com/3.html

3:46 tomjack: (when true) ?

3:49 "And what is this really gaining you over C?" -- missing the point

3:49 well.. part of the point

3:51 to be fair I missed that point to when I looked at ztellman's asteroids

3:52 murtaza52: I wanted an infinite loop, when the plugin task was run. So (when true) does it.

3:53 tomjack: if we look at something like ants.clj I think that's a very good point

3:54 refs pointing to persistent data is obviously a lot we gain over C, but ignoring that, what we gain seems to be sanity in the face of parallelism

3:54 which is not enough!

3:55 well maybe it's enough for ants.clj

3:55 francis_wolke: RE: what I said earlier, figured it out

4:01 rurumate: I want to add clojure to an existing JAX/RS project. It needs to be a servlet so I can integrate it via web.xml. Is there a elegant / fun way, other than (gen-class :extends HttpServlet)?

4:04 ddellacosta: aws s3 permissions #*$@%!

4:04 that's all I got

4:08 tomjack: rurumate: you might have a look at https://github.com/ring-clojure/ring/blob/master/ring-servlet/src/ring/util/servlet.clj

4:08 either for inspiration, or just use it

4:09 callen: ddellacosta: your first mistake was using S3. Your second mistake, and this is the really critical one, was to not anticipate its failure. This damaged your karma.

4:09 ddellacosta: callen: *sob*

4:09 tomjack: what's wrong with S3?

4:09 ddellacosta: ddellacosta: I don't know how to use it for one

4:10 callen: tomjack: not enough monads.

4:10 SegFaultAX: ddellacosta: What are you trying to do?

4:10 ddellacosta: whoops, just addressed myself

4:10 brilliant

4:10 tomjack: ah, true..

4:10 callen: ddellacosta: sign of a magnificent conversationalist when they can efficiently pare down the minimum by (dec 2)

4:10 ucb: monads and S3. Yes.

4:11 tomjack: hmm, core.logic bug? https://www.refheap.com/84fdcc8257787e30e53187611

4:11 callen: ucb: you're in for it now.

4:11 ddellacosta: I am trying to set ACL for public read on putting an object to S3 using clj-aws-s3. And I just get permission denied, no matter how I try to massage the permissions.

4:11 rurumate: tomjack: neat, thanks

4:11 ucb: callen: ruh-roh

4:11 ddellacosta: sorry, that was to SegFaultAX

4:11 callen: I try to be efficient

4:12 nothing to do with Clojure really, just felt like venting to someone, anyone (apologies)

4:12 SegFaultAX: ddellacosta: Is it possible that the access key and secret you're using don't have sufficient permissions on the bucket?

4:12 callen: ddellacosta: default bucket policy has read access for everybody

4:13 ddellacosta: so unless your policy is set to something other than the default or the ACL was previously modified, you're failing to modify the ACL of something you shouldn't modify.

4:13 ddellacosta: SegFaultAX: one can imagine this as a possibility, which is why I explicitly enabled the user whose credentials I'm using to read the bucket list, upload and set permissions

4:13 tomjack: ddellacosta: dunno if you already know, 404's will look like permission denied too

4:13 ddellacosta: callen: as far as I can tell, the images are definitely not read-all--tried looking at them without setting permissions

4:13 callen: ddellacosta: please check the bucket policy.

4:14 ddellacosta: tomjack: definitely getting a 403 here.

4:14 SegFaultAX: ddellacosta: ddellacosta Does that mean s3*?

4:14 s3:* rather

4:14 tomjack: that's what I mean

4:14 callen: 403s are now 404s? Sweet.

4:14 SegFaultAX: No, they aren't.

4:14 You'll get a perm denied if that's the case.

4:14 tomjack: you won't get a 404, you get a 403

4:15 callen: ddellacosta: and the bucket policy iiiiiiissssss?

4:15 ddellacosta: callen: https://www.refheap.com/16010

4:15 yeah, sorry I'm using s3

4:15 but I'm a total beginner, so it's not surprising I'm doing something stupid…

4:15 callen: ddellacosta: broskie, that's read access to everyone.

4:15 ddellacosta: callen: *sob*

4:16 callen: ddellacosta: that's the default policy. uhm. mostly. the Sid is unfamiliar to me.

4:16 action, effect, principal all mean what I think they mean though.

4:16 ddellacosta: callen: yeah, the principal thing seems to be the user/role this is being applied to

4:16 if I understand it properly

4:17 meh, gonna take a break. Maybe I'll have an epiphany and figure it out later.

4:17 callen: not to be a bore, but you're sure you 1. Need to set the ACL (this isn't publicly accessible?) and 2. You're using the right keys to set the ACL if #1 is true?

4:17 ddellacosta: thanks for your help, callen, SegFaultAX, tomjack

4:17 callen: ddellacosta: but now I'm interested.

4:17 gerd dermert.

4:17 ddellacosta: callen: heh

4:17 SegFaultAX: ddellacosta: You didn't say that accessing a blob from the bucket was an error. You said setting the perm was an error. Which is it?

4:17 callen: ddellacosta: while you're going, I'm going to own your box, steal your keys, and figure it out for myself.

4:18 ddellacosta: callen: WELL then, the thing I'm getting stymied on is exactly setting the ACL--that's where I get the 403 actually

4:18 callen: ddellacosta: okay fuck the ACL. Can you load the file as a public reader?

4:18 ddellacosta: verify that the ACL is a problem to begin with.

4:19 ddellacosta: SegFaultAX: that's it exactly. I think we got derailed a little when I posted the bucket policy, but that is and was my main problem.

4:19 SegFaultAX: ddellacosta: Can you change it from the console?

4:19 ddellacosta: Or the API?

4:19 callen: I asked for the bucket policy to verify the necessity of even touching the ACL.

4:19 ddellacosta: callen: yeah, I definitely can't get to files by default, and I'd rather be explicitly setting the policy on files in any case. Ah, gotcha.

4:19 callen: I still want to resolve the ACL permissions issue, mind, I just want to gather more data.

4:19 SegFaultAX: callen: Entirely irrelevant to the problem.

4:19 ddellacosta: SegFaultAX: I can change it from the console. Not from the API--that's where I get the 403.

4:20 SegFaultAX: ddellacosta: Sounds like your access key and secret aren't properly configured.

4:20 callen: ddellacosta: and you're sure the keys are proper? do the keys work for any other part of the AWS API?

4:21 SegFaultAX: ddellacosta: Check for stupid stuff, like missing the first/last letter of either the key or the secret during copy/paste.

4:21 ddellacosta: SegFaultAX, callen: the creds I'm currently using are a separate user I set up just for this bucket. They have allowed me to do stuff like access the list, upload objects, up until now, but now setting this permission seems verboten.

4:21 callen: ddellacosta: re-verify that other things work (just like one or two) please.

4:21 SegFaultAX: ddellacosta: Did you add change permissions for this IAM account for this bucket?

4:21 ddellacosta: sure

4:22 SegFaultAX: I explicitly added a permission so that this user can list, upload/delete, view permissions, and edit permissions.

4:23 callen: just tried uploading a file via my app again, works fine, as long as I don't attempt to set the permissions. Listing all the current objects works fine too (that's my default view).

4:23 callen: ddellacosta: dump the user policy please.

4:23 SegFaultAX: ddellacosta: And you can, from the console, change the perms /as this users/?

4:23 User*

4:23 callen: SegFaultAX: I think it's a one-off IAM thing he made

4:23 I don't think he's logged in as this credential in the user in question

4:23 ddellacosta: callen: that's exactly right

4:24 callen: ddellacosta: user policy prz.

4:24 ddellacosta: callen: one sec, getting' it

4:24 callen: cool.

4:27 ddellacosta: callen: sorry, not sure exactly how to dump these

4:27 SegFaultAX: ddellacosta: Easiest from the console.

4:28 ddellacosta: callen: basically, there's me ddellacosta, and "Authenticated Users", which have all List, Upload/Delete, View Permissions, and Edit Permissions set. That's it on this bucket.

4:28 callen: ddellacosta: https://aws.amazon.com/iam/ ?

4:28 ddellacosta: I am using an IAM user to access this, which I *assumed* qualified as an "Authenticated User"

4:28 SegFaultAX: ddellacosta: What arns?

4:29 ddellacosta: callen: yeah, just one user there, nothing in particular set--so I have to explicitly enable that user to access the bucket?

4:29 SegFaultAX: what's arns, sorry?

4:30 SegFaultAX: ddellacosta: The thingies in the "Resource" part of the policy.

4:30 callen: ddellacosta: you need to add the bucket to resource

4:30 ddellacosta: http://mikeferrier.com/2011/10/27/granting-access-to-a-single-s3-bucket-using-amazon-iam/

4:30 SegFaultAX: I'm not paid enough.

4:31 SegFaultAX: ?

4:31 ddellacosta: callen: I owe you a beer(s) or, maybe knowing you, tea(s)…

4:32 SegFaultAX: https://www.refheap.com/16010, but I'm going to try and update this now after reading the thing callen linked me to

4:33 SegFaultAX: ddellacosta: Your resource is wrong.

4:33 But try the link first.

4:33 (Your bucket is its own resource separate from its contents)

4:34 ddellacosta: SegFaultAX: yah, clearly I have more reading to do on AWS. In any case, I think between your pointers and callen's doc I'll be able to get this going…thank you both!

4:34 SegFaultAX: You mean Mike Ferrier's doc.

4:34 callen: SegFaultAX: I'm enjoying the attribution/credit - sshhhh

4:35 SegFaultAX: if Stack Overflow is be taken as an example, discovery and aggregation is as valuable as creation.

4:35 SegFaultAX: Ok.

4:35 callen: ddellacosta: so while trying to learn the underpinnings of AWS APIs, it's worthwhile to remember that a lot of this stuff fell out of internal SOA stuff.

4:36 ddellacosta: callen: interesting…I have to be honest, I've kind of put off learning the AWS security stuff, which is bad form, I know...

4:36 my excuse is that I haven't used it to any great extent until now.

4:37 callen: ddellacosta: I had the same attitude, we're all sinners and all that.

4:37 ddellacosta: yah, exactly.

4:37 callen: ddellacosta: I got tired of letting AWS APIs make me play the fool so I paused for a breather and just read for awhile.

4:37 ddellacosta: callen: yeah, I think I'm at that point too. *sigh* Here we go...

4:38 callen: ddellacosta: ever work with SOA before?

4:38 ddellacosta: service composition, policies, etc?

4:38 ddellacosta: not in any deep way

4:38 callen: I've dabbled with the architecture in a few projects here and there, but nothing that really implemented it seriously. More like, "SOA-lite"

4:39 callen: ddellacosta: I've been meaning to do a tutorial on writing your own micro-SOA but I feel like nobody would read it because nobody really cares until they're forced to about that sort of thing.

4:39 ddellacosta: yeah I'm usually "SOA-lite" as well.

4:39 ddellacosta: callen: I think that is sad but true.

4:39 callen: ddellacosta: well it's not like most projects need it or anything.

4:39 we're engineers, not cathedral designers.

4:39 or architects, rather.

4:40 although if you ask a country with professional engineers, we're not engineers either.

4:40 so we're just here, futzing around with our code. :)

4:40 ddellacosta: hear about the smog in Singapore?

4:40 ddellacosta: callen: yeah, exactly, and after my early career I've actually grown more wary of architecture…

4:40 callen: no, although I've been to Singapore a good number of times in the past few years, didn't notice a *ton* of smog

4:41 callen: ddellacosta: it's a recent phenomenon, AQI of like 200+, hit a peak of 415 the other day.

4:41 ddellacosta: callen: on the other hand, I spent most the time indoors, as people in Singapore are wont to do

4:41 callen: ddellacosta: the agricultural field burning in Indonesia is practically killing Singapore.

4:41 ddellacosta: wooah, no *shit*

4:41 callen: yeah I think some records for worst AQI were set for SG in the last two weeks

4:41 terrifying stuff.

4:41 ddellacosta: ugh

4:42 callen: you know, now that you mention it, I recall seeing someone tweet about the smoke

4:42 callen: I had the same experience where exposure to architecture astronomy scared me off. I re-acclimated to an appreciation of the nicer parts after having to build a larger-than-I-was-used-to service backend

4:42 ddellacosta: made a scotch joke

4:42 callen: early exposure, specifically.

4:43 ddellacosta: callen: yeah, I think that it's about calibration…lots of developers (myself included) start off thinking they can build these big cathedrals, or even that that is worthwhile

4:43 then you realize you don't need it for most stuff, and actually it causes huge problems, and you scale back

4:43 then you start to realize when you can and can't use it. I'm between that 2nd and 3rd phase I think, still have lots to learn

4:44 alright, it's sunny, I'm going out for a change.

4:44 callen: ddellacosta: cheers.

4:44 ddellacosta: thanks again for the help. :-)

4:44 callen: ddellacosta: glad I could be useful. Enjoy your sunny weather. Ours has been great too.

4:44 ddellacosta: callen: thanks. :-)

4:45 callen: SegFaultAX: SF was beautiful yesterday. 80% of passersby were remarking upon it.

4:45 SegFaultAX: callen: Yes.

4:48 callen: SegFaultAX: how is pair-programming treating you?

4:49 SegFaultAX: callen: Good.

4:49 callen: SegFaultAX: well?

4:50 SegFaultAX: how are you handling the constant stimulus and lack of music?

4:51 SegFaultAX: Communication, mostly.

5:46 tomjack: http://www.insteadofawesome.com/

5:51 noonian: wizard!

9:20 jouiswalker: do monads solve any problems in clojure?

9:25 Bodil: jouiswalker: Yes, but considerably fewer than in Haskell.

9:27 jouiswalker: Bodil: thanks

9:38 Rogach: Q: I tried to use import-static like this: (require 'clojure.contrib.import-static) (import-static ...), but it gives me "Unable to resolve symbol: import-static in this context". Why is this happening?

9:38 hyPiRion: Rogach: do (require '[clojure.contrib.import-static :refer [import-static]]) instead

9:39 Otherwise you'd have to fully qualify the namespace each time you invoke a function from it (e.g. you'd have to do (clojure.contrib.import-static/import-static ...))

9:39 Rogach: hyPiRion: I tried (use ...), to the same effect.

9:40 hyPiRion: Rogach: okay, then the function name is possibly different

9:40 Rogach: Now I have another funny problem - one of the imported symbols collides with clojure.core/once :)

9:42 Ah, it doesn't collide, it is not surrounded with parentheses.

9:42 hyPiRion: Rogach: a word of advice though, clojure.contrib.* is not maintained anymore. As for import-static, it hasn't been moved over, but most other contrib libraries have

9:43 Rogach: hyPiRion: Hm. And why import-static hasn't moved?

9:43 hyPiRion: https://github.com/richhickey/clojure-contrib/blob/master/src/main/clojure/clojure/contrib/import_static.clj

9:43 Rogach: hyPiRion: It's too small to bother moving? ;)

9:43 hyPiRion: Because that's it: It's not really much to fix in that library :p

9:43 yeah

10:46 gfredericks: what is the expected behavior when a memoized function throws an exception?

10:49 in particular if I have (def g (memoize f)) where f throws an exception only on the first invocation, what should I expect g to do on the second invocation?

10:57 TimMc: Rogach: https://github.com/baznex/imports might be what you want.

10:59 hyPiRion: gfredericks: oh, hahah

10:59 gfredericks: http://dev.clojure.org/jira/browse/CLJ-1053

11:01 gfredericks: Well, it's not referentially transparent then, is it?

11:05 gfredericks: hyPiRion: what isn't?

11:06 hyPiRion: with clojure.core/memoize the second invocation of g calls f directly and returns the result

11:07 but I don't think this is the case with clojure.core.memoize/memo-ttl

11:07 the latter fact woke me up at 1am a couple nights ago

11:12 hyPiRion: gfredericks: f is not referentially transparent

11:15 gfredericks: hyPiRion: that's fine

11:15 hyPiRion: that's not fine for memoize

11:15 gfredericks: okay so you're saying the behavior is undefined for good reason?

11:16 clojurebot: same reason we don't wear animal skins or hunt the wooly mammoth. because we're not savages.

11:16 gfredericks: and I should use some other abstraction for what I'm doing?

11:22 hyPiRion: gfredericks: I'm not sure what you mean. Memoize should generally keep the exception and throw it every time you attempt call with the same parameters again

11:22 gfredericks: oh okay

11:22 so clojure.core/memoize is the bad one then

11:22 is core.cache a decent thing to use directly?

11:23 I want to cache the result of a failable thing such that failure causes it to retry the next time

11:24 pellis: hello

11:25 so i know there are a couple book authors here :), i'm wondering what kind of toolkit to use for self-publishing a clojure mini book (would be my first book)

11:32 Okasu: pellis: Latex and editor of choice.

11:33 pellis: was thinking more in the direction of asciidoc

11:40 Morgawr: can somebody provide me an example of cond-> and cond->>? I don't quite understand how they work

11:42 gfredericks: Morgawr: they're like -> and ->> but you add a boolean expression before each threading form, which can "turn it off" if it's false

11:42 ,(-> 3 (* 2) (inc))

11:42 clojurebot: 7

11:42 gfredericks: ,(cond-> 3 true (* 2) true (inc))

11:42 clojurebot: 7

11:42 gfredericks: ,(cond-> 3 true (* 2) false (inc))

11:42 clojurebot: 6

11:42 gfredericks: ,(cond-> 3 false (* 2) true (inc))

11:42 clojurebot: 4

11:42 Morgawr: okay so, as soon as it hits a "false" expression it returns?

11:42 pdk: so it lets you switch them off individually to control threading at runtime

11:42 gfredericks: Morgawr:

11:42 no

11:42 Morgawr: oh

11:42 gfredericks: it skips that one

11:42 pdk: it sounds like it simply skips all falses

11:42 Morgawr: oh okay, so it just skips

11:42 pdk: and continues on with the trues until the end

11:42 same for cond->> i imagine

11:43 gfredericks: yep

11:43 Morgawr: thanks, that's what I really wanted to know

11:43 :)

11:43 (inc gfredericks)

11:43 lazybot: ⇒ 25

11:43 pdk: that's a clever mecro

11:43 Morgawr: (inc pdk)

11:43 lazybot: ⇒ 1

11:43 pdk: macro

11:43 is it able to use a list or something to give it a series of boolean values

11:43 as opposed to threading them in piecemeal

11:44 or a generated seq for that matter

11:45 gfredericks: nope

11:45 I think the idea is instead of simple booleans you'll have more complex expressions

11:48 the macros aren't really meant for data-oriented algorithms

11:48 you could easily use reduce for that

11:51 Morgawr: gfredericks: do I need an :else in cond->/cond->>?

11:51 gfredericks: nope

11:51 you don't need an :else in cond either

11:52 Morgawr: well, as far as I know without a :else (or anything that self-evaluates as true, like any keyword) it will throw an uncaught type exception (or something like that) if no condition matches

11:52 gfredericks: ,(cond false :not-this)

11:52 clojurebot: nil

11:52 gfredericks: ,(cond)

11:52 clojurebot: nil

11:53 gfredericks: ,(case :foo :bar :not-this)

11:53 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching clause: :foo>

11:53 Morgawr: oh

11:53 ohhhh

11:53 I was confusing it with condp

11:53 condp will throw an exception

11:53 sorry

11:54 gfredericks: ,(condp = :foo :bar :baz)

11:54 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching clause: :foo>

11:54 gfredericks: ,(condp = :foo :foo :baz)

11:54 clojurebot: :baz

11:55 gfredericks: anyhow no you definitely don't need an else. Even if all your exprs are falsy you'll just get the threaded value back

11:55 I'll sometimes use cond-> with just one pair because it's a bit less repetetive than the if version

11:55 ,(cond-> 12 (pos? -4) inc)

11:55 clojurebot: 12

11:55 gfredericks: compared to ##(if (pos? -4) (inc 12) 12)

11:55 lazybot: ⇒ 12

11:56 pdk: it sounds like it only threads through trues

11:56 so if everything's false you just get out what you put in

11:56 gfredericks: yes that's the idea

11:56 Morgawr: cool

11:56 gfredericks: it also works nicely with ->

11:56 ,(-> 12 inc inc dec (cond-> false (* 23)) inc)

11:56 clojurebot: 14

11:57 gfredericks: I'll do that to add a condition to just one or two clauses

11:57 Morgawr: mmm.. weird, I'm using ClojureScript and it doesn't seem to be working with cond->

11:58 gfredericks: do you know for sure it's defined?

11:58 it's new in 1.5

11:58 Morgawr: in the clojurescript source I've seen it referenced with import-macros

11:58 and I'm using Clojure 1.5.1

11:59 gfredericks: I haven't used CLJS lately

11:59 don't have an easy way to try it out

11:59 himera doesn't have it

12:02 Morgawr: it's weird, it just says "cannot call undefined"

12:02 gfredericks: probably gets compiled to a runtime call to cond->

12:02 Morgawr: even in the repl when I do a simple (cond-> true true true) or whatever

12:03 gfredericks: cljs does not check that things exist I don't think

12:03 so if you call a nonexisting macro it just compiles it to a function call on an undefined thing

12:03 Morgawr: yes, probably

12:03 but the question is... why it's not there?

12:03 gfredericks: correct.

12:04 Morgawr: https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/core.clj#L56 it's clearly referenced here

12:10 maybe dnolen_ knows? :(

12:18 gfredericks: mm.. I just copy-pasted the cond-> definition from clojure into my own macros file and it seems to be working

12:26 tmciver: What's the preferred way of working with json in clojure these days?

12:27 Is it clojure.data.json?

12:35 Okasu: tmciver: Cheshire.

13:06 tmciver: Okasu: thanks.

13:09 luxbock: I installed Cygwin and I'm now using Emacs through it (emacs-w32)

13:10 I installed leiningen using the shell script, but now nrepl-jack-in doesn't work anymore

13:10 I get: /usr/bin/env: bash: No such file or directory

13:10 in my *nrepl-server* buffer

13:10 any ideas why this might be?

13:17 'lein repl' in the cygwin terminal works fine, but not when I call it from Emacs via M-x shell (which is set to use bash as well)

13:48 got it working, had to remove the #!/usr/bin/env bash part from the lein file

15:18 bbloom: dnolen_: it's really such a bummer that core.async has to copy paste so much code to support cljs :-/

15:18 i know that 100% cross plat is a NON-goal, but avoiding copy paste seems like it should at least be a goal

15:19 i hope this core.async effort spurs some progress there

15:26 tomjack: I think it is

15:27 spurring I mean

15:28 or maybe it's just a coincidence, but shared code is a priority for 1.6

15:35 bbloom: tomjack: i've heard ppl say that, but i dunno where the evidence or progress is :-)

15:36 besides some notes from stuart halloway on the design wiki, i guess that's the best there is

15:36 granted, async is on that list, so maybe it's partially accurate :-)

15:39 tomjack: oh nice, new asm as well

15:40 cinc coming soon? :)

15:52 OneFourSeven: Hey guys. I'm running lein uberjar to package my web application. But the problem is that I'm using a local jar that I've included by adding the :source-paths line to project.clj. This jar isn't included in the uberjar. Is there a way to package the jar with it?

16:07 Bronsa: tomjack: I'm working on CinC as my GSoC project

16:07 tomjack: sweet, didn't notice that one

16:08 are you moving to the new asm?

16:09 Bronsa: I don't see what would prevent me from using the lastest version

16:09 so, yes.

16:10 tomjack: exciting :) best of luck

16:10 Bronsa: thanks :)

16:11 bbloom: Bronsa: how's it going so far?

16:12 Bronsa: bbloom: I'm backporting the Compiler.java analysys phase in a clojurescript-ish style right now

16:13 by next week hopefully the basic analyzer should be done

16:14 next I'm going to write locals-clearings, constant inlining etc as optional additional passes over that clojurescript-ish AST

16:14 bbloom: Bronsa: cool!

16:15 Bronsa: right now I'm trying to come up with a sane way to analyze '.

16:15 the clojure Compiler is kinda derp about that :/

16:15 bbloom: Bronsa: the clojure (and clojurescript) compilers are derpy about a bunch of things :-P

16:16 Bronsa: i'd probably try a direct 1-to-1 syntax port at first & then refactor from there

16:16 trying to keep it working as i go

16:16 Bronsa: bbloom: right, that's somewhat what i did for tools.reader

16:17 I planned on taking the same approach with CinC but.. I decided I wanted to get rid of C.EVAL since the beginning

16:18 bbloom: i'm not super familiar w/ compiler.java, would have to study it

16:20 Bronsa: well, clojure right now has an interpreted eval for some ops

16:20 hiredman: Bronsa: how are you getting rid of C.EVAL? explicit statement/return things?

16:20 Bronsa: e.g. def

16:21 hiredman: oh, you mean the eval method on Exprs?

16:21 Bronsa: hiredman: I'm wrapping every top-level in a ((^:once fn* [] ..))

16:21 yeah.

16:21 hiredman: sure

16:21 bbloom: yea, i saw that at somepoint, but wasn't sure how much of it was still being used. seemed like it was largely vestigial

16:21 Bronsa: bbloom: when you eval (def foo 1) it's actually interpreted

16:22 hiredman: it is only used in the repl for some simple toplevel forms

16:22 bbloom: Bronsa: heh. what's that quote? "The top-level is hopeless"

16:24 tomjack: so will analysis be side-effect free?

16:25 bbloom: tomjack: i don't think it can be in the face of def

16:25 Bronsa: no, there's no way that can be done

16:25 hiredman: well

16:27 you can have a var environment that is ultimately backed by the real enviroment, but when you add vars they co in some kind of map, and analysis would come with a :vars {} map

16:28 Bronsa: sure

16:28 hiredman: which, uh, maybe clojurescript already does?

16:28 Bronsa: but then you have to put that map in an atom

16:28 bbloom: hiredman: no, clojurescript uses a global namespaces atom w/ swap!

16:28 Bronsa: and that's still.. side-effects

16:29 hiredman: Bronsa: no, you can push it down through the tree, I believe

16:29 bbloom: (when false (def x 1)) still defines x in clourescript....

16:29 hiredman: bbloom: well, but that doesn't have to happen as part of analysis

16:29 tomjack: I don't care if there are side-effects when my actual top-level clojure code is analyzed, I'd just like to be able to use the analyzer in macros

16:29 bbloom: yes: you can have env-in and env-out for every ast node

16:29 hiredman: right

16:30 Bronsa: hiredman: you'd have to pass to the next call to analyze the previously returned map?

16:30 hiredman: Bronsa: depends on what you are doing with the analysis results

16:31 bbloom: you can definitely make analysis pure, but there are other weird things that can happen in that case too

16:31 hiredman: for the compiler, you are compiling a toplevel form at a time, so analysis->compile->run for every top level form, so you will get the side effects

16:31 Bronsa: right

16:31 yeah, I suppose it would be trivial to make a side-effect free version to be used for static analysis of single forms

16:32 tomjack: cool. not that that's really important compared to the larger goal of CinC :)

16:32 bbloom: more important than side effect free is idempotent and deterministic :-)

16:33 like in cljs, the analyzer used to do gensym, so multiple calls w/ the same input produced differing results

16:33 i fixed that & was considering fixing the side effects for def, but decided it would only matter if you were doing speculative analysis and then not going to commit creation of those vars via compilation

16:36 jtoy: what is the best interface for clojure to store data, like a database

16:36 wei_: jtoy: edn?

16:36 does anyone have an example of using the :if :then :else construct in clojure.algo.monads? trying to figure out the syntax

16:36 bbloom: jtoy: need lots more info from you

16:37 jtoy: i want to program in pure clojure and not have to deal with creating tables, running sql to update the database,etc

16:37 finishingmove: what's this error?

16:37 Unable to resolve symbol: union in this context, compiling:(NO_SOURCE_PATH:11:1)

16:37 i just try to use the union function

16:37 first i thought something was wrong with my project setup, so i made a new one with lein new

16:38 arrdem: finishingmove: clojure.set/union?

16:38 finishingmove: but the error remains

16:38 bbloom: jtoy: do you need durability? do you need queries? how much data? what are your access patterns?

16:38 finishingmove: arrdem yes, thanks... i thought it was in core

16:39 arrdem: finishingmove: np

16:39 finishingmove: that's what IRC is for :P

16:39 bbloom: jtoy: "what type of vehicle is best?". -- "do you want to go to japan or to the grocery store?" …. "oh, you want to go the bottom of the ocean?"

16:40 arrdem: bbloom: bottom of the ocean pah. TO THE MOON!

16:40 jtoy: bbloom: i need durability so i can query later , the queries could be sql or something else, but i want a clojure interface, the db would be small,i like using sqlite but i hate with any sql i need to continuously alter tables as im buidling the code

16:41 bbloom: i am using korma on anohte project, it is nice, but still not easy enough

16:41 bbloom: jtoy: do you want easy or do you want simple? :-P

16:41 jtoy: simple

16:41 arrdem: jtoy: what kind of scale? single local db or do you need a real db?

16:41 jtoy: single local db

16:41 for now:)

16:41 SegFaultAX: I feel mongo coming on...

16:42 arrdem: SegFaultAX: nope

16:42 bbloom: how much data? a meg? 10? 100? 1,000?

16:42 SegFaultAX: arrdem: Thank you. :)

16:42 bbloom: SegFaultAX: mongo should never be coming on

16:42 arrdem: SegFaultAX: I can play nice :D

16:42 ohpauleez: haha

16:42 SegFaultAX: The questions were going all mongoy. I was afraid for a moment.

16:42 arrdem: SegFaultAX: I'm not blind to Mongo's failings, I just don't care abou tmost of them.

16:43 ibdnox's simpledb?

16:43 * arrdem ducks for cover

16:43 jtoy: to store my browser history, so title,url, and timestamp, it would grow at probably 1 meg a week

16:43 bbloom: jtoy: why not try a simple atom in memory, plus prn and clojure.edn/read

16:43 SegFaultAX: jtoy: Sounds like you need something webscale, then.

16:43 * SegFaultAX ducks

16:43 arrdem: jtoy: simpledb is probably right up your alley

16:43 SegFaultAX: gtfo :P

16:43 jtoy: it's an in memory atom that gets dumped to a file by a worker

16:44 bbloom: jtoy: you can write to /tmp/whatever then atomically file-move over the old version of your file

16:44 SegFaultAX: jtoy: Have you considered MangoDB?

16:44 arrdem: SegFaultAX: .......

16:44 ohpauleez: HA!

16:44 SegFaultAX: arrdem: https://github.com/dcramer/mangodb

16:44 jtoy: SegFaultAX: i tried it a few years ago, data loose

16:44 SegFaultAX: jtoy: I promise you, Mango is webscale.

16:44 arrdem: SegFaultAX: raw terminal on an abandoned server atm. will look later.

16:45 bbloom: you could also try the free/embedded datomic, if you don't mind closed source, but really, flyswatter vs bazooka

16:45 SegFaultAX: arrdem: You will appreciate it. :D

16:45 jtoy: I've used riak and postgresql for scaling

16:45 arrdem: SegFaultAX: I'm sure I will

16:45 bbloom: since when did people become afraid of file systems? :-P

16:45 SegFaultAX: arrdem: (Wrapper for /dev/null)

16:45 bbloom: don't they teach anybody fopen in school anymore!?

16:45 SegFaultAX: bbloom: Filesystems aren't webscale.

16:45 arrdem: bbloom: lol wut iz posix?

16:45 jtoy: bbloom: since coming to clojure i have, it is so much easier to deal with files in ruby/python

16:45 arrdem: SegFaultAX: ah so it's really nulldb

16:46 bbloom: jtoy: you need spit and slurp. how much easier does it get?

16:46 jtoy: bbloom: it is painful for me when i use files in clojure, probably bc im still new

16:46 bbloom: (doc spit)

16:46 clojurebot: "([f content & options]); Opposite of slurp. Opens f with writer, writes content, then closes f. Options passed to clojure.java.io/writer."

16:46 bbloom: (doc slurp)

16:46 clojurebot: "([f & opts]); Opens a reader on f and reads all its contents, returning a string. See clojure.java.io/reader for a complete list of supported arguments."

16:46 SegFaultAX: The file interface designed by my x-wife.

16:46 bbloom: when you outgrow split & slurp, you can A) learn how to use the file APIs better or B) choose a bigger solution

16:46 * SegFaultAX lets himself out

16:46 jtoy: bbloom: using doseq, doall, do*, and lazy data, resource files vs io ,etc

16:47 arrdem: (dec SegFaultAX)

16:47 lazybot: ⇒ 1

16:47 bbloom: jtoy: don't bother with lazy io

16:47 SegFaultAX: arrdem: Learn to laugh, yo.

16:47 jtoy: bbloom: I have to because I am processing "bigdata" often

16:47 bbloom: jtoy: with your browser history?

16:47 arrdem: SegFaultAX: your inuendo is bad and you should feel bad

16:47 * arrdem can't spell

16:47 SegFaultAX: arrdem: I let myself out, didn't I?

16:47 jtoy: bbloom: no with my projects

16:47 bbloom: jtoy: ok, well for *this* project: forget lazy IO :-P

16:47 arrdem: wait. shit. copying a running mongo file ain't gonna work.

16:47 SegFaultAX: arrdem: Unfortunately for you I have IRC on my phone. So there.

16:48 jtoy: bbloom: haha, I will

16:48 arrdem: SegFaultAX: Q_Q irssinotify is the bomb

16:48 bbloom: i know startups who spend 73895783573 hours doing shit that could be solved w/ spit and slurp and would scale better than whatever nonsense they came up with :-P

16:48 jtoy: arrdem: that db has no examples, hard to tell

16:48 SegFaultAX: arrdem: I <3 irssi+znc

16:48 bbloom: hell, hacker news basically runs on the spit/slurp model with binary encoding

16:49 arrdem: jtoy: chris's noir demo blog uses it

16:49 jtoy: I swear that's how it works 'cause I ported that blog from simpledb to mongo for lulz one time

16:49 SegFaultAX: bbloom: Yea, but arc.

16:49 jtoy: ruby has a library called datamapper that will read in an sql definition and auto migrate the tables so you dont have to deal with manually updating the db

16:49 arrdem: jtoy: it's really just spit and slurp in a library.

16:50 * arrdem did not realize how many git repos he had on his server

16:51 jtoy: arrdem: where is the blog post about simpledb?

16:52 SegFaultAX: $google chris granger simpledb

16:52 lazybot: [Commit History · ibdknox/simpledb · GitHub] https://github.com/ibdknox/simpledb/commits/

16:52 arrdem: jtoy: just read the sauce. it's 52 lines and I'm on my phone

16:52 jtoy: i saw that, didnt explain anything about what it is

16:53 ill just use koram for now then

16:53 korma

16:53 SegFaultAX: jtoy: It's brief, read harder.

16:53 arrdem: (inc SegFaultAX)

16:53 lazybot: ⇒ 2

16:53 SegFaultAX: (inc arrdem)

16:53 lazybot: ⇒ 5

16:53 arrdem: welcome to clojure, where the source is probably the only docs.

16:53 but that's ok 'cause the source is readable :D

16:54 SegFaultAX: Didn't Holloway once say that the ratio from psuedocode to production code should be 1:1?

16:54 Clojure is often pretty damn close.

16:54 jtoy: i dont mind reading source

16:54 arrdem: SegFaultAX: could be. I'm still trying to pseudocode in python because interviewers look at me weird when I start writing lisp

16:55 jtoy: it's really just all the clojure.core maps functions wrapping a defonce'd atom

16:55 tomjack: also, it seems hard to write clojure on a whiteboard :(

16:55 bbloom: arrdem: fuck 'em, i pseudo code in whatever formalism i make up at the moment

16:55 SegFaultAX: arrdem: Most of the time I'll code in whatever the primary domain language is. When I use lisp, they think I'm a wizard.

16:55 amalloy: tomjack: no harder than it is to write it in notepad :P

16:55 arrdem: SegFaultAX: bust out some macros on that bitch and make 'em figure it out :D

16:56 tomjack: yes, harder, I claim

16:56 finishingmove: I'm trying to solve the first euler problem, and I get a weird result

16:56 tomjack: because you can't move text around, you may have to erase large sections and start over

16:56 finishingmove: ,(reduce (partial +) 0 (clojure.set/union (range 3 1000 3) (range 5 1000 5))))

16:56 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set>

16:56 arrdem: jtoy: the init() just kicks off a worker thread that dumps the atom to the db as the clojure prn render

16:56 for "db" being defined as "./sdb.db"

16:56 SegFaultAX: finishingmove: Whoa, inefficient much?

16:56 finishingmove: gives me 266333

16:57 instead of 233168

16:57 arrdem: jtoy: so you just put! and get, for some implicitly defined record structure which you create.

16:58 finishingmove: SegFaultAX isn't the point of high-level programming to write code that is easier to reason about rather than being more efficient?

16:59 SegFaultAX: finishingmove: Um, no?

16:59 Cr8: no reason you can't have both

16:59 finishingmove: anyway, what's wrong with my function? why is it not giving the expected result?

16:59 Cr8, sure, if there's a more efficient solution, I'd like to know about it

16:59 arrdem: finishingmove: only if you are willing to live with a shitty compiler....

16:59 ok gents, say goodby to this host. catch yall later.

17:01 amalloy: finishingmove: well, math. math is the more efficient way. you can easily enough derive a simple formula with just a couple multiplications, divisions, and additions, for the "fizzbuzz sum" up to any N you want

17:01 finishingmove: SegFaultAX do you have a more efficient solution?

17:01 what's so bad about my approach?

17:01 SegFaultAX: finishingmove: Well first of all, you're duplicating a shitload of work.

17:02 finishingmove: Don't worry about the summing part, that's trivial.

17:02 finishingmove: How can we efficiently find all the numbers between 1 and N that are divisible by 2 co-primes A and B?

17:03 finishingmove: Assume this constraint, you can iterate through the numbers 1 to N at most a SINGLE time.

17:03 finishingmove: i don't want to iterate at all

17:03 anyway, can u explain what you mean about duplicate work in my function?

17:03 how does it execute?

17:04 i see it as a simple 1-2-3-4-5 done

17:04 SegFaultAX: finishingmove: If you read what I just said, you might gain some insight.

17:04 finishingmove: i have, and i haven't

17:04 :s

17:04 how about being more concrete?

17:05 i believe you, but i don't see the problem

17:05 n_b: finishingmove: What's faster, counting out everything from 3,6...999, or finding the total via the formula for an arithmetic progression?

17:05 tomjack: clearly the former?

17:06 SegFaultAX: tomjack: Let finishingmove work it out.

17:06 finishingmove: i wouldn't think it's slower at all

17:06 maybe less memory efficient

17:06 tomjack: maybe you're much faster at algebra, but I can do very little algebra in the time it would take to count everything out

17:08 oh, I misread :)

17:08 SegFaultAX: tomjack: What?

17:08 n_b: I should've said, counting and summing

17:08 tomjack: I read "finding the formula.."

17:08 SegFaultAX: n_b: I think your meaning was clear anyway, given the context.

17:09 finishingmove: So what do we need to see if any number in our range fits the criteria?

17:11 finishingmove: haven't given it thought yet

17:13 SegFaultAX: finishingmove: Write a function that given some number n, returns true if and only if it is divisible by 3 or 5 (or both)

17:21 n_b: Trying to figure out the fast way of doing this in clojure

17:22 my solution seems way slower than it should be

17:23 SegFaultAX: n_b: What's your solution?

17:23 n_b: (reduce + (for [i (range 0 1000) :when (or (= 0 (mod i 5)))] i))

17:23 amalloy: SegFaultAX: introducing division isn't going to speed things up :P

17:24 SegFaultAX: amalloy: Over the original approach? How do you figure?

17:25 n_b: The simplest way is just the sum of divisors of 3 and 5 minus divisors of 15 I think?

17:26 amalloy: maybe a little, i guess? but i'm not sure why you're leading him down this path instead of just adding and subtracting a few arithmetic series

17:26 SegFaultAX: amalloy: Actually let me take that back, I don't know enough about the performance characteristics of hashsets to tell offhand if it will be slower or faster.

17:27 amalloy: SegFaultAX: you're probably right: i was thinking more about the allocation costs of the lazy-seqs, which isn't as large as you'd guess; but hashsets will need to do division anyway

17:27 n_b: The traditional solution is probably ```java int acc=0; for(int i=0; i<1000; i++) { if (i % 3 == 0 or i % 5 ==0) { acc+=i }};```

17:28 SegFaultAX: amalloy: Oh hmm, you bring up and excellent point, though.

17:28 amalloy: n_b: for a laugh re the traditional solution, you might enjoy http://dave.fayr.am/posts/2012-10-4-finding-fizzbuzz.html

17:29 gozala: can anyone please help me understand why does (let [x :let] (def x :def) x) evaluates to :let

17:29 rather than :def ?

17:30 bbloom: ,`(let [x :let] (def x :def) x)

17:30 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

17:30 finishingmove: ,(reduce (fn [x y]

17:30 (if (or (= (mod y 3) 0) (= (mod y 5) 0))

17:30 (+ x y)

17:30 x)) 0 (range 1 1000))

17:30 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

17:30 finishingmove: how is that ^ different to

17:30 (reduce + 0 (clojure.set/union (range 3 1000 3) (range 5 1000 5)))

17:30 ?

17:31 it gives different result (former is correct)

17:31 gozala: it seems to define x in the top scope rather than with in the let context

17:31 SegFaultAX: ,(time (let [sum (partial reduce +)] (+ (sum (range 3 1000 3)) (sum (range 5 1000 5)) (- (sum (range 15 1000 15))))))

17:31 clojurebot: "Elapsed time: 2.922747 msecs"\n233168

17:32 schmir: gozala: def creates a global var. read (doc def).

17:32 SegFaultAX: amalloy: I guess that's pretty low on a warmed jvm. 0.2ms

17:32 amalloy: I haven't compared it to the hashset version yet though.

17:32 amalloy: SegFaultAX: well, yeah, but why call (range) at all?

17:32 just look up the formula for summing an arithmetic series

17:32 SegFaultAX: amalloy: Fewer keystrokes.

17:33 bbloom: gozala: what schmir says is correct, but to answer the question anyway: x is resolved when that expression is compiled. during compilation, def hasn't run yet, so there is no x var to resolve against

17:33 gozala: that is, def has the side effect of creating a global called x. however, that's some.namespace/x instead of the 'x that is in the local context

17:33 SegFaultAX: amalloy: Oh well that wasn't the original problem we were discussing.

17:34 llasram: finishingmove: your `union`-based implementation has the effect of replacing `or` with `and` in the other implementation

17:34 SegFaultAX: amalloy: We were specifically not talking about the closed form solution, if that's what you mean.

17:34 gozala: bbloom: schmir thanks

17:34 finishingmove: llasram, shouldn't that be intersection?

17:34 gozala: trying to make up my mind what js should it compile to

17:34 amalloy: i didn't notice anyone stating that constraint

17:35 SegFaultAX: amalloy: Eh, I was addressing the set thing.

17:35 n_b: amalloy: That article is great; think I'll be stealing it for an Intro to FP presentation I'm doing next week. Cheers!

17:35 llasram: finishingmove: Oh, you're right. Brain not at full speed, apparently

17:36 SegFaultAX: Food time, bbl.

17:36 finishingmove: the union solution gives a higher number actually

17:42 Cr8: here's a weird one

17:42 ,(apply + (distinct (concat (range 3 1000 3) (range 5 1000 5))))

17:42 clojurebot: 233168

17:42 n_b: ,(clojure.set/union (range 0 20 3) (range 0 20 5))

17:42 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set>

17:42 Cr8: why is (distinct (concat c1 c2)) behaving differently from (union c1 c2) ?

17:43 finishingmove: I'd like to know too

17:43 llasram: Even better: &[(count (clojure.set/union (range 3 1000 3) (range 5 1000 5))) (count (clojure.set/union (set (range 3 1000 3)) (set (range 5 1000 5))))]

17:43 Er,

17:43 &[(count (clojure.set/union (range 3 1000 3) (range 5 1000 5))) (count (clojure.set/union (set (range 3 1000 3)) (set (range 5 1000 5))))]

17:43 lazybot: ⇒ [532 466]

17:44 Cr8: AH

17:44 Got it!

17:44 clojure.set/union *expects to be given sets*

17:44 n_b: yup

17:44 Cr8: as it's just (reduce conj <smaller set> <larger set>) when given two sets

17:44 llasram: And definitely does the wrong thing when given non-sets

17:44 Cr8: with two vectors you are just catting the larger one onto the smaller one

17:44 n_b: This is where core.typed would help :p

17:44 Cr8: or lists, catting in reverse

17:45 finishingmove: this is where haskell would have helped

17:45 :D

17:47 Cr8: except I had larger/smaller backwards for all of that

17:49 finishingmove: i still don't see how this:

17:49 (defn problem'

17:49 []

17:49 (reduce (fn [x y]

17:49 (if (or (= (mod y 3) 0) (= (mod y 5) 0))

17:49 (+ x y)

17:49 x)) 0 (range 1 1000)))

17:49 could be faster than

17:49 (defn problem

17:49 []

17:49 (reduce + 0 (distinct (concat (range 3 1000 3) (range 5 1000 5)))))

17:49 amalloy: finishingmove: please stop pasting large programs here

17:49 ~paste

17:49 finishingmove: never have, amalloy

17:49 clojurebot: paste is not gist.github.com

17:49 amalloy: $google refheap

17:49 lazybot: [Refheap - The pastebin for your, you know, pastes] https://www.refheap.com/

17:49 finishingmove: and these are not large programs, my dear clojurebot

17:49 s-h: ,(reduce + (filter #(or (= (mod % 3) 0) (= (mod % 5) 0)) (range 1 1000)))

17:49 clojurebot: 233168

17:49 n_b: I don't see how you could see the former *not* be faster than the latter

17:50 amalloy: s/large/multi-line

17:50 llasram: finishingmove: in this channel's etiquette, anything larger than one line is "large"

17:50 n_b: it's doing more work, plain and simple.

17:50 finishingmove: the first one generates a list of all numbers from 1 to 1000

17:51 the other one generates 2 lists with only a portion of numbers

17:51 and the total of the two is less than 1000

17:51 llasram: finishingmove: And IMHO is less about actual size, than just line breaks. Put your admittedly-small programs on one line, and your fine

17:52 finishingmove: i got the memo

17:52 amalloy: finishingmove: putting things into sets is not free. they have to build a data structure that supports conj/disj/contains? operations quickly

17:52 Cr8: finishingmove: it's easier to see the difference if you go higher than 1000

17:52 https://www.refheap.com/16020

17:54 fbernier: so... what's the difference between a mutex and a clojure "dosync" ?

17:55 finishingmove: interesting, Cr8

17:55 bbloom: fbernier: a lot. go read about dosync and "software transactional memory"

17:55 fbernier: but if you're new to clojure, you can basically just ignore dosync… it's pretty rare in most clojure code these days

17:56 devn: ignore that! :)

17:56 look into refs, build a simple in-memory db with them

17:56 it's fun

17:56 fbernier: bbloom: Ok thanks ... I am new to clojure but will be giving a presentation about it soon.

17:56 looking for cool examples to show off

17:57 devn: fbernier: i have one for you

17:57 hyPiRion: fbernier: so with mutexes you may deadlock, but that's impossible with STMs (dosync blocks)

17:57 devn: fbernier: https://github.com/Licenser/stupiddb

17:57 fbernier: that's an old project, but a fun one

17:57 bbloom: fbernier: clojure's concurrency primitives are only one of many interesting things in clojure. however, most would agree with me when i say that immutable/persistent data structures are of far deeper importance and are a prerequisite in understanding

17:58 llasram: +1. I have yet to need dosync or the STM to solve a real problem

17:59 fbernier: bbloom: Alright, I'll look into that and see how I can explain it easily.

17:59 llasram: But persistent data structures fundamentally change how you approach problems

17:59 devn: what about an agent llasram? an atom?

17:59 bbloom: fbernier: http://www.infoq.com/author/Rich-Hickey is the place to start if you like videos

18:00 devn: ^-watch Are We There Yet

18:00 bpr: ^ this

18:00 bbloom: yup, then "simple made easy"

18:00 Cr8: Atoms are quite useful

18:00 devn: my brain was like this: http://slackwise.net/files/images/Tim%20and%20Eric%20-%20Space%20Explosions.gif

18:00 llasram: devn: Sure, but those are different. Agents can participate in STM transactions, but STM isn't fundamental to them. Atoms have nothing to do with either the STM or dosync

18:00 Cr8: agents I don't think I've really used "correctly"

18:01 bpr: imo, rich's "simple made easy" has a larger impact if you watch Stu Halloway's talk about that topic first (iirc it was delivered in the first conj)

18:01 http://www.youtube.com/watch?v=cidchWg74Y4

18:01 devn: llasram: meh, datomic uses refs from what i understand

18:01 and that is certainly real world

18:01 llasram: devn: Hmm, I thought I read that the in-memory state is all just in an atom

18:02 devn: i might have that wrong

18:02 fbernier: thanks for the infos everyone

18:02 devn: you're probably right

18:02 llasram: devn: But I was specifically talking about my own production Clojure code. I wrote Clojure every day, and never used a ref

18:02 s,wrote,write,

18:02 finishingmove: i did "lein repl" in my project folder, but how do i call functions from my namespace?

18:02 devn: i wrote refs and then was like: oh, i could write this a different way

18:02 tomjack: I'd be surprised if datomic didn't use refs

18:02 devn: slowly unlearning my imperative BS

18:03 tomjack: they say you should have multiple transactions in flight for best performance

18:03 devn: ^-that

18:03 tomjack: which suggests refs underneath to me (though I too have never actually used them)

18:03 llasram: finishingmove: `require`, then probably `in-ns`

18:03 finishingmove: thanks

18:03 hyPiRion: finishingmove: (require '[my.namespace :as my]) then (my/function args)

18:03 finishingmove: ty!

18:04 devn: anyone here in SF?

18:04 bbloom: dnolen_: is refer-clojure not supported in cljs?

18:04 tomjack: I'm in berkeley, looking for a place in SF now

18:04 bbloom: dnolen_: the assert string says it is, but the code seems to strip it out

18:06 tomjack: or maybe pods replace refs in datomic's internals?

18:06 devn: my guess is: unlikely

18:06 but that'd be fun if it were true

18:06 tomjack: there are definitely some things called 'pod' in there

18:06 devn: tomjack: oh yeah?

18:07 tomjack: (but I don't actually know wtf pods really are, so..)

18:07 e.g. the log tail is a 'tail-pod'

18:07 devn: heh

18:08 bbloom: tomjack: http://dev.clojure.org/display/design/Mutex+references+%28pods%2C+nee+cells%29

18:08 devn: this is old chat

18:08 bbloom: tomjack: plus lots of irc discussion that was hard to find

18:09 devn: yeah we were talking about pods maybe 6months before the first conj

18:09 tomjack: I saw the talk about them but it seemed like it still was unclear what they should be exactly

18:09 devn: it's like transients

18:10 except it ensures the thread who created it is the the thread that changes it

18:10 the policy of who can change it is the ref type

18:10 that's my dumb understanding

18:10 tomjack: &(let [t (transient [])] @(future (conj! t :foo)))

18:10 lazybot: java.lang.SecurityException: You tripped the alarm! future-call is bad!

18:11 tomjack: oya

18:11 bpr: fbernier: this is one of my fav clojure-specific talks of rich's http://www.youtube.com/watch?v=dGVqrGmwOAw

18:11 just fyi

18:11 fbernier: thanks

18:12 devn: fbernier: seriously though, and yes, im going to be pushy: watch "Are we there yet?"

18:12 it's the original talk. it's THE talk

18:13 bpr: yes, that will change how you think about concurrent programming.

18:13 fbernier: I will surely watch it, but should I absolutely watch it before my talk on tuesday which should be an introduction to clojure?

18:13 I don't have much time to gather the best info I can ...

18:14 bbloom: fbernier: you're given a talk on a subject you don't know anything about? :-P

18:14 fbernier: I do know about basics ...

18:14 mdeboard: Simple Made Easy is another good talk. My fave talk actually

18:14 fbernier, I gave a talk on Clojure to a local Scala meetup, I'm a super beginner too. Don't sweat it.

18:15 I based my talk on Simple Made Easy, actually.

18:15 fbernier: it'll be an informal talk at a local event

18:15 bpr: fbernier: is your talk intended to be a first introduction to clojure, or is it more about the deeper rationale behind the design choices Rich made when creating the language?

18:15 devn: tomjack: http://www.infoq.com/interviews/hickey-clojure-reader

18:16 mdeboard: Yeah, that's how mine was too. bbloom signing up to give a talk on a subject you're not well-versed in is a great way to get well versed :)

18:16 fbernier: bpr: first introduction for sure

18:16 most will not be familiar with lisp

18:16 it's a web crowd

18:16 devn: tomjack: his response to the question about pods has this line in it: "Datomic has informed my thinking about pods and probably will enable me to complete them."

18:18 tomjack: cool, didn't notice that when I watched that interview before

18:18 bbloom: mdeboard: yeah, but if you only have a few days to prepare, you're unlikely to become well versed enough to speak about it intelligently. the audience has to sit through your ramblings…. they came to see YOU….

18:18 jtoy: anyone here use ring? how am i supposed to reload the server after i change it? right now i have to kill the repl for every change

18:18 mdeboard: bbloom, Oh, didn't know it was short-fuse like that :)

18:19 llasram: jtoy: Provide the vars holding your handlers as the handler functions to whatever server you're using. Reader macro: #'my-ring-handler

18:19 bpr: fbernier: http://bit.ly/11FVEN5

18:20 llasram: jtoy: When you make a change and reload the namespace, the function referenced by the var changes, and the server calls the new function

18:20 bpr: fbernier: I haven't watched all the videos on that list, but it seems like a good model for you. It seems like it's aimed at a similar audience and has similar goals

18:21 fbernier: bpr: cool thanks

18:21 bpr: np

18:21 jtoy: llasram: ok, ill try that

18:23 llasram: good example here: https://github.com/mmcgrana/ring/issues/72

18:26 arohner: can someone remind me why take-while says the function should be pure?

18:27 I have a list containing a bunch of numbers, and I want to take items off the list while the sum of the items is < N

18:27 jtoy: hmm, i cant get it to work though

18:28 tomjack: arohner: interesting!

18:28 llasram: arohner: Because it just makes no guarantees about when your predicate will be called

18:29 That particular problem is pretty easy to lazy-seq up directly though

18:29 arohner: reading the source, it seems like closing over an atom will work

18:30 fsmunoz: what0s the cleanest way in Clojure to do (setq foo (or some-value some-other-value))?

18:30 llasram: jtoy: It does in general. Code gist-able?

18:30 jtoy: llasram: im testing more

18:32 llasram: https://www.refheap.com/16022

18:34 llasram: arohner: But would be poor style! Everyone would frown at you, distressed and saddened

18:35 arohner: llasram: is there a better abstraction?

18:35 Cr8: arohner: https://www.refheap.com/16023

18:35 arohner: Cr8: oh, very nice

18:35 tomjack: :/

18:36 arohner: ?

18:37 amalloy: Cr8, arohner: why define take-while-reduce at all? just use reductions+take-while

18:37 tomjack: https://www.refheap.com/861a6a77c9f571804e7b06f38

18:37 I do still feel unsatisfied

18:38 Cr8: amalloy: well, he wanted the original list's items

18:38 you could zip the reductions and the original list together I suppose

18:38 then unzip

18:38 arohner: yeah, but that's annoying

18:38 amalloy: (map (fn [a b] a) xs (reductions ... xs))

18:39 but, sure, it's not a ton of fun at that point

18:39 Cr8: then wrap the (reductions) part with the take-while

18:40 tomjack: oh, good idea https://www.refheap.com/a2e63743cb5dc99ff046ec31c

18:40 my gut says Data.Lens has a much more beautiful solution

18:40 llasram: jtoy: Oh! You still need some way of reloadig the namespaces. Something standard provides a `wrap-reload` which will reload files which change. I myself just launch the server from an editor-connected REPL and reload namespaces like for any other Clojure work

18:40 tomjack: and I wish we could do this with reducers

18:41 devn: anyone here ever use jode?

18:41 Cr8: ,(let [xs (range 10)] (map (fn [a b] a) xs (take-while #(< % 10) (reductions + 0 xs))))

18:41 clojurebot: (0 1 2 3 4)

18:41 devn: (and are willing to admit it?)

18:41 llasram: tomjack: I wrote a `reductions` implementation for reducers, but it languishes in Jira

18:41 devn: llasram: it took me 1.5 years to get my patch on range in

18:41 don't fret

18:41 tomjack: I wrote one too but that is still unsatisfying

18:42 llasram: What would you wish instead?

18:42 dobry-den: Why is `doto` used here instead of the `->` macro? (let [mac (doto (Mac/getInstance hmac-sha1) (.init signing-key))] …)

18:42 seen here: https://github.com/mattrepl/clj-oauth/blob/master/src/oauth/digest.clj#L10

18:43 tomjack: I don't want to have to make a reducer of [reduction elem] and then project

18:43 feels like it should be fused away somehow

18:43 llasram: dobry-den: `doto` returns the result of evaluating it's first form-argument, while `->` returns the last

18:43 bpr: dobry-den: prob, b/c .init returns nil (or something other than the mac object)

18:44 tomjack: actually I don't even see how to do it with reductions

18:44 dobry-den: llasram: ahh, clojure has gotten me to completely forget about mutation.

18:44 also reminds me of how funny java apis are

18:45 bpr: dobry-den: lol, yes. I once had to wrangle BouncyCastle... it was painful

18:46 dobry-den: bpr: oh man, yeah that's actually my first experience using a java api.

18:47 bpr: wow. that musta been intense

18:48 arohner: amalloy tomjack: I learned something today, thanks

18:48 dobry-den: i dont understand how people are productive with it. there's a magical order in which you apply methods like .init() and .doFinal() and .update() yet the docs never answer simple questions like "how do you go from a string to sha512 hex hash?

18:48 bpr: although, with class names like DefaultSignatureAlgorithmIdentifierFinder and BcRSAContentVerifierProviderBuilder, it wasn't without it's humor

18:49 dobry-den: haha. i actually gave up trying to figure out how to implement elliptical curve signing

18:49 bpr: dobry-den: for real

18:49 its*

18:50 tomjack: s/Data.Lens/Control.Lens/

18:52 dobry-den: bpr: i did learn about Apache Commons, though. for instance: http://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/digest/DigestUtils.html

18:52 bpr: dobry-den: yeah, we looked at that. It wasn't sufficient for all our needs... i forget why

18:55 dobry-den: with simple methods like sha512Hex("secret") => hex hash, i have to wonder how unidiomatic it is in the java ecosystem

18:56 not enough object collaboration

18:57 sorry, the topic opened up old wounds. 'doto' is great

18:57 bpr: let me just say: clojure does java better than java :-p

18:58 Raynes: dobry-den: It should definitely return a HexHashFactorySingletonHashMaker

18:59 amalloy: dobry-den: you don't know true Java Zen until you write a single expression with two `doto` and three `->`

19:00 hyPiRion: Raynes: I thought it would return IPersistentHashMapMessageStrategyDefinitionIterableTest

19:00 * Raynes places his hands together palm to palm and nods his head.

19:01 amalloy: huh. apparently i gisted https://gist.github.com/amalloy/fd3fda4c707802740874

19:01 i wonder why

19:02 i bet Raynes was trying to bully me into using refheap instead of gist

19:02 dobry-den: every crypto lib starts like this: SomeCryptoClass.getInstance(KeyMaker.getInstance("secret", "Sha512"), SomeCryptoClass.getAlgorithm("SunSha512"))

19:03 to see the available magic strings you can get algorithms for, you do SomeCryptoClass.getProviders() and they aren't enumerating in the docs. so it leads me to wonder if the available algorithms change over time even if you don't update your crpto lib version. that's the only explanation i can think of

19:04 enumerated*

19:04 gfredericks: dobry-den: it sounds like idiomatic java design to me :P

19:04 they have obviously attained maximum flexibility

19:05 llasram: I think it's an artifact of the old US crypto export laws

19:05 dobry-den: it's just a stone's throw from (do-something "(+ 1 2)")

19:05 llasram: SHA-2 is a munition etc

19:05 bbloom: is there a way to make cljsbuild completely override the source-paths? I don't want my src/clj directory on the path at all when building src/cljs

19:05 amalloy: llasram: probably not; i think it's just DI gone mad

19:06 tomjack: bbloom: and you are going to produce two separate jars somehow?

19:06 llasram: amalloy: That might be the simpler explanation

19:06 bbloom: tomjack: *shrug* i dunno. my issue is that i'm not writing a clojure.core.foo or cljs.core.foo namespace. i have myapp.foo in both clj and cljs, so when looking for macros, i'm getting the clj version from cljs

19:06 tomjack: my conclusion was that you have to either have separate projects or different namespace names (e.g. cljs.core.async), if I understand the situation you're in

19:07 bbloom: yeah that's precisely the situtation i'm in

19:07 tomjack: ..until 1.6, I guess :)

19:07 bbloom: blargh. can't come fast enough :-P

19:07 i have like 375 things i'm putting off until clj/cljs cooperate better

19:08 * gfredericks likes imagining that most of bbloom's 375 things have nothing to do with programming

19:08 bbloom: gfredericks: 370 of them are happy dance moves

19:08 llasram: I'm going to imagine that he's doing them in a parallel world with 10 extra days per year, and he does one per day

19:09 gfredericks: let's all say our favorite thing to imagine about bbloom's list

19:09 tomjack: having separate projects would force separate projects on consumers who want both, it seems

19:09 so I guess an ugly workaround could be myapp.cljs.core for now :(

19:10 or core.async could maybe have gotten away with using the same namespace since it puts macros in a special cljs.core.async.macros ns anyway?

19:10 bbloom: tomjack: yeah, i guess that's gotta be the case. i don't want to make two separate projects, since i expect a clj server to talk to a cljs client. i guess i can just version them together...

19:12 tomjack: I asked about the 'take while cumulative sum' in #haskell-lens, turns out it's not lensy and the solution proposed (in non-lens haskell) was exactly the same as the solution we came up with

19:12 bbloom: maybe i'll just make two different git branches…. :-P

19:12 tomjack: actually our solution is ostensibly nicer

19:18 bbloom: still going to fuck consumers, eh?

19:18 I guess if you have no consumers it's ok

19:18 bbloom: lol

19:18 *shrug* you'll just need two deps

19:18 no big deal

19:18 tomjack: but won't they conflict?

19:19 bbloom: they will have different names

19:19 foo and foo-cljs

19:19 tomjack: but the namespaces?

19:19 bbloom: oh right. *sigh*

19:20 the git branches are nice tho… i can use git's rename detection to ease the porting of changes :-P

19:23 *shrug* consumers will just need to make two projects too lol

19:23 priority 1 is the port, will worry about that stuff later…

19:24 tomjack: yeah, oh well

19:25 glad to see an Executor protocol drafted in core.async

19:26 bblöom: maybe you'll be able to swap out setTimeout for your queue thingy

19:29 bbloom: tomjack: where is that protocol drafted?

19:29 tomjack: in the forkjoin branch

19:30 looks like they make a choice of executor for you though

19:49 francis_wolke: What are some good resources to learn how to correctly walk trees?

19:52 I realize that clojure.walk exists - but I'm not 'getting it' when it comes to dealing with trees - EG: the algorithms arn't jumping to mind and I think I may need to read some research papers/textbooks/articles

19:53 bbloom: francis_wolke: i've found that clojure.walk isn't super useful beyond trivial use cases

19:54 francis_wolke: start with just a really simple recursive walk

19:56 francis_wolke: bbloom - That's actually what I'm having the issue with - as the tree branches I'm not 'seeing' how my program can continue to walk down the tree. I realize that this is n00b stuff, but I've never had to do it before. :/

19:57 bbloom: francis_wolke: ah ok. well there are two general approaches to two types of traversals

19:58 there is iterative & recursive, then there is breadth vs first depth first

19:58 recursive and depth first is the easiest, so start with that

19:58 here's a good comparison of iterative solutions for depth vs breadth: http://stackoverflow.com/questions/687731/breadth-first-vs-depth-first

19:58 so you understand how they are related fundamentally :-)

19:58 cbp`: clojure.zip has functions to walk nested structures

19:59 bbloom: cbp`: let's not bring zip into this. he needs some practice with the fundamentals, he said

19:59 zippers would dramatically complicate things at this stage of his learning

19:59 francis_wolke: bbloom: k. Thanks.

20:00 bbloom: francis_wolke: the wikipedia pages have good pseudo code for all 4 possible approaches

20:00 start here: http://en.wikipedia.org/wiki/Depth-first_search

20:00 don't try to be general or anything yet. just manually traverse over whatever particular structure you're trying to work with

20:03 francis_wolke: oh actually, i showed you search. sorry. start here: http://en.wikipedia.org/wiki/Tree_traversal

20:41 tomjack: what's the point of IEnforceableConstraint?

20:41 I can understand why it's there for domc

20:41 but not the rest

20:50 callen: apparently my battery was just miscalibrated, been running at 0% for like 20min

20:53 tomjack`: there it goes :(

20:54 francis_wolke: bbloom: thanks for the pointers, they set me off in the correct direction.

23:25 clizzin: hey all, i'm looking to set up an api service that will be an oauth2 provider. what's the state of the art out there in terms of clojure libs for oauth2 providers? i found https://github.com/pelle/clauth but it looks quite old.

23:34 navgeet: https://github.com/cemerick/friend ?

Logging service provided by n01se.net