#clojure log - Nov 14 2014

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

2:35 cosmicexplorer: test

2:35 TEttinger: mic check, 1, 2

2:36 cosmicexplorer: we're good to go

2:36 TEttinger: welcome to clojure, here's some bots. ##["lazybot"]

2:36 lazybot: ⇒ ["lazybot"]

2:36 TEttinger: ,"clojurebot"

2:36 clojurebot: "clojurebot"

2:56 godd2: "redbot, standing by"

3:06 amalloy: neat, i didn't know that M-q takes a prefix argument to justify the text

4:04 engblom: Where should I look if I want to make simple clickable 2D graphics with Clojure for Android mobile devices?

4:04 A nice sample project to look at would be nice and of course some reference material to check up things.

4:14 sm0ke: well said justin_smith

4:23 m00nlight: When I use some clojure code in an java project using storm, it seems conflict of clojure.core/some? with backtype.storm/some?, does anyone have sollutions?

4:24 Glenjamin: m00nlight: see the example on https://clojuredocs.org/clojure.core/refer-clojure

4:27 m00nlight: Glenjamin: Thanks, I will have a try right now

4:27 sm0ke: m00nlight: you will still get that warning

4:27 unless you are willing to compile and edit storm code

4:29 TEttinger: engblom: I know libgdx works on android, and play-clj is a wonderful clojure binding to that library, but I don't know how well clojure in general runs on android

4:34 $google play-clj

4:34 lazybot: [oakes/play-clj · GitHub] https://github.com/oakes/play-clj

4:34 TEttinger: ^ engblom

4:35 m00nlight: sm0ke : but in fact it cause a exception

4:35 TEttinger: "The mobile support is currently experimental, and may have poor performance or even fail to run on some devices." That mainly refers to iOS, which has been trouble to perform well on even for the main lib in java

4:35 m00nlight: sm0ke:

4:35 java.lang.IllegalStateException: Attempting to call unbound fn: #'backtype.storm.util/some?

4:35 at clojure.lang.Var$Unbound.throwArity(Var.java:43) ~[clojure-1.6.0.jar:na]

4:36 sm0ke: ,(doc some?)

4:36 clojurebot: "([x]); Returns true if x is not nil, false otherwise."

4:37 m00nlight: sm0ke: I already exclude the some? in core

4:37 (doc some?)

4:37 clojurebot: "([x]); Returns true if x is not nil, false otherwise."

4:37 m00nlight: nil

4:38 TEttinger: did you then include backtype.storm ?

4:38 I guess the word is require or use

4:38 sm0ke: ah nice catch TEttinger

4:38 m00nlight: what are you trying to do?

4:39 m00nlight: Very simple code implement in clojure for some other Java program to use in storm

4:39 TEttinger: m00nlight, do you want to call storm's some? or your own some?

4:39 sm0ke: run storm of clojure 1.6 is not possible unless storm updates it

4:39 TEttinger: or clojure's some? i mean

4:39 m00nlight: TEttinger: So I need to use an old version of clojure?

4:40 TEttinger: 1.5 isn't that old, actually...

4:40 sm0ke, do you think 1.5 will work?

4:40 sm0ke: yes

4:41 storm has updated to 1.5

4:41 m00nlight: sm0ke: OK. Thanks, I will try to use clojure 1.5 instead

4:49 sm0ke: TEttinger: Glenjamin: Thanks very much, problem solved :)

4:49 TEttinger: woo

4:49 (inc sm0ke)

4:49 lazybot: ⇒ 7

4:51 sm0ke: storm is notorius with respect to clojure compatibility

4:52 mnngfltg: Vim users rejoice! I've created an "alternate star": https://www.refheap.com/93358

4:53 So you can move your cursor over a namespace and hit `_` to cycle through all uses of that namespace in your code.

4:53 sm0ke: and i am not sure where if that code style does any good

4:54 TEttinger: is that vimscript, mnngfltg?

4:54 mnngfltg: tettinger yes I think :)

4:55 TEttinger: that's _ in non-insert mode, right? :)

5:09 whodidthis_: how does one eval just a single line or symbol in fireplace

5:11 mnngfltg: Tettinger, right

5:12 whodidthis_, a single form (the one under the cursor): `cpp`

5:13 whodidthis_: what if i just want to see what is up in a symbol without writing (println mythingie)

5:15 engblom: TEttinger: Thanks!

5:15 whodidthis_: return contents of mythingie without writing println around it i mean

5:16 engblom: I thought (or ...) was always taking the arguments in order.

5:26 (first vector) will give the first element rather than using (nth 0 vector). Is there a similar thing for changing the first element rather than using (assoc vector 0 value) ?

5:28 sm0ke: ,(cons 0 (rest [1 2 3]))

5:28 clojurebot: (0 2 3)

5:29 engblom: sm0ke: the same long as (assoc [1 2 3] 0 0)

5:29 ,(assoc [1 2 3] 0 0)

5:29 clojurebot: [0 2 3]

5:30 sm0ke: engblom: thats pretty short imo

5:30 engblom: Maybe there is not a ready function for changing the first element and this is how it is done normally

5:31 ,(nth [1 2 3] 0)

5:31 clojurebot: 1

5:31 engblom: ,(first [1 2 3])

5:31 clojurebot: 1

5:32 engblom: What I meant is that in the same way as (first ...) is more elegant than (nth ...) for getting the first element, I was wondering if there is more elegant ways for changing the first rather than refering with an index.

5:34 hyPiRion: engblom: no, but if you use the list/vector as a stack, you can use pop, conj and peek

5:35 ,(conj 0 (pop (list 1 2 3)))

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

5:35 hyPiRion: ,(conj (pop (list 1 2 3)) 0)

5:35 clojurebot: (0 2 3)

6:25 dysfun: hrm, is there something in ring.middleware.session i've missed for setting how long the cookie will be valid? i see the cookie options but those don't appear to take functions, in which case how can i provide a DateTime (which it requires for Expires:) when it's a middleware?

6:26 i'm using the cookie store

7:21 is there an idiomatic way to rethrow an exception, adding extra information?

7:22 preferably one that might reasonably be understood by timbre so there's helpful information in the logs

7:24 clgv: dysfun: only the java way. you can wrap the exception in a new one and throw that one or just throw the current exception

7:24 hyPiRion: you can bounce with ex-info tricks. Lemme make a macro/function for that

7:25 dysfun: :)

7:27 * dysfun is quite pleased with this middleware. It adds the user id to any exceptions it catches and rethrows it (and shortly, adding more info in the process) so it can be caught by the logger, which in dev prints a stacktrace and in production does timbre/error

7:32 hyPiRion: dysfun: https://www.refheap.com/93366

7:32 Not sure how that works with timbre, but you can add data to the exception like this

7:34 actually, this is a bit better: https://www.refheap.com/93367

7:34 dysfun: hrm, i'm not guaranteed to be getting an ExceptionInfo though. I'd like to catch Exception more generally and then turn that into an ExceptionInfo

7:34 hyPiRion: multiple clauses.

7:34 Oh.

7:35 Well, you can add another catch for Exception afterwards, and let the map be an empty one

7:36 There, I updated it to do just that. Same link as latest

7:36 dysfun: I suppose in those cases, I can just create a new one, putting the original exception in the map of info. It's not ideal, but i can postprocess it

7:37 hrm, the colour scheme on refheap is quite nice on the eyes

7:38 hyPiRion: thanks for the help

7:38 hyPiRion: dysfun: no problem, hope it's useful for you

7:39 dysfun: :)

7:39 * dysfun sticks that in his util.macros

7:48 dysfun: hyPiRion: also why is it that so often the problem that makes people understand why macros are special involves exceptions? Are they really more tedious in most languages? I've never thought so.

7:48 well, no more than other things

7:52 hyPiRion: dysfun: Well, most things macros are used for is control flow related. Either through looping (dotimes, doseq) or exceptions. Most other things can just be solved by functions

7:53 dysfun: yeah. i find the lack of first class anonymous functions and closures to be much more annoying

7:56 hyPiRion: I feel that persistent data structures and functional programming matters more, but I suppose that's because most of the useful macros are already included in Clojure

7:58 dysfun: yes, i'm liking them both a lot. i found it very hard to program an imperative language recently after about 6 months of almost full time clojure

7:58 a lot of my imperative code has smelled functional for years though

7:58 (damn you, elisp!)

7:59 hyPiRion: hah – for me it was a lot harder to transition. Took a lot of time to unlearn mutable data structures.

8:02 dysfun: yes, i admit i struggled with that at first

8:02 but i've come to prefer it

8:03 but i used to program a lot of perl, which has map and grep built in

8:03 hyPiRion: me too – much easier to work with after the struggle was over

8:53 sveri: Hi, anyone here using clara (rule system) and knows how to generate rules on the fly?

9:07 Or can I somehow create namespaces on the fly in clj / cljs and add rules and whatever to it to evaluate it in memory then?

9:12 hyPiRion: sveri: yeah, you can create namespaces on the fly in clj. Not sure how clara works, but I wouldn't be surprised if you could make "anonymous" rules on the fly.

9:15 sveri: hyPiRion: thanks, something more to read about :-)

