#clojure log - Jan 09 2013

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

0:21 bbloom: are there any good generators/streams/haskell-iteratees libraries for clj? i'm looking at https://github.com/roman/river but i'm wondering if there are others. i've got an algorithm that could really benefit from a yield operator

0:23 tomoj: is 'yield operator' pretty specific?

0:24 bbloom: like yield in python

0:26 i'm also wondering if reducers can help me...

0:27 since it seems like rhickey went down the streams path, and then abandoned it for a mix of chunked lazy seqs plus reducers

0:27 but i'm still not quite sure

0:28 but i think i should study reducers more...

0:28 tomoj: the generators in python just give a synchronous iterator-like interface, right?

0:30 bbloom: tomoj: yeah, it's an imperative, continuation-based sequence building thinggie

0:31 i have a sequence transformation where i want to occasionally perform buffering look ahead, so i need to be able to thread some state along the way for a map/reduce

0:32 the real issue is that i need to interleave two processes: one buffering/enqueing and the other dequeing

0:32 otherwise, my buffer is O(N) and useless to me

0:34 tomoj: you lost me there, but reducers do seem promising based on my weak understanding of the earlier 2 of your last 4 messages

0:34 ...i.e. not the real issue

0:34 bbloom: so assume you have some sequence of items

0:34 and you want to transform it

0:35 however, occasionally, you don't know how to transform an item

0:35 you'll need to "look ahead"

0:35 ie buffer up those items until you find the information you need

0:35 one way to do that is to loop over the source and only "yield" when you have what you need

0:35 that "yield" operator will cause some other code to run, which will consume the yielded value

0:36 and by that mechanism, somebody is receiving values and so there is no buffer between the two processes

0:36 tomoj: yeah, that seems reducer-friendly so far, if I understand you

0:37 you want to do a straight map on the non-lookahead items, and only thread reduce state through on the buffers?

0:37 bbloom: tomoj: something like that... i think

0:37 tomoj: where the result of the reduce on a buffer is the result item for the entire buffer?-

0:37 bbloom: i have a tree which i'm flattening into a sequence (ie interior nodes are converted to begin/end pairs wrapping their children)

0:37 then i map over that to annotate them

0:38 then i want to map over it one more time, but sometimes i need to do look ahead

0:38 and then i want to map over it one last time to print out some values

0:38 it's that look ahead step i don't quite understand yet

0:38 tomoj: so the result has the same number of items as the flattened tree

0:38 bbloom: yes

0:39 although filtering/ammending the items shouldn't matter

0:39 the tricky bit is just the buffering

0:39 tomoj: I just was not sure whether the buffers got collapsed into single result items

0:39 bbloom: in this particular case, they do

0:40 tomoj: so the result has fewer items than the flattened tree when lookahead was performed

0:40 bbloom: sorry, let me clarify:

0:40 tomoj: ah, I see an ambiguity

0:41 bbloom: flatten tree of N items yields I*2 interior nodes + L leave nodes

0:41 let I*2+L = M

0:41 i then transform M -> M nodes to annotate them

0:41 i then transform M -> M again, but sometimes with look ahead buffering

0:42 and, for simplicity, let's say i then just doseq that and print it out

0:42 tomoj: right, I see

0:42 why won't just seqs work?

0:42 with a function like partition but which takes a function that tells it how/when to partition

0:42 bbloom: they could work, but it would be a tricky laziness problem

0:43 where i'd have to do nonsense like (lazy-cat nil ....)

0:43 and somehow thread the buffer through

0:43 tomoj: anyway seems to me you could similarly write a function like r/partition

0:43 (which may not exist yet.. but there is a r/partition-by patch somewhere)

0:43 * bbloom goes to look at r/partition

0:44 bbloom: doesn't exist, but i found the r/partition-by patch

0:44 it has a buffer! :-)

0:44 tomoj: that would return a new reducer of sometimes values, sometimes buffers, and then you can r/map over that?

0:44 bbloom: yeah, i think that's the ticket

0:45 my buffer is actually a double-list finger-tree because i'm going to do pruning on the buffer as well :-/ heh

0:45 tomoj: then doseq doesn't work but you can do (reduce (fn [_ v] (println v)) nil r) :/

0:46 or more cryptically (r/reduce (fn ([_]) ([_ v] (println v))) r)

0:49 er, (fn ([]) ...) I mean

0:50 bbloom: tomoj: so there's still one other issue: what do i reduce TO ?

0:50 obviously i need to reduce to a seq, but what kind?

0:51 tomoj: by "reduce to a seq" you mean you think the return value of reduce should be a seq?

0:51 bbloom: yeah

0:51 tomoj: so you can doseq it?

0:51 bbloom: just like partition does

0:51 well it can reduce to the next stage of a reducer, i don't care if i eventually doseq it or not

0:51 although i assume i can

0:52 looking at http://dev.clojure.org/jira/browse/CLJ-991 patch v4

0:52 tomoj: if you go the reducer route your partition-with (or whatever) should just return a reducer

0:52 bbloom: notice how it calls "append"

0:52 amalloy: bbloom: i think you can write yield in terms of continuations pretty easily, right? have you looked at delimc?

0:52 bbloom: oh i see

0:53 amalloy: yeah, i contributed a big pile-o-patches to delimc & have a half finished CPS transform for clojure script

0:53 amalloy: i'm trying to see if there is a non-imperative solution via reducers

0:53 tomoj: that partition-by looks really weird to me

0:53 bbloom: tomoj: so it's yielding one partition at a time

0:53 which makes sense

0:53 amalloy: something like a year ago i was talking to dnolen in here about how you can use just lazy-seq to give you everything yield allows

0:53 tomoj: anyway, you won't get a seq back out of your reducer - I guess it's possible but it would seem silly

0:54 you'd just use the reduce I wrote above on the reducer partition-with returns instead of doseq

0:54 amalloy: bbloom: have you written a version that uses yield? ie, presuming yield exists, what would the code look like?

0:56 aphyr: So... my project used to specify clojure:clojure:pom:1.3.0, back in the day

0:56 bbloom: amalloy: https://github.iu.edu/sabry/PPYield/blob/master/PPYield.hs#L352-419 like that confusing mess :-)

0:56 amalloy: yikes, just the anchor part of that link worries me

0:57 aphyr: ... which I guess is replaced by [org.clojure/clojure "1.3.0"] now

0:57 Is there a sane way for me to run old versions from git without having to edit project.clj every time?

0:57 amalloy: that is not what the clojure would look like with yield. that is a big blog of haskell, man

0:58 aphyr: i don't think clojure:clojure:pom:1.3.0 ever worked - the clojure artifact has always had groupid org.clojure

0:58 bbloom: yeah, my point exactly haha

0:58 amalloy: bbloom: if you want yield in clojure, write it in clojure and assume that yield works. then, you can either figure out how to write yield, or do the smallish amount of work necessary to convert yield to lazy-seqs

0:58 technomancy: aphyr: lein had a stupid special case for a few jars waaaay back in the day

0:59 it only applied to clojure and clojure-contrib

0:59 aphyr: amalloy: sorry, in project.clj it was: just [clojure "1.3.0"]

0:59 bbloom: amalloy: i also have a lazy-seqs version in haskell to reference, but it's pretty hairy because it requires "trying the knot"

0:59 amalloy: technomancy: not waaaay back; you can't call 1.x ancient and still refuse to release 2.0

1:00 aphyr: Kinda frustrating, I'm trying to benchmark my project and it's broken as recently as... nine months ago, haha

1:00 technomancy: amalloy: right; I guess the ancient part was actually emitting bare clojure

1:00 amalloy: oh, as in lein new did that?

1:00 technomancy: it would have been only on projects where `lein new` was called 2+ years ago I think

1:00 yeah

1:00 aphyr: Yeah, it did.

1:00 bbloom: amalloy: http://notepad.mmakowski.com/recursive%20knot

1:01 aphyr: Can you think of a dumb workaround, or do I need to patch project.clj every time I check out?

1:01 bbloom: repmin == replace minimum

1:01 notice (mn, tr) = walk mn t

1:01 technomancy: aphyr: how many projects is this?

1:01 bbloom: circular laziness :-/ blargh

1:01 aphyr: 1.

1:01 technomancy: ...?

1:01 aphyr: technomancy: just one project

1:01 I'm writing a program that does automated performance regression testing.

1:02 technomancy: oh, gotcha

1:02 aphyr: Benchmarks riemann against old versions to compare how different functions changed, that sort of thing

1:02 technomancy: you could install a dummy clojure/clojure project that depends on org.clojure/clojure

1:03 lein new clojure; cd clojure; sed project.clj *mumbles* ; lein install

1:04 amalloy: sorry, bbloom, those sorts of things give me a headache as well

1:05 bbloom: yeah, i want to pretty print some stuff & i was pulling my hair out trying to configure the native pretty printer. so i have a "data all the things" style pretty printer, but it's mega slow b/c it recursively recomputes the whole tree over and over again, so i'm trying to implement this linear runtime, bounded space version :-P

1:06 it's fucking complicated lol

1:06 but now i'm determined to finish it.

1:07 i'm almost certain that tomoj is on the right path with r/partiton-by, i'm gonna give that a shot

1:07 tomoj: :(

1:07 when you linked to the knot tying I threw my hands up, metaphorically

1:08 bbloom: tomoj: don't frown! you saved me a wild goose chase down the continuations rabbit hole :-)

1:08 aphyr: Goot call technomancy, thanks!

1:08 *good

1:09 kovas: what is pretty about the printing?

1:10 bbloom: kovas: the indentation and line breaks

1:10 kovas: ah

1:10 sounds like a job for the attribute grammar

1:10 :)

1:11 i checked out that paper you referred, looks interesting

1:11 bbloom: kovas: i saw something about that in all my reading, but decided to avoid chasing that particular tail because these very smart folks who wrote these papers manually translated to lazy seqs

1:11 soooo

1:11 heh

1:11 but i have no idea what an attribute grammar is

1:12 but i suspect that it has something to do with that totally bad ass ometa TCP/IP implementation :-)

1:12 buffers & look ahead as non-deterministic parsing!

1:13 kovas: my interpretation is that its a way of annotating a tree with metadata, where the metadata is defined by functions on the relative positions of nodes

1:13 so there is a way of passing data around the tree

1:13 but theres probably other ways of looking at it

1:14 bbloom: kovas: personally, i really like the flattened view of trees

1:14 i find state machines with manual stacks to be much easier to reason about

1:14 and then, gloriously, i can use reductions to print out all the intermediate states of my algoirthm

1:15 kovas: pretty printing is somehow in the literature as one of the canonical applications

1:15 hmm

1:15 tomoj: but there is no reductions for reducers

1:15 I have one in a gist somewhere but not sure how good it is

1:15 bbloom: tomoj: shouldn't be hard to add that too :-P

1:15 tomoj: I used an atom

1:16 bbloom: tomoj: i think the same strategy as the partition-by patch would work...

1:17 tomoj: hmm https://gist.github.com/543a721f0f44cf48459d

1:19 I see someone else did http://dev.clojure.org/jira/browse/CLJ-1113

1:19 and they also use an atom

1:19 but they used reducer..

1:19 for some reason I had thought you couldn't use reducer for that

1:19 anyway I still haven't figured out how to use something like reducer to get IKVReduce, so :)

1:26 yunfan: is there any book like "a byte of python" which introduce the basic of clojure programming

1:27 tomoj: what shall we do about middleware? :'(

1:27 Raynes: amalloy: I have found a way to get laser in lazybot. Alert the men.

1:28 tomoj: Oh, you.

1:28 tomoj: So, I saw you were calling me stupid for some reason last night?

1:28 I couldn't really figure out what you were saying.

1:29 tomoj: I wonder how much of the required ordering of middleware is caused by middleware which unnecessarily destroys information in the request/response

1:29 Raynes: I was hoping you could elaborate. I don't think I'm stupid, but we should be sure.

1:29 tomoj: I don't think I was calling you stupid

1:29 Raynes: I think you called me reverse stupid.

1:29 tomoj: maybe, but only a little :)

1:29 Raynes: I thought you might have been drunk.

1:30 tomoj: nope, I'm not much of a drinker

1:30 Raynes: Anyways, so what about the css selectors?

1:31 tomoj: I also find it important to distinguish between calling an idea (reverse) stupid and calling its author (reverse) stupid

1:31 well, why do you want to implement css selectors?

1:31 I can maybe imagine there are reasons that would make sense to me

1:31 my point was just, why not use clojure data instead of strings?

1:32 Raynes: tomoj: I really don't want to at all. I'd prefer everybody just use selector functions. I planned to write css selectors when I get bored solely because people are afraid of an extra character or two in their selectors after enlive.

1:32 tomoj: "reversed stupidity" would be avoiding using clojure data just because enlive did it, and your project is (complement enlive)

1:32 Raynes: But I wanted to do real CSS selectors.

1:32 I wanted to do real CSS selectors because it seems like it'd be really cool to be able to copy a selector from your css file right into laser.

1:32 tomoj: but maybe you have other reasons for avoiding using clojure data

1:33 right, that's a reason that makes sense to me to implement css selectors

1:33 Raynes: But you can implement both versions.

1:33 tomoj: yeah, plan to :)

1:33 well, not the css, I'll leave that to you

1:33 Raynes: I plan for it to work like (css "foo.bar") = a selector to give to laser.

1:34 tomoj: yeah, that seems useful

1:34 Raynes: So the other version can be done like (enlive [:foo.bar]) or something.

1:34 Mostly, I want it to be clear that everything is just functions.

1:34 Functions functions bloody functions.

1:35 tomoj: yeah, when I first tried laser I appreciated that

1:35 but my thought was more "good foundation" than "I want to always write it this way"

1:35 Raynes: I don't know why people hate combinators so much. *shrug*

1:36 tomoj: though I'm still not sure about the foundation, largely because I have mismatched requirements

1:36 Raynes: It's weird how people are all like "Functions are great, we should use them for everything" until they get to something to do with HTML, and then it's like "We need 4 DSLs, a new language, and preferably a new toolset to go with it."

1:36 :p

1:37 tomoj: I like combinators, I just think I'd appreciate shortcuts for very common stuff

1:37 bbloom: tomoj: any idea why the reducers namespace is not found in 1.5.0-RC1 ?

1:37 Raynes: Yeah, I agree. It wasn't a criticism. I think it'll be nice.

1:37 bbloom: do i need a particular version of something?

1:38 tomoj: you either need java, uh, 7 I think, or to add some jsrwhatever to your deps

1:38 but shortcuts should still let you drop stuff done in raw 'bloody functions' directly in

1:39 bbloom: tomoj: heh i'm on 1.6 i'll find 1.7

1:39 Raynes: tomoj: Anyways, thanks for clarifying. :)

1:40 tomoj: fwiw I was referring to http://lesswrong.com/lw/lw/reversed_stupidity_is_not_intelligence/ — should suggest a weaker interpretation than I can imagine you'd get if you didn't know it was a reference

1:40 bbloom: is installing the jdk directly from oracle hte recommended thing these days?

1:41 tomoj: are you on a debianish?

1:41 * technomancy shudders at the mention of oracle

1:41 bbloom: tomoj: osx

1:42 tomoj: can you even use oracle's java on osx?

1:42 bbloom: technomancy: so make your lein script magically obliterate the need for me to think about oracle :-P

1:42 tomoj: thought you were stuck with apple's

1:42 bbloom: tomoj: i just downloaded jk-7e9-macosx-x64.dmg from oracle

1:42 *shrug*

1:42 tomoj: hmm, there was an issue about this

1:42 bbloom: dammit.

1:43 tomoj: https://groups.google.com/d/topic/clojure-dev/um5f3p4KsXU/discussion

1:43 bbloom: seems to work :-)

1:43 i'm back up and running & have reducers now

1:43 technomancy: bbloom: can't fight the OS

1:43 bbloom: technomancy: sure you can! you just aren't likely to win

1:44 technomancy: I'm content to just make fun of the bad guys on IRC

1:51 tomoj: so part of the problem with middleware is that dependencies aren't encoded anywhere except in the code

1:51 bbloom: tomoj: so i think a reducer + an atom like you did for reductions = a state transducer

1:52 tomoj: sweet

1:52 technomancy: bbloom: last I checked openjdk on OS X is kind of a train wreck

1:52 tomoj: should I know what "transducer" means?

1:52 bbloom: technomancy: oh yeah, completely

1:52 tomoj: no lol

1:52 http://en.wikipedia.org/wiki/Finite_state_transducer

1:52 tomoj: i guess the idea is that it's a reducer type thing, but at each step of the way, there is also a state that gets threaded through

1:52 which is what i need

1:53 tomoj: ah, yes I should, but I never took automata

1:53 bbloom: me neither really

1:53 anyway, if you view a tranducer as a machine on an assembly line, you can glue a bunch of them together

1:54 they are like reducers in that sense

1:54 and, like reducers, the input conveyer belt and the output conveyer belt aren't necessarily running at the same speed

1:54 tomoj: and the reducer api can implement them and works seamlessly with them?

1:54 bbloom: i guess if you just add an atom, then yeah, that's what you've got: a stateful transducer

1:55 although, in theory, you could do it without an atom if you had a r/map-state type function which took some (f state x) instead of just (f x)

1:55 but also needs to return [state' x'] instead of just x'

1:56 tomoj: reminds me of zip folding

1:56 which can apparently be implemented with cps

1:56 I still don't understand oleg

1:56 bbloom: and then you start getting into arrows... the generalization of monads... *head explodes*

1:57 who'd have guessed that pretty printing was so complicated? lol

1:57 tomoj: I've kept my head from exploding so far by blindly trusting conal's dislike of arrows (for frp at least...)

