#clojure log - Dec 15 2014

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

0:00 Bruce_Wayne: I need this to be deployed on heroku

0:15 anyone know a good way to make a calendar on a web app?

0:22 sdegutis: Why did Clojure choose to be dynamically typed?

0:22 I find that especially odd because most people who like Clojure seem to prefer static typing.

0:27 rritoch: sdeguutis: You would need to ask the original developers to get an answer to that question but the following issues probably played a role http://stackoverflow.com/questions/3323549/is-a-statically-typed-full-lisp-variant-possible

0:33 puredanger: I don't think that had anything to do with it

0:34 having heard Rich talk about it a few times

0:34 sdegutis: puredanger: what do you think?

0:34 puredanger: I think Rich doesn't have a problem with types, but he prefers (given the benefits and consequences) not to be required to use them

0:35 rritoch: puredanger: So the original developers had nothing to do with the decision? It seems you were just looking for an excuse to counterdict me.

0:35 puredanger: Rich is the original developer

0:36 https://github.com/clojure/clojure/graphs/contributors (richhickey)

0:37 rritoch: I'm aware of that, I have a signed CA

0:37 puredanger: well then, I don't understand the question re original developers

0:38 rritoch: It was a rhetorical question.

0:39 puredanger: my point was that Clojure is not dynamic because statically typed lisps are hard/impossible, but because that's what Rich preferred

0:40 Shen is a pretty interesting statically typed Lisp for example http://www.shenlanguage.org/

0:41 rritoch: Either way, clojure is a bit of a hybrid now. There are often situations where type matters. Sometimes, but not always, clojure will resolve type issues with reflection, but when Java interop is involved, such as return types needing to match that of an interface, sometimes it's required to specifically cast to a required type.

0:42 * puredanger agreed

0:43 puredanger: I prefer to think of Clojure as a language that gives me choices about how much checking I want to do in different parts of my code

0:43 sdegutis: Intersecting.

0:43 puredanger: in some places I may use a bunch of libraries (prismatic etc) and rigorously check data against a schema either at compile-time or runtime

0:44 while in others, I may not care (or it may not make sense)

0:47 sdegutis: I like having compile time static type checking just as a way of having free extra tests.

0:48 puredanger: that is a popular view :)

0:48 sdegutis: Plus it helps me to design my system more thoughtfully, instead of changing some code 5 times before it's what I meant for it to be in the first place.

0:49 That said, it's not the popular view when writing web apps.

0:49 puredanger: I don't feel like static typing has any impact on that for me personally

0:49 in that I always do it wrong 5 times regardless of types :)

0:49 sdegutis: Honestly my only real complaint about Clojure is how long it takes to start up. I know there are tricks to compensate for it, but it's just not the same as having a clean, fresh start.

0:50 haha!

0:50 @ puredanger

0:50 puredanger: well, there's ongoing work in that. we'll get there eventually, maybe next yera.

0:52 it's really the cost of eager var loading that's expensive

0:52 sdegutis: Forgive me if I'm erring on the side of caution i.e. pessimism.a

0:54 puredanger: regarding startup time?

0:54 plenty of room for improvement

0:55 there are limits of course

0:56 Clojure never really targeted optimizing startup time given the jvm (which actually starts pretty quickly now)

0:58 sdegutis: I suppose that's reasonable.

0:58 I don't know what it is. Something just bothers me about Clojure these days.

1:00 rs0: sdegutis: if you work with the JVM a *lot* you get more used to it

1:00 puredanger: you just need more paren hugs ( ( ( ( ( ) ) ) ) ) )

1:00 arrdem: puredanger: I was gonna say have some faith but the parens hug is better :P

1:00 puredanger: I've got more if you need 'em

1:01 sdegutis: :)

1:01 arrdem: up to my eyeballs in 'em over here :c

1:01 sdegutis: Maybe it's actually just web dev that I'm getting tired of.

1:01 puredanger: ,(repeat "()")

1:01 clojurebot: ("()" "()" "()" "()" "()" ...)

1:01 sdegutis: All the static asset pipeline caching, all the hacks, all the nonsense.

1:01 rs0: after studying Clojure, i have a hard time finding programming languages to study that don't look boring. does anyone have suggestions for what i could study to get a similarly mind-blowing experience? Forth, Prolog, Smalltalk, APL?

1:01 sdegutis: Yeah, I'm pretty sure it's actually just web dev that I'm annoyed with.

1:01 puredanger: sdegutis: I'm so tired of that I can't even start

1:02 sdegutis: All the CSS preprocessors, the JS concatenation, the transpilers...

1:02 puredanger: rs0: Factor, Idris, Agda, Shen

1:02 arrdem: rs0: prolog is good, haskell is worthwhile but hard, haven't played with shen but it's somewhere inbetween the other two and clojure

1:03 * arrdem glares at his copy of TBoS

1:03 puredanger: yeah, prolog broke my brain when I first encountered it

1:03 rs0: arrdem: i've already studied haskell on and off. i was most recently looking at lenses and MPTCs (which i now understand in terms of multimethods)

1:03 TBoS?

1:03 arrdem: The Book of Shen

1:03 rs0: ah

1:04 arrdem: Dr. Tavor's overpriced, non US printed Shen manual but I'm not bitter or anything :P

1:04 puredanger: did I hear they were changing the license?

1:05 arrdem: puredanger: yeah the BSD changeover is confirmed. Sent in my £20 yesterday

1:05 rs0: puredanger: why specifically Factor over Forth? any reason?

1:05 puredanger: rs0: no reason / either

1:06 arrdem: damnit... the -1 bug is back

1:06 puredanger: this is one of my favorite Strange Loop talks from Chuck Moore http://www.infoq.com/presentations/power-144-chip

1:06 rs0: puredanger: anyway, thanks; those are good suggestions

1:06 puredanger: a guy on a totally different wavelength

1:06 arrdem: puredanger: that's an awesome talk.

1:07 every time I sat down on my LispM article I had that in the back of my mind as an argument to the contrary :P

1:07 puredanger: I saw him talking to Dan Friedman in the hall and I just thought man, those guys are both awesome and coming from totally opposite ends of the spectrum

1:08 rs0: puredanger: what dichotomy are you guys referring to? just high level/low level?

1:08 arrdem: i'm not sure which LispM article you're referring to

1:08 puredanger: yeah kind of abstraction vs hardware power optimization or something

1:08 arrdem: rs0: http://arrdem.com/2014/11/28/the_future_of_the_lispm/

1:08 puredanger: Moore actually drove to Strange Loop from Nevada

1:09 rs0: arrdem: "It is expected to piss off loper-os."

1:09 arrdem: okay, I immediately see where this is going

1:09 arrdem: :D

1:09 puredanger: that in itself is a lofty goal

1:09 rs0: arrdem: he's fascinating

1:10 arrdem: rs0: I go back and forth on that guy. And Rich. And Alex. It's probably a sign that I'm thinking about your work at this point :P

1:10 rs0: arrdem: but i don't think he's right about everything. i think he's extremely wrong about immutability

1:10 arrdem: rs0: where'd he go off on immutability? I don't remember that one.

1:12 rs0: arrdem: well, i can't remember exactly--i think it might have been his article where he eulogized Urbit or something. he said that mutability is useful and important because the hardware is inherently a mutable substrate, and because the mapping from immutable data structures to the underlying state of the machine is much more complex

1:12 http://www.loper-os.org/?p=1390

1:12 arrdem: yeah I remember reading that one.

1:13 Urbit... is its own kind of crazy.

1:13 I actually agree with loper-os there. The Urbut VM is crap, but for different reasons.

1:13 rs0: arrdem: i took one look at that and kept right on driving, so to speak. the aggressively unfamiliar and arbitrary lingo didn't help

1:13 which is of course superficial, but there was *so much stuff*

1:14 arrdem: yeah. I'm usually willing to read through the vitriol because there is technical merit there, but it takes effort and can't be done in bulk.

1:14 not someone I'd want to actually debate.

1:15 rs0: arrdem: i think he's most correct when he talks about how computers should actually work, and we don't really expect them to--but he's not exactly going out on a limb there, either. it's not a brave statement

1:15 arrdem: oshit. all my tests just passed. brb committing everything.

1:15 rs0: arrdem: i remember one of his articles about video codecs that seemed really out-of-touch with reality, despite the fact that the writing was amazing and hilarious. here, let me find it

1:15 arrdem: http://www.loper-os.org/?p=309

1:16 arrdem: the Kay stuff he's quoting there strikes me as the worst kind of quasi-object-oriented snake oil

1:18 fairuz: How do people usually deploy their clojure app in the test environement? uberjar / uberwar? Or still with lein

1:18 arrdem: fairuz: running lein in production is discouraged, so if you really want "test" you should be running from uberjar/uberwar.

1:19 * arrdem totally runs lein in production

1:19 arrdem: rs0: idk. I like his vision of the loper-os itself and the note taking prosthetic, I just think that he's setting out to do more than needs to be done which is the thesis of my LispM post.

1:20 rs0: he's reinventing a past that never existed and ignoring perfectly good hardware/software to do so.

1:20 why invent a "better" lisp when you could "fix" Clojure or r7rs neither of which is half bad.

1:20 rs0: arrdem: oh believe me, i can't wait to read this article

1:20 arrdem: whether he's right or wrong, he's making very important claims

1:21 arrdem: I'm just offended by his pervasive application of the No True Scottsman argument to define Clojure and any other lisp dialect he doesn't like as Not Lisp. It's kinda funny.

1:22 puredanger: so while I'm playing with reader madness... is #+foo #+bar qux defined?

1:22 rs0: arrdem: yeah. he's positioning it like Clojure is the sellout pop group and Common Lisp is the ballsy underground band

1:23 puredanger: arrdem: meaning what?

1:23 nested feature expressions?

1:24 arrdem: puredanger: are we/will we be allowed to nest host exprs to get logical conjunction?

1:24 yeah.

1:24 puredanger: the current impl has conjunctions built in

1:24 arrdem: kk.

1:24 puredanger: #+(and foo bar)

1:24 arrdem: Oh. Or that.

1:25 puredanger: I don't actually know what your example would do on the current patches but that's one of a few things I'm hoping to get back to soon

1:25 arrdem: I'll be watching with interest.

1:25 fairuz: arrdem: ty. Let say I'm using uberjar. When I did java -jar xxxx-SNAPSHOT-standalone.jar port 3000. I got an error with something like Exception in thread "main" java.lang.AssertionError: Assert failed: Something is wrong with the port argument: port. Is there other way to specify the port?

