#clojure log - Oct 30 2013

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

0:00 tbaldridge: https://github.com/clojure/tools.analyzer

0:00 brehaut: tbaldridge: yes, though its still the single link with the best overview

0:00 tbaldridge: yeah, there just isn't any work going on there anymore.

0:01 jared314: By changing requirement to choice, clj-in-clj will force people to choose a platform. But, most will choose the default because it is good. It's good reframing/marketing.

0:01 so the argument won't be what is better

0:01 it will be what are you doing, because the JVM is good enought

0:02 enough*

0:02 tbaldridge: "By changing the requirement to choice" not sure I understand that.

0:03 danlentz: recently i ran across an early clojure prototype implemented in common-list. I'm a bit sad it didnt happen at the same time I recognise that leveraging the java investment companies have made is perhaps the most significant reason clojure is emerging as such a viable platform in the marketplace

0:03 cmajor7: I am looking at core.async ops, and wondering.. what happens to the ops that don't just reify the Channel, but actually depend on the data within a channel.. in case the data is streaming in. for example, let's take a "split". the go-loop will only stop/exit producing those two channels (a vector of true and false for a predicate) in case the channel is closed http://bit.ly/16KkbDl , but what if the data is constantly streaming

0:04 danlentz: er, common-lisp that is

0:05 tbaldridge: cmajor7: go loops kick off a new logical thread. So the split function should return almost instantly.

0:06 cmajor7: tbaldridge: ah.. and then whoever is listening on tc/fc will get updates.. very niice

0:07 tbaldridge: could not see the next level of "inception" :)

0:07 tbaldridge: cmajor7: you must go deeper, and see where the rabbit hole goes.

0:08 cmajor7: tbaldridge: I am following him as we speak..

0:08 tbaldridge: a rabbit that is..

0:08 tbaldridge: cmajor7: I should mention, like most of Rich's code, async.clj contains a ton of "high performance" code. Some of the stuff with reifying ReadPorts and the like is kindof black magic.

0:09 he wrote it so we don't have to, but most of the time you don't need drop to the primitives he's using.

0:11 cmajor7: tbaldridge: yea, I am just quietly walking the path of something I hope is "understanding the flow" not to reinvent a feature I am looking for..

0:12 SegFaultAX: Anyone see that Uber was doing kitten deliveries in SF today?

0:12 cmajor7: tbaldridge: thinking of doing "batching" with a channel. where I can call a function on that "batch" on either a timeout or when a certain batch size is reached

0:12 SegFaultAX: It was /awesome/. They came to our office with 3 ADORABLE kittens and hung out for like 25 minutes. They even brought cupcakes and kitten ears.

0:13 Not rubbing it in or anything, but how often do you get kittens delivered to your office. :D

0:13 cmajor7: tbaldridge: that batch is state, so I wanted to see if I can leverage an internal channel to keep that state.. maybe..

0:13 tbaldridge: cmajor7: yeah, you just need a loop that takes from a channel with an alt! and a timeout. use a loop to manage the state

0:14 jared314: tbaldridge: what i'm saying is c-in-c simplifies porting, which, through community effort, expands platform choice. This also creates a paradox of choice, where most people will just end up picking the JVM.

0:14 danlentz: ah. i was just searching the web looking for the definition of "kittens" as some sort of clojure/java technospeak

0:14 SegFaultAX: danlentz: No, actual kittens.

0:14 cmajor7: tbaldridge: yes, I am very much into alt! for this.. but how do I chop that "batch" from a channel, as events keep coming in..

0:15 danlentz: sometimes a kitten is just a kitten...

0:15 jared314: tbaldridge: but they will no longer complain about it because it was their choice

0:15 technomancy: SegFaultAX: I have had cats wandering into my office a few times

0:15 not on demand though

0:15 (my office is a shed in my back yard)

0:16 danlentz: technomancy: did you follow the earlier discussion re: unsigned arithmetic?

0:16 SegFaultAX: Well I can assure you it was a welcomed distraction.

0:16 technomancy: danlentz: no

0:16 SegFaultAX: Well, it was in the middle of a heated ping pong match, but other than that, welcomed.

0:16 technomancy: SegFaultAX: with me I kept worrying that I'd forget he was in there once he took a nap on the recliner and lock him in for th enight

0:17 cmajor7: tbaldridge: e.g. if it wasn't Clojure per se, I would use a concurrent.LinkedBlockingQueue and would syncronize it (with a lock) to "fetch-a- batch" on either timeout or when batch size is reached. in Clojure however I feel it is already solved for me.. I just don't see "the way" at the moment

0:17 SegFaultAX: technomancy: We used to have a very open animal policy. There were 2 office dogs. It was pretty amazing... that is until the property manager decided to be a dick bag. :(

0:17 danlentz: i've4 been struggling to get a reasonably efficient means of doing 64bit unsigned arithmetic and have failed at some point with every solution I've come up with

0:18 `cbp: SegFaultAX: all I gotta do for cats to show up at my desk is to leave food overnight

0:18 amalloy: cmajor7: you have to look at core.async from the lens of javascript, where such niceties as blocking and threads don't exist

0:18 `cbp: and an open window

0:18 amalloy: it's still neat in clojure-jvm, in a similar way as lamina is, but it's not a huge deal

0:19 SegFaultAX: `cbp: Where is your office?

0:19 danlentz: popular wisdom is to put and search for some java project that might have been fought and won in this quagmire

0:19 punt rather

0:19 `cbp: SegFaultAX: mexico

0:20 cmajor7: amalloy: I am really for looking at it differently, but since a channel is just a pipe with no meta data (size, peeking, chopping..), I am trying to understand/find an approach to "chop that batch" while data is still coming in to the channel

0:20 danlentz: basically I need to do some bitwise manipulations for my uuid library and I'm struggling to get it to produce results equal to those implemented on platforms that natively support unsigned numeric representations

0:22 SegFaultAX: `cbp: Ah, neat!

0:22 danlentz: and i just had the unpleasant discovery that bigint cant do bitwise ops, and so there goes another approach

0:23 jared314: what happened with fogus's gloss project?

0:23 cmajor7: amalloy: can you think of one?

0:23 tbaldridge: cmajor7: this is what you want, I think https://gist.github.com/halgari/7226915

0:23 amalloy: no, because your desire is not expressed in a way i can understand

0:23 jared314: nm

0:24 tbaldridge: eh, there's a bug there, < should be > I think

0:24 danlentz: gloss is close actually

0:24 jared314: danlentz: have looked at how ztelman did gloss yet?

0:25 danlentz: spelling not guaranteed.

0:25 danlentz: its good stuff but has a different focus and doesnt really get me there for the kind of bit-twiddling I'm trying to accomplish

0:26 amalloy: danlentz: you might ask ztellman, though - in addition to gloss he has done more low-level mathy stuff in clojure than anyone i can think of

0:27 danlentz: also i've lookedv at primitive-math, byte-streams, byte-transforms, bit-sets, and a number of other libs but they dont really address the core issue i run into

0:27 amalloy: working with primitives etc

0:27 jared314: danlentz: which is?

0:27 cmajor7: tbaldridge: for max-pending, right.. very cool. looks great. my mistake was thinking about holding that "batch" within an internal channel, but a simple vector hidden under the go hood is even better. thanks a lot Tim!

0:27 coventry: danlentz: What is the core issue, anyway?

0:28 danlentz: which is the need to mask off bits and deposit replacements, etc

0:28 tbaldridge: cmajor7: you might be tempted to reset the timeout channel at each recur, but the way I have it may work better in situations where the semantics are "flush every sec" vs "flush after 1 sec of inactivity"

0:29 danlentz: the common-lisp functions are: #'byte #'dpb, and #'ldb

0:29 jared314: danlentz: It sounds like a java ByteBuffer would work for that. What is wrong with it?

0:31 danlentz: only my ignoance of it. maybe that is the answer... It definitely gives me a new avenue to work on anyway

0:31 bitemyapp: `cbp: awesome :)

0:31 jared314: danlentz: java.nio.ByteBuffers

0:32 danlentz: java.nio.ByteBuffer

0:32 danlentz: reflection of some of the difficulties picking up clojure without much of a java background...

0:32 bitemyapp: I don't think picking up Clojure without Java is that hard.

0:32 jared314: danlentz: i learned about ByteBuffers from gloss

0:32 tbaldridge: seems you could also use a byte array

0:33 cmajor7: tbaldridge: yea, I think "(recur new-pending tout)" in case a batch size wasn't reached makes more sense, then reseting it on every message (if I understood your comment correctly)

0:33 danlentz: you're right. I remember seeing it. I think at the time my thought was i had found what i needed by simply following his unchecked primitives technique

0:33 tbaldridge: cmajor7: yeah, it depends on the semantics you want.

0:34 cmajor7: tbaldridge: right. again, thanks a lot. makes it so much easier than "me thinking reifying a Channel and holding that state" :)

0:35 danlentz: by the time I realized the difficulties down that road I seem to have forgotten it. thanks for the assist.

0:37 bitemyapp: not insurmountable. just every so often one runs into some java thing that it would have been helpful to have known is all.

0:37 Java for the aspiring clojurist would be an encellent book, if it existed

0:38 technomancy: bitemyapp: it's not that; it's picking a good first project that's hard.

0:39 part of picking a good first project is knowing what's going to drop you straight into the guts of java.nio.* and avoiding that

0:39 but how are you supposed to know that starting out?

0:39 jared314: that's what happened to me. Listen to him and don't do what I did.

0:40 danlentz: a good first project imho is one where you learn a lot, not necessarily write an excellent app. And I've definitely learned a lot by having to struggle a bit with this unsigned aritmetic

0:40 `cbp: try struggling with java.awt.print :P

0:41 danlentz: i hadn't the slightest idea it would be so difficult to get essentially the same functionality as the very simple common-lisp ldb and dpb functions

0:43 and i've never encountered a situation where there was no concept of unsigned numbers -- very surprising how difficult it is to construct ones own unsigned representation using only a signed one

0:43 jared314: i've always found it strange to expect numbers to be bytebuffers

0:44 danlentz: i mean, doing the reverse is not that difficult

0:45 also, though, the jvm is overprotective in this regard when it thinks you are trying to represent an invalid number

0:46 things seem to dome down always to the fundamental issue of dealing with -0

0:46 which it is never going to like, ever.

0:51 so the representation of the word one would hope to create by means of (bit-shift-left 1 64) is just always going to run into problems even when you can create it with unchecked math trickery

0:53 bit-and ing it with some other 2s complement analog of the unsigned number you mean becomes a task mired in special cases and potential exceptions

0:54 bjl7: so I have the form like (do (when x (get-new-y)) (recur y)). Is there a nice way to pass the value from the first statement in the do to the second? I'm not sure I want to clutter global var space.

0:54 coventry: Do you need it in a number format for the UUID application?

0:54 danlentz: in the end, there is one-less number representable in any given 2s complement byte-size than in unsigned of the same width

0:55 coventry: you're suggestingf manipulating a string representation?

0:56 coventry: A ByteBuffer representation maybe.

0:56 danlentz: also an interesting idea. y the bytebuffer is my next approach

0:57 jared314: I like to image that old cereal commercial: You got a pointer in my numbers. No, you got numbers in my pointer. Oh well, lets just jump to the location and see what happens.

0:58 danlentz: although the bytes iun a bytebuffer are still signed so i'd have to use shorts in the bytebuffer and the basically reimplement the various bitwise-operations to support operating in that way

0:59 i've also looked at chars, which are, in fact, unsigned numbers

1:00 but unfortunately they seem to be undefined over certain ranges something like FD00-FDFF or some such

1:00 which i'm sure almost no java implementation probably checks, but still seems a bad idea to rely on that

1:01 ie, this would be viable, otherwise, to manipulate unsigned numbers as unicode strings

1:01 utf16 or what hace you

1:08 jared314: I think that's from reeses pointer-buffer cups

1:08 jared314: danlentz: now i'm hungry

1:12 danlentz: jared314: bytecode

1:15 jared314: (inc danlentz)

1:15 lazybot: ⇒ 1

1:16 jared314: (identity danlentz)

1:16 lazybot: danlentz has karma 1.

1:17 danlentz: jared314: your karma ran over my dogma...

1:18 sorry that joke was pretty lame i know

1:20 so... nicks represent a MUTABLE datatype?

1:21 wouldnt have expected to find that here

1:21 (identity danlentz)

1:21 lazybot: danlentz has karma 1.

1:21 danlentz: how un-ideomatic

1:23 (swap! danlentz inc)

1:23 hmm

1:25 lazybot: learn clojure

1:25 lazybot: My memory is more powerful than M-x butterfly. I won't forget it.

1:33 jared314: no, just a key in, I think, mongodb

1:34 and the inc is just a command it recognizes

1:34 https://github.com/flatland/lazybot/blob/master/src/lazybot/plugins/karma.clj

1:56 danlentz: ztellman: hello -- you are author of byte-streams, gloss, primitive-math, etc?

1:56 ztellman: danlentz: that's me

1:57 danlentz: well you might be the most likely person to have encountered some of the issues i've been worjking through on my maiden voyage in clojure

1:57 ztellman: such as?

1:58 danlentz: i come from a common-lisp background where there are a very powerful means of dealing with unsigned, signed, or even arbitrary bit-vector representations

1:59 as an excercise (and also b/c i need one) i've been working on a more useful UUID library extending java's UUID tyype

1:59 and my issue is to get results that equal those on platforms capable of unsigned arithmetic

2:00 ztellman: well, primitive-math is decent at that

2:00 it's not doing what you expect?

2:00 danlentz: i'm fine, of couse, dealing with everything up to LONG

2:00 y i've played with primitive math

2:01 ztellman: so what's the issue?

2:01 danlentz: the representation of the word one would hope to create by means of

2:01 (bit-shift-left 1 64) is just always going to run into problems even when you

2:01 can create it with unchecked math trickery

2:02 ztellman: at that point you want to use BigInteger

2:02 danlentz: in the end, there is one-less number representable in any given 2s complement

2:02 byte-size than in unsigned of the same width

2:02 ztellman: https://github.com/ztellman/primitive-math/blob/master/src/primitive_math.clj#L247

2:02 that allows arbitrary bitshifting, etc

2:02 danlentz: but bitwise ops are not defined on bigint -- am I missing the obvious?

2:03 ztellman: aren't they?

2:03 one sec

2:03 danlentz: if they were i'd be golden

2:03 ztellman: they are: http://docs.oracle.com/javase/1.4.2/docs/api/java/math/BigInteger.html

2:03 oh, well, that's an ancient versoin

2:03 but anyway

2:03 I'm talking about java.math.BigInteger, not clojure's BigInt

2:04 notice that's what primitive-math/long->ulong gives you

2:04 danlentz: (-> (bigint 1)

2:04 (bit-shift-left 1))

2:04 oh

2:04 ah

2:05 ztellman: yeah, you'll just be using the Java API for this

2:05 but it should do everything you need

2:05 danlentz: well this is why i'm a dunce still -- i didnt realize there was a difference between bigint and BigInteger

2:07 akurilin: Does anybody know if there's a way to force a non-validating SSL connection to PG in Korma?

2:08 In clojure jdbc you can just append sslfactory=org.postgresql.ssl.NonValidatingFactory to the DB address and you'll get an SSL connection even when the server cert is not trusted.

2:08 andyfingerhut_: danlentz: Be slightly cautious with BigIntegers in Clojure. Their hash is not consistent with = when comparing them with other integral types. http://dev.clojure.org/jira/browse/CLJ-1036

2:08 danlentz: Sorry, that is throwing you into more details than you might care to dive into right now, but if you deal with BigInteger types frequently in Clojure that gotcha may come up.

2:09 danlentz: so also the clojure bitwise ops wont work and the whole deal is tyhrough java you're saying

2:09 andyfingerhut_: Clojure bitwise ops work on longs only, I believe.

2:10 danlentz: andyfingerhut_: no worries I'd rather have the idea where dragons be lurking

2:11 andyfingerhut_: It is easy to convert between bigint and BigInteger, but if you work with BigInteger a lot, could be a hassle to remember to do the conversion everywhere necessary. I'd recommend using bigint in most places, and try to isolate BigInteger to only the places you must have it.

2:11 danlentz: BigInteger is going to be relatively slow I'm assuming... but if it's a solution i'll take it

2:12 andyfingerhut_: relatively slow to some other arbitrary precision integer library? Compared to libgmp perhaps, but I haven't measured carefully.

2:13 danlentz: ie coerce to BigInteger where i need to do the bit twiddling

2:13 andyfingerhut_: If you need something bigger than 64-bit ints, it is BigInteger, find someone patient enough to have written their own, or write your own, I would think.

2:13 danlentz: :}

2:13 no 64 bit unsigned values are what i'm trying to represent

2:14 andyfingerhut_: Well, if it is already a bigint, the coercion should just be a cast, I think.

2:14 danlentz: neat

2:14 andyfingerhut: If all you need are 64 bits, why not just use longs?

2:14 danlentz: ugh

2:15 because there are 1 fewer numbers representable in 2's complement signed arth than unsigned

2:15 andyfingerhut: I don't think that is true. There are exactly 2^64 of each.

2:15 danlentz: 2^64 or -0 being illegal

2:15 andyfingerhut: N-bit signed 2's complement values range from -2^(N-1) through 2^N-1, inclusive.

2:15 exactly 2^N values.

2:16 danlentz: 0x8000000000000000

2:16 1000000000000000000000000000000000000000000000000000000000000000

2:16 andyfingerhut: That is 2's complement representation for -2^63

2:16 If I'm guessing that you've got 64 bits there.

2:17 Are you sure you are not thinking of 1's complement representation, where there are separate bit representations of +0 and -0? 2's complement doesn't have that.

2:18 danlentz: user> (long 0x8000000000000000)

2:18 IllegalArgumentException Value out of range for long: 9223372036854775808 clojure.lang.RT.longCast (RT.java:1134)

2:19 andyfingerhut: Put a minus sign in front of it, and you won't get an exception.

2:19 danlentz: so bitmasks that are pretty important like 0xFFFF000000000000 are not representable

2:19 andyfingerhut: They are representable, but they are negative long values.

2:20 danlentz: only (unchecked-neg 0x7FFF000000000000)

2:20 well right 0x8000000000000 is the crux of the issue

2:21 andyfingerhut: I'm not saying that is convenient to use them as unsigned values. I am saying that if you really want to avoid BigInteger, and you only need 64-bit values, longs are 64-bit values, with 2^64 different possible values, and + and - that give the same bit-level answers as unsigned values do.

2:21 danlentz: thats why to represent an unsigned byte one must roll over into shorts

2:21 akurilin: I guess I couldn't find an SSL switch in Korma, but adding ssl=true to the parameters in the connection URL seems to force SSL on.

2:21 andyfingerhut: You can choose to, but you don't have to. signed bytes have 8 bits, just like unsigned bytes do.

2:22 danlentz: a signed byte can't represent 128

2:22 (byte 0x80)

2:22 IllegalArgumentException Value out of range for byte: 128 clojure.lang.RT.byteCast (RT.java:1019)

2:22 andyfingerhut: ,(byte -0x80)

2:22 clojurebot: -128

2:22 andyfingerhut: same bit pattern as unsigned 0x80

2:22 danlentz: signed bytes are -128->127

2:24 its 0xFFFFFFFFFFFFFF80

2:24 andyfingerhut: It might be more productive to talk about what you want to do with unsigned 64-bit values.

2:25 danlentz: well, I need to mask off abitrary bits of a 64-bit word and replace them primarily

2:26 ;; The string representation of A UUID has the format:

2:26 ;;

2:26 ;; clock-seq-and-reserved

2:26 ;; time-mid | clock-seq-low

2:26 ;; | | |

2:26 ;; 6ba7b810-9dad-11d1-80b4-00c04fd430c8

2:26 ;; | | |

2:28 sorry that got me booted ....

2:28 andyfingerhut: danlentz: Links are better.

2:28 danlentz: i'm back

2:29 y sorry abt that

2:29 so the canonical representation of UUID for java is 2 longs

2:30 andyfingerhut: Canonical as in that is how many people choose to store a UUID in Java?

2:30 danlentz: i need to mask off the various fields and takeb thier values as uint8, uint32, uint16 etc

2:31 that is how the java.util.UUID class seems to be implemented

2:32 one can extend type UUID e.g., (get-word-high [uuid]

2:32 (.getMostSignificantBits uuid))

2:32 (get-word-low [uuid]

2:33 (.getLeastSignificantBits uuid))

2:33 andyfingerhut: If you have two longs, the first holding the 6ba7b810-9dad-11d1 part in your example, you can use Zach's primitive-math library to do unsigned right shifts using the >>> macro (I think it is a macro -- maybe a function instead), e.g. (>>> long0 32) = 0x6ba7b810

2:33 Then convert that to a 32-bit int if you wish using unchecked-int

2:36 Clojure does not have an unsigned right shift operation yet, unfortunately, but one may be added in the next release.

2:36 danlentz: but what if those first 4 bytes are 0x80 0x80 0x80 0x80

2:37 andyfingerhut: bits are bits. Try this:

2:37 after doing (use 'primitive-math) on Zach's library

2:37 (format "%08x" (unchecked-int (>>> -0x8000000000000000 32)))

2:38 You should get out 80000000

2:38 (the string)

2:38 amalloy: ,(format "%08x" (unchecked-int (>>> -0x8000000000000000 32)))

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

2:38 amalloy: oh right, haha

2:39 andyfingerhut: >>> is part of primitive-math lib, not Clojure

2:40 danlentz: ah -- you're right

2:41 using unchecked-int afterwards is what I was missing

2:41 wow I think that really helped me out

2:41 andyfingerhut: It is easy to freak out about Java not having unsigned types, but except for the numerical ranges of values they are normally printed or read as, signed and unsigned integers fill the hardware registers the same way

2:41 danlentz: thanks for sticking with me through that

2:42 andyfingerhut: np. A-ha moments are a beautiful thing to have and behold.

2:42 danlentz: its been about a month now I've been banging my head on this

2:43 >>> = primitive-math/bit-unsigned-shift-right, yes?

2:43 andyfingerhut: format with %x is a nice way to print ints as unsigned values. There might be %u, too. Not sure about reading them, but I can experiment a bit.

2:44 Yes. Just a bit shorter :)

2:45 danlentz: and (type -0x8000000000000000) = Long

2:45 dear god i think this may help end my struggle!

2:45 (inc andyfingerhut)

2:45 lazybot: ⇒ 2

2:47 andyfingerhut: Looks like Java/Clojure's format is good for printing byte/short/int/longs as unsigned octal or hex, but I don't see a good way to do it in decimal unsigned.

2:47 danlentz: of course (type 0x8000000000000000) = clojure.lang.BigInt so some care is still in order w.r.t edge cases

2:48 andyfingerhut: Yes, that value is not a signed 64-bit long value.

2:48 danlentz: ive been using

2:48 (defn pphex [x]

2:48 (returning x

2:48 (cl-format *out* "~&~A [~64,'0b]~%"

2:48 (format "[%1$016X] " x) x)))

2:50 andyfingerhut: All of what would be unsigned long values from 0x8000_0000_0000_0000 through 0xFFFF_FFFF_FFFF_FFFF are signed values that are numerically 2^64 smaller than those unsigned values. But their bit representations are exactly the same as those unsigned values.

2:50 I have not seen 'returning' before. What is that?

2:50 danlentz: oh

2:51 its analogous to common-lisp's prog1

2:51 (defmacro returning

2:51 "Compute a return value, then execute other forms for side effects.

2:51 Like prog1 in common lisp, or a (do) that returns the first form."

2:51 [value & forms]

2:51 `(let [value# ~value]

2:51 ~@forms

2:51 value#))

2:51 andyfingerhut: ok, familiar with that one.

2:51 SegFaultAX: danlentz: Probably easier not to do multi-line paste in the channel.

2:51 refheap or gist are better options :)

2:52 danlentz: dunno how you guys live4 w/o it :)