9:54 zand`: Anyone using the debugger in cursive clojure? I can't seem to get it to stop at a breakpoint in a very simple test.. :-/

10:04 gfredericks: ,'ping

10:04 clojurebot: ping

10:17 justin_smith: $ping

10:17 lazybot: justin_smith: Ping completed in 0 seconds.

10:25 gfredericks: ~ping

10:25 clojurebot: PONG!

10:41 puredanger: idle Friday question - one change as a side effect of proposed changes in http://dev.clojure.org/jira/browse/CLJ-1546 is that vec would no longer guarantee a new vector instance. If passed a vector, it would simply return it. I imagine that 99.9???% of users would benefit from this change in meaning (by saving 100+ ns every time this is done).

10:42 Does anyone know of a case where a library actually relies on this "new vector instance" behavior? it would have to be something where identity is important (not just equality)

10:42 justin_smith: puredanger: going on intuition alone, I would have naively assumed vec already did that

10:42 puredanger: http://crossclj.info/fun/clojure.core/vec.html might jog your memory

10:42 justin_smith: (inc crossclj)

10:42 lazybot: ⇒ 3

10:42 puredanger: justin_smith: agreed. I'm looking for the odd duck here.

10:42 (inc crossclj)

10:42 lazybot: ⇒ 4

10:42 puredanger: for sure

10:42 I have been regularly using it to answer questions like this

10:44 verma: is this also the place for clojure-clr? or is there a dedicate channel for it?

10:44 justin_smith: hmm - I'll add a crossclj lookup plugin to my "lazybot nice to have" list - seems it would be straightforward to do

10:44 puredanger: verma: questions welcome here, not sure if there is a separate channel

10:44 EvanR: puredanger: if anyone is relying on something like that, they deserve to get broke by this ;)

10:45 verma: puredanger, sure thanks :)

10:45 justin_smith: EvanR: well the docs did explicitly say it would always make a new vec

10:45 puredanger: EvanR: I somewhat sympathize with this. I think Rich is on board with that too.

10:45 EvanR: the ideal of referential transparency and all

10:45 puredanger: justin_smith: the docs will change

10:45 EvanR: justin_smith: yurg

10:46 justin_smith: puredanger: right, just my 2¢ regarding "anyone who expected it deserves breakage"

10:46 puredanger: this is definitely a semantic (potentially breaking) change in behavior, but one that I think is extremely subtle

10:47 stuartsierra: I would be surprised if it broke anything.

10:48 puredanger: agreed, just trying to uncover that surprise early :)

10:49 I've looked through many usages found in crossclj and I have a hard time finding anything that relies on this "new" behavior

10:50 Bronsa: (inc crossclj)

10:50 lazybot: ⇒ 5

10:51 kungi: (inc crossclj)

10:51 lazybot: ⇒ 6

10:55 EvanR: whoever decided that and then decided it needed to be documented as such also deserves breakage

10:55 creative destruction

10:57 puredanger: one possible use case for old behavior would be to ensure the removal of meta

10:57 ,(meta (vec (with-meta [1 2] {:foo "foo"})))

10:57 clojurebot: nil

10:57 EvanR: what is meta :(

10:58 TimMc: yuck

10:58 puredanger: metadata

10:58 EvanR: very powerful

10:58 is metadata mutable?

10:58 TimMc: EvanR: with-meta attaches metadata to certain Clojure objects (gives you back a new object); meta retrieves it.

10:59 puredanger: collections generally retain meta through collection functions

10:59 sequence functions generally do not retain meta

10:59 (since they convert the coll to a seq)

11:00 TimMc: EvanR: When you see something like ^{:foo :bar}, that's attaching metadata to the next form for the benefit of the compiler.

11:00 edw: Speaking of crossclj, it's sketchy how it makes it so difficult to click out to wherever code originates from. It's like it doesn't want you to leave the site.

11:00 A more prominent link would be an important act of good faith.

11:01 TimMc: You think it's intentional?

11:01 puredanger: I don't think it's sketchy. just a lot of stuff on those pages :)

11:01 bbloom: ,123

11:01 clojurebot: 123

11:01 justin_smith: edw: no matter what you are trying to do, crossclj is a little confusing

11:01 puredanger: exactly :)

11:01 justin_smith: edw: they just need a UX overhaul

11:02 edw: TimMc: I have no idea whether it's intentional. But pretty every other similar resource makes it relativly easy. justin_smith, you're right; I should not ascribe to malice what's more easily explained by UX breakage.

11:03 justin_smith: edw: if they were serving any ads I may feel differently - but what do they gain from your page view?

11:04 edw: justin_smith: I hear you; some people (not saying the CrossClj folk(s), see above) are just greedy for people's attention.

11:05 The (old) Google ethos--get em in and out as quickly as possible--is not shored by most people.

11:05 s/shored/shared/

11:06 puredanger: so, vec could return essentially the same vector sans meta and it would at least be constant time 

11:06 justin_smith: edw: also, gmail is like the opposite of that

11:07 bbloom: puredanger: that would also produce a new identity

11:07 puredanger: yes

11:07 justin_smith: puredanger: that likely solves everything except folks who were exploiting array aliasing - and THEY deserve breakage I think

11:07 puredanger: justin_smith: I don't care about that

11:08 justin_smith: good

11:08 puredanger: I would happily break that :)

11:08 new patches hitting master right now, btw

11:08 including CLJ-1529 which has the Class.forName() improvement in it

11:08 stuartsierra: Brace yourselves, people.

11:09 puredanger: https://github.com/clojure/clojure/commits/master

11:10 * EvanR flies away from exploding terminal

11:12 clj-learner: hi, i'm learning neo4j with neocons, how do i vizualize a path in my application?

11:15 TimMc: puredanger: You think vec *should* strip metadata?

11:15 puredanger: it does now and someone might rely on that

11:16 TimMc: You think that's a more likely case than relying on identity changing?

11:16 puredanger: yes

11:16 bbloom: TimMc: definitely

11:16 puredanger: but it would also address that case

11:16 owengalenjones: in cljs, if Im using an external library do I need to *both* declare it in :cljsbuild :compiler :externs AND include it in a <script src = > tag?

11:17 TimMc: huh

11:17 dc_: in multimethod dispatch based on class, how do i specify that

11:17 edw: justin_smith: The Marissa-Mayer, Google-as-search-engine part of the company's history was dominated by the sort of thinking I described. It's well suited to things like the Grimoire, CrossClj, MELPA.

11:17 justin_smith: dc_: specify class as the dispatch function

11:18 dc_: i want a different method dispatched for a collection of chars vs a collection of integers

11:18 justin_smith: dc_: or use a protocol - they do that, and have better performance

11:18 dc_: justin_smith: sry hit send early

11:18 k, i'm aware of protocols and their power, but haven't used them yet, except in clojure koans

11:19 stuartsierra: dc_: That's not a class, you would need a dispatch function like (fn [coll] (type (first coll)))

11:19 justin_smith: ,(map (comp class first) [[] [1] "a"]) ; dc_

11:19 clojurebot: (nil java.lang.Long java.lang.Character)

11:19 Bronsa: wow, t.a.jvm loads noticeably faster with clj master than with clj 1.7.0-alpha3

11:21 justin_smith: dc_: yeah, for dispatch based on item type a protocol wouldn't help really, but you could use a dispatch function that checks the type of the first item

11:22 puredanger: Bronsa: yes, expect more of that :) doesn't help every project, but it does help in many cases, macro-heavy projects in particular.

11:31 EvanR: can i dynamiclly instantiate a java class that i have in a variable

11:31 can i even have java classes in a variable

11:31 ,(let [x java.lang.Long] x)

11:31 clojurebot: java.lang.Long

11:32 EvanR: ,(let [x java.lang.Long] (new x))

11:32 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: x, compiling:(NO_SOURCE_PATH:0:0)>

11:32 Bronsa: EvanR: no, you need reflection to do that

11:33 EvanR: core.incubator has a function for that

11:33 new-from-string or something similar

11:33 EvanR: hmm

11:33 hyPiRion: you can wrap them in functions as well

11:33 Bronsa: https://github.com/clojure/core.incubator/blob/master/src/main/clojure/clojure/core/incubator.clj#L76

11:33 new by name

11:33 EvanR: ok

11:43 donbonifacio: I have autotest running, after some full test runs (about 30), I start to get out of memory exception. Isn't it weirf?

11:43 - /s/weirf/weird

11:43 sdegutis: Seems normal to me.

11:44 donbonifacio: what about the GC? isn't it working? should I expect this kind of behaviour in prd?

11:44 sdegutis: Clojure is still young, and most libraries are ad-hoc and written just to get the job done for the author.

11:44 So expect to see lots of room for improvement all around.

11:45 justin_smith: donbonifacio: running out of heap, or permgen?

11:46 if heap, something in your test is holding onto data it does not need, if permgen, use a newer jvm that doesn't segregate permgen, or turn on permgen gc (it is often off by default)

11:46 donbonifacio: java.lang.OutOfMemoryError: unable to create new native thread

11:46 Bronsa: sdegutis: that's not true at all

11:46 technomancy: s/Clojure/the field of computing/

11:46 TimMc: *tools

11:46 justin_smith: donbonifacio: are you creating threads in your tests?

11:46 sdegutis: Bronsa: Well maybe you and I are using different libraries.

11:47 But the ones I'm using seem to break all the time.

11:47 donbonifacio: justin_smith: I'm testing pedestal, and making several requests to test the public rest api

11:47 justin_smith: donbonifacio: in the test teardown, are you properly shutting down the pedastal instance?

11:47 donbonifacio: noooo

11:48 I'm not doing anything like that

11:48 didn't know I had to, I confess

11:48 justin_smith: donbonifacio: so, to be clear: your test starts up pedastal, runs a few requests against it, and leaves it running?

11:49 ohpauleez: Or are you using Pedestal's testing `response-for`?

11:49 donbonifacio: yes, I have autotest running, and it reloads every thime. I don't know if it reloads pedestal

11:49 Bronsa: sdegutis: I don't see how you can go from "the libraries I use have bugs" to "most clojure libraries are ad-hoc and wrotten just to ghet the job done for the author"

11:49 sdegutis: Bronsa: Well sure, if that was all there was to it.

11:49 stuartsierra: Bronsa: I'll go there.

11:50 donbonifacio: ohpauleez: response-for

11:50 justin_smith: donbonifacio: does the test code start up pedastal, or does it assume pedastal is already up and running?

11:50 sdegutis: Bronsa: But experience fills in the missing context.

11:50 ohpauleez: donbonifacio: Ahh, so there's no running Pedestal. Are you doing a POST in any of the endpoints?

11:50 donbonifacio: I don't start pedestal, I use response-for

11:50 some POSTs and PUTs

11:50 a lot actually

11:50 justin_smith: oh, OK, I misunderstood that part

11:51 ohpauleez: donbonifacio: Do you store or hold onto the results to compare them across multiple tests?

11:51 justin_smith: donbonifacio: I would try profiling, to see what is being leaked each time the tests run. the jdk comes with jvisualvm which should suffice for this

11:51 ohpauleez: I've personally never heard of this happening, just seems like you're creating some data somewhere and never letting it go (you're always keeping a reference to it)

11:52 donbonifacio: ohpauleez: nop, each test is independent. But sometimes tests perform several requests

11:52 ohpauleez: it could also be the autotest runner

11:52 justin_smith: donbonifacio: ohpauleez: either way a profiler should likely catch it

11:52 ohpauleez: donbonifacio: Yeah, the multiple requests thing should be ok. I do that across a lot of Pedestal projects (and within pedestal itself)

11:53 donbonifacio: Yeah, if you just use jvisualvm, or whatever you have on hand, you'll see what's holding on to data

11:53 donbonifacio: ok, i'll try to use it, and if I find something and get back to you ohpauleez

11:53 ohpauleez: Also, feel free to bounce into #pedestal if you have any specific questions. Always more than happy to help!

11:53 Thanks! I appreciate it

11:54 justin_smith: donbonifacio: one thing to look for is in the threads panel, if it is creating new threads each time the tests run that maybe don't get disposed of

11:55 donbonifacio: kay thanks, never used it before, will play with it

11:55 btw, anyone using VIM? still can't find a nice workflow

11:56 engblom: donbonifacio: I am using vim, but I have a bit of the same problem.

11:56 ohpauleez: donbonifacio: I'm also using vim

11:56 I love my workflow

11:56 :)

11:56 donbonifacio: how's your workflow?

11:57 engblom: ohpauleez: Would you mind making a tar.gz of your setup? Or putting it on github?

11:59 ohpauleez: I use Pathogen. And then these: Paredit, fireplace, Ack, gundo, classpath, clojure-highlight, clojure-static, dispatch, leiningen, projectionist, surround

11:59 In my tmux, I split horizontally, and my lower pane is tiny. It runs a repl

12:00 From there I mostly only `cpp` and `cpr`

12:00 donbonifacio: how do you reload the code on the repl?

12:00 ohpauleez: I always have a `(comment )` block in the file I work in, to try things out

12:01 cpr

12:01 donbonifacio: reloads all or just the current file?

12:01 ohpauleez: requires-reloads current file (to my knowledge) and runs any tests present.

12:02 donbonifacio: one thing I like on my ruby workflow, is that I can run a test, and then go to other files make changes and run that test again.

12:02 ohpauleez: Why do you need to reload all? You just `cpr` when you make a change

12:02 donbonifacio: hum

12:02 yes, you're right ohpauleez

12:07 andyf_: Bronsa: So, I?m finally changing Eastwood?s suspicious-expression linter to use asts rather than source forms, so it is no longer giving incorrect warnings for things like (-> 1 (= 1))

12:07 Except for keyword typos, I think it is the last one that doesn?t use asts

12:09 I?m now hitting what should have been predictable: nested macro calls inside things like defrecord expansions that contain things that issue warnings, and/or with > 1 arg contain in their expansion a 1-arg and/or that warns if I don?t prevent it somehow, same for cond, etc.

12:10 My current plan is to add in checks for these cases by looking in the ancestor nodes of the ast for context that says "oh, that one is normal and shouldn't warn because it was expanded from foo". If you happen to think of a cleaner way, I'd be interested to know.

12:10 but I'm content going down this path if we don't think of anything better

12:14 justin_smith: andyf_: it seems like there would be a lot of constructs that would be a likely error at the top level of code, but be present expansion of a well-made macro

12:16 andyf_: Sure, but I can't think of a precise definition of "the top level of code" that doesn't eliminate checking inside macros you write yourself.

12:16 mdrogalis: tbaldrid_: re mailing-list: I'm not saying I agree/disagree with you about feature expressions being in core, but I find it funny that we sometimes argue that larger things should be in core 'because it would be convenient', and we use the exact opposite argument about adding very small things to clojure.core.

12:16 tbaldrid_: how is this a large change/

12:16 ?

12:16 justin_smith: andyf_: yeah, that's tricky

12:17 mdrogalis: tbaldridge: Feature expressions?

12:17 andyf_: justin_smith: Hmm. Perhaps "if the last macro expanded to get here was in clojure.core, then don't warn for it"

12:17 tbaldridge: if file.endswith(".clj") or file.endswith(".cljp") { load(file)}

12:17 mdrogalis: tbaldridge: That's really all there is to it?

12:17 tbaldridge: The approach I advocated isn't really feature expressions at all, it's just a new "portable" file extension.

12:18 mdrogalis: Yeah, I got'cha. I guess I'm mis-remembering some things from the last time I read the feature-expressions design doc.

12:18 tbaldridge: you put cross-platform code in the new file type, everything platform specific goes in .clj, cljc, or .cljs

12:18 yeah, it's changed alot recently

12:18 And some people like cfleming chimed in saying that anything that modifies the guts of the reader is going to be super hard for tools to figure out without evaling the namespace or something.

12:19 mdrogalis: tbaldridge: Ah, ignore my comment then.

12:19 tbaldridge: Now I have no say in the final approach Clojure takes here, it's just worth pointing out that not every variant of "feature expressions" is complex

12:20 mdrogalis: That's a good point.

12:20 Bronsa: wow. the reduce impl is even more confusing than I though. there are now 3 interfaces + 2 protocols implementing it

12:21 and some implementations are unreachable, e.g. it looks like reduce will never use the ArraySeq_prim IReduce impl

12:22 puredanger: ^ that's maybe something that should be addressed before 1.7, it seems that some IReduce/IChunk reduce impls still don't handle reduced

12:22 puredanger: which?

12:23 tbaldridge was supposed to find and fix all of those, so I'll blame him :)

12:23 Bronsa: puredanger: ArrayChunk/ArraySeq_[prim]/gvec

12:24 tbaldridge: Yeah, except, adding "reduced?" support to ArrayChunk breaks a bunch of thigns

12:25 Bronsa: also reduce on primitive arrays seems slower than it could be

12:25 tbaldridge: Bronsa: well it does do boxing, or are you thinking of something else?

12:25 puredanger: oh right, we talked about that didn't we

12:25 Bronsa: it gets routed from collreduce to internalreduce's Obejct impl rather than to the IReduce impl for their ArraySeq_*

12:26 puredanger: reduce will have a special case to prefer IReduce over CollReduce

12:26 Bronsa: puredanger: the thing is that (long-array [1 2 3]) is not IReduce, (seq (long-array [1 2 3])) is

12:26 puredanger: that's in CLJ-1572 which almost made it in today

12:27 Bronsa: ah wait, I see I'm wrong

12:27 or not. uhm.

12:28 yup, reduce doesn't seem to use the arrayseq path for arrays

12:30 puredanger: hmm, yeah CollReduce could potentially be extended to arrays

12:30 Bronsa: ah! there's an impl for arrayseq_* of internalreduce that's not broken

12:31 puredanger: if there's a gap here, please file a ticket

12:31 Bronsa: so arrayseq_* IReduce impl is broken, but internalreduce's impl is not broken

12:31 puredanger: I'll try to figure out what is a bug and what is just dead code and open a ticket

12:32 ,(.reduce (seq (long-array [1 2 3 4 5])) (fn [_ a] (println a) (reduced 6)))

12:32 clojurebot: 2\n3\n4\n5\n#<Reduced@d85409: 6>

12:32 puredanger: certainly, ArraySeq* should check reduced

12:32 Bronsa: like, this is obviously wrong but this path will never be used by reduce

12:33 ,(reduce (fn [_ a] (println a) (reduced 9)) (seq (long-array [1 2 3 4 5])))

12:33 clojurebot: 2\n9

12:33 puredanger: those sound like 2 separate jiras to me

12:35 Bronsa: puredanger: do you have any idea why IChunk defines a reduce method but doesn't extend IReduce?

12:35 bodie_: has anyone tried anything around pair programming in lighttable besides the firepad demo?

12:35 I'm thinking something like a floobits plugin or something over xmpp

12:37 puredanger: Bronsa: timbaldridge just looked into some of that stuff recently, but don't know. IChunk.reduce() has slightly different semantics than IReduce.reduce() iirc.

12:37 in particular, around reduced

12:38 Bronsa: puredanger: ok I'll dig into that code and try to figure it out.

12:38 puredanger: he was (I think) trying to reconcile them in the patch for http://dev.clojure.org/jira/browse/CLJ-1515

12:39 Bronsa: ah, there's also IKVreduce lol. 3interfaces+3protocols then

12:39 I feel like this could be cleaned out quite a bit

12:40 puredanger: Bronsa: if designed fresh, surely

12:41 but harder if considering how not to break existing users of CollReduce or IReduce

12:42 Bronsa: puredanger: meh, IReduce just got a breaking change

12:42 puredanger: ?

12:42 Bronsa: IReduce -> IReduce,IReduceInit

12:43 nevermind, I missed that IReduce extends IReduceInit

12:44 andyf_: you are in a maze of twisty little passages, all alike. :)

12:44 puredanger: I was just eaten by reduced

12:45 Bronsa: reduced added a ton of complexity in the impl

12:46 but I have to say, it's really handy

12:49 puredanger: Bronsa: I'm stepping away to work on some conj stuff but would really like those tickets. if you don't have time, drop me an email and I'll take care of it.

12:50 Bronsa: puredanger: I'll look into the code a bit more to understand what's a bug and what's just my misunderstanding but will definitely open those tickets later

12:51 as it stands now I'm pretty sure c.c/reduce is fine, OTOH using IReduce's reduce directly can be broken

13:01 brucehauman: hey all, Is anyone looking for a Conj ticket?

13:09 bbloom: if i suspect a `lein repl` instance, and come back, it says "Welcome back!"

13:09 but it doesn't seem toa ctually work

13:11 justin_smith: bbloom: also, odd behavior if you try to tell it to keep running in the background

13:12 bbloom: s/suspect/suspend

13:13 stuartsierra: bbloom: I always suspect lein.

13:13 bbloom: stuartsierra: my subconscious agrees

13:14 justin_smith: bbloom: you could compare the behavior of "rlwrap java -cp $(lein cp) clojure.main"

13:16 cfleming: tbaldridge: I think your proposed solution probably leads to more code duplication, but still gets a big (inc) from me.

13:22 kanobe: So I have a Go project that uses other Go projects (i.e. has their repos cloned)

13:22 oops wrong chan :P

13:22 Sorry

13:22 technomancy: ~guards

13:22 clojurebot: SEIZE HIM!

13:22 technomancy: =)

13:22 hfaafb: D:

13:23 martinklepsch: In James Reeves' `template` what are endpoints useful for? https://github.com/weavejester/duct

13:23 Is that for when parts of the application use different components/systems?

13:27 justin_smith: martinklepsch: I think that's the REST endpoint concept - you can have multiple endpoints that act as entities, each one accepts some subset of request methods (get/post/put/delete etc.)

13:28 stuartsierra: Isn't there a way to do (map first (partition 2 …)) with a single function?

13:29 TimMc: stuartsierra: take-nth I think

13:29 ,(take-nth 2 (range 20))

13:29 clojurebot: (0 2 4 6 8 ...)

13:30 stuartsierra: TimMc: That's it, thanks

13:31 TimMc: $findfn 2 [0 1 2 3 4] [0 2 4]

13:31 lazybot: [clojure.core/take-nth]

13:31 TimMc: \o/

13:31 You're a bot!

13:41 EvanR: can extend (the protocol thing) be used to implement java interfaces?

13:41 like ILookup

13:42 stuartsierra: EvanR: no

13:42 EvanR: alrighty then

13:44 _2_perez: hi(L)

13:45 Bronsa: tbaldridge: ok so ArrayChunk's reduce impl is right as it is now

13:46 csd_: What are some good books on unit testing, TDD, and debugging? They don't have to necessarily be Clojure specific

13:47 Bronsa: tbaldridge: basically reduce on a chunked-seq reduces over each chunk via ArrayChunk/reduce, that needs to return a reduced so that the chunked-seq reduce can know it has to unwrap it & return rather then reduce the other chunks

13:47 tbaldridge: which breaks the .reduce contract

13:47 Bronsa: tbaldridge: so changing that in your patch for range is wrong

13:47 tbaldridge: not really, that/s IChunk/reduce not IReduce/reduce

13:47 that's*

13:48 tbaldridge: oh, they're different, didn't know that

13:48 Bronsa: I guess that's why IChunk defines a reduce that's not IReduce's one

13:48 tbaldridge: it's similar to how kvreduce is implemented for maps -- kvreduce on PHM unwraps, kvreduce on the internal nodes doesn't

13:49 tbaldridge: yeah all that impl is kinda confusing bcause same signature but different contracts

13:51 eric_normand: I'm having trouble with tagged literals

13:51 This is the error message: RuntimeException No reader function for tag subspace/core-async-channe

13:51 (sorry, has \l at the end)

13:52 and this is my *data-readers*: {subspace/core-async-channel #'portal.subspace/read-channel}

13:52 portal.subspace/read-channel exists

13:52 any clues?

13:52 stuartsierra: eric_normand: Have you loaded 'portal.subspace'?

13:52 eric_normand: yes

13:53 stuartsierra: Then I got nothing.

13:53 Except that data readers are rarely necessary.

13:53 eric_normand: hmm

13:53 I might try doing without

13:53 thanks

13:55 sdegutis: ,zero?

13:55 clojurebot: #<core$zero_QMARK_ clojure.core$zero_QMARK_@113722b>

13:55 sdegutis: ,one?

13:55 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: one? in this context, compiling:(NO_SOURCE_PATH:0:0)>

13:55 sdegutis: Why isn't there a (one?) function?

13:57 ,(let [[foo1 & fooN] [1 2 3]] (if (empty? fooN) foo1 (first fooN)))

13:57 clojurebot: 2

13:57 sdegutis: I wanted to test whether a collection had 1 or more elements. Ultimately I ended up with something like that.

13:58 dmitrygusev: why returning 2nd element then?

13:59 eric_normand: (seq coll) tests if there are one or more elements in coll

13:59 ,(seq [])

13:59 clojurebot: nil

13:59 eric_normand: ,(seq [1 2 3])

13:59 clojurebot: (1 2 3)

14:00 technomancy: sdegutis: sounds like you need a pattern match

14:01 dmitrygusev: btw, quoting https://twitter.com/hlship/status/530395233410764800 : I'm experimenting with a convention that varargs arguments are prefixed with '&' (i.e. (defn foo [x & &xs]) … helps with the calling side

14:01 eric_normand: sdegutis: what technomancy said

14:01 sdegutis: See, I'm trying to return either the only one, or one that matches a pattern.

14:01 technomancy: I don't know what that means in Clojure.

14:02 eric_normand: sdegutis: I see.

14:02 what kind of pattern?

14:03 sdegutis: (str/contains ":" (:title %))

14:03 eric_normand: nice

14:03 what about:

14:03 sdegutis: I could just look for the pattern first, and (or) it with (first).

14:04 But that's less, umm, accurate.

14:04 (or (filter pattern thingies) (first thingies))

14:04 eric_normand: ,(let [coll [1 2 3] f (fn [pred coll] (or (first (filter pred coll)) (first coll)))] (f coll))

14:04 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox/eval142/f--143>

14:04 sdegutis: eric_normand: mainly because that fails

14:04 eric_normand: ,(let [coll [1 2 3] f (fn [pred coll] (or (first (filter pred coll)) (first coll)))] (f even? coll))

14:04 clojurebot: 2

14:04 sdegutis: Oh.

14:08 eric_normand: So yeah, we had the same idea. Seems more idiomatic Clojure, but seems much less semantically correct.

14:09 I admit that I sound like a heretic, but I've fallen out of love with Clojure, and I'm more annoyed with it these days than anything else.

14:11 nkoza: sdegutis: what are you using instead of clojure?

14:11 sdegutis: Nothing.

14:11 I just use Clojure.

14:12 xeqi: i thought pixie was the new hotness

14:13 godd2: I just started learning Clojure, so I haven't had the opportunity to be annoyed with it yet

14:13 sdegutis: I've had my eye on Swift, but it's Apple only so pretty much useless for my job (web app).

14:13 technomancy: writing code without pattern matching is super annoying to me too, but at least for application-level stuff you can bring in core.match, right?

14:13 I have a hard time understanding why you wouldn't, anyway

14:13 sdegutis: I've also had my eye on Rust, but I'm waiting until it's done changing before I seriously look at it.

14:13 technomancy: I don't know what that's for.

14:14 technomancy: does Clojure have pattern matching?

14:14 technomancy: sdegutis: there is a clojure lib that implements it as a macro, yeah

14:14 eric_normand: sdegutis: it's really nice

14:14 sdegutis: technomancy: core.match?

14:14 eric_normand: it looks nice

14:14 technomancy: yup

14:14 sdegutis: eric_normand: did you write it?

14:14 eric_normand: no

14:14 david nolen

14:14 sdegutis: Oh.

14:15 I guess that makes sense.

14:15 eric_normand: sdegutis: but I've used it

14:15 sdegutis: It looks just like a fancy (cond), is that all it does?

14:16 eric_normand: cond with unification

14:16 technomancy: that's like saying vars are just fancy variables

14:16 eric_normand: binds locals, pattern matches, and optimizes the matching

14:16 sdegutis: eric_normand: sold.

14:17 technomancy: it's like ... when you try to destructure against something that's not a collection, you get an error or nils or whatever, but pattern matching lets you offer a bunch of patterns and pick the branch that matches

14:19 sdegutis: Oh so it's also an enhanced destructuring? Nice.

14:20 What's a decent testing framework?

14:20 technomancy: lol

14:20 Bronsa: sdegutis: didn't you set yourself up to writing a better one for clojure last year? or am I confusing you with someone else?

14:21 sdegutis: Bronsa: That was me, I've since given up on trying to contribute to things.

14:21 Bronsa: So I'm just looking for a decent, stable one. Has the landscape changed since last year?

14:22 Bronsa: I've always only used clojure.test and have been happy with it.

14:23 sdegutis: I imagine clojure.test hasn't changed since last year.

14:23 Bronsa: right

14:23 sdegutis: Never mind. Perhaps I'll just fix this bug in the one I'm using.

14:23 (If only I knew how.)

14:32 arrdem: is there a core.logic idiom like run-1?

14:33 run-db has an [n]. okay.

14:51 rads: is there a difference between a reference and an identity when we're talking about state management?

14:51 I understand that both represent a sequence of values changing over time

14:51 gfredericks: I think I use those words interchangeable in that context

14:51 -bly*

14:51 TimMc: wordsbly

14:52 gfredericks: Ibly thinkbly Ibly usebly thosebly wordsbly interchangeablebly inbly thatbly contextbly

14:52 ^FTFM

14:52 rads: I feel like identity is a more abstract concept, and a reference type is an implementation of an identity in a program

14:53 does that make sense?

14:53 gfredericks: that sounds fair

14:53 rads: that helps with my understanding a bit

14:53 thanks

15:03 stuartsierra: rads: Sometimes we use "identity" to mean object identity, as in a Java Object.

15:05 justin_smith: amalloy_: I figured the eval privmsg thing out: the clojure plugin duplicates all the message dispatch logic that was in registry/try-handle, and I had only updated the latter. So I am going to abstract it out so it can continue to be correct in both places.

15:14 xyproto: Could someone please test "quine-relay-git" on Arch Linux (from AUR) and see if clojure errs out for you as well?

15:14 Unsure if it is a problem with quine-relay or clojure.

15:15 justin_smith: I don't use arch, but may be able to help if nobody more qualified is around: what's the error message?

15:16 xyproto: if the error is the fact that there is no clojure package, you likely want leiningen in its stead (which is a builder / packager / runner tool for clojure, clojure is just a jar file)

15:18 kenrestivo: "ibly" sounds like something i should register and domain-squat until some startup wants to use it as their company nam

15:19 justin_smith: kenrestivo: butter jump!

15:19 *better, lol

15:19 kenrestivo: butterjump.com is taken

15:20 justin_smith: http://ibly.com/ also

15:20 kenrestivo: sorry, ibly is taken, butterjump.com is not

15:20 justin_smith: butterjump.com is already halfway to being viral just by the name - next you need some unwarranted enthusiasm and absurd juxtapositions of in-jokes

15:21 maybe some loud noises

15:21 and BANG you have a hit

15:21 kenrestivo: ~butterjump is a hit

15:21 clojurebot: Ok.

15:21 kenrestivo: i wonder if there's a browsable database somewhere of all the clojurebot factoids. must be some high entertainment in there

15:24 sdegutis: ~guards

15:24 clojurebot: SEIZE HIM!

15:24 puredanger: (inc guards)

15:24 lazybot: ⇒ 1

15:24 justin_smith: ~gourds

15:24 clojurebot: SQUEEZE HIM!

15:35 gfredericks: kenrestivo: hiredman gave out a db dump once

15:35 I think I had it at one point but probably misplaced it

16:33 LIHOY: #bitcoin: Beware of scams! Scammers are sending users private messages with bitcoin-stealing malware and offers to trade. We are unable to stop them, so you must protect yourself. NEVER download or run programs from strangers! When in doubt, ask the ops.

16:33 îé

16:33 I'm from Russia . I thought that Russian server) fuck karoch )

16:34 arrdem: technomancy: fingerguns required

16:34 bbloom: technomancy: ^^

16:35 arrdem: (inc technomancy)

16:35 lazybot: ⇒ 157

16:35 technomancy: pew pew pew

16:43 TimMc: What an odd little spammer.

16:46 hfaafb: good advice tho

16:46 akkad: teknemancy?

16:46 technomancy: hfaafb: except for the last two words, yeah

16:57 augustl: anyone got some tips for using clojure data structures from another JVM language? I'm gonna use Groovy, with Gradle as the build system.

16:57 just depend on clojure, and call something.Something.init()?

17:01 gfredericks: augustl: you might need to require RT?

17:02 probably not though

17:02 so I don't think you have to explicitly init anything

17:02 arrdem: augustl: as of 1.6 or 1.5 you no longer need to explicitly init core

17:03 augustl: afaik there's something protocol related in maps that fails without RT

17:03 I'll just try 1.6 and see what happens :)

17:06 scape_: with string replace, how would I supply a var instead of a raw regex string? ie: #"abc" with (str "ab" "c")

17:07 oh wait

17:07 I can

17:07 hah

17:07 :-\

17:07 wait no i can't

17:07 arrdem: vars are an implementation detail and should always be transparent

17:08 scape_: https://clojuredocs.org/clojure.string/replace

17:08 arrdem: which example, scape_?

17:09 dbasch: scape_: use re-pattern

17:09 scape_: (clojure.string/replace "The color is red" #"red" "blue") where #"red" is instead (str "red") or something evaluated

17:09 oh

17:09 I'll see

17:09 dbasch: &(clojure.string/replace "abcabc" (re-pattern (str "ab" "c")) "def")

17:09 lazybot: ⇒ "defdef"

17:10 bbloom: (doc clojure.string/replace)

17:10 clojurebot: "([s match replacement]); Replaces all instance of match with replacement in s. match/replacement can be: string / string char / char pattern / (string or function of match). See also replace-first. The replacement is literal (i.e. none of its characters are treated specially) for all cases above except pattern / string. For pattern / string, $1, $2, etc. in the replacement string are substituted with the string that

17:10 scape_: thanks

17:10 repattern looks like it will work

17:10 bbloom: ,(clojure.string/replace "abc" "b" "x")

17:10 clojurebot: "axc"

17:10 bbloom: scape_: seems to work for me...

17:10 if you use re-pattern, you'll need to escape any metacharacters

17:10 ,(clojure.string/replace "abc" (str "b" "c") "x")

17:10 clojurebot: "ax"

17:11 dbasch: of course a string works too for that case

17:11 scape_: yea it looks like it is

17:11 hmm

17:11 I get clojure.lang.Compiler$CompilerException: java.lang.IllegalArgumentException: Invalid match arg: ,

17:12 gotta look closer I think, thanks

17:14 bbloom: scape_: i bet you're not passing it what you think you're passing it

17:14 scape_: yea I was willy nilly searching a map without checking if key existed

17:15 thx

17:18 hfaafb: how come rich hickey never says hi to anyone here

17:18 i just wanna autocomplete rhickey once in my life

17:18 or rich

17:18 or whatever

17:21 bbloom: hfaafb: i think you answered your own question... people want to talk to him just to talk to him, and he wants to accomplish things :-P

17:28 rads: "rads: Sometimes we use "identity" to mean object identity, as in a Java Object."

17:28 does that mean the identity of a java object is actually a value?

17:29 oh darn, stuartsierra is no longer here

17:30 gfredericks: we should have a ceremonial annual event where rich comes into #clojure and everybody gets to A) suggest using github PRs instead of jira and B) request exactly one function to add to clojure.core

17:30 puredanger: yeah, that would go over great :)

17:31 dbasch: rads: no, in java different objects can have the same value

17:32 i.e. two objects can be equal but not identical

17:32 seancorfield: gfredericks: would that be a bit like the annual event on the mailing list where the CA process is discussed? :)

17:32 gfredericks: seancorfield: oh right that should be a part of it somehow

17:33 dbasch: well, there’s always the old cardboard cutouts of rich hickey from the last conj, maybe someone can send one to hfaafb

17:35 rads: dbasch: do you know how the jvm determines if two objects are identical? does it simply compare the pointers to where the state is stored in memory?

17:35 gfredericks: maybe also everything gets to paste one stack trace they've encountered and gesture wildy while saying "just look at this thing!"

17:35 rads: depends on what you ask it to do

17:35 rads: the jvm can do pointer equality, or it can do custom equality based on Object#equals

17:36 clojure.core/= does something more complicated

17:36 dbasch: rads: == means are they the same reference

17:36 gfredericks: where == is java syntax

17:36 rads: I'm trying to get a fundamental understanding of these three terms: reference, value, and identity

17:36 dbasch: .equals means “do they have the same value” (for whatever definition of equals the class has)

17:37 rads: the "reference" is a location in virtual memory, correct?

17:38 it's just a pointer?

17:40 arohner: rads: 'value' typically means an immutable object: "foo", 42, {:a :b}

17:40 rads: 'reference' typically means a box that can point to a value. refs, atoms and vars are all reference types

17:41 rads: identity typically means a thing that is unique, that can be found by its unique attribute. it can be an immutable value that has e.g. an :id column, or a ref where there's only one of them in the system, etc

17:42 amalloy: hmmmm. can anyone think of a case where ~''x would produce something different from '~'x? i've seen the latter numerous times, and it just occurred to me that it should be identical to the former but i've never actually seen it

17:42 rads: arohner: thanks for that succinct explanation

17:43 here's something I've been wondering: is it fair to say that physical memory slots and CPU registers are the lowest level "references" available to programmers?

17:43 at the operating system level at least

17:43 arohner: probably

17:44 EvanR: registers in memory on devices

17:44 gfredericks: rads: people are being wishy-washy about this because these words don't have official definitions. you just gotta figure out what are useful meanings for your context and be explicit about that when you need to

17:46 rads: so technically there's no limit to how far you can "move the reference up" in a functional program, since you could represent your program as a function on the current state of the CPU registers and physical memory

17:46 does that make sense?

17:46 EvanR: rads: its useful to consider yourself working on a virtual machine with abstract notions of whatever the programming language is manipulating

17:46 dbasch: rads: memory and cpu registers are not “references”, any more than a mailbox or the trunk of your car is a reference

17:46 they are storage units

17:46 you can refer to them, of course

17:46 EvanR: thinking that you are direct accessing anything at any level is either misguided or inappropriate for the current abstraction

17:47 virtual memory, microcode, its all a lie

17:48 the internet protocol is a rich source of abstractions over things no one has ever heard of, or cares about for the purposes of application programming

17:49 rads: okay, so you make references that point to locations in storage units

17:49 EvanR: for example

17:49 rads: the storage unit is abstract

17:49 could be a CPU register, could be redis

17:49 the reference is a symbol within the program that provides access to that location within the storage unit?

17:50 is `int c` a reference in the C programming language since it changes mutable state?

17:50 justin_smith: rads: no, it is a storage location

17:51 rads: vars or local bindings provide access via symbols to those locations

17:51 that is no it is not a symbol

17:51 EvanR: int c is a declaration for storage

17:52 dbasch: in C, int c means “make a space for an int in the stack, and when you see c in this scope I’m talking about that space”

17:52 rads: I'm using C as an example for now because it's simpler than clojure's model

17:52 EvanR: dbasch: depending on where it appears

17:52 rads: you think?

17:52 dbasch: EvanR: yeah, I’m assuming a function

17:52 justin_smith: "int c" tells the c compiler you want to refer to some location in the stack or memory heap by the symbol c

17:53 "(def c)" tells clojure you want to refer to something, within this namespace, by the symbol c

17:53 rads: EvanR: not for writing programs on top of, but it's easier for me to understand if I can see the connection of the system itself

17:53 EvanR: do does (declare c)

17:53 so*

17:53 oskarkv: amalloy apparently ``'~'x is not the same as ``~''x. I don't know how to think about these cases, ie how to predict what they will produce

17:53 justin_smith: rads: (let [c 1]) tells clojure that you want to refer to 1 locally as c

17:53 rads: I see

17:54 what if you're mutating a struct? is the struct a reference?

17:54 justin_smith: rads: everything in the jvm that is not a primitive is a reference type

17:54 EvanR: rads: "the system" is another abstraction, you just more familiar with it, but its not even that simple of an abstraction

17:54 amalloy: oskarkv: well, ``~''x is identical to `''x