1:26 arrdem: after Tuesday lemme know if I can help :P

1:26 rs0: whatever happened to clojure-py2 and clojure-scheme? dead projects?

1:26 arrdem: fairuz: just from that I can't help a ton. Can you paste your -main somewher? refheap preferred.

1:27 rs0: well we have pixie now..

1:27 I think that clojure-scheme and clojure-racket are both kinda dead.

1:27 fairuz: arrdem: here you go https://www.refheap.com/94912

1:27 arrdem: Kiss/Oxlang has some life in it but they're more dialects/experiments than imp'ls

1:27 rs0: oh wow, pixie targets RPython. i wasn't familiar with this project

1:28 devll`: `

1:28 arrdem: fairuz: what's (first ["port" "3000"]) gonna be?

1:28 devll`: is Incanter dead too ?

1:28 arrdem: devll`: why would Incanter be dead?

1:28 more feature complete if anything..

1:29 fairuz: arrdem: yeah just realized that dumb mistake.

1:29 I got another error: Wrong number of args (0) passed to: core/production-config but let me investigate first :)

1:30 arrdem: fairuz: hey at least I'm gonna be nice about it :P

1:30 fairuz: arrdem: :)

1:30 puredanger: isn't someone working on an update of incanter?

1:30 arrdem: no idea. Incanter is something I haven't touched yet.

1:30 devll`: I don't see many updates recently .

1:31 puredanger: it has not been very actively developed for quite a while but I still use it occasionally

1:32 Looks like mikera is still tending it, probably useful as a front-end for core.matrix stuff

1:33 TEttinger: mikera's pretty awesome, I've seen some of his projects relating to core.matrix. it's a shame he doesn't come here often

1:33 devll`: Coming for Java background, I really like REPL while writing analytical stuff. I hope Incanter long live and prosper.

1:33 TEttinger: devll`, oh man absolutely

1:34 kenrestivo: (inc anter)

1:34 puredanger: heh

1:34 arrdem: is there a way to "clear" a multimethod? I'm not seeing one.

1:34 TEttinger: I think helping coders make sense of complex data is one of the biggest strengths of clojure

1:34 puredanger: arrdem as in removing existing methods?

1:34 rs0: arrdem: well, there's remove-method

1:34 arrdem: but i don't think you can list or clear methods

1:34 arrdem: puredanger: removing all methods.

1:35 mattrepl: anyone here use incanter?

1:35 puredanger: well MultiFn has reset() :)

1:35 * arrdem digs out clojure.lang.MultiFn again

1:35 arrdem: well damn.

1:35 I can't read.

1:35 lazybot is still AFK or I'd inc.

1:36 puredanger: (remove-all-methods)

1:36 calls that

1:36 arrdem: seeing exactly zero mentions of that googling around.

1:36 puredanger: I'm just looking at the source

1:37 arrdem: totally on ClojureDocs/Grimoire

1:37 puredanger: https://clojuredocs.org/clojure.core/remove-all-methods

1:37 rs0: that reminds me--it's pretty difficult to add multimethods from Java using only Clojure's Java API

1:37 arrdem: puredanger: got a minute to talk about docs stuff before I crash for the night?

1:37 rs0: i ended up using a StringBuilder to construct and eval Clojure code

1:37 puredanger: sure

1:37 rs0: ew

1:38 arrdem: rs0: why we have perfectly good list construction via `

1:38 (dec eval-string)

1:38 rs0: puredanger: https://github.com/rschmitt/dynamic-object/blob/master/src/main/java/com/github/rschmitt/dynamicobject/DynamicObjects.java#L119

1:38 puredanger: rs0: you could just call .addMethod() on the MultiFn

1:39 arrdem: puredanger: have you seen lib-grimoire?

1:39 rs0: puredanger: i realize that, but i was being a reeeeeal choir boy about the whole "don't take dependencies on Clojure's internal Java classes" thing

1:39 puredanger: rs0: <shrug>?

1:39 with great power, yada yada

1:40 rs0: puredanger: which is technically everything other than Clojure#var and Clojure#read I think

1:40 puredanger: arrdem: no, although I've seen enough updates from you here or elsewhere that I inferred what it must be :)

1:40 rs0: pretty much. IFn is kind of unavoidably public

1:40 kenrestivo: "remove all methods" sounds like it should be said in a dalek voice

1:40 puredanger: kenrestivo: agreed

1:40 rs0: puredanger: yeah it gets weird

1:41 arrdem: puredanger: lol. I basically exported the Grimoire datastore as a library and threw an abstraction layer around it so that you can have multiple backends besides the raw filesystem I use.

1:41 kenrestivo: speaking of which, i hope those fixes to multimethods make it into a release soon

1:41 rs0: kenrestivo: which ones?

1:41 puredanger: kenrestivo: the ones in my blog were in 1.7.0-alpha1

1:42 kenrestivo: this one? http://dev.clojure.org/jira/browse/CLJ-979

1:42 puredanger: I have that in my mental AOT bucket, not multimethods

1:42 but yes, I'm hoping to build a case for putting that in 1.7 this week

1:43 kenrestivo: thanks for all the work you're doing to move releases along.

1:43 arrdem: puredanger: so what I can do now is source in multiple repos/dir trees of docs and notes. My question to you is "officially" how should I handle Core|Contrib docs? Obviously I don't expect an authoritative answer now, but I'm cool to just run my own docs repo licensed appropriately or if you guys want to have an official docs package.

1:43 there's a proof of concept repo breaking out the 1.4-1.6 docs and notes somewhere, but I need to partition those.

1:44 puredanger: arrdem: well, I wouldn't gate on anything "official" :)

1:45 arrdem: puredanger: lol I vote on Jira I'm aware what I'd be waiting for ;)

1:51 rs0: arrdem: you mentioned that you go back and forth on Rich (among others). i was wondering what you think he might have gotten wrong

1:52 arrdem: rs0: lol you expect me to answer that in public?

1:52 /s

1:53 ticking: transducers

1:53 they are not worth the introduction of local mutable state

1:54 arrdem: So... I think it's an interesting design decision to base transducers on function composition. I'm not sure it's a decision I agree with, but I haven't thought about it yet.

1:55 ticking: they could also take an additional state argument which would be fine as well

1:55 rs0: ticking: you mean the stateful transducers like unique and take and so on?

1:55 ticking: rs0: yes

1:55 rs0: i think it's okay to have mutable state, and it's okay to have shared state, but it's not okay to have shared mutable state

1:56 and by "shared" i mean something more general than "across threads"

1:56 puredanger: inc that

1:56 ticking: rs0: any lazyly transduced function or channel will be shared

1:56 puredanger: transducer state is encapsulated inside the process and not shared

1:56 transducer functions are never lazy

1:56 ticking: the sequence produced by them is

1:56 potentially

1:57 puredanger: you mean via "sequence" ?

1:57 transduce doesn't produce a sequence

1:58 ticking: puredanger: via sequence or via a channel that has an associated transducer

1:58 once you do something that is not completely eager

1:58 puredanger: I don't know what a sequence with an associated transducer is

1:59 a channel encapsulates its transducing function (and any state) inside the channel

1:59 ticking: (sequence xf (range 1000))

1:59 nxqd: hi guys

2:00 puredanger: ticking: if you're saying that the sequence produced by that is stateful, I don't agree with that

2:00 nxqd: What is the meaning of this function in clojure : (defn ^String as-str . Is it used to define a function of an object ?

2:00 rs0: nxqd: i think you're referring to the type hint

2:00 puredanger: nxqd: ^String is a type hint on the return value

2:01 ticking: I don't think it's any different than a lazy seq with a pending tail

2:01 nxqd: rs0 and puredanger. Thanks for the keyword. I would read more about type hints :)

2:01 puredanger: ticking: (conceptually, obviously impl is different)

2:01 ticking: puredanger: yeah because lazy seqs are statefull as well, but at least they use atoms

2:02 puredanger: ticking: the state is encapsulated via synchronization in LazyTransfomer, so it's not any different in safety than lazyseq

2:03 ticking: puredanger: people are going to use that new datatype in places where it should not be used

2:03 puredanger: I'm saying you can't use it in that way

2:04 ticking: puredanger: I'm not saying that the transducers themselves are the problem, but the introduction of volatile

2:04 puredanger: unless you create your own transducible process that did evil things

2:04 ticking: oh, just volatile itself?

2:04 ticking: yeah

2:04 puredanger: it's a tool

2:04 ticking: but volatile was introduced for making transducers faster

2:04 puredanger: bad programmers do bad things

2:04 ticking: yeah but people will abuse it

2:04 no

2:04 puredanger: so don't do that

2:05 ticking: bad languages encourage mediocre programmers to do bad things

2:05 the way it will be used is the way the language encourages usage

2:05 also partition-bu

2:05 partition-by

2:05 nothing to do with the above

2:05 but its completely useless compared to a binary arggument version that splits on returning true

2:06 rs0: i gotta say, i think ticking is right regarding the larger point

2:06 puredanger: well, I disagree.

2:06 rs0: i'm less and less sympathetic to the arguments about how great multiple inheritance is if people would just use it correctly

2:06 but i don't think that transducers or volatile are an example of that

2:07 puredanger: Clojure has always aimed to give developers powerful tools

2:07 Empperi: I haven't really decided if I like volatiles in Clojure or not

2:07 they are a tool like puredanger said

2:07 but then again, a dangerous tool in wrong hands

2:08 most of the tools in Clojure are pretty safe for idiot use

2:08 rs0: powerful tools aren't necessarily dangerous. immutable persistent collections are a good example. how do you misuse them?

2:08 the worst-case scenario is pretty much poor performance

2:08 or sticking java.util.Date instances in them

2:08 Empperi: what I said :)

2:08 arrdem: ^ lol

2:08 puredanger: exactly

2:09 there are a million ways to subvert the paths that exist in Clojure to do things that are a bad idea

2:09 Empperi: anyway, volatiles are great to have when you need to get that very last performance improvement

2:09 puredanger: I would much rather have the tool for that then have to drop into java

2:10 if you want to see some abuse, go look at the alioth programs I worked on :)

2:10 Empperi: or some java programs I've written :P

2:10 or some co-workers of mine

2:10 arrdem: puredanger: come now that doesn't even count as Clojure. That's C written in Java written in Clojure.