2:52 andyfingerhut: will (print (format "%016x" x)) work just as well as the cl-format expression?

2:52 danlentz: SegFaultAX sorry

2:52 andyfingerhut: Oh, unless you are trying to get out binary.

2:52 danlentz: y had issues getting binary w/o cl-format iirc

2:53 SegFaultAX: danlentz: No problem, just something to keep in mind.

2:54 danlentz: btw i really love clojures auto-gensyms or whatever they're called

2:55 andyfingerhut: (Long/toBinaryString -0x8000000000000000)

2:55 danlentz: makes with-unique-names and once-only seem somewhat barbaric

2:55 andyfingerhut: Java method I just Googled.

2:56 danlentz: ooh. fantastic

2:56 andyfingerhut: The cl-format method you showed gave me an error when I tried it with that argument. Probably a bug.

2:58 danlentz: but wait the toBinaryString doesnt left-pad 0's

2:58 amalloy: danlentz: i wrote that `returning` function you pasted, but i can confirm it's pretty easy to do without since most of the time clojure functions are side-effect-free

2:59 danlentz: still easily remedieds

3:00 amalloy: y I didn't mean to omit the proper attribution -- just playing fast and loose to convey the idea

3:01 amalloy: no, i don't mind. just that you said you don't know how we live without it: it's easy if you avoid side effects. i'm pretty sure i haven't used `returning` for months

3:03 danlentz: amalloy: I copy-pasted it rather than call yours b/c I have a couple of extra tweaks in my utils.clj like an extended "returning-bind" version

3:04 analogous to the way paul grahams anaphoric aprog1 works without the lexical injection of an 'it binding

3:06 but "returningf" was a really nice choice of name much more aesthetic and semantically transparent than APROG1 for sure

3:06 "returning" that is

3:08 andyfingerhut: Hmph. I forgot that cl-format with 0-padding is not a good fit for negative numbers.

3:08 danlentz: i guess returning-bind might be more clojurishly named returning-let to be consistent with when-let, if-let etc... bind is a somewhat common-lisp centric terminology as symbols and bindings work somewhat differently....

3:10 mythz: Hey guys if anyone's interested I've just published a port of C#'s 101 LINQ examples to Clojure at: https://github.com/mythz/clojure-linq-examples - As I'm just starting out myself, any suggestions to improve readability or make the examples more idiomatic is welcomed!

3:11 danlentz: andyfingerhut: yes, the clojure implementation is unfortunately true to the CL version in that regard

3:11 i really hate format TBH

3:12 andyfingerhut: Java/Clojure's format is more like C's printf, and fortunately does not have that quirk of CL format / Clojure cl-format

3:12 danlentz: the only reason I use it is a profound disgust for all the alternatives....

3:14 but there is no simple clj.core/format recipie that will handle left-padding the result of (Long/toBinaryString x) with 0's -- or is there?

3:15 andyfingerhut: Not that I know of. If you want it, probably easiest is to write your own simple 0-padding function on strings.

3:16 danlentz: y just checkin --- you've been on a roll so I figured I'd ask just in case :)

3:17 i hadnt noticed the cl-format issue before

3:17 i'm sure there is a means of circumventing it

3:18 people do really magical things wioth cl-format

3:18 (unfortunately I'm not one of them..)

3:19 abaranosky: "hey"

3:21 egghost:

3:21 sorry for the spam guys... I'm learning to use IRC via Emacs, and making noob mistakes. :\

3:25 sszzqq: Cloujure could run in JVM & CLR, I think it could run in Perl/Ruby/Python, even Common Lisp.

3:27 abaranosky: sszzqq: it could!

3:27 andyfingerhut: tbaldridge (I think) wrote https://github.com/halgari/clojure-py

3:28 abaranosky: andyfingerhut: yep, that's by Tim Baldridge, indeed

3:28 sszzqq: Clojure could transfer to Javascript, I think it also could transfer Lua/Ruby/Perl/...

3:28 abaranosky: I wonder, is it production quality?

3:28 my impression is that only JVM Clojurea nd ClojureScript are indeed production ready

3:29 danlentz: andyfingerhut: how about https://www.refheap.com/20284

3:29 andyfingerhut: danlentz: Your cl-format-fu is certainly stronger than mine :)

3:30 SegFaultAX: A number of implementations have been started including Python and Lua. I don't think they've seen much work, though.

3:30 andyfingerhut: abaranosky: tbaldridge is probably the best to comment on production-worthiness of clojure-py. Clojure CLR has a few users, I think, but I've never tried it.

3:30 SegFaultAX: Hopefully Clojure in Clojure will bring down the barrier to entry for new impls.

3:31 abaranosky: andyfingerhut: cl-format is a wonder to behold

3:32 andyfingerhut: and to be fair, these are only my *impressions*, not actual facts :)

3:32 andyfingerhut: abaranosky: Yes, every time I see an even slightly complex example of it, I wonder :)

3:32 danlentz: andyfingerhut: its pretty flimsy actually -- kind of a punt to use cl-format and clj.core/format both like that I think

3:32 but a punt which works...

3:32 SegFaultAX: abaranosky: How's Staples?

3:33 andyfingerhut: danlentz: yes, it does work. You could simplify its format string to [%016X]" I think.

3:33 danlentz: Unless you like being explicit about argument position numbers.

3:34 SegFaultAX: abaranosky: How has the transition been for Runa?

3:34 danlentz: actually i've discovered that cl-format gives much much more informative error messages than CL format (at least under SBCL and prob most othetrs)

3:34 abaranosky: SegFaultAX: hey do I know you by real-life name? re: Staples, the acquisition has been really great. We've got ~5 planned machine-learning-based projects to improve conversion rates on the stples online store

3:35 we're remodelling the whole office, and in general expanding excitedly

3:35 SegFaultAX: abaranosky: We met at that prismatic thing a couple weeks ago.

3:35 danlentz: clojure.pprint/cl-format, correspondingly, is a hell of a lot easier to deal with

3:35 SegFaultAX: abaranosky: That's awesome! Congratulations again. :)

3:35 abaranosky: SegFaultAX: as far as transition I'd say it feels mostly the same, but witha transition to a one merchant focus

3:36 SegFaultAX: I'm always curious to see how little companies transition into big companies, especially via acquisition.

3:36 abaranosky: SegFaultAX: what's your name again? I met alot of people at the prismatic meetup

3:37 SegFaultAX: Staples is explicitly keeping us separate from the huge monoithic company structure, so as to give some innovation to pipe back into the mohtership

3:37 SegFaultAX: abaranosky: Michael-Keith (MK). Same nick on twitter if you're better with faces.

3:38 abaranosky: ah nice, recognize the face now :)

3:38 SegFaultAX: abaranosky: Is the Runa group dropping all the branding in favor of the Labs title?

3:39 abaranosky: I watched these videos by Tie Baldridge and loved them: http://www.youtube.com/watch?v=R3PZMIwXN_g&noredirect=1

3:39 yeah, we're not Runa anymore

3:39 but I hate saying Stples Innovation Lab. Too long.

3:39 clojurebot: excusez-moi

3:39 abaranosky: and SIL isn't very pronouncable

3:40 SegFaultAX: No, I don't suppose it is. Haha.

3:40 abaranosky: SIL is now going to be responsible for creating a variety of services to feed to the website... things like intelligent search, and recommendations engines

3:41 SegFaultAX: Is the scope pretty open or do you have specific projects?

3:42 abaranosky: specific projects for the first 6 months we've got planned, but as time goes by the scope will expand to more services as the business folks think of more

3:43 SegFaultAX: That's pretty great. Plus you probably have massive databases of data to train on.

3:43 abaranosky: yeah, and we've got allllllll of staples data too

3:44 Right now, we're looking to expand our developer-pool and data scientisit pool a ton. We'll be at Clojure Conj with a tables setup recruiting I'm sure.

3:45 SegFaultAX: abaranosky: Is Staples all Java on the backend?

3:45 At least from the web side.

3:46 abaranosky: youmean the mothership right?

3:46 they're using WebShpere ... the innovation lab has only a very small few files of Java

3:46 :D

3:48 SegFaultAX: "They're" don't you mean "we"? ;)

3:53 jared314: is there something like doseq without the bindings? i'm code golfing

3:53 abaranosky: SegFaultAX: "They" referring to the mothership

3:54 SegFaultAX: Is mothership staples in this instance?

3:54 abaranosky: jared314: `dotimes`

3:54 llasram: jared314: `do`? I'm not sure how the `seq` part would work w/o bindings :-)

3:54 abaranosky: the main Staples org... it's not an official term, hehe

3:54 llasram: jared314: Unless you mean `doall`/`dorun`

3:55 abaranosky: llasram, jared314: yeah depends what the code is actually doing

3:55 jared314: llasram: i need the side effects but not the result

3:55 https://www.refheap.com/20285

3:55 llasram: Sounds like `dorun`

3:56 jared314: llasram: but i need the looping

3:56 llasram: jared314: OOC, what is that macro doing which it would be difficult to do in a function?

3:56 abaranosky: llasram: seems like 'nothing'

3:56 llasram: jared314: `dorun` walks a lazy seq, forcing all side effects, but discarding the results and not holding the head

3:57 If you actually need to do something with each value, then you do need the bindings

3:57 jared314: i have to print them

3:58 llasram: You could (dorun (map println col)), but `doseq` is about the same length and clearer

3:58 abaranosky: jared314: if it were jusst printing I'd say to do something like (apply println (map f s2)) ... but you are also calling read-line

3:58 jared314: yeah, that is the hard part

3:58 abaranosky: when you have IO peppered in a function, it is hard to avoid this kind of verbose procedural code

3:59 jared314: abaranosky: and it has to be a macro because doc arguments