17:54 because `~ is a no-op

17:55 rads: I'm trying to understand how `c = 1` in C is different than `(reset! c 1)` in clojure

17:56 the end result is the same for the programmer

17:56 justin_smith: rads: so, if you are mutating a "struct" that struct will be represented in the jvm as an "Object" - an instance of some "Class", and you can refer to it the same way you would any other value - via local binding, or a namespaced global var

17:56 rads: in clojure, c is a reference type

17:56 technomancy: I had a waaaay easier time understanding C pointers after learning clojure's reference model.

17:56 justin_smith: rads: or of course a value in a slot of some other Object

17:56 technomancy: not that they're the same thing, but the fact that clojure's model was so explicit helped me keep the concepts straight in C where they can be fuzzier

17:57 dbasch: rads: for one, c = 1 is not an atomic operation

17:57 EvanR: the storage units in question have different lifetimes

17:58 rads: is reset! atomic?

17:58 EvanR: rads: its not exactly right to call anything in C a reference

17:58 rads: I thought you only get atomicity with swap!

17:58 dbasch: rads: what does reset! operate on?

17:59 rads: you would get the same semantics if you replaced c variables with atoms and only used resets instead of assignment, wouldn't you?

17:59 C, the language, variables I mean

17:59 EvanR: C the language doesnt guarantee any atomic operations

18:00 rads: but I'm saying if you have a bunch of writers using reset! on an atom, those operations are also not atomic

18:00 even though the reference type is called an atom

18:00 EvanR: :doc reset!

18:01 rads: "Sets the value of atom to newval without regard for the

18:01 current value. Returns newval."

18:01 if there is no coordination of the previous value, how can there be atomicity?

18:01 dbasch: rads: there is a subtle difference

18:02 you could execute a clojure program in discrete steps and a c program in discrete steps too

18:02 right after a reset!, the value would be what you put in

18:02 tuft: atomicity just means it either happens completely or not at all. if two threads try to assign the same variable in C a third may see an inconsistent state / partial update

18:02 dbasch: in c, the step after an assignment makes no guarantees if there are concurrent assignments

18:02 technomancy: dbasch: reset! is the same though

18:04 rads: so when you do `c = 1` in a C program, it is not immediately visible to other threads with access to the same memory location?

18:04 EvanR: youre not guaranteed to see the value you put it right after putting it in

18:04 dbasch: technomancy: you’re right, just looked at the code

18:04 rads: and the different with clojure is that the other threads will see the new value immediately?

18:04 difference*

18:04 technomancy: atomicity only matters if the new value is based on the old

18:05 (so, swap! but not reset!)

18:05 rads: yes, that's what I was confused about

18:05 EvanR: rads: when you were asking about atomicity issues, i was thinking you were talking about word tearing

18:05 like your variable gets half way committed

18:06 tuft: yeah that's what i'm talking about

18:06 that to me is atomicity too

18:06 oskarkv: amalloy yeah but I have trouble understanding what happends with ``'~'x

18:06 happens*

18:06 rads: my main motivation for this is figuring out what a useful AtomicReference implementation might look like in JavaScript

18:06 tuft: the other thing is more about serialization

18:06 amalloy: oskarkv: nothing very good. it's hard to imagine wanting to use taht

18:07 EvanR: rads: in browser javascript you are in luck, because the threads do not interleave, everything you do is atomic in this sense

18:07 oskarkv: hehe but i'm curious. amalloy do you understand it? :P

18:07 amalloy: take a look at even like ##``'x

18:07 lazybot: ⇒ (clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list (quote clojure.core/x))))

18:07 tuft: rads: doesn't ClojureScript already have an atom?

18:07 amalloy: `'~'x produces the code necessary to output (quote x)