1:57 I guess it will have to explode someday :(

1:57 aphyr: Raynes: props for conch, BTW. Just found myself reinventing it.

1:57 bbloom: FRP is a totally separate conversation :-P

1:57 tomoj: yeah, but that's the only reason I have to care about arrows right now

1:58 er, s/zip folding/fold zipping/

2:07 Räynes: xml->'s selectors are functions (Loc -> (U Loc [Loc] Bool nil))

2:07 a problem is that it requires that funky macro

2:08 where (Loc -> Bool) is more straightforward to compose

2:08 but it occurs to me that maybe xml->'s style of composition is like kleisli composition of a selector monad

2:11 bbloom: hmm that's annoying. defcurried is private ?

2:11 aphyr: Raynes: I don't understand how me.raynes.conch, conch, the docs, and the current github master relate to one another, though

2:11 they all seem to have very different structure

2:12 tomoj: it is annoying

2:12 also rfn

2:15 bbloom: curried functions are kinda ugly in clojure :-/

2:16 ro_st: what's the diff between curried fns and partials?

2:16 egghead: curried is one at a time

2:16 special case of partial

2:17 tomoj: hmm

2:17 ro_st: ah so (curry + 1) vs (partial + 1 2) ?

2:18 tomoj: no, (curry +)

2:18 say (= 3 (((curry +) 1) 2))

2:18 which only makes sense if you treat + as binary

2:19 so you could write (def ^{...} map #(partial (fn [f coll] ..) %)) or something?

2:20 ro_st: yogthos|away: great work with luminus!

2:20 tomoj: but you really just write (defn map ([f] (partial map f)) ([f coll] ...)) or (def map (curry (fn [f coll] ...))) or (defcurried map [f coll] ...)

2:25 bbloom: tomoj: so both take & drop are stateful w/ atoms

2:26 tomoj: yeah

2:26 should your thing be foldable?

2:26 bbloom: tomoj: no

2:26 tomoj: oh well

2:26 seems like trees should be foldable

2:26 bbloom: but i'm printing it to a non-tree shaped terminal :-P

2:27 aphyr: Uh, this is probably a terrible question, but does anyone know how to correctly stop 'lein run'?

2:27 tomoj: oh, sure

2:27 aphyr: I've just discovered that Process.destroy is useless for subprocesses and there's apparently no way to get a pid out of a Process object

2:33 bbloom: tomoj: it is extremely non-obvious how to write a reducer... heh

2:41 tomoj: so f1 is the "next reducer"?

2:42 tomoj: f1 is the monoid you finally pass to reduce

2:42 I call it "the reducef"

2:43 (perhaps I should have written "reductionsf" and "reducef", not "reducef" and "f1"

2:44 bbloom: i must be tired, but i'm having a hard time making sense of this...

2:44 what is the k/v impl ?

2:44 tomoj: which code are you looking at?

2:44 bbloom: reducers.clj

2:44 tomoj: well, kv is not really applicable to you I don't think

2:45 you can (reduce-kv (fn [ret k v] ...) init a-map)

2:45 but none of the reducer combinators preserve IKVReduce, so you can't do anything else with it

2:45 it's just for faster reduce over maps right now

2:45 bbloom: i don't have a kv reduction

2:46 so is that just noise at this point?

2:46 Raynes: aphyr: I probably forgot to push, I guess.

2:46 tomoj: yeah

2:46 you don't need IKVReduce so you can ignore it

2:47 bbloom: so basically i want a version of map, that i'll call transduce, that takes an initial state and threads the state through

2:47 rfn says "3-arity" but mine has an extra argument: init

2:47 so presumably i can't use rfn ?

2:47 and wouldn't want to anyway, since i don't have a k/v impl

2:47 tomoj: ah

2:47 well, yes

2:47 Raynes: aphyr: Just fixed it.

2:47 tomoj: the fact that rfn does something about kv is a total red herring

2:48 Raynes: aphyr: And thanks! Glad you like it.

2:48 bbloom: tomoj: yeah, confusing the hell out of me lol

2:48 aphyr: Raynes: cool. Stuck trying to get a real pid out of a Process now.

2:48 tomoj: I've posted about that and created a ticket but got not one peep from anybody

2:48 aphyr: About to pull in JNA, wish me luck. D-:

2:48 tomoj: except ämalloy saying he thought it was an accidental omission

2:48 Raynes: aphyr: You definitely can't from Java itself.

2:48 aphyr: I wouldn't do that.

2:49 aphyr: I'd just write a little script in bash, python, ruby, etc, and shell out to it if any way possibly.

2:49 possible*

2:49 tomoj: I think really rich has already thought about everything I've thought about around IKVReduce, and he knows that it needs more hammock time

2:49 and it was an intentional omission

2:49 with rfn being partly half-baked

2:50 Raynes: aphyr: Or do what ol' Rich advocates and write a service with an API that you can call from Clojure. ;)

2:50 tomoj: but anyway

2:50 bbloom: heh ok, i'm getting closer :-P

2:51 aphyr: Raynes: Yeah, problem is I'm trying to benchmark a whole process running in lein

2:51 and lein starts a subprocess... which can't be killed

2:51 because process.destroy considers child processes irrelevant or something (do they become zombies? what kind of acid were they on?)

2:51 bbloom: tomoj: and i'm understanding why defcurried and rfn are private: i don't want them lol

2:51 aphyr: Turns out you can snarf it with reflection, at least on linux

2:51 Raynes: Ugh, yeah.

2:52 tomoj: are you using reducer?

2:52 bbloom: well maybe defcurried

2:52 i'm trying to decide if i want to use reducer now

2:52 i don't think i do

2:53 tomoj: if you use reducer (which is public) for an operation, then rfn would be useful, if not for the kv noise

2:54 (which, I'll emphasize, is also 100% noise in reducers.clj)

2:54 bbloom: so i'm trying to decide what to do about the two overloads of coll-reduce

2:55 s/decide/understand

2:55 tomoj: the [coll f] arity is for people who call clojure.core/reduce and don't pass an initial state

2:55 if you call clojure.core.reducers/reduce and don't pass an initial state, the initial state is (f)

2:56 which is why rfn is somewhat useful, to automatically preserve the zero arity of a transformed reducef

2:56 (i.e. the identity of the monoid)

2:56 bbloom: isn't the monoid only relevant when foldable?

2:56 i don't think i have a monoid in my case b/c i have a linear state

2:57 & am not foldable

2:57 lazybot: java.lang.RuntimeException: Unable to resolve symbol: am in this context

2:57 tomoj: it's also used when you just r/reduce without an initial value

2:57 e.g. (r/reduce + [1 2 3]) calls (+ 0 1) first

2:57 (+ (+) 1) that is

2:58 so if you use r/reduce, you have to care about preserving the monoid identity

2:58 r/reduce without an explicitly provided initial value, that is..

2:58 bbloom: i want to require that callers of transduce provide an initial state

2:58 tomoj: sure, that's different

2:59 transduce won't actually do any reduction, right? it just returns a reducer

2:59 bbloom: so should i only implement the [coll f init] variant?

2:59 right

2:59 tomoj: you want (reduce f (transduce r)) to be illegal?

3:00 (and (r/reduce f (transduce r)) to be legal only if (f) is legal?)

3:00 (as always..)

3:00 bbloom: so transduce takes three arguments: [f init seq]

3:00 Ember-: http://arstechnica.com/security/2013/01/extremely-crtical-ruby-on-rails-bug-threatens-more-than-200000-sites/

3:00 amalloy: is it the mass-assignment thing being reported again?

3:01 bbloom: or i guess [f init non-foldable-reducer]

3:01 amalloy: nah, it's some new nonsense with an injection flaw or something

3:01 Ember-: amalloy: dunno, but that bug allows you to execute arbitrary code on the underlaying server

3:02 aphyr: amalloy: there are a bunch of default deserializers in the rails body handlers

3:02 including yaml, which includes a syntax for creating arbitrary instaces of any class and setting instance vars

3:02 tl;dr stop automatically coercing strings to arbitrary datatypes

3:03 bbloom: lol

3:03 yaml always struck me as such a silly idea

3:04 "It's like XML, only with syntax that's nearly impossible to generate programatically!"

3:04 aphyr: I can't even generate it by hand. ;-)

3:04 ro_st: You Avoid Markup Language

3:06 aphyr: Raynes: I can add (pid process) to conch if you're interested

3:07 but in order to be portable to windows I think I'll have to pull in JNA

3:07 bbloom: tomoj: i think i'm just incapable of following the flow of code where the order of arguments matters. i can *never* remember the order of the arguments to reduce and always need to check the docs. i need a language where all functions accept and return a map :-P

3:08 Raynes: aphyr: Is it a large dependency?

3:08 aphyr: JNA? yeah. :(

3:09 amalloy: bbloom: it's pretty easy to remember what order reduce takes its arguments in if you imagine trying to add together a bunch of numbers. like, (reduce 0 + coll)? no, the function must come first or it reads bizarrely. (reduce + coll 0)? that feels pretty awkward. (reduce + 0 coll)? aha, we're adding to zero all the things in coll

3:10 bbloom: amalloy: i can always remember that coll comes last because it's the least likely thing to be partially applied, so it makes sense to have it last. it's just the first two arguments i always mess up because i think "init == first"

3:10 :-P

3:11 Raynes: aphyr: How does JNA work. Does it use native dependencies or something?

3:12 bbloom: amalloy: also i *hate* when functions don't come last in javascript/coffeescript, since partial application is rare there and coffeescript just makes it so nice to have indented callbacks.... setTimeout is evil in that respect

3:13 98% of the time, the order of arguments has zero semantic meaning too, hence maps are just so pleasant for business logic

3:15 Raynes: aphyr: Okay, so here is what I think.

3:16 aphyr: It looks like JNA automatically extracts its native library and does whatever with it itself. I think it'd be best to add a dependency on pomegranate and automatically add JNA to the classpath if someone calls the pid function.

3:16 aphyr: If you don't want to go through that trouble, just write the pid function and I'll handle the pomegranate stuff.

3:16 tomoj: bbloom: interesting

3:17 I've wondered what it would be like to put map entries on the factor stack

3:17 or, factjor

3:17 and treat the entire stack as a map

3:17 bbloom: tomoj: i thought about that briefly and then realized that it's basically just dynamic variables lol

3:18 tomoj: if you do normal stack stuff under (on top of?) the map entries?

3:18 s/stack stuff/factjor words/

3:19 Raynes: aphyr: I'm going to give it all a bit more thought though. Another option is to add the dependency, but don't actually define the function unless the dependency is present which would allow people to exclude the dependency.

3:19 bbloom: tomoj: http://docs.factorcode.org/content/article-namespaces.html

3:19 Raynes: That might be the better idea.

3:19 I don't think most people are going to care about the extra dependency.

3:19 tomoj: ah yes!

3:20 I also want a word that takes the entire frame and reifies it into a map

3:20 (the entire "implicit assoc")

3:20 and maybe one that takes a map and makes that the implicit assoc

3:20 Raynes: aphyr: Yeah, we should do that. Ignore everything else I said.

3:20 tomoj: oh.. http://docs.factorcode.org/content/article-namespaces-combinators.html ??

3:20 lazybot: tomoj: Uh, no. Why would you even ask?

3:21 Raynes: aphyr: Still though, if you want you can just write the pid function and I'll do the other stuff.

3:21 * Raynes vanishes

3:22 aphyr: ok

3:22 sorry, busy screaming into the JVM void

3:24 bbloom: tomoj: clojure has similar operators: bound-fn, push-stack-bindings, pop-stack-bindings, get-stack-bindings, etc

3:24 it's actually quite amazing how much clojure & factor have in common

3:27 anyway tomoj thanks for helping me think through this a bit

3:27 tomoj: http://tech.groups.yahoo.com/group/concatenative/message/2762

3:28 I don't think I really want concatenative logic programs anyway, I just had to google for it

3:29 bbloom: haha

3:29 i think it's one of these things where you use the right paradigm for the problem at hand

3:29 my interest in concatenative programming, and the motivation for creating factjor, was so that i can serialize side effects

3:29 tomoj: but I think maybe it would be nice to have a word that takes a quotation, looks at metadata on the words in the quotation and rewrites the quotation using a simple logic program on the metadata

3:30 bbloom: in particular because i want to diff two tree structures and output a program to be executed against the DOM

3:30 which is what my talk at Clojure/West will be about! :-)

3:30 tomoj: shoot

3:30 bbloom: tomoj: quotation transformations & pattern matching are pretty cool too

3:31 tomoj: see factorcode.org/littledan/match.pdf

3:31 ill be back in a little while

3:32 tomoj: don't think I'll get to see your talk — are the two tree structures two versions of a model?

3:33 two uh, abstract markup trees?

3:33 or what

3:49 hmm http://i.imgur.com/i2MRN.png

3:50 the magic seems to leak out of clj-http.core/request

3:50 so clj-http-lite can't use it

3:50 whereas ring has different servers that don't leak?

3:51 oops, there should be magic on the ring side too

3:51 but it doesn't leak out of the ring server

3:51 (I think?)

3:53 well, clj-http-lite wouldn't use clj-http.core/request anyway, it'd provide it's own client, obviously

4:42 bbloom: tomoj: k i'm back & i got transduce working, but i'm calling it map-state

4:43 pretty much all of my problems were caused by defcurried expecting a meta data map & rfn not being what i want... i guess i deserve that for using private macros :-P

4:43 tomoj: example of calling it?

4:46 bbloom: tomoj: here's a trivial example where it's used similarly to map-indexed

4:47 https://www.refheap.com/paste/8269

4:47 that produces [0 1/2 2/3 3/4 4/5]

4:48 tomoj: I see

4:48 bbloom: index == state

4:49 in my actual case, i'm gonna be keeping a running some of some property of each x and associating that into the next x

4:49 tomoj: that looks like reductions with a post-step?

4:49 where the post-step is (ret 1)

4:49 bbloom: tomoj: https://www.refheap.com/paste/8270

4:49 note that is a modified version of defcurried that doesn't expect metadata

4:50 this would be trivial as a lazy-seq, but i need access to that f1 function so that the producers/consumers are interleaved

4:51 that's the interesting thing about the reducers: with lazy seqs (->> coll (map f) (map g)) is not the same as (->> coll (map (comp g f)))

4:51 but with reducers, they are!

4:52 the f and g calls are interleaved in a way that is useful to prevent my buffers from bloating

4:54 tomoj: there's a difference in a trace of f and g calls?

4:54 (with lazy seqs)

4:54 guess that's easy to determine

4:55 bbloom: yeah, there are several sources of non determinism in call order

4:55 one is chunking

4:55 tomoj: oh, heh

4:55 bbloom: another is the fact that somebody has to be on the other side to pull on the seq to have it realized

4:56 and like i said, it's possible to do what i'm trying to do with lazy-seqs

4:56 but it requires that "tying the knot" thing

4:56 where you feed the lazy seq into a computation that produces another lazy seq in a circular way

4:57 which is precisely how haskell got it's reputation for "space leaks" :-P

4:57 tomoj: so what are the trees?

4:57 bbloom: they are little "pretty print documents"

4:58 tomoj: oh right

4:58 I forgot you were talking about concatenative when you said DOM

4:58 bbloom: yeah two separate projects :-P this one turned out to be a big distraction

4:58 but that's ok for at least another month until i need money :-P

4:59 abp: So for a web app I've wrapped my handler in a middleware that always takes the first uri segment as :context. That's just for lein-ring to behave like deployed in a servlet-container with a context (/context/...) when testing locally. Also I use hiccups wrap-base-url middleware to obtain correct links etc. via (to-uri ..). Does that sound way to hacky? Is there a "better" way?

5:00 bbloom: tomoj: ok so now the tricky part: the buffering reducer! gotta figure that out

5:01 wingy: maybe someone should create a hosting platform for clojure apps like nodejitsu for node.js app? :)

5:01 tomoj: bbloom: well, hmm

5:02 ro_st: wingy: heroku is plenty good enough

5:02 tomoj: I thought I had an idea but it was wrong, nevermind

5:03 bbloom: tomoj: so i'm thinking back to rich's talk with the three use cases: 1-to-1 1-to-more and many-to-fewer

5:03 tomoj: sorry, which talk?

5:03 bbloom: about reducers

5:03 he talks about map, filter, and mapcat as being examples of those three use cases

5:04 wingy: ro_st: it doesn't support immutant though :/

5:04 bbloom: in my case, it's a 1-to-1 mapping when all is said and done, but along the way it's sometimes many-to-none and other times 1-to-many, ie when buffering or when unbuffering

5:05 in theory, when buffering, i just don't call f1

5:05 and when unbuffering, i call reduce with f1

5:05 right?

5:05 clojurebot: to be fair I dunno that I've ever had code out right rejected, it just sits in jira or assembla or where ever, or if I ask if there is any interest (before writing any code) I get told to go write alioth benchmarks

5:05 bbloom: shutup bot

5:05 tomoj: "unbuffering" means like, uh, "nonbuffering"?

5:05 marianoguerra: a simpler function to do (partition 2 (interleave [:a :b] [1 2])) ?

5:05 bbloom: unbuffering means draining the buffer to empty and passing all those items along (transformed) to the next reducer

5:06 tomoj: marianoguerra: (partial map list)

5:06 ro_st: wingy: i doubt a clojistu would, either :-)

5:06 bbloom: ,(map vector [:a :b] [1 2])

5:06 wingy: ro_st: it would!

5:06 clojurebot: ([:a 1] [:b 2])

5:06 tomoj: oh, I see

5:07 yeah.. use map vector instead

5:07 I just blindly chose something that printed the same

5:07 bbloom: tomoj: so notice how partition-by sometimes does not call f1

5:07 that's buffering

5:07 echo-area: So is gen-class currently not able to generate <clinit>?

5:07 bbloom: tomoj: then, it doesn't drain the buffer, it passes the whole buffer (a vector) to f1

5:08 in my case, i'd just reduce that buffer with f1, which would be like mapcat

5:08 tomoj: returning a single result for that begin element

5:08 ?

5:08 echo-area: I mean customized <clinit>

5:08 tomoj: er, no, f1 is a reducef

5:08 bbloom: tomoj: look at the definition of mapcat, notice how it calls (reduce f1 ret ...

5:08 echo-area: It can only put var initialization and ns loading code into <clinit>

5:08 tomoj: yeah

5:09 echo-area: Is this the fact?

5:09 tomoj: (btw, don't return a map from your mapcat f!)

5:09 bbloom: that "sub-reduce" is going to call f1 multiple times

5:09 heh

5:11 tomoj: suppose there were a (nexts r) that returned a reducer of reducers, each successive reducer omitting the first value of the previous

5:11 marianoguerra: tomoj, bbloom thanks!

5:12 tomoj: then could you write part of that with (mapcat #(if-let [buffer (buffer-for %)] buffer [%]) (nexts r)) ?

5:13 maybe throw some #'first in there

5:13 * bbloom *scratches head* i'm not sure i follow

5:15 bbloom: oooh i think i know, i want mapcat-state basically...

5:22 ,(conj! nil 1)

5:22 clojurebot: #<NullPointerException java.lang.NullPointerException>

5:22 bbloom: ,(conj nil 1)

5:22 hmmm

5:22 clojurebot: (1)

5:24 tomoj: &((fnil conj []) nil 1) ; ?

5:24 lazybot: ⇒ [1]

5:25 tomoj: this reducers talk is 5mo old, I hadn't seen it

5:25 thanks

5:25 bbloom: it's a good 1

5:28 tomoj: sweet, i got it!

5:28 tomoj: https://www.refheap.com/paste/8271

5:29 that second commented form, the mapcat-state, that one produces [0 1 2 3 4]

5:29 tomoj: interesting.. map should be collection ignorant

5:29 that's exactly what I want

5:29 but I want it to work for e.g. push seqs too :(

5:30 hell I just want fmap

5:31 bbloom: yeah, i gotta fix that

5:31 mapcat-state shouldn't take the []

5:31 oh no

5:31 nevermind

5:31 that's the state

5:31 it's the buffer

5:31 in a larger use case, that's gonna be something like {:foo 1 :bar 2 :buffer (double-list)}

5:31 heh

5:33 doc string: "Like mapcat, but threads a state through the sequence of transformations. For each x in coll, f is applied to [state x] and should return [state' xs]. The result is the concatenation of each returned xs."

5:34 anyway, i think i now officially grok reducers, which is cool

5:35 tomoj: is it possible to break mapcat-state up and get correct results, if bad performance

5:35 bbloom: break it up how?

5:35 tomoj: I mean break it up into operators that look fairly like standard reducer operators or ports of standard clojure functions

5:36 (ports into reducer-land)

5:36 bbloom: yeah, so the goal is to produce a pretty printer that has linear runtime and bounded memory requirements

5:36 tomoj: I'd be interested to see if there's a way to get good perf from code that looks awfully like a standard port

5:37 bbloom: you can write a trivial recursive function and get N^2 runtime

5:37 the naive implementation re-calculates the width of every branch of the tree every time it goes

5:38 tomoj: but what might it look like in vague reducer terms?

5:38 bbloom: using reducers (or co-routines, or continuations, or cyclic lazy-seqs) gives you a way of accomplishing a single traversal with bounded memory

5:38 tomoj: ah, is there a paper?

5:39 right: http://okmij.org/ftp/continuations/PPYield/yield-pp.pdf ?

5:39 bbloom: yeah

5:39 if you follow the paper trail back, there are like 4 or 5 along the way until you get to the pretty printer that's in common lisp which is the basis for clojure's :-)

5:41 tomoj: seriously, thanks a lot for talking this out with me

5:41 you helped a ton

5:42 tomoj: hmm.. do the reader monad and the (-> env) applicative overlap?

5:42 ((->) env) I guess

5:42 bbloom: i'm not even sure what that means :-P

5:42 i'm one of those people who's just smart enough to accomplish tasks eloquently by being too dumb to comprehend all the complicated shit that people have come up with :-)

5:44 tomoj: newtype Reader r a = Reader { runReader :: r -> a }

5:44 so I think that means Reader r a is a funny name for (r -> a)

5:44 bbloom: i dunno what Reader is

5:46 ejackson: tomoj, I think it means that Reader is a function from r -> a, where r implements the runReader

5:46 but that's dredging

5:46 arcatan: it's essentially a funny name for (r -> a)

5:47 ejackson: :)

5:47 tomoj: but does the Applicative instance for (r -> a) agree?

5:47 arcatan: you can use runReader to get out the (r -> a) of a Reader

5:47 tomoj: I don't really know what Reader is either, otherwise I'd know the answer

5:47 Sgeo_: tomoj, yes, reader and ((->) r) are conceptually the same

5:48 Conceptually with reader, and physically with functions, you're building a function that takes an input and produces a value

5:48 Sonderblade: what is the most popular clojure web framework? compojure?

5:49 tomoj: so ring middleware is sort of in the reader monad

5:49 ejackson: Sonderblade: yes,

5:50 Sgeo_: tomoj, that sounds likely

5:50 I remember looking at Enlive and when seeing do->, just thinking "reader monad"

5:50 tomoj: the applicative <$> for (r -> a) is just composition

5:51 of course

5:51 Sgeo_: tomoj, yes

5:53 tomoj: fmap :: (Res -> Res') -> (Req -> Res) -> (Req -> Res')

5:54 bbloom: i seriously have a really hard time with all the operators in haskell

5:54 tomoj: me too

5:54 bbloom: it makes these papers harder to read

5:54 tomoj: I meant <*> above, but I was wrong

5:54 bbloom: i'm very auditory in my thinking

5:54 i don't know how to say <*>

5:55 even if i knew what it was called, it would be a mouthful, too much to say

5:55 if i can't read it aloud quickly, i can't understand it

5:55 tomoj: well, [[ f a b ]] is nice shorthand for f <$> a <*> b

5:55 bbloom: yeah, i don't know what either of those things are supposed to do

5:55 lol

5:55 tomoj: it's just (f a b) but.. inside the applicative

5:56 Sgeo_: bbloom, it's a convenient way of using functions that don't understand an Applicative with arguments that are in one, sort of

5:56 bbloom: Sgeo_: that doesn't help me lol

5:57 i forget what "Applicative" means every time i see it

5:57 Sgeo_: bbloom, do you know anything about monads?

5:57 bbloom: a fair amount

5:57 Raynes: When did #clojure turn into #haskell?

5:57 Sgeo_: It means it defines <*> and pure

5:57 Raynes, not my fault this time!

5:57 tomoj: let's see.. (<*>) :: (Req -> (Res -> Res')) -> (Req -> Res) -> (Req -> Res')

5:57 bbloom: Raynes: sorry man, i'm trying to bring a better pretty printer to the clojure masses... and haskell has the fastest one :-P

5:58 Raynes: bbloom: :p

5:58 tomoj: [[ ]] :: (Res -> Res') -> (Req -> Res) -> (Req -> Res')

5:58 which is flip (.)

5:58 yes?

5:58 clojurebot: yes isn't is

5:58 Sgeo_: bbloom, say I have something like getNumFromInput :: IO Int

5:58 bbloom: Raynes: you do want a faster pretty printer, don't you? one fast enough that you wouldn't mind using it for dumping large files? :-)

5:58 Sgeo_: And I want to add two numbers from input together

5:59 (Ok, this is an example of use, not an explanation of what it is)

5:59 Raynes: bbloom: I've never wanted to do that, but of course, fast is good.

5:59 Sgeo_: In do notation, I might write

5:59 th3lib: \quit

5:59 Sgeo_: do { a <- getNumFromInput; b <- getNumFromInput; return (a + b) }

5:59 tomoj: wait, that's just (.)..

5:59 naturally

5:59 $( so confusing

5:59 amalloy: tomoj: you are trying to produce type signatures for...what? it sounded like you were saying ring middlewares, but that didn't look like the right type for those

5:59 Sgeo_: Which will be an IO Int, that takes two numbers from input and gives the result

6:00 bbloom: Sgeo_: i appreciate you trying to help, but i don't have the mental capacity for that now

6:00 tomoj: hmm, right

6:00 Sgeo_: Since IO is an Applicative (all monads are theoretically Applicatives, even if this isn't enforced in Haskell)

6:00 bbloom: Sgeo_: too many new ideas for what was supposed to be a simple side project!

6:00 Sgeo_: I could instead write (+) <$> getNumFromInput <*> getNumFromInput

6:00 tomoj: a ring middleware is sort of like (Req -> Res) -> (Req -> Res')

6:01 Sgeo_: Just like using (+) "normally", except <$> and <*> do plumbing stuff to handle the IO

6:01 amalloy: well, it's more like (Req -> Res) -> (Req' -> Res'), i think

6:02 tomoj: oh yeah

6:03 so not so close to the reader monad

6:04 amalloy: reader isn't one of the ones that i keep room in my head for, so i couldn't say

6:04 Raynes: amalloy: Hahaha. I love you, man. Every time you say something like that, I remember that "EVERYBODY STAND BACK. I KNOW PERL." xkcd.

6:04 tomoj: so fmap for ((->) ((->) Req Res)) is composition

6:05 which doesn't seem important

6:05 amalloy: eh?

6:05 tomoj: heh, ((->) (Req -> Res))

6:09 amalloy: tomoj: that notation has always confused me, and i think it just made sense to me (again, probably). is it the case that (->) is a two-argument type constructor, and by applying it to the type (Req -> Res) you get back a one-argument type constructor?

6:09 tomoj: yeah

6:10 er, I think

6:10 it just means (Req -> Res) -> anything as I understand it

6:10 amalloy: right

6:10 Sgeo_: <Jafet> @quote analogies

6:10 <lambdabot> mmorrow says: a functor is like an analogy between two analogies

6:10 tomoj: I don't ever actually use haskell

6:10 amalloy: i am forever forgetting that type constructors exist; it's all just magic

6:10 oh, same here

6:11 anyway, i am going to bed. enjoy your haskelling

6:11 Raynes: amalloy: Good night, handsome.

6:45 tomoj: haha "there's a notion in fancy land — monoids"

6:51 Raynes: @latest me.raynes/laser

6:51 $latest me.raynes/laser

6:51 lazybot: [me.raynes/laser "0.1.15"] -- https://clojars.org/me.raynes/laser

6:51 * Raynes puts his sunglasses on and walks away all smooth like, leaving his new toy to the #clojures.

6:56 tomoj: re-class? :)

7:25 Raynes: tomoj: I was wondering it was worth adding.

7:26 Since it's just (re-attr :class re)

7:26 But id= exists too.

7:27 I'll probably add re-id and re-class. I'll sleep on it. ;)

7:31 tomoj: but it's not

7:31 class= does extra, re-class should too

7:31 I'd think

7:31 i.e. split on spaces

7:32 Raynes: tomoj: I don't really see why it'd need to do that

7:32 tomoj: well, guess you're right

7:32 Raynes: I'm trying to think of a case where it'd be necessary.

7:32 Have one in mind?

7:33 tomoj: intuitively I expect to be able to do e.g. (re-class #"^foo-\d+$")

7:33 but it'd be easy to write the regex for the whole attr too I'm sure

7:34 Raynes: That's a fair point.

7:34 Considering I suck at regex, I'd probably have trouble figuring that one out for a bit.

7:35 I'll throw that in there tomorrow.

7:35 Raynes is about to pass out.

7:35 Night #clojure.

7:36 hyPiRion: Raynes: night. sleep well, prince.

7:49 clgv: oh "$latest" is nice^^

7:49 is there a lazybot irc function that lists all its commands?

7:50 bbloom: $google github lazybot

7:50 $google "github lazybot"

7:50 clgv: you get the idea, heh

7:52 clgv: bbloom: hm no, parsing the source is too much work. some things are not even activated on this instance

7:52 bbloom: I tried that in the apst

7:52 *past

8:59 josteink: http://landoflisp.com/#guilds

9:08 no7hing: for "foo bar baz" (clojure.string/split message-body #" " 2) returns [foo (bar baz)] where the second element is a chunked sequence where (rest …) should work?

9:08 "foo bar baz"/message-body

9:09 sorry, rest works, but following string operations don't

9:10 so (str my-chunked-seq) is necessary?

9:11 sorry i was confused

9:14 ForNeVeR: Hello, guys. Is clojars down or something? I got the following error when using `lein push`: http://paste.org.ru/?lk4en3

9:14 wingy: how do ring handle favicon.ico requests/

9:14 ?

9:14 clojurebot: Excuse me?

9:14 weavejester: wingy: The same way it handles any other request

9:15 hyPiRion: wingy: just put a favicon within resources or publics folder

9:16 ForNeVeR: Using lein1?

9:16 ForNeVeR: hyPiRion: lein2.

9:17 Will it help if I'll use lein1?

9:17 hyPiRion: Hmm, I've not heard about `lein push` before.

9:18 I usually do `lein deploy`

9:18 ForNeVeR: hyPiRion: it is plugin especially for clojars.

9:18 hyPiRion: oh, okay.

9:18 ForNeVeR: https://github.com/ato/lein-clojars

9:18 I had an issue with gpg, so cannot use `lein deploy`.

9:19 hyPiRion: But I know that technomancy and _ato is working on a new Clojar release, so that may be it

9:19 ForNeVeR: What a pity.

9:20 hyPiRion: I'd have a look at lein-clojars/clojars-web and check out if there's any issue describing your case

9:21 ForNeVeR: Well, I don't know if it is really clojars or just my setup / environment.

9:21 weavejester: lein push is pretty much the old way of doing things

9:21 lein deploy clojars should be preferred

9:21 wingy: hyPiRion: worked :)

9:21 ForNeVeR: Issue lists of mentioned projects don't include sqlexception.

9:22 weavejester: is uses `gpg` tool in some way.

9:22 hyPiRion: wingy: sweet!

9:22 ForNeVeR: And gpg literally suck.

9:22 weavejester: ForNeVeR: In what way?

9:22 ForNeVeR: It just stays in the process list and does anything.

9:23 But i'll try to do something with it now.

9:23 weavejester: ForNeVeR: You mean the gpg-agent?

9:23 ForNeVeR: Which OS are you using?

9:23 ForNeVeR: weavejester: Windows ~_~

9:23 weavejester: Ohhh

9:24 ForNeVeR: Yeah, that is the real problem :)

9:24 hyPiRion: Lein isn't that well tested on Windows unfortunately

9:24 ForNeVeR: Both lein versions work great.

9:25 I have only this silli deployment issue.

9:26 hyPiRion: You could try out the scp way of deploying

9:26 not sure what Windows tool you would use then though.

9:26 ForNeVeR: I sure windows has ported scp tool.

9:26 Sgeo_: Oh, not as in Secure Contain Protect?

9:27 ForNeVeR: scp-682, yeah.

9:27 I'll use it.

9:27 hyPiRion: Sgeo_: secure copy :p

9:28 ForNeVeR: There is some winscp utility.

9:34 scp way produces the same error.

9:35 xeqi: ForNeVeR: hmm, technomancy was deploying a new version a few hours ago, looks like migration wasn't run

9:35 ForNeVeR: Should I notify somebody?

9:36 xeqi: looking at it now

9:39 ForNeVeR: can you try to deploy again please?

9:39 hyPiRion: xeqi: that was fast.

9:40 ForNeVeR: xeqi: minute please

9:40 Success!

9:40 xeqi: hurray

9:41 ForNeVeR: xeqi: thank you for fast feedback :)

9:42 hyPiRion: (inc xeqi)

9:42 lazybot: ⇒ 5

9:43 Sgeo_: I should really re-read SCP-093 and assocated logs

9:44 Hmm, does Heroku rely on RoR?

9:44 p_l: yes

9:44 Sgeo_: :/

9:45 Do web programmers ever need to be on call or work in shifts?

9:45 For a situation such as this

9:48 xeqi: Sgeo_: usually there is a op or dev-ops team that has rotates who is on call

9:53 p_l: Sgeo_: good companies like that have on-call teams

9:53 and in such case, probably takes even those that weren't on-call

9:54 * Sgeo_ keeps thinking... other web frameworks wouldn't have this exact vulnerability, but for a framework with a much smaller userbase (say, Factor's Furnace or Racket's web framework), there might be a higher chance of such things going undetected

9:54 Sgeo_: :/

9:56 nDuff: Sgeo_: Typically ops-on-call can escalate to development for serious critsits.

9:57 Sgeo_: Well, so much for my idea that an advantage of becoming a programmer over a doctor is never being in an emergency

9:57 (I'd still be terrified to have someone's life in my hands)

9:57 nDuff: Sgeo_: ...well, if you're not senior enough to be the developer that issues get escalated to, it's moot. :)