4:00 abaranosky: you could do: (apply println (interleave i# (repeat "\n"))) but this is longer and weirder than your implementation :D

4:01 jared314: previously i was using println string/join, but doseq println is shorter

4:01 abaranosky: it is shorter and cleaner

4:02 llasram: jared314: doc arguments?

4:02 SegFaultAX: Well presumably if you're golfing, it doesn't matter how weird it is.

4:02 As long as you're shaving bytes.

4:02 Bytes are like yaks, all of them must be shaved.

4:02 abaranosky: yeah, I guess I'm not really a golfer in my heart of hearts

4:02 llasram: Oh, calling `doc`

4:03 jared314: the point of it is to paginate the output of doc

4:03 abaranosky: what type does 'doc' expect

4:03 jared314: doc is a macro

4:03 llasram: It's unfortunately a macro :-/

4:03 SegFaultAX: Lisps don't tend to be the best golfing langs in my experience.

4:03 Golfing is one time where the parens really do bite you.

4:04 abaranosky: SegFaultAX: they come pregolfed in a sense

4:04 jared314: then clojure needs more arrows

4:04 abaranosky: not golfed like Perl..., but compared to most languages, you don't have much cruft you can pull out

4:05 SegFaultAX: Heh, well perl golfing is a different level.

4:05 abaranosky: if you want to know, a better way to write this is to make doc2 a macro, but then implement sa fn like doc2-fn that implements everything execpt for the (split-at ....) sexp

4:05 SegFaultAX: That's Odin-tier golfing, and only because of metavars.

4:06 abaranosky: ... hmmmm , I think I'm too tired to think this through fully, but it looks suspect to need tha tmany lines of macro code

4:06 SegFaultAX: Err perlvars rather.

4:07 abaranosky: Perl really is the only *true* golfing imho

4:07 jared314: I found a way to trim your code!!!

4:08 SegFaultAX: Well and J/K/APL

4:08 But when you invent your own glyphs, that's sort of cheating isn't it?

4:08 jared314: abaranosky: ?

4:08 abaranosky: add (let [p# println]) then call p# everywhere instead of println

4:08 that saves you a few chars right?

4:09 SegFaultAX: jared314: Nevermind golfing, convert your macro to swearjure if you want to be truly elite.

4:10 abaranosky: SegFaultAX: life is not fair

4:10 jared314: i saw that presentation, it was in line with bf and whitespace

4:10 abaranosky: take it easy gents, time for bed :)

4:11 SegFaultAX: Me too, night.

4:15 jared314: oh well, i think it is as short as i'm going to get it right now

4:17 amalloy: jared314: (.. getTerminal getHeight) is shorter as .getTerminal .getHeight

4:18 jared314: amalloy: not with the extra parens

4:18 amalloy: what extra parens?

4:18 just put in what i wrote

4:18 jared314: oh using the arrow

4:18 true

4:19 amalloy: and of course your doseq could be a local fn: (let [q# #(doseq [x# %] (p# x))] ...) should save a couple characters

4:23 jared314: thanks for the help, i'm going to call it a night

4:56 algal: I notice "lein deps :tree" helpfully warns me that some of my project dependencies don't get along well. It seems like their transitive dependencies are over-riding each other. can anyone point me to a link on how to think about or solve this problem?

4:58 beppu: (for all the grief javascript gets, the one thing they got very right was the ability to load multiple versions of the same library)

5:02 vijaykiran: algal: you can use exclusions to get rid of unwanted depenedencies

5:02 algal: e.g., https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L47

5:02 algal: beppu: I take it that we can't do that in JVM-land, that's why leiningen etc need to have a policy to choose just one version of the library, and that's why it gives warning when different project components depend on different versions?

5:04 beppu: algal: I believe that's the case (but I'm new to Clojure and I don't have much experience w/ JVM langs, so I can't say for sure) </disclaimer> ;)

5:04 algal: vijaykiran: Is there any documentation on exclusions that is not maven documentation?

5:05 vijaykiran: algal: I'm not aware of any OTOH, but dependency management is done via maven deps - so that docs should be helpful

5:05 clgv: beppu: algal: well even in theory ths dependency problem seems not solvable as soon as you depend on two incompatible versions of a library and need to pass data between them through the transitive call hierarchy

5:06 algal: clgv: I would settle for the problem being solvable in practice.

5:06 clgv: algal: you just exclude the lib in the dependency that pulls in the undesired version

5:07 algal: So (dumb question, maybe) what's the rule of thumb here, when lein deps :tree spits out an alarming cascade of warning about override leading versions ?

5:07 clgv: algal: not really on the technical site but on the social site by pushing the maintainer of the lib that transitively pulls in an old version of the conflicting lib to upgrade ;)

5:07 algal: Should I spend my days lovingly curating a set of exclusion declarations so that the project only pulls the latest and greatest?

5:08 clgv: algal: well in practice I have only one or two exclusion statements per project

5:08 beppu: the social solution seems to be the best course of action

5:09 mindbend`: what's the most popular to automate deployment of clojure applications?

5:09 clojurebot: Excuse me?

5:10 mindbend`: clojurebot: I'll strangle you now

5:10 clojurebot: I don't understand.

5:12 clgv: mindbend`: there is pallet but I don't know about its general popularity

5:12 mindbend`: for deployment to several remote machines

5:12 algal: what decides what overrides what? Is it the order of dependencies in my ns form dictating the order of jars which dictates the lookup order in the classpath?

5:12 clgv: algal: afaik lein just picks one of the versions

5:13 algal: at random, each time? Inconceivable. Mr Technomancy is all about repeatability. So there must be a rule that makes it deterministic.

5:13 clgv: algal: no, not at random

5:14 algal: you gotta look up what rule is used since I did not care too much for that yet to investigate it

5:15 algal: clgv: seems like dependency order is driving it, presumably via jar order -> class path order.

5:19 clgv: algal: huh? I thought you meant the rule that selects the version of the dependency that is transitively depended on in two different versions

5:19 algal: clgv: I did.

5:20 clgv: algal: so why are you talking about classpath order then?

5:21 algal: clgv: because I think dependency order is translating into classpath order, and so the dependency order is determining which transitive dependencies are shadowed by earlier items on the classpath.

5:21 llasram: algal: Leiningen picks one version of any given dep to put on the classpath, using the same algorithm as Maven.

5:21 algal: llasram: agreed. what is that algorithm?

5:22 clgv: algal: no. there is only one version of the lib on the classpath

5:22 llasram: Order by (top-most, earliest)

5:22 clgv: algal: everything else would be insane ;)

5:22 llasram: So dependencies you specify override transitive deps. Deps directly specified by any of your deps beat further transitive deps, etc

5:22 Any conflicts at the same depth are resolved by earliest-first

5:23 algal: llasram: "earlier" in time? in version number? in what?

5:23 llasram: Earlier in the dependency list

5:23 Yeah, wasn't clear :-)

5:23 algal: llasram: aaah! okay.

5:24 llasram: thanks,this is enlightening.

5:24 feels sort of impossible to understand clojure's tooling without understanding Java's, which is sad.

5:25 clgv: algal: thats just wrong since leiningen is clojure tooling

5:25 llasram: It's more to take on to really master the ecosystem, but also is part of how much leverage you get with Clojure

5:27 algal: thanks for the help, chaps. g'night.

6:32 nonuby: when in a http-kit (async http client) callback if I want to push a result on a core.async.channel presumably I use the blocking version of 'put' >!! since the http-kit has a seperate threadpool

6:33 since it doesnt make sense to stick the work of pushing onto a channel on to the core.async threadpool ?

6:50 andrewmcveigh: Hi, I have a macro 'with-action, and I'd like it to know whether it's called within itself E.G., (with-action :beat-up (some-fn (with-action :kick ...))) - is there a non-awful way for the action :kick to know that it's part of a larger action :beat-up?

6:51 not a very good example... I know.

6:56 llasram: andrewmcveigh: Depending on what you're trying to achieve, there's a few different approaches...

6:56 Does `with-action` need to its scope during macro-expansion, or during evaluation?

6:57 s,need to,need to know,

6:58 andrewmcveigh: llasram: Well, I'm just toying around. Essentially, I'm trying to transform the body of code passed into it. But I'd like the transformation to be a bit different if it's called within a larger action.

6:58 So macro-expansion time, I guess?

7:00 llasram: Ok, in which case "within" can only mean "within the lexical scope of the larger action" -- if arguments contain function calls which contain more `with-action` calls, you have no way of impacting them

7:01 So then probably the easiest thing to do is use clojure.walk or one of the libraries specific to code-walking macros and modify the `with-action` calls to contain the full stack of actions within scope

7:02 I believe ztellman's is the most complete ATM: https://github.com/ztellman/riddley

7:02 Note that if you want this to be something which happens at run time via dynamic scope, it's waaaaay easier :-)

7:05 andrewmcveigh: llasram: Thanks. Not done any code-walking stuff yet. Mostly shyed away from it...

7:06 Maybe it's time to have a look... I have a week off work :)

8:17 Jarda: is there a 'standard' equivalent for the nodejs NODE_ENV variable?

8:32 glosoli: Hey, any ideas what could be wrong with such interop in for https://www.refheap.com/4b0b8a303448d107f745a02d2 I get index out of bounds exception, I am sure it retrieve page object properly

8:44 jkkramer: glosoli: for is lazy and would be realized after the stream has been closed. wrapping it in (doall) should help

8:45 glosoli: jkkramer: thank sir, you saved me a headache! :)

9:19 arrdem: 3

10:02 Jarda: hi

10:03 if if I have a vector [1 2 3 4 5 6] how can I multiply 1 and 4 by 2, 2 and 5 by 3, 4 and 6 by 4

10:03 I tried take-nth but couldn't get it to work as I wanted

10:04 should I use map-indexed and check if index is dividable by 3 etc

10:05 ToBeReplaced: Jarda: i don't understand the algorithm.... can you put a more involved example?

10:06 Jarda: ToBeReplaced: the algorithm is the following: starting from left multiply first item by 2, second item by 3, third item by 4, fourth item by 2, fifth by 3, sixth by 4, seventh by 2 ... etc

10:07 ToBeReplaced: okay, you're down the right path -- you need map-indexed because you require the index

10:09 there's a few other cutesie ways that don't involve the division -- ex. partition and map cat +

10:09 ,(doc cycle)

10:09 clojurebot: "([coll]); Returns a lazy (infinite!) sequence of repetitions of the items in coll."

10:10 ToBeReplaced: so something like (map + v (cycle [2 3 4])) is prob sufficient

10:11 ,(map + (range 1 7) (cycle [2 3 4]))

10:11 clojurebot: (3 5 7 6 8 ...)

10:28 jcromartie: I'm patiently waiting for a paradigm that completel eliminates complexity in information systems.

10:28 clgv: jcromartie: could there ever be such a thing from a theoretical perspective?

10:33 milanj: how to set emacs/nrepl for loading clojure code that is part of java source tree

10:33 jcromartie: clgv: I don't know. I am becoming increasingly convinced that software is governed by the same laws of entropy as any physical system.

10:34 I haven't studied any systems engineering, though. My brother did his MS in systems engineering, and has gone on to write big-ball-of-mud software in PHP and Perl so far.

10:34 (for wall st)

10:35 clgv: jcromartie: PHP and Perl? *shudders*

10:35 jcromartie: not exactly HFT or anything, just conservative traders doing modelling

10:35 I can definitely buy the whole functional over OOP thing for reducing complexity at some level

10:36 but I think as an industry we just have no idea what we're doing

10:36 clgv: jcromartie: good intro to go back to call it "art of computer programming" ;)

10:36 jcromartie: "There are only two kinds of languages: the ones people complain about and the ones nobody uses."

10:38 so we have all these high-level many-moving-parts kind of solutions to complexity

10:39 I like what I'm seeing in dnolen's work with core.async in clojurescript

10:39 but there's no silver bullet right

10:39 clgv: jcromartie: fo mankind's sake I hope PHP will move to the second kind

10:39 jcromartie: but you can't argue that people get stuff done

10:40 and there's really no way to tell, from the outside, if some successful system is written in PHP or Clojure or Brainfuck for that matter

10:40 as long as we're talking about an opaque system that takes strings and turns them into other strings

10:40 clgv: jcromartie: but the problem is you can't measure how much money is wasted that way also if you consider security issues

10:44 jcromartie: http://en.wikipedia.org/wiki/No_Silver_Bullet

10:54 dav: How can I get clojure.pprint/pprint to print recursive hashes on multiple lines and with indent?

10:58 devn: dire looks pretty neat

11:00 also, the datomic console -- excited to try that out

11:00 mdrogalis: devn: Thanks.

11:03 jcromartie: the pretty printer source code is something else

11:03 clgv: mdrogalis: does dire match exceptions to superclasses yez?

11:03 *yet

11:04 mdrogalis: clgv: Next release, probably 2 weeks away. Need to figure out how to specify priorities

11:04 If you have a subclass, superclass, and predicate, which gets evaled first?

11:05 jcromartie: it looks a lot like your average mutable Java object design but with another level of indirection

11:05 https://github.com/clojure/clojure/blob/master/src/clj/clojure/pprint/pretty_writer.clj

11:05 clgv: oh nice. I was struggling with that when wanting to use dire for debugging

11:06 mdrogalis: I frankly just never thought of it until lately. :P

11:06 jcromartie: a struct with several refs in it :|

11:06 mdrogalis: I'm emailing with someone who has an idea about it. I can make a GitHub issue for public discussion if you want to weigh in.

11:06 jcromartie: there has got to be a better way to make a pretty printer

11:08 clgv: mdrogalis: wont hierarchies with prefer-statements work?

11:08 cmajor7: jcromartie: https://github.com/brandonbloom/fipp ?

11:08 mdrogalis: clgv: Yeah, that is kind of what I was thinking.

11:08 Sort of how multimethods do it.

11:09 jcromartie: cmajor7: nice

11:14 jtoy: why cant I turn a string into a buffered io stream with (clojure.java.io/input-stream "asdasd")? according to the docs I think that should work?

11:14 ,(clojure.java.io/input-stream "asdasd")

11:14 clojurebot: #<SecurityException java.lang.SecurityException: denied>

11:15 cmajor7: jtoy: (ByteArrayInputStream. (.getBytes s)) ?

11:16 llasram: jtoy: Try: ##(-> "example" .getBytes clojure.java.io/input-stream)

11:16 lazybot: ⇒ #<BufferedInputStream java.io.BufferedInputStream@1713e71>

11:17 llasram: jtoy: The default conversion pathway for strings tries to treat them as filenames

11:17 But byte arrays ^^

11:19 jtoy: cool, testing it out

11:23 drorbemet: Hi, did any body use the 7-Zip-JBinding library http://sevenzipjbind.sourceforge.net/index.html ? Would you be so kind and direct me to som hints on how to use java libraries of this kind in clojure? Untill now I didn't had to deal with java exeptions and the like in clojure code.

11:26 joegallo: http://clojure.org/java_interop

11:27 and http://clojure.org/special_forms#Special%20Forms--%28try%20expr*%20catch-clause*%20finally-clause?%29

11:27 you can translate their example http://sevenzipjbind.sourceforge.net/snippets/GetNumberOfItemsInArchive.java into clojure pretty straightforwardly

11:28 i usually start by pasting the java into a clj buffer, and then editing it into parens...

11:28 jtoy: llasram: cmajor7: yes, it worked!! thanks: (-> @(httpkit/get url :body .getBytes clojure.java.io/input-stream parse-feed :entries)

11:28 joegallo: then the .close calls become with-opens, and any assignments become lets

11:28 next thing you know, bam, it's working ;)

11:33 drorbemet: Ah, thanks, slowly I get going, have a nice day :-)

11:35 joegallo: you're welcome. if you end up with something that's not quite working, just check back in. you can paste your code using a paste-bin like refheap.com and folks can give you pointers on where you might be going astray

11:35 good luck!

11:37 Jarda: hi

11:37 if I have a number X, how can I find the distance to number Y where Y is the next number with Y % 10 == 0

11:38 so fo 84 I'd like to return 6 (84+6=90)

11:39 clgv: Jarda: integer division by 10, add 1 multiply by 10

11:39 jcromartie: is this homework?

11:39 Jarda: jcromartie: nope

11:39 jcromartie: :P

11:39 Jarda: I'm just having hard time with math today

11:39 and thought there would be some 'ceil' function that would have the precision

11:39 clgv: Jarda: I described how to find Y. above

11:40 Jarda: clgv: yeah thanks

11:40 jcromartie: (defn next-po10 [n] (* 10 (inc (int (/ n 10)))))

11:40 clgv: (defn next-po10 [n] (* 10 (inc (quot n 10))))

11:41 more readable as seq of operations (defn next-po10 [n] (-> n (quot 10) inc (* 10)))

11:41 Jarda: thanks

11:41 hyPiRion: yeah

11:41 joegallo: what's the desired answer for 80? 80, or 90?

11:42 i mean, sure 81 -> 90, but what about 80?

11:42 clgv: 6 I guess

11:42 Jarda: joegallo: actually 80 would be fine

11:42 clgv: harr good one. he said "next" which I interpreted as greater relation ;)

11:42 hyPiRion: joegallo: next number

11:42 Jarda: but I can special case

11:42 joegallo: also, do you want the number (86 -> 90), or do you want the distance (4)?

11:43 jcromartie: clgv: nice refactor

11:43 Jarda: the distance actually

11:43 joegallo: ,(- 10 (rem 86 10))

11:43 clojurebot: 4

11:43 joegallo: there ya go

11:43 clgv: yeah right distance via modulo is easier ^^

11:43 Jarda: thanks

11:43 I knew there's an elegant solution

11:44 jcromartie: yeah

11:44 Jarda: it's been a while since I last did basic math in uni..

11:44 joegallo: :)

11:44 hyPiRion: joegallo: actually, that should be mod instead of rem if you need to support negative integers

11:45 joegallo: true enough