18:07 dbasch: rads: javascript is single-threaded (at least in the browser) so atomicity means nothing

18:07 rads: tuft: yeah I'm talking JS only

18:08 it becomes important when you're synchronzing data with the server

18:08 EvanR: javascript over the years has silently saved countless programmers from even knowing that concurrent programming challenges exist

18:08 amalloy: ``'~'x produces the code necessary to produce the code necessary to output (quote x), which is not very useful

18:08 tuft: yeah no volatiles in js land

18:08 except web workers?

18:08 dbasch: rads: no, it means nothing

18:08 EvanR: tuft: new fangled contraptions ;)

18:08 rads: what if I want to perform an operation on the client concurrently with other clients?

18:08 oskarkv: amalloy yeah ok gonna think about it some more. Just as an exercise ;)

18:09 rads: that needs to be an atomic operation

18:09 oskarkv: thanks

18:09 dbasch: rads: in that case you care about atomicity on the server side

18:09 EvanR: rads: are you sure you are using the word correctly yet?

18:10 rads: maybe this is a better phrasing: I want to make an abstraction in JavaScript that makes performing atomic operations between the client and server easier

18:10 technomancy: hooo boy

18:10 dbasch: I give up

18:10 technomancy: so yeah, a distributed system is completely different

18:11 tuft: rads: could we have a concrete example please?

