#clojure log - Apr 08 2015

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

0:44 netroby: Where is clojure Sepecification document?

0:44 I can not find it anywhere

0:54 justin_smith: it doesn't exist

1:55 netroby: Oh. no . every language had a specification paper. why clojure does not have one?

1:56 mavbozo: python, ruby also do not have one

1:56 TEttinger: many successful languages do not have specs for important reasons.

1:56 one is that if there's a mistake in the spec, implementations need to implement that mistake

1:57 netroby: https://docs.python.org/3/reference/

1:57 TEttinger: that is a reference manual not a spec

1:57 justin_smith: netroby: we have docs at clojure.org

1:57 netroby: http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=59579

1:57 I am not interesting document, i am asking for specification document.

1:58 justin_smith: netroby: that python link is not a specification

1:58 netroby: Like java specification https://docs.oracle.com/javase/specs/

1:58 justin_smith: netroby: clojure does not have one, and never will

1:58 netroby: Even scala have it's specification http://www.scala-lang.org/files/archive/spec/2.11/

1:59 justin_smith: netroby: I am not arguing that some languages have specifications

1:59 TEttinger: if you require a spec, may I suggest looking at scheme, which has things like s6rs, and all implementations of scheme that people use have, of course, non-specified extensions

1:59 justin_smith: netroby: what I am saying is that the authors of clojure have said explicitly that they will never make a spec

1:59 it's not up to any of us here

2:00 TEttinger: the java specification is kinda a joke, I'd be interested if any alternative implementations of java actually follow it

2:01 netroby: If you would like to implement a language . you need to read specification or something like that.

2:01 TEttinger: gwt doesn't I am fairly sure, dalvik, if it did, that was probably used against google in oracle's spec

2:01 no.

2:01 justin_smith: netroby: that's not true

2:02 TEttinger: *in oracle

2:02 netroby: It just like a blue print

2:02 TEttinger: *in oracle's lawsuit against google

2:02 justin_smith: netroby: I know what a spec is, and I know clojure will never have one.

2:02 mavbozo: other python implementation is based on cpython implementation not specs, ruby also

2:03 netroby: mavbozo: Python have spec document (relate to specification paper)

2:03 mavbozo: Ruby have a ISO paper

2:03 mavbozo: ISO/IEC 30170:2012

2:03 justin_smith: netroby: that is not true, python has no spec

2:04 netroby: Even c language have it's spec, ISO/IEC 9899:2011

2:04 mavbozo: netroby, but other python and ruby implementations does not strictly follow the specs

2:04 TEttinger: in most languages without explicit specs, if you implement a different version of the non-specified language, you copy as much of the functionality of the existing language as the new version can given platform differences. clojurescript obviously has differences from JVM clojure, stemming from JS' lack of threads that work everywhere, and several other key limitations of JS

2:04 mavbozo: netroby, the canonical references for both languages are its original implementation in C

2:04 justin_smith: netroby: I don't know what you are trying to prove - even if you convinced everyone in this room that clojure needed a spec, none of us are the implementor of clojure, that's not our decision to make.

2:06 netroby: justin_smith: I just searching for clojure language specification document. It's absolutely none

2:06 justin_smith: netroby: that's true

2:06 TEttinger: correct

2:06 justin_smith: ther is none

2:06 TEttinger: like python

2:06 mavbozo: agree

2:08 netroby: After coding for a while, I am interesting how Clojure implements and how about the language, so read a specification paper should be useful.

2:08 justin_smith: netroby: I think it would be awesome to have a pet unicorn.

2:10 Jaood: justin_smith: to big for a pet

2:11 justin_smith: Jaood: I would also like a 100 acre field for my unicorn

2:11 mavbozo: netroby, great but unfortunately clojure does not have a formal spec

2:11 netroby: Hum, i thought i should have to read the source code of clojure instead.

2:12 Jaood: I would like a lein like tool written in Java :P

2:12 netroby: laood: you have ant, maven.

2:12 justin_smith: Jaood: that's definitely the most achievable one so far

2:12 ant is nothing at all like lein, maven would need quite a bit of work

2:13 though maven's support for multiple config file formats now is a step in the right direction

2:17 mavbozo: Jaood, don't we have in our eclipse, intellij? (I assume those IDEs hide all that ant, maven complexities)

2:17 netroby: Gradle is useful and better choice for java developers

2:17 justin_smith: mavbozo: the problem with that is that now everyone on your team needs to use the same ide

2:18 mavbozo: it's actually strongly recommended against for that reason

2:21 mavbozo: justin_smith, recommended against even java development projects?

2:21 *even for*

2:22 Jaood: mavbozo: I was complaining more about start-up time and memory consumption

2:22 justin_smith: mavbozo: yeah

2:22 mavbozo: that's the party line on ##java

2:23 mavbozo: also, this makes it harder to have nice things like CI tools

2:23 unless you expect travis or jenkins to be running your IDE...

2:23 mavbozo: justin_smith, interesting. so you don't want to use eclipse, intellij, or others for maintaining legacy java codebase?

2:24 Jaood: maven is very project centric

2:24 justin_smith: mavbozo: you can use them to maintain a codebase, that's fine. Don't let them control dependency management. Use a proper IDE-agnostic tool (like maven)

2:24 I'm not saying no IDE, I'm saying no IDE automagic dep controls

2:25 a build system that requires starting up a specific app that isn't a build tool is bad

2:27 Jaood: does Hickey uses lein? I would guess he's more of a maven peson

2:27 s/peson/person

2:27 justin_smith: clojure.core is still maven

2:27 I wonder if it will ever have a project.clj

2:28 Jaood: hmm yeah, it looks like it supports both ant and maven

2:29 mavbozo: justin_smith, thanks for the advice. might come in handy if someday i have to maintain a legacy java codebase

2:29 Jaood: Hickey would probably respond, "get off my lawn"

2:37 netroby: In 1994, Steele joined Sun Microsystems and was invited by Bill Joy to become a member of the Java team after the language had been designed, since he had a track record of writing good specifications for existing languages.He was named a Sun Fellow in 2003.

2:38 justin_smith: I know arrdem would be very happy if there was a spec. Probably Bronsa too.

2:40 mavbozo: is there any good story of language spec written after the language implemented?

2:40 justin_smith: mavbozo: common lisp kind of counts - the hyperspec defined a common spec to bring together a bunch of lisp implementations

2:40 netroby: On 16 March 1984, Steele published Common Lisp the Language (Digital Press; ISBN 0-932376-41-X; 465 pages). This first edition was the original specification of Common Lisp

2:40 The same guy.

2:40 justin_smith: yup

2:41 he also worked on the scheme srfis

2:41 mavbozo: justin_smith, people complained that the spec is bloated

2:41 netroby: Written Java specification and Lisp specification

2:41 justin_smith: which form the scheme spec

2:41 so clearly the answer is to elect guy steele to replace rich hickey

2:41 netroby: Do you have vote?

2:41 mavbozo: justin_smith, and make it really hard to fully implement that spec

2:42 justin_smith: netroby: no, that was a joke, rich hickey doesn't run clojure as a democracy

2:42 mavbozo: i vote younger ones such as ambrosebs

2:42 ensuring clojure longevity

2:43 netroby: Guy Lewis Steele Jr. 61 years old

2:43 mavbozo: he also has proven track records in making typed.clojure

2:44 netroby: I am using Emacs, seems he also the coauthor of Emacs

2:44 This guy really stronger and powerful

2:44 mavbozo: ambrosebs is about 20s

2:44 justin_smith: definitely a smart guy

2:45 netroby: The newer programmer will not to invent a new language or new tools.

2:46 mavbozo: justin_smith, agree ambrosebs is definitely a smart guy

2:46 netroby: If the old guys dead. we have nothing left

2:46 justin_smith: netroby: there's a good video of a talk by guy steele jr. - "growing a language" https://www.youtube.com/watch?v=_ahvzDzKdB0

2:47 netroby: justin_smith: thanks

2:49 tahmid: Hello guys

2:49 mavbozo: hello