11:45 hyPiRion: ,(map (fn [f] (- 10 (f -12 10)) [rem mod])

11:45 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

11:45 hyPiRion: ,(map (fn [f] (- 10 (f -12 10))) [rem mod])

11:45 clojurebot: (12 2)

11:52 jcromartie: this is a weird construct: (= (pos? num) (pos? div))

11:52 isn't that logical nor?

11:52 bbloom: seems reasonable to me

11:52 jcromartie: wait no

11:52 bbloom: assuming it makes sense in context

11:53 jcromartie: yeah I guess boolean equality is the right operator

11:54 bbloom: comparing if two booleans are equal is (comp not xor)

11:55 silasdavis: How can I cycle a list: [1 2 3] -> [2 3 1]

11:55 ?

11:55 or the other way

11:56 joegallo: ,(vec (take 3 (drop 1 (cycle [1 2 3])))

11:56 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

11:56 joegallo: ,(vec (take 3 (drop 1 (cycle [1 2 3]))))

11:56 clojurebot: [2 3 1]

11:56 llasram: silasdavis: reverse...?

11:56 Oh, you want to rotate

11:58 silasdavis: yes

11:59 hyPiRion: ,(let [q (into clojure.lang.PersistentQueue/EMPTY [1 2 3]) elt (peek q)] (-> q pop (conj elt)))

11:59 clojurebot: #<PersistentQueue clojure.lang.PersistentQueue@7c3f>

11:59 hyPiRion: If you need performance, keep it as a queue

12:01 sritchie_: hey guys, has anyone here used clojurescript for a chatroom-like application?

12:01 I'm working on an example that uses websockets and redis pubsub behind the scenes to communicate between nodes serving the chat room -

12:02 most examples keep a map {userID -> websocket} around

12:03 with multiple chat rooms, I guess the way to go forward would be to keep a nested map of {room -> {id -> websocket}}

12:03 silasdavis: hyPiRion: thanks, why elt?

12:03 hyPiRion: because you need to push the element back in

12:04 read as: set elt to the first element in the queue. Then remove the element and conjoin it to the end

12:11 silasdavis: no sorry I just wondered what elt stood for

12:12 element

12:12 right

12:12 looks like clojure.contrib.seq-utils has a rotations that would do what I'm after

12:12 but I cant' find that on clojars

12:12 or on the clojure git hub

12:18 llasram: silasdavis: it's a dead contrib

12:19 ToBeReplaced: sritchie: that's an example pedestal app if you google it

12:19 llasram: silasdavis: But easy enough to write as a function: ##((fn rotate [n coll] (->> (cycle coll) (drop n) (take (count coll)))) 1 [1 2 3])

12:19 lazybot: ⇒ (2 3 1)

12:23 gfredericks: does kibit suppress unused-argument warnings if the arg starts with _?

12:24 silasdavis: llasram: better/worse?: (let [x [1 2 3]] (map (fn [n _] (concat (drop n x) (take n x))) (range) x))

12:25 oh I want all rotations, but is cycle better than concat

12:25 llasram: `cycle` uses `concat`, so really doesn't matter

12:30 jonasen: gfredericks: not sure what you mean?

12:32 sritchie_: cemerick, as the resident cljs genius, I have a quick design Q to run past you

12:32 if you have a second

12:33 cemerick: sritchie_: sure, but LOL, wtf, etc ;-P

12:33 sritchie_: haha

12:33 cemerick: I play Curly to dnolen's Moe.

12:34 sritchie_: I wouldn't be surprised to find out that dnolen is, in addition to being a javascript coder at NYT, cljs committer, also a war journalist, columnist, etc

12:34 somehow getting all of it done

12:34 cemerick: it's actually just my question from above, I'm just trying to flatter you to rope you in to answering :) I'm getting my websockets on in cljs,

12:35 with core.async

12:35 and the single chat room example that every has, using redis's pubsub to broadcast new chat messages between servers so they can tell the relevant websockets, is pretty clear

12:36 with a single chat room, each server instance maintains a map of userID -> websocket;

12:36 my Q is, if I want to tackle multiple chat rooms, is the "right way" to keep a nested map of room -> userid -> websocket?

12:36 dnolen: cemerick: your analysis of 643 looks good, been wanting to clean this up for a while - also it's why we have spurious protocol errors, race condition on namespaces since it's not currently thread safe - it should definitely be dynamically bindable

12:36 sritchie_: now that I type it out it sounds like that's the only damned way

12:37 cemerick: sritchie_: in {room -> {id -> websocket}}, what's the point of `id`?

12:37 oh, userid....? Is this P2P?

12:38 tbaldrid_: cemerick: apparently not if he's using redis to route the messages

12:38 sritchie_: well, I guess I should be specific. What I'm actually trying to do is create a "live results" feature

12:38 for various athletic events

12:38 cemerick: tbaldrid_: oh, didn't catch that part

12:38 sritchie_: so, there might be five events going on at some race (men's, women's, 1 man boat, 2 man, etc)

12:38 and the race organizer is timing the thing and firing new results up to the server

12:39 so I'm trying to write a page that will allow new results to show up as they're posted for each event

12:39 cemerick: dnolen: I think we can get back to how e.g. ~1853 worked w.r.t. downstream tools/usage with a minimal set of changes. What are your specific concerns re: namespaces?

12:39 dnolen: cemerick: I don't really have any except that tools should be able to bind it to have thread safe builds

12:39 but also REPLs

12:40 sritchie_: cemerick: tbaldridge_: I guess if sockets have proper equality I could keep a map of eventID -> Set[WebSocket]

12:40 cemerick: dnolen: I think being able to provide a compilation environment will superset that; there's no doubt that namespaces is touched the most of all though.

12:41 dnolen: cemerick: are you talking about some longer term thing - I don't see how the compilation environment fixes thread races on namespaces

12:41 NeedMoreDesu: Can I do something like this in clojure: start a background thread doing something, and on some part of calculations it executes some code back in main thread? like (future (let [result (heavy-calculations)] (execute-in-main-thread (some-thread-context-fn result))))

12:41 cemerick: sritchie_: If you have a single upstream producer, then why not have a single websocket/SSE source, and merge events it sends down into a top-level model? You can then watch/react on an atom holding that model to disperse bits of data into your view(s).

12:42 tbaldridge_: sritchie_: and I don't imagine that you would have billions of race results a minute, so why not send all the updates to all the websockets?

12:42 clgv: NeedMoreDesu: will your main thread be idle until the event?

12:42 sritchie_: tbaldridge_: and just have them filter the ones they want?

12:42 cemerick: sritchie_: Javelin does this for simple cases, pedestal front-end for more complex models...and CRDTs if you want the superset of 'em.

12:42 NeedMoreDesu: Nope, it'll execute something.

12:43 tbaldridge_: sritchie_: yep, just do client side filtering

12:43 sritchie_: that's a good call, actually

12:43 since, yeah, we're not talking much data here :)

12:43 NeedMoreDesu: I know I can deref or test if future is finished time to time, but that's not very convinient.

12:44 cemerick: dnolen: nothing longer-term; each compilation environment would be entirely separate. Races would be nigh-impossible.

12:44 clgv: NeedMoreDesu: I thought of using a promise either blocking or querying whether it is delivered

12:44 sritchie_: cemerick: that's a good route, for sure, but I'm more wondering how to do the routing to the right clients

12:45 clgv: NeedMoreDesu: you'll have to provide more details I guess

12:45 sritchie_: but tbaldridge_'s solution seems like the right one for now, then fix it in a year when we're at twitter scale and processing 10k races / sec

12:45 tbaldridge_: sritchie_: that's a whole lotta running :-P

12:45 technomancy: aren't you at twitter scale already?

12:45 sritchie_: tautologically, yes

12:46 cemerick: sritchie_: You mean if a client is looking at a subset of races? Yeah, I'd just send everything until it matters, as tbaldridge_ suggests.

12:46 * technomancy nods sagely

12:46 silasdavis: is pop on a PersistentQueue constant time?

12:46 tbaldridge_: silasdavis: pretty close

12:46 silasdavis: but count wouldn't be?

12:47 dnolen: cemerick: not following at all, what will happen to namespaces? will it be bound around a compilation unit via some map containing a atom provided by the user? your comment is low on details.

12:47 tbaldridge_: silasdavis: count is a field on the class that's maintained by conj/pop. So yes, that is also constant time.

12:48 dnolen: cemerick: anyways, gotta run for a bit, feel free to update the ticket w/ details.

12:48 NeedMoreDesu: clgv: Imagine main thread as some gui thread. And gui functions can be used only in main thread. And then we have some heavy calculations, that need to be done in parallel, and just use some main-thread fn's.

12:48 clgv: NeedMoreDesu: swing? there are a functions/methods in swing to execute something in th GUI thread

12:48 cemerick: dnolen: the namespaces get swapped into the compilation env atom, as they are now, just under a particular key. One compiler caller's `namespaces` never touches another's.

12:49 sure, I'll expand a bit on the ticket

12:51 silasdavis: tbaldridge_: ah so it is, so no point doing (reductions (fn [q _] (rotate-queue q)) queue (pop queue)) over (reductions (fn [q _] (rotate-queue q)) queue (range (- (count queue) 1)))?

12:51 NeedMoreDesu: clgv: so this is library features, right?

12:53 tbaldridge_: silasdavis: rotate-queue?

12:55 NeedMoreDesu: clgv: I'm looking for something like this, actually http://stackoverflow.com/questions/10558019/does-using-dispatch-get-main-queue-mean-that-my-code-will-be-on-the-main-threa

12:55 silasdavis: tbaldridge_: (conj (pop queue) (peek queue)))

12:56 kolemannix: Hey guys I have this function that takes 3 collections (all of the same length), operates on each triple using map, and returns a single collection of the same length

12:56 silasdavis: tbaldridge_: (defn rotate-queue [queue] (conj (pop queue) (peek queue))))

12:56 kolemannix: something like this (defn format-instruction [op locn comm]

12:56 90 (str (encode op) \tab locn \tab (pad op) comm))

12:56 clgv: NeedMoreDesu: yes, in Swing it is e.g. http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingUtilities.html#invokeAndWait%28java.lang.Runnable%29

12:57 tbaldridge_: silasdavis: ick, that doesn't seem like a good idea. There's got to be a better way of doing whatever you're trying to do.

12:57 clgv: NeedMoreDesu: or invokeLater

12:57 silasdavis: tbaldridge_: which part?

12:58 tbaldridge_: silasdavis: if you read the implementation of PersistentQueue.java (it's pretty simple actually) you can see that rotate-queue will use queues in a way they aren't really meant to be used in.

12:59 kolemannix: What's the best way to pass "state" into a function?

12:59 I have a function that operates on 3 collections, but I need to give it some additional information

12:59 NeedMoreDesu: clgv: ok, thanks

13:00 kolemannix: I don't really want to pass in the "state" info as a 4th argument

13:00 rasmusto: kolemannix: I've done something similar with reduce (and a state map as the other argument)

13:00 tbaldridge_: silasdavis: I mean it works, its just it seems that something like a LinkedList would work better, or even doing nth on a vector.

13:00 rasmusto: kolemannix: why don't you want the 4th arg?

13:01 kolemannix: I was just wondering if there's a better way to give the state map

13:01 I guess I can use a 4th arg

13:02 dnolen: cemerick: ok sure like I said above. Do you want to take this patch on?

13:02 cemerick: dnolen: replied on the ticket.

13:03 rasmusto: kolemannix: this probably isn't 100% what you want, but it shows how I use reduce + a state map https://www.refheap.com/19930

13:03 cemerick: dnolen: well, it *has* to be done. The `reset` approach is just broken IMO, esp. for REPLs. I'm happy to do the refactor, but I'll need help esp. with testing source maps, since I don't use them at all, and it doesn't look like there's any automated tests around them?

13:04 dnolen: cemerick: writing tests for them is difficult because of unpredictable loss around inlining and dead code elimination

13:05 cemerick: dnolen: yeah, not faulting the lack of tests, but I suspect you're the only one that has any idea how they should work :-)

13:05 dnolen: cemerick: we could write some for the simpler cases, but I really don't see how you could mess up source maps w/ this change. source maps tracking is per file and not really exposed

13:06 cemerick: beyond the compiled-cljs caching

13:06 kolemannix: rasmusto: Thanks, even though it's not the same thing it helps

13:06 cemerick: dnolen: Yeah, the refactor is actually a pretty straightforward transformation from (swap! *data-name* assoc ...) to (swap! *compile-env* update-in [:data-name] assoc ...)

13:06 namespaces being maybe a bit different, but we'll see

13:07 the relation between REPL envs and compilation env is the biggest unknown at the moment.

13:08 dnolen: cemerick: I don't see any obvious issues, the CLJS compiler is REPL centric

13:08 cemerick: outside of closure.clj

13:10 cemerick: dnolen: yeah, agreed

13:12 dnolen: cemerick: one issue is accessing namespaces from macros, with your compilation environment idea it will be different

13:12 cemerick: that's the real breaking change

13:14 cemerick: could be avoided reading out namespaces and binding it seperately to support old interface

13:14 cemerick: dnolen: there are macros that look at ana/namespaces directly?

13:15 dnolen: cemerick: that's whole idea, literally since day 1

13:15 part of the original design since there are no vars

13:17 dav: How can I get clojure.pprint/pprint to print recursive hashes on multiple lines and with indent?

13:19 cemerick: dnolen: as long as the usage is read-only, then yeah, ana/namespaces can be updated to mirror the value of the :namespaces slot in the compiler env. Can you point to a macro that looks at ana/namespaces now, though? Looks like extend-type et al. are the only ones in cljs itself?

13:19 clgv: dav: maybe you can convince "fipp" easier to do that

13:19 dnolen: cemerick: it is the intended use case, Rich said this himself

13:21 cemerick: the question is whether we should push the idea further and leave direct namespaces access behind, and provide more utilities like cljs.analyzer/resolve-var to accomplish the same thing.

13:21 cemerick: dnolen: fine enough, wasn't aware of the word ;-P Any chance the discussion was online?

13:24 dav: clgv: nope that one prints on one line too..

13:27 dnolen: cemerick: can't find anything beyond the source, but it's come up in conversation before when people have complained about lack of vars.

13:27 cemerick: yah, ok

13:27 dnolen: cemerick: whatever we come up with 643 should support reading namespaces for sure

13:28 bbloom: dnolen: did you see https://github.com/YaroslavGaponov/node-jvm ?

13:28 cemerick: dnolen: aside from maintaining the existing "api", shouldn't they just hang off of &env?

13:28 dnolen: cemerick: the namespace isn't in &env

13:29 cemerick: &env is just the local environment of the compilation unit

13:29 cemerick: I think conflating the two when they aren't conflated in Clojure doesn't make much sense anyhow

13:29 dav: so seriously, there's no canned function for pretty priting nested structures nicely?

13:30 dnolen: bbiab

13:30 cemerick: dnolen: Clojure has ambient access to namespaces/vars; seems like binding ana/namespaces into &env makes sense, so that macros would rely upon analyzer impl. details less.

13:31 jcromartie: dav: did fipp not look good?

13:31 bbloom: dav: clojure.pprint is included and my fipp is available as an extensible option if you need to build your own pretty printer

13:34 dav: jcromartie / bbloom - I can't seem to get them to print the structure on multiple lines.

13:34 I guess they deem the width to narrow?

13:34 bbloom: dav: what structure?

13:34 dav: {:a 1 :b {:c 3 :d 4}}

13:35 bbloom: yeah, that's pretty narrow :-P both pprint and fipp are targeted at pretty printing for humans. they are not uniform indenters

13:35 you can force fipp to do something naive for indenting if you just print with {:width 1}

13:35 dav: score! thanks.

13:37 *sigh*, it doesn't make [[[[:a :b]]] [[:c :d]] [:e :f]] readable at all :(

13:38 bbloom: dav: if you know the schema of your data, you can write your own pretty printer with fipp trivially

13:38 look at https://github.com/brandonbloom/fipp/blob/master/src/fipp/edn.clj

13:38 you juse use defprinter & you can make a custom pretty printer in a handful of lines of code as pure functions

13:40 dav: bbloom: I just wanted to print some data structure from 4clojure in a readable way

13:41 bbloom: dav: both pprint and fipp are tuned for making realistic data easy to read. if you're having trouble reading that tiny data structure, i don't know what to do for you other than to suggest you copy paste it in to your editor and turn on brace-matching :-P

13:42 dav: if you want a particular style of indentation, you can achieve whatever you want with fipp and it's seriously both simple AND easy

13:46 coventry: dav: Do you use paredit-mode in emacs? Put the cursor just after the first [, and C-M-f / C-M-b will move between the top-level elements of the list.

13:47 bbloom: dav: also, aren't you a haskell convert? how could you possibly think that small list is hard to read? :-)

13:48 coventry: Come on, parsing a deeply nested structure without automation is tedious and error prone. :-)

13:49 bbloom: particularly with associativity :-P

13:53 dav: coventry: I ended up doing the equivalent in vim

13:53 bbloom: that data structure is invalid in haskell ;-)

13:54 bbloom: (variable depth recursive lists..)

13:54 bbloom: yup, you'd need to wrap every damn thing in a descriminated union... weeeeee fun times

13:54 dav: bbloom: you just wouldn't ;-)

13:55 bitemyapp: dav: exactly how is it invalid?

13:57 dav: bitemyapp: lists in haskell are lists of some specific type, not lists of "Any". So unless you define a tree structure or use the either type, you can't have a list of "sometimes lists, sometimes things'

13:58 bitemyapp: okay, but when you said that, I was thinking about Either and trees as counterpoints.

13:58 I wanted to make certain I hadn't missed something.

13:58 dnolen: bbloom: oh whoa, a JVM bite code interpreter in Node, heh

13:58 er byte

13:58 bitemyapp: I would prefer not to think of that Haskell "can't", but rather, Haskell encourages you to keep its type system in the loop on what the fuck is going on.

13:58 dnolen: hella slow, but amusing.

13:59 coventry: Someone should hook it up to js source maps so we can have a real clojure jvm debugger. :-)