18:11 technomancy: welcome to CAP theorem =)

18:11 dbasch: the point is that if you run an operation in js, nobody will come and change your state while it’s pending

18:11 rads: I can't go into a ton of detail

18:12 basically I want to perform simple synchronization between the client and server in a web app where the writes are not very common, but better than just last write wins

18:12 tuft: rads: maybe you can obfuscate your $1e6 idea sufficiently? =)

18:12 dbasch: rads: if you’re competing with other clients, it’s up to the server to synchronize access to whatever

18:13 rads: I just don't want to risk violating any contracts with my employer, sorry

18:13 dbasch: e.g. you and someone else are trying to buy the last ticket to a concert

18:13 tuft: rads: what dbasch said

18:13 dbasch: either you buy it or the other person does, but there’s nothing the browser can do about it

18:14 rads: dbasch: no, but the browser can perform the operation optimistically. at that point you have two states to reconcile when you get the next response from the server

18:15 dbasch: rads: why would you want to do that?

18:15 rads: why would I want to perform operations optimistically before I get a response from the server?

18:15 dbasch: not for that example. Are you writing a text editor that claims to save but really hasn’t saved anything?

18:16 rads: it's more about not making the UI block when the user performs an action

18:17 otherwise you have to wait for the server response to have a consistent state if you have no plan to reconcile any optimistic opereations