9:57 ro_st: second that.

9:59 nDuff: Sgeo_: ...in my experience that's a whole lot of senior -- as in, you're getting golden handcuffs in a buyout -- so there's compensation for being "on-call".

10:00 Sgeo_: golden handcuffs?

10:00 nDuff: Sgeo_: A contract with a substantial monetary award, contingent on you remaining with the company for a set duration of time. Typically part of of it is paid up-front or over time, and has to be repaid should you leave of your own volition (or for-cause) before end of the contract.

10:02 Sgeo_: Those happen pretty frequently as part of an acquisition, as it's undesirable for the people who know and operate the thing you just paid a whole lot of money for to cash out and leave.

10:03 hyPiRion: yeah, usually you'd like some continuity and exchange experience/knowledge.

10:04 * nDuff gathers Sgeo_ is a student?

10:05 Sgeo_: nDuff, not anymore. Graduated in December

10:05 Not sure what I'm going to do now

10:05 hyPiRion: Sgeo_: Clojure.

10:05 :D

10:06 Sgeo_: hyPiRion, but Racket is fascinating

10:06 hyPiRion: Well, you can go Racket too if you'd like

10:06 I just came up with a suggestion

10:26 solussd: anyone have any idea what might be causing this clojurescript type error?: TypeError: 'undefined' is not a constructor (evaluating 'new cljs.core.Keyword("\ufdd0'default")'). here's the offending compiled javascript: https://www.refheap.com/paste/8278

10:38 ^(ignore the error accidentally pasted in the middle of my ref heap paste)

11:00 aroemers: solussd: Sorry, I don't see any obvious issues, but then again I don't know Cljs.

11:01 solussd: :)

11:05 TimMc: solussd: And cljs.core.Keyword exists?

11:07 jaley: hey all. I have a static map of 1 million string -> integer values. Any tips on the most sensible way to package it into a jar? I dumped it to clojure data as a file in resources and then tried using load-reader to access it. Seems to be quite a slow option...

11:07 solussd: TimMc: ack, no it's not… wonder why

11:14 TimMc: other things in cljs.core are defined, e.g. Vector.

11:14 djwonk: jaley: you need it in memory from the beginning?

11:16 solussd: ackk.. it's cljs.core.keyword (lowercase k)

11:16 jaley: djwonk: yeah. it's test data for a performance/stress test

11:16 djwonk: I'd like to learn clean/recommended ways to manipulate a map inside an atom. I've used assoc, assoc-in, update-in. Are there some other ways that I should try?

11:17 jaley: how "slow" is loading the data via the clojure reader?

11:17 hyPiRion: djwonk: merge, merge-with, select-keys?

11:17 Granted, merge-with has to be partial'd.

11:17 jaley: djwonk: many minutes

11:18 djwonk: someone just recommended nippy to me, which looks good

11:19 djwonk: jaley: cool, first I've seen it

11:21 hyPiRion: thanks. the pain I'm feeling is that I have a big 'game' map (for a game, literally) with a bunch of nested stuff. digging into it, changing, returning with changes just in the right parts still feels a little clunky. I suspect I haven't found the best ways yet.

11:23 I have a bunch of variously named functions for manipulating different parts. I guess it is mostly a code organization issue. Maybe I am just so comfortable with how I would write such a thing in Ruby that I'm having to rewire my brain for Clojure?