13:59 shaungilchrist: hahah!

13:59 * bitemyapp grumbles darkly at coventry's comment

14:00 dav: bitemyapp: yes. and I wouldn't need the pretty printer in haskell because the type system would tell me exactly what I need to handle ;-)

14:00 coventry: bitemyapp: I know, I know.

14:03 bitemyapp: dav: that's probably the greatest gift I got from learning Haskell. Thinking in types.

14:03 Most compressed and efficient way to think about programs I can think of.

14:04 tbaldridge_: dav: that's probably the greatest gift I got from learning Clojure. Thinking in data. Most compressed and code efficient way to think about programs I can think of. </troll>

14:04 I'm sorry everyone, I couldn't resist.

14:05 dav: I love macros and the access to the JVM libraries, but despite these massive advantages, I'm still quite on the fence.

14:06 coventry: dav: I'm curious about frege as a jvm-based alternative to haskell. Do you have an opinion about it?

14:07 dnolen: dav: there's always Frege

14:09 dav: coventry / dnolen - first time I hear of it. Will look into.

14:10 bitemyapp: tbaldridge_: types are about recognizing no data is a special snowflake. Nothing is exempt from categorization or pattern recognition.

14:10 tbaldridge_: further, types can describe morphisms across huge swaths of the program, data stands alone.

14:11 dnolen: dav: https://github.com/Frege/frege

14:12 bbloom: grumble grumble... something something about how types should be optional b/c in theory any data could have multiple interpretations via types.... people conflate types and tags... grumble grumble

14:12 tbaldridge_: But why would I need any of that? The whole thing with types is that they supposedly provide some sort of way to reason about code. But then you see talks like "The Problem With Types" or "Molog" and you realize types are holding these people back from getting stuff done.

14:13 bitemyapp: well it's a trade-off, like everything else. But you'll note that I said Haskell's greatest gift (to me) was letting me think in types - day job is Clojure. Clojure was my decision.

14:13 It's worth considering that there might be value in the abstract faculty for thinking in types and categories even when somebody uses and prefers Clojure.

14:13 dav: I've found that the times the typesystem is in the way is when writing macros

14:13 Every other time, the typesystem is incredibly helpful

14:13 coventry: I thought it was interesting in "The Trouble with Types" that Odersky cited the constraint a type system places on people as a source of good design. Seemed to miss the point at little.

14:14 dav: And I've yet to write a program in Haskell that compiles but crashes or produces any eroneous output

14:14 tbaldridge_: coventry: yeah I have a big problem with that talk. He basically states that good design is finding things that fit into the typesystem well. I remember crazy talk like that from my OOP days.

14:14 bitemyapp: dav: that's easiest to accomplish when you aren't using dynlibs.

14:14 dav: bitemyapp: what is?

14:15 bitemyapp: non-crashing Haskell programs.

14:15 hiredman: I cannot imagine trying to do minikanren with a strong type system

14:15 bitemyapp: hiredman: static*

14:15 dnolen: dav: no erroneous output? you must do a lot of testing.

14:15 hiredman: fighting with go's is hard enough

14:15 bitemyapp: Clojure is a strong type system.

14:15 eric_normand: hello!

14:15 bitemyapp: eric_normand: hi!

14:16 dnolen: eric_normand: yo

14:16 * znDuff makes a mental note to actually find the time to play with Typed Clojure

14:16 eric_normand: jvm on heroku is working funny

14:16 :(

14:16 tbaldridge_: hiredman: that's what molog is, and yeah it was a interesting talk but boiled down to "we can't do this in Haskell, so I cheated in these ways..."

14:16 dav: bitemyapp: what are dynlibs

14:16 bitemyapp: dynamic libraries yo.

14:16 hiredman: tbaldridge_: right, he did the clojure west talk

14:16 dav: dnolen: I've never written a test

14:16 tbaldridge_: hiredman: yeah, I forgot that video was out.

14:16 dav: dnolen: but then again I haven't written that much Haskell..

14:17 eric_normand: anyone else have trouble with clojure.java.io/resources returning a URL for a directory?

14:17 dnolen: dav: heh, well there's not much more to talk about then.

14:17 llasram: eric_normand: In what sense?

14:17 (of trouble)

14:17 dnolen: dav: nearly every serious Haskell book / person talks about testing. Not testing is only for goofy blog posts.

14:17 dav: dnolen: it's just that when I write clojure (or any other language), I run snippets of code 50 times and they crash until I fix all the little bugs. In haskell it runs from the first time (but i have to try to compile it 50 times)

14:18 eric_normand: llasram: (clojure.java.io/resource "static/") is returning a url on heroku

14:18 tbaldridge_: dav: BINGO!

14:18 dav: dnolen: agreed. I never built a large scale app.

14:18 tbaldridge_: (inc dav)

14:18 lazybot: ⇒ 1

14:18 hiredman: x is a logic var, but that logic var may be unified with something else, I dunno of any type system that could deal with that without making everything a union type with lvar

14:18 eric_normand: llasram: but returns null on my local machine

14:18 dav: tbaldridge_: I'm immutable ;-)

14:18 rasmusto: dav: that's a good point. Does either one of those methods feel more interactive? I tend to prefer seeing erroneous output over compiler errors

14:18 bitemyapp: I find peoples' eager glee at avoiding learning new things disturbing.

14:18 eric_normand: llasram: is causing ring/wrap-resources to read it as input stream, which doesn't break but is empty

14:18 llasram: eric_normand: It depends on the class path. io/resource will always return either `nil` or a URL.

14:18 Ahhh

14:18 Yeah

14:19 eric_normand: llasram: seems like new behavior. it was working before!

14:19 rasmusto: s/interactive/productive

14:19 llasram: There was a recent change in Leiningen to add directory entries to (uber)jars, as the spec apparently actually requires

14:19 eric_normand: llasram: I see

14:19 llasram: But most versions of ring apparently have issues

14:20 eric_normand: llasram: let me update leiningen

14:20 tbaldridge_: bitemyapp: I just don't have time anymore. I can't even bring myself to learn more emacs, let alone a new language.

14:20 dav: rasmusto: when some clojure function expects a list and gets a nil or a number or something and barfs, the errors aren't particularly helpful. Plus if this happens in an untested branch of an if statement, your user may crash an app that would never have compiled in Haskell...

14:20 llasram: eric_normand: I would more suggest updating ring

14:20 bbloom: hiredman: there is some recent progress on typing logic vars

14:20 llasram: eric_normand: Or if that's not an option, downgrading leiningen

14:20 justin_smith: hlship: regarding the challenge last night, I found M-x javadoc-lookup (provided by the javadoc-lookup package)

14:20 bbloom: dataflow & logic variables in type sytesm: www.cs.indiana.edu/~sabry/papers/rational.pdf

14:20 eric_normand: llasram: I don't know if I can downgrade it on leningen

14:20 bbloom: basically adds fractional and negative types to the notion of sub and product types

14:21 s/sub/sum

14:21 cmajor7: In regards to "Problem With Types": I feel that Scala needs types. Scala can't survive its "implicit" complexity without types. Scala is so far more complex with comparison to something like Haskell or ML, that it must have something to hide behind and hold it together. Clojure has a very strong type system, but it is not leaking out and does not hurt the end user (Clojure developer), where in Scala it always is a battle of something being not "contravariant

14:21 hjvbe8hgqt4kjh98: Do usa&Israel use chat &facebook 2 spy?!?!?!?

14:21 Do they record &analyse everything we type?!?!?!?

14:21 Do usa&israel use chat&social communicationprog(facebook&twitter) to collect informations,,,,can we call that spying!!!!

14:21 هل تستخدم امريكاواسرئيل الشات والفيس بوك للتجسس!؟!؟!؟!؟!؟!؟!

14:21 Do usa&Israel use chat &facebook 2 spy?!?!?!?

14:21 Do they record &analyse everything we type?!?!?!?

14:21 Do usa&israel use chat&social communicationprog(facebook&twitter) to collect informations,,,,can we call that spying!!!!

14:21 هل تستخدم امريكاواسرئيل الشات والفيس بوك للتجسس!؟!؟!؟!؟!؟!؟!

14:21 Do usa&Israel use chat &facebook 2 spy?!?!?!?

14:21 Do they record &analyse everything we type?!?!?!?

14:21 hiredman: technomancy: !!!!!!

14:21 dav: wtf

14:21 eric_normand: llasram: thanks. I can now reproduce the problem on my local machine! :)

14:22 bitemyapp: cmajor7: I like to think of types as an opportunity for leverage, especially in situations where a codebase begins getting larger.

14:22 llasram: eric_normand: np

14:22 bbloom: dav: it's actually much easier to write a haskell program that segfaults than a java one :-)

14:22 bitemyapp: cmajor7: that Scala mis-uses that leverage to paper over bad complexity is their fault. Haskell and ML do a much better job

14:22 bbloom: the word "unsafe" is a scientifically accurate term when you have unsafeIO or whatever

14:22 dav: bbloom: segfault is just one particular kind of crash..

14:23 hiredman: bbloom: gross

14:23 bbloom: right, but the JVM for example enforces safety dynamically

14:23 even tho Java is statically typed, the runtime enforces safety with dynamic checks

14:23 bitemyapp: You don't need unsafePerformIO in Haskell any more than you need mutability in Clojure.

14:24 bbloom: where as haskell punts, b/c many of their optimizations rely on a smarter compiler and a dumber runtime

14:24 dav: bbloom: right, that's like saying my computer won't explode when my program segfaults (popping the stack by 1 level)

14:24 cmajor7: bitemyapp: that's the thing with Clojure.. you very rarely work with a "large" codebase

14:24 bitemyapp: the practical reality of writing Haskell is that you get an "assistant" as you write your program. It's a pleasant experience.

14:24 bbloom: well yeah, you're relying on your operating system's dynamic checks :-P

14:25 eric_normand: llasram: I hadn't noticed that ring was upgraded. There was a fix for it

14:25 bitemyapp: cmajor7: avoiding the hard work that sometimes needs to be done isn't a win.

14:25 eric_normand: llasram: thanks a bunch!

14:25 rasmusto: dav: okay, gotcha. Clojure null pointers definitely make me scratch my head

14:25 bbloom: hiredman: yeah, it's gross, but apparently it actually simlifies signatures for a lot of things that were hard to do in a typed context before.

14:25 bitemyapp: cmajor7: one should of course, avoid attacking problems that don't need to be attacked, but that response is just putting your head in the sand.

14:25 cmajor7: I've been hurt in my efforts in Clojure for want of type-checking in much smaller programs than you might suspect.

14:25 dav: time for me to go to bed. good chatting with you all..

14:26 bitemyapp: not to mention how HORRENDOUSLY painful refactoring dynamically typed programs can be once they become non-trivial.

14:26 hlship: know my pain

14:27 cmajor7: bitemyapp: refactoring is only a pain if the code wasn't manageable in the first place (bad design). and this is nomatter the languages

14:28 tbaldridge_: (inc cmajor7)

14:28 lazybot: ⇒ 2

14:28 cmajor7: bitemyapp: unfortunately I don't know Haskel well (never worked with a large Haskel codebase). but I can tell you that I did with Scala and Clojure. And while Scala has all the types in the world, refactoring was a lot more painful there..

14:28 bitemyapp: types have reduced my "time to understand failure" as contrasted with Clojure

14:29 I got bit really badly by Clojure's dynamic type system at Clojure Dojo and even extra pairs of eyes weren't able to figure it out.

14:29 it wasn't until I dug in with some deftrace that I was able to figure out that I mis-destructured something.

14:29 * technomancy was just debugging an NPE which shadowed another NPE this morning

14:29 bbloom: the big problem in scala is the temptation to use the type system to do work for you

14:29 same with C++ and others

14:29 * znDuff means to spend some time playing with Typed Clojure

14:29 bbloom: you code up things that rely on types to do some metaprogramming or automatic insertion of values

14:29 bitemyapp: znDuff: that's the next step for me.

14:30 bbloom: and then now you have a hidden, global, cyclic dependency ball of mud

14:30 bitemyapp: core.typed is pretty expressive, I'm going to start using with Clojure code I actually give a fuck about.

14:30 cmajor7: bitemyapp: I feel, you are going to experience this less and less, as you do things in a more idiomatic way..

14:30 bitemyapp: (being bit badly)

14:30 bitemyapp: cmajor7: wrongo.

14:31 cmajor7: I've been doing Clojure for quite awhile. I was doing my thing in a Clojure idiomatic way.

14:31 I simply got bit badly.

14:31 cmajor7: bitemyapp: the thing with Clojure is not types or lack of them. it is really a different dimension of thinking..

14:31 technomancy: granted my bug was just due to a java lib that used exceptions in an annoying way; wouldn't have been an issue with ex-info

14:31 bitemyapp: cmajor7: please stop talking to me as if I haven't drunk the Clojure kool-aid too.

14:31 cmajor7: bitemyapp: ok, then maybe I am wrong, since I don't know your particular case. but this is just how I feel.

14:32 bitemyapp: cmajor7: I was structuring a multi-stage predicate application of in terms of data. It was quite nice and declarative. However, a problem that would've been rectified in 5 minutes or less in the presence of type system ended up taking multiple people and sets of eyes 2 HOURS to rectify

14:33 cmajor7: bitemyapp: what was the problem, can you give an example?

14:34 bitemyapp: cmajor7: This was the program we were refactoring, I chose to do it with a [predicate -> change-fn] pipeline. https://github.com/mjansen401/gilded-rose-clojure

14:34 cmajor7: I'm not really super interested in nit-picking the specific problem, because once you know what's wrong (I already said waht it was earlier) it naturally seems "easy" or "simple"

14:34 if you weren't "on the ground" when the problem was still a mystery, you aren't capable of evaluating how difficult or annoying it was.

14:34 tbaldridge_: "update-quality" what on earth is that?

14:35 bitemyapp: tbaldridge_: the intrinsic value of the item drops as it decays from day to day

14:35 mdrogalis: Has anyone ever used the Janino microlanguage in app development before?

14:35 bitemyapp: tbaldridge_: it's a discrete algorithm for shifting time one day at a time.

14:35 tbaldridge_: I know the problem, it's just there has to be a much better way than a 29 mess of Clojure code.

14:35 bitemyapp: cmajor7: do you do Clojure at your day job?

14:35 tbaldridge_: *29 line

14:35 bitemyapp: tbaldridge_: you...do understand that that's the point right?

14:35 tbaldridge_: you're supposed to refactor that.

14:36 tbaldridge_: I wouldn't refactor it, I'd delete it :-P

14:36 mdrogalis: Hah.

14:36 bitemyapp: tbaldridge_: it's an interview exercise, to see how you handle tackling somebody else's complexity budget and how far-sighted and clear-minded you can be about refactoring things you didn't necessarily write

14:36 I actually think it's a great exercise.

14:37 shaungilchrist: "todo: write tests later"

14:37 technomancy: shaungilchrist: https://mobile.twitter.com/GonzoHacker/status/395607991367397376?p=v

14:37 cmajor7: bitemyapp: yes, I did Scala for a couple of years. I am doing Clojure for about a year and a half now (day job that is)

14:38 bitemyapp: cmajor7: if Scala is your only exposure to advanced type systems, then you are impoverished.

14:38 I'd reject programming and civilization itself if Scala was my day job, let alone type systems.

14:38 Go live inna-da-woods.

14:39 cmajor7: bitemyapp: I also have jobs after the "day" ends you know :)

14:39 bitemyapp: cmajor7: and you've written how much Haskell or ML?

14:39 tbaldridge_: I'm just saying, that code shouldn't have been written in the first place, so claiming a type system would have helped is a moot point. Now say the same about something like this: https://gist.github.com/davespanton/3848306 and we can start talking.

14:39 bitemyapp: tbaldridge_: you've missed the point.

14:40 technomancy: heh

14:40 bitemyapp: tbaldridge_: the point is that I've had nice type systems help me understand what I'm doing, wrong or right, faster.

14:41 I don't care about program verification or any of the other stuff, I simply like having the sanity-assistant compiler tell me what's what.

14:41 technomancy: no code that should never have been written ever gets written in the real world, am I right?

14:41 reiddraper: technomancy: +1

14:41 tbaldridge_: sure, if the code is badly written that you can't hold it all in your head.

14:41 bitemyapp: technomancy: totes. Clojure programmers only write perfect code, in quantities no greater than 300 LOC per library.

14:42 tbaldridge_: "if the building is so badly designed that it needs brick instead of straw, it shouldn't be built"

14:42 tbaldridge_: you are rejecting leverage and knowledge. That is insane.

14:43 llasram: Oh dear. My library is getting close to 6k lines

14:43 technomancy: ~guards

14:43 clojurebot: SEIZE HIM!

14:43 llasram: heh

14:43 cmajor7: bitemyapp: is that an interview? ML/Haskell not much, just for selfeducative purposes.. I mostly did Java/C/Python/Erlang and friends before. However I think that your "misfortune" with Clojure is not because Haskell is great and Clojure is not, but because you had a problem with software and at that day it was Clojure. If it was Pascal we would be talking about it instead.

14:43 gfredericks: reiddraper: ping

14:44 reiddraper: gfredericks: pong

14:44 TimMc: PING

14:44 technomancy: ICMP_ECHO_REPLY

14:44 gfredericks: reiddraper: curious about a use for simplecheck

14:44 TimMc: (Player 3 has joined the game.)