18:18 technomancy: any recommendations for learning about distributed systems?

18:19 dbasch, tuft: I appreciate your help so far. this is a tough problem

18:19 dbasch: rads: look into Om if you want to do this in Clojure

18:20 or any other react-based framework

18:20 rads: that's what this is for, a react application

18:21 trying to understand how the different pieces fit together and centralize the state synchronization with the server in one place

18:21 I followed Om closely when it came out last year, but I'm trying to understand the fundamentals behind Om itself

18:22 so that maybe I could contribute back to Om one day with a better understanding of these principles

18:41 myguidingstar: hi all, what is the best way to write a Leiningen template?

18:42 is there anyway to make one from a working project?

18:43 justin_smith: myguidingstar: not that I know of. But there is "lein new template [name]"

18:43 myguidingstar: well, I know that

18:44 justin_smith: oh, you knew about the template template?

18:44 have you checked out the files it makes?

18:46 myguidingstar: I know how to write lein template from scratch

18:47 I'm thinking of a conventional way to convert a 'working temple' into a template with {{placeholders}}

18:47 s/working temple/working template/

18:48 oh, I meant 'working project'

18:48 justin_smith: if that exists, I have not heard of it

18:49 technomancy: you should write one =)

18:49 myguidingstar: technomancy, yeah, I'm thinking of it

18:51 should be a set of rules: hello-project (real, runnable symbols!!!) to {{placeholders}}

18:53 and finally: "lein templatize input-dir output-dir"

18:54 technomancy, any suggestions about such rules?

18:54 technomancy: part of the reason it doesn't exist yet is it's difficult to come up with sufficiently generalizable rules =)

19:04 andyf: technomancy: "Subprocess failed." Is printed by lein if a plugin does (System/exit 1) and that is by design, yes? Just confirming

19:08 technomancy: andyf: ideally the plugin could replace that generic message with something more descriptive, but if they don't, then yeah that's what you'd see if a project JVM exited nonzero.

19:09 andyf: Understood. I'm just documenting it for now since it wasn't already and someone thought it was a bug in Eastwood

19:14 gfredericks: andyf: is issue #21 still unworked-on, and is it work-onable?

19:16 andyf: gfredericks: I think I have both time and interest to get a start on it this weekend, but it depends how much time it takes me to finish #93 first

19:17 But if you want to go for it, I don't mind

19:17 gfredericks: okay I will give you a heads up if I do

19:19 andyf: I keep getting reminded when creating linters (1) how much easier tools.analyzer makes it, and (2) how much I don't know about corner cases that exist when I start

19:20 technomancy: andyf: I'd recommend doing eval-in-project in a try/catch and watching for :exit-code on an ExceptionInfo

19:21 also... why ExceptionInfo and not InfoException?

19:21 gfredericks: well it's not an exception due to Info

19:22 andyf: On the exception name, Bronsa named it

19:23 technomancy: it's less verbose at least than DataConevyingException

19:23 Bronsa: andyf: I believe technomancy is talking about c.l.ExceptionInfo, not about t.a.j.ExceptionThrown

19:23 andyf: Or is there an existing InfoException you are asking why we are not using it instead?

19:23 gfredericks: clojure.lang.ClojureProblem

19:23 Bronsa: but I haven't read the scrollback so I might not have all the context

19:25 technomancy: total bikeshed, forget I said anything

19:25 andyf: Bronsa: You did not choose name of ExceptionInfo in tools.reader?

19:26 Bronsa: ah

19:26 andyf: Wait, what were we talking about again? :-)

19:26 Bronsa: andyf: not really, that's just to implement c.l.ExceptionInfo in clj 1.3 or whatever the version

19:27 puredanger: ah by the way, importing by default ExceptionInfo would be super for writing cross language code.

19:27 andyf: Bronsa: I currently aot that class only in Eastwood and I recall adding that because things broke without doing so

19:27 eric_normand: clojure.edn/read does not use *data-readers*

19:28 is that a bug?

19:28 Bronsa: eric_normand: no, a design choice

19:28 eric_normand: Bronsa: why?

19:28 Bronsa: eric_normand: c.edn/read has a different signature than c.c/read

19:28 eric_normand: it uses a map arg rather than dynamic vars

19:28 andyf: eric_normand: it lets you specify them in arg I think?

19:28 eric_normand: I see

19:29 andyf: More explicit that way

19:29 eric_normand: yes

19:29 Bronsa: andyf: dunno, I don't recall how compilation works there. but tools.reader's ExceptionInfo is only used by clj <=1.3

19:33 andyf: Bronsa: Namespace c.t.reader.impl.utils requires it unconditionally, doesn't it ?

19:34 Bronsa: andyf: ah yeah. right so it has to be AOT compiled or the type hint will fail

19:35 andyf: now I remember, loading the namespace conditionally would mess with maven or something like that

19:35 andyf: No big deal for me. Just making sure I wasn't missing something

19:37 Bronsa: Some years down the road I hope that (= 3 (:minor *clojure-version*)) requires updating :-)

19:37 Bronsa: heh

19:38 andyf: I'm just counting on the fact that when (if) the time comesclojure 2.x will break so much existing code that changing that will be the last of my problems

19:38 andyf: Probably so