2:49 benzs129: Hello, I'm new here and have some question regard ISP. I am planing to change my ISP service from Verizon Fiios to Time warnner cable. My current plan with verizon is 75/75 down and up load speed for $140/m. The new plan that I'm currenlty consider is Time wanner 200/20 $100/m. Should I change the plan?

2:49 tahmid: In cljs how to add multiple classes using the #js

2:49 I can add one class like this #js {:className “myclass”}

2:50 But how can I add multiple classes

2:50 btw I am talking about om

8:07 J_Arcane: Seesaw seems really nice.

8:17 timvisher: justin_smith, tbaldridge, Jaood: thanks for the input. the other thing that's killing http-kit at this point as far as my org is concerned is lack of in-band https support

8:18 i keep talking about VPN with SSL termination on the outside via nginx etc. but our tech lead really wants SSL on all end points, which means that I can't use http-kit unless I also embed an SSL terminator

8:19 Glenjamin: would sit any http-kit-based server behind a load balancer, i'd have thought

8:19 so i'd usually terminate SSL there

8:20 timvisher: Glenjamin: yeah. the concern seems to be sniffing on the internal network

8:20 Glenjamin: you have an insecure internal network?

8:20 timvisher: also the goal is to have each of our services eventually be public facing, so then they'll all need SSL anyway

8:21 Glenjamin: not in any known way, but paranoia :)

8:24 mpenet: you could just use jetty9, it is fairly solid in my experience, not to mention "modern" if you need such things as async, spdy, soon http2 etc

8:25 websockets as well

8:27 we switched from http-kit a while ago, we hit some of the issues you can see in its issue tracker

8:30 pcn: I'd much rather have a proxy on localhost with ssl managed there than have to deal with java's keystore and truststore annoyances.

8:30 timvisher: mpenet: yes. that's another scary thing. maintenance seems to be tough for the http-kit devs.

8:30 mpenet: did you go with ring-jetty9-adapter?

8:30 or did you rolly our own jetty 9 dep?

8:31 s/rolly/roll/

8:31 pcn: i would too

8:31 you have any good docs to link to as far as why ssl in java isn't the best idea?

8:33 mpenet: timvisher: no we rolled our own: https://github.com/mpenet/jet

8:33 it started as a fork and ended up rewriting pretty much everything

8:33 timvisher: mpenet: nice. thanks for the link

8:34 pcn: timvisher: it doubles operational cost of e.g. maintaining CA certs. Adding and removing them are a specialized set of commands.

8:34 timvisher: mpenet: have a write up as to why?

8:35 pcn: oh man i totally forgot about that :)

8:35 mpenet: timvisher: why the switch or why the lib?

8:35 pcn: And then you have to start putting logic surrounding what is secure vs not in your code

8:35 Lutin`: anyone have tips on profiling a clojure program?

8:36 timvisher: mpenet: why you rewrote the jetty9-adapter

8:36 Lutin`: start with visualvm and see how far that gets you

8:37 Lutin`: Alright, thanks. Will take a look

8:37 mpenet: we wanted tighter core.async integration, and some of the internals of rint-jetty9-adapter where not of our liking (missing options here and there, proxy vs reify etc)

8:37 timvisher: mpenet: thanks!

8:37 danlentz: Lutin`: probably doesn't qualify as a "tip" but I recently used YourKit and criterium

8:37 mpenet: + I ended up doing client side stuff wrappers too (websocket & http clients)

8:38 Lutin`: danlentz: Counts for me! I guess I meant more like suggestions than "tips". I don't know haha

8:38 danlentz: YourKit for a statistical (?) profile and criterium to optimize hot spots

8:38 timvisher: danlentz: did you pay for it?

8:38 or was it for an opensource thing?

8:39 YourKit is definitely best of breed afaik, but it costs money for proprietary profiling

8:39 danlentz: No, it was open source but even do I just downloaded the beta version

8:39 But I think you can apply for a license

8:39 tbaldridge: yeah YK is pretty nice about handing out free copies to OSS projects

8:40 danlentz: I should do that actually. It's a very useful package.

8:41 But, my scenario was that I needed to get a high level picture of where cost was incurred during computation of UUID's

8:41 timvisher: danlentz: ah. is that feature-restricted or time restricted?

8:41 danlentz: So once I had that I focused in using criterium

8:42 timvisher: the beta is time restricted

8:42 timvisher: Lutin`: for wider application profiling and visibility you could also consider something like NewRelic

8:42 does NewRelic have first class clojure support at this point?

8:42 s/application/system

8:43 Lutin`: Right now I'm just profiling an IRC bot

8:43 trying to figure where all this memory usage is coming from for something I thought would be fairly small

8:43 danlentz: I think YourKit retails for something like $600 which is well worth it

8:44 timvisher: Lutin`: yeah. push visualvm to its limit and then see whether YK does what you need. :)

8:46 Lutin`: huh, so GC increases the PermGen size

8:46 didn't know that

8:47 maybe it's just due to the way VisualVM does it

8:48 timvisher: pcn: could you elaborate a bit more on putting code around what's secure and what's not in your code?

9:00 Lutin`: hmm so it looks like at this point most of my memory savings are going to be from removing libraries?

9:00 Only need about 10MB on the heap, but the total resident memory is around 80MB

9:02 Trying to slim this down to run on a VM with only 128MB available ram and 256MB swap, which might be a bit crazy

9:08 sveri: Hi, I want to generate some clojure code and put it into a file with a namespace and require expressions so it's working later OOTB. What would be the most idiomatic way to do this? spit clojure data structures into a file?

9:54 csd_: How can I play with async code without having to kill the repl session each time I want to stop the code? e.g. https://www.refheap.com/99362

9:54 justin_smith: Lutin`: clojure uses a lot more permgen than a normal java program would

9:54 Lutin`: but in 1.8 this is not as much of a concern