14:44 reiddraper: gfredericks: shoot

14:44 gfredericks: ... are you guys being nerds?

14:44 TimMc: I would never.

14:45 technomancy: this sir is calumny

14:45 gfredericks: reiddraper: I'd like to be able to test a chess-rules thing by playing a random chess game; problem is I therefore need to generate moves interactively, where the available moves at any point are obviously dependent on the previous moves

14:45 bitemyapp: cmajor7: jesus christ dude, that is not what I said.

14:46 gfredericks: I can imagine a generator that generates an entire game, which just leaves my test to give a thumbs up and assert that no exception was thrown in the process

14:46 bitemyapp: cmajor7: you keep talking to me like I haven't been writing Clojure for years.

14:46 gfredericks: which seems like a weird approach

14:46 bitemyapp: cmajor7: or that I'm somehow dissatisfied with Clojure. I'm expressing that there is a utility to type systems that can help write better code, faster.

14:46 hiredman: sh/win 21

14:46 tbaldridge_: bitemyapp: nah, the more correct approach is this: If your building is so complex that it can only be built by having each brick only fit against bricks of the correct types, it shouldn't be built.

14:46 bitemyapp: cmajor7: the practical result for *me* is that it means I'm excited about ambrose's work.

14:47 gfredericks: reiddraper: so I feel like what I want is to be able to have a (loop [position initial] ...) and be able to do a rand-nth each time through

14:47 tbaldridge_: bitemyapp: use generic modular bricks (like bricks in real life) and all will be fine :-)

14:47 reiddraper: gfredericks: yeah, this is defniitely something that comes up in erlang quickcheck,

14:48 bitemyapp: reiddraper: you mean Haskell's?

14:48 gfredericks: generative testing is great. Have you tried the Clojure library?

14:48 reiddraper: gfredericks: erlang quickcheck has something called 'statem', which let's you write generates that depend on previously generated values, but it's possible to do this just with 'bind'

14:48 bitemyapp: nope, i mean erlang quickcheck, EQC

14:48 bitemyapp: http://www.quviq.com/index.html

14:49 bitemyapp: haha, they charge for it? jesus.

14:49 gfredericks: bitemyapp: test.generative you mean?

14:49 bitemyapp: gfredericks: whatever. just use stuff.

14:49 cemerick: those g.d. bastards charging money for work! </troll>

14:49 reiddraper: bitemyapp: it's much more advanced than haskell quickcheck

14:49 gfredericks: reiddraper: yeah I figured some lower-level mechanism would suffice; so bind is the best approach then?

14:50 reiddraper: bitemyapp: and written by one of the same original authors of haskell quickcheck, it's _excellent_

14:50 gfredericks: yeah, so i think what you'd want to do is write something that allows you to take a look at the previously generated moves, and then make a decision about what is 'allowed' based on that history

14:50 cmajor7: bitemyapp: I guess to each his own. I am not saying that types are crap, or you don't know Clojure well. I just don't see where explicit types would help me in Clojure (in most cases). They do help me in Java, but that's the whole point, right..

14:51 bitemyapp: cmajor7: I didn't understand where types would help me until I got the "Zen" of Haskell and ML either.

14:51 cmajor7: bitemyapp: ok, maybe you just know something I don't.

14:52 bitemyapp: cmajor7: then once I started taking stock of where my time was going over the course of solving a particular problem, I noticed that I would "net out" on time saved and frustration generated if I had certain faculties and static assurances available to me.

14:52 I can walk into a Haskell program and modify it with far less knowledge or memory of it and reasonably expect to come out the other side pretty okay.

14:52 technomancy: maybe cmajor7 knows how to avoid NPEs =)

14:52 plz spill the beans

14:52 bitemyapp: technomancy: he must be perfect. The chosen one.

14:52 cmajor7: bitemyapp: but I am happy with developing my happy Clojure "Zen", since until now it had never let me down (which I can't say about Scala for example)

14:52 reiddraper: gfredericks: happy to try and hack out something more concrete too, this is a cool, and should be possible use-case

14:53 bitemyapp: cmajor7: you've never done (apply nil [blah lol woot]) eh?

14:53 tbaldridge_: cmajor7: yep, the best way to shut-up detractors....just build cool stuff.

14:53 bitemyapp: detractors...seriously?

14:53 I use Clojure and I'm happy with it. I'm talking about the utility of type systems and why I think core.typed is a good idea.

14:54 how does that make me a detractor? absurd.

14:54 technomancy: look, typed clojure has clojure in the name; therefore it's OK to be a fan of clojure and not dislike it.

14:54 gfredericks: reiddraper: btw, I hacked together an immutable PRNG lib the other day

14:54 technomancy: not sure how it could be clearer =)

14:54 gfredericks: not sure if that's something you'd consider useful

14:54 tbaldridge_: bitemyapp: I meant a dynamic typing detractor

14:54 bitemyapp: tbaldridge_: I'm not saying I have a problem with dynamic typing either

14:55 gfredericks: reiddraper: https://github.com/fredericksgary/four

14:55 bitemyapp: which leads me to believe you misunderstood what I was saying even worse than I thought.

14:55 tbaldridge_: if I had a problem with dynamic typing, I wouldn't be interested in using core.typed.

14:55 I love dynamic typing and love having it in my day-to-day language.

14:55 reiddraper: gfredericks: oh really, sweet, so cemerick has a prng that is cljs/clj compatible, might be interesting to trade notes

14:55 cmajor7: bitemyapp: "(apply nil [blah lol woot])" and what would I do that for? :)

14:55 bitemyapp: cmajor7: k, I can write you off as a smug dude that writes no bugs. Got it.

14:56 but for the rest of us mere mortals - take a look at core.typed.

14:56 cmajor7: bitemyapp: I just have a very good bug spray

14:56 bitemyapp: tbaldridge_: you do understand that using a type system like core.typed doesn't make Clojure *not* dynamically typed, right?

14:56 cemerick: reiddraper, gfredericks I'm dumbly just wrapping seedrandom.js in pprng

14:56 tbaldridge_: bitemyapp: but the fact that it's optional is the key part I think. That's why I don't use ML, Haskell, etc. the typing system is non-optional.

14:56 gfredericks: cemerick: wat is pprng

14:56 bitemyapp: tbaldridge_: why do you think I use Clojure?

14:56 gfredericks: cemerick: so is it mutation-based then?

14:57 cmajor7: bitemyapp: and I like the idea of core.typed. but honestly mostly because it is giving Clojure a good marketing

14:57 cemerick: gfredericks: Clojure/ClojureScript-portable pprng API: https://github.com/cemerick/pprng

14:57 in the process of lifting simple-check on top of it

14:57 tbaldridge_: bitemyapp: I really haven't a clue....almost every day you complain how it doesn't do X or Y from Haskell. :-P

14:57 bitemyapp: tbaldridge_: pardon me for knowing what's possible.

14:58 gfredericks: reiddraper: okay so his is mutable; mine's the haskell-style monadic thing

14:58 again, not sure if that's actually useful

14:58 next-long is probably a confusing name now that I think about it

14:58 reiddraper: gfredericks: it might be, not having it be the monadic style was definitely interseting in porting from haskell to clojure

14:59 gfredericks: I wrote it for the sake of being able to serialize an in-process computation

14:59 haven't ended up actually using it yet though :)

15:00 reiddraper: yeah, and it also allows for you to repeat something without having to create a new RNG

15:00 which is handy

15:01 gfredericks: right

15:01 TEttinger: are there any random number generators for clojure that alter the behavior of shuffle and rand-nth?

15:02 gfredericks: cemerick: before reading your README I imagined perhaps it stood for pseudo-pseudo-RNG

15:02 muhoo: regards types, i've noticed that a shit-ton of my functions have {:pre [(string? arg1) (every? number? [arg2 arg3]) (map? arg4)]}, and that tells me it's time to lookin to typed clojure :-/

15:02 reiddraper: gfredericks: i've also worried about using a mutable RNG if it gets shared between threads, things not being deterministic anymore

15:02 cemerick: gfredericks: add enough pseudos, and you can build ANYTHING

15:03 TEttinger: I'm pretty sure my current code uses rand-nth a bunch

15:03 hiredman: cemerick: doug lea has shown us that

15:03 TEttinger: although I suppose I could define my own...

15:03 bitemyapp: muhoo: Yep. :)

15:04 gfredericks: does anybody know any good reason for clojure not providing a *rand* underneath its random functions?

15:04 hiredman: I was thinking of http://cs.oswego.edu/pipermail/concurrency-interest/2013-July/011579.html and I guess the doug lea remark doesn't make sense without context

15:04 bitemyapp: muhoo: This is a good way to familiarize: http://nathanic.org/posts/2013/typed-clojure-tour/

15:05 cemerick: hiredman: even then... :-P

15:06 * hiredman freely associates cemerick out the door

15:08 muhoo: and if i get very many more [{keys [foo bar baz]}] {:pre [(every? (comp not nil?) [foo bar baz])]}, i also should probably be looking at records too instead of maps :-/

15:10 still, clojure lures me into yak shaving like no other language i've used before. not sure if that's just me or the language. but stuff just doesn't "look right" and i spend way too much time making it look right instead of just slapping shit together to make it work. not sure that's a good thing.

15:10 reiddraper: gfredericks: have you seen any of the papers that the haskell rng is based on?

15:11 bitemyapp: I write better code in Clojure than I did in previous languages, but it's hard to extricate that from simply having programmed longer. I don't find myself yak-shaving Clojure code much.

15:11 reiddraper: gfredericks: there's at least one referenced here http://hackage.haskell.org/package/random-1.0.0.1/docs/System-Random.html

15:11 bitemyapp: I generally wait for some kind of refactor-ROI trigger to happen.

15:12 reiddraper: gfredericks: particularly, take a look at the comment in 'split'

15:13 tbaldridge: muhoo: it can be that way. Clojure has deftype, reify, defprotocol, multimethods, etc. I've found myself sometimes mucking with those. In Python/C# all I had were Objects...so I didn't have much of a choice.

15:14 muhoo: when there's 20 ways to do things, you can end up shaving yaks more. Unless you completely understand the problem then you may just pick the right primitive the first time.

15:17 bitemyapp: technomancy: working on a migration library for Datomic, finished writing a test, ran the test: actual: java.lang.NullPointerException: null

15:17 clearly I failed to be a proper Clojure ubermenschen.

15:20 gfredericks: reiddraper: oh that's interesting; I hadn't thought too much about trivial approaches to that not being ideal

15:20 e.g., take the next two Ints and use those for seeds

15:22 seangrove: cemerick: Very good points on 643, was interesting reading your notes, thanks for taking the time.

15:23 cemerick: seangrove: heh, we'll see if it'll end up being worth anything :-) Definitely an area that needs some TLC, in any case.

15:23 seangrove: technomancy: Do you commit the AOT'd uberjar to the git repo when pushing to heroku? It still seems like it trigger compilation anyway.

15:24 cemerick: Well, a lot of the problems are from my keywords/constants-table change, so definitely let me know if I can help

15:24 I like (obviously) making the analyzer/compiler as functional and idempotent as possible

15:27 dnolen: seangrove: constants-table is a symptom rather than the disease, CLJS was never particularly thread safe and as the compiler has become more sophisticated it's jut more evident now

15:27 s/jut/just

15:27 cemerick: seangrove: No worries, better to keep moving forward than to maybe get stuck fiddling with minutiae. I'm happy to tidy up APIs while people like you and dnolen and Bronsa and bbloom keep pushing the actual compiler bits.

15:27 seangrove: dnolen: Sure, but it's certainly a tractable problem.

15:30 cemerick: Finally grokking why things have been a bit sideways since 1847 has made me reconsider the subject of default/provided cljs versions in cljsbuild, though. It may be that there's no obviously-correct policy there.

15:32 dnolen: cemerick: I think the problem with pinning has been that we're still kinda moving at alpha speeds here - I do think we're close to something more stable. Source maps that work for everyone and a thread safe compiler would be a solid release to pin to.

15:33 seangrove: cemerick: Still confused about the default cljs in cljs-build - you already warn if I haven't explicitely stated the cljs version dep in my project.clj, right?

15:34 cemerick: dnolen: I don't want pinning, people should be able to deviate from the default.

15:35 dnolen: cemerick: sorry yes.

15:35 cemerick: But, the dependency-resolution mechanism is simply too narrow to communicate the necessary info to end users, e.g. this version of cljsbuild is known to work with cljs rXXX - rYYY.

15:35 dnolen: which reminds me, somebody should really resubmit the CLJS patch to attach the version so it's inspectable from the source/REPL :)

15:35 cemerick: I'm contemplating some kind of side-channel for that info that is occasionally checked/cached.

15:35 seangrove: dnolen: Yes, please.

15:37 cemerick: seangrove: confused that there's a default at all?

15:38 seangrove: cemerick: Nevermind, after reading your last remark about the narrow-band of potentially compatible cljs releases, it makes more sense

15:42 technomancy: seangrove: no, committing jars to the repo isn't encouraged. putting :uberjar-name in project.clj should be enough to trigger generating an uberjar at push time

15:42 seangrove: gonna grab lunch but feel free to pm me if you have any questions and I can take a look when I get back

15:42 seangrove: technomancy: But the process is excruciatingly slow on heroku's build servers vs on our build servers - is that just usually just not an issue?

15:42 Sure, no worries

15:43 technomancy: there are other non-git ways to deploy if you want to do your own builds

15:43 seangrove: technomancy: Ah, alright, I'll pm you when you're back then ;)

15:54 muhoo: i'm curious though, if you're using a uberjar, why use heroku? why not just run it on some java container service?

15:54 the main advantage to me of using heroku is being able to run from git instead of having to generate uberjars and running in some apache or google container

15:58 bja: Yeah, I feel if you're going through the effort of uberjar or war generation, you'd just use a war hosting service like Elastic Beanstalk or CloudBees

16:00 xeqi: cemerick: could you point me to where austin/piggieback passes the options to the cljs compiler?

16:13 sritchie: goog.require could not find: clojure.browser.repl

16:13 have you guys seen that before?

16:14 bitemyapp: sritchie: restart lein cljsbuild?

16:14 sritchie: yeah, I ran it again

16:14 bitemyapp: sritchie: is the DOM ready when you run that code?

16:14 clojure.browser.repl needs to be run after DOM ready.

16:14 sritchie: I was including that in a scripts block down at the bottom

16:14 danlentz: is it preferred to use (defmulti xyz type) or (defmulti xyz class) ?

16:15 sritchie: bitemyapp: this is using austin

16:16 xeqi: sritchie: do you have [clojure.browser.repl] in your :require and are not using :optimizations :advanced ?

16:17 sritchie: xeqi: I DID have it in there before - let me try cleaning

16:17 and nope, not using advanced,

16:17 this is on a dev build with simple optimizations

16:17 trying a clean

16:18 danlentz: or am i beimng boneheaded conflating the two (third option...)

16:19 sritchie: xeqi: bitemyapp doesn't fix it, unfortunately

16:19 bitemyapp: even when the page is loaded,

16:19 when I run goog.require('clojure.browser.repl') at the console

16:19 I get an error

16:20 BUT, I'm not referencing it in my code

16:20 my cljs code

16:20 bitemyapp: sritchie: shut off optimizations completely?

16:20 sritchie: :optimizations :whitespace

16:20 let me try to say :none

16:20 bitemyapp: bah, yeah that won't do anything.

16:22 dnolen: sritchie: anything except :advanced should work, cemerick would know more about piggieback, are you trying with 1847?

16:22 sritchie: [org.clojure/clojurescript "0.0-1934"]

16:23 this worked yesterday, strangely

16:23 dnolen: but I cleaned a few times

16:23 dnolen: oh, you know what

16:24 dnolen: I DID change something - I used to have a "repl.cljs" file that had a browser repl import,

16:24 but then removed it, since cemerick's code was handling the repl connect call generation for me

16:27 dnolen: boom, manually adding that require to any of my cljs files fixes the issue

16:28 cemerick: xeqi: it mostly doesn't, it reuses cljs.repl/evaluate-form https://github.com/cemerick/piggieback/blob/master/src/cemerick/piggieback.clj#L105

16:30 sritchie: you squared away?

16:31 sritchie: cemerick: sure, but I think that might be something that austin should highlight,

16:31 (cemerick.austin.repls/browser-connected-repl-js)

16:31 that call won't work unless one of your cljs files has a require for the browser repl file

16:32 cemerick: sritchie: really? What error/behaviour do you get?

16:32 oh, *unless*

16:32 sritchie: yeah

16:32 the console shows that the lib doesn't exist

16:32 cemerick: right

16:33 sritchie: maybe you could add a parenthetical list item to the README @ https://github.com/cemerick/austin/tree/master/browser-connected-repl-sample ?

16:33 pointing to the .cljs file therein that has the require, etc

16:33 sritchie: sure

16:34 cemerick: or open an issue suggesting the addition, so I don't forget :-)

16:36 sritchie: cemerick: https://github.com/cemerick/austin/pull/24/files

16:36 cemerick: awesome, thanks :-)

16:39 apricots: in leiningen profiles.clj is there some way to build configuration programatically? e.g. I'm trying to specify a path based on $HOME (str (System/getProperties "user.home") "/datomic-free")

16:40 sritchie: cemerick: btw

16:40 if I reload a page that austin's connected to

16:40 https://gist.github.com/sritchie/66845142f8fc9afceece

16:41 cemerick: hrmph