19:38 technomancy: MAH EYEZ https://github.com/ztellman/cambrian-collections/blob/master/project.clj#L10-L15

19:39 why, github, why?

19:39 is this revenge for something untoward rich said about pull requests?

19:39 Bronsa: lol

19:39 technomancy: syntax highlighting for clojure has been broken for over 20 days :(

19:39 andyf: Github has seen the rising tide of Clojure popularity and is trying to quell it

19:40 justin_smith: technomancy: what really got me was the bright red highlighting of some square brackets in racket code

19:40 but yeah, that is pretty wtf too

19:40 technomancy: http://p.hagelb.org/chair.gif

19:42 andyf: But how do you feel, really?

19:42 technomancy: actually it's a shame the gif cuts off where it does

19:42 because the next few frames reflect it perfectly

19:43 justin_smith: that movie was surprisingly good

19:43 andyf: Youtube source?

19:43 technomancy: (inc lego-movie)

19:43 lazybot: ⇒ 1

19:44 technomancy: andyf: http://www.youtube.com/watch?v=YkCeUjvgXRk

19:45 Jaood: to bad that patch didn't made it to 1.7

19:46 amalloy: justin_smith: currently in https://github.com/flatland/useful/blob/develop/src/flatland/useful/seq.clj, some of the commas are highlighted bright red and some are not

19:46 Bronsa: Jaood: which patch?

19:46 amalloy: i think it's the case that commas preceded by punctuation are bright red; if there's a letter before it, it's not

19:46 Jaood: Bronsa: ztellman's

19:47 justin_smith: amalloy: woah, that sucks

19:51 andyf: Time to make an overlay site for github with better highlighting choices?

19:51 technomancy: andyf: yeah, a userstyles.org thing would be great

19:51 justin_smith: maybe a petition of payed members (I pay for membership there, and I would sign)

19:52 martinklepsch: whats a good project to look at to understand the component system? I looked at duct but it seems to be different to most (https://github.com/weavejester/duct)

19:52 justin_smith: s/membership/account I guess

19:52 technomancy: maybe it's a sign that github's pseudomonopoly needs to come to an end

19:53 I really wish I could recommend gitlab. so close, but still frustrating.

19:54 hyPiRion: Let's make something ourselves, how hard could it be

19:54 andyf: Pushes, pulls, issues, free hosting of public files and static web pages. All still good

19:57 technomancy: a fork of gitlab that actually uses the project readme as the splash page. boom.

19:58 justin_smith: maybe the new highlighting is a passive-agressive way to encourage us to do less code-browsing on site

19:58 (original definition of passive-agressive, not the new one)

19:59 hyPiRion: the new one?

19:59 justin_smith: hyPiRion: where people call being friendly while making a criticism, or leaving a note, or being indirect "passive agressive"

19:59 the old definition was pretty specific: undermining a project without overt hostility

20:00 Jaood: technomancy: but gitlab is for self-hosting so you can really compare them?

20:00 s/can/can't/

20:00 technomancy: Jaood: gitlab is both

20:01 but they make some decisions that only make sense in the context of private repos

20:01 like refusing to use readmes as splash pages

20:01 they have hosted gitlab both for OSS and private stuff

20:04 Jaood: technomancy: oh true, was not obvious from their landing page

20:06 technomancy: you don't like bitbucket?

20:07 technomancy: Jaood: I remember being very unimpressed with the issues system

20:07 but GH's isn't great either

20:08 maybe it just reminded me too much of jira

20:10 michaniskin_: what's the best way to read in a clojure file that contains forms like ::foo/bar?

20:10 i don't want to evaluate it, i just want to read the forms

20:11 Bronsa: michaniskin_: it's not possible without at least evaluating the namespace form

20:11 michaniskin_: wonderful

20:11 thanks Bronsa

20:12 Bronsa: michaniskin_: well that's not entirely true I guess, you *can* read it without evaluating it, all you need is the alias setup

20:12 michaniskin_: yeah i have that already

20:12 i was just checking that i wasn't insane

20:13 i was hesitant to assume that reading and evaluation were complected

20:14 Bronsa: michaniskin_: also you can use tools.reader to do that without messing with the namespace system if you already know the aliases

20:14 michaniskin_: https://github.com/clojure/tools.reader/blob/master/src/main/clojure/clojure/tools/reader.clj#L303-L313

20:14 michaniskin_: i don't want an AST, i want to read forms

20:14 Bronsa: michaniskin_: tools.reader is not tools.analyzer :)

20:14 michaniskin_: ah ok

20:15 yes i have some filthy code that sniffs ns decls

20:15 but i don't feel good about myself when i think of it

20:16 it makes me sad how clojure seems to get more complicated every release

20:16 instead of more elegant

20:16 Bronsa: really? why do you say that?

20:16 andyf: You are in good company, if it is anything like tools.namespace ns form detection

20:17 michaniskin_: well i make a lot of build tooling, and it just requires more and more filthy hacks every release

20:17 i have a ghetto compiler basically to emulate the evaluation that's mixed up in the reader

20:18 Bronsa: michaniskin_: I'm just curious, examples of features added in recent releases that complicate it?

20:18 michaniskin_: ::foo/bar is a big one

20:18 Bronsa: that's been there since 1.0

20:18 michaniskin_: also the stuff that supports that kind of thing in the destructuring forms

20:18 tagged literals in source files

20:19 andyf: michaniskin_: How do those features affect a build tool?

20:19 michaniskin_: because you can't manipulate source files without evaluating them in some way

20:19 andyf: Maybe you do want tools.analyzer :-)

20:19 michaniskin_: instead of being able to read lists like normal, you need a context in which to evaluate a minilanguage

20:19 Bronsa: michaniskin_: the only valid complaint I'll give you is the one about tagged literals, but that's been there for 2 years now

20:20 michaniskin_: if you do a lot of metaprogramming stuff these affordances really weigh on you

20:21 anyway i know it's a minority opinion

20:21 Bronsa: michaniskin_: don't get me wrong, I can agree with you if you said that some things in clojure could be easier, I just don't agree on you when you say that it's getting more complex with every new release

20:22 michaniskin_: i don't want it to be easier, i want it to be simpler :)

20:22 andyf: I don't know exactly the goals your tool have, but I wonder whether there is a different approach that works better with Clojure, rather than at odds with it

20:22 Bronsa: forgive my loose usage of language, that was not my point though

20:22 michaniskin_: haha i know, i'm just pulling your chain :)

20:23 but seriously this is how it seems to me, things getting easier but less simple

20:23 Bronsa: andyf: I guess the biggest source of "complexity" for tool writers for clojure is that clojure's evaluation model is form-at-a-time and that the namespace system is mutable

20:24 michaniskin_: Bronsa: yes, that, too. that's exactly right

20:24 Bronsa: andyf: it's much better for cljs `ns` is a special form and there's no way to intern something at runtime

20:25 michaniskin_: we're currently experimenting with that with boot

20:25 using fresh clojure runtimes for each expression and so forth

20:26 maybe what i need is a language that compiles to clojure

20:33 andyf: Bronsa: I tried timing whole Eastwood crucible run with 1.7 alpha3 vs alpha4 and it went from 36.3 mins to 33.3 mins. Nice, but not huge.

20:34 I think of code speedups as opportunity to add more projects in :-)

20:41 justin_smith: amalloy: pr that fixes the privmsg triggers on lazybot submitted

20:41 also, it is a clean history

20:42 amalloy: *chuckle*

20:42 justin_smith: you tested it?

20:42 justin_smith: yes indeed

20:42 but feel free to double check my work, of course

20:43 Bronsa: andyf: yeah alpha4 has only load time enhancements, alpha3 had a big impact on runtime for t.a.jvm because of better caching in multimethods

20:46 arrdem: justin_smith: r u havin a giggle there with lossy karma m8

20:46 justin_smith: heh

20:47 arrdem: note that that hasn't been submitted officially as a pr (yet?)

20:47 amalloy: justin_smith: i think he is now not responding to PMs which are commands *or* inline hook things

20:47 justin_smith: err...

20:48 * arrdem massively entertained by lazybot/104

20:49 amalloy: itym Raynes/lazybot#104

20:49 lazybot: correct privmsg handling -- https://github.com/Raynes/lazybot/pull/104 is closed

20:49 arrdem: huh. didn't know about that command.

20:50 amalloy: arrdem: well, of course it's not actually a command but a hook: if he sees user/repo#issuenum in any message he says that

20:50 arrdem: justin_smith: yo was this supposed to get comitted? https://github.com/noisesmith/lazybot/commit/a79782382763cef9cc00f08b8b03c621443742f0#diff-f3ec7c8cbebc04166e5e467a96fe641aR30

20:51 justin_smith: arrdem: damn, gotta fix that too, thanks

20:51 arrdem: np

20:52 justin_smith: this pr was not as ready as I thought it was...

20:53 amalloy: odd, I am sending anybot clojure commands and he is evaluating them

20:54 amalloy: he is evaluating regular commands but only when prefix is supplied...

20:55 and the only diff I see from upstream/master is the removal of that pprint

21:54 Bronsa: andyf: not sure if this will help you w/ eastwood, but t.a now supports early termination of walking at any point via reduced: http://sprunge.us/UNdd?clj

21:55 andyf: Nice. Can't think of where I'd use that, but will try to keep it in mind. Tend to just scan all the nodes.

21:55 Bronsa: the impl suffered a bit in readability but this is a great feature to have when needed

21:56 andyf: e.g. in the mexpansion-steps function I wrote a while ago for cfleming I used a dyn var to short-circuit walking after the first macroexpansion, this makes it possible to do that without it

21:57 then: https://gist.github.com/Bronsa/28720fbc280d661f91d7/007717a14f48488bc5e795b5ea45ea5af3322166#file-gistfile1-clj-L46-L47 vs now: https://gist.github.com/Bronsa/28720fbc280d661f91d7#file-gistfile1-clj-L44

22:00 andyf: Today I learned that using :raw-forms, your assumptions of what is there can be made wrong if someone uses their own custom macro expander, as tools.macro's with-symbol-macros does

22:01 gfredericks: dang symbol-macros

22:01 andyf: do you know if riddley does that too?

22:01 Bronsa: andyf: your assumption of my assumption? :P

22:02 andyf: I don't know about riddley.