9:55 Lutin`: the issue is that every function made via fn is a new class

9:55 (or, that's part of the issue)

10:01 sobel: heh, looks i have design approval to avoid interfacing clojure to java

10:02 ...this time

10:02 justin_smith: congrats

10:03 sobel: if you do have to make your clojure accessible from java, a good option is to make a small wrapper in java code, that does the interop calls via RT to your real code

10:03 that way you can provide whatever sort of interface java coworkers expect without having to do anything weird on the clojure side

10:03 sobel: yeah, i'm going to treat it like a sql dao

10:04 justin_smith: makes sense

10:04 in-process or ipc?

10:04 sobel: it's pretty basic OO, there

10:04 in-process, when i do have to go there

10:04 justin_smith: haha, so a dao model for code within the same vm

10:05 sobel: sure, clojure is foreign enough to need that much fanfare around the interface

10:05 it keeps the abstraction tight :)

10:05 justin_smith: but with a very thin wrapper, it need not be at all

10:05 but if dao works, it works

10:05 sobel: in this case, 100% of the domain is implemented in clojure

10:06 mapping the useful bits 1:1 to java methods makes sense

10:07 mnngfltg2: ,(let [v (with-meta [1 2] {:foo :bar})] (map #(meta %) [v (conj v 3) (map identity v) (subvec v 1)]))

10:07 sobel: i got this one hammer, you see... :)

10:07 clojurebot: ({:foo :bar} {:foo :bar} nil nil)

10:07 mnngfltg2: I'm a bit confused about meta-data. When a PersistentVector has meta-data, it is preserved when modifying it, though not always.

10:08 justin_smith: mnngfltg2: yes, map and subvec are not going to preserve metadata

10:08 and yeah, vectors or maps only sometimes

10:08 and it's not good to rely on it

10:08 mnngfltg2: justin_smith, huh

10:08 is there a way to *prevent* the proliferation of metadata?

10:09 justin_smith: mnngfltg2: you could use into

10:09 mnngfltg2: My use case is that I want to know if v has changed

10:09 justin_smith: mnngfltg2: v never changes

10:09 it's immutible

10:09 mnngfltg2: yes I know

10:10 justin_smith: then you want to know if you are accessing v, or something else derived from v? = should suffice for that

10:10 mnngfltg2: true

10:10 my use case is that I keep track of an immutable collection

10:11 something outside my control makes a change and returns me a new-val

10:11 now I want to know if I've already seen new-val

10:11 justin_smith: I would keep a binding to the coll, and compare new values to it

10:12 mnngfltg2: so I could keep track of what I've seen in a lookup table?

10:13 justin_smith: sure, a stack or hash-map would make sense, depending on how your access pattern works

10:13 mnngfltg2: hm ok

10:14 if I do (assoc {} big-object :seen)...

10:14 does it store big-object once more, or just a reference to it?

10:14 i.e. a pointer

10:14 seems silly to ask that, but I'm not sure now

10:14 justin_smith: mnngfltg2: it's effectively a pointer

10:14 the only drawback is that it would prevent gc of the value

10:15 mnngfltg2: preventing gc is fine by me, for now

10:15 justin_smith: but thanks to structural sharing, this will be done fairly efficiently where it matters

10:15 mnngfltg2: alright I'll try that then

10:15 justin_smith: eg. if you have it and a modification, they can share their internals past a certain size of common elements

10:15 mnngfltg2: yes, that feature of persistent data structures I know

10:15 justin_smith: hyPiRion has a good series of articles on how that works with vectors

10:16 mnngfltg2: I've read them

10:16 justin_smith: oh, cool :)

10:16 * mnngfltg2 is a big fan :)

10:16 mnngfltg2: it'a pity my meta-data approach doesn't work though

10:16 justin_smith: I would think that in that case one would know that the assoc didn't do a full copy :)

10:17 mnngfltg2: justin_smith, I suspected it

10:18 it would have been cool to just tag the vector itself so I can check if I've already written it to disk

10:18 justin_smith: mnngfltg2: yeah, metadata doesn't work that way though (as you've seen)

10:19 if you are tracking items and whether you have seen them, a set seems a natural fit for that

10:19 mnngfltg2: I wonder what's the rationale behind the "transitivity" of metadata

10:19 justin_smith: mnngfltg2: it's a weird abstraction leak to be sure

10:19 (exposing when the collection gets promoted up to a bigger vector)

10:19 mnngfltg2: rich must have had some use case in mind when he added that feature

10:20 sobel: ok, i started a simple lein app project and now i want to change its namespace to match with some java code. do i need to modify my src tree same as java package spaces?

10:20 or should i just make a new project and drop my ONE source file into it

10:21 justin_smith: sobel: yeah, I would think so. There is a project for automating this sort of namespace refactor, but I forget the name.

10:21 from technomancy iirc

10:21 sobel: was it vinyasa?

10:22 guess i'll try it by hand once just to see it break

10:22 justin_smith: no, that isn't for refactoring at all is it?

10:23 mdrogalis: justin_smith: Slamhound

10:23 justin_smith: sobel: for emacs, there is clj-refactor

10:23 mdrogalis: AHA!

10:23 (inc mdrogalis)

10:23 lazybot: ⇒ 8

10:23 justin_smith: that's the one

10:24 mdrogalis: That's the first thing I've said on here in ages!

10:24 mnngfltg2: sobel, yes the directory layout needs to match the one.two.three class hierarchy in clojure (as in java)

10:24 justin_smith: sobel: https://github.com/technomancy/slamhound makes this stuff easy

10:26 * justin_smith goes to add slamhound to his default :dev profile libs

10:30 yellow13: hi there! https://www.refheap.com/99364

10:30 i was wondering which of these is more idiomatic

10:30 justin_smith: so you want to return nil if url is nil?

10:31 it would be more typical to return page unchanged if url is nil, or page with a new url assoc'd on if it isn't

10:34 yellow13: some function will upload a file and produce a url if it suceeds

10:34 then im gonna put that new url on the page

10:34 im not sure how to remember the pages where the upload failed

10:35 thats why change-page-url accepts nil

10:35 justin_smith: OK

10:36 yellow13: if you either return a modified page, or nil, then the surrounding code needs a conditional to replace something it has, or do nothing

10:36 if you either replace page unmodified, or update its :url key, then the caller can unconditionally use the result

10:37 that's the kind of pattern I would see in my own code, at least

10:45 yellow13: justin_smith: the original idea was this (map pages #(some->> % upload-page (change-page-url %)))

10:45 resulting in [nil {:url "a"} nil] then ill save on mongo the updated pages

10:46 im trying to wrap my head around the functional way, ima mainly a php dev

10:55 sobel: hope slamhound works...bout to attempt it through the LT plugin

10:57 justin_smith: yellow13: oh, you have the args to map reversed, but that could make sense

10:58 yellow13: just, in my experience, having the default be the unmodified thing rather than nil tends to usually simplify my code

11:00 sobel: i must say, i love RainbowParens

11:00 sliced bread, etc

11:01 timvisher: sobel: i should really turn that on at some point

11:01 paredit makes much more of a difference for me though :)

11:01 sobel: yeah, i use that too.

11:01 but even with paredit, it's still easy enough to get lost in nests

11:01 the_frey_: paredit > rainbow parens

11:01 sobel: paredit + rainbowparens

11:05 zerokarmaleft: paredit + show-paren-mode is a bit more subtle...I find the additional color distracting

11:06 sobel: maybe i'll get tired of it later. surely helping me for now, though.

11:10 timvisher: has anyone written a ring adapter using netty?

11:10 sorry... should have googled https://github.com/RallySoftware/netty-ring-adapter

11:10 sobel: hm, still not clear how i would use slamhound to refactor my src. just want to change the package space and get the dirs/files handled by it

11:11 mpenet: timvisher: aleph is likely more stable/advanced

11:13 timvisher: mpenet: good point

11:14 justin_smith: sobel: move the namespaces to where they should be in the directory structure, and use slamhand to fix the ns forms

11:16 sobel: noice

11:19 hm, it didn't seem to pick up the file/pkg changes

11:38 danlentz: Anyone yet had a look at "Clojure Applied"?

11:38 https://pragprog.com/book/vmclojeco/clojure-applied

11:39 justin_smith: danlentz: I'd give it a positive just because puredanger is one of the authors

11:39 though I don't have the book

11:39 danlentz: He should just write under the name puredanger

11:39 arrdem: just going from the clj-public post it looks interesting

11:40 justin_smith: hehe

11:40 arrdem: I'd read it expecting to learn something

11:40 justin_smith: arrdem: and write everything in the form of superhero comics

11:40 arrdem: hahah

11:40 * arrdem should have found a more awesome handle

11:41 justin_smith: I mean, if we're talking about uncreative handle choice...

11:42 arrdem: oh you win at that hands down

11:42 for some definition of win

11:42 danlentz: Half of developers use their real name but a fake avatar, the other half use their real profile picture with a fictitious name.

11:43 sobel: i stole mine from something i heard a grunt say in warcraft3

11:43 arrdem: my initials are "R D M" and if you slur that a bit...

11:43 szatz: just discovered transients. the post on them says not to bash in place, but the example calls conj! over a range. is this not bashing?

11:44 justin_smith: szatz: bashing is using conj! but not using the return value

11:44 arrdem: szatz: link? it's only bashing if you don't use the return value

11:44 justin_smith: tl;dr: use the return value

11:44 arrdem: I should just give up and let justin_smith have all the low hanging karma

11:44 szatz: http://clojure.org/transients

11:44 justin_smith: hahaah

11:44 * arrdem doomed to sub-50

11:45 justin_smith: arrdem: your turn, I'll peace out for a bit

11:45 arrdem: god save us

11:46 justin_smith: szatz: in the example on that page, it's not bashing it because (conj! v i) is an arg to recur

11:46 which means the return value is captured and used

11:46 szatz: sorry if this sounds silly, but in what situation would one not use the return value?

11:46 justin_smith: szatz: if you were coding as if it were java

11:47 danlentz: Could someone give me the address of the website where I can cash in irc karma for cool gifts and prizes? I seem to have misplaced it.

11:47 arrdem: when you are abusing update in place

11:47 danlentz: I have a bridge I'd like to interest you in

11:47 justin_smith: $karma justin_smith

11:47 lazybot: justin_smith has karma 235.

11:47 szatz: thanks to all you guys for jumping all over this, btw.

11:48 justin_smith: nice, almost enough to get the collectable beer-koozy

11:48 sobel: why does using the retval make it not bashing?

11:48 arrdem: sobel: first, convention, second the transient contract does not guarantee that updates will always occur in place

11:49 szatz: hmm, OK re: "like java." maybe me not getting it is a good thing.

11:49 justin_smith: sobel: ##(let [h (java.util.HashMap.)] (.put h :a 0) h)

11:49 lazybot: ⇒ {:a 0}

11:49 justin_smith: sobel: it's not bashing because the args to recur are the new bindings for the next iteration

11:50 szatz: sorry, I miss-directed this before ##(let [h (java.util.HashMap.)] (.put h :a 0) h)

11:50 lazybot: ⇒ {:a 0}

11:50 justin_smith: that's java style - notice I modify h but don't use the return value of the .put method

11:50 sobel: so it's not bashing because the retval is used inside the loop scope

11:50 justin_smith: sobel: right

11:50 sobel: think i got it

11:51 justin_smith: sobel: bashing is if you ignore the return value, and then just use the thing it implicitly (probably) modified

11:51 that is error-prone with transients - it works until it doesn't

11:51 with no warning

11:51 sobel: there was a related discussion in the cljs minecraft demo, about giving in to bashing a JS array on the inner loop because it was sooooo performant

11:52 justin_smith: sobel: yes, if something is performance critical, bashing an array in place is almost always the best option

11:52 but it also leads to less than sane code

11:52 if used without discretion

11:53 less so in js where "arrays" aren't

11:53 but the general principle still holds

11:54 arrdem: justin_smith: worth mentioning doto

11:54 justin_smith: yup

11:55 sobel: yes, all was caveated appropriately, then they bashed that array for a pretty sweet 3d render loop in cljs

11:56 justin_smith: cool - yeah trying to do that with persistent data structures would likely be bad for your frame rate, on today's hardware at least

11:56 szatz: justin_smith: so the mutating call should always be inside another call? is that the gist?

11:57 justin_smith: szatz: yeah - the return value of the conj! or whatever should be replacing your binding

11:57 whether that's because it becomes an arg to recur, or the return value of your reducing function, whatever

12:00 szatz: OK, I got it. I think I got tripped up because there are two returns going on when transients are used correctly, it seems.

12:00 one from the mutation, and one to move that value to whatever's next.

12:02 justin_smith: szatz: it's the same way it would look if you were using conj in a loop

12:02 the only reason it is tricky is because conj! will sometimes work as if it updated in place - it's just that this is not guaranteed to work and should not be relied on

12:04 szatz: justin_smith: yeah, i got it. thanks a lot.

12:05 oddcully: is map killing a binding? as in (binding [*a* b] (map ...))?

12:06 arrdem: oddcully: map is lazy, binding is eager. If you are relying on dynamic bindings to pass values into your mapped function, you're gonna have a bad time.

12:07 justin_smith: (inc arrdem)

12:07 lazybot: ⇒ 43

12:07 timvisher: this is probably not sensical, but `lein deploy` doesn't appear to be able to deploy war files, only jars.

12:07 arrdem: oddcully: prefer partial application of the mapped function if possible.

12:07 timvisher: that's accurate right?

12:08 justin_smith: timvisher: I use lein beanstalk to deploy wars

12:08 err... to beanstalk at least :)

12:08 timvisher: justin_smith: do you use lein release?

12:08 justin_smith: never tried it

12:08 oddcully: arrdem: thanks. this right now is just some test code and it tripped me over. so i am not sure right now, if binding is the best thing in my case anyway

12:09 arrdem: oddcully: binding is generally discouraged for playing really badly with lazy sequences and implicit lazy behavior

12:09 justin_smith: oddcully: general rule with binding and with-* macros -- force any laziness before it leaves scope, and if that isn't a good idea, that macro isn't a good idea

12:10 arrdem: shout out to Chas.. http://cemerick.com/2009/11/03/be-mindful-of-clojures-binding/

12:10 justin_smith: does lazybot have factoids on?

12:11 since I can't use clojurebots

12:11 mpenet: justin_smith: transients are not always faster than normal maps btw, depends on the usage pattern really (calling persitent!/transient has a cost)

12:12 *persistent!

12:12 justin_smith: mpenet: very true

12:12 oddcully: thanks, guys. i guess i will look for something other than bindings

12:12 (inc arrdem)

12:12 lazybot: ⇒ 44

12:12 arrdem: sure thing. good luck!

12:12 justin_smith: arrdem: I forget the name of the plugin, but I think so

12:13 arrdem: justin_smith: https://github.com/Raynes/lazybot/blob/master/src/lazybot/plugins/knowledge.clj ?

12:14 justin_smith: $addtopic help lazybot can organize help in topics

12:14 lazybot: justin_smith: It is not the case that you don't not unhave insufficient privileges to do this.

12:14 justin_smith: arrdem: it's in help.clj, but you need perms to add topics :(

12:14 arrdem: laem

12:14 justin_smith: arrdem: knowledge is for some natural language query system api iirc?

12:14 arrdem: clearly the only choices I have are to roll yet another bot or write a bunch of elisp macros for frequently linked articles

12:15 * justin_smith starts chanting E-LISP E-LISP

12:16 sobel: do you have a db behind clojurebot?

12:16 arrdem: my elisp foo is amazingly weak. I have bbatsov and john2x for that

12:18 hiredman: clojurebot currently is storing factoid data in postgres

12:27 sobel: hmm.. i renamed everything but somehow lein is still trying to find old names. i hit my src directory structure, ns declaration, and related names in project.clj

12:39 gah, i just found a file out in /tmp with info i am trying to refactor.. how do i make lein clear its cache?

12:39 justin_smith: sobel: have you been doing all this without restarting lein?

12:42 sobel: no

12:42 i am not using lein except to build uberjar for the most part

12:44 justin_smith: in that case you may need lein clean

12:44 sobel: oh, maybe LT is making that cache

12:44 i did lein clean

12:45 why would it be looking for foo/bar_baz.clj after i changed its filename and project.clj reference to foo/bar-baz.clj

12:48 nuwanda__: sobel: pretty sure every - turns into _ when dealing with file names

12:48 oddcully: sobel: it is _ for dirs. so for sure also for file names then too

12:50 sobel: oh. yuk.

12:50 i wasn't aware of that mangling.

12:52 oddcully: i bet it's for this popular non-unix-os

12:53 justin_smith: it has to do with what java accepts as a package name

12:58 yellow13: can a function like this #(foo %1) receive args and disacrd them?

12:59 arrdem: ##(println (quote #(foo %1)))

12:59 lazybot: ⇒ (fn* [p1__46534#] (foo p1__46534#)) nil

13:00 arrdem: yellow13: you would have to use the term %& and ignore its value IIRC

13:00 ##(println (quote #(let [_ %&] (foo %1))))

13:00 lazybot: ⇒ (fn* [p1__46545# & rest__46544#] (let [_ rest__46544#] (foo p1__46545#))) nil

13:18 TimMc: yellow13: Sure, but it would be clearer to say (fn [_] foo) rather than using #() and adding hacks to get around that.

13:18 or (fn [x & _] (foo x))

13:19 _ is a convention for "unused value"

13:20 sobel: thx all, that fixed me up

13:21 oh i just realized i'm jerk for making a class with _ in it

13:22 yellow13: TimMc: youre right

13:22 i was just thinking about the possibilities

14:50 pbx: apparently i unknowingly broke something in my lein/clojure setup in the past hour. lein now dies with a core dump: http://dpaste.com/06KSQQP#wrap

14:52 sobel: pbx: commit early, commit often?

14:54 pbx: sobel, to clarify i didn't knowingly change anything between when it worked a couple hours ago and this. i have no project, this happens with a bare invocation of lein

14:54 the offending line fwiw: http://dpaste.com/01XQ5CR

14:59 andyf: sobel: Eastwood linter can help quickly find file name / namespace mismatches. Plus done other things

14:59 S/done/some/

15:01 ~Eastwood

15:01 clojurebot: Pardon?

15:01 andyf: Can someone in the know make that link to github URL for Eastwood?

15:01 rrraaafff: https://github.com/jonase/eastwood

15:02 Bronsa: ~eastwood

15:02 clojurebot: eastwood is https://github.com/jonase/eastwood

15:03 dnolen: Bronsa: looks like Alex Miller wrapped up the conditional reader patch, let me know when you can get that applied + released. Would like to push a new ClojureScript release by Friday so people can actually use and test this stuff.

15:03 Bronsa: dnolen: I'm already looking at it :)

15:03 dnolen: Bronsa: k cool, thanks! :)

15:03 justin_smith: pbx: are you using a super old version of lein?

15:04 pbx: justin_smith, not to my knowledge no

15:04 justin_smith, again, it worked two hours ago

15:04 so it's clearly my fault but how i do not know

15:04 lein 1.7.1

15:04 Kowryh: what development environment do you guys use?

15:05 I'm on this course that uses lighttable, I've found it pretty good (on Linux)

15:05 justin_smith: pbx yeah, that is ancient

15:06 pbx: at least try lein 2.x

15:06 pbx: justin_smith, interesting. orthogonal to my problem but probably worth fixing anyway. i installed from the ubuntu software center

15:06 andyf: It would be funny if running 'Lein ancient' with old versions of Lein replied with 'yes, I am.'

15:06 justin_smith: pbx: it's a very old version of lein, I would not be surprised if things in newer libs break it

15:07 andyf: haha

15:07 pbx: don't use a package manager for lein, lein is better at managing deps (including its own) than your package manager is

15:07 I also use ubuntu

15:08 pbx: justin_smith, yeah, i wanted it to be available to all users and the leiningen.org method was one-user, but i'll work around

15:08 puredanger: Bronsa: would be interested in any review on latest reader conditionals patch for tools.reader http://dev.clojure.org/jira/browse/TRDR-14

15:08 pbx: thanks for the help

15:09 justin_smith: pbx: it's a single shell script, you can put it in a place that is on everyone's PATH

15:09 oddcully: Kowryh: vim-fireplace and cursive

15:15 Bronsa: puredanger: I'll let you know, might take me a couple of hours -- not the most lightweight of patches

15:18 puredanger: yeah, it was a pain. no urgent rush. David is still working on the cljs side of it.

15:41 katratxo: hi all, i'm trying to use s3-wagon-private to deploy some library code and i'm getting an Access Denied error (the .jar and some other files end up in the bucket) ... i've tried the technomancy and circle fork ... any hint on what can be wrong?

15:41 i'm using an `iam` user that has full access to that bucket

15:51 ncthom91: hey all. I'm working on a small project involving creating a simple tree. This alone is a pretty simple task, but I'd also like to keep an index into the tree for quick access to each node. The way I've been building this involves side effects which update an (atom {}) representing my index, which causes some headache errors when lazy evaluation yields before hitting the side effect I was expecting. Surely this isn't the clojure

15:51 way... how would you approach maintaining an index like this while assembling a tree or graph structure?

15:53 cfleming: So I'd like some suggestions for how to show seqs in the debugger

15:53 I'm planning to have custom renderers for LazySeq, Cons and IChunkedSeq

15:54 For LazySeq I'll display all the realised elements up to a limit, and for Cons I'll show all elements also up to a limit

15:55 For IChunkedSeq it looks like I can call chunkedFirst, and display that whole chunk, but I'm not sure how/if I should handle chunkedNext and chunkedMore

15:56 For other ISeq implementations I'm not sure what to do

15:57 amalloy: cfleming: it's more complicated than that, right? like a sequence isn't any one of those things, necessarily, but an amalgam

15:57 cfleming: amalloy: Yeah, I'll actually probably have a single Seq renderer, and handle those three cases

15:57 amalloy: eg, (iterate inc 1) is a Cons, followed by a LazySeq

15:58 puredanger: not anymore it's not...

15:58 amalloy: well

15:58 cfleming's going to want his renderer to work on 1.6 anyway, i'm sure. and this was just an example

15:58 cfleming: And... right, I don't know how, or if, all this ties in with transducers

15:58 puredanger: for sure

15:58 it doesn't

15:59 cfleming: Right, they're just consumption rather than production, right?

15:59 puredanger: you might want to make sure eduction does something useful though

15:59 Eduction that is

15:59 cfleming: Ok, I don't really understand how that works, I'll read up on it.

16:00 puredanger: Calling eduction returns an Eduction instance, which is an implementation detail, but it will implement Iterable and IReduceInit, but not sequence

16:01 cfleming: But amalloy is right, I definitely need a combined renderer. Is there an example anywhere of how to iterate the realised values of a chunked seq?

16:01 puredanger: first and next work pretty well :)

16:02 cfleming: So in the case of a chunked seq, it doesn't have the concept of realisation in the same way? I wanted to iterate the realised elements, but I may be misunderstanding how that works.

16:02 puredanger: they're all seqs, so you can always walk them as such

16:03 cfleming: Right, but for LazySeq at least, I only want to walk the realised elements, and not provoke realisation if the user hasn't asked for that

16:03 Is LazySeq really the only special case, then?

16:04 All other ISeqs I just walk them until either I'm done or I hit my limit?

16:04 puredanger: sure

16:04 chunked seqs (ChunkedCons) will realize 32 at a time - I'm not sure if you care though

16:05 cfleming: Ok. Eduction might be tricky, I'll have to check what the debugger does currently with Iterables

16:05 puredanger: Iterable produces an Iterator, which is stateful

16:05 cfleming: And I'll never encounter an Eduction instance walking a seq, since they're not really seqs, right?

16:06 Right, so I'm not sure I actually want to do anything with that.

16:06 puredanger: right

16:06 cfleming: So Eductions might be tricky to display

16:06 puredanger: you could wrap an iterator-seq around it of course

16:07 and treat it as a seq - as of 1.7 iterator-seq will also be a chunked sequence

16:07 cfleming: Hmm - I think I'll get seqs to do something useful first, and then worry about eduction

16:07 puredanger: sure

16:08 cfleming: Actually, while I have you, I have another related question. When I'm reading the indices in IntelliJ, they use a process() model, where I pass it essentially a function which is invoked for the elements of the index

16:09 puredanger: like nth?

16:09 cfleming: What's the best way to use a push model like that with transducers/seqs, which are a pull model.

16:09 Bronsa: puredanger: any reason I'm missing why return-on-value is a parameter rather than just being READ_FINISHED hardcoded?

16:09 puredanger: Bronsa: hang on :)

16:09 cfleming: puredanger: No, this is more when I'm handling, say, all the values I have indexed for a particular ns

16:10 puredanger: cfleming: not really getting what you're asking

16:10 cfleming: I give intelliJ what is essentially a function, and it calls that function for each matching element. What I currently do is use an atom, and put the elements into a vector, which I then return when process() is done.

16:10 puredanger: Bronsa: good question - this might be an artifact of how the Clojure patch evolved, let me double-check

16:12 cfleming: so it controls the iteration and processing model

16:12 cfleming: Right

16:13 puredanger: So now I'd like to actually do my processing as I'm called back, so I'm not buffering a bunch of values - this places an unnecessary delay on autocompletion

16:14 puredanger: something like core.async channels and go blocks right?

16:14 cfleming: puredanger: It seems like a transducer might work well here, since I could create my processing logic and then either create a process() which calls the transducer or just run the transducer over a collection for the cases when I actually have a collection.

16:15 Hmm, maybe - I was hoping there was a simpler solution

16:15 puredanger: you could use the same transducer with either transduce or with an async channel

16:15 jcromartie: what's the *right* way to implement the associative interfaces

16:16 cfleming: puredanger: Right. I'll play around with that idea and see what I come up with.

16:16 puredanger: Thanks.

16:16 puredanger: cfleming: the hard part is really the inversion of control

16:17 cfleming: puredanger: Yeah, that's what's difficult, since sometimes it controls the processing model, and sometimes I do.

16:18 puredanger: But I'd like to be able to use the same logic. I haven't played around with transducers enough to know how I'd make that work, but from what I understand it seems like a good fit.

16:18 puredanger: channels are reducible too

16:21 Bronsa: I think you're probably right.

16:21 ircxy: Shouldn't (read-string nil) return nil instead of throwing a NPE?

16:23 Given the NPE behavior I have to wrap with an if. (if x (read-string x) nil)

16:27 puredanger: why are you trying to read a nil string? this seems like correct behavior - trying to read a string, but found nil.

16:28 kungi: OMG! Cider has a debugger now. This is so awsome!

16:29 danlentz: puredanger: purchased my beta copy of Practical Clojure. That's you?

16:29 puredanger: yep! thanks!

16:30 ircxy: puredanger: I'm validating required and optional parameters on a rest call. When the optional params are not given they're nil. When they're both nil it's valid, both provided also valid.

16:31 puredanger: danlentz: oops, I assume you meant Clojure Applied :) Practical Clojure is Luke VanderHart and Stuart Sierra

16:32 danlentz: Right, sorry

16:32 puredanger: danlentz: (also a good book!)

16:33 ircxy: it may not match up for your particular use case, but current behavior is consistent with many other parts of Clojure

16:33 danlentz: You should just author under the name puredanger so people would just know to buy the book.

16:33 ircxy: puredanger: min and max are optional rest params, but they must either both be there of not. (xor min-param max-param) So if they're both given validate them, like min < max, etc.

16:33 justin_smith: ircxy: (some-> x read-string)

16:34 ,(some-> "hello" read-string)

16:34 clojurebot: hello

16:34 justin_smith: ,(some-> nil read-string)

16:34 clojurebot: nil

16:34 ircxy: justin_smith: cool, didn't know about some->. thanks.

16:34 justin_smith: ircxy: it also does chaining like -> does

16:34 but stops at the first nil, and I think in this case it is clearer than an if

16:35 ircxy: justin_smith: learned something. tx

16:39 danlentz: Pragmatic seems to turn out quality texts more consistently than packt, in what limited experience I've had. Although I've also been learning a lot from Leonard Borges Reactive Clojure

16:40 Quite a month in clojure publications

16:47 puredanger: danlentz: pragmatic has a much stronger and more rigorously enforced house "style than any publisher I know

16:49 danlentz: Coming over from common-lisp, this sensation of having new texts published all the time for clojure is quite a nice thing

17:04 szatz: hello, again. after seeing how transducers can get rid of computation in a scenario like (into [] (comp (take 2) (map some-fn)) big-collection) vs. older style, it seemed like just further laziness. Something similar can be done by default in Haskell: take 2 $ map someFn bigCollection. i feel like there's more to transducers that i'm missing. can anyone offer guidance?

17:06 mikerod: szatz: I guess I don't know if Haskell allocates intermediate sequences there.

17:06 raspasov: szatz: they can be applied to core async channels, and potentially other things in the future

17:06 mikerod: I also do not know if there is a sort of "thunking" setup laziness overhead in Haskell

17:06 hiredman: mikerod: it does, without adding stream fusion or whatever

17:06 szatz: mikerod: given that you can take 2 $ map someFunction [1..] means it doesn't.

17:06 mikerod: or listen to hiredman, but you get a result with an infinite list.

17:07 mikerod: szatz: transducers will run the composed function in one pass over the input data producing the output structure - no further allocations and no necessary lazy-thunking overhead

17:07 hiredman: szatz: that doesn't mean anything about if intermediate results are generated, it just means they are lazy

17:07 (the [1..] bit)

17:07 mikerod: hiredman: yeah, I thought it would

17:07 I don't know at all about the stream fusion stuff - I've just heard the name

17:08 szatz: hiredman: so the thunking (which seems inexpensive, but perhaps i'm wrong) is the only overhead from the Haskell one?

17:08 hiredman: szatz: I dunno

17:08 mikerod: szatz: and intermediate seq allocation potentially

17:09 perhaps :)

17:09 hiredman: szatz: it can seem inexpensive, but igven the effort people have gone through to make stream fusion work, obviously it can be expensive enough

17:10 mikerod: I can't imagine how that would work - sounds magical

17:10 I guess when the compiler can't figure it out, it just falls back to the normal style

17:10 szatz: hiredman: ok, that's fair.

17:11 mikerod: However, isn't there a concept with transducers that the tranducer "process" itself can be sort of optimized for specific usages. So like `into` is "aware" that laziness is not needed. The composed functions are just applied as a single fn per item that passes through the process.

17:12 So you can write transducer processes for different types of scenarios. `transduce` vs `sequence` vs `educe` vs etc

17:13 justin_smith: mikerod: right, but the main advantage of that is bypassing the thunking

17:13 mikerod: justin_smith: yeah, I'd figure so

17:13 Well there is the difference of caching vs non-caching

17:14 in other scenarios

17:14 Does Haskell cache realized lazy elements?

17:14 time to know more about Haskell I guess :(

17:17 amalloy: mikerod: haskell caches all computed values that you save a reference to

17:17 "caches", of course, since like...what else would it do

17:18 justin_smith: I wonder what a language that doesn't do that would look like

17:18 mikerod: I mean caching in the sense of computing the value once

17:18 not in the sense of throwing away referenced objects or something

17:18 amalloy: mikerod: in java, when you write: int x = 2 + 2; is the compiler caching x?

17:18 mikerod: educe vs sequence

17:20 so in Clojure if I have a lazyseq it is a bunch of thunks that delay teh computation. when the element is needed it is realized and cached - thunk isn't called anymore.

17:21 that's what I mean by caching.

17:21 So if Haskell returns an infinite lazy collection and one caller wants 5 elements. the next caller wants

17:21 6

17:21 is only 1 new computation done

17:22 amalloy: mikerod: all values in haskell start as thunks, which are cached if you save a reference to them

17:22 mikerod: (assuming the first caller is done with those 5 references)

17:22 amalloy: if all references disappear, does it start from scratch again?

17:22 amalloy: that's impossible

17:23 how could you reuse an object with 0 references to it?

17:23 mikerod: scope?

17:23 clojurebot: scope is at http://paste.lisp.org/display/73838

17:23 mikerod: caller needs a few values of an infinite seq to figure something out then doesn't need them anymore

17:23 I'm not seeing how that is an impossible scenario

17:24 amalloy: mikerod: it's not impossible, but it's not having 0 references to the object

17:24 mikerod: oh, ok

17:24 amalloy: because you're assuming the second caller somehow gets a reference to the same seq

17:24 which means that the original seq still had a reference to it somewhere

17:24 mikerod: I see what you mean. So they are cached indefinitely.

17:24 amalloy: uhhhh

17:24 they are cached for as long as you have a reference to them

17:24 mikerod: yes

17:24 I get it, sorry

17:34 szatz: sorry if i'm being hard-headed, but i'm still not clear on if there is more to transducers than avoiding the thunking?

17:34 perhaps it's because the concept ports "easier" to other languages that don't support laziness as strongly as Haskell?

17:35 mikerod: My point on caching was that with educe you can have a lazy computation that you don't retain the results if they are not held specifically. So the computation will happen again. But I give up on that topic I guess. I've alos noticed it is really hard to search for `educe` on the internet.

17:35 it just gets fixed and assumed to be `reduce` :P

18:10 pandeiro: is there any hope for clj-webdriver or is the compatability battle a lost cause?

18:24 ambrosebs: how can I throw an exception from nREPL middleware without stopping the entire REPL?

18:25 do I manually set e* and prn the exception?

18:25 that sounds sane enough

18:25 justin_smith: as a user, I would find the fact that I couldn't catch and handle it confusing

18:26 ambrosebs: I don't want the user to catch it, I'm piping code through core.typed for checking

18:27 justin_smith: my usual assumption would be that if I saw an exception printed (or what looked like an exception being caught and printed) I could catch it myself nad handle it some other way. But if this is totally not interactive I guess that's another thing.

18:28 ambrosebs: makes sense

18:28 it would be like catching a type error in Haskell. not advised.

18:28 so perhaps setting e* doesn't make sense either

18:29 justin_smith: I guess this is a strange beast - it deserves printing and handling but shouldn't be caught or handled - maybe you don't want an exception, you just want sternly worded logging?

18:29 *shouldn't be caught or handled outside of your middleware, of course

18:30 ambrosebs: yes this is what I want

18:30 justin_smith: yeah, I would say logging with level of WARNIGN or SEVERE ?

18:31 ambrosebs: ,(throw 1)

18:31 clojurebot: #error{:cause "java.lang.Long cannot be cast to java.lang.Throwable", :via [{:type java.lang.ClassCastException, :message "java.lang.Long cannot be cast to java.lang.Throwable", :at [sandbox$eval25 invoke "NO_SOURCE_FILE" -1]}], :trace [[sandbox$eval25 invoke "NO_SOURCE_FILE" -1] [clojure.lang.Compiler eval "Compiler.java" 6784] [clojure.lang.Compiler eval "Compiler.java" 6747] [clojure.core$eval ...

18:31 ambrosebs: right, I want something special like that

18:31 but no return value

18:31 but it's not an "exception" either

18:31 justin_smith: right, so just a WARNING log or a SEVERE log I'd say

18:32 it will get attention, but it doesn't affect control flow

18:32 ambrosebs: well I'm going to throw away the REPL interaction if we get a type error

18:32 hiredman: why don't you want users to be able to catch it

18:33 ambrosebs: hiredman: this is a simple typed repl: code goes in, return or type error comes out

18:33 I'm not sure what catching a static type error would mean

18:34 core.typed already exposes primitives for type checking arbitrary code, which you can call if you need to "catch" type errors

18:34 hiredman: ambrosebs: sure, but like, we can't think of a reason to allow that now, is it a good idea to rule it out?

18:35 what is the harm of allowing users to catch it if for some crazy idea they want to?

18:35 ambrosebs: hiredman: I don't even know what this would look like.

18:35 hiredman: so throw an exception and whatever

18:35 ambrosebs: hiredman: you can't catch a static type error in any typed langauge I know

18:36 hiredman: *shrug*

18:36 the compiler throws exceptions

18:36 ambrosebs: do you mean I should populate e* ?

18:37 hiredman: I dunno, just throw an exception

18:37 *e is a property of the repl implementation you use

18:37 ncthom91: http://stackoverflow.com/questions/840190/changing-the-current-working-directory-in-java is there really no way to change the cwd in clojrue?

18:37 ambrosebs: right. I'm implementing nREPL middleware and I don't know how to simply throw an exception. It seems to just kill the entire repl.

18:38 must be some special handler to do so.

18:38 hiredman: ambrosebs: oh, right, the thing to do there is send a response message explaining the error

18:38 ambrosebs: when dealing with nrepl, you are doing rpc

18:39 justin_smith: ncthom91: it's a portability problem

18:39 hiredman: ambrosebs: you are not in a single jvm, throwing exceptions doesn't exist

18:39 justin_smith: ncthom91: there's an answer that works for like everything but windows

18:39 ambrosebs: hiredman: aha

18:39 hiredman: setting *e doesn't exist

18:40 https://github.com/clojure/tools.nrepl#handlers has a section that mentions error keys in nrepl messages

18:40 ncthom91: justin_smith hm... that's a bummer. I'm working on a tool that will look for a config file in the cwd... would like to set up a "mock" directory structure within my project to test within

18:41 justin_smith: ncthom91: if you don't need windows support, it can be done

18:42 ambrosebs: hiredman: seems like I want a {:status :error} entry, where do I put the error message?

18:42 ncthom91: justin_smith sure. how can I do that?

18:43 justin_smith: ncthom91: it requires using jna to change the PWD environment variable

18:44 turns out "current directory" is just that one var in your env

18:44 ncthom91: https://github.com/arohner/lein-daemon/blob/master/daemon-runtime/src/leiningen/daemon/runtime.clj

18:44 hiredman: ambrosebs: checkout some other middlewares I guess, https://github.com/clojure/tools.nrepl/blob/master/src/main/clojure/clojure/tools/nrepl/middleware/interruptible_eval.clj#L55

18:45 maybe you just put the message in :out or something

18:46 justin_smith: ncthom91: but even that is not portable to Linux - he uses user.dir instead of PWD (I guess osx must use user.dir?)

18:47 oh, getProperty not getenv

18:47 I've got that confused

18:48 ncthom91: this may be more helpful http://stackoverflow.com/questions/840190/changing-the-current-working-directory-in-java/8204584#8204584

18:49 ncthom91: the magic lines in that gist are line 45 and line 45

18:49 err, 35 and 45

18:56 ambrosebs: hiredman: struggling to find where :status is actually checked

19:00 ncthom91: justin_smith cool, thanks

19:03 hiredman: ambrosebs: a client would use it

19:04 ambrosebs: like leiningen?

19:04 hiredman: ambrosebs: tools.nrepl has a simple client, but tools.nrepl is mostly just the server

19:04 ambrosebs: reply is the client leiningen uses

19:04 cider contains a client written in elisp

19:04 etc

19:05 ambrosebs: ok

19:30 daviid: how do i write (let ((i 0)) ... (when something (set! i (+ i 1)))) in clojure ?

19:31 amalloy: daviid: first, embed a common lisp interpreter

19:32 (you can't mutate locals)

19:32 daviid: amalloy: i know, what would you write to get the same result ?

19:33 amalloy: something else. (let [i (if something 1 0)] ...), for example. the stucture will depend on why you think you need to mutate it

19:41 daviid: amalloy: here is a code extract: http://paste.lisp.org/+35CI where i have an ep variable init to 0 and i need, somehow, to increment it [last line, scheme code on purpose] and use it in the write-pp-h call, how woulkd you write that in proper clojure ?

19:41 tolstoy: daviid: Maybe (loop [i 0] do-something (recur (inc i))) if do-something has side effects, or reduce if not?

19:43 amalloy: yeah, the answer is to not use dotimes probably

19:44 although honestly even in CL this structure wouldn't work, because you're initializing a brand-new `ep` in every iteration of the loop anyway

19:44 daviid: amalloy: yes i did paste too quickly :) the ep is out the dotimes ...

19:45 but still, i just don't know

19:45 how do we write proper clojure for this trivial example?

19:45 amalloy: (loop [i 0, ep 0] (let [...] (when (< i obj-num) (let [...] (if ... (do (write-whatever) (recur (inc i) ep)) (recur (inc i) (inc ep)))))))?

19:46 it's hard to say exactly, because this paste is kinda vague in what you expect to happen inside of the if/dotimes

19:46 oh, and i wrote too many lets. doesn't matter really

19:47 daviid: but you got the quizz right? i have an external let holding ep, a loop of what ever construct, and i want to increment ep when an object is smaller then ..

19:47 tolstoy: The idea is to use recursion (or reduce) to produce a value and return it.

19:47 amalloy: daviid: yeah the idea is to not do that

19:48 daviid: tolstoy: reduce won't work, or show me

19:48 as i said, i'm learning, please tell me

19:48 an example

19:48 amalloy: i did show an example

19:48 i don't understand your followup "you got the quizz right"

19:53 tolstoy: (loop [i obj-nb ep 0] (if (zero? i) ep (do (whatever) (recur (dec i) (if (min-max-thing) (inc ep) ep))

19:54 Something like that.

19:54 ?

19:54 justin_smith: daviid: you can't change ep if something else holds it - you need to return it from your loop

19:55 tolstoy yeah, that looks about right

19:55 tolstoy: You could use reduce, but that "write" thing suggests a side-effect.

19:55 daviid: ok, recursive function i can write, i'll try that because these loop construct i am not so familiar with, but thanks all of you!

19:56 justin_smith: daviid: loop is like a recursive function

19:56 daviid: tolstoy: the 'write' is a funct5ion which writes the file which is a crop of the original image

19:56 justin_smith: daviid: be careful, in clojure recursion is not optimized (except via recur)

19:56 daviid: oh! id that true?

19:57 justin_smith: daviid: if you call recur it's fine

19:57 just don't expect normal recursion to be optimized as a tail call

19:57 daviid: oh too bad

19:57 i love tail call recursive 'style'

19:58 but let me try one of yur examples

19:58 justin_smith: the only difference is calling recur

19:58 instead of your own function

20:06 Bronsa: dnolen: fixed a couple of bugs in the reader conditionals patch, can't see any other issue right now. I'm going to wait until tomorrow anyway and if nothing else comes up will release 0.9.0

20:06 dnolen: Bronsa: cool, on the CLJS side of things, I'm ready for tools.reader, anywhere a user can supply .cljs, .cljc is now permitted and checked first

20:07 Bronsa: dnolen: if you want to try it out it's in the reader-conditionals branch

20:07 dnolen: so the only thing I need to do at this point is turn on conditional reading for .cljc files

20:07 Bronsa: yeah I saw that, done for the day, will check it out tomorrow, thanks!

20:11 daviid: i wrote this: http://paste.lisp.org/+35CI/1 it complains you can only recur from tail position

20:12 oh tipo

20:14 justin_smith: daviid: while inside loop is almost never the right thing

20:14 daviid: http://paste.lisp.org/+35CI/2 but it still complains

20:14 justin_smith: fine, what do you suggest ?

20:14 justin_smith: daviid: the while is infinite, because i cannot cahnge in the scope of i

20:14 daviid: remove the while

20:15 instead, only recur if i is less than obj-nb

20:15 otherwise don't recur

20:15 daviid: ah ok let me try

20:15 justin_smith: from a quick read this looks very close to being what you want though

20:16 daviid: justin but if obj-nb is zero it will crash if a execute the let and only check at recur time

20:16 that why i wrote while ...

20:16 justin_smith: then you need the if before the let block

20:17 maybe you want when instead of while

20:17 daviid: when will work?

20:17 justin_smith: the thing about using when is that it means you return nil

20:17 daviid: becasause if outside the loop sounds redondant

20:18 justin_smith: it's not outside the loop

20:18 it would be inside the loop

20:18 but before the let

20:18 if you want to return nil, use when

20:18 (exactly in the way you had used while)

20:18 daviid: i thing when is fine

20:18 justin_smith: if you want to return ep, then make an if that either returns ep, or enters the let block

20:19 daviid: ok

20:22 http://paste.lisp.org/+35CI/3 this works, is this good coding standard for clojure ?

20:23 justin_smith: daviid: it would be much simpler if you can get a seq over obj-nb and use some sort of filter / map / reduce

20:23 but getting a working loop is a good start :)

20:23 err, a seq over results I mean

20:24 daviid: i don't know how to write that [ a seq over results ]

20:25 i'd love too, this code is very verbose to my scheme taste :)

20:25 justin_smith: daviid: if it was a Collection or an Enumeration we have seq or enumeration-seq built in

20:28 daviid: justin_smith: i've no idea how to write this shorter than i did

20:29 justin_smith: daviid: what is the class or type of result ?

20:29 because if it were a sequential thing, it could be converted to a reduce that would be less verbose

20:30 daviid: i'm not sure what it is, it is a java beast [imagej] i thought it ws an array

20:30 justin_smith: oh, you can reduce on an array

20:32 it would be something like (reduce (fn [ep item] (let [x (something item "BX") ...]) 0 results)

20:32 the next question being what the right call is when you have a single element of results, and not the whole collection

20:32 (to fill in for that "something", of course)

20:34 daviid: justin_smith: here is a def http://rsbweb.nih.gov/ij/developer/api/ij/measure/ResultsTable.html

20:36 justin_smith: yeah, you're stuck with the ugly way, unless you want to write a bunch of clumsy interop to try to treat that as a normal collection

20:37 which would be uglier, unlessy you plan on operating on many of these, then it might be worth just doing it once and getting it out of the way

20:37 *unless

20:38 daviid: justin_smith: ok, that's fine this results beast is a given inagej object, not much i can do i guess

20:40 justin_smith: daviid: it's kind of sad, because we have all these wonderful tools for collections of things, and then an API like that doesn't contain any data that couldn't be represented that way, but just has to be a special snowflake and not cooperate with any of our nice otherwise-reusable abstractions

20:40 daviid: i could apply map list maybe ?

20:40 justin_smith: but it isn't a list

20:40 it's not exposing itself as anything sequential

20:41 daviid: i could grab 4 list of values

20:41 bx by width and height

20:41 justin_smith: instead, you have to ask for an X and Y (row and column) to get a value

20:41 daviid: then reduce

20:41 justin_smith: yes, that's the "clumsy" way I was mentioning above :)

20:43 daviid: ok, have to run, thanks a lot! i'm not regular at #clojure but will be back sometine, maybe soon :)

20:43 tx all!

20:44 justin_smith: rx np

21:00 ncthom91: Hi all. Suppose I define an instance of nashorn at the top of my file... (def nashorn (.getEngineByName (ScriptEngineManager.) "nashorn")), but then I spin off some threads that each evaluate various expressions and function calls in that nashorn engine... Nashorn doesn't guarantee thread safety, so how can I make sure that each thread gets its own instance of the nashorn engine?

21:00 (I'm using the executors framework with newFixedThreadPool)

21:00 so theoretically each thread could bind its own reference and then just hang onto it for its lifetime

21:01 amalloy: that's pretty much the only way to do it, ncthom91; solutions will just be more or less fancy ways of doing it

21:01 justin_smith: ncthom91: if each thread should have its own instance, don't bind it at the top level

21:01 ncthom91: justin_smith where bind it then?

21:02 amalloy: you could eg use https://github.com/flatland/useful/blob/develop/src/flatland/useful/utils.clj#L201, and (def nashorn (thread-local (.getEngineByName (ScriptEngineManager.) "nashorn")))

21:02 then each thread can just refer to @nashorn to get its private version

21:03 ncthom91: amalloy that sounds pretty nice

21:04 amalloy: this presupposes that giving each thread its own copy is the right thing to do, which only you know for sure

21:05 ncthom91: well that seems to be the only way to safely evaluate js in an MT environment given that nashorn doesn't support it itself, right?

21:05 ubuntuboy: hello all

21:06 amalloy: well, you could ensure that there's only one engine, and that only one thread accesses it at a time

21:06 or you could create engines in some other context, such as a "job" or something at a different granularity level than a thread

21:07 ncthom91: amalloy true. I expect the js execution will be the bottleneck, so I don't want the threads blockign each other for access to the engine

21:07 ubuntuboy: I have a question, does anyone know why I can not stream Time Warner live tv in Ubuntu 14.10?

21:08 amalloy: ubuntuboy: this is the wrong channel for that question

21:09 ubuntuboy: sorry cant you point me in the right channel?

21:09 amalloy: try #ubuntu, i dunno

21:09 ubuntuboy: okay thanks.

21:14 ncthom91: amalloy can you explain thsi syntax to me? https://github.com/flatland/useful/blob/develop/src/flatland/useful/utils.clj#L195-L196

21:14 amalloy: ,(doc proxy)

21:14 clojurebot: "([class-and-interfaces args & fs]); class-and-interfaces - a vector of class names args - a (possibly empty) vector of arguments to the superclass constructor. f => (name [params*] body) or (name ([params*] body) ([params+] body) ...) Expands to code which creates a instance of a proxy class that implements the named class/interface(s) by calling the supplied fns. A single class, if provided, mus...

21:16 ncthom91: heh, thanks :)

23:11 danielglauser: Why do defmulti and defmethod have defonce semantics?

23:15 justin_smith: danielglauser: if you redefine the defmethod, it destroys all your multis

23:15 so the default is to make it defonce so just reloading your ns does not break other namespaces

23:16 tomjack: just defmulti, not defmethod, though, yes?

23:16 amalloy: i think you had method/multi backwards there justin_smith

23:16 tomjack: (or did I get them backwards yet again?)

23:16 justin_smith: amalloy: oh, yeah, I did flip those

23:17 tomjack: I guess my mnemonic will be that it's in order: multi. method. :)

23:17 danielglauser: justin_smith: That makes sense. I don't often have the defmethods in other namespaces but yeah, that's a thing.

23:55 Igor: When I want swap! atom with value, must I do it in sync block, if value depends on given atom?

23:55 justin_smith: Igor: you swap! an atom with a function

23:56 and no, using atoms does not require sync blocks or transactions

23:57 Igor: no swap! , reset! , sorry

23:57 justin_smith: no, reset! does not require a sync block, if you are only changing one atom

23:57 if you have two changes that have to go together, something like that may be called for (and you may be better off using a ref)

Logging service provided by n01se.net