16:41 sritchie: if you send an expression to eval anyway, does iti sort itself out

16:41 ?

16:41 sritchie: it hangs, even with multiple reloads,

16:41 until I manually enter the "connect" call at the console

16:42 I wonder if I'm just putting the repl call too early or something

16:42 cemerick: hrm, this happened to someone else before....

16:42 sritchie: make sure the austin-generated js is the last thing in the page, after your app's js?

16:42 sritchie: it's in the body, and the only thing after it is some google analytics

16:42 code

16:43 cemerick: hrm

16:45 sritchie: he was having a similar problem, thus the suggestion https://github.com/cemerick/austin/pull/21

16:45 sritchie: if the REPL is hanging, then there's something keeping the browser-repl ns from being required/loaded or the connect call from being executed

16:46 sritchie: yeah, it's not that particular issue

16:46 but I had figured that one out on my own yesterday

16:46 I'll see if I can move that call around

16:46 and get some more info

16:47 cemerick: sritchie: or just put a breakpoint on the connect call and make sure it's being hit

16:47 sritchie: oh, good call

17:02 yeoj___: i have an old piece of code looking at clojure.contrib.except for :only throwf... where did that go?

17:07 llasram: yeoj___: Probably didn't make it. What's it do? Name suggests just a function wrapping `throw`

17:08 technomancy: yeoj___: ex-info is a general replacement for clojure.contrib.except, but throwf has no contemporary analog

17:08 seangrove: what's up

17:08 gfredericks: what did throwf do?

17:09 yeoj___: looks like it does string formatting, but i'm not sure where the string goes (to logging?)

17:09 seangrov`: technomancy: The current blog post on how to deploy to heroku didn't mention anything much about AOT, or non-git-deploy methods, etc. Very curious about how you're doing it internally.

17:09 technomancy: throw+format on the Exception message

17:09 llasram: Ah

17:09 yeoj___: i found it here: https://github.com/michakurt/clojure-etl/blob/master/etl.clj I guess i can find another way.

17:09 technomancy: seangrov`: AOT should just always happen. non-git deploys are more experimental.

17:10 gfredericks: throwf is fun to pronounce

17:11 llasram: gfredericks: You must pronounce it differently than I do :-)

17:13 gfredericks: llasram: in one syllable

17:15 hiredman: win 19

17:17 * gfredericks imagines "win 19" being a future version of ms windows

17:23 xeqi: cemerick: ah, no obvious way to plug in a source-map there :/

17:30 hiredman: gfredericks: win 19 is a private club of which I am a member

17:30 mikerod: I'm am making a Java interop call of the form (doto <some ArrayList> (.remove (dec <some-num>)))

17:31 After some investigation, the .remove is returning False

17:31 this would indicate that it is calling the ArrayList#remove(Object) method, instead of ArrayList#remove(int)

17:31 sritchie: cemerick: final error that I'd been seeing

17:31 if I cycle the repl a couple of times

17:31 I get this

17:31 CompilerException java.lang.StackOverflowError, compiling:(form-init8604265301067731997.clj:3:13)

17:32 mikerod: So I tried to change it to `(doto <some ArrayList> (.remove (int (dec <some-num>))))` in hopes of making sure it is being passed the primitive int, to match the correct signature

17:33 yet, it still seems to be calling the ArrayList#remove(Object) method instead. Is there a different way to get a primitive int from a Clojure numeric value, which I know are the "boxed" Long type.

17:33 hiredman: mikerod: the clojure reflection stuff is always picking the most general method, because it doesn't no the reciever type of .remove

17:33 so you need to type hint <some ArrayList>

17:33 gfredericks: hiredman: does (int ...) imply an ^int typehint?

17:34 hiredman: gfredericks: sure, but the reflector doesn't care

17:34 "oh, look, a remove that takes Object, use that"

17:34 mikerod: hiredman: the hint fixed it.. (doto ^java.util.List <some ArrayList> (.remove (dec <some-num>))) worked, I didn't even use the `int` call

17:34 hiredman: yep

17:35 dec is typed hinted to return a number

17:35 technomancy: seangrov`: what magnitude of differences are you seeing with your builds?

17:37 mikerod: Thanks, that one had me confused. I guess I haven't had much of a good look at the Clojure reflection code around choosing the method.

17:37 pepijndevos: Where should I look if I wanted to implement a toy datalog?

17:37 (an plan for world domination afterwards)

17:38 justin_smith: pepijndevos: bacwn?

17:38 https://github.com/tailrecursion/bacwn

17:38 tbaldridge: pepijndevos: Pedestal UI has a 200 line implementation of datalog. let me dig it up....

17:38 hiredman: mikerod: it is very easy to forget about hinting the reciever of a method call

17:39 tbaldridge: pepijndevos: correction, it's only 120 lines: https://github.com/pedestal/pedestal/blob/master/app/src/io/pedestal/app/query.clj

17:39 pepijndevos: tbaldridge, whoo

17:39 also, justin_smith whoo

17:39 hiredman: damn, mine is 197

17:39 pepijndevos: I need to figure out what this pedestal thing is anyway...

17:39 tyler__: I have approx 100 futures that im mapping over, it *appears* that its going about 30 futures at a time before it grabs the next set. I thought future uses an unbounded thread pool. anyone have any ideas?

17:40 s/100/1000/

17:40 tbaldridge: pepijndevos: from the author's own admission it's not fast, but it works, and it runs on CLJS which was the original goal.

17:40 hiredman: ~map

17:40 clojurebot: map is lazy

17:40 hiredman: ~map

17:40 clojurebot: map is an evil genius.

17:40 tbaldridge: ~chunked-seq

17:40 clojurebot: Pardon?

17:41 hiredman: tyler__: map is sequential, the only reason you see an parallelism of your futures at all is this other thing called chunking

17:41 danlentz: clojurebot: danlentz is an evil dunce

17:41 clojurebot: 'Sea, mhuise.

17:41 hiredman: any

17:41 tyler__: most likely you are producing the futures lazily and then derefing them lazyingly, so you need to not product them lazily

17:42 justin_smith: if you need the return vals, mapv is not lazy, or doall can force it, if you don't need the return there is doseq

17:42 danlentz: lazybot: what is your relationship to clojurebot?

17:42 lazybot: It's AWWWW RIGHT!

17:42 hiredman: (map deref (for [i (range 10)] (future (+ i i)))) ;; bad

17:42 (map deref (doall (for [i (range 10)] (future (+ i i))))) ;; better

17:43 tbaldridge: reducers....better

17:43 danlentz: uncanny, sometimes

17:43 tyler__: hiredman: the code: (map #(future (oy/request-remote %)) remote-params) (map deref ref-result)

17:43 tbaldridge: well I guess unless you want 1000 threads...

17:43 hiredman: tyler__: see my examples

17:43 tyler__: hiredman: thanks

17:44 technomancy: 1000 threads is peanuts

17:44 justin_smith: hiredman: with the (map deref (doall ...)) shouldn't the doall be outside thte map?

17:45 hiredman: justin_smith: it should be where it is

17:46 tyler__: hiredman: is there a diff between using doseq vs doall and for?

17:47 hiredman: read the docs

17:47 cemerick: sritchie: Well, the filename is coming from cider/nrepl.el IIRC

17:47 tyler__: rgr

17:47 bitemyapp: sritchie: are tagged unions/case classes regarded as a code smell in Scala?

17:47 cemerick: not sure how to relate it back to austin/piggieback tho, without part of the stack

17:48 sritchie: yeah, makes sense

17:48 bitemyapp: I don't think so

17:48 I use them, anyway, mostly as a more explicit exception handling mechanism

17:49 Either, for example, right?

17:49 brehaut: tyler__: the docs are two private msgs with clojurebot or lazybot away

17:49 pepijndevos: tbaldridge, how do i even use it? Reading code is hard. Especially tricky code without knowing what it does.

17:49 bitemyapp: sritchie: It's also not clear to me what distinction, if any, is made between Either being a type union vs. a monad one binds values out of

17:50 brehaut: bitemyapp: the monad is just an interface that the union implements

17:50 sritchie: yeah, the only distinction is that scala has no monad tait

17:50 trait*

17:50 bitemyapp: brehaut: that makes sense. So in order to access the contents of the union, you bind?

17:51 tbaldridge: pepijndevos: it's pretty much a rip-off of Datomic's datalog, so: https://github.com/pedestal/pedestal/blob/master/app/test/clj/io/pedestal/test/app.clj#L1168

17:51 brehaut: bitemyapp: thats one way yes

17:51 tyler__: hiredman: only asking because ostensibly there is no real difference i was wondering if you picekd one way for a specific reason that wasn't apparent to me

17:51 pepijndevos: tbaldridge, is the Datomic one equally short?

17:51 tyler__: picked*

17:52 TEttinger: tyler__, there's a lot of difference

17:52 hiredman: tyler__: there is a very real difference, have you looked at the doc strings?

17:52 brehaut: bitemyapp: theres probably also map (functor) and applicative operations for different access to it too

17:52 llasram: tyler__: If you mean `dorun`, there isn't much effective difference

17:52 tyler__: `doall` though, big diff

17:52 TEttinger: for and doseq at least are very different

17:52 tbaldridge: pepijndevos: I don't know (I haven't seen the source), but I guess not. Datomic Datalog is backed by indexes and it also caches queries. This shorter example is very brute force.

17:52 pepijndevos: I see.

17:52 TEttinger: err maybe I am exaggerating

17:53 one returns the seq, one doesn't, so totally different uses

17:53 bitemyapp: brehaut: I would hope so, yes.

17:53 pepijndevos: Yea, i read datomic uses like 3 indices.

17:53 bitemyapp: pepijndevos: eavt vaet avet and I might be missing one.

17:54 pepijndevos: oh and aevt.

17:54 hiredman: https://github.com/sonian/Greenmail/blob/master/src/clj/greenmail/db.clj is a nice little "datalog" that uses core.logic for the actually search, but actually indexes facts(similar to datomic datoms) in memory

17:55 bitemyapp: pepijndevos: would you like an article on how to harness datomic's indexes directly?

17:55 pepijndevos: bitemyapp, sure.

17:55 tyler__: hiredman: k thnx

17:55 bitemyapp: pepijndevos: http://www.dotkam.com/2013/05/31/datomic-can-simple-be-also-fast/

18:15 mlb-: what are the uniqueness guarantees on gensym?

18:15 llasram: mlb-: You can generate collisions if you try, but probably not if you don't set out to do so

18:19 mlb-: llasram: is it thread-safe?

18:19 llasram: tldr yes, but I encourage you to read the implementation :-)

18:20 hiredman: mlb-: if you have to ask those questions, the answer is (java.util.UUID/randomUUID)

18:20 mlb-: I'd love to! Where might I find a javadoc for clojure.lang.RT?

18:20 hiredman: gensym is just useful enough for generating code, you shouldn't use it for anything else

18:24 bitemyapp: mlb-: a java doc for clojure.lang.RT? Are you serious?

18:27 llasram: mlb-: No javadoc, but here's the source: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java

18:28 mlb-: bitemyapp: Entirely serious. Why shouldn't I be?

18:32 llasram: cool, found enough information to satisfy my curiosity

18:32 sad there's no javadoc, though

18:57 bitemyapp: so I just wrote "drop-keys", how did I do? --- (select-keys m (reduce disj (set (keys (target-s))) dropped-keys))

18:57 properly: (select-keys m (reduce disj (set (keys m)) dropped-keys)))

19:00 I'm sure in J it would just be ->!{} ^^ [::]

19:03 brehaut: ,(#([[%&]] (+)) 1 2 3)

19:03 clojurebot: [(1 2 3)]

19:05 hyPiRion: drop-keys is easier than that

19:05 (apply dissoc m dropped-keys)

19:06 * bitemyapp facepalms

19:07 bitemyapp: hyPiRion: commented my version out and appended ;; for humility. to it.

19:07 hyPiRion: haha

19:08 it's easy to get lost in the Clojure world

19:11 akurilin: Why is it that when I return a file outside of a JAR from a ring app, it's a File object, and when it's in a JAR, it's a BufferedInputStream object.

19:12 brehaut: akurilin: at a guess because when it comes from a jar its pulled out of a zip file on demand

19:13 and its not a full 'file'

19:13 bitemyapp: akurilin: why go to the trouble of faking a filesystem inside a jar?

19:14 akurilin: brehaut, is that how jar content is usually deal with? It's kept zipped in of the filesystem and then pulled into memory on demand, or are all the contents of a jar automatically cached in memory at java -jar time?

19:15 brehaut: akurilin: i would presume its implementation specific

19:15 bja: can lein load clojure source via stdin?

19:16 nvm

19:16 akurilin: brehaut, got it.

19:16 bitemyapp, no reason. Just trying to debug a few quirks I get with MIME types when running the app from a .jar

19:16 led to a fun 3am debugging session.

19:18 bitemyapp: akurilin: if you want fun, let me talk to you about doing migrations with Datomic.

19:20 akurilin: bitemyapp, I think it'd go over my head at this point :)

19:20 Argh Compojure docs. List the middleware backwards with respect to how they're listed in code in the threading macro

19:33 talios: anyone here using Jay Fields expectations testing library at all?

19:35 brehaut: morning talios

19:35 TimMc: bja: Not that I'm aware of, but clojure.main accepts an -e containing code to execute.

19:35 talios: 'lo brehaut

19:46 bja: if I build a standalone uberjar, will running the jar with java -jar intercept the stdin before my jar gets to it

19:47 so doing something like: echo "msg" | java -jar foo-standalone.jar

19:48 hyPiRion: not afaik

19:49 bitemyapp: ahhhhh fuck I need Fluokitten.

19:50 llasram: wow

19:52 bitemyapp: May I ask what for?

19:54 bitemyapp: llasram: roughly - (group-by :db/id (Either Datomic.List Datomic.Map))

19:54 a group-by functor for a Datomic transaction category.

19:54 llasram: hmm

19:54 bitemyapp: so that I don't have to (cond (vector? ...) (map? ...))

19:55 because that is fucking bullshit.

19:55 llasram: Not just a multimethod or protocol?

19:55 bitemyapp: it doesn't merit reification in that manner.

19:55 llasram: I see

19:55 bitemyapp: it's also not that simple

19:56 the List forms have less data "apiece" than the Map forms.

19:56 you can't implement an isomorphic interface to both

19:56 you'd have to reduce the List forms into the Map forms to get a complete picture, but the Map forms are less expressive.

19:57 llasram: I don't know enough datomic to fully grok. Curious to learn how your fluokitten-ing goes though :-)

19:58 bitemyapp: llasram: I'm holding off on the Fluokitten, I'm suffering the schlep for now.

19:58 but the ROI is encroaching...

19:58 writing this migration toolkit for Datomic is probably the most pissed off I've been in months.

19:59 bja: any idea why https://gist.github.com/emidln/7241957 would let me say "lein run < project.clj" but building an uberjar and then saying "java -jar target/edn2json-0.1.0-SNAPSHOT.jar < project.clj" has no output?

19:59 bitemyapp: bja: is that the standalone jar?

19:59 bja: err

19:59 yeah, meant to be the standalone jar

19:59 mistyped the question

20:01 java -jar target/edn2json-0.1.0-SNAPSHOT-standalone.jar < project.clj

20:07 bitemyapp: llasram: I thought I was the only one that liked Fluokitten.

20:08 hoangelos: I have some clojure code that calls clojure.java.shell/sh. The (third-party) script being called included a password. I'm trying to make sure the output for that isn't logged.

20:09 when there's an error it seems to log the output and the input including the full script command line args.

20:38 yeoj___: i'm trying to simply write a large pipe delimited file.... but i'm getting "streamclosed". Can someone take a look at this: (ns metadata.db.table-dump

20:38 [:use

20:38 [clojure.pprint]

20:38 [metadata.db.connections]

20:38 [metadata.db.metadata]

20:38 [clojure.string :only (join)]

20:38 ;[clojure.core.incubator :only [throwf]]

20:38 ]

20:38 [:require

20:38 [taoensso.timbre :as timbre :refer (trace debug info warn error fatal spy with-log-level)]

20:38 [clojure.java.io :as io ]

20:38 [clojure.java.jdbc :as j ]

20:38 [clojure.java.jdbc.sql :as sql]

20:38 ]

20:38 )

20:38 (timbre/set-config! [:appenders :spit :enabled?] true)

20:38 (timbre/set-config! [:shared-appender-config :spit-filename] "log.log")

20:38 hyPiRion: yeoj___: would be lovely if you put this on a pastebin instead

20:38 yeoj___: (def sql "select * from comcast_lineup ")

20:38 (let [

20:38 joiner (fn [v] (join "|" v ))

20:38 ;results (rest (j/query local-postgres [sql ] :as-arrays? true :row-fn joiner ))

20:38 results (rest (j/query local-postgres [sql ] :as-arrays? true :row-fn joiner ))

20:39 ]

20:39 (with-open [wrtr (io/writer "test.txt")]

20:39 (map #(.write wrtr %) results )

20:39 ) )

20:39 opps.

20:39 sorry

20:39 i mean't this: https://www.refheap.com/20306

20:39 * yeoj___ shame

20:39 yeoj___: hyPiRion: i'm sorry. goofed on a copy paste.

20:40 hyPiRion: yeah, no worries. It's just easier to read/test on a pastebin, and has the additional bonus of not spamming the channel =)

20:40 yeoj___: hyPiRion: i understand. i'll be more careful.

20:48 amalloy: ~map

20:48 clojurebot: map is lazy

20:50 hyPiRion: yeah, yeoj___, the problem is that map is lazy. You attempt to write on a closed resource. Try to use mapv, or wrap the map call in a dorun

20:52 yeoj___: ok, I'm trying to dump massive resultsets... I'm hoping results stays lazy (as it writes) but the doall only effects the vertor for each row

20:53 also it seems like it returns nil for each row that i .write. but i have the output accurate at this point.

20:58 logic_prog: how does sessions work in https://github.com/ring-clojure/ring/wiki/Sessions -- can I assume that I can (1) store in a session the user name of an authenticated user and (2) there is no way the suer can change it (since the cookie is encrypted)

21:00 Apage43: logic_prog: correct, the cookie store should be tamper-proof https://github.com/mmcgrana/ring/blob/master/ring-core/src/ring/middleware/session/cookie.clj

21:01 what you do have to worry about is the fact that a user could *save* their cookie and reset it to an old state later

21:01 so if you want to expire it, you'll need to stick a timestamp in it

21:01 logic_prog: *thinking*

21:01 let me skim the cookie.clj file first then raise objections :-)

21:03 https://github.com/mmcgrana/ring/blob/master/ring-core/src/ring/middleware/session/cookie.clj#L92 <-- isn't this dangerous

21:03 i.e. if someone broke AES, they could cause an read-string

21:03 and then use read-macors to do a remote execution

21:03 Apage43: "if someone broke AES"

21:03 logic_prog: yes

21:03 Apage43: actually more of a concern is whether someone can break the HMAC

21:04 they don't need to break AES to tamper the cookie, just the HMAC

21:04 but yes

21:04 if you don't trust the HMAC you can't trust cookie store

21:04 you can probably trust it though

21:04 logic_prog: shouldn't there be a (binding [*read-eval* false]) ?

21:04 Apage43: logic_prog: no. I mean, the data inside the cookie necessarily came from the server

21:04 it's not user data

21:05 logic_prog: not if someone could forge a MAC

21:05 Apage43: assume that that is hard

21:06 hn

21:06 *hm

21:06 actually it's using the same key for AES and HMAC

21:06 which you *shouldn't* do

21:06 logic_prog: someone should file an issue ticket

21:06 Apage43: I've done my part (pointing out the lfaw). I leave the rest to you. :-)

21:06 Apage43: but... probably won't be what kills you

21:08 logic_prog: this seems rather bad

21:08 because suppose there's some other vulnerability that lets the client guess the AES key

21:08 now they can do arbitrary code execution

21:10 Apage43: logic_prog: ..

21:11 really I think if your crypto is busted

21:11 you probably have worse problems

21:11 logic_prog: that's like saying: "if you have cancer, don't worry about the scraped knee"

21:11 Apage43: yes

21:11 it is exactly like saying that

21:12 you can probably ignore a scraped knee if you have cancer

21:12 Raynes: Not really

21:12 logic_prog: well, actually it's different

21:12 it's more like "here is a scraped knee; which, if you have cancer, will suddenly drain your bank account"

21:12 Raynes: Apage43: That scraped knee could become infected and do away with you much quicker than the cancer.

21:12 logic_prog: it goes from "broken crypt" to "full ownage"

21:12 Raynes: Even if you've got an expiration date, if it's more than two weeks you should probably go ahead and put some peroxide on that.

21:13 Just saying.

21:13 bitemyapp: ah how's that for cool? I think my migration stuff is working now.

21:13 logic_prog: more accurate is "this is a like a weird gene, where should you one day get cancer, it'll cause you to sponteanously to go into flames"

21:13 Apage43: i mean

21:13 *the whole point of having crypto here*

21:13 is that you are relying on it for the correctness of your system

21:13 if this crypto is broken

21:14 even if it doesn't give you code execution *there*

21:14 bitemyapp: logic_prog: there's defense in depth, and then there's realizing there's a line across which you cannot defend your program or your data, period.

21:14 Apage43: the system is probably severely compromised

21:14 bitemyapp: logic_prog: if magical gnomes with the ability to read hard disks are inside my colo, I'm fucked regardless. I don't give a damn if they get "root"

21:14 logic_prog: concordantly, if they break AES...then *FUCK* it.

21:15 Apage43: Most folks are going to store "logged in as <user>" in this. if you can just change that to "logged in as admin" (you broke AES).. well you have enough of a foothold you can probably get into the rest of the system

21:15 bitemyapp: Apage43: generally what one does is store a UUID4

21:15 logic_prog: logged in as admin != root shell

21:15 bitemyapp: Apage43: this points to an unguessable db-backed session

21:16 Apage43: this prevents cracking of cookie crypto translating into arbitrary user access

21:16 Apage43: the whole point of using the cookie store is that you don't have a better session store =P

21:16 if you have a db just send a session id and don't use the cookie store

21:16 bitemyapp: Apage43: I know, I'm just proffering alternatives.

21:16 Raynes: If they break AES then chances are they've earned their prize.

21:16 bitemyapp: but yeah, if you are stuck with non-db-backed sessions, then the hell with it.

21:16 logic_prog: are you implying that if someone broke AES, instead of hacking my lol-cats site to change their karama, they would hack banks?

21:16 bitemyapp: crypto is everything with cookie-stores. doesn't fuckin' matter if they crack it.

21:17 Apage43: logic_prog: well hopefully your app isn't running as root =P

21:17 bitemyapp: logic_prog: there are two kinds of pedants in this world.

21:17 TimMc: No, there are at least 12.

21:17 bitemyapp: logic_prog: Ones that actually know what they're talking about (amalloy) and then there's those that don't.

21:17 Raynes: There is TimMc, TimMc, TimMc, TimMc, and so on up to 12.

21:18 bitemyapp: logic_prog: you can make yourself less obviously a member of the latter group by dropping the bullshit whine-fest and wasting somebody else's time.

21:18 Raynes: lol

21:18 TimMc: OK, I need a filk, stat: "When [...], that's-a monad"

21:18 bitemyapp: If I got a PR on Github like this I would drop-kick it to Mars and then nuke Mars.

21:18 logic_prog: what's PR?

21:19 Raynes: Pull request.

21:19 * bitemyapp puts on his kicky boots and grins toothily at logic_prog

21:19 Raynes: What's a github, bitemyapp?

21:19 o.o

21:20 bitemyapp: Raynes: I just snorted diet coke you little shit

21:20 now my nose burns

21:20 logic_prog: actually

21:20 I can just wrap CookieStore

21:20 bitemyapp: logic_prog: nobody cares

21:21 llasram: bitemyapp: Let's keep this a friendly community, yes?

21:21 Raynes: No.

21:21 bitemyapp: llasram: fine fine. There's been a stream of people like this lately and it's exasperating.

21:21 * Raynes whisks llasram away with a broom.

21:21 bitemyapp: Whenever you write any libraries/software that involves web apps, suddenly everybody becomes a fucking expert.

21:22 then you get people like Captain Peanut Gallery ^^ up there.

21:22 TimMc: More to the point, no one is going to break AES -- but they may break your poor usage of it.

21:22 Apage43: yep

21:22 but the construction in ring's cookie store is pretty much right

21:22 llasram: bitemyapp: I agree that the particular topic is probably not going to generate useful discussion, but I think tone is important

21:22 Apage43: you can feel comfortable using it

21:22 TimMc: E.g., some people think "Oh I'll ust encrypt it to myself, everything will be fine"

21:23 bitemyapp: llasram: this is really just another reason to use Fluokitten.

21:23 Raynes: bitemyapp: We need more data pipelining practices.

21:23 llasram: A dismissive atmosphere makes it easier to accidentally dismiss genuine issues

21:23 haha

21:23 Raynes: Stat!

21:23 TimMc: and then some clever Ukrainian flips a few bits blindly and gets a valid result

21:23 bitemyapp: llasram: if I use Fluokitten, muggles get scared away and don't make silly comments.

21:23 Raynes: decomplected data pipelining practices.

21:32 TimMc: "When a type con-structor has a bind and return... that's-a monad..."

21:32 I'm done, good night.

21:32 I expect to see something better by morning.

21:57 logic_prog: is there a way to tell cljure.tools.namespace.repl/refresh that nameslace Blah.clj no longer needs to be loaded?

22:11 l4u: should I use tools.namespace or pomegranate for code reload in REPL?

22:15 jcromartie: why is javagit development using SVN

22:17 seangrove: jcromartie: Because cvs is horrible, duh.

22:19 jcromartie: git log --pretty=format is my new best friend

22:21 devn: hello all

22:22 jcromartie: hi

22:45 gvickers: Is anyone familiar with Quil, the processing library for clojure? In my draw function I am trying to draw a ellipse for all the elements of a vector using (for [x vec] (let [bla bla] (ellipse bla bla bla bla))). Is there something I dont understand about processing, can the draw function only handle 1 new shape at a time? I am getting a nullPointerException on the draw function.

22:50 amalloy: gvickers: i'm not, but a quick look at the quil readme makes me think that draw is side-effectful, and so putting that in a for (as opposed to a doseq) is doomed to fail

23:15 uvtc: Is there a function to write to stderr, or should I write `(binding [*out* *err*] (println "..."))`?

23:20 `cbp: uvtc: I guess you could use (.println *err* "foo") but there's no clojure function that i know of