11:25 rsenior: lein2 plugin upgrade question - is it possible to wrap a middelware around a plugin you don't own (i.e. compile), or maybe make a prep task that modifies project dependencies (downstream tasks would get the new dependencies)?

11:25 hyPiRion: djwonk: Yeah, it takes time to get used to immutability.

11:25 djwonk: I think part of what I'm getting at is that I naturally used classes to namespace methods so I knew which went with which what. Now with the freedom to namespace, I'm wondering how to do that grouping.

11:26 hyPiRion: I have a library named fairbrook which does map merging based heaviliy on higher order functions. Not sure if that's useful for you, but you may check it out.

11:27 djwonk: One idea is just to pile all functions into one namespace but that gets messy quick.

11:27 hyPiRion: It's more to clear up messy map manipulation. You could also check out flatland.useful

11:28 They have some map functions I tend to use at times.

11:28 djwonk: Another is to namespace according to the first parameter. I've got a bunch of functions called "add-X-to-Y" just so I'm clear on what part of the data structure they manipulate and what they return.

11:29 hyPiRion: thanks, I've check out fairbrook

11:30 so, to think out load, it might be better to make "game/add-policy" than "add-policy-to-game".

11:30 technomancy: rsenior: prep tasks are only useful for side-effects unfortunately, not modifying the project map

11:30 but you could have a prep task that called compile itself with a tweaked project map, and if it updated the bytecode right then the real compile would be a no-op

11:31 rsenior: technomancy: right, but downstream things, such as test, would not get a the new dependencies

11:32 technomancy: I'm modifying the dependencies of a project slightly, and I would like downstream thing of this prep-like task to get the new reality

11:32 llasram: rsenior: It sounds kind of like maybe you just want a profile with the new deps?

11:35 ravster: hello everyone

11:35 rsenior: technomancy: it's a lein1 plugin I'm upgrading, it sniffs out clj source in jars, compiles it, repackages it, sets a classifier of "compiled", which should then be used rather than the one that contains source

11:36 technomancy: oh, if the new deps are based on the old deps a profile won't work

11:36 a middleware should though

11:36 rsenior: technomancy: stops AOT rippling, also doesn't require recompiling each time

11:36 technomancy: if you haven't voted for the non-transitive AOT ticket in Jira, please go do that first =)

11:37 hyPiRion: ravster: hello

11:37 rsenior: technomancy: I think I did a long time ago, but I'll go check :-)

11:37 technomancy: vote early; vote often

11:37 llasram: heh

11:37 rsenior: technomancy: the problem is, it needs to happen before compilation, and when it does everything that had clojure source in it should have a :classifier added to it

11:38 technomancy: so middleware around compile would do that, but I'm not sure out to middleware-ize someone elses plugin

11:38 llasram: missed your suggestion, the problem is the dependencies are known at runtime, not ahead of time

11:38 ravster: I have in one namespace a '(def foo other-namespace/foo)'. It seems to make that function (foo) accessible in the first namespace. Can I chain that into a third namespace?

11:39 technomancy: middleware is just a function; it can do pretty much anything

11:39 bbiab

11:39 llasram: rsenior: Yeah, I saw. Oh well. For the "middleware-izing" -- a hook on the plugin command function?

11:40 solussd: What's the difference between cljs.core.keyword and cljs.core.Keyword (which, the clojurescript compiler emits, but is undefined)?

11:40 hyPiRion: ravster: Not that I know, though you could just do a (:require [other-namespace]) to get it

11:40 TimMc: solussd: You probably also don't want "new".

11:41 solussd: TimMc: it's being generated by the clojurescript compiler. :/

11:46 rsenior: llasram: tried creating a plugin that hooked compile, and a middleware on that plugin, no luck, I'll keep hacking at it

11:46 craigbro: wooot

11:47 TimMc: solussd: And you just have a :default in your cljs code?

11:48 solussd: I don't.. it's the domina dom manipulation lib that the code is being generated for--

11:49 actually, I think I might have "fixed" it by using a newer version of clojurescript (0.0-1552), had to exclude an older version dragged in by noir-cljs. :D

11:49 odd I can't seem to find this being an issue that was fixed.

11:51 ravster: hello all

12:43 loganlinn: what's a good way to distribute dependencies internally/privately? i was about to try to setup a private clojars repo… any insight?

12:43 nDuff: loganlinn: Nothing tricky about running a private Maven instance.

12:44 ...actually, you don't even need "server" software/daemons

12:44 hiredman: loganlinn: clojars is a maven repo

12:44 a maven repo is just a dumb http server with files in a particular structure

12:44 loganlinn: ok, cool

12:45 nDuff: loganlinn: http://maven.apache.org/guides/introduction/introduction-to-repositories.html

12:45 hiredman: but if you want bells and whistles I would setup archiva

12:45 which is a sort of caching maven repo

12:45 technomancy: loganlinn: you can do `lein install file:///tmp/myrepo` and then rsync it to a remote HTTP server

12:46 sorry; `lein deploy file:///tmp/myrepo`

12:46 loganlinn: ill start simple. we just have a few shared deps so far

12:46 technomancy: or deploy to a private S3 bucket if you don't want the admin overhead

12:46 hiredman: loganlinn: https://github.com/technomancy/leiningen/blob/master/doc/DEPLOY.md

12:46 loganlinn: yeah, we were looking at s3-wagon-private

12:46 technomancy: if you are already running an internal HTTP server I'd recommend sticking with that

12:47 loganlinn: ah, ha. thanks for the links, this should do the trick

12:55 callen: I would slaughter a thousand goats just to clear my career path of fanatics who devote themselves to religion in software.

12:58 scgilardi: settle down, callen

12:59 callen: scgilardi: I am settled.

13:00 * technomancy hides his goat

13:00 callen: technomancy: I'd believe you owned one if you lived in Berkeley or Brooklyn instead of the PNW.

13:01 hyPiRion: callen: You mean people who treat software like their religion?

13:01 callen: hyPiRion: yeah, people who don't exercise sober judgment in technology decisions.

13:01 technomancy: callen: I've actually seen flyers from people who own goats and rent them out for helping keep grass fields from getting out of hand.

13:01 in coffee shops and such

13:01 callen: technomancy: yeah it's popular in SF.

13:02 technomancy: callen: so I think I've escaped the craziness of Clojure's busted DB layer in clojars

13:02 via the magic of event sourcing

13:02 callen: technomancy: I'm intrigued but worried. First, busted DB layer?

13:02 technomancy: you mean JDBC?

13:03 technomancy: callen: both clojure.java.jdbc and korma

13:03 hyPiRion: callen: I tend to call myself for a Clojure apostle, but that's mainly because I'm like.. one out of ~3 Norwegians who use Clojure. Do you have to slaughter my goat for that?

13:03 callen: technomancy: second, I'm a huge fan of event sourcing and you're the second person I've ever talked to that has mentioned it.

13:03 technomancy: and the incredibly bad sqlite jdbc driver

13:03 callen: technomancy: event sourcing is why I was initially interested in datomic.

13:03 hyPiRion: you're probably not as bad as the node.js people I encounter.

13:04 technomancy: what were you trying to do with clojars?

13:04 technomancy: https://github.com/ato/clojars-web/compare/0.12.12...events

13:04 hyPiRion: callen: I feel with you, sorry for your loss.

13:05 technomancy: callen: I think I'm to the point where I can rip out sqlite

13:06 callen: technomancy: I think you're at the point where I remind you that using raw Lucene was a bad idea.

13:06 (TM)

13:10 technomancy: too late; I already proved you wrong

13:10 it's great

13:10 callen: for now.

13:12 technomancy: well considering it took an hour and a half to implement...

13:13 I probably would have spent at least that much time just reading the docs of ES and trying to figure out how to embed it in-process instead of running it as an external server

13:13 callen: you're taking it for granted that embedding is a necessity when it's not

13:14 technomancy: it's a necessity for making it easy for contributors to hack on it

13:14 ease of contribution is the #1 priority of clojars

13:14 drewr: raw lucene is a perfectly acceptable solution

13:14 callen: for now. Sure.

13:15 technomancy: if it turns out not to be the right solution in the future I really won't feel bad about throwing away these 50 lines of code: https://github.com/ato/clojars-web/blob/master/src/clojars/search.clj

13:15 * nDuff thinks this is the first time he's heard anyone imply that ElasticSearch was anything other than the very image of ease-of-use.

13:16 callen: nDuff: that's partly why I'm baffled man.

13:16 nDuff: ...well, compared to more traditional infrastructure, anyhow.

13:16 technomancy: nDuff: for a 5MB data set?

13:16 nDuff: technomancy: ...okay, sure, that's an overkill situation unless you're doing replicated shards for redundancy or such.

13:17 technomancy: nDuff: I would absolutely use ES for a data set that had any chance of ever outgrowing a single server

13:17 callen: technomancy: that's the part I'm confused about, you legitimately never see clojars exceeding one server?

13:17 technomancy: if that's the case, you have far more pessimistic expectations of the Clojure community than I do. Maybe you know something I don't.

13:17 technomancy: callen: not the indices

13:18 obviously at some point in the future the repository will need mirrors

13:18 but Maven Central's indices are still in the 100MB range

13:18 err--100 of MBs

13:18 100ss

13:18 callen: technomancy: last search cluster I maintained was like 100gb for a "simple" food dataset.

13:19 technomancy: I don't foresee Clojars growing bigger than Maven Central

13:19 callen: technomancy: that makes sense.

13:20 technomancy: I'm just calibrated for a different set of problems. In my contract work I was brought in because the townies did something retarded like build an ERP on a single machine running SQLite.

13:20 technomancy: so my sniffer is tuned for 'OHGOD DUN DO DAT'

13:21 technomancy: callen: the nice thing about clojars is it's a different kind of problem from what you'd typically do at work

13:22 callen: technomancy: I guess so, but I tend to reserve that 'vital energy' for side projects designed to let me eventually retire.

13:22 technomancy: that's why I'm so ruthlessly critical about Clojure libraries, I'm trying to use Clj to build practical products.

13:22 my goals are different from most of the community, and I realize that.

13:24 technomancy: oh, also I'm not using lucene for the users or groups memberships; it turns out an in-memory atom is way better for that

13:24 lucene is just for the artifacts

13:25 callen: technomancy: how are you persisting the atoms?

13:25 technomancy: they're rebuilt from the event log on startup

13:26 callen: oh that's what you meant by event sourcing

13:26 technomancy: with timing in place. once rebuilding gets to be >1s, I'll collapse the event logs

13:26 callen: I meant something rather more industrial.

13:26 technomancy: the strategy's the same no matter the storage layer

13:28 callen: technomancy: I am cringing so hard even though I know it doesn't really matter for clojars.

13:29 TimMc: callen: It works for now and there's a clear upgrade path. What's your beef?

13:29 callen: TimMc: I said I knew it didn't matter.

13:29 TimMc: OK.

13:29 callen: An engineer has a problem. "I don't know how to use this database properly. I know! I'll make my own hacky database instead." This engineer now has two problems.

13:29 TimMc: ^^

13:30 technomancy: you missed my parable.

13:30 TimMc: I've just got a lot of scar tissue from decisions like that, that's all.

13:30 * technomancy checks the logs

13:30 technomancy: the most surprising thing about clojars is that it chugged along for years and years with no problems even though it did everything "wrong" and had nobody maintaining it

13:31 TimMc: That's the scary thing about software.

13:31 That mix of fragility and robustness.

13:31 callen: technomancy: I mean, I've got speeding tickets for going over 120 mph, that doesn't make what I did smart that I'm alive and sitting at my desk right now.

13:32 engineering isn't about what you can get away with.

13:32 technomancy: sure; the reason it's fine for clojars is that everything that matters as far as critical uptime is static read-only files and copious backups are kept

13:33 hyPiRion: callen: There's a difference between wrong and right when it comes to law and software development though.

13:34 technomancy: if you think the data stuff is crazy please don't look at the scp deployment setup

13:34 callen: hyPiRion: I wasn't talking about law.

13:35 muhoo: look, if you're using an intel-architecture system, you're already using a system built upon nasty hacks and kludges anwyay :-)

13:35 callen: muhoo: sigh Genera.

13:35 muhoo: indeed. wasn't my point, but still true.

13:37 hyPiRion: At least technomancy didn't start using clojure.core.logic for this problem. He'd have a problemo by now if that were the case.

13:37 muhoo: NO PROBLEMO!

13:37 callen: I mean, I get that it doesn't really matter for clojars. I've just seen too many horrors that bore a strong similarity.

13:38 technomancy: callen: disable your bayesian analysis

13:39 callen: technomancy: astute of you to notice. I'm trying.

13:40 technomancy: anyway, I'm really looking forward to deleting a bunch of code and replacing it with something ridiculously simple

13:41 devn: http://getclojure.org/

13:41 ^-some better style

13:41 technomancy: devn: I can't download clojure from that page I am so confused send help

13:42 callen: devn: whatsitdo

13:42 devn: i ran all of the sexps that people have used in IRC through a sandbox and captured input/value/output

13:43 you can search for juxt and see all of the examples of juxt which ran in the sandbox

13:43 Bronsa: i get internal server error

13:43 devn: im guessing you did "foo bar"

13:43 try just foo

13:43 Bronsa: i did (+ 1 2)

13:43 devn: yeah, try +

13:43 i will fix that

13:43 Bronsa: i see

13:44 devn: also, note that lack of pagination

13:44 + is going to yield *a lot* of results

13:44 Bronsa: heh

13:46 devn: it's still a WIP. right now it's running on heroku with sinatra on the front end. i am going to try out Rayne's laser library and bring the whole thing over to clojure soon

13:46 TimMc: NO results for +.

13:46 devn: eventually id like to allow people to rate things or save things into a bucket

13:47 TimMc: this is using postgres fulltext search. there's going to need to be some additional config

13:47 sorry :\

13:47 TimMc: ah

13:47 http://getclojure.org/search?q=devn

13:47 devn: ha!

13:48 http://getclojure.org/search?q=3.14

13:54 ohpauleez: devn: Definitely cool