22:02 Bronsa: gfredericks: IIRC riddley's macroexpander matches clojure's

22:03 andyf: My assumption. My approach to writing linters is to look at ast contents of one or a few cases, write some pattern matching conditions, and see what happens. Usually works well

22:03 Bronsa: ah, gotcha

22:03 andyf: have you thought about using core.match for eastwood linters btw? could save you some trouble

22:04 andyf: Fortunately this is "only" a linter, so if I don't catch everything possible, it is par for the course

22:04 ztellman: riddley matches it, but also does inline expansion

22:05 Bronsa: ztellman: I believe clojure's does too

22:05 ztellman: Bronsa: it doesn't

22:05 Bronsa: ,(macroexpand-1 '(inc 1))

22:05 clojurebot: (inc 1)

22:05 lazybot: ⇒ 9

22:05 andyf: Thought about it, but haven't learned core.match yet.

22:05 Bronsa: ouch.

22:05 ztellman: weird, I assumed it did

22:05 ztellman: so did I, until it bit me

22:05 Bronsa: I guess it does inlining later during analysis

22:06 ztellman: likewise, (clojure.walk/postwalk macroexpand ...) doesn't do what it should in quoted forms

22:06 and a bunch of other things

22:06 basically clojure.walk/macroexpand-all is badly named

22:07 Bronsa: macroexpan-all-and-maybe-more?

22:07 andyf: Sorry, what is it in "riddley matched it "?

22:07 ztellman: macroexapnd-some-and-maybe-more

22:07 andyf: A subset of a superset of the right thing?

22:07 Bronsa: ztellman: I know about the "maybe-more" what about the "some"? :)

22:07 ztellman: Bronsa: the inlined forms

22:07 Bronsa: ah ok

22:08 gfredericks: "A subset of a superset of X" can be basically anything I think

22:08 that must be the joke

22:08 ztellman: andyf: I'm not following

22:08 andyf: That's what I was going for

22:08 Bronsa: well the subset of the superset of x kinda approximates x

22:08 gfredericks: joke explanations brought to you by gfredericks

22:08 Bronsa: kinda sorta until it stops working

22:09 andyf: ztellman: Earlier you said "riddley matches it ..." and I didn't understand the meaning

22:09 ztellman: ah! I mean riddly matches the compiler's macroexpansion behavior

22:09 +e

22:10 the clojure.walk version is both less and more than the compiler's macroexpansion

22:11 Bronsa: riddley could be implemented in a couple of lines using t.a.jvm btw :P

22:12 ztellman: Bronsa: well, I'm actually using the LOCAL_ENV exposed by the compiler, so I'm more guaranteed to be accurate, but sure

22:12 Bronsa: ztellman: that's true, yeah

22:13 ztellman: I don't recall t.a.jvm being available at the time, though

22:13 maybe I wasn't paying attention

22:14 Bronsa: ztellman: it was still really alpha at the time

22:15 it's unfortunate that the vals of &env leak compiler classes rather than an info map. luckly because of that almost nobody uses it (except probably ztellman and amalloy)

22:16 ztellman: Bronsa: the compiler was clearly never designed with extensibility in mind, I'd be overjoyed if that were changed

22:16 but I'm only brave enough to poke at the compiler a bit

22:18 arrdem: more or less convinced that the existing compiler is ossified by simple virtue of core not being interested in changes to it forget anything else

22:20 andyf: Other fish for them to fry, most likely

22:21 C-in-C seems to be taking shape nicely, though

22:21 Thanks to someone whose nick rhymes with kadonsa

22:29 cfleming: While we're talking macroexpansion, is it true that if I want to accurately expand a subform inside some larger form, I would have to macroexpand all its ancestors from the top-level form down to the form I want, but should not have to macroexpand any of the siblings of those ancestors?

22:29 arrdem: unless your users are evil people who have non-toplevel defmacros

22:30 cfleming: Unfortunately I have to assume that all my users are potentially evil

22:30 Or at least misguided

22:30 andyf: Other possible evilness that is rare: macros with side effects during expansion

22:31 E.g. gen-class if I recall correctly

22:31 Bronsa: midje does interning at macroexpansion for example

22:32 cfleming: I see - I actually did that myself while trying to write my macroexpand stepper, I used an atom to count when to stop.

22:32 andyf: gen-class writes to file system

22:32 cfleming: Bronsa: I'll have to go back and look at your example again. The feedback I got was that naive stepping took too long and was tedious for large forms.

22:33 But it turns out to be quite hard to support accurate expansion of arbitrary subforms.

22:33 justin_smith: andyf: during macro expansion?

22:34 Bronsa: cfleming: if you want to try https://gist.github.com/Bronsa/28720fbc280d661f91d7 out, behare that you'll need t.a and t.a.j from master

22:35 cfleming: Thanks, I'll take a look. I'm a little worried about needing t.a. and t.a.j as a dependency since I'd have to load them into the user's REPL, but I might have to.

22:35 andyf: justin_smith: Yes.

22:35 justin_smith: wow

22:35 cfleming: I wanted to use Riddley, but that was also slightly complicated by the need to load a Java class over a REPL connection.

22:37 andyf: cfleming: Eastwood uses a copy and rename hack to avoid namespace version conflicts with user projects. Not fun, but effective

22:37 cfleming: andyf: gen-class just writes the class files, right? Or does it write more than that?

22:37 andyf: Yes, I'd have to do that, for sure.

22:37 andyf: cfleming: I think only 1 class file

22:37 TEttinger: I'm wondering if anyone with experience in uberjar internals would be able to make sense of this issue I'm having bundling JREs with Clojure Uberjars, but not Java Runnable Jars. https://github.com/libgdx/packr/issues/33#issuecomment-62863164

22:38 that's a jump to the comment that gets to what I think the issue may be

22:41 cfleming: andyf: I assume proxy probably does as well - deftype/reify have built in forms so they don't have to.

22:42 andyf: I don't recall the others I found right now - keeping a list for future reference would have been a good idea

22:46 cfleming: I guess definterface etc as well - pretty much anything pre-protocols which generates a class

22:47 Bronsa: cfleming: btw if you're interested in that, I think I can think of a way to do out-of-order macroexpansion with t.a.jvm

22:47 cfleming: you're correct, yes

22:47 cfleming: Bronsa: I am definitely interested in that.

22:48 Bronsa: deftype/defprotocol/reify do that at analysis time otoh

22:48 cfleming: I'm still not sure how the UI should work, but basically the desire is to be able to select a form for expansion, and have that expansion be as accurate as possible.

22:49 justin_smith: regarding proxy, I just did ##(proxy [Object] [] (toString [] "boo")) and did not see anything show up on disk

22:49 lazybot: java.lang.ClassCastException: clojure.lang.Var$Unbound cannot be cast to clojure.lang.DynamicClassLoader

22:49 cfleming: justin_smith: Actually, proxy might just define the class from memory directly.

22:50 justin_smith: gen-class and definterface have to.

22:50 Bronsa: justin_smith: proxy aots only with *compile-files* true

22:50 justin_smith: cool

22:50 cfleming: to write to disk, that is.

22:51 justin_smith: cfleming: now that I think about it, it makes sense on an intuitive level that the constructs that directly deal with java stuff like classes / interfaces would construct things on disk

22:51 Bronsa: cfleming: yes I think I understand what you need. I'm going to sleep now but I'll think about it & let you know if it can be done in a reasonable way

22:51 cfleming: Bronsa: BTW Cursive can now mark vars that are not used anywhere in the project

22:51 justin_smith: while more abstracted stuff may not

22:51 cfleming: Bronsa: Ok, thanks. I'm pretty busy right now, this will all be post-conj, so no rush.

22:53 justin_smith: Right, it's just a little odd that it happens in macroexpansion. It makes sense though since there's really no other time to do it without language changes.

22:54 justin_smith: yeah, a side-effect-free expansion stage would allow interesting tooling though

22:54 and simpler

22:54 cfleming: justin_smith: Yeah, this is why I don't want to automatically macroexpand for Cursive's analysis

22:55 Scheme macros would be easier since that's a pattern matching system IIRC, it doesn't allow arbitrary code execution.

23:00 Bronsa: cfleming: would you be able to add a metadata flag to the sub-form that needs to be macroexpanded? e.g. (foo (bar ^:mexpand-this (baz ..) ..) ..)

23:01 cfleming: Bronsa: I was planning to, I can't see any other way to keep track of where you need to macroexpand.

23:02 Bronsa: I'm not doing anything with metadata yet, I'd actually like to be able to expand with full metadata, then I can hide it in the UI and selectively show what the user wants to see (full metadata, only type hints, etc).

23:03 Bronsa: But I think to do that I'd have to read from the top of the file for the metadata to be accurate.

23:08 Bronsa: cfleming: you mean, for source-info metadata?

23:08 cfleming: Bronsa: Right.

23:09 Bronsa: Plus whatever metadata previous macroexpansions have added, but I don't need to parse from the top of the file for that, just from the top-level form.

23:09 Bronsa: cfleming: well, you could use tools.reader's IndexingPushbackReader :P you can specify the line/col offset in the ctor

23:10 cfleming: Bronsa: Oh nice :)

23:11 Bronsa: It might be possible to get away without custom metadata, and just saying "expand the form at line 100, col 23"

23:11 Bronsa: That metadata should be preserved through expansions I think.

23:11 Bronsa: cfleming: there might be ways to do that with the clojure reader aswell but I'm obviously going to promote my libs :P

23:12 cfleming: Bronsa: Of course, I expect nothing else :)

23:12 Bronsa: cfleming: yeah that should be possible aswell

23:12 cfleming: Bronsa: Anyway, you should go to bed, this isn't urgent for me.

23:12 Bronsa: right.

23:22 sm0ke: play-clj is great, but it still feels very low level, i wish there was a higher level of abstraction for making games

23:22 something like elm in clojure

23:28 bbloom: sm0ke: https://twitter.com/ClojureNYC/status/533435896939700224

23:29 sm0ke: $google github clojure reagi

23:29 lazybot: [weavejester/reagi · GitHub] https://github.com/weavejester/reagi

23:29 sm0ke: btw reagi is awesome, but the main problem lies in tying frp with game entities

23:31 anyhow the paper on elm could be an intersting read

23:31 thanks bbloom

Logging service provided by n01se.net