#clojure log - Jan 27 2015

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

0:23 elarson: looking at java.io.Reader.read and the args in the java doc suggest that you pass in the char buf you want to to read the chunk into. how would that work in clojure?

0:26 for example, something like (let [chunk (.read fh 1024)]) makes more sense to me

0:27 justin_smith: elarson: I think the straightforward way is to create a buffer to read into, and then create a string from the relevent subsequence after reading

0:27 elarson: ah ok, so I would go ahead and create a buffer

0:27 justin_smith: like, there isn't a method with the signiture you suggest here

0:29 yeah, and the mutability isn't a huge issue, because the buffer should be local in scope and all you do is read into it and immediately create an immutable string from that

0:29 though of course accidentally sharing a buffer would be a nono

0:31 elarson: justin_smith: that makes sense. is this idiom relatively common b/c of clojure's java/jvm roots?

0:32 justin_smith: yeah, in my experience at least

0:32 you could make a wrapper, but it's only a small amount of interop, and there would be many ways for the wrapper to go wrong

0:32 * elarson might try to write one anyway for practice :)

0:50 audiodude: hello, I’m learning Clojure with the Pragmatic book "Programming Clojure"

0:51 any recommendations for a starter project?

0:56 scottj: audiodude: everytime you wish there were a program that doesn't exist add it to a list and you'll never have to ask that question again :)

0:58 sujeet: audiodude, or clone simple programs that already exist

0:59 audiodude: scottj: I feel like I am very complacent because I’m largely satisfied with the character and quality of existing programs

0:59 sujeet: that seems like not a bad idea

1:21 jinagarano: i'm having trouble setting up korma, when i try to insert it says "table not found." where can i find a solution?

1:35 fairuz: Hi guys. Is there any simpler than this -> (cons A (if (vector? B) B [B]))

1:35 It should produce (A B) at the end

2:20 tomjack: I'm guessing there is something in core.logic.nominal which has performs badly in the number of noms involved?

2:22 https://www.refheap.com/d77cdbc9bea84a3e02c122ce8

2:23 it's strange to me, because I'm unifying with an lvar

2:23 the term is already there, I just want to convert noms to a_i so it prints a bit prettier

2:26 also, it's a rather simple term :)

2:33 I feel like I'd better start playing with debruijn indices...

3:40 hmm, that happens even without noms

3:40 and without ties

3:41 esets maybe..?

3:49 hellofunk: i'm looking at this: http://dev.clojure.org/display/community/Library+Coding+Standards odd i had not seen it before. this suggestion is confusing to me: "Don't unroll optional named arguments. While it's nice for callers to not have to wrap optional named arguments in a map, clearly specified configuration maps are laudable."

3:51 Glenjamin: hellofunk: it's annoying to build unrolled kwargs manually

3:52 it refers to (func :a 1 :b 2) vs (func {:a 1 :b 2})

3:54 oh, i se - there's already an example

3:54 oh, weird

3:54 the prose doesn't seem to match the code sample in the doc

4:01 tomjack: I think the sample just makes a second point that is not in the prose?

4:02 Glenjamin: the prose indicates the second and third are preferrable

4:03 but the comments say to use 1st and second

4:04 tomjack: s/Don't unroll/Consider not unrolling/ ?

4:04 hellofunk: exactly, it's a confusing point being made there

4:05 Glenjamin: the general advice i've seen lately is that (release-sharks 2 {:verbose true}) is sensible for optional options

4:08 zacts: hi

4:11 hum.. I need more experience with designing functional programs. I don't know what to represent with functions, and what to represent with data.

4:14 Glenjamin: zacts: this talk might help https://www.youtube.com/watch?v=3oQTSP4FngY

4:15 "Decompose the pieces. If your name isn't Rich, don't write a form as long as, say, the definition of doseq."

4:16 clgv: Glenjamin: how about `for`? :P

4:16 Glenjamin: i type the following with trepidation:

4:16 $source for

4:16 lazybot: for is http://is.gd/x33p56

4:16 Glenjamin: also, robots are great.

4:17 clgv: `doseq` almost fits on the 24" screen here ;)

4:17 Glenjamin: i'd always sort-of assumed doseq was (comp doall for)

4:18 #_"not the inner-most loop" ; <- amazing comment

4:18 clgv: Glenjamin: the `for` implementation is the best example how you do not need comments in Clojure since it's implementation is so clear when reading through it quickly

4:19 hyPiRion: not sure if srs

4:19 clgv: hyPiRion: pssshhht!

4:19 Glenjamin: a large part of the length seems to be functions-in-let

4:20 i wonder why they're not just defn-

4:20 ah, there's quite a bit of closing over stuff

4:20 clgv: Glenjamin: strange idea of hiding them since the implementer thinks they are not useful in any other context

4:21 Glenjamin: *implementor doesn't want to have to support using in other context?

4:21 clgv: yeah maybe the closures make it less complicated ;)

4:21 Glenjamin: i guess you can rely on the fact that changing them will only affect the definition of for

4:23 slipset: I seem to remember from http://vimeo.com/100518965 that Rich doesn't always write code with readability in mind...

4:23 he seems to be optimizing for something else.

4:23 zacts: cool, thanks /me watches

4:23 Glenjamin: hah, i recall rich briefly refuting the large java files being a problem directly after that talk

4:24 i dunno if that's on video

4:24 slipset: Glenjamin: one thing is the 10k loc, but another thing is that one may argue that the code is not strictly idiomatic java

4:24 Glenjamin: well, rich pointed out that although it's 10k lines, it's really flat and the IDE lets you jump around functions easily

4:25 hyPiRion: it's idiomatic hickey-styled java

4:25 Glenjamin: and then wiggled his mouse at the symbol list in intelliJ

4:25 slipset: but IIRC, the first clojure compiler generated java-code, not java byte code, right?

4:25 clgv: Glenjamin: that's true the IDE helps a lot there

4:25 slipset: and I was thinking when I saw this code, that it looked as if it would make sense if it was generated.

4:26 clgv: slipset: are you sure?

4:26 slipset: clgv: nope

4:26 clgv: slipset: I somehow doubt that statement

4:26 Glenjamin: the indentation is a bit unusual, but i've never had a real problem reading clojure's java code

4:26 clgv: Glenjamin: could have more comments and method descriptions ;)

4:26 Glenjamin: it's just a bit different. I saw a suggestion once that writing code differently forces the reader to slow down and actually read it

4:27 that's true, i've mostly only looked at the collection implementations, which are tidy to a point, then arcane

4:27 clgv: you have to rely on debugging step by step a lot of times to find out what is actually happening

4:27 Glenjamin: I hacked the compiler a bit ;)

4:27 hyPiRion: The collection implementations are okay. They are just hard to grasp when you don't know *why* they're doing that one weird thing

4:28 Glenjamin: luckily someone wrote a bunch of blog posts about that :)

4:28 hyPiRion: hehe :p

4:29 slipset: and is preparing talks about it, as one can read on twitter

4:31 hyPiRion: slipset: That was just a suggestion from someone – I'm not sure if a talk will be that valuable, but we'll see

4:31 slipset: I know it was a suggestion from someone, since I know the guy quite well.

4:31 hyPiRion: ah

4:31 slipset: If you know what I mean :)

4:31 * hyPiRion looks at the username and walks away

4:33 hyPiRion: slipset: well, I'm considering it at least :)

4:33 slipset: :)

4:34 I don't know if flatmap(oslo) is happening this year, but even though it's a (mostly) scala conf,

4:34 I think the subject should fit right in.

4:35 There's been clojure workshops and om and datomic talks

4:35 (or was it quiescent)

4:35 hyPiRion: yeah, and the ImmutableVector in Scala is basically the same thing

4:44 cfleming: Is there an easy way to check if two objects are equal, but also take into account if their metadata is equal?

4:44 whodidthis: how do i (defmacro [& thingies] `~thingies)

4:45 Empperi: whodidthis: please elaborate

4:45 tomjack: cfleming: (and (= x y) (= (meta x) (meta y)))

4:45 hyPiRion: cfleming: not afaik. You also have to be a bit careful with objects that can't contain metadata

4:46 ,(meta 1)

4:46 tomjack: ah, I see

4:46 clojurebot: nil

4:46 cfleming: tomjack: That won't take into account if their sub-objects' meta is equal

4:46 hyPiRion: huh, that used to fail

4:46 whodidthis: sorry, (defmacro a [& b] `~b) so i get all them thingies in (a 1 2 3) in a list or something

4:46 Empperi: hyPiRion: (meta 1) gives nil

4:46 tomjack: cfleming: ah

4:46 s/objects/clojure collections/ ?

4:46 hyPiRion: Empperi: yeah, I just tried :p

4:47 Empperi: whodidthis: (defmacro a [& body] (list ~@body))

4:47 cfleming: tomjack: Well, collections are objects, but right, I should have been more precise, sorry

4:48 zacts: huh cool

4:50 james234: hi

4:50 I'm having trouble getting my clojure app to accept a POST request

4:50 is this the right place to ask?

4:50 slipset: could be,

4:50 hyPiRion: huh, that is weird. I thought meta would throw an error if given a non-IMeta object.

4:50 tomjack: cfleming: good question

4:50 hyPiRion: But it appears it never has.

4:50 Glenjamin: $source meta

4:50 slipset: james234: do you have a link to your code?

4:50 lazybot: meta is http://is.gd/bgjvT6

4:50 cfleming: hyPiRion: I believe it checks (instance? IMeta)

4:51 Glenjamin: maybe that's with-meta?

4:51 james234: slipset: let me get one

4:51 Glenjamin: ,(with-meta {} 1)

4:51 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IPersistentMap>

4:51 Glenjamin: i think i did that wrong...

4:51 tomjack: I mean, really all you need is map, for whatever functor you pick (like "lists of lists of lists of ..." or what you like)? then you can (map (juxt identity meta)) and compare?

4:52 zacts: I guess I have the problem that with some of my projects the functions/procedures rely too heavily on the data having a specific form. What are ways people have had to deal with this problem? So that one can extend or modify the data later on? Would I need to use Data Abstraction?

4:52 james234: slipset: here is a link to the relevant code:

4:52 cfleming: tomjack: But that's still not recursive, right? I'd need something like tree-seq

4:52 james234: slipset: http://pastebin.com/FJwV0N04

4:52 zacts: and how does data abstraction, in the SICP sense, work with Clojure with all of it's already presented data types?

4:53 Glenjamin: zacts: try and separate the "doing work" functions from the "extracting data from the structure" functions

4:53 zacts: it seems clojurists want to keep their data structures naked, rather than abstracting data in the SICP sense?

4:53 clgv: james234: the nested defroutes is certainly weird

4:53 tomjack: cfleming: right, I just mean you need the "map" operation for some type which is not lazy seqs

4:53 clgv: james234: you know that there is just `routes`

4:53 tomjack: say, trees, if that's what you've got

4:54 james234: clgv: yeah I tried that also

4:54 zacts: huh, ok Glenjamin

4:54 tomjack: then you write a tree-map and do (= (tree-map (juxt identity meta) x) (tree-map (juxt identity meta) y))

4:54 clgv: james234: are you sure you actually sent a "POST"?

4:54 and not a "GET"

4:54 james234: clgv: this code seems to work, when I test the 'app' function, I get back a normal response map

4:54 Glenjamin: eg. (fn my-thing [some-map args] (update-in some-map [:drill :down :data] apply-transformation args))

4:55 james234: clgv: yes I am sending the "POST" using postman

4:55 zacts: Glenjamin: was that for me?

4:55 Glenjamin: yeah

4:55 zacts: ah ok

4:55 cfleming: tomjack: Interesting idea, I'll play around with that, thanks. I'm a little worried about the elements of tree-seq not necessarily being the elements used by default equality (i.e. trickiness around map entries, or whatever) but that looks promising.

4:56 zacts: Glenjamin: so your example would not be a good design in this case

4:56 because it has the transformation stage within the data access functionality

4:56 Glenjamin: that's preferrable to one big function, because the structure part is separate from the "apply-transformation"

4:56 tomjack: yeah.. good luck. maybe look at clojure.walk too if it works with the data you've got?

4:56 Glenjamin: you still need both bits, but you can combine them in more ways like this

4:57 maybe that wasn't the best example

4:57 cfleming: tomjack: yeah, I'll take a look at that too - thanks

4:58 james234: clgv: when I test the 'app' function in the repl, using a request map, I get back a status 200 response map. But when I try to send a POST using postman (or my clientside javascript) it always sends back a 404.

4:58 hellofunk: slipset: that vimeo video like many is frustrating to watch since it doesn't show any of the slides the presenter is talking about.

4:58 slipset: oh i slap my face. i see there isa link in the comments to the slides.

4:58 slipset: hellofunk :)

4:59 hellofunk: btw, I haven't watched the video, I was in the audience.

4:59 zacts: I guess the goal for me is to make composable pieces like if I were composing music. Let me think of my example. I want to build more complex pieces of music from smaller building blocks

5:00 I don't want to represent a song as a specific data structure

5:00 slipset: hellofunk: maybe an idea for euroclojure to integrate the slides into the video

5:00 zacts: I want it to be composed from functions

5:00 so I guess one of my problems is how to represent something like this in data that I could share with others

5:00 yet the data still contains how it was composed together

5:02 I want many of my projects to have the flexibility of this kind of functional composition, in my design with functions and data

5:02 I don't know how to design data, namely config formats, and composable functions

5:02 (I hope this kind of makes sense)