2:10 rs0: if i had to maintain an incompetent developer's code, i would prefer that that code was being written in Clojure. i guess it's possible to basically write PHP in Clojure but all the idioms and documentation and creature comforts of the language are working against it

2:11 Empperi: one of the things I love in Clojure is the fact that it makes it really hard for you to write bad code

2:11 rs0: obligatory: https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition

2:11 arrdem: rs0: right because immutable datastructures force decoupling so unless there are atoms literally everywhere it can't be bad.

2:11 Empperi: one sees that "this cannot be the way it should be" when writing clojure improperly

2:21 ticking: puredanger: sorry disconnect

2:45 TEttinger: Empperi, I recognize that it isn't easy to write bad clojure, but I do it anyway https://www.refheap.com/94916

2:45 that got reformatted by refheap, the original message is

2:46 (clojure.string/join" "(repeatedly 200(fn[](apply str(concat[(rand-nth["s""z""t""k""ch""n""th""sh""y""p""k""l""g""ny"""""])](take(+ 3(* 3(rand-int 2)))(interleave(repeatedly #(rand-nth["a""i""o""e""ia""u""ai"]))(repeatedly #(rand-nth["""""""-""'"]))(repeatedly #(rand-nth ["s""pr""t""rl""n""k""gl""g""ts""lt""gr""rk""kh""x""sh""ng"]))))[(rand-nth["urr""icth""ato""omkur""iashi""oroth""okh""yng""otep"""""])])))))

2:48 Empperi: TEttinger: :)

2:48 TEttinger: although to be fair there's no way that would fit in one IRC message in any curly-brace language

2:49 ticking: TEttinger: needs more space

2:49 TEttinger: hits the limit in about 5 more chars, ticking

2:49 ticking: ah

2:50 TEttinger: 414 chars with the prepend to evaluate, and the limit on some servers is around 418-420-something

2:55 ticking: TEttinger: what is this for :)?

2:55 aaelony: hi, I'm doing some Java interop with a library that has little documentation. I am able to get a method call to return an object that appears to have the information I need (a country lookup) among the 12 fields in that object, however I'm not sure how to extract one particular field. Is there a way to learn the names of the fields the object contains, and extract one of them?

2:55 TEttinger: aaelony, yeah you can use reflection, I wouldn't recommend overusing it though

2:56 ticking, in another channel we got trying to come up with ancient greek sounding random words

2:56 aaelony: TEttinger: How would I do that? Once I know the correct name, I'll use that name in the code

2:57 ticking: TEttinger: is there a reason for multiple empty strings in the syllable lists?

2:57 aaelony: for example, I can see: #<TheObjectNameHere> blah 123 456 foo bar

2:57 suppose I want the "foo" part

2:58 TEttinger: ,(clojure.reflect/type-reflect String)

2:59 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.reflect>