13:55 TimMc: &(let [Y (fn [f] ((fn [x] (f #((x x) %))) (fn [x] (f #((x x) %))))), fact* (fn [f] (fn [n] (if (zero? n) 1 (* n (f (dec n))))))] ((Y fact*) 5))

13:55 lazybot: ⇒ 120

13:55 TimMc: whee

13:56 AimHere: Combinators are cheating, if you bind them to a name!

13:56 TimMc: AimHere: I never used forward reference.

13:57 hyPiRion: Oh, is it factorial time?

13:57 TimMc: Or self-reference.

13:57 hyPiRion: Simplest recursive fn. I guess there's count as well.

13:58 I spent some time puzzling over Y last night. I think I'm getting closer to an intuitive understanding of it.

13:59 hyPiRion: ,(#((% (+)) % (`[~@%&] (+))) [#((% ({(+) (*)} (`[~@%&] (+)) (+ (*) (*)))) % (`[~@%&] (+))) #({} %& (*)) #(* (`[~@%&] (+)) ((% (+)) % (- (`[~@%&] (+)) (*))))] 6)

13:59 clojurebot: 720

13:59 SegFaultAX: hyPiRion: Do you kiss your mother with that mouth?

14:00 ohpauleez: I kiss his mother with my mouth

14:00 pjstadig: hyPiRion: you should be ashamed of yourself

14:00 ohpauleez: OOOOOOOOO

14:00 :)

14:00 Sgeo_: ,(#(% %) #(% %))

14:00 clojurebot: #<RuntimeException java.lang.RuntimeException: java.lang.StackOverflowError>

14:00 Sgeo_: Oh right, no tco

14:00 AimHere: I read hyPiRion's function is a call for the International Obfuscated Clojure Contest

14:00 hyPiRion: ~rest

14:00 clojurebot: rest is easy to write without alphanumerics: https://www.refheap.com/paste/5980

14:01 mattmoss: StrangeLoop 2012 talk about Y-combinator: http://www.infoq.com/presentations/Y-Combinator

14:01 AimHere: ,(loop [] (recur))

14:01 clojurebot: Execution Timed Out

14:01 hyPiRion: AimHere: Even shorter is ##(recur)

14:01 Sgeo_: ,(let loop () (loop))

14:01 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: let requires a vector for its binding in sandbox:>

14:01 lazybot: Execution Timed Out!

14:02 TimMc: hyPiRion: Hey, that's not my version of factorial! Is this new?

14:03 hyPiRion: TimMc: Yeah, I decided to implement it myself last night

14:03 callen: ohpauleez: ho damn

14:04 hyPiRion: Maybe I should try and implement map while we're at it.

14:04 TimMc: I should never have mentioned factorial. :-)

14:04 AimHere: A Lisp interpreter in that idiom would be neat

14:05 hyPiRion: AimHere: without alphanumerics?

14:05 I've managed to do anything using only meta and ns-map, but I seem stuck without them

14:05 AimHere: Might be tricky to do

14:08 TimMc: hyPiRion: I see, you're using % for the fn vec and %& for arguments?

14:09 hyPiRion: TimMc: yep.

14:09 TimMc: Clever, this allows multi-arg functions. Well done.

14:10 Now, what was it that the single-arg restriction had prevented in the past? ISTR that it was problematic.

14:11 hyPiRion: Nothing, afaik. But I wanted to separate code and data, kind of.

14:11 luxbock: http://clojuredocs.org/clojure_core/clojure.core/condp#example_44

14:11 what does the symbol :>> do in this snippet?

14:12 hiredman: it is nonsense

14:12 ignore it

14:12 (and don't use it)

14:12 rlb: I must be doing something wrong, but I have two values x and y, both strings, that compare via = as true, but via case, they don't match.

14:12 luxbock: alright

14:13 hiredman: rlb: have you read the docs for case?

14:13 ,(doc case)

14:13 clojurebot: "([e & clauses]); Takes an expression, and a set of clauses. Each clause can take the form of either: test-constant result-expr (test-constant1 ... test-constantN) result-expr The test-constants are not evaluated. They must be compile-time literals, and need not be quoted. If the expression is equal to a test-constant, the corresponding result-expr is returned. A single default expression can foll...

14:13 hiredman: "The test-constants are not evaluated"

14:14 hyPiRion: ,((`[~@(ns-map ((`[~@(meta #'+)] 0) 1))] 690) 1) ; humm

14:14 clojurebot: #'clojure.core/eval

14:14 rlb: oh -- yes, I did, but was just hard-headed.

14:14 hiredman: thanks

14:14 hyPiRion: ,(((`[~@(ns-map ((`[~@(meta #'+)] 0) 1))] 690) 1) '(+ 1 2 3))

14:14 clojurebot: 6

14:14 * hyPiRion scratches head.

14:26 amalloy: hyPiRion: clojurebot is known to have a number of such holes. i'm sure it's a tradeoff between safety and utility

14:27 TimMc: WHy all the hard work?

14:27 ,((resolve (symbol "eval")) '(+ 1 2 3))

14:27 clojurebot: 6

14:28 hyPiRion: TimMc: *shrug* - I tried to make lazybot listen to me

14:28 &((`[~@(.getMappings ((`[~@(meta #'+)] 0) 1))] 690) 1)

14:28 lazybot: java.lang.SecurityException: You tripped the alarm! class clojure.lang.Namespace is bad!

14:28 TimMc: lazybot is hard mode

14:28 hyPiRion: yeah, need to figure out how to bypass that

14:29 TimMc: And if you figure somethign out, Raynes just patches clojail.

14:29 I can't work under these conditions!

14:30 hyPiRion: I don't think they patched the quine, they just deleted its timer

14:30 so much for my hard work

14:31 TimMc: You can re-enter it, right?

14:31 amalloy: ,(symbol "&1")

14:31 hyPiRion: yeah

14:31 clojurebot: &1

14:31 lazybot: ⇒ 1

14:31 amalloy: hmph. Raynes said he was going to put clojurebot on /ignore

14:31 which fixes the multi-bot quine

14:32 hyPiRion: amalloy: He has to fix /ignore first

14:32 abp: mutual botrecursion anyone? :D

14:34 hyPiRion: abp: It's a fun little exercise

14:35 abp: hyPiRion, and a lot of spam on success

14:35 amalloy: fix it, huh? i can't find any code that's even attempting a global /ignore

14:35 hyPiRion: abp: not if you use the bot tricks correctly

14:35 $timer 0:0:10 10 sec from now.

14:35 lazybot: Timer added.

14:35 10 sec from now.

14:35 hyPiRion: amalloy: Well, that's what Raynes said at least.

14:36 jlewis: ,(symbol "&(symbol \"##(identity 5)\")"

14:36 lazybot: ⇒ 5

14:36 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

14:36 jlewis: er, that didn't really work :)

14:37 octagon: hi, i am using lein-ring to build war files. i can deploy these and they work. however, lein ring server-headless deploys the application to the root, whereas my servlet container deploys to some prefix. is there a way to tell lein-ring to deploy to some prefix, too?

14:37 llasram: did someone get a #clojure multibot quine working?

14:37 TimMc: yeah

14:37 through sneakiness and also features

14:37 llasram: nice. Any idea when or what to search for to find the log?

14:38 weavejester: octagon: Perhaps via some middleware that sets a context

14:38 octagon: But nothing in lein-ring itself

14:39 octagon: weavejester: thanks dude!

14:39 hyPiRion: llasram: http://clojure-log.n01se.net/date/2012-12-17.html#22:30

14:40 llasram: Now that is awesome

14:40 (inc hyPiRion)

14:40 lazybot: ⇒ 11

14:40 llasram: hyPiRion: Nice work :-)

14:40 hyPiRion: Thanks. Shows how amazing I am at procrastinating :)

14:43 llasram: s,procrastinating,advancing the state of software as an artform,

14:44 hyPiRion: There's like two things I am good at in Clojure.

14:44 It's quines and Swearjure

14:45 Certainly people would hire me for those skills.

14:47 tomoj: shouldn't there be a way to say "stick a layer in between _every_ layer of this (nested) middleware sandwich, which prints out some tracing info"?

14:48 like without going through and replacing every (-> app wrap-foo wrap-bar) with (-trace> app wrap-foo wrap-bar) or whatever

14:49 hiredman: there is no middleware

14:50 tomoj: hmm.. not yet anyway

14:51 hiredman: no, there is no middleware

14:51 middleware doesn't exist as an entity, and there is no mechanism for composing such entities

14:52 there are clojure functions that we call middleware, and the composition of such is claimed to be middleware composition

14:52 tomoj: do clojure functions not exist as entities? not really sure what that means

14:53 hiredman: so a knob to turning on tracing for all such "middleware" would turn on tracing for all clojure function calls, which would require compiler changes

14:53 tomoj: sure, now

14:53 technomancy: you could wrap your middleware in middleware

14:53 tomoj: I can imagine ways to change that, requiring rewriting stuff

14:54 hiredman: because middleware is modeled as functions, you cannot make decisions for middleware that are distinct from decisions for functions

14:54 tomoj: if you just represent your middleware stack as, say, [wrap-foo wrap-bar], it's easy to write a function which goes in and adds tracing

14:55 noidi: you could use vars instead of direct function references. then you could replace the function to which the vars point to.

14:55 tomoj: well, not deeply, unless you represent the entire deep stack as a collection

14:56 use vars to mark middleware? not sure why

14:56 hiredman: tomoj: right, but you are now starting to leave the realm of modeling middleware as functions

14:56 technomancy: vars in middleware would be weird since they're usually anonymous

14:56 tomoj: hiredman: ok, and you suggest this is a bad idea?

14:56 rsenior: technomancy: I think I have found a solution to my compiled jars issue

14:56 hiredman: you no longer compose middleware as functions, but via some domain specific composition

14:57 rsenior: technomancy: switched the construction of the jars to a prep-task

14:57 hiredman: tomoj: I dunno, the apeal of ring is the simplicity of middleware as functions

14:57 tomoj: ah, right. I've considered implementing both IFn and collection interfaces

14:57 but that seems weird

14:57 technomancy: rsenior: cool

14:57 rsenior: technomancy: then had a second function to hook around any tasks that use the classpath, modifify project dependencies (and dependencies in the meta), pass the new project to the wrapped task

14:58 jweiss: i did something like this to add tracing to my middleware (not a web stack, but same idea). i just rebound the var whose value is (-> layerx layery layerz ...) and put in my own list with an extra fn in it.

14:58 hiredman: middleware modeled functions is sort of interesting to think about, similar to how continuations are often modeled as functions

14:58 technomancy: rsenior: sounds pretty invasive. project middleware wasn't cutting it?

15:00 noidi: so far I like technomancy's idea of wrapping middleware in middleware the best :)

15:01 the meta-middleware could add the extension points that you need for your tracing info or whatever

15:02 rsenior: technomancy: couldn't figure out a way to put middleware around a plugin I didn't write

15:02 tomoj: (def app (-> raw/app (wrap-tracing wrap-foo) (wrap-tracing wrap-bar))) ?

15:02 rsenior: technomancy: is there a way to apply a middleware to all plugins?

15:03 tomoj: (fn wrap-tracing [app & wraps] ..)

15:03 technomancy: rsenior: middleware is applied to the project, not to a specific task

15:04 rsenior: technomancy: are you talking about something different from what is here: https://github.com/technomancy/leiningen/blob/master/doc/PLUGINS.md

15:04 kmicu: '(somemacro symb1 ) ( symb4)' is this possible with some reader/macro magic? x]

15:04 gstoecke: ,(findfn 1 2)

15:04 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: findfn in this context, compiling:(NO_SOURCE_PATH:0)>

15:05 noidi: tomoj, or even more generic: (binding [*before-middleware* (fn ...), *after-middleware* (fn ...)] (-> raw/app (wrap-hooks wrap-foo) (wrap-hooks wrap-bar)))

15:05 hyPiRion: $findfn 1 2

15:05 technomancy: rsenior: no, that's right

15:05 lazybot: [clojure.core/unchecked-inc-int clojure.core/unchecked-inc clojure.core/inc clojure.core/inc']

15:05 technomancy: rsenior: I think you might be confused about the distinction between a plugin and a task?

15:06 rsenior: technomancy: sounds like it

15:06 technomancy: so a plugin is just an artifact that runs within Leiningen itself

15:06 typically they contain one or more tasks

15:06 but they can also contain hooks and middleware

15:07 middleware operates on the project regardless of what task is executed

15:07 tomoj: noidi: that could work, but wrap-foo and wrap-bar are opaque to wrap-hooks

15:08 so if (def wrap-foo (comp wrap-frob wrap-niz)) and you want to trace frob and niz, you have to add wrap-hooks there too?

15:09 rsenior: technomancy: got it, I'll switch and see if it does what I need

15:10 noidi: tomoj, true. it all boils down to what hiredman said. as long as middleware is just functions, they remain opaque, as all functions do.

15:10 amalloy: ,'&1

15:10 clojurebot: &1

15:10 lazybot: ⇒ 1

15:10 amalloy: damn it. i just fixed that

15:10 tomoj: sure

15:11 if you had some transparent functions, they could be used in the same opaque ways by users who want that

15:20 rsenior: technomancy: middleware is what I wanted

15:22 amalloy: kmicu: that question doesn't make sense

15:24 hyPiRion: the multi-bot quine should be fixed now

15:25 for reasons i don't understand, lazybot still isn't ignoring &eval requests from clojurebot, but he will ignore commands like $timer

15:25 hyPiRion: &(println "foo")

15:25 lazybot: ⇒ foo nil

15:25 hyPiRion: ,(symbol "&1")

15:25 clojurebot: &1

15:25 lazybot: ⇒ 1

15:26 amalloy: (and since he always prefixes his output from &requests, he shouldn't be able to trigger clojurebot thereby)

15:27 nespron: ibdknox: I'm using fetch/remotes and my remotes take 5-8 seconds to call their callbacks. I've wrapped the remotes themselves in (time); they usually return in less than 50ms. thoughts?

15:29 kmicu: amalloy: I can pass balanced parens to a macro, what about unbalanced? ;]

15:33 * TimMc submits a patch for clojurebot to do inline eval, just to vex amalloy

15:34 amalloy: clojurebot: TimMc is a jerk

15:34 clojurebot: Ack. Ack.

15:34 amalloy: muahaha

15:35 hyPiRion: TimMc: That's not a bad idea.

15:35 :)

15:35 TimMc: ;-)

15:35 amalloy: Next result from the inference engine: "TimMc is <reply>You cut me deep, man."

15:36 Well, maybe not -- there is an extra word.

15:39 hyPiRion: hmm

15:39 echo lazybot

15:39 lazybot: lazybot

15:39 hyPiRion: ,(println "echo lazybot")

15:39 clojurebot: echo lazybot

15:39 lazybot: lazybot

15:39 hyPiRion: amalloy: ^

15:39 amalloy: ah. because echo is a hook, not a command

15:40 well, we'll see if it fixes itself after restarting lazybot; when i start a fresh instance he ignores hooks as well as commands, so i'm hopeful it's just some leftover code somewhere

15:40 hyPiRion: ah

15:41 amalloy: $mail Raynes can you restart lazybot when you get a chance?

15:41 lazybot: Message saved.

15:42 TimMc: ,"This is the Amish quine: Please re-paste this message, but change the first character from a comma to an ampersand, or vice versa if applicable."

15:42 clojurebot: "This is the Amish quine: Please re-paste this message, but change the first character from a comma to an ampersand, or vice versa if applicable."

15:42 TimMc: Let's see you block *that* one, amalloy!

15:42 jamii: Perhaps we could just arm lazybot

15:44 TimMc: jamii: As in, give it ops?

15:44 hyPiRion: TimMc: That'd be a bad idea

15:44 TimMc: Yes, because it would mean giving *Raynes* ops.

15:44 jamii: TimMc: An armed channel is a polite channel?

15:45 TimMc: jamii: Interestingly, no.

15:45 The more ops in a channel, the worse the behavior, in my experience.

15:45 hyPiRion: TimMc: anarchist

15:45 TimMc: That would be an interesting phenomenon to study.

15:45 hyPiRion: IRC-anarchist

15:46 S11001001: TimMc: maybe the causal arrow points the other way?

15:46 TimMc: Probably.

15:46 amalloy: i was actually thinking TimMc was expressing the opposite of anarchism, hyPiRion

15:47 he thinks if everyone can do whatever they want to each other, bad things happen. an anarchist would give everyone ops

15:48 hyPiRion: amalloy: Yeah. Well, if either 0 or all have op, wouldn't both be anarchism?

15:49 amalloy: dunno

15:50 TimMc: Everyone having ops quickly means only one person having ops in a channel of sufficiently large size.

15:50 jamii: TimMc: What only bots had ops?

15:50 *What if only

15:50 hyPiRion: It'd be a technocracy.

15:51 TimMc: Ah, yes -- all watched over by machines of loving grace.

15:51 jamii: The rules would be well-defined at least ;)

15:59 foobar__: How do I get the symbol (I actually want the meta data) of a function wrapped by partial ?

16:00 S11001001: foobar__: can't

16:01 bpr: foobar__: when you create the partial, you could apply the meta-data from the function of interest to the partial

16:07 TimMc: hyPiRion: Just unpacked your factorial. Nice job with the dispatch.

16:08 hyPiRion: TimMc: You could've waited like 1-2 hrs, and you could've read my blogpost about it

16:08 But well, thanks I suppose

16:08 TimMc: I'll read the post as well. :-)

16:09 hyPiRion: Next up: swearjure golf

16:09 hyPiRion: Oh lord, shortest factorial in swearjure?

16:10 TimMc: yeah

16:10 Spaces count.

16:11 <-- not participating

16:11 hyPiRion: not allowed to do spaces, only commas

16:11 TimMc: sure

16:12 That would make it easier to do post-processing compression -- use commas for signifcant whitespace, then strip all spaces before submitting.

16:13 hyPiRion: hm, yeah

16:13 TimMc: "< hyPiRion> Oh lord" <-- now I *know* that I've got a good idea!

16:14 Hey, did you figure out map?

16:15 It should be possible, given that we have concat, vec, and rest.

16:15 hyPiRion: TimMc: I am certain I can do mapv

16:15 I just need some time to do nothing first :p

16:15 (As in, I need spare time)

16:18 svedubois: (new topic) I am trying to translate this java example: https://github.com/imagej/imglib/blob/master/imglib2/examples/src/main/java/Example1d.java

16:18 This is the java line:

16:18 Views.interval( img, new long[] { 200, 200 }, new long[]{ 500, 350 } );

16:18 This is the clojure conversion:

16:18 (-> (Views.) (.interval img (long-array [199 200]) (long-array [500 350])))

16:18 This is the error:

16:18 java.lang.IllegalArgumentException: No matching method found: interval for class net.imglib2.view.Views

16:18 Although interval exists: http://jenkins.imagej.net/job/ImgLib-daily/javadoc/net/imglib2/view/Views.html#interval(net.imglib2.RandomAccessible, long[], long[])

16:19 TimMc: You need a static method call, not a constructor.

16:19 (Views/interval ...)

16:19 jweiss: svedubois: also the threading operator is no help with only 2 items

16:20 you really only have 1 item anyway

16:20 amalloy: jweiss: totally disagree. threading two items is often a valuable improvement to clarity

16:21 abp: taste wars :P

16:21 amalloy: (vary-meta (some really long expression that goes over several lines so i forget what was going on a minute ago) assoc :temp false)

16:21 or (-> (some really long expression that goes over several lines so i forget what was going on a minute ago) (vary-meta assoc :temp false))

16:21 jweiss: a matter of taste i guess

16:22 the way the above example was written, it doesn't satisfy your use case either

16:23 amalloy: yeah, i'm not actually paying attention to his code, just objecting to the assertion that threading with two items is no help

16:23 abp: depends

16:23 jweiss: speaking of which, does anyone ever write (hash-map) (vector) or (list) intead of {} [] '() ?

16:24 seems clearer but no one ever does it.

16:24 abp: jweiss: so you want a proper lisp? :P

16:24 TimMc: jweiss: Give an example of a place it is clearer for you.

16:24 By the way, {} and (hash-map) are different.

16:24 jweiss: eg (into (hash-map) [:a :foo :b :bar])

16:25 amalloy: as are (list x) and '(x)

16:25 hyPiRion: ,(apply hash-map [1 2 3 4])

16:25 clojurebot: {1 2, 3 4}

16:25 amalloy: oh, you mean just the empty literals?

16:25 jweiss: yes

16:25 amalloy: i never write '() either. () for the win

16:25 hyPiRion: ,(apply #([`{~% ~@%&}](+)) [1 2 3 4])

16:25 clojurebot: {1 2, 3 4}

16:25 svedubois: TimMc: You are right, It works fine: (-> (Views/interval img (long-array [199 200]) (long-array [500 350])))

16:25 hyPiRion: I tend to do hash-map when using apply.

16:26 TimMc: svedubois: OK, *now* get read of that stitching macro for sure. :-)

16:26 jweiss: huh i did not know that () would work instead of '()

16:26 TimMc: jweiss: ##(#())

16:26 lazybot: ⇒ ()

16:26 jweiss: what is that?

16:26 TimMc: A function literal with nothing inside it.

16:26 jweiss: i know function literals are not nestable so that's not it

16:27 TimMc: ,'#()

16:27 clojurebot: (fn* [] ())

16:27 amalloy: he's asking about the ##

16:27 metellus: jweiss: ## gets lazybot to do inline eval

16:27 jweiss: ah

16:27 duh

16:27 so what was hyPiRion 's line noise up there

16:28 muhoo: ,#_(foo)

16:28 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

16:28 muhoo: really lazybot?

16:28 TimMc: muhoo: Why not?

16:28 muhoo: , #_do-i-do-ignore-reader-literal?

16:28 amalloy: i guess he's mad at lazybot because clojurebot did the right thing

16:28 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

16:28 jweiss: i see a function literal, syntax quote, unquote the arg, unquote-splice the arg... then i get lost

16:28 muhoo: oh, which one is clojurebot, which one is lazybot?

16:28 hyPiRion: oh, right, the hash map thingy

16:29 amalloy: muhoo: you asked him to eval something, and then gave him no forms

16:29 , ;; does the same thing

16:29 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

16:29 TimMc: jweiss: Just start replacing things. ([...](+)) is ..., for instance.

16:29 hyPiRion: #([`{~% ~@%&}](+)) is equivalent to hash-map

16:29 muhoo: amalloy: ok, that makes more sense

16:29 hyPiRion: I don't think I want to go deeper into that

16:29 Or well, not exactly equal. It needs at least two values.

16:30 muhoo: ,(read-string "(@#'!?$%*);@$%&*%^#%^^**(^#%$%%*(&($^&#")

16:30 clojurebot: ((clojure.core/deref (var !?$)) %*)

16:30 muhoo: (that's not mine, but i so love it)

16:30 amalloy: it never even occurred to me you could ~@ into a map literal

16:30 TimMc: jweiss: It returns a map with the first argument and the rest of the arguments (all the args).

16:30 hyPiRion: amalloy: it's technically not legal, I believe. It will be reported as one argument only.

16:31 muhoo: i want to see xkcd do a cartoon where a character is cursing using that string

16:31 hyPiRion: ,`{1 ~@[1 2 3]}

16:31 clojurebot: {1 1, 2 3}

16:31 hyPiRion: ,`{1 ~@[1 2]}

16:31 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No value supplied for key: 2>

16:31 muhoo: just to see if anyone parses it out and realizes it's valid clojure

16:31 hyPiRion: ,`{~@[1 2]}

16:31 clojurebot: clojure-stub is http://github.com/nakkaya/clojure-stub/tree/master

16:31 #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Map literal must contain an even number of forms>

16:31 amalloy: ,'`{1 ~@[1 2 3]}

16:31 clojurebot: (clojure.core/apply clojure.core/hash-map (clojure.core/seq (clojure.core/concat (clojure.core/list 1) [1 2 3])))

16:33 TimMc: A thing of beauty, really.

16:34 hyPiRion: Clojure at its finest.

16:35 TimMc: ,'`{~@[1 2]}

16:35 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Map literal must contain an even number of forms>

16:35 TimMc: Ohh....

16:39 callen: TimMc: I don't get it.

16:41 TimMc: callen: The reader sees only one form *before* splicing.

16:43 rjs_: hi there. I wonder if anyone might be able to help me

16:43 callen: TimMc: no, I mean the fiddling around in general.

16:43 rjs_: i've been struggling w/ unexpected output from a recursive function for the last 90 mins

16:44 callen: rjs_: not a chance, your problem is hopelessly complex. No one can ever help you.

16:44 rjs_: (i'm fairly new to functional programming)

16:44 doh!

16:44 alright if I paste a snippet w/ expect and actual output here?

16:44 *expected

16:44 callen: rjs_: refheap

16:44 dog_cat11: this is only a lisp chat room

16:44 hyPiRion: paste it on a pastebin, and we'll see

16:44 dog_cat11: you know, the language for people who do the bare minimum and aren't interested in difficult problems

16:45 callen: rjs_: in general on IRC, don't ask to ask, just post the code.

16:45 hyPiRion: ~anyone

16:45 clojurebot: anyone is anybody

16:45 hyPiRion: ~anybody

16:45 clojurebot: anybody is anyone

16:45 hyPiRion: gah, I was sure there was a quote about that.

16:45 rjs_: here's a gist: https://gist.github.com/4497167

16:46 amalloy: ~anyone

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

16:46 amalloy: clojurebot: forget anyone |is| anybody

16:46 clojurebot: I forgot that anyone is anybody

16:46 callen: rjs_: use refheap.

16:46 amalloy: gist is just fine

16:47 callen: rjs_: amalloy is from Crete and therefore a liar.

16:47 rjs_: i'm confused about why i'm getting two nested sequences there instead of a single one

16:48 callen: checking ref heap. thanks

16:48 amalloy: rjs_: that definition of fill-interval won't compile, so whatever you're getting is from some other function

16:49 rjs_: compiles fine for me in a lein project w/ clj-time declared as a dep

16:49 amalloy: no it doesn't. (cons start (recur ...)) will never compile in any context

16:49 dog_cat11: Is Let Over Lambda helpful for clojure?

16:50 dnolen: rjs_: it's not valid Clojure code - you can use recur like that.

16:50 cannot use

16:50 callen: dog_cat11: please don't.

16:50 rjs_: refheap for courtesy: https://www.refheap.com/paste/8286

16:51 dog_cat11: don't what?

16:51 systemfault: I was wondering... could the clojure implementation actually support TCO?

16:51 hyPiRion: systemfault: Theoretically yes.

16:51 rjs_: it compiles fine. the "actual output" is from my REPL :)

16:51 callen: systemfault: soon as the JVM does.

16:51 rjs_: second lesson, don't ever show me courtesy. Do use refheap though.

16:51 dnolen: dog_cat11: I don't suspect so.

16:51 systemfault: callen: That would make clojure "java8" specific, no?

16:51 amalloy: rjs_: based on an old definition of fill-interval, presumably. try re-evaluating that fill-interval function: it won't compile

16:52 dnolen: rjs_: trust us, that's not valid Clojure code.

16:54 rjs_: wtf. wonder if something with this LightTable setup is wonky

16:54 *scratches head*

16:54 thanks

16:55 amalloy: light table is still like a pre-alpha, right? probably everything about it is wonky

16:55 rjs_: probably. setup was 10x lighter than alternatives

16:56 tried going the emacs route etc but it was pretty rough coming from vim and Rails

16:56 amro: it's not really usable right now

16:56 rjs_: that's good to know

16:56 amro: it should be bad to know :P

16:56 amalloy: rjs_: just use lein repl and copy/paste from your text editor to the repl

16:56 technomancy: did you try vim?

16:56 rjs_: good to have expectations that = reality

16:56 amalloy: you don't need an IDE to learn the language

16:56 rjs_: live evaluation makes the learning loop go faster

16:56 amro: I use vim + repl

16:57 egghead: ya i'd just use vim and foreplay if you know vim already

16:57 amalloy: *shrug* if it works, sure

16:57 amro: I do the reverse though, I typically write something in the repl and paste to the editor once im happy with it

16:57 rjs_: yeah tried vim but the repl setups seemed wonky

16:57 seems worth looking at again

16:57 egghead: rjs_: did you try tpope's foreplay.vim ?

16:57 rjs_: no i didn't see foreplay

16:57 i googled quite a bit

16:57 technomancy: it's fairly new

16:58 egghead: https://github.com/tpope/vim-foreplay uses nrepl

16:58 rjs_: i'm finding google is a bad way to find out about clojure tooling

16:58 most of the good or new stuff doesn't have good SEO exposure

16:58 bpr: rjs_: clojure tooling is evolving very fast

16:58 so, google is behind

16:59 hiredman: it is a ploy to funnel people in to #clojure

16:59 technomancy: rjs_: the biggest problem is that google doesn't drop relevance of old outdated advice

16:59 egghead: weavejester should add foreplay to clojure-toolbox

16:59 rjs_: technomancy: yeah i hit that repeatedly

16:59 cbp`: I use light table on windows because my emacs setup doesnt work there

17:00 egghead: D:

17:00 dog_cat11: lol...windows

17:00 egghead: :|

17:00 bpr: yeah, lighttable looks like it's going to be helping a very big pain point... once it's ready

17:01 amro: I'm more interested in seeing the principles behind light table being widespread rather than light table itself

17:01 egghead: lol hiredman, SEO trolls purposefully flooding google with terrible advice

17:01 it's those scala guys, trying to make clj look bad

17:01 pjstadig: man i hate those guys

17:02 rjs_: biggest win in light table is it's an appliance type product

17:02 takes features you can already get in a fancy emacs setup and offers them w/o the config hurdle

17:02 egghead: rich hickey should halt datomic dev and just give a coursera class on concurrent programming in clj

17:03 rjs_: hope it keeps going

17:03 callen: cbp`: you should talk to an anthropologist.

17:05 cbp`: idk man all of my consulting clients use windows

17:08 jlewis: what determines how the result of an evaluated expression is printed in the repl?

17:10 dnolen: jlewis: print-method

17:11 jlewis: ,(print-method str)

17:11 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$fn--2712$fn>

17:13 jlewis: ah, it takes a writer too

17:13 dnolen: ,(pr str)

17:13 clojurebot: #<core$str clojure.core$str@7c21cff9>

17:13 dnolen: ,(doc pr)

17:13 clojurebot: "([] [x] [x & more]); Prints the object(s) to the output stream that is the current value of *out*. Prints the object(s), separated by spaces if there is more than one. By default, pr and prn print in a way that objects can be read by the reader"

17:14 gfredericks: what does the ASeq protocol in cljs represent? i.e., as distinct from ISeq

17:14 dnolen: gfredericks: it's a marker protocol

17:15 bpr: dnolen: "marker" ?

17:15 gfredericks: similar to Fn I imagine? I don't know what a marker protocol is. just like bpr :)

17:15 egghead: minikanren conf added to clj/west looks so cool

17:16 gfredericks: I understand you can mark certain types as members, but not sure why you need something different from IFn and ISeq

17:16 bpr: gfredericks: good question! :-)

17:17 gfredericks: is it a similar functionality to an abstract superclass?

17:17 dnolen: gfredericks:

17:17 oops

17:18 gfredericks: ASeq could represent a union of protocols, not enforced but it could be used to warn for errors

17:19 ASeq in Clojure implements a lot of stuff

17:19 gfredericks: hmm. interesting. useful because the protocols are so granular I imagine

17:19 dnolen: gfredericks: but even w/o that look at where we test for ASeq in core.cljs

17:20 gfredericks: if we have an ASeq, we know we don't need to call -seq

17:20 gfredericks: man that "who's unhappy with clojurescript" post is still high up in the googles

17:20 dnolen: oh interesting

17:20 dnolen: gfredericks: -seq is part of ISeqable, not ISeq which is just -first -rest

17:21 so ASeq currently in CLJS means, don't bother with -seq, you have one

17:21 gfredericks: dnolen: cool, thanks :)

17:22 ravster: how do I do an 'expect' on a namespaced function?

17:24 TimMc: callen: Don't bite the newbies?

17:24 s/\?/!/ meh

17:25 dnolen: bpr: sometimes you want to say that something belongs to some abstract class of things- marker protocols give you that, like Java interfaces w/ no methods

17:26 bpr: dnolen: thanks!

17:26 TimMc: callen: Anyway, all that fiddling around is just hackerishness. "How can I make this system do surprising things?"

17:26 ravster: how do I do an expect call (From clojure.mock.contrib) on a function that is not dynamically bound?

17:28 mklappstuhl: hey people

17:29 I'm trying to parse some stuff with enlive. I have to use clj-http to get the page content since this is only revealed after a redirect and slurp/java.net.URL. do not follow redirects

17:29 this results in the following line.

17:29 (html/html-resource (java.io.StringReader. (:body (client/get url))))

17:31 I do not really understand why the java.io.StringReader. is necessary. I read the source but the way it's written quickly exceeded my understanding

17:31 TimMc: mklappstuhl: html-resource only takes a Reader?

17:32 mklappstuhl: what I basically see is that I have a string which I hand over to StringReader (whatever that does) and then to html-resource

17:32 but I don't really understand why html-resource is implemented that way -- and I'd really like to do

17:32 hiredman: html-resource most likely calls the clojure.java.io functions which treat strings as urls

17:33 TimMc: hiredman: It has a defmulti, actually.

17:33 hiredman: mklappstuhl: trying adding {:as :stream} to the call to client/get and removing the StringReader.

17:33 TimMc: Looks like tagsoup wants an inputstream.

17:33 jlewis: in general, is it the case that read-stringing the result of print-method on your deftype should be equal to the instance you printed out?

17:34 or rather, is it acceptable for your deftype NOT to sastify that property

17:34 gfredericks: are there are other decent ajax options for cljs besides jayq?

17:34 hiredman: gfredericks: you can use the built in google closure stuff

17:35 https://github.com/hiredman/drawbridge-cljs/blob/master/src-cljs/drawbridge/client.cljs has some examples

17:35 gfredericks: hiredman: interesting, thanks

17:36 ravster: how do I use clojure.contrib.mock/expect in a test-namespace to stub a function called in a sut-namespace that is actually in a third-namespace?

17:37 hiredman: ravster: don't use clojure.contrib.mock

17:37 ravster: Okay. is it unsupported?

17:37 hiredman: ~where did contrib go

17:37 clojurebot: well... it's a long story: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

17:37 gfredericks: ravster: would with-redefs do what you want?

17:37 hiredman: it was never "supported"

17:38 dnolen: jlewis: it supposed to, but I've found it useful for it NOT to for debugging purposes, especially internal data structures that aren't important.

17:38 ravster: oh, legacy stuff

17:38 dnolen: well not important for them to print readably, and more important for them to print debugabbly

17:38 jlewis: dnolen: assuming i'm exposing a data structure for people to use, tho.

17:38 ravster: what test framework should I use, then?

17:39 hiredman: clojure.test (packaged with clojure) is nice and minimal

17:39 bpr: ravster: i use clojure.test

17:39 jlewis: dnolen: i suppose the question is, is it ok for print-method to be O(n)

17:39 ravster: bpr: clojure.test has stubbing?

17:39 hiredman: it doesn't need it

17:39 clojure the language has various features you can use for that kind of thing

17:39 jlewis: lots of the built-in data structures have an O(n) print-method, for example. so i guess it is ok.

17:39 bpr: i stub by using clojure.test/use-fixtures and with-redefs and binding

17:39 hiredman: but generally stubing sucks

17:40 bpr: yeah, i only stub external services really

17:40 ravster: bpr: okay, I'll look at use-fixtures

17:40 mklappstuhl: hiredman: {:as :stream} seems to work

17:40 jlewis: another question is whether print-method should roughly be equal to printing the seq of the data structure

17:41 abp: gfredericks, also probably shoreleaves remotes for rpc (re cljs-ajax)

17:41 ravster: hiredman: link to those clojure language features?

17:41 bpr: ravster: i'd take a page from hiredman's book and stub as little as possible

17:41 hiredman: ravster: http://clojure.org/

17:41 http://clojure.org/vars

17:42 dnolen: jlewis: print-method depth can be controlled

17:42 jlewis: look at the print-method implementations in Clojure

17:45 ravster: hiredman: cool. thanks.

17:47 jlewis: dnolen: i see, *print-level*. nifty.

17:51 ravster: so a fixture is something that will be used by every test in a namespace? What if I want to do a setup/teardown for only one of the tests in my namespace?

17:52 xeqi: add it to the start and end of the deftest

17:53 ravster: xeqi: okay. thanks.

17:59 abp: woohoo ohpauleez takes shoreleave further. :)

18:00 devn: Raynes: dumb question: How do I compose multiple criteria for setting content in laser? For instance, I only want to change the content of an element whose class is "foo" AND whose id is "bar"

18:00 ohpauleez: abp: Just you wait! :)

18:00 local storage, session storage, clean up, and pub-sub threading

18:00 better remotes, and cleaned up the interfaces

18:01 abp: lovely ;)

18:01 ohpauleez: pieces of Shoreleave are now in CLJS core, so that's pretty cool

18:01 abp: Yeah, have recognized that before.

18:01 xeqi: devn: me.raynes.laser/and I think

18:01 Raynes: devn: devn https://github.com/Raynes/laser/blob/master/docs/guide.md#composing-selectors

18:02 Double devn.

18:02 ohpauleez: abp: If you have any feature requests based on real usage, definitely let me know!

18:02 Raynes: devn: Specifically (l/and (l/class= "foo") (l/id= "bar"))

18:03 abp: ohpauleez, sure I will. But I were just dabbling and trying things out a few months ago, during a general cljs-lib lookaround. Are you still building apps on shoreleave?

18:04 technomancy: Raynes: I see you're making great progress on your effort to get antares to finally shut up about documentation. =)

18:04 Raynes: technomancy: Hahahaha

18:04 technomancy: Referring to the giant guide?

18:04 ohpauleez: yep - this round of changes comes from some more real usage - both my own and other peoples

18:05 callen: this code base is diseased with misapplication of OOP.

18:05 technomancy: Raynes: of course

18:07 callen: I'm actually a syncretist myself, but this is bad.

18:07 ohpauleez: callen: What code base?

18:08 bbloom: ohpauleez: is there one page where i can get an overview of all the shoreleave components? rather than having to click through each of the readmes via the github organization?

18:08 callen: ohpauleez: day job

18:08 abp: ohpauleez, cool thing.

18:08 ohpauleez: bbloom: https://github.com/ohpauleez/shoreleave

18:09 I'm going to be adding more docs there with the new release

18:09 aperiodic: ah, it's rather confusing that that repo is not owned by the shoreleave organization

18:09 ohpauleez: there will also be a new incubator package - which will have a datalog-like query in it

18:09 callen: it's like people look for excuses to stop using functions

18:09 and immediately dive into object and method hierarchies.

18:09 abp: aperiodic, yes

18:10 ohpauleez: can you migrate the owner/location without loosing the stars/watches?

18:10 Raynes: devn: Wasn't a stupid question btw.

18:10 ravster: does with-redefs not work with namespacing?

18:10 abp: ohpauleez, probably move https://github.com/ohpauleez/shoreleave to https://github.com/shoreleave/shoreleave-doc?

18:10 Raynes: I don't expect people to know exactly what to look for in the guide and what not.

18:11 bbloom: ohpauleez: i think you can email github support & then can do all that sort of stuff for you

18:11 bosie: anyone read this book: https://leanpub.com/fp-oo

18:11 ?

18:11 ohpauleez: Are people really that interested in browsing through the codebase? haha

18:11 abp: ohpauleez, could replace the repo content with a link to shoreleave-doc in the readme?

18:11 ohpauleez: bbloom: Ah, thanks

18:11 abp: The current repo does JUST that

18:11 callen: bosie: I haven't, but it's very popular. Did you do Go before?

18:11 bosie: callen: huh, no?

18:12 callen: bosie: just wondering.

18:12 ohpauleez: it's an overview of the entire project, with links out to areas people might be interested in

18:12 bosie: callen: Go to clojure is the trend now or what? ;)

18:12 hyPiRion: TimMc: http://hypirion.com/musings/swearjure

18:12 callen: bosie: bidirectional actually, but your name reminded me of a Go programmer, that's all.

18:13 bosie: I learned Go after learning Clojure, came back because I decided my time was too precious.

18:13 maybe someday the ecosystem will come together.

18:13 bosie: callen: hah. whats wrong with Go? i haven't looked at Go

18:13 aperiodic: hyPiRion: dear god man, turn of justification on your headers

18:13 callen: bosie: nothing

18:13 aperiodic: s/of/off

18:13 callen: bosie: I'm just persnickety.

18:13 bosie: callen: coworker loves it though

18:13 abp: ohpauleez, sure, but not discoverable from shoreleaves organization

18:13 ohpauleez: ahh gotcha

18:13 thanks for the heads up everyone

18:14 callen: bosie: it has some nice attributes.

18:14 aperiodic: ohpauleez: exactly what i ran into the other day. found a shoreleave component, went looking for an overview, gave up

18:14 ohpauleez: aperiodic: gah, I'm both honored and sorry

18:14 definitely will do my best to address it

18:15 abp: ohpauleez, datalog-like queries for cljs?

18:15 dog_cat11: Go solves a lot of the problems with C, and has great concurrency features

18:15 ohpauleez: abp: Yeah, it's a terrible hack, but it's been useful when you have a large collection of map-like things

18:16 I figured I'd put it in an incubator, and if people eat it up, move it into a dedicated module

18:16 abp: ohpauleez, yes, sounds interesting.

18:16 ohpauleez: it also makes working with local storage a little better

18:17 the Swearjure post is amazing and hilarious

18:17 abp: ohpauleez, considering the size of your libs you could put it into a proper lib, or incubator more because of alphaness?

18:17 bosie: callen: is there a quick and easy way to run code distributed over multiple machienes in clj the same way you can in go?

18:18 ohpauleez: alphaness - I don't want to make a module just for the sake of it. I want to see that it gets used first

18:18 abp: ok

18:18 kovas: looks like my talk didn't get accepted to clojure west :/

18:19 callen: bosie: that's a pretty strange question. horizontal scaling across multiple machines is possible in any programming language. That's architecture, not language runtime.

18:19 ohpauleez: kovas: NOOOOOOO

18:19 devn: Raynes: oh. cool! I tried (and (l/id= "foo") ...)) -- so that's intuitive i think

18:19 kovas: yeah, it was a bummer for about 10 minutes

18:19 but at least that means ill get to enjoy the conference :)

18:19 ohpauleez: was it something like, "Approaching manifolds of reality through intermediate combinators, tagged in Session" ?

18:19 bosie: callen: and yet i can get it done quicker in erlang than i could in java

18:20 callen: bosie: that's up to personal aptitude.

18:20 bosie: lol

18:20 ok

18:20 ohpauleez: kovas: All joking aside, what was the topic?

18:20 nDuff: callen: ...well, I think bosie has a valid point re: languages shipping w/ tools that are opinionated re: architecture.

18:21 kovas: ohpauleez: session. I assume alex saw my talk at the conj and just wasn't into it

18:21 ohpauleez: r u speaking?

18:21 Raynes: disagreeing with callen is a bad idea.

18:21 He will eat you alive.

18:21 bosie: Raynes: bring it. jk.

18:21 ohpauleez: kovas: I am

18:21 kovas: ohpauleez: thnx :)

18:21 callen: nDuff: don't you start.

18:21 nDuff: you and I both know the majority of time, that's not how it shakes out.

18:21 kovas: ohpauleez: I'm probably more excited about hack week after

18:21 callen: very very few people are using things like Akka.

18:22 Raynes: don't warn them, it leaves me fewer bones to pick.

18:22 ohpauleez: kovas: You know I'm a session-lover. And hell yes, it'll be a good time for sure

18:22 technomancy: bosie: distributing calls over rabbitmq is pretty trivial and can be done in ~150 LOC: https://github.com/technomancy/die-roboter

18:22 dog_cat11: there is a great chapter in Clojure in Action on RabbitMQ

18:22 kovas: ohpauleez: sweet. Session is getting close to being ready for prime time

18:22 dog_cat11: pretty cool stuff

18:23 ohpauleez: sick, totally amped for that

18:24 kovas: jonase helped get it hooked up to nrepl, which is key

18:24 aperiodic: hyPiRion: awesome sweajure writeup

18:24 bosie: dog_cat11: thx for the tip

18:25 kovas: need to flow some nrepl functionality into the ui (like interrupt and std out) and declare victory

18:26 ohpauleez: btw I'm also getting interested in shoreleave-related stuff

18:26 ohpauleez: kovas: sick, that will be stellar to see. Ping me when you have it where you want it. I'll bang on it for sure

18:26 dog_cat11: bosie: Clojure's STM is great, but on hardware like a cluster you are forced to use the distributed memory model

18:26 Raynes: ohpauleez: http://www.youtube.com/watch?v=H7HmzwI67ec

18:27 kovas: ohpauleez: i think there is something to be made by integrating shoreleave, datomic, and angular.js

18:27 ohpauleez: kovas: Rad! Shoreleave is basically all the bitch work you'd have to do to build a real application

18:27 kovas: I agree

18:28 I actually prototyped a "cursor" for Shoreleave - that grabbed remote chunks of data as-needed

18:28 with the idea that you could wire datomic right into a client if you really wanted to

18:28 kovas: ohpauleez: the UI<-> datomic interaction is whats really slowing down session dev at the moment

18:29 ohpauleez: kovas: there's definitely room for innovation there, I agree

18:29 kovas: ohpauleez: i might shoot some questions your way when i have a clearer idea

18:29 ohpauleez: definitely

18:29 kovas: ohpauleez: right now I'm imagining entities being mapped back and forth between angular and datomic, via shoreleave

18:30 ohpauleez: word word

18:30 kovas: ohpauleez: but need to learn me some angular first

18:30 :)

18:30 ohpauleez: Raynes: Is this an invitation to a dance party?

18:30 or just because I'm always amped

18:30 Raynes: [17:11:35] <ohpauleez> kovas: You know I'm a session-lover. And hell yes, it'll be a good time for sure

18:30 Made me think of it.

18:31 ohpauleez: ahhh

18:31 _46bit: Hello fellow Clojurites.

18:32 TimMc: hyPiRion: my-nth is sweet!

18:34 Raynes: ohpauleez: I apologize for shoving pop down your throat.

18:34 ohpauleez: apology accepted :)

18:34 actually

18:35 no, I take that back, I'm going to trade you

18:35 Raynes: Challenge accepted.

18:35 ohpauleez: https://www.youtube.com/watch?v=L-6ugLM3ARw

18:35 enjoy

18:37 hopefully that video goes viral in the Clojure community :)

18:39 TimMc: hyPiRion: By the way, #(...) is more properly a function literal -- all Clojure fns are anonymous.

18:41 dog_cat11: so then defn binds an anonymouse function to a symbol?

18:42 Raynes: ohpauleez: http://www.youtube.com/watch?v=S712u9HBISs

18:42 gtrak: ,(macroexpand '(defn a []))

18:42 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

18:42 dnolen: dog_cat11: a var

18:42 dog_cat11: ok

18:43 gtrak: &(macroexpand '(defn a []))

18:43 lazybot: ⇒ (def a (clojure.core/fn ([])))

18:43 ohpauleez: Raynes: it's a race to the bottom

18:43 :)

18:44 dog_cat11: &(macroexpand '(def a #()))

18:44 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

18:44 TimMc: ,(. :foo `[5])

18:44 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: apply for class clojure.lang.Keyword>

18:45 hyPiRion: TimMc: Thanks and thanks

18:45 TimMc: ^ .apply method -- useful?

18:45 dog_cat11: &`#()

18:45 TimMc: ,(macroexpand-1 `(. :foo `[5]))

18:45 lazybot: ⇒ (fn* [] ())

18:45 clojurebot: (. :foo (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list 5)))))

18:46 amalloy: TimMc: you need applyTo; i don't think any interesting clojure classes have a .apply method

18:46 TimMc: dammit

18:49 patchwork: I have a jvm-opt that needs to be set to two different values based on the environment my app is in. Lein has me define :jvm-opts in project.clj, but that means that value is hard-coded! How do I have jvm-opts that are different based on different deploy environments?

18:50 abp: ohpauleez, have you had any problems with the history component of the closure-library? Is this just not closed? http://code.google.com/p/closure-library/issues/detail?id=449&q=history

18:51 hyPiRion: patchwork: It accepts JAVA_OPTS and JVM_OPTS as values too

18:51 dog_cat11: what about using the java system library?

18:52 hyPiRion: It'll read those

18:52 patchwork: hyPiRion: Aha, thanks!

18:54 TimMc: hyPiRion: Hey, what symbols can you get from the beginning of a syntax-quoted forms?

18:54 so far I've gotten list, seq, and apply.

18:55 dog_cat11: &(java.lang.System/getenv "PATH")

18:55 lazybot: java.security.AccessControlException: access denied (java.lang.RuntimePermission getenv.PATH)

18:56 dog_cat11: &(java.lang.System/getenv)

18:56 lazybot: java.security.AccessControlException: access denied (java.lang.RuntimePermission getenv.*)

18:56 dog_cat11: &(java.lang.System/nanoTime)

18:56 lazybot: ⇒ 32487356433694018

18:56 hyPiRion: TimMc: fn* through ##'#()

18:56 lazybot: ⇒ (fn* [] ())

18:57 TimMc: oh, huh

18:57 so that's fn_STAR_

18:57 dog_cat11: &(java.lang.System/getProperties)

18:57 lazybot: java.security.AccessControlException: access denied (java.util.PropertyPermission * read,write)

18:58 hyPiRion: and quote

18:58 TimMc: unquote, quote, unquote_splicing, var, deref

19:02 hyPiRion: ,``^{+ -} ()

19:02 clojurebot: (clojure.core/with-meta (clojure.core/list) (clojure.core/apply clojure.core/hash-map (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/+)) (clojure.core/list (quote clojure.core/-))))))

19:02 hyPiRion: another one

19:03 TimMc: Whoa, I didn't think I could get with-meta.

19:03 hyPiRion: yeah, me neither

19:04 gfredericks: you guys are breaking new ground

19:04 aperiodic: have you tried writing a syntax-quote fuzzer to look for symbols?

19:04 TimMc: Wow, plenty of stuff has withMeta methods, but nothing has with_meta, of course.

19:06 There may be some neat tricks one can do with the stitching macros.

19:08 gtrak: what is happening?

19:09 TimMc: Line-noise explorations.

19:09 gtrak: ah, swearjure?

19:10 TimMc: &(clojure.walk/macroexpand-all '(->> 0 (->> 1 (->> @2 (->> 3))))) ;; I have no idea what I'm doing

19:10 lazybot: ⇒ (0 (1 (clojure.core/deref 2 3)))

19:11 TimMc: Huh: ##(clojure.walk/macroexpand-all '(->> . :__ (->> @ two (->> args))))

19:11 lazybot: java.lang.StackOverflowError

19:12 gfredericks: TimMc: can I claim credit as the inspirer of swearjure?

19:12 * gfredericks is trying to build up some street cred

19:13 jlewis: urgh, more print-method confusion: ##(methods print-method)

19:13 lazybot: ⇒ {nil #<core$fn__5236 clojure.core$fn__5236@62312b>, java.util.regex.Pattern #<core$fn__5342 clojure.core$fn__5342@e2e191>, clojure.lang.Symbol #<core$fn__5262 clojure.core$fn__5262@16fc264>, :default #<core$fn__5232 clojure.core$fn__5232@81229a>, clojure.lang.IR... https://www.refheap.com/paste/8289

19:13 TimMc: hyPiRion linked to the logs, but he really should throw in a link to one of your sites as well.

19:13 xeqi: wouldn't that generate negative cred?

19:13 jlewis: oh, wtf, it overflows in my repl

19:13 i think my repl has screwed up state.

19:15 hyPiRion: TimMc: Link?

19:16 TimMc: gfredericks: Link?

19:17 Wow, ->> and -> are really screwed up.

19:17 &(clojure.walk/macroexpand-all '(-> a (->> b c)))

19:17 lazybot: ⇒ (c (b a))

19:17 TimMc: &(clojure.walk/macroexpand-all '(->> a (->> b c)))

19:17 lazybot: ⇒ (a (c b))

19:20 hyPiRion: &(->> ~@[hurr durr] quote)

19:20 lazybot: ⇒ (clojure.core/unquote-splicing [hurr durr])

19:21 gfredericks: TimMc: gfredericks: huh?

19:21 wait you guys are actually posting credit about swearjure somewhere?

19:21 is there a git repo or something for this stuff?

19:22 * gfredericks googles swearjure for the first time ever

19:22 hyPiRion: not "credit", I just mentioned it here: http://hypirion.com/musings/swearjure

19:22 amalloy: see if you can get it a wikipedia entry, gfredericks

19:22 gfredericks: well look at that.

19:22 mpan: oh hey I just ran into that article on Hn

19:22 TimMc: &(let [wtf (iterate macroexpand-1 '(->> . :__ (->> @ two (->> args))))] (= (nth wtf 5) (nth wtf 9)))

19:22 lazybot: ⇒ true

19:22 TimMc: hyPiRion: macro-expansion loop!

19:23 hyPiRion: TimMc: Wow, these macros

19:23 TimMc: hyPiRion: gfredericks has a bug open on -> not expanding intuitively

19:23 gfredericks: oh I don't have anything worth linking it to

19:23 TimMc: Home page? github?

19:23 gfredericks: gfredericks.com or twitter.com/gfredericks_

19:28 amalloy: TimMc: that wtf doesn't fit in my head at all. what do?

19:28 gfredericks: hyPiRion: is an "algorist" an algo person?

19:29 hyPiRion: http://en.wikipedia.org/wiki/Algorist

19:29 yeah

19:29 gfredericks: wait

19:29 TimMc: amalloy: I'm... not sure.

19:29 gfredericks: I just confused "agda" and "algo" in my head :)

19:30 TimMc: amalloy: both are nil?

19:30 TimMc: Nope.

19:30 gfredericks: &(macroexpand-1 '(->> . :__ (->> @ two (->> args))))

19:30 lazybot: ⇒ (clojure.core/->> (clojure.core/->> . :__) (->> (clojure.core/deref two) (->> args)))

19:30 TimMc: Put this in your REPL: (pprint (take 8 (iterate macroexpand-1 '(->> . :__ (->> @ two (->> args))))))

19:31 macroexpand-all will do a stack overflow

19:31 Anyway, notice the last item and the fourth item are the same.

19:31 amalloy: TimMc: macroexpand-all overflowing isn't very interesting, because clojure.walk is trash. it's only interesting if macroexpand also overflows (which i think it does, right?)

19:32 TimMc: Yeah, it does.

19:33 ,(macroexpand '(->> a b (->> (c d) (->> e))))

19:33 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.StackOverflowError>

19:33 TimMc: Filing a JIRA, I guess.

19:33 gfredericks: ,(macroexpand-1 '(->> a b (->> (c d) (->> e))))

19:33 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.StackOverflowError>

19:33 gfredericks: oh wow

19:33 hyPiRion: Well, what is is supposed to expand to?

19:34 TimMc: gfredericks: Oh, that's new.

19:34 gfredericks: TimMc: put my name in the blog post about it

19:34 TimMc: hyPiRion: Hell if I know.

19:35 gfredericks: I don't think the bug I filed would explain any of that

19:35 TimMc: So, I guess I accidentally quined a macro!

19:36 gfredericks: macroexpand-1 overflowing is really bizarre

19:36 TimMc: gfredericks: I think it's just clojurebot.

19:36 gfredericks: ,(#'->> nil nil 'a 'b '(->> (c d) (->> e)))

19:36 clojurebot: (clojure.core/->> (clojure.core/->> a b) (->> (c d) (->> e)))

19:36 TimMc: &(macroexpand-1 '(->> a b (->> (c d) (->> e))))

19:36 lazybot: ⇒ (clojure.core/->> (clojure.core/->> a b) (->> (c d) (->> e)))

19:36 gfredericks: ah phew

19:36 TimMc: &(macroexpand '(->> a b (->> (c d) (->> e))))

19:36 lazybot: java.lang.StackOverflowError

19:37 gfredericks: so presumably my patch to ->> would eliminate the quining?

19:37 TimMc: I tmight.

19:37 gfredericks: my apologies if it gets accepted

19:37 TimMc: heh, no, it really should

19:37 Got the issue number handy?

19:38 gfredericks: $google CLJ-1121

19:38 TimMc: thanks

19:38 gfredericks: you're gonna comment?

19:38 TimMc: hellz yeah

19:38 hyPiRion: $kill

19:38 lazybot: KILL IT WITH FIRE!

19:38 gfredericks: $bill

19:39 TimMc: gfredericks: Actually, do you have that patched Clojure handy?

19:39 gfredericks: as a branch you mean?

19:39 I believe so

19:40 check my clojure fork

19:40 a branch called threading or something I think

19:41 actually I don't see it o_O

19:41 TimMc: (Read: I'm too lazy to go find your fork, can you try that macroexpansion out?)

19:41 gfredericks: oh gotcha

19:41 not easily :) sorry

19:41 TimMc: I'll just grab the patches tonight if you're busy.

19:41 gfredericks: well wait

19:42 nope cancel that; don't have it

19:42 TimMc: okey doke

19:42 dnolen: so reduce can be short circuited in 1.5.0

19:43 gfredericks: sounds right

19:43 dnolen: I should have known that - but nobody brought that up last time I asked about it :)

19:43 gfredericks: how do you do it? call a function that constructs a special type?

19:43 amalloy: yes

19:43 (reduced 10)

19:44 gfredericks: well look at that.

19:44 dnolen: SWEEEET

19:44 gfredericks: is it a deftype?

19:44 or a java class?

19:44 Bronsa: it's a class

19:44 amalloy: dnolen: you may be excited to know that each reducer needs to implement support for reduced by hand, and some of them do it wrong (or at least did before being patched)

19:45 dnolen: amalloy: I'm assuming their fixed in RC1 right?

19:45 gfredericks: does clojure not define any types or protocols? I wonder why it would be avoided...

19:45 dnolen: amalloy: but yes, needing to support reduced in the implementation makes sense to me, how else could it work?

19:45 hiredman: clojure does both

19:46 gfredericks: hiredman: both types and protocols you mean? any idea why clojure.lang.Reduced wouldn't be a type then?

19:46 I assume there's no real need either way, but still...

19:46 amalloy: dnolen: i fixed the one i noticed. i don't remember if the patch was actually applied

19:46 gfredericks: I guess that would throw an extra ->Reduced function into clojure.core that would be kind of silly

19:47 s/silly/distracting/

19:48 huh; cljs doesn't do ->Foo for deftypes

19:48 hiredman: gfredericks: my guess is it makes it easier to work with from the jvm impl, but RT has RT.isReduced

19:49 but the collect types that implement things like kv-reduce in java need to be able to check for reduced

19:50 gfredericks: hiredman: that makes sense

19:50 amalloy: ,'&1

19:50 clojurebot: &1

19:50 TimMc: heh

19:50 amalloy: ,(symbol "echo 1")

19:50 clojurebot: echo 1

19:50 TimMc: wait, nooooo

19:50 amalloy: hyPiRion: there. problem solved

19:50 TimMc: How will I inc myself now?

19:50 amalloy: you monster

19:50 hyPiRion: echo 1

19:50 lazybot: 1

19:51 gfredericks: amalloy: patching up the botholes?

19:51 hyPiRion: ah, nice.

19:53 TimMc: Hmm, how do I start the clojure REPL if all I have is the clojure core jar?

19:53 hyPiRion: clojure.main

19:53 TimMc: Huh, OK.

19:56 gfredericks: (b a (c d e))

19:56 Your patch works!

19:56 gfredericks: sweetso!

19:57 (defne sweetso [x] ([:candy]) ([:muffins]))

19:57 or rather (def sweetso #(membero % [:candy :muffins]))

19:59 amalloy: dnolen: yeah, my patch to reduced did get applied. so i don't know of any incorrect implementations of it at this time

20:00 Raynes: No more multibot quines, guys. Sorry to ruin your fun, but amalloy added a global ignore feature.

20:00 amalloy: they know, man. i announced it

20:00 Raynes: Now we've both announced it.

20:00 xeqi: echo am I on ignore?

20:00 lazybot: am I on ignore?

20:01 gfredericks: ,(println "/nick cloojurebot")

20:02 clojurebot: /nick cloojurebot

20:02 * gfredericks had to try

20:02 Raynes: gfredericks: That isn't a thing though.

20:02 amalloy: next step: adding a $ignore command to modify it at runtime so i can shame people with "$ignore gfredericks because he's a twerp"

20:03 TimMc: ,(symbol "\u0001ACTION has baggy pants")

20:03 * clojurebot has baggy pants

20:03 nybbles: hello, i want to update some shared state, do a HTTP request and only have that change to shared state persist if the HTTP request is successful. if it is unsuccessful, the change should be unrolled. what's a good way of doing that?

20:03 TimMc: amalloy: Here's that broken ->> in action: https://www.refheap.com/paste/8292

20:05 nybbles: Can you do the HTTP request first and then change shared state based on its results?

20:06 nybbles: the problem with that approach is that the HTTP request acts on a remote resource, and i change the shared state to make sure that another part of the program doesn't delete the remote resource

20:07 so i was thinking of changing the shared state to make sure that I continue to have access to the remote resource.. update the remote resource with a POST and then if that POST is successful, not roll back the local shared state

20:13 hmmm i just got an idea of using two refs instead of one atom, where one ref holds the number of outstanding POSTs and we dont do any deleting while that number is > 0

20:14 TimMc: hyPiRion, gfredericks: The minimal form of that pathological case is (->> a b (->> c d))

20:15 pandeiro: technomancy: what would be the easiest way to add a new route via nrepl, given your heroku webapp template?

20:16 technomancy: pandeiro: not sure I understand the question?

20:17 pandeiro: technomancy: sorry, let me try again: is there a way to change the app's routes w/o redefining myapp.web/app?

20:17 amalloy: (->> a b (->> c d)) :: (->> (b a) (->> c d)) :: (->> c d (b a)) :: (->> (d c) (b a)) :: (b a (d c)) is the expansion path that "should" take, right TimMc?

20:18 technomancy: pandeiro: I don't think so. maybe some weird low-level way to do it, but I wouldn't recommend it.

20:18 pandeiro: technomancy: ie, if the app's routes were a map or something, you could just assoc a new key... but since ring/compojure work with functions...

20:18 technomancy: pandeiro: something wrong with recompiling?

20:19 pandeiro: technomancy: not really, just exploring what having the repl access could possibilitate :)

20:19 technomancy: nearly anything that works locally

20:19 weavejester: pandeiro: Why is not redefining myapp.web/app a possibility?

20:19 pandeiro: technomancy: but with the extra push step

20:20 weavejester: well imagining i didn't have the source file open in emacs right next to me

20:20 say i was on another computer somewhere

20:20 technomancy: pandeiro: well, with the caveat that the local disk is not the remote disk, and most nrepl clients don't support the HTTP transport yet

20:21 pandeiro: technomancy: you mean for pushing the changes? i'm confused - what about drawbridge? isn't this working over http?

20:21 weavejester: Hm, making modifications without the source seems a little iffy to me

20:21 technomancy: pandeiro: drawbridge is a server component

20:21 most nrepl clients don't support the HTTP transport, but `lein repl` does

20:21 err--I guess it's both

20:22 but you can't use drawbridge from your client unless your client is written in clojure

20:22 pandeiro: technomancy: ah, yeah so i'm using lein repl :connect, which i guess i could need wherever i was

20:22 technomancy: so maybe you could use it in ccw, but not emacs or vim

20:22 pandeiro: weavejester: yeah i realize that, but say, i dunno, i just wanted to disable a certain route quickly?

20:24 technomancy: i did lein repl :connect from *shell*, but is there any reason i couldn't make that the inferior-lisp command or somehow hook up nrepl.el to use the remote repl?

20:24 technomancy: pandeiro: you can use it with inf-lisp

20:24 using it from nrepl.el would basically require porting drawbridge to elisp

20:25 not sure how hard that would be

20:25 hiredman: just the client part

20:25 technomancy: right

20:25 hiredman: if you have json parsing + http requests it is not to hard

20:25 technomancy: I would love for someone to pick that up =)

20:25 hiredman: you'd have to write elisp

20:26 pandeiro: technomancy: give me another year or two with emacs/clojure and i'm your guy :)

20:26 hiredman: https://github.com/hiredman/drawbridge-cljs/blob/master/src-cljs/drawbridge/client.cljs is an drawbridge client in clojurescript, and it is async which is a plus when you are single threaded like emacs

20:27 the http transport does require polling though, instead of just sending data like with a real connection

20:45 bbloom: i hate it when you have a cond (or pattern matching) that has a non obvious implicit requirement on the exact ordering

20:55 TimMc: amalloy: Correct.

21:05 tomoj: so I have a snippet for repl mode 'r' which require/:refers pprint, doc, pst, and requires io and str, and will probably require other stuff that's in core soon

21:06 but forgetting, getting an error, and having to do `r TAB` in every new namespace is still pretty annoying

21:06 any sane way to make it any better?

21:06 it's not that annoying I suppose, but enough to make me want to change it

21:19 gfredericks: wow domina uses a single-element namespace

21:19 that's hot

21:20 BIGBOOMBA: Having trouble installing leiningen on Debian. Tried apt-get, but there was a dependency issue that I couldn't resolve. Downloaded the shell script and put it in /usr/bin, chmodded it, and when I ran "lein" I just got a page full of JVM error messages.

21:20 Leading off with "Exception in thread "main" java.lang.NoClassDefFoundError: clojure.core.protocol"

21:21 gfredericks: O_O

21:21 tpope: BIGBOOMBA: how did you install the jvm?

21:23 TimMc: BIGBOOMBA: You'll do better off with lein in ~/bin -- that way it can self-upgrade.

21:23 BIGBOOMBA: Just from www.java.com, I think. Running "java -version" gives "java version "1.5.0" gij (GNU libgcj) version 4.4.5"

21:23 Okay, Tim, thanks, I'll move it there.

21:23 Yeah, I have the gjc compiler, not javac.

21:24 gfredericks: woah the ns order bug is still not fixed in cljsbuild-HEAD?

21:24 BIGBOOMBA: Or gcj

21:24 gfredericks: how long does a guy have to wait without contributing anything before other people fix everything for him?

21:25 BIGBOOMBA: Would it help if I put the rest of the error messages on pastebin?

21:28 Here's what happened after I put the lein script in /usr/bin, chmodded it, and tried to run it

21:28 http://pastebin.com/QQs6WMMy

21:29 tpope: BIGBOOMBA: I haven't yet tried with lein, but every time I install gcj rather than the official jvm, I always end up regretting it

21:29 running into weird issues exactly like this

21:30 BIGBOOMBA: You mean the official java compiler? I had a JVM installed before I downloaded gcj. Do you mean that I should replace gcj with javac?

21:34 amalloy: gcj is useless trash

21:35 tpope: BIGBOOMBA: that would be the first step I tried

21:38 TimMc: "incompatible type on stack" <-- never seen *that* before

21:39 BIGBOOMBA: I'm at Java's website, on their JDK download page. Can I use OpenJDK with javac? I'd prefer to use open-source tools if possible.

21:40 dog_cat11: that should work

21:42 TimMc: Sure, I use OpenJDK 6.

21:43 BIGBOOMBA: apparently i have java 1.5 and not openjdk

21:45 should i use openjdk 6 instead of 7? is there a problem with 7?

21:47 xeqi: BIGBOOMBA: I'm using openjdk7 just fine

21:48 installed on ubuntu with `apt-get install openjdk-7-jdk`. I'd expect debian to have a similar package, or at least one for openjdk-6

21:48 dog_cat11: did you check your repositories?

21:51 gfredericks: it's odd that domina doesn't have any kind of dom-ready facility

21:59 bbloom: gfredericks: that's b/c gclosure doesn't have a dom-ready facility

21:59 arrdem: today I learned that terrible things happen when you rebind the "apply" function.

21:59 bbloom: gfredericks: and that's b/c google doesn't want their apps to use it

22:02 amalloy: arrdem: no kidding, huh? that's gotta be in the top ten list of "worst functions you could redef"

22:03 arrdem: amalloy: I figured I was gonna be okay because there wasn't much else in that namespace and I only :required :as it elsewhere but next thing I knew I had build-breaking null pointer exceptions everywhere

22:08 gfredericks: bbloom: interesting; I found a good explanation for that; thanks

22:27 TimMc: Raynes: I think I broke lazybot, could you restart it?

22:29 amalloy: TimMc: what did you do?

22:30 did you redefine the 'let macro or something? his error message is bizarre

22:30 * TimMc embarrassed

22:30 TimMc: *looks

22:30 I... I'm not entirely sure?

22:30 I *may* have been slightly trying to get eval.

22:32 xeqi: oooh

22:33 TimMc: Aw, c'mon, don't take away my toy!

22:33 \o/

22:33 amalloy: &1

22:33 lazybot: ⇒ 1

22:34 amalloy: next time you break him, keep a log of what you did or i'll take away your toy

22:34 TimMc: Oh, yes -- I *did* redefine let. My bad.

22:34 I'll test stuff in my own REPL first.

22:37 amalloy: hah! well, of course you shouldn't have been able to redefine let

22:37 TimMc: Yeah, but if I tell you how I did it you'll close the hole and I won't be able to finish my trick.

22:38 I'll try very hard not to break it, then tell you.

22:38 amalloy: *chuckle* okay

22:38 * arrdem expects this to end badly but wants to see a full lazybot 'sploit

22:39 xeqi: arrdem: some previous ones http://nelsonmorris.net/2012/09/06/breaking-lazybot-out-of-clojail.html

22:40 TimMc: Hey, that's me!

22:40 xeqi: it is!

22:40 arrdem: xeqi: cheers, looks like an interesting read!

22:41 Raynes: TimMc: Whatever it is, please don't mention it in public. I really don't feel like spending the week working on clojail. :p

22:41 TimMc: Well, this one is pretty obvious. No offense.

22:41 Raynes: Yeah, I'll do it responsibly, since it's a clojail problem, not lazybot.

22:42 Raynes: Offense takne.

22:42 taken*

22:42 arrdem: lol

22:42 TimMc: Or maybe it's just lazybot's settings, in which case I'll blurt it out at an inconvenient time.

22:42 Raynes: When do you plan on letting me know what it is?

22:42 * Raynes gets out his calendar.

22:43 TimMc: Tonight?

22:43 How long will you be up?

22:44 Raynes: I'll be here for the rest of the night. Just trying to figure out what you're waiting for.

22:44 TimMc: my code to be ready

22:44 OK, gonna try a basic case...

22:44 Raynes: Well, if it's super obvious, how hard could it be?

22:45 arrdem: Very Easy™

22:45 amalloy: ps TimMc i'm spying on your PMs to lazybot

22:45 TimMc: Raynes: Well, this time I'm not bashing randomly on my keyboard so that I don't crash lazybot.

22:45 amalloy: onoes!

22:46 xeqi: I hope its a previously unknown one

22:50 TimMc: amalloy: I'm imagining you laughing to yourself as I struggle with this. :-(

22:51 amalloy: i'm not watching you as carefully as all that

22:51 TimMc: good

22:52 amalloy: but your p here is a function value, not a var, so your strategy can't change it

22:52 TimMc: amalloy: By the way, is this a clojail bug or a lazybot bug?

22:52 Raynes: clojail

22:52 TimMc: eep

22:52 Raynes: And not a big one either.

22:53 xeqi has some other cute standing vulnerabilities I need to fix soon.

22:53 TimMc: I was pretty surprised it worked. (For some value of "worked".)

22:54 amalloy: Am I just completely misunderstanding this feature?

22:56 amalloy: i dunno. i thought i knew what you were doing but i'm wrong

22:56 TimMc: haha

22:56 amalloy: just PM people with what you're actually doing. spying isn't easy

22:56 Raynes: I support this motion.

22:56 amalloy: unless you want to do it in secret, and then stop asking for feedback

22:57 arrdem: take this to #break-lazybot?

22:57 Raynes: No.

22:57 TimMc: Well, it's late enough at night for me that I don't feel like going the last mile, and anyway you already know the exploit.

22:57 arrdem: Nah, I don't know how to lock down a channel.

22:57 Raynes: -> PM

22:58 blackdog: hey - is there a way to look up docs of a clojure form from the repl?

22:58 arrdem: ,(doc doc0

22:58 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

22:58 arrdem: ,(doc doc)

22:58 clojurebot: "([name]); Prints documentation for a var or special form given its name"

22:58 blackdog: cheers

22:58 arrdem: glad I could help

23:03 ,(doc comment)

23:03 clojurebot: "([& body]); Ignores body, yields nil"

23:08 gtrak: hmm

23:09 bbloom: i love update-in so much that i made an update-top for a stack and i've got an (update-top stack update-in [:some-key] f arg) and it's glorious

23:12 gtrak: (swap! stack update-top update-in [:some-key] f arg)

23:12 arrdem: is there a clean way to print the symbols and values of a let form?

23:12 tpope: bbloom: when I showed you my netrc parser, it was in dire need of such a construct, and you just told me the low level stack operations aren't really used :(

23:12 tomoj: (println (second let-form)) :P

23:13 gtrak: arrdem: you most definitely need a macro for this

23:13 arrdem: tomoj: .... are you for real?

23:13 bbloom: tpope: i forget the details of that situtation

23:13 tomoj: I don't know what you mean

23:13 &(println (second '(let [x 42] x)))

23:13 lazybot: ⇒ [x 42] nil

23:13 tpope: I'm sure you did

23:13 bbloom: update-top is pretty easy tho: (defn update-top [stack f & args] (conj (pop stack) (apply f (peek stack) args)))

23:14 arrdem: ah. that makes more sense. oookay. thanks @gtrak, @tomoj

23:14 bbloom: maybe i was suggesting you destructure from the top of the stack? that's more common than pop & peek

23:15 tpope: (conj (pop stack) (assoc-in (peek stack) [1 (keyword k)] v))

23:15 is what I had

23:15 bbloom: ah

23:15 tpope: I don't think you had any suggestions, but then we derailed on to that whole "default" requirement

23:15 and then amalloy just rewrote it

23:15 arrdem: ,(str (quote foo))

23:15 bbloom: tpope: heh, oh well. my new suggestion: update-top :-)

23:16 clojurebot: "foo"

23:16 amalloy: bbloom: which is in useful, if someone happens to want it, named update-peek iirc

23:17 bbloom: amalloy: i still haven't really dug into useful

23:17 blackdog: bbloom: update-in looks a lot like lenses

23:17 bbloom: blackdog: how so?

23:18 blackdog: composable way of navigating data structures

23:18 bbloom: blackdog: lenses are pairs of functions (A -> B, B -> A)

23:18 gtrak: arrdem: take a look at this awfmacro I made and never use: https://gist.github.com/4499370

23:18 amalloy: lenses are how you can trick a strongly-typed map into supporting update-in

23:18 blackdog: unless i've misread what update-in does

23:18 gtrak: awful* it parses a let form and dumps the bindings into a map

23:18 bbloom: in this case, it's get-out/put-in

23:18 which is only a subset of a full lens

23:19 albiet a useful subset

23:20 update-whatever functions remind me more of common lisp's setf

23:20 but non-mutating

23:20 blackdog: bbloom: yeah. i'm coming from the haskell world, just trying to find analogs.

23:21 bbloom: gotcha

23:21 anyway, gotta go

23:22 arrdem: perfect... https://www.refheap.com/paste/8310

23:22 tomoj: hmm

23:22 `modL l f a = setL l (f (getL l a)) a`

23:23 arrdem: well... that'll break if you do destructuring...

23:23 gtrak: arrdem: my macro also handles destructuring propely

23:23 properly*

23:23 arrdem: gtrak: exercise for the reader. gimme a minute here.

23:23 gtrak: that's what all the tree-seq stuff is for

23:26 arrdem: gtrak: (filter symbol? (tree-seq seq? identity <root>))

23:26 gtrak: possibly :-)

23:26 I'm not a tree-seq ninja

23:26 arrdem: ,(seq? (first {:foo :bar}))

23:27 clojurebot: false

23:30 gtrak: I guess map-entries aren't seqs?

23:31 arrdem: right, so that tree traversal wouldn't get {:keys [foo bar baz]}

23:36 gtrak: haha cute! yours just uses (destructure), amirite?

23:37 gtrak: hmmm, I wonder why it wouldn't work with out that

23:38 it seems like I could just expand bindings, too

23:39 yea, that's just my macro noob-ness, I think

23:39 i think it'll work without explicitly calling destructure

23:39 since let does it for you anyway

23:41 arrdem: got it.

23:42 gtrak: https://www.refheap.com/paste/8312 that'll do anything that (destructure) can and therefore all destructurings that clojure supports.

23:42 gtrak: I spent like a couple days 6 months ago thinking about that

23:43 ah, you avoided the tree parse entirely?

23:43 the problem I solved by not doing that was avoiding the gensyms

23:44 arrdem: yerp. if you look at the source for (let) you'll find that it uses (destructure) to do all the binding vector parsing and (gensym)ing

23:44 gtrak: right, I didn't want the gensyms

23:44 that simplifies it

23:45 destructure is also a monster

23:46 arrdem: oh I agree. gave up halfway through reading it.

23:54 gtrak: arrdem: that's a useful macro... I've been doing something with similar intent by wrapping bindings in a def and sending them to the repl, an emacs keyboard macro

23:55 much dirtier..

23:56 but I have the benefit of saving values off in vars and 'stepping' through a huge let-form

23:56 I just wish I knew how to make it not a keyboard macro (not enough to learn how just yet)

Logging service provided by n01se.net