5:04 should a song in this case be represented as maps / vectors / etc... or should it be a bunch of composed functions, I think the latter would be better.

5:04 slipset: zacts: sounds to me like you'd want to design a dsl for yiour problem?

5:04 zacts: huh, yeah kind of

5:04 I want a dsl for composing music

5:04 ianhedoesit: zacts: github.com/overtone/overtone

5:05 zacts: yeah I know overtone

5:05 ianhedoesit: oh okay

5:05 zacts: but I'm also trying to extend this metaphore into other domains

5:05 metaphor

5:05 ianhedoesit: I wasn't saying "use that instead!" or anything, I was going to say maybe get ideas from that

5:05 zacts: ah ok

5:05 ianhedoesit: I haven't looked into overtone itself much though, so don't expect anything. I only know of it because I'm using overtone/at-at for a project.

5:05 slipset: zacts: curious if you could make your data somthing like tools.analyzer.jvm

5:06 check this video by tbaldridge https://www.google.no/url?sa=t&rct=j&q=&esrc=s&source=video&cd=5&cad=rja&uact=8&ved=0CDQQtwIwBA&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DKhRQmT22SSg&ei=g2LHVO2pI4X5yQOTooKoBQ&usg=AFQjCNGnX0-U0XGGwwT8QKu2bcEbGxASTA&sig2=WJ4BCXTMoTDXnsb0sfkD4Q&bvm=bv.84349003,d.bGQ

5:07 zacts: I guess I really like the flexibility of composing music this way, I know how to do this. I just want to apply this level of flexibility and composability in other non-musical domains of design

5:07 some of my other projects seem to be too rigid

5:08 and I would like to extend this composablitity to other projects.

5:09 perhaps a more concrete example would be better.

