2015-04-08
| 00:44 | netroby | Where is clojure Sepecification document? |
| 00:44 | netroby | I can not find it anywhere |
| 00:54 | justin_smith | it doesn't exist |
| 01:55 | netroby | Oh. no . every language had a specification paper. why clojure does not have one? |
| 01:56 | mavbozo | python, ruby also do not have one |
| 01:56 | TEttinger | many successful languages do not have specs for important reasons. |
| 01:56 | TEttinger | one is that if there's a mistake in the spec, implementations need to implement that mistake |
| 01:57 | netroby | https://docs.python.org/3/reference/ |
| 01:57 | TEttinger | that is a reference manual not a spec |
| 01:57 | justin_smith | netroby: we have docs at clojure.org |
| 01:57 | netroby | http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=59579 |
| 01:57 | netroby | I am not interesting document, i am asking for specification document. |
| 01:58 | justin_smith | netroby: that python link is not a specification |
| 01:58 | netroby | Like java specification https://docs.oracle.com/javase/specs/ |
| 01:58 | justin_smith | netroby: clojure does not have one, and never will |
| 01:58 | netroby | Even scala have it's specification http://www.scala-lang.org/files/archive/spec/2.11/ |
| 01:59 | justin_smith | netroby: I am not arguing that some languages have specifications |
| 01: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 |
| 01:59 | justin_smith | netroby: what I am saying is that the authors of clojure have said explicitly that they will never make a spec |
| 01:59 | justin_smith | it's not up to any of us here |
| 02:00 | TEttinger | the java specification is kinda a joke, I'd be interested if any alternative implementations of java actually follow it |
| 02:01 | netroby | If you would like to implement a language . you need to read specification or something like that. |
| 02:01 | TEttinger | gwt doesn't I am fairly sure, dalvik, if it did, that was probably used against google in oracle's spec |
| 02:01 | TEttinger | no. |
| 02:01 | justin_smith | netroby: that's not true |
| 02:02 | TEttinger | *in oracle |
| 02:02 | netroby | It just like a blue print |
| 02:02 | TEttinger | *in oracle's lawsuit against google |
| 02:02 | justin_smith | netroby: I know what a spec is, and I know clojure will never have one. |
| 02:02 | mavbozo | other python implementation is based on cpython implementation not specs, ruby also |
| 02:03 | netroby | mavbozo: Python have spec document (relate to specification paper) |
| 02:03 | netroby | mavbozo: Ruby have a ISO paper |
| 02:03 | netroby | mavbozo: ISO/IEC 30170:2012 |
| 02:03 | justin_smith | netroby: that is not true, python has no spec |
| 02:04 | netroby | Even c language have it's spec, ISO/IEC 9899:2011 |
| 02:04 | mavbozo | netroby, but other python and ruby implementations does not strictly follow the specs |
| 02: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 |
| 02:04 | mavbozo | netroby, the canonical references for both languages are its original implementation in C |
| 02: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. |
| 02:06 | netroby | justin_smith: I just searching for clojure language specification document. It's absolutely none |
| 02:06 | justin_smith | netroby: that's true |
| 02:06 | TEttinger | correct |
| 02:06 | justin_smith | ther is none |
| 02:06 | TEttinger | like python |
| 02:06 | mavbozo | agree |
| 02: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. |
| 02:08 | justin_smith | netroby: I think it would be awesome to have a pet unicorn. |
| 02:10 | Jaood | justin_smith: to big for a pet |
| 02:11 | justin_smith | Jaood: I would also like a 100 acre field for my unicorn |
| 02:11 | mavbozo | netroby, great but unfortunately clojure does not have a formal spec |
| 02:11 | netroby | Hum, i thought i should have to read the source code of clojure instead. |
| 02:12 | Jaood | I would like a lein like tool written in Java :P |
| 02:12 | netroby | laood: you have ant, maven. |
| 02:12 | justin_smith | Jaood: that's definitely the most achievable one so far |
| 02:12 | justin_smith | ant is nothing at all like lein, maven would need quite a bit of work |
| 02:13 | justin_smith | though maven's support for multiple config file formats now is a step in the right direction |
| 02:17 | mavbozo | Jaood, don't we have in our eclipse, intellij? (I assume those IDEs hide all that ant, maven complexities) |
| 02:17 | netroby | Gradle is useful and better choice for java developers |
| 02:17 | justin_smith | mavbozo: the problem with that is that now everyone on your team needs to use the same ide |
| 02:18 | justin_smith | mavbozo: it's actually strongly recommended against for that reason |
| 02:21 | mavbozo | justin_smith, recommended against even java development projects? |
| 02:21 | mavbozo | *even for* |
| 02:22 | Jaood | mavbozo: I was complaining more about start-up time and memory consumption |
| 02:22 | justin_smith | mavbozo: yeah |
| 02:22 | justin_smith | mavbozo: that's the party line on ##java |
| 02:23 | justin_smith | mavbozo: also, this makes it harder to have nice things like CI tools |
| 02:23 | justin_smith | unless you expect travis or jenkins to be running your IDE... |
| 02:23 | mavbozo | justin_smith, interesting. so you don't want to use eclipse, intellij, or others for maintaining legacy java codebase? |
| 02:24 | Jaood | maven is very project centric |
| 02: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) |
| 02:24 | justin_smith | I'm not saying no IDE, I'm saying no IDE automagic dep controls |
| 02:25 | justin_smith | a build system that requires starting up a specific app that isn't a build tool is bad |
| 02:27 | Jaood | does Hickey uses lein? I would guess he's more of a maven peson |
| 02:27 | Jaood | s/peson/person |
| 02:27 | justin_smith | clojure.core is still maven |
| 02:27 | justin_smith | I wonder if it will ever have a project.clj |
| 02:28 | Jaood | hmm yeah, it looks like it supports both ant and maven |
| 02:29 | mavbozo | justin_smith, thanks for the advice. might come in handy if someday i have to maintain a legacy java codebase |
| 02:29 | Jaood | Hickey would probably respond, "get off my lawn" |
| 02: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. |
| 02:38 | justin_smith | I know arrdem would be very happy if there was a spec. Probably Bronsa too. |
| 02:40 | mavbozo | is there any good story of language spec written after the language implemented? |
| 02:40 | justin_smith | mavbozo: common lisp kind of counts - the hyperspec defined a common spec to bring together a bunch of lisp implementations |
| 02: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 |
| 02:40 | netroby | The same guy. |
| 02:40 | justin_smith | yup |
| 02:41 | justin_smith | he also worked on the scheme srfis |
| 02:41 | mavbozo | justin_smith, people complained that the spec is bloated |
| 02:41 | netroby | Written Java specification and Lisp specification |
| 02:41 | justin_smith | which form the scheme spec |
| 02:41 | justin_smith | so clearly the answer is to elect guy steele to replace rich hickey |
| 02:41 | netroby | Do you have vote? |
| 02:41 | mavbozo | justin_smith, and make it really hard to fully implement that spec |
| 02:42 | justin_smith | netroby: no, that was a joke, rich hickey doesn't run clojure as a democracy |
| 02:42 | mavbozo | i vote younger ones such as ambrosebs |
| 02:42 | mavbozo | ensuring clojure longevity |
| 02:43 | netroby | Guy Lewis Steele Jr. 61 years old |
| 02:43 | mavbozo | he also has proven track records in making typed.clojure |
| 02:44 | netroby | I am using Emacs, seems he also the coauthor of Emacs |
| 02:44 | netroby | This guy really stronger and powerful |
| 02:44 | mavbozo | ambrosebs is about 20s |
| 02:44 | justin_smith | definitely a smart guy |
| 02:45 | netroby | The newer programmer will not to invent a new language or new tools. |
| 02:46 | mavbozo | justin_smith, agree ambrosebs is definitely a smart guy |
| 02:46 | netroby | If the old guys dead. we have nothing left |
| 02: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 |
| 02:47 | netroby | justin_smith: thanks |
| 02:49 | tahmid | Hello guys |
| 02:49 | mavbozo | hello |
| 02: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? |
| 02:49 | tahmid | In cljs how to add multiple classes using the #js |
| 02:49 | tahmid | I can add one class like this #js {:className “myclass”} |
| 02:50 | tahmid | But how can I add multiple classes |
| 02:50 | tahmid | btw I am talking about om |
| 08:07 | J_Arcane | Seesaw seems really nice. |
| 08: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 |
| 08:18 | timvisher | 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 |
| 08:19 | Glenjamin | would sit any http-kit-based server behind a load balancer, i'd have thought |
| 08:19 | Glenjamin | so i'd usually terminate SSL there |
| 08:20 | timvisher | Glenjamin: yeah. the concern seems to be sniffing on the internal network |
| 08:20 | Glenjamin | you have an insecure internal network? |
| 08:20 | timvisher | also the goal is to have each of our services eventually be public facing, so then they'll all need SSL anyway |
| 08:21 | timvisher | Glenjamin: not in any known way, but paranoia :) |
| 08: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 |
| 08:25 | mpenet | websockets as well |
| 08:27 | mpenet | we switched from http-kit a while ago, we hit some of the issues you can see in its issue tracker |
| 08: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. |
| 08:30 | timvisher | mpenet: yes. that's another scary thing. maintenance seems to be tough for the http-kit devs. |
| 08:30 | timvisher | mpenet: did you go with ring-jetty9-adapter? |
| 08:30 | timvisher | or did you rolly our own jetty 9 dep? |
| 08:31 | timvisher | s/rolly/roll/ |
| 08:31 | timvisher | pcn: i would too |
| 08:31 | timvisher | you have any good docs to link to as far as why ssl in java isn't the best idea? |
| 08:33 | mpenet | timvisher: no we rolled our own: https://github.com/mpenet/jet |
| 08:33 | mpenet | it started as a fork and ended up rewriting pretty much everything |
| 08:33 | timvisher | mpenet: nice. thanks for the link |
| 08:34 | pcn | timvisher: it doubles operational cost of e.g. maintaining CA certs. Adding and removing them are a specialized set of commands. |
| 08:34 | timvisher | mpenet: have a write up as to why? |
| 08:35 | timvisher | pcn: oh man i totally forgot about that :) |
| 08:35 | mpenet | timvisher: why the switch or why the lib? |
| 08:35 | pcn | And then you have to start putting logic surrounding what is secure vs not in your code |
| 08:35 | Lutin` | anyone have tips on profiling a clojure program? |
| 08:36 | timvisher | mpenet: why you rewrote the jetty9-adapter |
| 08:36 | timvisher | Lutin`: start with visualvm and see how far that gets you |
| 08:37 | Lutin` | Alright, thanks. Will take a look |
| 08: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) |
| 08:37 | timvisher | mpenet: thanks! |
| 08:37 | danlentz | Lutin`: probably doesn't qualify as a "tip" but I recently used YourKit and criterium |
| 08:37 | mpenet | + I ended up doing client side stuff wrappers too (websocket & http clients) |
| 08:38 | Lutin` | danlentz: Counts for me! I guess I meant more like suggestions than "tips". I don't know haha |
| 08:38 | danlentz | YourKit for a statistical (?) profile and criterium to optimize hot spots |
| 08:38 | timvisher | danlentz: did you pay for it? |
| 08:38 | timvisher | or was it for an opensource thing? |
| 08:39 | timvisher | YourKit is definitely best of breed afaik, but it costs money for proprietary profiling |
| 08:39 | danlentz | No, it was open source but even do I just downloaded the beta version |
| 08:39 | danlentz | But I think you can apply for a license |
| 08:39 | tbaldridge | yeah YK is pretty nice about handing out free copies to OSS projects |
| 08:40 | danlentz | I should do that actually. It's a very useful package. |
| 08:41 | danlentz | But, my scenario was that I needed to get a high level picture of where cost was incurred during computation of UUID's |
| 08:41 | timvisher | danlentz: ah. is that feature-restricted or time restricted? |
| 08:41 | danlentz | So once I had that I focused in using criterium |
| 08:42 | danlentz | timvisher: the beta is time restricted |
| 08:42 | timvisher | Lutin`: for wider application profiling and visibility you could also consider something like NewRelic |
| 08:42 | timvisher | does NewRelic have first class clojure support at this point? |
| 08:42 | timvisher | s/application/system |
| 08:43 | Lutin` | Right now I'm just profiling an IRC bot |
| 08:43 | Lutin` | trying to figure where all this memory usage is coming from for something I thought would be fairly small |
| 08:43 | danlentz | I think YourKit retails for something like $600 which is well worth it |
| 08:44 | timvisher | Lutin`: yeah. push visualvm to its limit and then see whether YK does what you need. :) |
| 08:46 | Lutin` | huh, so GC increases the PermGen size |
| 08:46 | Lutin` | didn't know that |
| 08:47 | Lutin` | maybe it's just due to the way VisualVM does it |
| 08:48 | timvisher | pcn: could you elaborate a bit more on putting code around what's secure and what's not in your code? |
| 09:00 | Lutin` | hmm so it looks like at this point most of my memory savings are going to be from removing libraries? |
| 09:00 | Lutin` | Only need about 10MB on the heap, but the total resident memory is around 80MB |
| 09:02 | Lutin` | Trying to slim this down to run on a VM with only 128MB available ram and 256MB swap, which might be a bit crazy |
| 09: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? |
| 09: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 |
| 09:54 | justin_smith | Lutin`: clojure uses a lot more permgen than a normal java program would |
| 09:54 | justin_smith | Lutin`: but in 1.8 this is not as much of a concern |
| 09:55 | justin_smith | Lutin`: the issue is that every function made via fn is a new class |
| 09:55 | justin_smith | (or, that's part of the issue) |
| 10:01 | sobel | heh, looks i have design approval to avoid interfacing clojure to java |
| 10:02 | sobel | ...this time |
| 10:02 | justin_smith | congrats |
| 10:03 | justin_smith | 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 | justin_smith | 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 | justin_smith | in-process or ipc? |
| 10:04 | sobel | it's pretty basic OO, there |
| 10:04 | sobel | 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 | sobel | it keeps the abstraction tight :) |
| 10:05 | justin_smith | but with a very thin wrapper, it need not be at all |
| 10:05 | justin_smith | but if dao works, it works |
| 10:05 | sobel | in this case, 100% of the domain is implemented in clojure |
| 10:06 | sobel | 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 | justin_smith | and yeah, vectors or maps only sometimes |
| 10:08 | justin_smith | and it's not good to rely on it |
| 10:08 | mnngfltg2 | justin_smith, huh |
| 10:08 | mnngfltg2 | 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 | justin_smith | 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 | mnngfltg2 | my use case is that I keep track of an immutable collection |
| 10:11 | mnngfltg2 | something outside my control makes a change and returns me a new-val |
| 10:11 | mnngfltg2 | 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 | mnngfltg2 | if I do (assoc {} big-object :seen)... |
| 10:14 | mnngfltg2 | does it store big-object once more, or just a reference to it? |
| 10:14 | mnngfltg2 | i.e. a pointer |
| 10:14 | mnngfltg2 | seems silly to ask that, but I'm not sure now |
| 10:14 | justin_smith | mnngfltg2: it's effectively a pointer |
| 10:14 | justin_smith | 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 | 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 | mnngfltg2 | 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 | justin_smith | 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 | justin_smith | (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 | sobel | 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 | justin_smith | from technomancy iirc |
| 10:21 | sobel | was it vinyasa? |
| 10:22 | sobel | 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 | justin_smith | mdrogalis: AHA! |
| 10:23 | justin_smith | (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:30 | yellow13 | hi there! https://www.refheap.com/99364 |
| 10:30 | yellow13 | 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 | justin_smith | 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 | yellow13 | then im gonna put that new url on the page |
| 10:34 | yellow13 | im not sure how to remember the pages where the upload failed |
| 10:35 | yellow13 | thats why change-page-url accepts nil |
| 10:35 | justin_smith | OK |
| 10:36 | justin_smith | 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 | justin_smith | if you either replace page unmodified, or update its :url key, then the caller can unconditionally use the result |
| 10:37 | justin_smith | 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 | yellow13 | resulting in [nil {:url "a"} nil] then ill save on mongo the updated pages |
| 10:46 | yellow13 | 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 | justin_smith | 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 | sobel | sliced bread, etc |
| 11:01 | timvisher | sobel: i should really turn that on at some point |
| 11:01 | timvisher | paredit makes much more of a difference for me though :) |
| 11:01 | sobel | yeah, i use that too. |
| 11:01 | sobel | 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 | timvisher | 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 | sobel | 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 | danlentz | 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 | justin_smith | 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: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 | arrdem | 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: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 | justin_smith | 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 | arrdem | 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 | justin_smith | 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 | justin_smith | that is error-prone with transients - it works until it doesn't |
| 11:51 | justin_smith | 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 | justin_smith | but it also leads to less than sane code |
| 11:52 | justin_smith | if used without discretion |
| 11:53 | justin_smith | less so in js where "arrays" aren't |
| 11:53 | justin_smith | 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 | justin_smith | 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 | szatz | 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 | justin_smith | 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 | justin_smith | 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 | arrdem | justin_smith: does lazybot have factoids on? |
| 12:11 | arrdem | 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 | mpenet | *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 | oddcully | (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: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 | sobel | 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 | sobel | 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 | sobel | i did lein clean |
| 12:45 | sobel | 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 | sobel | 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 | arrdem | ##(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 | TimMc | or (fn [x & _] (foo x)) |
| 13:19 | TimMc | _ is a convention for "unused value" |
| 13:20 | sobel | thx all, that fixed me up |
| 13:21 | sobel | oh i just realized i'm jerk for making a class with _ in it |
| 13:22 | yellow13 | TimMc: youre right |
| 13:22 | yellow13 | 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 | pbx | 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 | andyf | S/done/some/ |
| 15:01 | andyf | ~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 | pbx | justin_smith, again, it worked two hours ago |
| 15:04 | pbx | so it's clearly my fault but how i do not know |
| 15:04 | pbx | lein 1.7.1 |
| 15:04 | Kowryh | what development environment do you guys use? |
| 15:05 | Kowryh | 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 | justin_smith | 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 | justin_smith | andyf: haha |
| 15:07 | justin_smith | 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 | justin_smith | 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 | katratxo | 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 | ncthom91 | 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 | cfleming | I'm planning to have custom renderers for LazySeq, Cons and IChunkedSeq |
| 15:54 | cfleming | 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 | cfleming | 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 | cfleming | 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 | amalloy | 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 | puredanger | 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 | puredanger | 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 | cfleming | Is LazySeq really the only special case, then? |
| 16:04 | cfleming | All other ISeqs I just walk them until either I'm done or I hit my limit? |
| 16:04 | puredanger | sure |
| 16:04 | puredanger | 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 | cfleming | 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 | puredanger | 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 | puredanger | cfleming: so it controls the iteration and processing model |
| 16:12 | cfleming | Right |
| 16:13 | cfleming | 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 | cfleming | 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 | cfleming | 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 | cfleming | 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 | puredanger | Bronsa: I think you're probably right. |
| 16:21 | ircxy | Shouldn't (read-string nil) return nil instead of throwing a NPE? |
| 16:23 | ircxy | 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 | puredanger | 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 | justin_smith | ,(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 | justin_smith | 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 | danlentz | 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 | szatz | 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 | hiredman | (the [1..] bit) |
| 17:07 | mikerod | hiredman: yeah, I thought it would |
| 17:07 | mikerod | 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 | mikerod | 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 | mikerod | 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 | mikerod | 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 | mikerod | Well there is the difference of caching vs non-caching |
| 17:14 | mikerod | in other scenarios |
| 17:14 | mikerod | Does Haskell cache realized lazy elements? |
| 17:14 | mikerod | 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 | amalloy | "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 | mikerod | 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 | mikerod | 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 | mikerod | that's what I mean by caching. |
| 17:21 | mikerod | So if Haskell returns an infinite lazy collection and one caller wants 5 elements. the next caller wants |
| 17:21 | mikerod | 6 |
| 17:21 | mikerod | 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 | mikerod | amalloy: if all references disappear, does it start from scratch again? |
| 17:22 | amalloy | that's impossible |
| 17:23 | amalloy | 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 | mikerod | 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 | amalloy | 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 | amalloy | they are cached for as long as you have a reference to them |
| 17:24 | mikerod | yes |
| 17:24 | mikerod | 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 | szatz | 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 | mikerod | 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 | ambrosebs | do I manually set e* and prn the exception? |
| 18:25 | ambrosebs | 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 | ambrosebs | it would be like catching a type error in Haskell. not advised. |
| 18:28 | ambrosebs | 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 | justin_smith | *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 | ambrosebs | but no return value |
| 18:31 | ambrosebs | 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 | justin_smith | 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 | ambrosebs | I'm not sure what catching a static type error would mean |
| 18:34 | ambrosebs | 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 | hiredman | 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 | hiredman | 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 | hiredman | *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 | ambrosebs | 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 | hiredman | 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 | hiredman | 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 | justin_smith | turns out "current directory" is just that one var in your env |
| 18:44 | justin_smith | 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 | hiredman | 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 | justin_smith | oh, getProperty not getenv |
| 18:47 | justin_smith | I've got that confused |
| 18:48 | justin_smith | ncthom91: this may be more helpful http://stackoverflow.com/questions/840190/changing-the-current-working-directory-in-java/8204584#8204584 |
| 18:49 | justin_smith | ncthom91: the magic lines in that gist are line 45 and line 45 |
| 18:49 | justin_smith | 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 | hiredman | ambrosebs: reply is the client leiningen uses |
| 19:04 | hiredman | cider contains a client written in elisp |
| 19:04 | hiredman | 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 | amalloy | (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 | amalloy | 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 | daviid | but still, i just don't know |
| 19:45 | daviid | 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 | amalloy | 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 | amalloy | 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 | daviid | as i said, i'm learning, please tell me |
| 19:48 | daviid | an example |
| 19:48 | amalloy | i did show an example |
| 19:48 | amalloy | 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 | tolstoy | Something like that. |
| 19:54 | tolstoy | ? |
| 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 | justin_smith | 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 | justin_smith | just don't expect normal recursion to be optimized as a tail call |
| 19:57 | daviid | oh too bad |
| 19:57 | daviid | i love tail call recursive 'style' |
| 19:58 | daviid | but let me try one of yur examples |
| 19:58 | justin_smith | the only difference is calling recur |
| 19:58 | justin_smith | 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 | dnolen | 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 | daviid | 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 | daviid | 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 | justin_smith | daviid: remove the while |
| 20:15 | justin_smith | instead, only recur if i is less than obj-nb |
| 20:15 | justin_smith | 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 | daviid | that why i wrote while ... |
| 20:16 | justin_smith | then you need the if before the let block |
| 20:17 | justin_smith | 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 | justin_smith | it would be inside the loop |
| 20:18 | justin_smith | but before the let |
| 20:18 | justin_smith | if you want to return nil, use when |
| 20:18 | justin_smith | (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 | daviid | 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 | justin_smith | but getting a working loop is a good start :) |
| 20:23 | justin_smith | err, a seq over results I mean |
| 20:24 | daviid | i don't know how to write that [ a seq over results ] |
| 20:25 | daviid | 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 | justin_smith | 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 | justin_smith | it would be something like (reduce (fn [ep item] (let [x (something item "BX") ...]) 0 results) |
| 20:32 | justin_smith | the next question being what the right call is when you have a single element of results, and not the whole collection |
| 20:32 | justin_smith | (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 | justin_smith | 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 | justin_smith | *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 | justin_smith | it's not exposing itself as anything sequential |
| 20:41 | daviid | i could grab 4 list of values |
| 20:41 | daviid | 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 | daviid | 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 | ncthom91 | (I'm using the executors framework with newFixedThreadPool) |
| 21:00 | ncthom91 | 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 | amalloy | 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 | amalloy | 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 | justin_smith | 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 | justin_smith | 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 | justin_smith | 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) |