23:21 uvtc: `cbp, thanks. I was just poking around in the clojure source, and it appears to me so far that `binding` `*out*` is the way it's typically done.

23:25 Ah. https://github.com/clojure/clojure/blob/master/src/clj/clojure/pprint/utilities.clj#L95 (using `binding` as above)

23:30 teslanick: I'm a clojure newbie, and I'm having a hard time parsing the `for` form.

23:30 (take 10 (for [n (whole-numbers) :when (even? n)] n))

23:30 (From Programming Clojure 1st edition)

23:31 I'm not sure I understand how to map `for` into something I'm more familiar with.

23:31 uvtc: `for` is a way to generate sequences.

23:32 brehaut: teslanick: what languages are you familiar with (impossible for anyone to make an analogy without that info)

23:32 uvtc: Like Python's square bracket thingy: `[i for i in range(5) if i % 2 == 0]`

23:32 `cbp: list comprehension

23:32 uvtc: Right. That's it. :)

23:32 teslanick: I'm most familiar with javascript, but I know java-esque languages as well.

23:32 brehaut: uvtc: like generator comprehensions, not list comprehensions

23:32 round parens

23:33 teslanick: how well do you know jquery's map function?

23:33 teslanick: Yes.

23:33 All of it. :)

23:34 uvtc: teslanick, you use `map` and `filter` when you've already got a sequence. You can make new sequences with functions like `range` and `iterate`, or you can custom-make them with `for`.

23:34 teslanick: I'm actually really familiar with JS's map and reduce functions

23:34 brehaut: teslanick: $.map([1,2,3], function (a) { return [a,a,a]; });

23:34 /=> [1, 1, 1, 2, 2, 2, 3, 3, 3]

23:35 s/^\//\/\//

23:35 jquery's map is broken, but its useful for analogy

23:35 teslanick: What would that map into in Clojure?

23:36 brehaut: directly: mapcat

23:36 ,(mapcat (fn [a] [a a a]) [1 2 3])

23:36 clojurebot: (1 1 1 2 2 ...)

23:36 teslanick: I get mapcat, map, reduce, etc. I

23:36 brehaut: but mapcat and for are isomorphic; for is simply a syntax for mapcat

23:36 teslanick: I'm just having trouble parsing the example code for :when and :while with `for`

23:36 coventry: teslanick: Programming Clojure probably isn't the best book to be learning from these days.

23:37 teslanick: It's the book I have. ;)

23:37 But what would you recommend?

23:37 brehaut: ,(for [a [1 2 3] generated [a a a]] a)

23:37 clojurebot: (1 1 1 2 2 ...)

23:37 coventry: Clojure Programming is more recent.

23:37 brehaut: :when adds a filter

23:37 `cbp: arent they both 1.3?

23:38 normal: How do I use the jar from "lein jar"? Or how do I make it find the project dependencies?

23:38 coventry: teslanick: ##(for [n (take 10 (range))] (* n n))

23:38 lazybot: ⇒ (0 1 4 9 16 25 36 49 64 81)

23:38 uvtc: teslanick, Oh. `:when` is for when you want to keep going through the rest of the `for`; `:while` is when you want to stop once your predicate says you're done. Have you had a look at http://clojuredocs.org/clojure_core/clojure.core/for ?

23:38 brehaut: so the mapcat version ##(filter odd (mapcat (fn [a] [a a a]) [1 2 3]))

23:38 lazybot: java.lang.RuntimeException: Unable to resolve symbol: odd in this context

23:38 coventry: teslanick: ##(for [n (take 10 (range)) :when even?] (* n n))

23:38 lazybot: ⇒ (0 1 4 9 16 25 36 49 64 81)

23:38 brehaut: ,(filter odd? (mapcat (fn [a] [a a a]) [1 2 3]))

23:38 clojurebot: (1 1 1 3 3 ...)

23:39 coventry: teslanick: oops ##(for [n (take 10 (range)) :when (even? n)] (* n n))

23:39 lazybot: ⇒ (0 4 16 36 64)

23:39 coventry: teslanick: oops ##(for [n (take 10 (range)) m [\a \b \c] :when (even? n)] [(* n n) m])

23:39 lazybot: ⇒ ([0 \a] [0 \b] [0 \c] [4 \a] [4 \b] [4 \c] [16 \a] [16 \b] [16 \c] [36 \a] [36 \b] [36 \c] [64 \a] [64 \b] [64 \c])

23:39 * `cbp didn't know about :while

23:40 brehaut: ,(for [i (range) :while (< i 3)] i)

23:40 clojurebot: (0 1 2)

23:40 brehaut: exactly what it says on the tin

23:40 ,(for [i (range) :when (odd? i) :while (< i 6)] i)

23:40 clojurebot: (1 3 5)

23:40 brehaut: ,(range)

23:40 clojurebot: (0 1 2 3 4 ...)

23:41 amalloy: brehaut: yes, although people are often surprised by ##(take 20 (for [x (range) y (range) :while (< y 5)] [x y])

23:41 &(take 20 (for [x (range) y (range) :while (< y 5)] [x y]))

23:41 lazybot: ⇒ ([0 0] [0 1] [0 2] [0 3] [0 4] [1 0] [1 1] [1 2] [1 3] [1 4] [2 0] [2 1] [2 2] [2 3] [2 4] [3 0] [3 1] [3 2] [3 3] [3 4])

23:42 amalloy: :while isn't *exactly* "what it says on the tin", simply because it's hard to realize what is the expected behavior of :while

23:42 uvtc: brehaut, Oh. Didn't know clojurebot could handle an ∞ seq. (`,(range)`)

23:42 brehaut: uvtc: its just a flag for the printer

23:43 teslanick: Can I enable that flag in the repl? I've bumped into that a few times :)

23:43 brehaut: uvtc: http://blog.n01se.net/blog-n01se-net-p-85.html

23:43 a chouser classic

23:43 uvtc: brehaut, Sorry, don't know what you mean. What magic is clojurebot doing?

23:44 brehaut: uvtc: its doing exactly zero magic. simply setting the *print-length* variable does that automatically

23:44 uvtc: Heh. That's a pretty exact amount of magic. :) Thanks, and also thanks for the link.

23:44 teslanick: brehaut: aww yiss.

23:46 * gfredericks gets bit by how some-fn handles multiple args

23:47 TimMc: ,`[~@(range)]

23:47 clojurebot: #<OutOfMemoryError java.lang.OutOfMemoryError: Java heap space>

23:47 brehaut: TimMc: now do it without the alpha characters

23:48 TimMc: hehehe

23:48 amalloy: gfredericks: the way it handles multiple args is insane

23:48 TimMc: Blow the heap, you mean?

23:48 gfredericks: amalloy: I remember this from back in the day; apparently I almost never use some-fn in this way

23:48 brehaut: TimMc:

23:48 TimMc: yeah

23:48 gfredericks: but I can't for the life of me imagine using it the way it was written to be used

23:48 TimMc: Mmm, I don't think I can generate infinite seqs.

23:49 amalloy: gfredericks: right, because the way it was written to be used is easy to emulate with existing functions

23:49 dav: is there a way to tell clojure what to do if destructuring fails to match the mattern?

23:49 pattern

23:49 TimMc: I could race the stack against the heap and try to allocate too much heap before I use too much stack...

23:49 gfredericks: amalloy: what on earth is going on with your for example above?

23:49 dav: ((fn ([[x y]] (+ x y))) [4]) -> NullPointerException

23:50 gfredericks: I can't imagine how :while would be implemented to get that behavior

23:50 teslanick: Thanks for all your help. I'm still making my way out of Plato's proverbial cave over here.

23:50 amalloy: gfredericks: :while only terminates the innermost loop variable

23:50 goes back up a level and starts with the next seq item

23:51 gfredericks: amalloy: that's what I thought; so why is your result finite?

23:51 amalloy: gfredericks: (take 20)

23:51 gfredericks: oooh

23:51 PHEW

23:52 man for a second there for was pretty dang weird

23:53 amalloy: (for [x xs y ys :while (f x y)] [x y]) => (mapcat (fn [x] (mapcat (fn [y] [x y]) (take-while (fn [y] (f x y)) ys))) xs), more or less, i think

23:57 TimMc: dav: You can use :or to put in default values.

Logging service provided by n01se.net