5:09 whodidthis: ok im just being a bad, if i have (defmacro a [& b] `(let [b# ~b] b#)), how do i make it less bad so that it wont call (1 2 3) but return [1 2 3] or something

5:10 zacts: huh, let me find the plugin for one problem I had

5:11 clgv: whodidthis: transform it to a vec

5:11 whodidthis: oh '~b and then just convert it seems to work

5:11 thanks, sweet

5:12 zacts: I found it

5:12 clgv: ,(defmacro a [& b] `(let [b# (vec ~b)] b#))

5:12 zacts: https://github.com/lispcast/intro-clojure-1/blob/master/video1.clj

5:12 clojurebot: #'sandbox/a

5:12 clgv: ,(a 1 2 3)

5:12 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

5:12 zacts: ^ I was following this lispcasts tutorial

5:12 clgv: ,(defmacro a [& b] `(let [b# ~(vec b)] b#))

5:12 clojurebot: #'sandbox/a

5:12 clgv: ,(a 1 2 3)

5:12 clojurebot: [1 2 3]

5:12 whodidthis: ohh, dont even need to quote it cool

5:13 clgv: whodidthis: for this case you need quote only if you want a list as value

5:13 slipset: zacts: multimethods?

5:13 zacts: what are multimethods?

5:13 slipset: (defmulti action :action)

5:13 zacts: the interesting thing with this project, is that he represented much of the code as a datastructure

5:14 ah yeah

5:14 slipset: (defmethod action :squeeze ...)

5:14 {:action :squeeze ...

5:14 zacts: well I seem to lose much of the composability of the data from this

5:14 slipset: then you could imagine just sending a nested map to your action function and let it walk it.

5:14 zacts: kind of like how I want to keep the composability similiar to my music idea

5:15 what is the advantage of multimethods, versus just using functions?

5:15 s/is/are/

5:15 slipset: it's open ended polymorphism

5:16 zacts: I don't know what that means

5:16 you can overload the same functions with multiple data?

5:17 slipset: nope, it means you can solve the expression problem :)

5:17 zacts: please define 'expression problem'

5:17 slipset: if I give you a library with a multimethod and several implementations, you can add your own other implementations which suit your data

5:17 http://www.ibm.com/developerworks/library/j-clojure-protocols/

5:18 here done with protocols

5:18 http://adambard.com/blog/structured-clojure-protocols-and-multimethods/

5:19 zacts: ah cool let me read this

5:20 this is kind of what my questions in my mind have been about, now realized into a blog.

5:20 slipset: great!

5:20 zacts: thanks

5:24 ianhedoesit: slipset: I like the Data All The ASTs talk.

5:25 slipset: zacts: https://gist.github.com/slipset/42ce72108f9fa4502ada

5:26 ianhedoesit: cool!

5:28 zacts: oh neat slipset

5:28 hellofunk: zacts: a meaningful and flexible way to organize the data that is music is something i've thought about a lot. for me, it seems to depend on what you consider the key organizing parameter. for example, all music is a function of time. but is time a good way to organize it?

5:29 biellls: Hello everyone, I'm getting a really strange error when I apply str to a lazy seq http://pastebin.com/xj8Dni2D . Does anyone know why that happens?

5:29 zacts: hellofunk: yeah

5:30 hellofunk: zacts: when you structure music data as an application of time, you easily lose the independent flow of individual moving lines, so i'm not convinced that's the wise approach.

5:30 zacts: and also, there could be static songs that are exactly the same, and then there can be guidelines for an improvisation or composition, that are different every time

5:32 slipset: the problem I see with that is that you still have to write action handlers for each action

5:32 and

5:32 just a sec..

5:33 I'm trying to gather my thoughts on this

5:33 hellofunk: zacts: and when you structure a piece such that all the musical lines are slaves to time, you lose the ability for each line to easily have its own interpretation of time, which is what makes 19th centure music so great, and jazz, and any arena where the expression is separated from the constraints of a shared rhythm

5:33 zacts: hellofunk: indeed

5:34 I think the quote from SICP is good for this musical idea

5:34 let me find it

5:34 (Even while it changes, it stands still.)

5:34 Heraclitus

5:35 how do you represent movement in a static data type?

5:35 hellofunk: zacts: the naive yet common commercial approach is to organize music data as moments in time, but that is deeply flawed in my opinion and greatly limits what can be *easily* achieved in computer music. i've more recently thought serious about music as not data points in time, but rather each point is a minor thunk (type of function application) that governs its place in the greater context.

5:35 zacts: yeah, that sounds neat.

5:36 hellofunk: after all, that's how the musical mind subsconsciously creates the expression, musicians are thinking in the same way that a computer is prorammed (usually)

5:36 i mean, *not* thinking

5:37 zacts: would like to know what SICP quote you are referring to

5:37 zacts: http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-19.html#%_chap_3

5:37 at the top of ch3 in SICP

5:37 hellofunk: interesting

5:38 zacts: it's a metaquote (kidding) (I'm referencing a quote that is quoted within SICP)

5:39 hellofunk: zacts: that's an intresting quote. after all, a function is something that transforms something else (i.e. a type of "change"). yet, the function itself is a value that is not changing.

5:40 and in the immutable world (which at its heart, isn't all the universe immutable?), even what the function changes is not really changing.

5:42 zacts: well I had this idea that anything could be computed given infinite time, it just takes forever to get there. and that is where all motion comes from. so it's like godel escher bach. or a strange loop.

5:42 so there is both motion and no motion at the same time, it just takes forever to get the motion

5:42 or something like that

5:42 but now we are getting philosophical GEBish. lol.

5:43 so I think a turing machine is sort of right and sort of wrong at the same time

5:44 and with that, I must get some tea or coffee

5:45 I think we must view functions / state as a strange loop

5:46 pure functional vs mutated state

5:46 clgv: zacts: that assumption is false. not everything is computable

5:46 not even when you assume you had infinite time

5:46 zacts: clgv: indeed, but it's like a strange loop

5:47 TEttinger: can you compute the last digit of pi?

5:47 zacts: nope

5:47 clgv: TEttinger: hehe nice try

5:48 zacts: but back to clojure, this is getting too philosophical

5:48 clgv: zacts: it's called theoretical computer science ;)

5:48 hellofunk: TEttinger perhaps the question is, not whether can we or anyone compute it, but rather, is it possible in some way to compute it, but we haven't discovered how?

5:48 zacts: clgv: lol

5:48 yeah

5:48 ianhedoesit: TEttinger: I bet it's [0-9]

5:48 clgv: hellofunk: there is none since pi is transcendent ;)

5:49 TEttinger: hellofunk: it's easy if you use a base-pi numbering system

5:49 hellofunk: clgv: but correct me if i'm wrong, doesn't nature manage to "compute" it just fine?

5:49 TEttinger: never precisely

5:49 approximately

5:49 zacts: well, I see pi as this

5:49 just a sec..

5:50 pi is like a thunk as hellofunk described

5:50 it's not a static thing, but it's a means for finding the relationships between things

5:50 or something like that

5:50 clojurebot: Cool story bro.

5:50 TEttinger: lol clojurebot

5:50 clgv: clojurebot: botsnack

5:50 clojurebot: thanks; that was delicious. (nom nom nom)

5:50 zacts: lol

5:52 hellofunk: i wonder what triggered that clojurebot retort

5:52 zacts: oh, well. It's like 3:50am for me. I'm still waking up, perhaps this is just philosophical mind vomit from me

5:52 clgv: hellofunk: I think he does that randomly from time to time

5:52 hellofunk: zacts: waking up or going to bed?

5:52 zacts: waking up

5:52 hellofunk: zacts: damn son you are an early riser. you aren't Tim Cook by chance?!

5:52 zacts: no I'm zac

5:52 hellofunk: i was kidding

5:53 clgv: maybe he just slept through the entire monday ;)

5:53 zacts: :-D

5:53 so, back to clojure let me try to come up with a more concrete example for this baker idea

5:53 hellofunk: zacts: i will guess that you live in Porland or near SF

5:54 zacts: heh, I used to live in Portland, I live in NM now

5:55 hellofunk: zacts: right, SF, as in Santa Fe

5:55 zacts: oh sorry, I thought san francisco

5:55 hellofunk: just kidding. i meant the other SF. but my guesses were badly designed. i was off by an hour. i've thought about moving to NM more than once in my life.

5:56 ianhedoesit: hellofunk: Portland's cooler.

5:56 literally.

5:56 martinklepsch: wondering how to test private fns?

5:56 is this the way to go: (#'scratch.core/super-secret-function 5) ?

5:56 clgv: martinklepsch: don't make them private in the first place. this is seldom a good idea

5:57 martinklepsch: clgv: making functions private is rarely a good idea?

5:57 clgv: why that?

5:58 clgv: martinklepsch: have you not been annoyed so far that when writing a macro some of the clojure core functions used in defn or similar are private?

5:58 ianhedoesit: martinklepsch: I don't know his reasoning, but I would like to ask you why should some function be private? what benefits are there in the situation?

5:58 Glenjamin: if it's not private, you're sort-of promising not to break it in future

5:59 clgv: martinklepsch: similar holds for different libraries. the implementation is there, but you need to rearrange it differently. but with idiomatic clojure you cant because of the private fns

5:59 martinklepsch: clgv: actually havn't written many macros so that problem is unknown to me

5:59 Glenjamin: smaller api surface area is sometimes beneficial when publishing a library

6:00 martinklepsch: ianhedoesit: the reason is that there is some functionality that is exposed via a single public function and I don't want anyone to use the functions used to implement that functino

6:00 ianhedoesit: why not?

6:00 schmir: some people prefer implementation namespaces to private functions. that would allow using the function from multiple namespaces

6:00 martinklepsch: because most likely it would be wrong to use those functions somewhere else

6:01 schmir: impl namespaces don't restrict usage as private fns do

6:02 This is mostly a warning sign for other people working with the code - "hey! you're not supposed to do that"

6:03 schmir: martinklepsch: yes, right. I also use private functions. I don't see a problem with them....

6:03 martinklepsch: btw. thanks for the nice talk on boot!

6:04 ianhedoesit: martinklepsch: as a counter point (and I don't have a strong opinion on the matter, really. I think private functions have their place and there isn't necessarily a hard and fast rule), I've been using a library which does some stuff I need, but it has tons of private functions that I've ended up needing to recreate in my code because I need the lower-level functions the authors thought would not be needed. I don't like this.

6:04 martinklepsch: schmir: oh thank you :) who are you? :P

6:04 zot: hidey ho :) I'm trying clojure.walk for the first time, and have a nested tree-ish structure built both from vectors and maps; I would ideally like to walk the structure, building up a 'path' along the way, which would be suitable for use w/ (update-in) while evaling the 'inner' function. anybody know of some example/sample/working code that does something similar?

6:04 justin_smith: ianhedoesit: @#'ns/f :)

6:04 ianhedoesit: justin_smith: shh. neat!

6:05 martinklepsch: ianhedoesit: yeah I see the point, I guess there it's mostly a design decision. like the library author wants to keep the surface area he has to maintain small

6:05 schmir: martinklepsch: Ralf Schmitt, but we didn't talk

6:05 martinklepsch: justin_smith: what does that do vs #'ns/f?

6:06 schmir: too bad. say hi next time :)

6:06 schmir: are you using boot?

6:07 justin_smith: martinklepsch: it explicitly derefs, for a function it isn't needed actually I guess

6:07 schmir: martinklepsch: I'm thinking about switching over for a GUI application that I develop

6:08 martinklepsch: justin_smith: for what would that be needed? (I guess it's not an atom deref kind of thing)

6:08 schmir: Clojurescript based?

6:09 justin_smith: martinklepsch: vars need to be derefed, but in the calling position the deref is automatic

6:09 ,(@#'+ 1 1)

6:09 clojurebot: 2

6:09 justin_smith: ,(#'+ 1 1)

6:09 clojurebot: 2

6:10 martinklepsch: ,(def n 5)

6:10 clojurebot: #'sandbox/n

6:10 schmir: martinklepsch: no, clojure with javafx as a GUI toolkit

6:10 martinklepsch: (+ #'n 1)

6:10 ,(+ #'n 1)

6:10 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Var cannot be cast to java.lang.Number>

6:10 martinklepsch: ,(+ @#'n 1)

6:10 clojurebot: 6

6:10 martinklepsch: I see. Thanks for the explanation justin_smith

6:11 schmir: nice. let me know if you need help :)

6:11 (i.e. run into trouble or anything like that)

6:12 schmir: martinklepsch: thanks!

6:23 hellofunk: ,(apply #'+ 5 6)

6:23 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

6:24 hellofunk: ,(apply #'+ [5 6])

6:24 clojurebot: 11

6:24 hellofunk: justin_smith: that was not in the calling position, right? still didn't need de-ref

6:24 justin_smith: apply translates to a call where it is in the calling position though

6:24 Bronsa: hellofunk: vars automatically deref when used as functions

6:25 justin_smith: yeah, that's more precise anyway

6:25 (inc Bronsa)

6:25 lazybot: ⇒ 87

6:28 H4ns: does anyone have recommendations for an image processing library? i mostly need to rescale jpegs. i have tried mikera.imagez, but it is lacking.

6:29 justin_smith: H4ns: for lichen we used the built in java stuff and it just works (BufferedImage etc.)

6:29 what was lacking?

6:29 Glenjamin: ~lichen

6:29 clojurebot: Pardon?

6:29 Glenjamin: justin_smith: what's lichen?

6:29 justin_smith: Glenjamin: lichen is an image resizing server with aws support

6:30 Glenjamin: ah, i see

6:30 justin_smith: Glenjamin: supports upload, and then cached resizes based on request parameters

6:30 can host locally, or use aws storage

6:30 does jpg, gif, png, with transperency support

6:30 H4ns: justin_smith: rescaling is lacking parameters, and it cannot save all jpegs without screwing up the colors. i've seen how that'd be fixed in its usage of the java builtin stuff, yet if there'd be something that works, i'd gladly use that instead of hacking on imagez

6:32 justin_smith: i'll review lichen, thanks!

6:32 justin_smith: H4ns: we got the stuff working via interop with the built in stuff in java, it shouldn't be too hard to use the appropriate functions in lichen but not run the server

6:32 H4ns: justin_smith: lichen has the same bug as imagez with respect to screwing up the colos of jpegs, as far as i can see :)

6:33 justin_smith: oh, do tell the fix

6:33 H4ns: justin_smith: http://stackoverflow.com/questions/9340569/jpeg-image-with-wrong-colors

6:33 justin_smith: https://github.com/caribou/lichen/blob/master/src/lichen/image.clj#L135 this is the function you would likely want to use, btw

6:33 H4ns: justin_smith: basically, one needs to save the original image metadata


6:33 thanks man!

6:33 I will fix it

6:34 H4ns: :D

6:34 justin_smith: that solution is a total hack though :(

6:35 H4ns: the java image api is so clunky. if one wants to know how java sucks, that is what to look at to be convinced.

6:35 sorry for the pointless ranting

6:36 justin_smith: np, I tore my hair out over that bug

6:36 the issue is that the java libs don't support CMYK jpeg

6:36 this workaround is to treat it as a generic jpeg, and then hand copy the headers

6:36 hmm

6:38 H4ns: maybe i should just wrap gd

6:46 clgv: martinklepsch: that was one example of many where private fns made things much more complicated than need be

6:46 justin_smith: why not implement the metadata fix in mikera's lib or mine and issue a PR? I'll likely implement it eventually but it feels a bit hackish.

6:47 clgv: martinklepsch: why can it be wrong to use a function somewhere else? that reminds me strongly of http://steve-yegge.blogspot.de/2010/07/wikileaks-to-leak-5000-open-source-java.html

6:49 martinklepsch: clgv: that article is fun.

6:49 I'm not working on a library but on an application. so any other developer can just make it public, there's no way to avoid this (and also I don't want to avoid it)

6:50 making it private in my case is probably more a kind of documentation than it is an attempt to restrict people from using it

6:51 "Who cares if I have a private helper function they need? What, is their copy/paste function broken?" hahaha

6:51 clgv: ;)

6:52 Glenjamin: something like this: (defmacro publicize [vr] (def (name ~vr) (var vr)))

6:53 clgv: Glenjamin: hacking the check is not really a solution to this ;)

6:53 justin_smith: Glenjamin: you likely want a deref on that var, then it works for private data too

6:53 clgv: you could just use #'the.ns/f instead ;)

6:54 Glenjamin: it's probably more of a philosophical question really :)

6:54 clgv: or similar, depending on your :require clauses

6:54 it's uncessary additional code.

6:54 Glenjamin: i was thinking the macro expresses intent a bit better than using the var quote

6:55 and specifically imports into the current namespace

6:55 which in the testing scenario, is probably desirable?

6:57 martinklepsch: clgv: you still think it's a bad idea to make this private?

6:58 clgv: martinklepsch: usually there is almost no benefit from a private fn but much more hassle

6:59 Glenjamin: clgv: what about having to maintain back compat on the api? or do you prefer some other method to indicate "i might change these" vs "i'm unlikely to change these" ?

7:00 clgv: another thought: if you are trying to test private functions and you made them private because they are only supposed to be used internally, then you are testing implementation details, which is not a good idea at all, since they will likely break on valid refactorings

7:01 Glenjamin: there is :skip-wiki although I don't like that name. then it is in generated docs. would you suspect undocumented functions to be backwards compatible?

7:01 +not

7:01 Glenjamin: that's probably a reasonable line to draw

7:03 martinklepsch: clgv: what speaks against testing an implementation detail?

7:03 Glenjamin: on the testing private side: i think there's value in testing an implementation detail - but not that testing a caller uses that implementation detail correctly

7:03 eg. test a helper fn, but don't test the real fn with the helper mocked

7:03 jinagarano: i'm trying to set up korma with an h2 database. i did a ragtime migration, and when i try to do an insert, i get an error "table not found." why? project.clj and the korma code point to the same file.

7:12 clgv: martinklepsch: valid refactorings are likely to cause test errors

7:19 H4ns: justin_smith: i'll be doing that, now that i know about leiningen checkouts :)

7:24 jinagarano: i'm trying to set up korma with an h2 database. i did a ragtime migration, and when i try to do an insert, i get an error "table not found." why? project.clj and the korma code point to the same file.

7:25 zoldar: Hi. When writing and executing tests created with "deftest" directly from active repl, I experience a following problem: after removing and/or renaming one or more tests the old bindings are still in the namespace. I have to either a) restart REPL b) do manual unmap with 'ns-unmap'. Is there some more convenient approach, like clearing the whole namespace before reevaluating it?

7:26 clgv: zoldar: namespace reloading via tools.namespace

7:27 zoldar: or a custom function that flags all current variables as :old, then reloads the current namespace and ns-unmaps those that are still marked as :old

7:27 zoldar: clgv: forgot about this one, thanks

7:36 luxbock: what's the best way to get a [ns sym] tuple from a symbol?

7:37 clgv: luxbock: (juxt namespace name)

7:37 ,((juxt namespace name) 'bla.blubb/foo)

7:37 clojurebot: ["bla.blubb" "foo"]

7:37 luxbock: clgv: thanks

7:38 I just ran into an amusing bug with my solution

7:38 I was doing ##(apply str (drop 2 (str (resolve 'map)))) first

7:38 lazybot: java.lang.SecurityException: You tripped the alarm! resolve is bad!

7:39 luxbock: which worked but then when it got a class name, then it would return "ass clojure.lang.Number"

7:42 clgv: luxbock: Clojure swearing back at you ;)

7:43 luxbock: I think I'll have to handle classes as a special case anyways

7:43 ,((juxt namespace name) 'clojure.lang.Numbers)

7:43 clojurebot: [nil "clojure.lang.Numbers"]

7:56 Glenjamin: just catching up on that yegge rant - interesting that "final" is included, given clojure's hard stance on any inheritance

7:56 even if it means there's loads of legwork to implement custom collections

7:58 clgv: Glenjamin: "final" is evil in the cases "this is almost what I need if I could just add something to that one function" ;)

7:58 Glenjamin: mm

8:14 SagiCZ1: how does exception catching works in clojure? i need to catch a specific type of exception and handle it.. and all OTHER exception types just log and rethrow..

8:14 would this work?

8:14 (try ... (catch MyException e ...) (catch Exception e ...))

8:15 Glenjamin: yes, it should

8:15 SagiCZ1: and how would this behave?

8:15 (try ... (catch xception e ...) (catch MyException e ...))

8:16 s/xception/Exception

8:16 Glenjamin: try it and see

8:18 SagiCZ1: ok.. the order does matter.. if the Exception catch is first, it will catch and handle everything.. so it needs to be last

8:32 jinagarano: i'm trying to set up korma with an h2 database. i did a ragtime migration, and when i try to do an insert, i get an error "table not found." i don't understand why, project.clj and the korma code point to the same file.

8:34 SagiCZ1: does anyone know how to get ButtonGroup reference from JRadioButton? considering the JRadioButton is assigned to the ButtonGroup.. i just have references only to the buttons, not to the button group

8:47 gfrederi`: am thinking of making a lein task for deploying a fork

8:51 * gfrederi` so many yaks

9:18 clgv: gfredericks: got into the shaving business, eh?

9:21 freewater: Hello. If I'm writing a macro that has `(aggregate (count :id)), when I do macro expand I get (korma.core/aggregate (clojure.core/count :id)) which is not what I want. I understand this is because of the ` but how do I get escape that to get just count without the clojure.core before it?

9:22 tbaldridge: freewater: you can import korma.core with a name, and then prefix the call to count. `(aggregate (k/count :id))

9:23 *require korma.core with a name

9:23 gfredericks: clgv: it's a yakky sort of morning

9:23 tbaldridge: freewater: (:require [korma.core :as k])

9:23 gfredericks: people are always adding features to the master branch of their library and then waiting four months to make a release

9:24 Glenjamin: that's one thing i like about Node - the culture is to release often, and not be afraid to have lots of version numbers

9:25 i guess fragmentation is more of a worry in this case?

9:25 * gfredericks shrugs

9:26 freewater: tbaldridge: thanks, but the problem is it isn't in korma.core, and it does a lookup on the key 'count: https://github.com/korma/Korma/blob/master/src/korma/sql/engine.clj#L234

9:26 muhuk: freewater: also `(aggregate (~'count :id))

9:26 tbaldridge: freewater: ahh, then you can do this:

9:26 muhuk: freewater: but it might not be what you want.

9:26 tbaldridge: yeah, what muhuk said

9:26 (or just don't use korma...it's pretty macro-heavy)

9:27 muhuk: gfredericks: and there is no pull request for releases

9:27 gfredericks: muhuk: good point

9:27 tbaldridge: freewater: perhaps consider something like yesql https://github.com/krisajenkins/yesql#rationale

9:27 freewater: tbaldridge & muhuk: thanks, I'll give that a try

9:28 muhuk: yw

9:28 freewater: tbaldridge: I tried looking at that first, but I couldn't figure out how to easily create dynamic queries, for lack of a better description

9:28 clgv: tbaldridge: a little offtopic: does pixie already have something like primitive type hints for function arguments and return value?

9:32 tbaldridge: clgv: not needed, as the JIT adds them automatically.

9:33 clgv: tbaldridge: it does? interesting. so I should be able to do benchmark comparisons for numeric calculatins between clojure and pixie

9:33 tbaldridge: clgv: yep, The JIT created by pypy is known as a "tracing jit" and is quite a different beast from the JVM

9:35 clgv: tbaldridge: I just remembered that Common Lisp needed those declare statements to optimize for numerics.

9:36 tbaldridge: yeah, most JITs and compilers that only look at a single function in isolation will need that. Tracing JITs like PyPy, LuaJIT, etc. compile loops, not functions, so they will often inline much more aggressively, leading to less need for type hinting.

9:36 freewater: :muhuk does this work because ~ first unquotes from the ` and then requotes it with ', which doesn't return fully qualified symbols?

9:37 clgv: tbaldridge: are there facilities to see what the JIT does to a specific executed code snippet?

9:41 gfredericks: huh; clojars lets you claim a subgroup of an existing group

9:41 stuartsierra: gfredericks: That sounds like an oversight.

9:41 gfredericks: agreed

9:41 confirming

9:42 stuartsierra: Unless the group you're claiming is a subgroup of a group you already own.

9:43 gfredericks: I just deployed this by accident despite not owning the existing mvxcvi group: https://clojars.org/mvxcvi.com.gfredericks.forks/puget

9:43 Glenjamin: clojars has subgroups?

9:43 gfredericks: Glenjamin: maven generally

9:45 the one I linked to doesn't come up when searching for "puget" though

9:46 muhuk: freewater: ~'sym is actually sym, except when ` looks for stuff to quote it sees it as a call to ~ instead of the result of ~'sym

9:46 gfredericks: lol; the clojars issues page has delete requests in it

9:46 muhuk: freewater: something like that

9:47 Glenjamin: gfredericks: it looks like some pages reverse the group id

9:48 oh, nope - you just pushed it again

9:48 gfredericks: right

9:48 welp I filed an issue

9:49 can't figure out why my task failed to modify the description, but oh well

9:56 okay here's a new deploy-fork task you can use: https://github.com/gfredericks/corncob-cigar#deploy-fork

10:12 zacts: yo

10:14 hellofun`: zacts: 'sup

10:14 zacts: hey man

10:14 hellofun`: I would be interested in working further with you on some music + clojure ideas.

10:14 but right now I need to wake up a bit, and make some breakfast

10:15 I took a nap, but I'm waking up now

10:15 hellofun`: zacts: no doubt my G. i'm actually about to shut down for the day. been a long one already and a long night last night too.

10:15 zacts: coolio

10:15 heh, I'm actually listening to bach's air on the G string right now, and bobby mcferrin singing it

10:16 hellofun`: yo 'sup bobby

10:16 zacts: bach was the original G I guess

10:16 hellofun`: yo that dude be everybody's G, son

10:17 zacts: there have been a number of interesting discussions lately with amalloy_ about related ideas too. it's an interesting area of research

10:17 zacts: ah cool

10:24 SagiCZ1: can i somehow call a function if i have the string of its name?

10:24 (call "foo")

10:24 tbaldridge: ,((resolve 'clojure.core/+) 1 2)

10:25 clojurebot: 3

10:25 SagiCZ1: tbaldridge: thank you very much

10:25 ,(resolve (symbol "+"))

10:25 clojurebot: #'clojure.core/+

10:25 SagiCZ1: sweet

10:26 zwer: ,(resolve (symbol "+") 1 2)

10:26 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: core/resolve>

10:27 zwer: ,((resolve (symbol "+") 1 2))

10:27 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: core/resolve>

10:27 SagiCZ1: ,((resolve (symbol "+")) 1 2)

10:27 clojurebot: 3

10:27 zwer: .. right

10:27 tbaldridge: SagiCZ1: note though that resolve returns a var. If you don't want the var, but the thing inside the var, you'll need to deref it.

10:27 It's just that vars auto-deref when they are called like functions

10:28 SagiCZ1: tbaldridge: interesting.. well it is a function so i guess i dont need to deref it

10:29 (def foo (shuffle [1 2 3]))

10:29 (defn foo [] (shuffle [1 2 3]))

10:30 the difference between these two is just that if its a function it gets shuffled every time its called?

10:30 gfredericks: yep

10:30 hellofun`: SagiCZ1: def foo is just storing the return value from shuffle, one time

10:30 SagiCZ1: so if i have a zero argument function and i want the result to be the same every time and it has no side-effect.. i should just use def, right?

10:30 tbaldridge: yep

10:30 hyPiRion: (defn foo [] ...) is just (def foo (fn [] ...))

10:30 "just"

10:30 SagiCZ1: thanks, that makes sense

10:32 hellofun`: i'm curious about terminology. if a fn doesn't make side-effects, but depends on data that could change that it reads from outside, then while it is side-effect-free, it is not pure, yes?

10:33 SagiCZ1: hellofun`: isnt reading outside data a form of side-effect?

10:33 Glenjamin: not under the hickey definitions

10:33 SagiCZ1: well in any case it is not referentially transparent

10:33 hellofun`: SagiCZ1: i don't know, i'm curious about the terminology

10:33 stuartsierra: People tend to toss around terms like "pure" in conversation without being precise about their meanings.

10:34 tbaldridge: hellofun`: example? what do you mean by "reads from the outside"

10:34 hellofun`: i think of "pure" as meaning a funciton that is idempotent, referentially transparent, and without side-effects. is this valid? simply

10:34 gfredericks: idempotent, no

10:35 e.g., inc is not idempotent

10:35 Glenjamin: yes it is

10:35 hellofun`: tbaldridge: consider a zero-arg fn that merely returns the dereffed value of an atom but makes no changes

10:35 tbaldridge: it is if you always pass in 1

10:35 Glenjamin: (inc 1) is always 2

10:35 gfredericks: Glenjamin that's not what idempotent means

10:35 tbaldridge: hellofun`: right, that's not pure

10:35 Glenjamin: well, in that case isn't it meaningless on immutable values?

10:36 gfredericks: Glenjamin: no, idempotent means (= (f x) (f (f x)))

10:36 hellofun`: that (inc 1) is always 2 is idempotence, no?

10:36 Glenjamin: hrm, i see what you mean

10:36 tbaldridge: hellofun`: so by that standard, no clojure function is really pure, as a var could be re-deffed. But that's a price paid for REPL development

10:36 Glenjamin: that's a good strong simple definition of idempotence - i like it

10:36 gfredericks: I think it's *the* definition :)

10:37 Glenjamin: http://stackoverflow.com/a/1077421/173062 seems to offer 2 definitions, no source though =/

10:37 gfredericks: yeah I guess there's a usage in the context of side-effects as well

10:38 hellofun`: actually, that (inc 1) always = 2 is perhaps an example of referential integrity/transparency

10:38 SagiCZ1: resolve takes a namespace parameter.. can it be in the short form as created by :require :as ? .. it works in repl but not in the actual program

10:39 stuartsierra: "Idempotence" is mostly useful when you're talking about something that potentially changes state or has side effects (e.g. HTTP GET vs POST).

10:39 SagiCZ1: ,(require clojure.string :as str)

10:39 clojurebot: #<CompilerException java.lang.ClassNotFoundException: clojure.string, compiling:(NO_SOURCE_PATH:0:0)>

10:39 SagiCZ1: ,(require clojure.core.string :as str)

10:39 clojurebot: #<CompilerException java.lang.ClassNotFoundException: clojure.core.string, compiling:(NO_SOURCE_PATH:0:0)>

10:39 gfredericks: I just used clojure inheritance to do something useful https://github.com/gfredericks/dotfiles/blob/master/.lein/profiles.clj.symlink#L26

10:40 SagiCZ1: ,(require '[clojure.string :as str])

10:40 clojurebot: nil

10:40 SagiCZ1: ,(str/join "hey" "word")

10:40 clojurebot: "wheyoheyrheyd"

10:40 tcrayford____: garee you're profiles.clj

10:40 woah

10:40 SagiCZ1: ,(resolve (symbol "str" "join"))

10:40 clojurebot: #'clojure.string/join

10:41 gfredericks: tcrayford____: I decided to start putting effort into it a year ago or something

10:41 SagiCZ1: ,(resolve (symbol "clojure.string" "join"))

10:41 clojurebot: #'clojure.string/join

10:41 tcrayford____: that thing is huge

10:41 SagiCZ1: it should work..

10:41 gfredericks: tcrayford____: um and beautiful

10:42 defn: Hello

10:42 What's the rationale for having both partition and partition-all?

10:43 SagiCZ1: (inc defn)

10:43 lazybot: ⇒ 1

10:43 benmoss: defn: a blog post just from yesterday on the two: http://gigasquidsoftware.com/blog/2015/01/26/partition-with-game-of-thrones-pugs/

10:44 does anyone konw how the version of Clojure determined if you don’t specify one in your project.clj?

10:44 defn: benmoss: ya my question remains

10:45 No sense in having both as far as I can tell

10:45 tbaldridge: maybe you want one or the other. What's the harm in having both?

10:45 defn: Subtle errors and no real expressivity benefit

10:46 SagiCZ1: does anyone know why resolve can resolve aliased namespaces in repl but not at run-time in the app? (resolve 'alias/foo)

10:46 defn: Not the end of the world but I don't understand the rationale

10:46 tcrayford____: defn: I agree with this - I've been using clojure for 5 years, not really used partition that much, ran into this recently and went kinda crazy

10:47 defn: "Why not both?" Is not a rationale

10:47 Glenjamin: defn: there are two distinct scenarios, which would you remove?

10:47 SagiCZ1: defn: dont they do different things? can you achieve partiton-all with partiton or vice-versa?

10:47 defn: I don't see why not

10:48 I'd drop partition-all, make the default behavior of partition to be inclusive

10:48 tbaldridge: and all existing code that uses partition may break

10:49 defn: He asked. I never said its a viable option.

10:49 SagiCZ1: defn: and what if i want not inclusive partition?

10:49 defn: Check the last yourself

10:49 hyPiRion: it's not "the last" though

10:50 ,(partition 3 1 (range 4))

10:50 clojurebot: ((0 1 2) (1 2 3))

10:50 hyPiRion: ,(partition-all 3 1 (range 4))

10:50 clojurebot: ((0 1 2) (1 2 3) (2 3) (3))

10:50 tbaldridge: (inc hyPiRion)

10:50 lazybot: ⇒ 60

10:51 defn: Alright. Nailed it.

10:51 That's all I was looking for :)

10:51 tbaldridge: for the feature I've used several times, but always forget.

10:51 SagiCZ1: how do i deref a var?

10:51 Glenjamin: deref

10:51 ,(identical? + @#'+)

10:51 clojurebot: true

10:52 SagiCZ1: oh.. thanks

10:56 stuartsierra: SagiCZ1: re your question about aliased Vars, it's because the REPL knows what the "current" namespace is. Running application code usually doesn't.

10:56 SagiCZ1: stuartsierra: cool.. well i used the fully qualified name and it works

11:00 sdegutis: So I'm going through the book /Learn you a Haskell for Great Good/ and so far Haskell has all the features that made me love Clojure so much.

11:01 The one feature I miss from Clojure that Haskell doesn't have is the -> macro.

11:01 Just thought I'd report my findings to anyone who also likes Clojure very much like me :)

11:02 *like I do

11:03 hellofun`: sdegutis: i would think there is an analog to clojure's comp though, is there?

11:03 sdegutis: Yep, the . operator (or function since all operators are functions)

11:04 hellofun`: i've always preferred comp-style to threading for some reason

11:04 sdegutis: Haskell's map foo . filter bar is Clojure's (comp (partial map foo) (partial filter bar))

11:05 agarman: question: why do transducers comp in reverse to normal functions?

11:05 hellofun`: it's interesting (from what i read online) that you can fold left and right both and still maintain laziness. that's the quality of the language i find so interesting. and that partial is implicit

11:05 sdegutis: agarman: they do? huh, didn't realize that

11:05 hellofun`: oh neat I didn't know that -- but I bet you can do the same thing in Clojure

11:06 agarman: yeah, (comp (filter odd?) (map inc)) -- does filter then does a map

11:06 sdegutis: So far Clojure can do everything Haskell can do (I think), just with dynamic typing.

11:06 stuartsierra: agarman, sdegutis: It just sort of falls out of how they are implemented. Each layer of composition adds another "step" to the beginning of the "process".

11:06 agarman: versus (comp inc second)

11:06 hellofun`: sdegutis: no, not on those things i mentioned. we've had a number of debates in here and on SO, those are features clojure doesn't really have

11:06 sdegutis: agarman, stuartsierra: well at least it reads more naturally to me this way

11:06 hellofun`: oh

11:07 agarman: @sdegutis it reads backwards from mathematical function def (f (g (h x))) => (comp f g h)

11:07 sdegutis: I forgot why I ever liked dynamic typing.

11:07 agarman: ah

11:07 ToxicFrog: I liked dynamic typing because I'd only ever used languages with terrible static typing.

11:07 sdegutis: agarman: I don't know math so I'm unbiased.

11:07 ToxicFrog: So the options were "dynamic typing" or "Java"

11:07 sdegutis: ToxicFrog: that's probably the same with me too (C++, C, etc)

11:08 ToxicFrog: Static typing looks a lot more attractive once you're introduced to type inference, generics, etc

11:08 You spend less time fighting with the type system.

11:08 SagiCZ1: ToxicFrog: do yuo consider java to have good static typing system? jw

11:08 ToxicFrog: SagiCZ1: no

11:08 sdegutis: Yeah Go really got me into type inference, but lack of generics put me off. Then recently I learned Swift which has both but with a similar syntax, but it's Apple-only.

11:09 Glenjamin: haskell has type classes, which are nice

11:09 not many well known langs with ad-hoc polymorphism =/

11:09 sdegutis: Then I found OCaml which is basically a better Swift, but it's still pretty weird in some spots for me. So that's why I'm learning Haskell which has type inference and generics (kind of) and *all* my favorite features of Clojure.

11:09 ToxicFrog: sdegutis: looked at Rust? I haven't used it but I have a friend who's very pro-static-typing-for-real-world-use and speaks favourably of it after some experimentation.

11:09 Haskell is one of those languages that I really like on paper but have never actually gotten anything done with.

11:09 Glenjamin: rust doesn't have ad-hoc polymorphism either afaik :(

11:09 ToxicFrog: I think it was Scala that convinced me that static typing doesn't have to be a painful trainwreck.

11:09 sdegutis: ToxicFrog: yeah but Rust is still a low-level language, where you can't really omit specifying low-level details when you want to write higher-level code, which turned me off to it

11:09 hyPiRion: Glenjamin: ad-hoc? It has traits

11:10 hellofun`: sdegutis: how is that book LYAGH

11:10 sdegutis: ToxicFrog: that's why I looked into Nim(rod) and OCaml.

11:10 ToxicFrog: Clojure with static typing would be pretty great, but core.typed just isn't there yet

11:10 sdegutis: hellofun`: sooooo good

11:10 Glenjamin: hyPiRion: my understanding was they're limited in such a way that don't actually give you the same power as protocols and type classes

11:10 ToxicFrog: I haven't tried OCaml, I've looked at some resources for it and found it pretty offputting at first glance

11:10 hellofun`: sdegutis: i believe amalloy_ was recommending the same book to me last year or last night can't remember, recently

11:10 Glenjamin: i am now reading up on it

11:10 sdegutis: hellofun`: if you know Clojure it'll be slightly slow, but his very colorful and humble writing style makes it a breeze (and fun) to skim

11:10 ToxicFrog: what about it?

11:11 hyPiRion: Glenjamin: type classes doesn't give you the same power as protocols though. You can afaik only implement typeclasses where the type is defined or where the typeclass is defined

11:11 ToxicFrog: sdegutis: no polymorphism, mostly, so you need different operators/functions for different data types even if the conceptual operation (e.g. addition) is the same for both

11:11 hellofun`: sdegutis: i didn't realize that book was online for free. i wonder if that is recent.

11:11 Glenjamin: hyPiRion: right, that's probably what i'm thinking of - i had assumed the "ad-hoc" part meant you didn't have to be the owner

11:12 ToxicFrog: I like having one "+" function that works for all numeric types and one "map" function that works for all sequence types

11:12 sdegutis: ToxicFrog: ouch yeah that sucks

11:12 hyPiRion: Glenjamin: That being said, I can imagine typeclasses with some language extensions (or maybe even without) being more general than traits.

11:12 Glenjamin: one of the nicer parts is that functions are namespaced

11:13 whereas (afaik) obj.method syntax isn't - even with traits

11:13 hyPiRion: yeah

11:13 ToxicFrog: sdegutis: arguably I haven't given ocaml a fair shake, I haven't actually written any code in that, but I just find that feature-lack really, really offputting.

11:13 crash_ep: In clojure.test, are there any hazards with making the "is" checks in a separate thread, or with looping them? I ask b/c I notice the final report says I only have N assertions, where N is the number of separate occurrences of "is" in the code, although I am calling it hundreds of times in a separate thread.

11:14 sdegutis: So as I'm reading through Learn you a Haskell online (http://learnyouahaskell.com/), I'm finding in pretty much every chapter that the examples look *almost exactly* like Clojure.

11:14 Glenjamin: is there a general name for "solves expression problem and has avoids namespace collisions on dispatch item" polymorphism?

11:14 sdegutis: And I'm just like "Awesome, it has that feature too!"

11:14 ToxicFrog: no you're right, that's totally fair

11:15 ToxicFrog: I had a lot of problems with OCaml that I tried to overlook to learn it, and then there was one or two that was just the straw that broke the Caml's back and I was like "welp, let's look at Haskell"

11:15 So far I haven't had *any* problems with Haskell yet. It's basically a typed Clojure with fewer parentheses and less syntax.

11:15 ToxicFrog: sdegutis: yeah, I've futzed around with haskell a bunch but I've never actually solved any problems with it. I always end up confused, sad, and tangled up in the IO monad. :(

11:16 sdegutis: Heh, I haven't gotten to IO or monads yet -- we'll see if that causes me to abandon it! ;)

11:17 hyPiRion: read http://blog.jle.im/entry/io-monad-considered-harmful before you dig into it

11:17 sdegutis: love the first paragraph :D

11:18 hyPiRion: But I don't think it's prudent of me to read that until I first learn about monads in LyaH.

11:19 hellofun`: sdegutis: correct me if I'm wrong, but didn't you just start learning ocaml about a week ago?

11:19 hyPiRion: sdegutis: sure, just be aware that the "IO monad" might be referring to the IO type instead

11:19 sdegutis: hellofun`: nope, only a few days ago

11:19 hellofun`: I definitely didn't get far.

11:20 hellofun`: sdegutis: ok i thought so. while i admire your energetic survey of all these languages, i do think you'd have to use a language and understand its idioms for a while before passing judgements on what the langauge lacks, because usually there are hidden strengths to how it does things

11:20 sdegutis: hellofun`: we'll have to agree to disagree on that in part

11:21 Glenjamin: i think i agree with this io monad post

11:21 hellofun`: sdegutis: after all, your early desire to get OOP going in Clojure.. different languages have different thought processes

11:21 sdegutis: hellofun`: "early"?

11:21 Glenjamin: recently someone said deferred IO action to me - and it all clicked

11:22 ToxicFrog: hyPiRion: so, the issue I have is that as soon as I want to do any sort of IO at all, I can no longer figure out how to appease the type checker

11:22 hellofun`: sdegutis: apologize if it sounds like criticism but i just think it's not always black/white to compare features between languages and you might find fascinating concepts if you give them a chance to be their own thing

11:23 sdegutis: hellofun`: you most likely misunderstood my experiment due to lack of context -- I've been using Clojure for years, striving to learn and write very idiomatic code

11:23 hellofun`: sdegutis: oh ok.

11:23 sdegutis: hellofun`: and while my opinions are flexible and mutable, I try to both learn idiomatic language features and pragmatic approaches and patterns before deviating in any way from idiomaticity

11:24 That's not a word actually.

11:24 Glenjamin: ToxicFrog: i like to think of the IO type as tagging my value as dirty, and to get back into clean code i need to shake off the IO part somehow

11:24 ToxicFrog: I keep wanting to learn Haskell and I keep bouncing off it.

11:24 hellofun`: i have a cousin who insisted a few years back that objective-c wasn't a real programming language. the reasoning was bonkers, so perhaps i am projecting that context i have into the discussion. he tried to compare it to a bunch of other languages, all of which have their own weaknesses.

11:24 sdegutis: ToxicFrog: that happened to me about twice in the past 4 years ;)

11:24 hellofun`: it's a terrible language, sure, but very real

11:25 hellofun`: it's got many legitimate and permanent flaws that make Swift a great alternative

11:25 hellofun`: sdegutis: i don't know, it has a lot of cool features for a strong OO language

11:25 the rich OO and dynamic typing make it quite an odd one in and of itself.

11:25 sdegutis: hellofun`: meh it really only has very few features, the rest is just stuff the standard library provides

11:26 Glenjamin: very good and helpful analogies so far, thanks for them

11:27 * hellofun` heads off to continue with the lyah book now

11:27 sdegutis: Anyway am I doing a good job being bitemyapp/callen in his absence?

11:27 ToxicFrog: hyPiRion: now that I've read the whole thing, one issue seems to be "it's only when you want to sequence these [IO actions] that you need the monadic interface", but that's all the time

11:27 clojurebot: Excuse me?

11:28 Pupnik_: honestly I didn't find LYAH that helpful

11:28 ToxicFrog: I can't think of a single program I've written where I either (a) only needed to do one IO operation or (b) had to do a bunch but didn't care what order they happened in.

11:28 Glenjamin: ToxicFrog: was that due to the structure of the solution, or the problem space?

11:28 sdegutis: ToxicFrog: my window manager might count, I plan to port it soon enough

11:28 Glenjamin: for example: consider implementing unix's sort

11:29 or even grep

11:29 99% of the program is not IO

11:29 implementation optimisations notwithstanding

11:29 Pupnik_: https://github.com/bitemyapp/learnhaskell good haskell resources

11:30 ToxicFrog: Glenjamin: right, but in the parts that are you often need some kind of ordering, or to use the results of one IO operation to decide what the next one should be

11:30 Which means you need do

11:30 Which means monads

11:30 Glenjamin: right, but only in that little bit

11:31 ToxicFrog: Right, but if you can't write that little bit, you don't have a working program!

11:31 Glenjamin: and as mentioned elsewhere, you can use data to describe the relationship between the actions, and have something else translate to IO

11:31 hyPiRion: ToxicFrog: a >>= b is "take the dirty IO value from a, polish it, and give it as a "pure" argument to b which then returns an IO type"

11:31 Glenjamin: yeah, but if you just use do notation, it looks like normal imperative code - assuming you're not mixing in other, wackier monads

11:31 ToxicFrog: In the comments the OP is also saying "you don't have to understand Functor or Applicative or Monad to use this, you just need to understand fmap, pure, bind, etc" but all of the explanations of what those do, how they work, and when to use them rely on understanding of Functor, Applicative, or Monad!

11:32 hyPiRion: hm

11:33 ToxicFrog: I tried to understand what they were by reading about them, gave up and just played with them until I understood what they actually were

11:33 Glenjamin: i dunno (if (= x 1) y z) is pure, and you can just fmap that onto any IO Int (i forget the real haskell syntax)

11:33 hyPiRion: *are

11:33 Glenjamin: if x = 1 then y else z

11:34 ToxicFrog: hyPiRion: I like understanding things by reading about them, especially in a language like haskell where not understanding them means I can't even experiment in the REPL because the type checker will reject everything I enter with messages I don't understand.

11:34 Glenjamin: i did nearly type that, but it seemed too psudeocodey

11:34 hyPiRion: *==

11:36 ToxicFrog: Maybe I'm just too used from Lua, Scala, and Clojure to being able to understand builtins by reading the reference documentation and source code for them.

11:40 Hijiri: I just think of IO as composable programs

11:40 ToxicFrog: Actually, question for the Haskellers in here, esp. Glenjamin and hyPiRion -- what's the deployment and GUI story like?

11:41 Like, with Clojure if I want to release a program 'lein uberjar' gives me a redistributable jar, and Seesaw gives me a native API for GUI programming. What are the Haskell equivalents?

11:41 Glenjamin: i'm not a haskeller i'm afraid - i just did some ages ago and went to an talk relatively recently where the IO penny dropped :)

11:41 Hijiri: Haskell is compled down, usually statically

11:41 Glenjamin: https://wiki.haskell.org/WxHaskell seems to exist, i dunno if wx is still popular

11:42 ToxicFrog: wx, the foremost test suite in C compiler error reporting~

11:46 SagiCZ11: under what circumstances does this throw Duplicate key: null exception?

11:46 (filter #(#{x y} %) coll)

11:47 Bronsa: ,#{nil nil}

11:47 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Duplicate key: null>

11:47 SagiCZ11: Bronsa: oh

11:47 Bronsa: ,(let [x nil y nil coll []] (filter #(#{x y} %) coll))

11:47 clojurebot: ()

11:47 Bronsa: ,(let [x nil y nil coll [1]] (filter #(#{x y} %) coll))

11:47 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Duplicate key: null>

11:47 Bronsa: ^there

11:48 SagiCZ11: Bronsa: thank you

11:54 clgv: SagiCZ11: you know that you do not need to wrap the set into a function right?

11:54 ,(filter #{2 5 9} (range 20))

11:54 clojurebot: (2 5 9)

11:55 SagiCZ11: clgv: yeah there was some more code in the function i just simplified it for the sake of this exampl

12:18 pdoherty: has anyone had issues with lein repl ignoring keypresses on os x?

12:19 it refuses to let me enter "("

12:20 crash_ep: ToxicFrog: GHC-compiled Haskell apps are native binaries, so the only "deployment" is whatever it takes to get the binary onto a machine that can execute that architecture, and exposing it somehow to be executed.

12:20 gfredericks: anybody know if there's a way to customize leiningen to look for local profiles in a specific file of the project?

12:20 I think it supports /profiles.clj or something to that effect

12:22 crash_ep: ToxicFrog: I'm not sure about 100% pure Haskell GUI apps. My understanding is that some GUI developers write a thin GUI in another language/framework (e.g., Swift/Cocoa) and then call into a Haskell library to "do work".

12:22 Though there are pure Haskell GUI bindings.

12:22 ddima_: gfredericks: yes, it can: https://github.com/technomancy/leiningen/blob/master/doc/PROFILES.md - ~/.lein/profiles and profiles.d/

12:22 crash_ep: (And then of course there are langauges like Elm)

12:23 ddima_: gfredericks: oh, misread your question

12:25 gfredericks: maybe you can just symlink the file in question to project-profiles.clj

12:25 gfredericks: ddima_: my goal is to not check this stuff into the project

12:26 but gitignoring that file either in the project or globally seems unideal

12:26 ddima_: gfredericks: but then you could use the user-local profiles location maybe (and maybe additionally symlink)

12:26 gfredericks: the what?

12:27 ddima_: well, ~/.lein/profiles.clj would be perfectly outside of your project, if you have clashing profile names for multiple projects, then maybe symlink to project location

12:27 that would be my attempt at quickly getting this out of the way ;)

12:28 gfredericks: but ~/.lein/profiles.clj is global, I'm thinking for project-specific stuff

12:31 I'll probably just monkeypatch leiningen.core.project/project-profiles

12:31 ddima_: hm, thought one could solve it with custom profile names, but well. then I guess .gitignore is the way to go, its also the way i've seen it done with almost any build system if "global" (user-wide) settings are not appropriate :/

12:34 for some project I also had some small script set up to switch ~/.m2 to a project specific location, but thats not too much fun

12:36 justin_smith: ddima_: wait, why would you need that? two different versions with the same pom?

12:38 gfredericks: I was hoping I could monkeypatch leiningen from my user profile but I suppose at that point it might be too late to affect profile lookup behavior

12:38 HMMMM.

12:38 ddima_: justin_smith: well, if was actually the settings.xml with different corporate repos/passwords, so I kept to repo/ but needed different * mirrors

12:39 gfredericks: it will probably turn out this is only possible with env variables

12:39 justin_smith: ddima_: ahh, OK

12:39 ddima_: justin_smith: but not really worth discussing, I have not invested much time figuring out if theres a cleaner way, I just needed it to work quickly ;)

12:39 muhuk__: I'm trying to make sense of indentation customization of cljfmt.

12:40 It says "You can also customize the indentation rules cljfmt uses.", but where do we put that map?

12:42 justin_smith: muhuk__: https://github.com/weavejester/cljfmt#configuration

12:43 muhuk__: justin_smith: that's where I was quoting from

12:43 justin_smith: "You can configure lein-cljfmt by adding a :cljfmt map to your project:"

12:43 it goes in your project.clj

12:44 muhuk__: justin_smith: keep reading

12:44 justin_smith: I read it, what's your question?

12:44 csd_: Can any of you recommend a resource for learning to write a threaded server application?

12:45 muhuk__: justin_smith: where do we put the map where we specify :inner & :block?

12:45 justin_smith: muhuk__: in your project.clj, you add a key :cljfmt and a map of options

12:45 muhuk__: justin_smith: like this https://github.com/weavejester/cljfmt/blob/master/cljfmt/resources/cljfmt/indents/clojure.edn

12:45 justin_smith: the key will be :cljfmt, and it should be followed by that map

12:45 in project.clj

12:46 do you understand how project.clj works?

12:46 muhuk__: justin_smith: so these symbol keys are mixed with the keyword ones? (:insert-missing-whitespace? etc.)

12:47 justin_smith: as far as I know, yes.

12:48 muhuk__: alternately, you could try shadowing resources/cljfmt/indents/clojure.edn within your own project

12:49 if the former does not work

12:49 muhuk__: justin_smith: I'm trying to make 'checker behave line 'defn

12:49 justin_smith: :cljfmt {checker [[:inner 0]]} doesn't work

12:50 justin_smith: OK

12:50 muhuk__: justin_smith: also tried with 1 instead of 0

12:50 justin_smith: also tried 'checker instead of checker

12:50 justin_smith: sometimes weavejester is around, but it appears he is not here now

12:50 muhuk__: still doesn't use 2 spaces

12:50 justin_smith: try creating your own copy of resources/cljfmt/indents/clojure.edn

12:51 which should be a modified copy of the version in the original project

12:51 that's the only other way I could see that being customized

12:51 muhuk__: justin_smith: thanks, but no thanks

12:52 I still expect these overrides to be under some keyword and not mixed with the other stuff.

12:54 justin_smith: muhuk__: AHA - reading the source, it looks for an :indents key

12:54 https://github.com/weavejester/cljfmt/blob/master/cljfmt/src/cljfmt/core.clj#L167

12:54 that's totally missing from the readme

12:55 should have just read the source in the first place, my apologies

12:55 muhuk__: justin_smith: why, thanks for your help

12:55 justin_smith: I was trying to find something in the lein plugin src

12:56 justin_smith: muhuk__: so, based on the source :cljfmt {:indents {...}} should be your option

12:56 hyPiRion: ToxicFrog: Deployment is rather easy with Cabal, but may take some time. Not done any GUI apps, but web apps are apparently alright

12:56 R0B_ROD: Hi

12:57 muhuk__: justin_smith: indeed it worked

12:57 justin_smith: thanks!

12:57 justin_smith: awesome, do you want to make that pr against the readme, or should I?

13:03 Jahkeup_: Is anyone having/had issues bringing up cider repl in Emacs?

13:03 I can connect but the repl doens't seem to open or connect

13:06 justin_smith: Jahkeup_: did you do a version upgrade recently?

13:06 Jahkeup_: today, I use quelpa to fetch HEAD

13:06 I was having the ns problem so I updated

13:06 justin_smith: you probably need to delete all your relevant elc files, and then restart emacs

13:07 this is a common issue with cider version upgrades

13:07 Jahkeup_: I did restart, but haven't removed the .elc..one sec ;)

13:07 justin_smith: yeah, you can end up with invalid compiled code very easily after an upgrade

13:09 Jahkeup_: justin_smith: I removed all versions of cider I had and reinstalled, its working

13:09 justin_smith: thanks a bunch!

13:10 justin_smith: Jahkeup_: np

13:10 SagiCZ11: uberjar creates two jars.. one is standalone and the other not.. whats the diffrence?

13:11 justin_smith: SagiCZ11: the standalone is the actual uberjar

13:11 SagiCZ11: its so big though

13:11 martinklepsch: when specifying a plugin dep in leiningen is that loaded as transitive dep when I'm using the lib: https://github.com/DomKM/silk/blob/master/project.clj#L24

13:11 justin_smith: SagiCZ11: yes, it has to contain all the code of all of your dependencies

13:11 so it will be big if you have a lot of deps

13:12 tcrayford____: (for the reference, Yeller's is 82MB)

13:12 SagiCZ11: justin_smith: i am using incanter so i guess it is a big dependency.. is there a way to just depend on a small part of that library?

13:12 justin_smith: SagiCZ11: not that I know of - you could try making your own stripped down fork with only the parts you use?

13:12 I bet its license would allow that

13:12 SagiCZ11: justin_smith: ok thanks.. not worth, let the bandwidth suffer

13:14 muhuk__: justin_smith: what I was talking about: https://github.com/weavejester/cljfmt/issues/4

13:14 justin_smith: muhuk__: interesting. I left this PR btw https://github.com/weavejester/cljfmt/pull/9

13:15 muhuk__: justin_smith: yeah, I saw that.

13:16 justin_smith: exciting lib/plugin, I'll definitely give it a try later

13:16 DomKM: martinklepsch: Hmm, yeah it looks like is being pulled in https://clojars.org/com.domkm/silk

13:16 martinklepsch: None of the other plugins are. I'm not sure why cljx is.

13:19 martinklepsch: DomKM: maybe try adding something like :scope "test"? I don't really know whats going on there so thats really an out-of-the-blue guess

13:20 DomKM: martinklepsch: Are you able to add cljx to exclusions for now?

13:21 martinklepsch: DomKM: it's not an issue for me, I just was surprised to see that happening

13:23 DomKM: martinklepsch: Cool, sorry about that. I'll look into it.

13:36 papachan: hi i am trying to use joda-time to get year-s date

13:36 but cannot get string format

13:36 always have a date object

13:38 justin_smith: papachan: so you want to get the date as a string?

13:38 papachan: i am trying this:

13:39 a basic example: http://paste.awesom.eu/raw/papachan/BLnr

13:40 R0B_ROD: Non-programmer here learning computer science (self-study)

13:40 justin_smith: papachan: that will print the value of our-formatter followed by now

13:40 papachan: you need to use joda/unparse

13:40 papachan: ah

13:40 justin_smith: (if clj-time.format is mapped to joda)

13:42 admittedly, "unparse" is a weird name for format

13:42 papachan: joda/print is not equivalent?

13:43 or joda/parse-date-time

13:43 justin_smith: well, the parse functions take a string and give you a date-time thing

13:43 I had assumed print in your paste was clojure.core/print

13:44 * justin_smith is off to write a lib with complementary unformat / unparse functions

13:47 TimMc: justin_smith: <3 unparse (as a name)

13:47 Atarian: Is there any way to save the changes you make in the REPL back to the source, or do you just copy and paste it back into emacs?

13:48 TimMc: I'd never thought of unformat but I like it now.

13:48 justin_smith: haha

13:48 (def undivide *)

13:48 (def unmultiply /)

13:50 Atarian: another option is to write your definitions in the source file and use C-M-x to send those definitions to the repl

13:51 Atarian: justin_smith: That's what I've been doing, it just seems too similar to the edit/compile

13:51 then swear cycle of C

13:51 :D

13:51 justin_smith: Atarian: M-h / M-w makes it easy to select and copy a balanced form all the way out to the top level

13:52 llasram: Atarian: Are you not using CIDER?

13:52 justin_smith: (M-h selects the whole form out to the top level, M-w copies the selection)

13:52 Atarian: Yes, I'm using Cider - I tend to use C-k to update the REPL

13:53 Glenjamin: i've found it tricky to balance writing code in the editor for saving, with interacting with that code quickly in the repl to try it out

13:53 Atarian: I wasn't familiar with M-w/M-h, I'll have a play with those thanks

13:54 Glenjamin: Me too, that's why I thought I might be missing something

13:54 Glenjamin: like, i'll send a defn to the repl

13:54 then call it a bit

13:55 maybe try some snippets

13:55 it feels weird to write the calls/snippets in the editor, but if i do them in the repl its slightly more work to get them back into the editor

13:56 Atarian: Glenjamin: Yeah, the REPL seems to have more potential than what I'm using it for

13:56 If that makes sense

14:23 sgg-: Hey, all. I'm going through the Seven Concurrency Models book and am a little hung up on the section dealing with reducers and protocols. I can't figure out how to determine which function gets called in a reify block. More specifically, why the three-arity gets called instead of the two-arity here: https://www.refheap.com/0b0d107ef29973a54fae68ad9

14:26 amalloy: sgg-: have you looked at the source for into?

14:26 $source into

14:26 lazybot: into is http://is.gd/caQYZB

14:26 amalloy: specifically https://github.com/clojure/clojure/blob/clojure-1.7.0-alpha1/src/clj/clojure/core.clj#L6471 which reads (reduce conj to from)

14:29 sgg-: ha, that explains it. I was looking at the protocols source and was just baffled.

14:39 hiredman: is there a clojure library for printin trees / graphs as ascii art?

14:42 amalloy: hiredman: you need ascii art, can't use eg rhizome?

14:44 hiredman: I dunno, I am just sort of brain storming about this thing I want, part of which will be a randomly generated tree, and it would be nice to print it out

14:44 lgrapenthin: hiredman: may want to try this https://github.com/drcode/vijual

14:44 hiredman: I was thinking a console type thing, but I guess I might as well give it a web interface

14:45 lgrapenthin: some example screenshots here http://lisperati.com/vijual/

14:45 hiredman: that name kind of hurts me

14:45 I mean, that is neat

14:46 that does look exactly like what I was looking for though

14:46 lgrapenthin: it seems pretty unmaintained. would love to hear about your experience with it.

14:48 amalloy: wow, that project.clj is like a time capsule

14:49 hiredman: oh, gplv3, that may be a hard sell

14:54 lgrapenthin: maybe you can take it as inspiration for a lgpl3 based project?

14:55 hiredman: or Conrad might be willing to release it under lgpl3

14:56 hiredman: could be, I am just sort thinking for the future

14:58 arohner: are there any good libraries for working w/ BDB?

15:01 justin_smith: http://www.oracle.com/technetwork/database/berkeleydb/overview/index-093405.html this bdb?

15:06 arohner: justin_smith: yeah

15:07 I'm still evaluating options though

15:07 looking for an embedded DB that can store somewhat arbitrary clojure maps

15:07 justin_smith: the licensing on that seems a bit onerous, I would expect that to reduce the chances that there is any clojure specific wrapper or util lib

15:07 arohner: so I'm hesitant to use SQL

15:07 mapdb is looking good

15:08 justin_smith: datomic is good at that :)

15:08 arohner: justin_smith: this doesn't seem that onerous? http://www.oracle.com/technetwork/database/berkeleydb/downloads/jeoslicense-086837.html

15:08 datomic doesn't support embedded operation

15:10 justin_smith: arohner: interesting, maybe I was finding out of date info about bdb licensing

15:10 arohner: yeah, I think a lot of the (reasonable) FUD came about after Oracle acquired SleepyCat, and then oracle didn't release any info about what they were going to do, so people got paranoid

15:11 gzmask: heya folks, if I use (take x (repeat (chan))) to generate x channels, are they x different channels, or are they x same channels? what if I do (for [a (range x)] (chan))?

15:11 justin_smith: gzmask: (repeat (chan)) returns the same chan over and over

15:11 try (repeatedly chan)

15:12 ,(take 10 (repeatedly rand))

15:12 gzmask: ah, thanks ... how about the for version?

15:12 clojurebot: (0.3777431544040436 0.8949146539323458 0.6030477173980103 0.13408026637948045 0.9454645144975672 ...)

15:12 hiredman: ,(doc repeatedly)

15:12 clojurebot: "([f] [n f]); Takes a function of no args, presumably with side effects, and returns an infinite (or length n if supplied) lazy sequence of calls to it"

15:12 justin_smith: gzmask: it would work, but I think (take x (repeatedly chan)) is much clearer

15:13 that's like, precisely the use case repeatedly was designed for

15:16 oh, of course (repeatedly n chan) would be even better (thanks for making me look at the doc string again)

15:16 (inc hiredman)

15:16 lazybot: ⇒ 67

15:22 moquist: reiddraper: Right now I'm using 'fmap to truncate items (strings, vectors, etc.) that are too large, but I assume 'clojure.test.check.generators is doing lots of work generating larger things that I then butcher. Is there a way to tell the generators something about the target size range?

15:23 reiddraper: I looked at all the 'size' related things, but it all seemed to be related to shrinking, and not user-specified target sizes. Maybe I'm missing something that should have been obvious...

15:24 muhuk: What's the most succinct way to do: (fn [f x _] (f x)) ?

15:24 #(f %) throw arity error, since outer function is called with 2 params.

15:25 Bronsa: #(% (do %& %2))

15:25 justin_smith: muhuk: wouldn't you want #(% %2) anyway?

15:25 (inc Bronsa)

15:25 lazybot: ⇒ 88

15:26 muhuk: justin_smith: you are right. Anonymous function is closing over f, my first form should've been: (fn [x _] (f x))

15:26 Bronsa: muhuk: then #(f (do %& %))

15:27 amalloy: muhuk: why is most-succinct important?

15:27 reiddraper: moquist: sizing is related to generation as much as shrinking, for many generators its use to cap the size of a collection, or at least serve as a linear-correlation to size, so i'd recommend defining a max-size function, something like: (defn max-size [g n] (gen/sized (fn [s] (gen/resize (min s n) g))))

15:28 muhuk: Bronsa: ha! I didn't know about %&, neat

15:28 amalloy: better than verbose

15:29 llasram: muhuk: I think what you had to start with is more legible; much more clearly describes your intent

15:29 amalloy: muhuk: #(f (do %& %)) is atrociously unreadable. just use a (fn ...)

15:29 density is not the utmost goal

15:30 muhuk: amalloy: yes, I'll go with the fn one

15:30 moquist: reiddraper: OK. Sounds like I just didn't grok it and need to re-read the code. Thanks for the fn suggestion; I'll try it out.

15:31 gfredericks: moquist: reiddraper: I think I have a cap-size in test.chuck

15:31 moquist: reiddraper: The more I think about that, the more it makes sense... shrinking involves targeting generation sizes, so... yeah. I should've realized.

15:32 gfredericks: cool. I will check that right now. :)

15:34 reiddraper: gfredericks: yeah cap-size is probably what you want, and actually, shrinking doens't adjust the size parameter, it's a separate process

15:34 cc moquist ^

15:34 gfredericks: I was wondering about that

15:34 moquist: reiddraper: [nod]

15:34 samiswellcool: I've tried writing a macro (my first) but have hit a bit of a wall...http://pastebin.com/YJ2td5EC

15:35 gfredericks: samiswellcool: you want ` instead of '

15:35 justin_smith: samiswellcool: ~ needs to be inside `

15:35 amalloy: samiswellcool: also why is this a macro instead of a function

15:36 samiswellcool: I've tried to write a macro (my first) and have run into a bit of a wall... my code: http://pastebin.com/YJ2td5EC

15:37 ah

15:37 eriktjacobsen: I think I’m going to print “Why is this a macro instead of a function” out and frame it near my desk

15:37 samiswellcool: my connection is bad so apologies for posting that twice haha

15:37 I'm not sure - I'm really trying to figure out where I'd write a macro for

15:38 muhuk: samiswellcool: perhaps quote with ` instead of '

15:38 gfredericks: samiswellcool: there's nothing wrong with not writing any macros

15:38 samiswellcool: but I wanted to write (tile :name "name" :property 5 ...) rather than (tile {:name "name" :property 5}) just to give it a go

15:38 justin_smith: samiswellcool: macros are good for when you need to create a unique syntax (or wrap / parameterize another macro)

15:39 muhuk: samiswellcool: when you call tile in some other namespace, it's trying to find a tile-validate in that ns, instead of what tile-validate refers to in tile's ns.

15:39 samiswellcool: gfredericks: I guess there's nowhere that I've seen that explains what they're useful for, mainly just places going 'woah, macros are so powerful'

15:39 justin_smith: muhuk: more fundamentally, ~ is illegal outside of `

15:40 samiswellcool: ah, I'll probably revise that decision then

15:40 muhuk: justin_smith: eh, I didn't see ' is quoting the list, not the symbol. right

15:41 gfredericks: samiswellcool: http://www.infoq.com/presentations/macros-clojure-west-2013

15:41 samiswellcool: cheers, I'll give that a watch

15:43 muhuk: AtomEditableWorld here https://github.com/muhuk/clecs/blob/master/src/clecs/backend/atom_world/editable_world.clj When I delegate like this, it's quite convenient when testing with Midje. You can't mock protocol methods, but you can fn's. Do you guys think this is *weird* code like this?

15:44 samiswellcool: and for now I've removed the macro and I'll just deal with passing a hash-map

15:44 muhuk: I'm considering inlining them.

15:44 samiswellcool: and suddenly my tests pass :)

15:44 thanks guys

15:58 timvisher: is there a function that lets me filter a map for values/keys that pass a predicate that returns the filtered map rather than a seq?

15:58 i'm aware i can easily write one but i have some vague memory of a function like that but i can't find it

15:58 justin_smith: timvisher: seems you could do it with reduce-kv

15:59 timvisher: justin_smith: that's just about it. :)

15:59 thanks

15:59 justin_smith: that would work by associating the keys you want, rather than filtering of course

15:59 R0B_ROD: Hello justin_smith :>

15:59 justin_smith: but should be pretty straightforward

15:59 R0B_ROD: hello

16:02 timvisher: so all that reduce-kv wins you is the avoidance of a single destructure…

16:03 `(fn [acc k v]…)` vs `(fn [acc [k v]]…)`

16:03 nic77: what are you making?

16:03 tbaldridge: and the allocation of a structure to hold the kv pair

16:03 so it's probably a tad faster

16:06 timvisher: nic77: i'm trying to write a graph traversal that's some approximation of A*. so i'm keeping my shortest known path from start to n in a map which is {[start n] shortest-known-path}. i'm then calculating the path from start to n' (a neighbor of n) by conjing on to the shortest known path [start n]. i'd then like to merge the new paths from n to n' but only if the new path is shorter than the current shortest path

16:08 so i calculate the new-path from n to n' and shove it all in a map {n' new-path}, and then i'd like to filter that map so that the paths that are longer than the current known shortest path are removed, and thus can i can just (merge known-shortest-paths new-paths)

16:08 which might all be the wrong approach. this is the first time i'm working with graph data structures directly at all so… :)

16:09 tbaldridge: i did think i noticed that

16:10 justin_smith: timvisher: you could consider using an adjacency list (not that it is hugely different from what you describe, but it is a well researched and documented graph representation that is friendly to immutable datatypes)

16:10 nic77: ok i dont know what all of that means yet but thankyou its gonna help someday

16:11 justin_smith: :)

16:11 nic77: whats it for essentially

16:11 justin_smith: nic77: you can learn a lot just by looking at the wikipedia pages for things people mention here - A* is quite well described

16:11 nic77: yeah i like wikipedia

16:12 justin_smith: nic77: A* is a graph algorithm for finding paths, it is used for monster movement in video games if the monster should be chasing the player, for example

16:13 nic77: theres not enough time or neurotransmitters for wikipedia the way i do it

16:13 timvisher: justin_smith: interesting. it looks like i accidentally stumbled on guido's suggested implementation of this. my graph is represented as {n1 [n1'…] n2 [n2'…]}

16:14 nic77: interesting, monster movements

16:14 justin_smith: timvisher: as in the python guy?

16:14 timvisher: and in this case, distance is a constant so i don't need to worry about that in the equation

16:14 justin_smith: indeed

16:14 celwell: Hi, regarding Compojure routes, how can I get both the uri segment and the entire POST body? How should I modify this: (POST "/reset-password/:key" {body :body}

16:14 timvisher: effort to traverse an edge is always 1

16:14 nic77: distance is a constant whats that saying

16:15 you dont have to set one?

16:15 timvisher: nic77: so in generalized graph theory (as i understand it), edges can either be constant or they can have weight

16:15 justin_smith: timvisher: yeah, the assoc of node to an array of adjacents is a natural choice I think :) It is good to know the name of the representation and know it is well researched

16:15 timvisher: so two nodes can be connected by an edge, and in the case of an unweighted graph you treat the edge as free

16:16 justin_smith: nic77: for a concrete example: what if one part of the area had a swamp (slow locomotion) and another was a paved path (fast locomotion) - that would effect what turns out to be the fastest route

16:16 timvisher: in the case of a weighted graph however, the edge can be of varying weights, and thus it has to come into play in your calculations as for as what the shortest path is

16:16 nic77: lol. what justin_smith said :)

16:16 nic77: oh sweet generalized graph theory, its got a name and all.

16:17 justin_smith: nic77: it's a huge and fascinating subject

16:17 timvisher: nic77: i enjoyed reading this http://theory.stanford.edu/~amitp/GameProgramming/index.html

16:17 nic77: ok,

16:17 weights? thats another explanation?

16:17 like a theory lol

16:18 cool, i dont want to pester too long i got some stuff to look at now thanks :D

16:18 justin_smith: they use "weight" as the generic name for the cost of each node - since there are many problems solvable with the same algorithm

16:18 hiredman: timvisher: have you looked at loom?

16:18 nic77: hmm

16:19 this is gonna be great

16:19 timvisher: so in the interest of my own brain i'm simplifying a* (i think) because my own problem is constrained in relation to the general problem of shortest-path graph traversal

16:19 hiredman: nope.

16:19 * timvisher $googles loom

16:19 timvisher: $google loom

16:19 lazybot: [Loom - Wikipedia, the free encyclopedia] http://en.wikipedia.org/wiki/Loom

16:19 nic77: im gonna go from one tab to the next and run out of memor

16:19 timvisher: $google loom clojure

16:19 lazybot: [aysylu/loom · GitHub] https://github.com/aysylu/loom

16:20 hiredman: loom is a graph library, the default graph implementation it has sounds similar to yours, and it has an A* implementation

16:20 https://github.com/aysylu/loom

16:21 timvisher: hiredman: ooo! that looks cool. all the other ones i found were jvm implementations and i'm on clojurescript here

16:21 nic77: like the time i looked at some element and it informed me of a thing that required me to learn another thing to understand it

16:21 then the next thing was the same way, i had to learn another thing to understand it

16:21 justin_smith: nice, I had forgotten about loom, and I think it might help me solve this issue that has had me stumped for a little while...

16:22 hiredman: ah, that still may require some porting work (I dunno if loom works in clojurescript)

16:22 nic77: untill the end of it all i knew everything there was to know about everything

16:22 timvisher: nic77: just push onto the stack ;)

16:22 nic77: then i went to bed, and heres today

16:22 justin_smith: nic77: pre-requisites will happen - but once you master a sufficient percentage amazing things can start to happen

16:22 nic77: yeah, its not daunting at all

16:22 timvisher: hiredman: not seeing anything so far that explicitly reaches for the jvm

16:22 nic77: not my first mountain climb hehe

16:22 timvisher: bah!

16:23 except they use clojure.data.priority-map

16:23 hrm…

16:23 tbaldridge: port it!

16:23 {blake}: I'm loading in two csses (hiccup.page/include-css), bootstrap and a custom one. When I load bootstrap, the response header contains a content-type while the local css does not.

16:23 timvisher: well, back to square one then :)

16:23 tbaldridge: but but but, there's _so much jvm_ in clojure.data.priority-map!

16:23 tbaldridge: :-D

16:23 celwell: Hi, regarding Compojure routes, how can I get both

16:23 the uri segment and the entire POST body? How

16:23 should I modify this: (POST "/reset-password/:key"

16:23 {body :body}

16:24 timvisher: i mean yeah, closure's got goog.structs.PriorityQueue but…

16:27 {blake}: celwell: I don't know but I usually put in some middleware and dump the entire request to figure that stuff out.

16:30 timvisher: tbaldridge: so what's the deal with porting clojure libraries at this point between clj and cljs?

16:30 is cljx still the state of the art?

16:30 this is twice now that i've not been able to do something because priority-map isn't in on cljs

16:30 it'd be nice to rectify that

16:32 does mark engelberg hang out in here?

16:32 nic77: that sounds familier whos that

16:33 arohner: instaparse guy

16:34 timvisher: nic77: he's implemented a bunch of stuff, but he's i believe the maintainer of priority-map

16:34 nic77: how the hell did i hear about him i wonder :|

16:36 {blake}: OK, none of my local js comes back with a "Content-type" tag either. Remote jquery, bootstrap both have the appropritae content-type settings, but local ones do not. I don't even get how that's possible.

16:37 Unless the response is coming from the remote server rather than ring.

16:40 moquist: reiddraper, gfredericks: My tests are faster now. A 14x improvement. Thanks!

16:45 {blake}: Aaand that's the answer. It's always middleware. That's my new motto.

16:50 cfleming: timvisher: I believe (but would be happy to be corrected) that cljx cannot be used for core libraries, since it's a non-core dependency.

16:57 atratus: soo if I build clojurescript locally does it automatically configure itself with leiningen?

16:58 texy: dot

17:01 dnolen: atratus: if you install locally into your Maven uses pom.xml, for boostrapping it uses some bash scripts

17:01 amalloy: timvisher: i don't think mark hangs out in irc. i've seen him once or twice maybe, but not regularly

17:06 atratus: ahh i needed to up my version in the project.clj. TY

17:06 groux: !

17:06 levabalkin: hi, I use a startup/user.clj file in a lein project to declare a function to reload the project (using clojure.tools.namespace). After reload I loose the function doc from the repl. How can I keep the original repl env everytime after reloading my project ?

17:07 justin_smith: levabalkin: to get doc back (among other useful functions) you can run (use 'clojure.repl)

17:08 levabalkin: justin_smith: can I automate that from my reload function ?

17:08 justin_smith: I assume tools.namespace is resetting the ns thouroghly, so you lose the implicit usage of clojure.repl for your starting ns in the repl

17:08 levabalkin: well, you can add that call to be run while inside the ns being redefined I guess?

17:09 I'm not sure of the finer details of how it's being reloaded

17:09 gfredericks: yet another reason to use lein-shorthand instead of preparing a special repl namespace

17:09 * gfredericks says without paying much attention to the context

17:11 levabalkin: justin_smith: it works by calling (use 'clojure.repl) after ns reload, thanks

17:11 stuartsierra: levabalkin: You can add :require [clojure.repl :refer [doc]] to the 'ns' declaration of your user namespace.

17:12 dsb: Can anyone tell me why this doesn't work? http://pastebin.com/AgUnBceL

17:12 stuartsierra: Usually clojure.repl gets referred in by whatever launches your REPL, but tools.namespace will remove those on reload.

17:12 E.g. clojure.main does it https://github.com/clojure/clojure/blob/05af4b52a474bc60d2eb931e388b302c14edc884/src/clj/clojure/main.clj#L162

17:13 dsb: It's telling me n is not a namespace and the app won't run :/

17:13 justin_smith: dsb: so you would expect (show 'foo) to run (display-module foo/info) ?

17:13 yeah, namespaces don't work that way

17:15 dsb: maybe something like this ##(get (.getMappings (find-ns 'clojure.core)) '+)

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

17:15 justin_smith: :P well it works in a real repl

17:16 elarson: does anyone know if circle ci supports badges like travis?

17:16 amalloy: justin_smith: notice you just looked up a symbol in a map, like you were saying yesterday nobody does

17:16 dsb: justin_smith: when I call (display-module foo/info) with foo being the namespace name it works

17:16 justin_smith: amalloy: indeed! good point

17:16 amalloy: ('+ (.getMappings (find-ns 'clojure.core)))

17:17 justin_smith: dsb: yeah, because x/y is a reader thing

17:17 dsb: putting a variable in place of x is different, and will fail

17:17 so you need to manually do the lookup

17:17 dsb: ah makes sense

17:18 thanks

17:19 justin_smith: ,('+ (ns-publics 'clojure.core))

17:19 clojurebot: #'clojure.core/+

17:19 justin_smith: dsb: that's probably the best way to do it ^

17:21 stuartsierra: (resolve-ns (the-ns 'clojure.core) 'conj)

17:21 ,(resolve-ns (the-ns 'clojure.core) 'conj)

17:21 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: resolve-ns in this context, compiling:(NO_SOURCE_PATH:0:0)>

17:21 stuartsierra: ,(ns-resolve (the-ns 'clojure.core) 'conj)

17:21 clojurebot: #'clojure.core/conj

17:21 stuartsierra: there we go

17:21 justin_smith: ahh, that's a good way too

17:37 kaiyin: https://gist.github.com/kindlychung/1b71b14e61ceed2ec869

17:38 sorry, wrong channel.

17:38 amalloy: holy cow kaiyin, ====? what language is this?

17:39 kaiyin: java.

17:39 amalloy: well it looked like java, but java doesn't have a ==== operator

17:39 kaiyin: ok. then it must be a typo in this book.

17:39 gfredericks: ,(defn ==== [x y] (and (= x y) (identical? x y) (== x y) (= (str x) (str y))))

17:39 clojurebot: #'sandbox/====

17:40 gfredericks: ,(==== 42 42)

17:40 clojurebot: true

17:40 kaiyin: gfredericks: very cool. :-)

17:40 gfredericks: ,(==== 42.0 42.0)

17:40 clojurebot: false

17:40 gfredericks: ^ protip

17:40 stuartsierra: ,(==== nil nil)

17:40 clojurebot: #<NullPointerException java.lang.NullPointerException>

17:40 stuartsierra: heh

17:41 gfredericks: seems poetically appropriate somehow

17:42 kaiyin: gfredericks: care to introduce this in clojure 1.7?

17:45 mikerod: when doing something like `(reduce-kv (fn [m k v] (assoc m (something k) (something v)) {} my-associative)`

17:45 should you use a (transient {}) as the seed

17:45 or does reduce-kv already do this efficiently

17:45 thiagowfx: why it is false? Round error?

17:46 justin_smith: thiagowfx: they are not identical? because they are not the same object

17:46 they are two different boxed doubles

17:46 amalloy: justin_smith: rather, two boxes around the same double

17:46 mikerod: I missed a paren too

17:46 justin_smith: amalloy: aha, thanks

17:46 mikerod: I meant `(reduce-kv (fn [m k v] (assoc m (something k) (something v))) {} my-associative)`

17:47 justin_smith: mikerod: I don't think it would be able to automatically insert a transient for you

17:47 gfredericks: I was reading about doubles last night and was surprised they were more complicated than I was expecting; I probably shouldn't have been

17:47 thiagowfx: justin_smith: ...this implies that 42 and 42 are the same object. Does clojure cache small integers, like python? (newbie here)

17:48 amalloy: thiagowfx: yes

17:48 well, java does. but i don't think it *promises* to - it's just an implementation detail

17:48 mikerod: justin_smith: oh yeah, then your reduce-step fn would have to be transient awar

17:48 That was a dumb question then I think :P

17:48 den1k: generating mock db result map using test.check. Randomness is great, however I need unique vals as ids. How?

17:48 amalloy: eg, (identical? 42 (Long. 42)) is false, because you're explicitly making a new box

17:50 gfredericks: den1k: I've actually done okay just relying on a huge ID-space, combined with no-shrink

17:50 den1k: another option that could work for you is fmapping with distinct-by

17:50 i.e., you just delete things with duplicate ids

17:51 den1k: @gfredericks okay, I will do that. Thanks!

17:51 gfredericks: distinct-by can be had via prismatic/plumbing

17:51 and elsewheres I'm sure

17:53 den1k: cool

18:27 tomjack_: I'm guessing #? can't be implemented as a tagged literal, say in the style `#?[:clj foo :cljs bar]` ?

18:28 justin_smith: tomjack_: why wouldn't that be possible?

18:28 amalloy: well tagged literals can't return 0 forms, or multiple forms

18:28 tomjack_: that's basically my question

18:28 ah

18:40 justin_smith: tomjack_: ahh, so you meant a particular implementation of #?, not just #? as a valid tag for a tagged reader in general

18:40 never mind then

18:44 tomjack_: I meant #? as in read-cond

18:46 I guess you don't need to return multiple forms?

18:46 but zero, in case no features match

18:47 oh and there's #?@

18:47 ok, thanks :)

19:20 alandipert: tomjack_, thanks for the expansion-passing style paper btw, read and enjoyed

19:21 tomjack_: I'm still not sure whether it's relevant

19:27 timvisher: cfleming: so is there any way to have a dual targeting library in core at this point?

19:27 i suppose there's core.async but they're two completely separate implementations?

19:28 hiredman: timvisher: outside of clojure core people can use cljx

19:28 inside of clojure core it seems like a pain to use anything outside of clojure core

19:30 https://www.youtube.com/watch?v=Ah9p8cqkTOg chas gave a talk about it

19:30 timvisher: (inc cemerick)

19:30 lazybot: ⇒ 17

19:33 timvisher: hiredman: is there a blog post version of that anywhere?

19:33 hiredman: no idea

19:43 retrogradeorbit: hi there peeps, I need help with advanced compilation

19:43 Im using audio, and including the w3c_audio.js externs from here: http://closureplease.com/externs/

19:44 and "AudioContext" is not munged

19:44 but... .decodeAudioData is

19:44 even though its defined on the object as a function in the externs!

19:44 example code is suuuper simple

19:44 (def audio-context (js/AudioContext.))

19:44 (.decodeAudioData audio-context "data" #(println %))

19:45 compiles to:

19:45 ;var zv = new AudioContext;

19:45 zv.Rd("data", function(a) { return fo.c(mh([a], 0));

19:45 });

19:45 zv.Rd is wrong

19:46 it should be zv.decodeAudioData

19:46 any ideas why the externs file is only HALF working?

19:48 hiredman: retrogradeorbit: my guess is you are not passing the right number of arguments

19:48 but I dunno

19:49 retrogradeorbit: ok so google closure compiler is aware of arity?

19:49 let me check

19:49 hiredman: I don't do much clojurescript, and have never had resounding success fighting with externs

19:49 retrogradeorbit: ah it does have wrong arity.

19:49 let me try

19:50 nope. didn't work

19:51 I mean its wierd, cause without the w3c_audio externs, AudioCOntext is munged

19:51 so the externs is working

19:51 but only partly

20:12 dnolen: retrogradeorbit: this might be a Closure type inference issue?

20:12 retrogradeorbit: what happens if you do that in a let binding or inside of a function?

20:13 retrogradeorbit: Closure needs a type annotation when at the top level it might be easy place for us to help out

20:13 retrogradeorbit: also probably something us to support via type hints

20:13 "If Closure needs a type annotation"

21:12 devn: Halp!

21:12 I upgraded cider and cider-jack-in is broken for me

21:12 It seems to connect successfully

21:12 but the interaction buffer is missing

21:13 justin_smith: devn: did you delete all the elc files and restart? someone else had the same problem today and that fixed it

21:13 devn: lemme try that

21:14 :(

21:14 error in process filter: let: Symbol's function definition is void: clojure-mode-variables

21:14 error in process filter: Symbol's function definition is void: clojure-mode-variables

21:14 maybe my clojure-mode is out of date

21:15 justin_smith: couldn't hurt to update that too

21:15 devn: and company, hey -- why not?! :)

21:18 justin_smith: well, it works now

21:18 justin_smith: cool

21:18 devn: but i keep getting this message that "the follow required nREPL ops are not supported: apropos classpath complete eldoc ..........."

21:18 "please install or update cider-nrepl 0.9.0-SNAPSHOT

21:19 but AFAICT im on latest

21:20 justin_smith: devn: maybe you need to force the snapshot update?

21:25 dnolen: just released Om 0.8.7 w/ new cljsjs.react dep

21:25 devn: justin_smith: i didn't have a 0.9.0-SNAPSHOT before this, so it definitely got pulled

21:25 dnolen: nice!

21:26 gfredericks: ,(set! *allow-unresolved-vars* true)

21:26 clojurebot: #<IllegalStateException java.lang.IllegalStateException: Can't change/establish root binding of: *allow-unresolved-vars* with set>

21:26 devn: ,*clojure-version*

21:26 clojurebot: {:interim true, :major 1, :minor 7, :incremental 0, :qualifier "master"}

21:40 munderwo: Hi all. I have a number of concurrent threads that all accept events, I would like to be able to get an ordering of which events happen, so I can tag them and later reconstruct the ordering, I think like a vector clock. I just need an incrementing integer really. Should I be using atoms or agents or refs for this? or something else?

21:41 stuartsierra: munderwo: An atom should be sufficient, or a java.util.concurrent.atomic.AtomicLong if you want.

21:42 munderwo: so I should just be able to do (swap! atom inc)? I thought that might be able to do it, but wasnt sure if I was mixing up atoms an agents

21:43 rhg135: munderwo, ya that'll work

21:43 munderwo: Is there something about atoms that the function can be possible run twice? so you could double inc?

21:43 rhg135: also see clojure.lang.RT/nextID i think it was

21:43 justin_smith: munderwo: if it has side effects, the side effects can happen twice

21:44 munderwo: but it will happen such that the resulting value reflects each inc only happening once

21:44 munderwo: the retries are not an issue as long as the effects of the function run are fully reflected in the value of the atom, and not as side effects

21:45 munderwo: right, so for every event I get in I inc the counter. My counter isnt guaranteed to be 10 but it is gaurenteed to only hand out 10 numbers?

21:45 justin_smith: munderwo: if it has been swap! ed via inc 10 times, it is guaranteed to be 10 if it started as 0

21:45 if two of the incs happened at the same time, one would have to retry, that is what makes it atomic

21:46 otherwise an inc could be lost (this is more realistic with a more cpu heavy calculation than an increment, of course)

21:46 kenrestivo: as anyone ever done a count of exactly how many clojure SQL DSL's there are.

21:46 munderwo: ahh, so say 7 and 8 came in at the same time, 8 would retry and still get 8, as would 7?

21:46 well I mean 7 wouldnt retry

21:46 justin_smith: munderwo: 7 or 8 do not come in

21:46 munderwo: inc and inc come in

21:47 munderwo: right, sorry I meant the 7th and 8th event come in.

21:47 justin_smith: and swap! incs, then ensures no other operation happened in the meantime

21:47 munderwo: cool. I think that gets as close as I can get to what I want while still having multiple threads :) Thanks for the help!

21:47 justin_smith: so if the 8th inc happens before the 7th inc commits, the eighth would retry, yes

22:06 Jaood: dnolen: where are cljsjs jars hosted?

22:14 dnolen: Jaood: Clojars

22:15 zacts: hellofunk: I found a good book for me to study http://mitpress.mit.edu/books/computability

22:17 and http://mitpress.mit.edu/books/outer-limits-reason

22:28 http://mitpress.mit.edu/books/musimathics

22:28 ^ and volume two of this book looks cool for representing audio in clojure

22:28 tomjack: dnölen: I presume it is unreasonable to expect this to complete quickly? https://www.refheap.com/fde7e947be7437979924d239f/raw (note, looks like noms and ties, but it's not, I took the noms and ties out while trying to understand the slowness)

22:30 amalloy: tomjack: when did dnolen acquire a diaeresis?

22:30 tomjack: when I didn't want to ping them :/

22:31 sujeet: didn't work too well

22:31 kbp: tomjack: what does that script do?

22:31 tomjack: it does reification of a tree with lvars in it

22:33 the present purpose merely being to replace "<lvar:26647>" in the printed representation with "_0" etc

22:36 nothing jumped out after sampling with yourkit

22:37 kbp: tomjack: thanks for explanation

22:59 tomjack: hmm, I guess nrepl-ritz is not easy to set up these days?

23:01 kbp: I am playing with cider-nrepl. just a rookie tho

23:04 tomjack: I use cider-nrepl, but am looking for a debugger

23:04 * tomjack restarts intellij 4 times to install cursive

23:57 tomjack: hmm, I notice that, stopping at a random point, one of the lvars which only occurs once in the term has been clojure.core.logic/walk*'d 624 times

23:57 I guess it has to recur into subterms over and over

Logging service provided by n01se.net