2:59 TEttinger: ,(require 'clojure.reflect)

2:59 clojurebot: nil

2:59 TEttinger: ,(clojure.reflect/type-reflect String)

2:59 clojurebot: {:bases #{java.lang.Object java.lang.Comparable java.lang.CharSequence java.io.Serializable}, :flags #{:public :final}, :members #{#clojure.reflect.Method{:name replaceAll, :return-type java.lang.String, :declaring-class java.lang.String, :parameter-types [java.lang.String java.lang.String], :exception-types [], ...} #clojure.reflect.Field{:name CASE_INSENSITIVE_ORDER, :type java.util.Comparator, ...

2:59 TEttinger: ,(:fields (clojure.reflect/type-reflect String))

2:59 clojurebot: nil

2:59 aaelony: that is very, very cool

3:00 thank you TEttinger

3:00 TEttinger: no prob, I just learned about it too!

3:00 ,(:members (clojure.reflect/type-reflect String))

3:00 clojurebot: #{#clojure.reflect.Method{:name replaceAll, :return-type java.lang.String, :declaring-class java.lang.String, :parameter-types [java.lang.String java.lang.String], :exception-types [], ...} #clojure.reflect.Field{:name CASE_INSENSITIVE_ORDER, :type java.util.Comparator, :declaring-class java.lang.String, :flags #{:public :static :final}} #clojure.reflect.Method{:name indexOf, :return-type int, :de...

3:00 aaelony: wow

3:00 TEttinger: I knew it was possible, just not the details

3:01 aaelony: :)

3:01 TEttinger: ,(:members (clojure.reflect/type-reflect Math))

3:01 clojurebot: #{#clojure.reflect.Method{:name atan, :return-type double, :declaring-class java.lang.Math, :parameter-types [double], :exception-types [], ...} #clojure.reflect.Method{:name getExponent, :return-type int, :declaring-class java.lang.Math, :parameter-types [float], :exception-types [], ...} #clojure.reflect.Method{:name max, :return-type long, :declaring-class java.lang.Math, :parameter-types [long...

3:01 TEttinger: neat stuff

3:02 ticking: indeed

3:04 aaelony: hmmmm, uh oh..

3:04 IllegalArgumentException No implementation of method: :typename of protocol: #'clojure.reflect/TypeReference found for class

3:06 TEttinger: how'd that happen...

3:07 aaelony: it's weird..

3:07 but this works: (reflect obj-name)

3:07 I have a long method call to generate the object

3:08 if I assign that long method call to a (def x ...) and then reflect the x, it works

3:08 otherwise, it got confused

3:08 TEttinger: oh, yeah type-reflect takes a type, not an object of that type, that might be it

3:08 aaelony: ahh

3:09 well, it's working now :)))

3:09 TEttinger: sweet!

3:09 aaelony: really sweet!!

3:09 big thanks for showing me reflection

3:13 TEttinger: no problem, it's something I haven't needed yet but know I will someday

3:16 arrdem: I take it there is no good way to do string unescaping from Java or Clojure without a library?

3:18 ticking: (+ 3 (* 3 (rand-int 2))) is a bit weird :D

3:18 TEttinger: why?

3:19 TEttinger: oh heh

3:20 ticking, we were fiddling with procedural name generation and some of the greek gen was handy.

3:21 greek generator: https://www.refheap.com/94919

3:22 ticking, that's used to get a random number of vowel-option-consonant triples, either 3 or 6 items in total, where option is either an empty string or sometimes a fantasy standby character like ' or -

3:23 ticking: (rand-nth [3 6])?

3:24 TEttinger: it was a modified version of some more numbers that were allowed

3:24 ticking: ah

3:25 TEttinger: neat though, it saves 7 chars :P

3:25 thanks ticking

3:25 ticking: yeah

3:56 rritoch: Hi, is anyone here familiar with classfiles? I'm trying to make a persistent classfile reader but I keep running into cp_info.tag = 0 cases which I can't find any documentation on. As a test I wrapped the inputstream as a pushbackinputstream and did a pushback on the zero, and now it seems to be working, but this doesn't seem right to me.

3:57 WIth some class files this never hits the cp_info.tag = 0, but many do.

4:00 You can see the pushback here > https://github.com/rritoch/clj-bytecode/blob/master/src/java/com/vnetpublishing/java/asm/bytecode/T_CPInfo.java#L80-L82

4:32 ticking: TEttinger: https://gist.github.com/ticking/f25dbc47d084cbfed89b

4:32 306 chars

4:34 zot: good (or morning afternoon evening)!

4:34 TEttinger: nice, ticking. the extra empty quotes were to change the behavior so ' and - are not in 2/3 of syllables

4:34 zot: when using clojure.async, with code that's running in another thread, what's the idiomatic way to handle exceptions? i already have a control channel and could do try/catch and pass it through the channel, but was curious if there are other ways (that might not rely on a control channel)

4:35 ticking: TEttinger: yeah, I figured it was to skew the probability distribution, so I just went with a slighlty altered one

4:36 TEttinger: adding them back won't increase the code size significantly though

4:36 TEttinger: oh yep.

4:36 it's good.

5:04 dagda1_: I've just been using transducers with native javascript arrays in clojurescript and I had to wrap the reducing function in completing (completing-me (fn [arr x] (.push arr x) arr))

5:04 I mean (completing (fn [arr x] (.push arr x) arr))

5:04 what does the tranducer function expect that made this necessary and why is this not necessary with something like conj

5:05 (transduce (filter #(not (.hasOwnProperty prevChildMapping %))) (completing (fn [arr x] (.push arr x) arr)) #js [] nextKeys) is the whole expression

5:06 Bronsa: dagda1_: conj already has 0 and 1 arities

5:06 ,(conj)

5:06 clojurebot: []

5:06 Bronsa: ,(conj [1])

5:06 clojurebot: [1]

5:06 dagda1_: Bronsa: which one does the reducing function expect, 0 or 1?

5:07 Bronsa: dagda1_: a reducing function to transduce has to have 0 1 and 2 arities

5:08 dagda1_: read http://clojure.org/transducers#toc8

5:08 dagda1_: Bronsa: perfect, I missed this point. Thanks

5:09 Bronsa: dagda1_: note that completing still expects your function to have the 0 arity, it will only add the 1 arity

5:10 dagda1_: Bronsal: I need to add the 0 arity to my function?

5:12 Bronsa: dagda1_: no, sorry. I was wrong, the reducing function only needs 1 and 2 arities.

5:13 dagda1_: Bronsa: k, thanks

5:15 TEttinger: I bet Raynes is wondering what's going on with refheap

5:16 https://www.refheap.com/94935

5:16 ticking, with those shortenings you did, I was able to add punctuation to make fake sentences

5:16 ticking: TEttinger: nice :D

5:31 TEttinger: without the re-find right? otherwise only single words are output for me

5:32 TEttinger: uhhh

5:33 I made a bunch of changes, the re-find is so it doesn't have punctuation at the start and starts with a capital letter

5:36 rritoch: I found the problem and the classreader is now working. Aparently there's an undocumented flaw where longs and doubles count as two entries in the constant pool table. So this library is now functional, but has a ways to go.

5:37 ticking: TEttinger: well the version you posted only produces single words :\

5:37 TEttinger: this one? https://www.refheap.com/94935

5:38 hydo: I have a namespace clash with clojure.core/update in module X, despite it being :required with :as something, and (refer-clojure :exclude [update]). Could someone tell me what I'm missing?

5:38 Bronsa: rritoch: I don't have contex but the fact that longs and double take 2 slots is not an undocumented flaw, it's definitely documented in the jvm spec

5:39 rritoch: Bronsa: Ok, well I'm looking at the specs and I didn't notice anything about it.

5:39 ticking: (if (seq b) s (.toLowerCase(a s))) ?

5:40 TEttinger: b is always either an empty string or not, but (.toLowerCase (apply str(flatten ""))) is also ""

5:40 TEttinger: so the check is not needed

5:40 TEttinger: ,(seq "")

5:40 clojurebot: nil

5:40 Bronsa: rritoch: in fact there are bytecodes that come in `x` and `x`2 variant, where the `x`2 variant works for double/longs by acting on two slots rather than one e.g. pop vs pop2

5:40 rritoch: Bronsa: Ok, I found it. They should really highlight that fact

5:41 ticking: ,(.toLowerCase (apply str(flatten "")))

5:41 clojurebot: ""

5:41 TEttinger: and that's a used value, it needs to apply str so it doesn't have lazyseq@126t263 as a word

5:41 ticking: ,(str)

5:41 clojurebot: ""

5:41 rritoch: Bronsa: The only way I was able to solve the problem was looking at other (non persistent) classreaders

5:41 TEttinger: wait, I used flatten "" ?

5:42 ticking: TEttinger: maybe you test the wrong variable? because b is (n"!""..."".""""""""")

5:42 TEttinger: ah, you're confusing b (just the beginning) with the s I use (the single word string)

5:42 ticking: TEttinger: yeah youre right sorry haven't slept much

5:42 TEttinger: it's fine, you've already shaved like 100 chars off :P

5:43 ticking: I thought you did (if (seq b) b (something b))

5:43 TEttinger: no, it checks b to see if there's punctuation, if not it lowercases the word

5:43 ticking: yeah

5:43 I misread that as the above though :D

5:43 rritoch: Bronsa: I haven't actually made it that far with this system, but its good to know. Im trying to make persistent class manipulation systems, it should make inspecting and manipulating code at a low-level easier, and possibly thread-safe.

5:44 Bronsa: rritoch: nice, have you had a look at the syntax I've used for bytecode emission in t.e.jvm? might be relevant

5:45 rritoch: Bronsa: I'm not familiar with t.e.jvm , is that short for something?

5:46 Bronsa: rritoch: tools.emitter.jvm

5:46 rritoch: https://github.com/clojure/tools.emitter.jvm/blob/master/src/main/clojure/clojure/tools/emitter/jvm/emit.clj#L1402-L1442 this is how I'm representing bytecode/class info as a persistent data structure

5:46 rritoch: Bronsa: Oh, I haven't heard of it. But I'll take a look.

5:46 ticking: TEttinger: and yeah the last one only produces single words

5:47 TEttinger: solved it

5:47 ticking: if you copy from refheap, it turns one " " into "\n"

5:47 by line breaking inside a string

5:47 (let[a #(apply str(flatten %))r repeatedly n #(rand-nth %&)w(fn[](let[b(n"!""..."".""""""""")s[(n"S""Z""T""K""N""Th""Sh""Y""P""K""L""G""Ny""Ft""Cth")(r(n 1 2)#(vector(n"a""i""o""e""ia""u""ai")(n"""""""-""'")(n"l""h""s""pr""t""rl""n""k""gl""g""gh""ts""lt""gr""rk""kh""x""sh""ng")))(n"urr""ato""omkur""iashi""oroth""okh""yng""otep""ilal""ugu""""")]][b" "(if(seq b)s(.toLowerCase(a s)))]))](re-find #"[A-Z].+"(a(r 200 w))))

5:48 ticking: TEttinger: ah yes I see :D

5:48 TEttinger: that in turn breaks the regex, which only goes to end of line

5:53 ticking: TEttinger: btw you can shave of one char by changing #(vector to (fn[][]

5:55 rritoch: Bronsa: I see. What I'm doing is mostly in java, Developing persistent types for low-level class manipulation. Currently I only have one clojure function, read-class, which reads the source classfile for a provided class so it can eventually be manipulated.

5:56 Bronsa: Though your project looks like it is very close to something I've been asked for. Someone wanted me to write code which would compile clojure forms into opencl or cuda.

5:57 Bronsa: rritoch: ah gotcha, I assumed you were doing this in clojure :)

5:57 rritoch: Bronsa: No, just for clojure

6:00 Bronsa: https://github.com/rritoch/clj-bytecode

6:01 Bronsa: The types are all persistent, and being designed to interact with clojure to make it easy to inspect classes. Though I'm not sure this would apply well to generated code unless I knew the classname and classloader it was generated with/into.

6:51 ticking: dn

6:51 sorry, does anybody know if there is a reason that core.match is not able to match lists and sets?

6:52 It seems weird that the patterns only encompass a small subset of the clojure datastructures syntactically expressable

6:59 yogsototh: Hi does someone knows how I could write a test.check generator to generate maps with fixed keys?

7:00 I would like to generate {:keyword (gen/string)}

7:02 CookedGryphon: just use fmap

7:05 a pattern I sometimes use if I want a fixed structure with multiple generated components is to gen a tuple of all the values i want, then fmap a function which just slots each of the generated values into my structure

7:20 noidi: yogsototh, there's gen/hash-map

8:00 yogsototh: noidi: thanks, I don't know why I didn't saw it!

8:54 hydo: Who was it that was working on the context class loader? I asked a question a few days back about how I had to disable it to get my plugin to work, and someone else said that there was work being done to make it semi-optional or somesuch. I'd really like to use things like embedded nrepl in my project :)

8:55 I just can't remember who it was.

9:19 m1dnight_: guys, I'm trying to manipulate some code with a macro but i'm not getting what i want

9:20 I have a function replace-recur which should replace (recur ..) with (do (foo) (recur ...))

9:20 I'm not sure what to pass to the function that does this for me though..

9:20 At the moment I call it like this: (replace-recur % `end-receive), where % is my form

9:20 and in the form I traverse and return this: (= (first body) 'recur)

9:20 `(do (fnname) body)

9:20 oh, sorry for multiline paste

9:21 but this gives me, instead of "meta-clojure.stm.actor-friendly/end-receive", "meta-clojure.stm.actor-friendly/fnname"

9:26 stuartsierra: m1dnight_: If "fnname" and "body" are arguments to the macro, you probably need to unquote it like `(do (~fnname) ~@body)

9:30 m1dnight_: hrm, okay

9:30 i'm testing it atm hold on. Some issues atm with emacs :p

9:32 is it nrmal that lein run does not print my expanded macro, and emacs does?

9:32 it just gives me back my input, i dont get it :p

9:34 oh wait, for '(and 1 2) it does give me back my desired output

9:34 stuartsierra: m1dnight_: It's hard to diagnose editor / environment issues over chat. :) The standard way to test a macro from the REPL is (macroexpand-1 '(my-macro …))

9:34 m1dnight_: yeah, that is what I'm trying

9:34 in my core.clj I have (println (clj/macroexpand '(and 1 2)))

9:35 that works fine in emacs and in lein repl console

9:42 ugh, what is this sorcery :p

9:43 https://github.com/m1dnight/meta-clojure/blob/master_slave_transactions/src/meta_clojure/core.clj

9:43 this is the core.clj file

9:43 https://github.com/m1dnight/meta-clojure/blob/master_slave_transactions/src/meta_clojure/stm/actor_friendly.clj#L658

9:43 this is the code it is calling

9:44 is there something about namespaces and macros that differs between lein run and emacs?

9:44 oh wait, I restarted cider and now I have the same problem again

9:44 so now it matches the lein run output

9:50 stuartsierra: Wow, there's a lot going on in there. :) Don't think I'll be able to help much.

9:50 Remember that Clojure's macroexpand keeps expanding the source form until the first element is no longer a macro. macroexpand-1 is usually easier to use if you just want to see what your macro is doing.

9:55 m1dnight_: well, that's what I'm trynig

9:55 it seems to work fine in cider, but lein run just gives me unchanged input

9:55 not the kind of issues one likes to handle on mondays :(

10:01 silasdavis: where can I find an authoritative latest version for org.clojure/foo libraries?

10:01 for use in project.clj

10:01 justin_smith: silasdavis: lein search for finding, lein ancient for getting info of newer versions

10:02 clojars has search too

10:02 silasdavis: yeah I usually use clojars

10:02 stuartsierra: silasdavis: http://search.maven.org/

10:02 m1dnight_: so it appears that I have to fully qualify my macro, even though I expand in the namespace it is defined in

10:02 silasdavis: but for example data.avl is not on there

10:02 justin_smith: https://github.com/xsc/lein-ancient

10:02 stuartsierra: All org.clojure libs are released to the Maven Central Repository, not necessarily Clojars.

10:02 silasdavis: ah

10:02 cool thanks

10:05 engblom: silasdavis: I am using 'lein ancient' for upgrading all dependencies to the latest. https://github.com/xsc/lein-ancient

10:05 silasdavis: It is a lein plugin that is nice to have

10:31 nXqd: hi guys, what is the trick behind showing clojure doc of the function under the cursor in this video : http://youtu.be/HXfDK1OYpco?t=8m14s

10:31 * in emacs editor

10:52 itruslove: nXqd: it's cider's eldoc integration. You will need to add a tiny bot of configuration to your init.el to turn it on. See the first item in https://github.com/clojure-emacs/cider#basic-configuration

11:01 ordnungswidrig: Is there a simple way to graph the dependencies in a lein project? (Including different revisions required by transient dependencies)?

11:01 munderwo: lein deps :tree

11:02 that gives you wants currently depended on by your leiningen project

11:04 lgrapenthin: Is it true that I still have to run an extra JVM to "lein cljx auto"?

11:05 (I'd prefer cljsbuild would do this already)

11:07 ordnungswidrig: munderwo: i'd like to have a graph: blobs, connected by lines

11:30 birdspider: hello, in java "0xFF000000 is -16777216" in clojure "0xFF000000 is 4278190080" why ? I assumed that the literal syntax for hex is the same ? I suppose it gets auropromoted but is there a way to keep it java-style at least in local scope ?

11:30 justin_smith: birdspider: fixed point literals are longs in clojure, ints in java

11:30 birdspider: justin_smith, aaaah

11:31 justin_smith: &(unchecked-int 0xFF000000)

11:31 ,(unchecked-int 0xFF000000)

11:31 clojurebot: -16777216

11:31 birdspider: very nice, thank you

11:31 Bronsa: birdspider: clojure numeric literals are always autopromoted anyway

11:32 ,Long/MAX_VALUE

11:32 clojurebot: 9223372036854775807

11:32 Bronsa: ,9223372036854775808

11:32 clojurebot: 9223372036854775808N

11:32 Bronsa: ^ it's autopromoted to a bigint

11:33 birdspider: Bronsa, yes I knew that, I just wanted to be unchecked in this particular case since im in java-interop-land - but could formulate what I needed for google :)

11:37 justin_smith: so unchecked-int should do what you need then

11:46 jeffterrell: To nobody in particular: in case you're ever helping anybody with a 4Clojure problem and they're getting time outs, the problem might be that they're using `for`. https://github.com/4clojure/4clojure/issues/211

11:46 I spent days wrestling with time outs until I found that.

11:48 Also apparently `case` doesn't reliably work either.

12:58 aaelony: hi, I'm using a static class method via java interop and not understanding the behavior I'm seeing. I can call (.methodname (. (. com.blah.blah.blah.blah.util.theLibrary _aMapField) findResult x y ) ) and get the output of the function I am looking for, e.g. the "foo" part of #<TheObjectNameHere> blah 123 456 foo bar. But.. if I wrap the methodname call above in a function, I get a "No matching method found" error. I also need to avoid using

12:58 reflection as this method call will happen a lot. any ideas on how to resolve this?

13:00 noonian: i'd recommend using the threading macro or .. to make that a little more readable. if it isn

13:00 aaelony: noonian: yeah, I've been trying that, but the java call is somewhat fragile

13:01 noonian: are you trying to dynamically build the method call in your function? thats something you will probably need to use a macro for if so

13:01 mnngfltg: static class methods you can also call like this: (java.lang.Math/abs -3)

13:01 aaelony: I just need to pass the method call 2 arguments and capture the result

13:02 mnngfltg: I'm trying to convert my call to (java.lang.Math/abs -3) syntax.. haven't been successful with that yet

13:04 noonian: something like this? https://www.refheap.com/94947

13:04 aaelony: let me try...

13:06 noonian: that gives me "No matching method found"

13:07 ... at clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:80)

13:07 ben8: hello clojure. I have question: if someone running clojure web in production - do you use Nginx as proxy and are there alternatives?

13:07 justin_smith: ben8: nginx is the best option I know of

13:08 ben8: ah ok. Netty maybe?

13:09 mnngfltg: ben8, Apache is fine too for my needs

13:09 justin_smith: ben8: none of the java http servers I know of have the security features of nginx.

13:10 ben8: I see. jetty is not that great...

13:11 there is for example https://github.com/ztellman/aleph

13:11 justin_smith: sure, but you still should put nginx in front of that

13:14 TimMc: heck, put 3 in front in serial

13:14 just to be sure

13:14 ben8: juston_smith: thanks for the info. I'm trying to figure out why this is standard, and if there is not a more light weight way of load-balancing (?)

13:15 justin_smith: ben8: it's not about load balancing, it's about not getting your shit hacked

13:15 andyf: Bronsa: If I have a :map ast, is there already a util fn to get the :vals ast for a particular key? Easy for me to write, but wondering if it exists.

13:15 justin_smith: ben8: load balance however you like, but you are better off with nginx in front regardless

13:17 ben8: last I checked, nothing java native did what it does, sadly.

13:17 ben8: I see. on what attack vectors? DDOS?

13:17 trying to wrap my head around this. I wonder what Java-enterprise solutions look like

13:17 Tomcat is not very fancy

13:17 justin_smith: ben8: there are a lot of gotchas in http. nginx covers them.

13:18 ben8: right, you put an nginx reverse proxy in front of tomcat

13:22 ppppaul: can someone point me to a url that can help me learn about the datomic aggregate functions

13:23 justin_smith: ben8: there is a nice rundown on setting nginx up securely, if you want to use something else instead, there should be equivalent options for each of the settings http://www.cyberciti.biz/tips/linux-unix-bsd-nginx-webserver-security.html (you need to scroll down a bit until you get to nginx specific stuff)

13:24 ben8: ok, cool. there is this specific module: https://github.com/nginx-clojure/nginx-clojure

13:24 justin_smith: ben8: that is one option, but it is more often to just set up nginx as a reverse-proxy

13:24 though I hear the plugin module method does have excellent performance

13:24 s/more often/more common/

13:37 TimMc: justin_smith: Looks like just headers and timeouts, basically.

13:38 justin_smith: and blacklists based on referrer

13:38 TimMc: From the article: "Referer spam is dengerouns."

13:38 justin_smith: yeah, not a top notch article

13:38 TimMc: cyberciti.biz

13:39 .exe

13:41 justin_smith: TimMc: I don't pretend to be an expert on all the particulars, but I have been told that nginx will protect from a bunch of stuff that the java based servers don't really address (or don't address properly). But I would be pleased to see a more reputable source. I just went on word of mouth from a trusted colleague to be honest.

13:41 engblom: There seem to be plenty of web frame-works for clojure. Which one do you recommend at this moment?

13:41 TimMc: I would say "eh, adding nginx can't hurt" but it does increase the attack surface a little.

13:45 technomancy: it reduces the attack surface since nginx should run as a separate user and has a much stricter HTTP parser.

13:45 elarson: TimMc: I could see it reducing the attack surface by only exposing nginx vs. a cluster of java based servers.

13:48 TimMc: technomancy: *Should* run as a separate user, but it's still a C program exposed to internet traffic.

13:48 A buffer overflow + privilege escalation could still lead to funtimes.

13:48 nginx is pretty mature so that's less likely than a vuln in your own program, but that does still contribute to an increased attack surface.

13:49 technomancy: if you're terminating in Java then you don't need a privilege escalation

13:50 TimMc: OK, so the filtering it does probably decreases the overall attack surface, but I think it bears mentioning.

13:50 hiredman: technomancy: you are refering to port 80 being a privileged port?

13:51 (because that is easily fixed)

13:51 technomancy: hiredman: no, just that the jvm is likely to run as the same user as your application code

13:51 so a compromise will likely expose your DB, etc

13:51 hiredman: ah

13:52 justin_smith: and local priv escalations are available on every system out there, even openbsd, and clojure has a bytecode compiler and shell access for arbitrary strings available at runtime

13:57 TimMc: hiredman: Huh, I never thought about that port 80 issue.

13:58 I guess I've always either run on a different port or had something else fronting my app.

14:13 justin_smith: (inc eastwood)

14:14 amalloy_: you around for a lazybot restart?

14:14 "lein do clean, check, eastwood, run"

14:15 andyf: justin_smith: Find something non-obvious?

14:15 justin_smith: yeah, yet again :) thanks

14:16 Bronsa: andyf: if you missed it, ccw now has eastwood integration

14:17 andyf: I did notice that.

14:18 Bronsa: The quickref docs for ASTs say that :tag is "The tag this expression is required to have", whereas :o-tag is "The tag of this expression, based on the node's children". If that is correct, what criteria is used to determine :tag ? Something about how the value is used?

14:19 I don't need to know in great detail, just curious about the basic idea.

14:19 Bronsa: andyf: yeah. differences between :o-tag and :tag imply casts/boxings

14:20 andyf: re your earlier question -- no, you have to search in :keys and use the index.

14:21 andyf: In my particular case right now, I'm looking at a call to clojure.core/str in a place where it is the value of a literal map key. Its :tag is java.lang.String, but its :o-tag is java.lang.Object. Since clojure.core/str has a :tag of String in its defn, this seems backwards to me.

14:22 I wrote a function to do it in the mean time. Thanks for the info, though.

14:22 triss: hey all. I recently rebooted and my clojure/cljs/lein/chestnut project has gone to pot.

14:22 aaelony: noonian: Thanks for your help earlier, it turns out the answer was that I needed to cast my function arguments to the types that java expected. That solved everything.

14:22 amalloy: justin_smith: aww, i thought we'd fixed the problem of needing restarts

14:22 Bronsa: andyf the return type of an .invoke call is Object, thus the :o-tag is Object. str has a type hint of String the :tag will be String

14:22 noonian: aaelony: nice!

14:22 triss: i'm getting this error:

14:22 java.lang.IllegalArgumentException: No implementation of method: :make-reader of protocol: #'clojure.java.io/IOFactory found

14:22 for class: nil

14:23 aaelony: what a relief... ;)

14:23 triss: when it comes to compiling my cljs

14:23 everything was fine prior to restating the repl

14:24 andyf: Bronsa: OK, so :o-tag is indeed an inferred type, but it is a generic Object because :invoke's all return that type. :tag is what the value is required to be, because that is what the type tag on the defn says it should be?

14:24 triss: I see: Uncaught ReferenceError: goog is not defined(index):9 (anonymous function)

14:24 in the browser

14:24 I've tried lein clean, lein cljsbuild clean and restarting and the issue remains

14:24 stephenmac7: Is (last (take n l)) or (nth l (inc n)) preferred?

14:25 Bronsa: andyf: yeah

14:25 stephenmac7: (dec n) I mean

14:26 ,(last (take 3 '(1 2 3)))

14:26 clojurebot: 3

14:26 amalloy: justin_smith: interesting. the last thing lazybot remembers saying or hearing was a NOTICE he sent to someone about an unread $mail message

14:26 triss: is my app now not able to find the google closure stuff? (wherever that comes from... this stuff is a bt of a mystery to me)

14:26 stephenmac7: ,(nth '(1 2 3) (dec 3))

14:26 clojurebot: 3

14:26 amalloy: after that there have been lots of server messages (eg, QUIT/PART), but no messages to or from users

14:27 no, i guess that's not true

14:36 justin_smith: amalloy: which part? I am fully ready to blame mongo, of course

14:37 (inc eastwood)

14:37 lazybot: ⇒ 4

14:37 amalloy: justin_smith: nah, i was wrong

14:38 justin_smith: amalloy: it would be nice to track down the rest of the instability issues, I'll be happy to accept any logs that help track the issue down

15:03 nicferrier: if I want to map over a ref, can I just go (map #(...) (dosync @ref))

15:04 technomancy: nicferrier: the dosync there is a no-op

15:05 it works but it probably doesn't do what you think it does

15:05 justin_smith: yeah, if you wanted to ensure refs are in sync while mapping, you could do (dosync (map ...))

15:05 nicferrier: I just want to get at the value

15:05 technomancy: justin_smith: that would also be a no-op =)

15:05 justin_smith: no need for dosync if you are not updating anything

15:05 amalloy: justin_smith: that's lazy :P

15:05 technomancy: justin_smith: multiple consistent reads also need a dosync

15:05 justin_smith: technomancy: I mean if the fn inside the #() did any ref alterations

15:06 nicferrier: oh I thought I wasn't even allowed to deref outside of a tx?

15:06 justin_smith: fair points

15:06 amalloy: nicferrier: observation is always free

15:06 technomancy: as long as you don't need to guarantee consistency with other reads you should be good without it

15:07 nicferrier: ok then.

15:07 hum.

15:13 amalloy: haha. just found a lazybot bug

15:13 (incrementing users works even with synonyms)

15:13 lazybot: ⇒ 1

15:14 AimHere: (incredibly interesting)

15:14 lazybot: ⇒ 1

15:15 dweave: if you were making a real time chat app in clojure how would you go about it.

15:18 TimMc: amalloy: Nice.

15:18 $karma interesting

15:18 lazybot: interesting has karma 0.

15:18 TimMc: $karma redibly interesting

15:18 lazybot: redibly interesting has karma 1.

15:18 justin_smith: haha

15:18 dweave: how does aleph differ from an event loop

15:19 justin_smith: that's a weird question

15:19 dweave: mine?

15:19 justin_smith: it's like asking "how does a rabbit differ from biology"

15:19 dweave: how does aleph differ from node’s event loop

15:19 i guess

15:19 conceptually

15:20 amalloy: well more than one thing can happen at a time

15:20 that's a big plus

15:20 justin_smith: for one thing, aleph has actual threads

15:20 dweave: i’m just trying to discover some different paradigms for making real time apps

15:20 amalloy: also, aleph is a websever built on top of lamina; lamina has all the primitives you're thinking of

15:21 noonian: with a real time chat app your server is pretty much just a message broker; you might use something like sente (websockets) to get you easy push to clients

15:22 justin_smith: dweave: the major division in the clojure world is between the servers that give each request a thread from a pool (ie. jetty) vs. those that use a thread pool plus async so that the request doesn't own its own thread (ie. aleph, httpkit)

15:22 triss: arghhhhh. I keep being told: Uncaught SyntaxError: Unexpected token .

15:22 amalloy: (decrement redibly interesting)

15:22 fixed it

15:22 triss: by my browser.

15:23 dweave: i see justin_smith

15:23 triss: but when I navigate to the source my browser sees... or the copy of it in my project there's not a . to be found

15:23 any one experienced this?

15:24 TimMc: Uh... should I assume this is a CLJS project?

15:24 triss: oh yes... sorry TimMc

15:24 dweave: is httpkit similar to like netty?

15:25 amalloy: dweave: lamina is built on top of netty. dunno about httpkit

15:25 dweave: ah ok cool thanks

15:25 llasram: OMG -- I just figured this out: clojure.lang.Namespace isn't final, which lets you implement namespaces which do dynamic code generation on Var lookup

15:25 * llasram laughs maniacally

15:25 dweave: these questions probably sound stupid but the answers help

15:26 amalloy: triss: http://stackoverflow.com/a/24164554/625403 is an interesting-looking possibility

15:26 noonian: dweave: http-kit is all implemented in clojure instead of using netty

15:27 dweave: gotcha

15:27 amalloy: that's...interesting, llasram

15:27 * TimMc backs slowly away from llasram

15:27 triss: thanks amalloy... I'll take a look

15:28 amalloy: noonian: that's kinda an absurd claim. it has to be based on something in java. and if you read the project.clj, it depends on netty

15:28 dweave: so one more: in node you would use something like redis for shared memory between processes. Is this a problem that doesn’t exist in clojure world? Couldn’t you just use STM

15:28 Raynes: llasram: whoa r u srs

15:28 noonian: amalloy: my bad then, that was my understanding based on their docs

15:29 llasram: amalloy: This actually came up at the atl-clj meetup, and there was some confusion. I actually believe http-kit only has it in the *dev* profile

15:29 Probably for benchmarking comparison or such

15:29 amalloy: oh, you're right

15:29 it has to be based on java still. nio sockets, i guess?

15:30 llasram: Raynes: the constructor is package-private, so you need to put something in the `clojure.lang.` package to get access, but a narrow path remains open

15:30 Raynes: llasram: You should make a branch of conch that uses this to do something fantastic.

15:31 amalloy: yeah. nio socket channels. so of course it's not "all clojure", but it's implemented on top of a low-level-enough primitive that it's reasonable to call it all clojure. sorry for claiming it was absurd

15:31 noonian: it looks like http-kit has a decent amount of java code in its implementation also, it just doesn

15:31 llasram: Raynes: Oh, like the Python sh package? That could be fun

15:31 noonian: doesn't wrap netty is what i meant

15:32 Raynes: llasram: The saddest thing I had to give up with conch was the Python version's lovely import magic that allows you to just magically pull import shell programs

15:32 I'd be very grateful to gaze upon a crazy hack that allows something similaer

15:32 amalloy: lol. opened up the first interesting-looking source file in http-kit, and here is the first line of code i see: https://github.com/http-kit/http-kit/blob/master/src/java/org/httpkit/server/AsyncChannel.java#L25

15:32 Raynes: similar*

15:37 justin_smith: dweave: in one clojure process you can use STM between threads, yeah. Eventually you may want multiple machines (there is little point to having multiple jvms running a clojure server on one box since it will likely be using pthreads), then you would look for some shared state solution, either Redis, or Kafka, or ZeroMQ or RabbitMQ or whatever...

15:37 and it would have to be a networked sharing of state, of course

15:37 sometimes even a db suffices, depending on what you are trying to do

15:39 dweave: usually you don't even need STM, and an atom coordinating values between threads suffices

15:40 ~refs

15:40 clojurebot: Excuse me?

15:40 justin_smith: ~stm

15:40 clojurebot: Huh?

15:40 justin_smith: I keep forgetting where the factoids are at

15:42 llasram: Not a "good" use, but: https://github.com/llasram/method-fn/blob/master/src/clojure/method/fn.clj#L99-L107

15:43 * llasram chortles maniacally a bit more

15:50 llasram: The obvious thing to do now is factor that out into a tiny little library, allowing the meme to more easily infect new victims

15:52 amalloy: llasram: what happens if you :refer :all?

15:53 llasram: amalloy: If humor: ha! If actual question: I believe it'll pull in everything which has already been dynamically created, in this case under un`read`able names

15:54 It's probably be pretty easy to further refine so that the mechanism used to discover the namespace contents turns up empty

15:55 Oh, interesting -- actually the NS was never `require`d so it errors on failing to find matching source

15:55 Also would be easy to fix for e.g. Raynes proposed use

15:58 There we go -- yep, works like hypothesized

15:59 reborgclj: Hello, quick sanity check:

15:59 ,(unchecked-subtract Integer/MIN_VALUE 1)

15:59 clojurebot: -2147483649

16:00 reborgclj: shouldn't that be 2147483647?

16:01 amalloy: reborgclj: 1 is a long

16:01 reborgclj: ,(unchecked-subtract Integer/MIN_VALUE (int 1))

16:01 clojurebot: -2147483649

16:01 godd2: https://clojuredocs.org/clojure.core/unchecked-subtract

16:01 in the docs, the example shows it should be 2147483647

16:02 amalloy: godd2: clojuredocs isn't "the docs", it's a community-maintained (and mostly unmaintained) collection of examples

16:02 it probably was 2147483647 back in 1.2

16:02 reborgclj: @amalloy so possibly clojuredocs not correct? Ah.

16:03 godd2: reborgclj any doc is possibly incorrect ;)

16:04 amalloy: reborgclj: oh, right. clojure only does primitive math on longs and doubles

16:05 mikerod: What would be a good reason why leiningen can always download dependencies from "https://clojars.org/repo/&quot;, but always fails to from "https://repo1.maven.org/maven2/&quot; ?

16:05 I am fairly sure this has something to do with a proxy

16:05 reborgclj: So no way I can reproduce in clj what I can do in Java with (-2147483648 - 1)?

16:06 mikerod: I get "If you are behind a proxy, try setting the 'http_proxy' environment variable." as my message, but I'm not sure how accurately that describes what could be going on.

16:06 puredanger: reborgclj: what result are you looking for?

16:06 mikerod: If there is something to do with a proxy though, why is clojars ok, but not the maven repo?

16:06 amalloy: reborgclj: probably not without modding the result

16:06 reborgclj: @puredanger 2147483647

16:07 puredanger: so underflow

16:07 amalloy: oh, of course. you can use unchecked-int

16:08 ,(unchecked-int (- Integer/MIN_VALUE 1))

16:08 clojurebot: 2147483647

16:08 puredanger: reborgclj: yeah, the -int functions give you integer over/underflow characteristics

16:08 reborgclj: @amalloy that's it! :)

16:08 amalloy: oh, there's unchecked-subtract-int, too

16:08 puredanger: useful for hash calculation sometimes

16:08 amalloy: that's much more sensible, puredanger

16:09 noonian: is anyone using the chestnut template with prismatic's schema? i'm not sure where the conflict is but schema.macros won't compile because it cant find potemkin

16:10 reborgclj: amalloy: puredanger thx

16:10 mikerod: never mind, I just realized why I have problems.

16:11 amalloy: i just realized clojure.lang.RT.intCast(int) : int exists. that's a funny little method

16:11 sure hope it gets inlined by the jit

16:12 hiredman: or has a compiler intrinsic

16:12 amalloy: hiredman: it doesn't

16:12 hiredman: oh, just the unchecked-int cast does

16:13 amalloy: i noticed it because it was showing up in the disassembly; checked, and there's no intrinsic (of course, otherwise it wouldn't have been in the disassembly)

16:14 hiredman: I guess the checked cast actually does something

16:14 the unchecked cast has an intrinsic as a nop

16:14 https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Intrinsics.java#L103

16:15 amalloy: hiredman: the checked cast doesn't actually do anything; the intrinsic was just omitted

16:15 and the intrinsic for unchecked-subtract-int is broken

16:16 hiredman: :/

16:16 Bronsa: amalloy: how so?

16:16 amalloy: i'm not sure how it's broken, since it seems fine to me. but when i disassemble (unchecked-subtract-int (unchecked-int Integer/MIN_VALUE) (unchecked-int 1)), it emits a call to clojure.lang.Numbers.unchecked_int_subtract(int, int)

16:16 rather than just an isub

16:19 hmmmm, interesting. maybe the intrinsic isn't broken, but gets bypassed somehow if it's the final return value?

16:20 if i change it to like (unchecked-inc-int (unchecked-add-int 1 (unchecked-subtract-int (unchecked-int Integer/MIN_VALUE) (unchecked-int 1)))), then all the operations get intrinsified except the outermost one, which uses a static method

16:21 ticking: hey I was wondering, is it expected behaviour that :or default values in map destructuring get evaluated eagerly wether they are used or not?

16:21 Bronsa: amalloy: ah I think I see why it's so. probably the intrinsic ops are emitted only when the value can be a primitive, since an IFn invoke can't return an int, that never gets through

16:21 just a guess though

16:21 amalloy: Bronsa: well the value *can* be a primitive here. the function looks like https://www.refheap.com/aa32fa60ce419f4f599b11491 - ends with a static method returning an int, and then an Integer/valueOf

16:22 that static method call could be intrinsified at no cost

16:22 Bronsa: amalloy: not saying it can't be done, just that because of how it's implemented the optimization is probably skipped

16:23 amalloy: agreed

16:24 nicferrier: this is frustatring. I've got a go-loop with a bunch of channels that I'm mapping from a map along with a timeout channel and I'm alt!-ing them and I seem to be getting the timeout only once.

16:24 it's frustrating as well as frustatring

16:25 noonian: are you making the timeout channel anew each loop?

16:25 pandeiro: nicferrier: are you let binding the timeout ?

16:25 nicferrier: yes

16:25 (let [[[message id arguments] ch] (alts! (conj channels (timeout 100)))]

16:26 Bronsa: amalloy: yeah looking at the source, intrinsics for static methods are used only on emitUnboxed

16:27 amalloy: nicferrier: what message does a timeout channel produce? if you try to destructure that into [message id arguments], does that break?

16:28 nicferrier: amalloy: good question, but I seem to get nil

16:28 I want proper matching.

16:30 really the problem is my messaging is broken. it was working. and then I changed stuff around. and now it's not! hurrah!

16:31 noonian: ,(let [[a b c] nil] [a b c])

16:31 clojurebot: [nil nil nil]

16:32 nicferrier: :-)

16:37 why would the channel I'm trying to use be different in the function I made it from the function I'm trying to read off it from?

16:37 the jvm object is different.

16:40 hmmm. no I can probably explain that.

16:40 noonian: nicferrier: could you post the code? you said you are doing it in a loop, somehow you must be getting your references mixed up

16:43 tuft: colleague just came up with a great class name: AbstractUntestableStateMachineMixin

16:45 nicferrier: recommended pastebin?

16:45 turns out my personal one is broken for clojure

16:45 noonian: nicferrier: refheap

16:45 nicferrier: requires login

16:46 technomancy: I don't think it does?

16:46 noonian: not for public pastes at least

16:46 nicferrier: aha. if you go to the right url it's ok

16:47 https://www.refheap.com/94954

16:49 amalloy: Raynes: feature request: make refheap work even if you go to the wrong url

16:49 nicferrier: amalloy: the top urls on p1 of google all imply login.

16:49 noonian: nicferrier: style nitpick: (map #(% :from) @started) can just be (map :from @started)

16:49 nicferrier: probably because no one needs to link to the paste post page

16:49 noonian: cool.

16:50 amalloy: nicferrier: what? you searched for "refheap" and got links that suggest you log in? i can't find a single link that does that

16:50 nicferrier: amalloy: no I searched for clojure pastebin and didn't get the front page of refheap

16:51 noonian: nicferrier: i think your go-loop is throwing an error because you have no default case in the 'case' (since the timeout will return nil on close) and go blocks at least used to swallow errors and fail silently

16:51 amalloy: iiinteresting. refheap's about page does look a little unfriendly

16:52 Raynes: feature request: make a google search for "clojure pastebin" take you to the right place

16:52 nicferrier: noonian: I've tried filtering that out

16:52 noonian: putting a (when message ...) around it for example. makes no difference.

16:53 dbasch: $google clojure pastebin

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

16:53 nicferrier: the about page just needs a link to the front page.

16:53 titled something like "paste something now"

16:53 amalloy: nicferrier: well, of course it does have a link to the front page, the Refheap logo. but it does need a more obvious "paste" link

16:55 nicferrier: noonian: the process actually starts in startProcess, but I never get the messages either.

16:55 pretty sure the alts! is hanging.

16:55 printlns show the loop going rounf again

16:56 noonian: and you get more than one println?

16:57 nicferrier: yes. but I did something different now. adding the when and the printlns I got 2 sets of output.

16:57 Raynes: amalloy: You can be my SEO go. Have at it.

16:57 noonian: because the second go-loop will definitely throw an exception as soon as you get a message that isnt :line or :exit

16:57 nicferrier: yeah, I put a when around it.

16:57 but it's still not working in some scenario.

16:58 amalloy: Raynes: seriously though i do like nicferrier's suggestion: the About page could use a link labeled "Paste now" or somethign

16:58 as it is, the About page looks like all you can do is sign in

16:58 Raynes: You can click on the header image

16:58 'image'

16:58 nicferrier: https://www.refheap.com/94956

16:58 amalloy: Raynes: i know you can, and i said the same

16:59 it just *looks* like there's nothing you can do but sign in

16:59 noonian: afk a min

16:59 mikerod: is https://github.com/thickey/lein-nevam abandoned ?

17:02 nicferrier: do refs and go blocks work ok together?

17:07 oh well. I'm sure I can make it work in the morning. it's holding up pretty well against the scala version right now. which is good.

17:07 chouser: nicferrier: excellent question! If I had to bet, I would say reading and writing on channels is a side effect, and thus not safe in a dosync.

17:08 nicferrier: chouser: my code isn't reading or writing channels in a dosync.

17:08 so that should be ok.

17:08 chouser: oh. Just reading from refs in a go block?

17:09 nicferrier: it's alt!ing on a bunch of channels derived from an @ref

17:09 alts!ing rather

17:13 noonian: chouser: here is the code in question: https://www.refheap.com/94956

17:13 nicferrier: ok. I think it's falling over on channels being nil.

17:14 so what gets passed to alts! is [(timeout 100) nil]

17:14 which it barfs on

17:14 I think.

17:15 the empty vector is true. :-(

17:16 noonian: yup, everything except nil and false

17:16 nicferrier: right.

17:17 justin_smith: &(map not-empty ["" "hi" [] [1]])

17:17 lazybot: ⇒ (nil "hi" nil [1])

17:18 justin_smith: for when you want empty to be falsey, but also to preserve the type

17:19 nicferrier: is really odd. it never times out when the channels are more than just the timeout channel.

17:19 puredanger: are you ever closing the timeout channel?

17:19 if so, don't do that

17:20 nicferrier: puredanger: no. I'm making a new one in the loop.

17:21 grrr. still have an nil channel. raarr.

17:22 ok. that's got it.

17:22 now I'm not alts!ing from nil it's working.

17:22 it's not working. but it's working. if you see what I mean. :-)

17:23 puredanger: I haven't thought about it much, but if that's always a bug, we could presumably throw an error in that case.

17:23 nicferrier: so my problem is... apparently I never get the actual channels from the ref.

17:31 working now! https://www.refheap.com/94961 - thanks everyone

17:33 this makes quite a good exercise I think.

17:33 I might take it to the clojure dojo and see what people think.

17:38 less than 70 lines of code is pretty good.

17:49 ikitommi_: yogsototh: not very simple to add a new custom serialization format for compojure-api. Should be fixed, wrote an issue of it (https://github.com/metosin/compojure-api/issues/61).

17:50 would love to push the needed changed to ring-middleware-format but it doesn't seem to be taking PRs in.

18:15 triss: hey all. I'm rather pleased to be finding myself saying stuff like (partial apply blah blah blah)

18:15 i do it rather a lot... i wonder if there's a short hand?

18:16 justin_smith: do you ever provide more than one arg?

18:17 if not, #(apply blah blah blah %)

18:17 triss: i have done.

18:17 justin_smith: OK

18:17 triss: of yeah!

18:17 thanks man.

18:20 amalloy: you can also (def ap (partial partial apply)), and then (ap blah blah blah)

18:21 that's in useful somewhere

18:21 triss: hah splendid.

18:21 what's useful?

18:21 amalloy: http://flatland.org/useful/

18:22 mostly i use useful.utils, useful.seq, useful.fn, and useful.map

18:23 triss: some of this looks really useful...

18:23 amalloy: that's the idea

18:27 triss: hmmm. applied! if I was clever that's what Id have called this function too..

18:28 makes the ap abbreviation a little clearer I think.

18:41 keeds: quit

18:44 TimMc: keeds: No, I refuse!

18:50 keeds: TimMc: Sorry, please don't!

18:56 TimMc: :-)

19:17 turbofail: we'll beat #haskell's offer by 10%

19:34 triss: hey all. if I've got a function name as a symbol how do i apply it

19:34 ?

19:34 ticking: triss: you mean you want to get the function associated with a symbol?

19:35 triss: yep and feed it some values....

19:35 amalloy: triss: usually the answer is to hop in a time machine and get the function as something better than a symbol

19:35 triss: i was just thinking that.

19:35 noonian: thats the correct answer

19:35 the one you shouldn't do in actual code is use eval

19:35 justin_smith: there is resolve though, usually useful for ugly hacks

19:35 (doc resolve)

19:35 clojurebot: "([sym] [env sym]); same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)"

19:36 noonian: ah thats better too

19:36 justin_smith: ,((resolve 'clojure.core/+) 1 1)

19:36 clojurebot: 2

19:36 justin_smith: better than eval at least

19:36 ticking: also find-var

19:37 ,((find-var 'clojure.core/+) 1 1)

19:37 clojurebot: 2

20:49 akkad: your Uber door is a jar

21:42 seangrove: The flexibility of the ns form seems to cause endless debate/trouble

21:48 andyf: what kind of trouble?

21:50 In particular, if you?ve ever been bitten by a problem that Clojure itself didn?t tell you about, I?m interested to add a warning to it for Eastwood, if I can figure out how. I think I?ve got most of the common problems covered in the next version.

21:51 seangrove: andyf: I think they're probably all covered by eastwood at this point

21:52 andyf: Just saw some comment about it on an internal GH project

21:53 andyf: about Eastwood, or about trouble debugging something with an ns form?

21:53 seangrove: Debugging ns form style

22:02 yguan: ,(take-while even? [-2 -1 0 -1 -2 3])

22:02 clojurebot: (-2)

22:02 yguan: why only -2 is returned?

22:03 seangrove: ,(filter even? [-2 -1 0 -1 -2 3])

22:03 clojurebot: (-2 0 -2)

22:03 eyelidlessness1: is there a particular approach to printing clojure values that will show a visual distinction between `false` and `(Boolean. false)`?

22:04 yguan: seangrove: :), right so take-while stops when it hit something?

22:04 seangrove: Yup, it takes until the predicate is false

22:05 yguan: seangrove: my bad... need some tea...

22:05 seangrove: yguan: No worries!

22:08 andyf: eyelidlessness1: I hope you are not using (Boolean. false) in your own code on purpose? Read this if so: http://clojuredocs.org/clojure.core/if

22:08 If you are trying to debug occurrences of (Boolean. false) that may be injected by other code you didn't write, then I'm not sure if there is an easy way to display it differently.

22:09 eyelidlessness1: andyf: nope, not using it directly. got bitten in a return value from… something

22:09 TEttinger: ,(= (Boolean. false) false)

22:09 clojurebot: true

22:10 eyelidlessness1: ,(when (Boolean. false) true)

22:10 clojurebot: true

22:10 TEttinger: ,(= (Boolean/false) false)

22:10 clojurebot: #<CompilerException java.lang.NoSuchFieldException: false, compiling:(NO_SOURCE_PATH:0:0)>

22:10 andyf: (if (Boolean. false) "logical true" "logical false")

22:10 ,(if (Boolean. false) "logical true" "logical false")

22:10 clojurebot: "logical true"

22:10 TEttinger: ,(= Boolean/FALSE false)

22:10 clojurebot: true

22:10 TEttinger: ah, that is confusing

22:10 andyf: Java docs warn about this, and recommend against ever using it.

22:11 That's why I wrote that page in ClojureDocs, so I could link to it when it comes up :)

22:11 TEttinger: ah, that is confusing

22:11 eyelidlessness1: had to special case a particular (when) form into (= false), but without better visibility into where that value became (Boolean. false), no confidence in my fix

22:12 andyf: eyelidlessness1: Is it reasonable to walk traverse whatever data structure you have that might contain those, and conver all (Boolean. false) values to false? That might not be easy, I realize.

22:13 Could it be coming from one of several different libraries?

22:13 TEttinger: ,(defn bad-boolean? [huh] (and (= huh false) (when huh)))

22:13 clojurebot: #'sandbox/bad-boolean?

22:13 eyelidlessness1: it is tough to automatically sanitize, i have several uses of defrecord which does not support (empty)

22:13 TEttinger: ,(bad-boolean? (Boolean. false))

22:13 clojurebot: nil

22:14 eyelidlessness1: and yes, there are several libraries that may have interfered

22:14 the data source was JSON, so it certainly wasn't in the original data

22:14 TEttinger: ,(when (Boolean. false))

22:14 clojurebot: nil

22:14 TEttinger: ,(when (Boolean. false) true)

22:14 clojurebot: true

22:14 TEttinger: ,(defn bad-boolean? [huh] (and (= huh false) (when huh true)))

22:14 clojurebot: #'sandbox/bad-boolean?

22:14 TEttinger: ,(bad-boolean? (Boolean. false))

22:14 clojurebot: true

22:15 TEttinger: ,(bad-boolean? (Boolean/FALSE))

22:15 clojurebot: nil

22:15 andyf: eyelidlessness1: You know that your JSON reader lib doesn't produce (Boolean. false) values?

22:15 TEttinger: ,(bad-boolean? Boolean/FALSE)

22:15 clojurebot: nil

22:15 eyelidlessness1: andyf: it never had before.

22:15 TEttinger: will that check fail for anything big?

22:16 ,(bad-boolean? false)

22:16 clojurebot: nil

22:16 andyf: I suppose there are conditions all over your code that might be affected, not just a handful?

22:16 eyelidlessness1: andyf: using clojure/data.json

22:16 yes, potentially

22:16 it would take a while of close analysis to have any confidence

22:17 TEttinger: andyf, eyelidlessness1: would (defn bad-boolean? [huh] (and (= huh false) (when huh true))) be suitable for checking?

22:18 eyelidlessness1: the function seems suitable enough, but it doesn't solve the immediate issue, that i now cannot be sure whether any (if) form in my codebase(s) does what i expect (nor any macros around it, like when-*)

22:20 perhaps a lesson not to trust "truthyness" at all

22:20 and to be more specific in expected values

22:20 that tends to be harder in lower-level code though

22:22 andyf: eyelidlessness1: This (Boolean. false) thing does affect your code at a fairly low and pervasive leve, which is very annoying.

22:22 I spot-checked data.json, and don't see any obvious way it could be producing these bad falses.

22:22 eyelidlessness1: so.

22:22 andyf: Are you getting booleans from a database?

22:22 eyelidlessness1: no

22:23 my strong suspicion

22:24 we are also using storm. my strong suspicion is that it is an artifact of deserialization of custom types by storm

22:24 but i have not proven that yet

22:24 andyf: In a situation like this, it would be nice if you could set a flag before starting Clojure that would cause it to throw an exception if it ever did a condition test on (Boolean. false).

22:24 eyelidlessness1: YES.

22:24 andyf: But I'm not aware of anyone who has implemented something like that.

22:25 eyelidlessness1: it would require forking clojure, as far as i can tell.

22:25 andyf: It might be not very difficult to do by creating a modified version of Clojure.

22:25 eyelidlessness1: (if) is in Compiler.java

22:25 TEttinger: can you do a multimethod on Boolean?

22:25 eyelidlessness1: it may well be worth it

22:25 andyf: Yeah, if making a locally modified version like that doesn't scare you, I'd say go for it.

22:26 eyelidlessness1: the relevant compiler code is pretty clear

22:26 andyf: I'm not saying you should be scared -- just some might avoid it.

22:26 eyelidlessness1: i'm mostly concerned about selling that to my team :)

22:27 TEttinger: maybe just use a fork for testing, not in production?

22:27 eyelidlessness1: but… we are using storm. thus stuck on clj 1.5.1. so not a huge maintenance risk.

22:27 andyf: Have you built and installed modified versions of Clojure before? git clone on the source code, git checkout to get to the version you want to modify (after 'git tag -l' to list the tags available), edit source code, then 'mvn install' to install it in your local mvn repo after compile and test.

22:27 eyelidlessness1: haven't before but the process seems straightforward enough.

22:28 andyf: If you can localize your testing to a single machine, that would be easiest.

22:28 TEttinger: might want to change the pom to be a snapshot if it isn't

22:28 puredanger: andyf: also, don't forget running antsetup.sh

22:28 andyf: Yeah, if you can easily change "1.5.1" to "1.5.2-SNAPSHOT", that would help keep it isolated to your local version.

22:28 puredanger: Even if you do 'mvn install'?

22:29 puredanger: I think so

22:29 been a while

22:29 eyelidlessness1: one way you can get new Booleans is via deserialization

22:29 andyf: I'll check, but I thought that was only if you ran 'ant', and I don't know how to use 'ant' to install in the local maven repo

22:31 eyelidlessness1: puredanger: interesting. that does seem like the likely culprit.

22:31 andyf: Out of curiosity, that would be deserialization performed from what source, for what reason?

22:32 eyelidlessness1: storm spout or bolt to bolt

22:33 Bruce_Wayne: Does anyone know how to produce a calendar

22:33 andyf: eyelidlessness1: If you do track down where these values are coming from, I hope you file reports about the issues, in hopes of eliminating them.

22:33 eyelidlessness1: absolutely

22:33 Bruce_Wayne: I want to make a clickable html calendar with data structures behind each day that lead to a display of that data structure

22:34 puredanger: eyelidlessness1: this might be too crazy for you, but you might consider hacking the jdk to debug this

22:34 Bruce_Wayne: I already have code to display the data structure, just need to know a quick way to produce an html calendar with linkgs

22:34 links

22:35 puredanger: eyelidlessness1: grab the source for Boolean, modify it to dump stack when a new instance is created, compile, prepend to your bootclasspath

22:36 eyelidlessness1: puredanger: i feel far more comfortable modifying clojure, and at a glance it seems like a straightforward change.

22:36 puredanger: andyf: you're right btw, mvn works w/o antsetup

22:36 eyelidlessness1: fair enough - maybe it's a next step to find the source of the bad values

22:37 eyelidlessness1: is it crazy to suggest that clojure ought to just treat (Boolean. false) as (Boolean/False)?

22:38 it could be a surprise for java interop

22:39 andyf: eyelidlessness1: It may be a performance degrader, since conditional tests are so pervasive.

22:39 And Java itself has the same issues, hence the documentation against using these Booleans.

22:39 puredanger: eyelidlessness1: that stuff pre-dates my deep involvement but I know it's just a huge pain in the ass

22:41 eyelidlessness1: andyf, puredanger: this has been really helpful. thanks for taking the time to point me in a good direction (and understanding my frustration!)

22:42 puredanger: sure, ping me at alex.miller@cognitect.com if you run into anything in clojure itself

22:42 eyelidlessness1: cheers!

22:49 munderwo: Hi all. Is there anyway to have a look at the contents of a core.async channel in a javscript debugger?

22:54 steve: anyone have any good tips on web validation

23:00 kenrestivo: i find that most of the web is invalid. c.f. http://research.microsoft.com/en-us/people/mickens/ToWashItAllAway.pdf

23:02 joking aside, there's https://github.com/weavejester/valip, https://github.com/joodie/pretzel , http://github.com/leonardoborges/bouncer, https://github.com/michaelklishin/validateur

23:02 probably lots others, but that's what i have in my notes

23:10 steve: thanks ken. yeah, so many choices makes it hard on the new guy :)

23:13 seems people were using Schema for it, but I guess I'll stick with noir since I at least have a pretty good example

23:14 kenrestivo: schema has a lot of other advantages too.

23:15 i'm using it for validating a conf file. haven't used it for form validation, but it seems like it'd do that well, also api input, lots of things.

23:19 steve: yeah, i guess i didn't get how to make the connection between the error map it throws and an actual error message i'd want to show the user.

23:20 also so new, not ever sure how error handling in clojure really works yet. Thanks for the thoughts, i'm sure it'll start to click as i go

23:57 gfredericks: is #"((x)|(y))\2\3" unmatchable? it seems to be

Logging service provided by n01se.net