1. 3

    What?

    Surely this is wrong. Does Rust have this issue?

    1. 14

      It’s not really about Rust. What Rust does is insert the deallocation code automatically when the owner goes out of scope, but C or C++ code would need to deallocate an equivalent structure at some point (or they could decide to never deallocate and just let it leak, which is also an option in Rust), and the cost of deallocation isn’t based on the language. Chasing 1,000,000 pointers to free what they’re pointing to is going to be expensive in any language.

      1. 4

        This still seems weird…like, why is the caller freeing what’s passed in? Is there some additional context (say, this function is the last one being invoked in the lexical scope of the lifetime of the value being passed in) here we’re not being given?

        Or is Rust really using copy-on-pass semantics that require it to free the copies made during function invocation?

        1. 22

          Rust uses move semantics for owned objects, which in this case effectively means “the compiler knows how to figure out where to insert free()/drop() calls for you”. The single-threaded example turns into:

          fn get_size(a: HeavyThing) -> usize {
              a.size();
              drop(a);
          }
          

          and the multi-threaded example is, as described:

          fn get_size(a: HeavyThing) -> usize {
              let size = a.size();
              std::thread::spawn(move || drop(a));
              size
          }
          

          This is Rust’s real secret sauce.

          1. 16

            The caller isn’t freeing it. The caller is moving the value into the callee and gives up ownership. The callee is now the sole owner of the value and drops it implicitly (if it isn’t passed around further or passed back as a return value).

            1. 8

              icefox and freddyb gave good answers and my Rust knowledge is not the deepest, but I wanted to address this part:

              why is the caller freeing what’s passed in?

              The main alternative to the “move” semantics when passing an argument to a function is to pass a reference instead, in which case the called function would be “borrowing” the value instead of owning it outright. In that case Rust would not insert the deallocation code at the end of the function because the compiler knows that the caller is not done with the value.

              Depending on the purpose of the function and how it fits in with the rest of the code, another option for controlling when deallocation happens could be to pass in a reference and have a caller somewhere up the stack decide exactly when to drop it.

              1. 2

                The other answers all cover aspects, but I feel they may not be clear enough.

                When something is passed directly (not by reference) to a function, it will either be moved or copied (depending on whether the type implements the Copy trait, which is only possible for types which can be freed without chasing pointers). In the case of a move, the data now belongs to the callee function, and when the owner (the formal parameter name) goes out of scope (unless ownership is passed back to the caller in the function return, this would be at the end of the function), the Rust compiler inserts a drop call to free the owned data (calling the type’s Drop trait implementation). In the case of a copy, the same still happens, but the callee is working with a distinct copy of the data, so the caller’s copy of it is still valid and will be dropped when its own owner goes out of scope.

            2. 4

              Doesn’t everything have this issue? It’s just the old memory management trade-off of “would you rather your performance be bounded by the size of the set of things you’re deallocating, or the size of the live set?”, isn’t it?

              You can deterministically deallocate things as their owner goes out of scope, which is sometimes going to involve chasing pointers to a large number of interior allocations at an inconvenient moment (like the vector-of-vectors here), so you might want to move ownership onto a less critical thread and deallocate in the background, as shown here or as in COM or some other C & C++ codebases, or stop allocating from general purpose heap, create a specific arena for your large set of allocations, and deallocate the arena in one go.

              Or you can have a GC that does a mark-and-sweep and have the same “spend a lot of time chasing pointers to a large number of allocations“ problem, but at a less predictable time.

              Or you can have a GC that does a copy-and-compact, which might let you avoid the interior pointer chasing to a large number of allocations (if there’s nothing like finalizers that need invoking), but now you’ve got the opposite problem in that your performance is bounded by the size of the live set instead of what’s being deallocated.

              What would a language that doesn’t have this issue do instead?

              1. 2

                What would a language that doesn’t have this issue do instead?

                Probably this:

                stop allocating from general purpose heap, create a specific arena for your large set of allocations, and deallocate the arena in one go.

                I think it’s probably true for many applications that the common case is all pointers stored in a collection (transitively):

                a) are allocated in the same place, specifically to be placed in that collection

                b) are not stored anywhere else

                c) have finalisers who are only chasing and freeing other pointers allocated in the same transitive tree rooted in the collection

                and so releasing the collection would be quick+easy if this knowledge was given to the language/runtime.

                A language which made this easy would do well here.

                We’re paying for the cost of the fully general case all the time, when we probably don’t need to.

                1. 3

                  Zig makes this pretty easy. The stdlib data structures, and anything else that needs to allocate, take an allocator parameter, which can be an arena (and one is provided by the stdlib.)

                  1. 2

                    Thanks, that’s interesting!

                    I know the c++ stdlib allows you to specify allocators etc, but I was wondering about a “more natural” way of doing it.

                    In many languages we anchor the constructor to a type: f = foo.New() or similar. That ctor will need to grab memory, which is generally stack, heap or custom allocator.

                    I guess I was wondering what it would be like if we did something like alloc through an owning object:

                    func handleRequest(r Request)
                      m = r.New(Map) // allocate a map owned by the request. When that goes, so does the map
                      f = m.New(foo) // allocate a foo owned by the map. When 'm' goes, so does f
                      m["myfoo"] = f
                      ...do stuff...
                      return // neither m nor f cleaned up, but when caller kills 'r', they are thrown away
                    }
                    

                    If the natural way to alloc was with an owning object, we’d get arena-allocation by default.

                    You’d need other ways of allocating to handle exceptional cases, but they could be done via a global or similar. Which seems to make sense, since an allocation which isn’t tied to an owning object (and needs to live beyond a request or equivalent) is global.

                    I assume C++ and rust (and Zig!) all allow this, but I’m wondering how far we can take “first class ownership, allocation and freeing” to enable the default use of memory pools.

            1. 19

              Elixir is probably the most practical language to learn today that meets your criteria.

              Not exactly statically typed, but has type annotations and the compiler checks all function calls (names and arity) at compile time. Erlang’s static analyzer (Dialyzer) can check the types but i haven’t used it.

              The official guide is pretty good : https://elixir-lang.org/getting-started/introduction.html

              1. 4

                Regarding static analysis with Dialyzer, I’m using it day-to-day right now and I’ve found that the tooling situation has improved greatly for me over the past couple years. I use VSCode and the latest versions of the ElixirLS plugin work great:

                https://github.com/elixir-lsp/vscode-elixir-ls

                I used to have to add a package called dialyxir to my project and run stuff manually, now I get first-class editor integration with everything taken care of for me seamlessly. I think most of the Elixir community still doesn’t use Dialyzer, though, which means help can be hard to come by.

                Dialyzer itself isn’t perfect, and there’s no comparison with a type system like Haskell’s. It can be frustrating running up against its limitations and figuring out which surprising things it will let you do to shoot yourself in the foot…but over time I’ve found that I can kind of “meet it half way” by adjusting my coding habits and expectations. Right now I have a pretty good relationship with it, and it helps me write Elixir code in a way that feels almost-sort-of like it were a language with a strong first-class type checker built into the compiler.

                1. 4

                  Oh, I totally blanked on Elixir. Thank you for the reminder! I always did want to poke around at it.

                  1. 2

                    The cool thing about learning Elixir is that you’ll also learn the most of Erlang for free. Syntax differs a lot and Elixir has a whole bunch of additional libraries and tooling, but that’s about it. Types, semantic, memory models, runtime are just exactly the same and there’s no FFI, calling Erlang code from Elixir is so easy and seamless that I often use the Elixir REPL to play with Erlang libraries.

                    Maybe you’ll wonder what’s the point of learning Erlang if Elixir is better*. The point is about existing code. Lots of super interesting software has been written in Erlang since decades and is still in use.

                    *: This is subjective of course! There are probably people out there who prefer Erlang.

                    1. 2

                      I’ve been wondering about the relation of Elixir to Erlang, is there an analogy one could make, that goes beyond just the technical aspects, and reflects how the communities see each-other? Is it like Java to Kotlin, or Javascript to Typescript? C to C++?

                      1. 2

                        Not an active member of the Elixir community, but from what I can tell it’s probably most similar to Javascript to Coffeescript; the developer isn’t making any particular changes to the language like with Typescript or C++, rather just making the syntax more conventional. Maybe that’s like the Java-Kotlin relationship but I’ve never really used either. José Valim seems to have a very healthy relationship with a lot of the Erlang community.

                        That’s just what I can tell as an outsider, though.

                        1. 2

                          Is it like Java to Kotlin, or Javascript to Typescript?

                          Yes! This is a very relevant analogy because both Elixir and Erlang share the same virtual machine (ERTS), which is similar to the JVM or a JavaScript engine like V8. Interoperability works without FFI (at least for JavaScript/TypeScript).

                          C to C++

                          Well, it’s more complicated. I’d say “not really” because these are not dynamic languages, there’s no big runtime and they are not compatible (C++ is not an exact superset of C, and more importantly you need extern "C" in C++ headers and this is a kind of FFI, and AFAIK there’s no way to use C++-specific features from C).

                      2. 2

                        I second the Elixir recommendation. If you’re valuing types more and are ready for a bit more experimental / early stuff, I would give Gleam a shot.

                        1. 1

                          Elixir runs on the Erlang VM, right? Has that VM’s performance been improved since I last looked at it circa 2012? Back then it was a standard bytecode interpreter without JIT or native compilation options, and so rather slow, e.g. way slower than JavaScript. (Too slow for my use case, which was on smartphone-class hardware.)

                          I know people tout Erlang’s performance, but it gets that from parallelization and scalability, even though each CPU core isn’t being used very efficiently. Or wasn’t, at the time. Maybe it’s better now?

                        1. 3

                          Aside from aligning with predicate logic, I have found that this behaviour ends up being what I want in practice for most problems I encounter. Most of the time if I’m checking that all elements of a list are true, or that all of them match some predicate, then what I’m doing can be thought of as a validation problem, and an empty set of validations should always pass.

                          1. 6

                            What would be the advantage over using an existing language like ClojureScript. It looks like you could do everything Mint does in a ClojureScript right now. For example, here’s what an SPA would look like. You can specify HTML using regular data structures instead of having additional syntax, and do inline CSS styling. There is robust state management available with re-frame and routing with reitit. In addition, ClojureScript provides hot loading out of the box, code splitting, pruning code down to function level, and robust library management.

                            1. 1

                              If you’re comparing lists of things you can do with different front-end languages and frameworks, I think you’ll find relatively little to distinguish any of them. ClojureScript has been around for a while now and certainly has lots of great things going for it.

                              However from what I gather on the website, Mint provides a significantly different development experience compared with ClojureScript that some people might prefer. It explicitly takes a lot of inspiration from Elm, and has a similar type system. If you strongly prefer ClojureScript to Elm, and find that the trade-offs of compile-time type checking don’t work well with the way you like to write programs, then I expect you’ll likely also prefer ClojureScript to Mint.

                              Meanwhile some people enjoy working with a compiler that checks types for them. They like using records and sum types to model data, and enjoy having a compiler that helps them make sure they are using those types the way they were designed to be used. They enjoy how the compiler can guide them in refactoring with confidence. They find that very rarely having to deal with runtime exceptions is worth a lot to them. They like the way that all of these factors change the way that they approach problems.

                              But maybe they are also not completely satisfied with Elm, ReasonML, PureScript, or whatever other similar front-end languages they may have tried. In that case Mint might be worth investigating as a possible alternative.

                              Compared with Elm, Mint’s website makes the case explicitly: https://www.mint-lang.com/guide

                              Compared with ReasonML, Mint seems to be aiming for a more polished and unified developer experience.

                              Compared with PureScript, Mint’s type system is much more simplified, like Elm’s, with the usual trade-offs that implies.

                              As always, if you are happy with your current tools then that’s great!

                              1. 1

                                ClojureScript is just an example I’m personally familiar with, but as you note there are plenty of statically typed languages that compile to Js as well. If Elm is too restrictive, there’s also Reason, which is basically OCaml, and a few others. At the end of the day I’m just not seeing any differences between these languages that result in significant productivity gains for the developers. Personally, I’d much rather see effort going to improving tooling and overall developer experience for existing languages than seeing yet another language that makes some slightly different trade offs from half a dozen existing ones.

                                If people feel that the problem Mint is solving is justified who am I to argue though. :)

                            1. 2

                              I notice that (on Mac), even if you SIGTERM the localhost process (pid found with lsof -i :19421, but killall ZoomOpener also works), Zoom just restarts it when you join a meeting/call. As described in the article, the executable resides in ~/.zoomus. I mved this away somewhere, thinking I would be taking away the thing Zoom is executing, but, guess what: Zoom literally just recreated the dir and all its contents upon joining a meeting. *facepalm* *wipe face downwards*

                              1. 3

                                The article includes proper patch instructions in the “Patch Yourself” section (the trick they use is to create a new file at ~/.zoomus and chmod 000, so that the app doesn’t mess with it, but future versions of the app could bypass this).

                              1. 2

                                I’m kind of surprised at the idea that anyone would use 5 Whys entirely on its own. My guess is that they don’t, really, because there’s got to be some context of informal lateral thinking going on…right?

                                When I learned how to run RCAs, 5 Whys was presented as one tool with a very limited scope—basically if the group isn’t going deep enough then it’s a useful exercise to force the recognition of a deeper chain of causes. (Likewise if the group is focusing too much on depth and needs more breadth, you spend a few minutes encouraging that instead.)

                                Lateral thinking is important not only because you might be missing some important causes of the Bad Thing, but also because you might be defining that thing too narrowly in the first place. This results in narrow solutions that don’t address larger classes of recurring issues.

                                By starting with a substantial amount of lateral brainstorming and then focusing alternatively on depth and breadth as required, a small group with 90 minutes and a facilitator can generate a meaningful web of causes and arrive at a small set of manageable action items that would prevent the Bad Thing(s) from happening in the future.

                                Ultimately it’s all about humans so I try to stay very light with the terminology and prioritize making people feel safe, listened to, and un-blamed.

                                1. 2

                                  I think the best ideas presented in this talk are the ones about separating optionality out of schemas. clojure.spec seems really nice and it looks like Rich has been very thoughtful about it and is taking it in a great direction.

                                  Clojure was the first functional programming language I fell in love with, but I haven’t spent much time writing Clojure code in a few years now because I found languages with nice type systems that were so refreshing and liberating for me that it’s hard to go back. Rich’s arguments about how wrong Haskell’s type system is just don’t ring true for me.

                                  The problem of changing a return value from Maybe a to a isn’t nearly as much of a problem in practice as how he makes it seem. The compiler tells you what you need to change, and you change it. Furthermore, I find it is much more common to need to make the opposite kind of change where return values need to have more possible values (e.g. a to Maybe a). I have found those kinds of changes much more common, and a good type system really helps with those.

                                  The bit about [a] -> [a] not telling you anything useful is bizarre. I guess he was “just exaggerating” but in the end it does nothing to foster healthy discourse.

                                  It seems like Rich is very happy with the way he’s able to build things with Clojure and hasn’t found that Haskell’s type system provides a good set of trade-offs for him. Unfortunately the way he expresses these opinions tends to be overstated and absolutist, not really acknowledging that he is talking about trade-offs at all. It gives me the impression that he is trying to convince his audience of Clojure users that they should feel comfortable not exploring other ways of doing things, which I think is an unfortunate message to send.

                                  1. 6

                                    Can we please stop using the “Make X Y Again” schema for advertising things? I know there is no ill intent behind this but some of us are directly affected by the policies and rhetoric that comes out of the very much sincere desire to roll back progressivism by decades.

                                    1. 13

                                      Your comment is off-topic.

                                      You reasonably observe that the name of the project is derivative, acknowledge that the author bears you no ill intent, but nevertheless suggest the project name is harming you and yours.

                                      You don’t address the author, you don’t talk about Medium as a platform, you don’t talk about blogging or anything apparently connected to the article. Your comment is a generic complaint. (Applies to any submission matching your pattern.)

                                      We’re a community of practitioners. We show (create, invest, fix), rather than tell (scold, beg, demand).

                                      1. 26

                                        The title of this project is a riff on a political slogan that itself is a riff on various fascist slogans throughout history. Making a joke of it by using it as the name of a browser extension is, at the very least, in poor taste. The commenter you responded to made a polite request to the community to stop doing this thing that is in poor taste. There was no need for them to address the substance of the project because the comment was only concerned with the choice of title. In terms of scolding/begging/demanding, I see more of that in your comment than in the one you responded to.

                                        1. 1

                                          Apologies for the off-topicness, but are Mel Brooks’ Hitler jokes/comedy in bad taste? Can something horrible be alleviated by ridiculing it?

                                          This is a philosophical question that doesn’t wven account for the author’s intent with the naming.

                                          And on the other side, would “Medium we can believe in” or “Medium we can” be more acceptable or less, and to whom?

                                          A rose by any other name… It seems to be a somewhat useful browser addition regardless.

                                          1. 2

                                            Can something horrible be alleviated by ridiculing it?

                                            Yes, somewhat, and only if actually done well. (And even then, sometimes the supposed object of ridicule can miss the point entirely and embrace whatever the “joke” was about.)

                                            I guess the point is, naming entirely unrelated things with the same pattern (“Make X Y again” here) is not comedy! It’s literally just spreading the slogan.

                                        2. 19

                                          You can’t ignore politics when they are no longer ignoring you. However much you may think that Lobsters is a domain of pure, unadulterated reason and everything unreasonable is offtopic, the linked software decided to make a political slogan ontopic.

                                          You’re grandstanding here about how neutral Lobsters is, but there’s no neutrality on this moving train, and telling people to shut up about the politics that affects them isn’t nice.

                                          1. 9

                                            We’re a community of practitioners. We show (create, invest, fix), rather than tell (scold, beg, demand).

                                            I like this a lot! The internet would be a better place if there were more places that followed this philosophy.

                                            1. 0

                                              Yeah, wouldn’t that be something…

                                              :-/

                                            2. 8

                                              I also happen to feel playful takes on MAGA is putting googly eyes on swastika, and was about to post similar comment. Didn’t post as the earlier exchanges OT exchanges like this on Lobsters suggest ethics is a taboo subjects to many here.

                                              But seriously, screw this.

                                              1. -6

                                                Fine, let’s discuss ethics.

                                                Calling a playful riff on the MAGA slogan”putting googly eyes on a swastika” is bullshit. It’s the same authoritarian communist rhetorical technique that the East German government used when they called the Berlin Wall the “anti fascist defense wall”. I’m not a huge fan of Trump myself, but I’m even less of a fan of the anti-Trumpist faction in American politics characterizing Trump’s policies as literally Nazi-like so they can feel justified in weaponizing the social norm that “Nazis=bad” in western society against their poltiical enemies.

                                                Nothing the Trump administration is doing is in any meaningful way close to the bad things that the Nazis did - frankly most of what he’s been doing are the same things that every post-WWII American presidential administration has done, just with less high class verbiage to describe it. The people who claim otherwise are doing so in order to make themselves feel like they’re morally-righteous crusaders instead of people having ordinary political disagreements in the American political system.

                                                Lobsters isn’t a political discussion forum, but if people are going to say that nonpolitical articles that happen to reference the current US President’s campaign slogan should be considered forbidden, you’re already bringing politics into the space, and you shouldn’t expect that your particular poltics must go unchallenged. There’s nothing wrong with the title of the article, and people claiming otherwise are making a backhanded political argument that Trump is Bad on a technical forum.

                                                1. 3

                                                  Now this is an off-topic comment.

                                                  1. 10

                                                    And yet despite being in good company, it is the only one flagged to death, because it comes from the perspective of the wrong tribe.

                                                    You see why I object to politics and “ethics” discussions? This is sort of the reason why–people don’t get a fair shake.

                                                    1. 0

                                                      This is a tough problem to solve, for sure.

                                                      I am among those who have flagged it as off-topic, as per @alynpost ’s comment here

                                                      https://lobste.rs/s/f4t0y2/make_medium_readable_again#c_ty2pp6

                                                      (based on my understanding, posted here: https://lobste.rs/s/f4t0y2/make_medium_readable_again#c_szkkme)

                                                      As both this downvote and the one I made on the other post were made in affect, I have removed them both.

                                                      1. -1

                                                        This whole discussion is a response to unnecessarily politicised title. Ironically, it’s the objection to the title was attacked by no ethics pls crowd.

                                                    2. 2

                                                      I’m not taking the bait. Would just remark that my reply, and your rant could be precisely avoided if the author stuck to fucking technicals for technical write up.

                                                  2. 6

                                                    How does one show, create, invest or fix in response to a negative pattern like the “Make X Y Again” headline?

                                                    1. 4

                                                      Indeed. I suppose one could suggest an alternate name for the project, in which case I will propose “Readable Medium” as a straightforward name for a browser extension that would entirely avoid any political connotations that only serve to distract from the substance of the project.

                                                      1. 1

                                                        I like that also because I find it humorous – a medium is a person who may do a “reading”, so “readable medium” sounds backward to me.

                                                      2. 0

                                                        If the title of the project bothers you, open an issue and try to convince the author of your point. If not possible, fork it.

                                                      3. 3

                                                        I downvoted this comment as “incorrect” but I have since reconsidered and removed my downvote.

                                                        I initially read the comment to mean “never discuss anything political, (as defined by us the community*) on this site”.

                                                        I know hope it reads “please feel free to discuss things political, but the focus should be on the technical contents of the submitted post”.

                                                        In this spirit, I will submit a comment that both reflects my opinion on the linked content, and will serve as a template for an acceptable comment that also addresses the political/ethical implications.

                                                        [start comment]

                                                        This project strikes me as useful for now, but ultimately reactive. It’s easy for Medium to redesign their site to defeat the circumvention, and the developer and users will engage in a game of whack-a-mole to keep up.

                                                        It’s a similar situation with ad blockers, with the significant difference that the market for ad-free browsing is much larger than the market for reading Medium without a bunch of banners.

                                                        This segues nicely into the problems with Medium’s business plan. Ultimately, it’s just Wordpress.com with a nicer editor and draconian rules about CSS. There’s really no reason to pay for Medium apart from the content, and the content, for me personally, seems mostly to be cryptocurrency boosters nowadays. Essentially it’s content as a commodity… there has to be a critical mass of writers who are only available on Medium for it to be worth paying for.

                                                        If Medium promised a cleaner reading experience as part of a paid tier, that would maybe help?

                                                        As to the name of the linked project - it’s unfortunately hard to detect irony on the web, and considering the “alt-right” has had some success in shifting the conversation by “pretending” to be racist, saying it’s for the “lulz”, I am prepared to automatically assume that someone who seems to do the same is either on the same side as this political faction, or insensitive to how they appear by choosing this name.

                                                        Personally I would add the name choice as a negative in evaluating this project.

                                                        [end comment]

                                                        If anyone upvotes or downvotes this comment, please let me know if it was because of the content, or the presentation, or the meta-narrative on how to handle political/ethical/sensitive submissions to the site.


                                                        * who represents this community is another question that deserves discussion but that’s for another time.

                                                        1. 0

                                                          Good comment, upvoted. You address the content of the article first, make good points and analysis, and close with minor but reasonable speculation and an opinion–and you don’t go on a screed.

                                                        2. 2

                                                          @gerikson, @jamesmacaulay, @JordiGH, @varjag I’ll reply to all of you at once in the interest of my time.

                                                          I have had folk observe that I’m prone to understatement. I may have done that here describing the project name as derivative, when I could have said political slogan (h/t jamesmacaulay) or dog whistle (h/t gerikson). Both would have been more accurate.

                                                          The de minimis statement I made supporting my off-topic claim was “Your comment is a generic complaint.” I then provided a test so the claim can be falsified: “[Your comment] applies to any submission matching your pattern.” This same test holds without regard to the sentiment of the comment. A similarly context-free comment supporting, rather than detracting, this political slogan, dog whistle, or derivative name would also be off-topic.

                                                          We know that naming things is hard. The problem is featured in a widely known joke. (“There are two hard problems in computer science…”) We also know that names can be chosen because they’re provocative. (“There’s no such thing as bad publicity.”) Discussing names gets the benefit of the doubt regarding topicality. The comment in question is off topic qua a kind of behavior.

                                                          Thank you all for your replies.

                                                        3. 1

                                                          I suppose to a progressive, the title would sound like “make medium awful again” – the exact opposite of what the author is trying to convey!

                                                          (I didn’t even pick up on the political reference until you pointed it out.)

                                                          1. 1

                                                            Can’t speak for others, but to me the original intent was clear given the context. But it’s hard to divorce the connotations of opression and hate from it. As @JordiGH said so eloquently, at this point it’s impossible to ignore politics as they won’t ignore you. Using this language will hurt people. I assume this wasn’t anyone’s intention by choosing this name, so I’m just trying to point this out hoping that when the next time comes around people can make a more informed decision.

                                                        1. 3

                                                          This is the one tool that is making me seriously consider flipping my workflow upside down and switching from vim + git cli to emacs.

                                                          That said, if anyone knows of something similar to magit that doesn’t require emacs, I’m interested in hearing about it! I’ve played with tig[0] a bit, but always go back to using git from the cli..

                                                          1. https://jonas.github.io/tig/
                                                          1. 3

                                                            I recently started using spacemacs in vim mode (which is its default) and it’s lovely. It’s been a much better experience getting a decent environment going than I’ve ever had with vim. Haven’t dug into Magit yet but I’m eager to. The docs for spacemacs are a bit scattered but this was the most useful for me to get going:

                                                            https://github.com/syl20bnr/spacemacs/blob/master/doc/BEGINNERS_TUTORIAL.org

                                                            1. 1

                                                              How long did you use vim workflows before switching? I’ve been a fulltime vim user for about 10 years, and I’m afraid that my productivity will take a serious spill as I try to unlearn muscle memory and build new ones. If you used vim for a while, I’m curious how that experience was for you.

                                                              1. 5

                                                                I switched mostly to emacs + evil (also used for Spacemacs) after a decade and a half or so on various vi implementations. Evil is very complete, evil often feels more like a complete vi implementation in Emacs Lisp rather than ‘vi emulation’. So far I didn’t have to unlearn any muscle memory.

                                                                I used Spacemacs for the initial switch, but I found it to be very buggy and slow. So, at some point I just switched to Emacs + hand-picked packages. I use use-package to load/install packages that I install with Nix and manage with home-manager. I use general to set up spacemaps-like key bindings (e.g. SPC-p-f to find a file in a project SPC-b-b to search buffers, etc.).

                                                                However, the Emacs ecosystem can be a bit overwhelming, so Spacemacs is a good entry point.

                                                                1. 1

                                                                  I never spent longer than six months or so using vim full time, so I’m in a very different situation. You’ll be able to put much of your muscle memory to good use in spacemacs, using the same keystrokes to navigate and edit within a buffer. However you’ll need to re-learn many other common tasks.

                                                                  You will absolutely take a big productivity hit at first, but if you stick with it then you’ll start feeling comfortable pretty quickly. Learning is its own reward! :)

                                                              2. 2

                                                                I have used vimagit and fugitive (both Vim/Neovim plugins) together for a while now. Vimagit is far from equal to magit in terms of power, but provides my Vim setup with the main features I missed from magit (visual range staging, easy amends, etc.). Fugitive is also useful on its own, but I currently mostly use it to asychronously push/pull from within Neovim (as vimagit does not yet provide these features itself).

                                                                1. 2
                                                                  1. There’s nothing wrong with converting to the true faith ;)
                                                                  2. There was a Go project called lazygit that was posted here a while back that a few people claimed was quite nice (haven’t tried it myself, so I can’t say), and reminded me of Magit – maybe that would be worthwhile?
                                                                  1. 2

                                                                    One thing I’m wondering about trying is a TUI-only Emacs configuration with a virtually completely empty .emacs file, flset up for just magit and nothing else. I’m wondering if the load time with a maximally stripped-down configuration would be short enough to make it feasible to use magit in a non-Emacs-oriented workflow. So, edit in something else, launch Emacs+magic in terminal, stage changes, close Emacs.

                                                                    The Emacs daemon mode might be an option too but it adds a bit of complexity to the setup. :/

                                                                    1. 1

                                                                      I use tig a lot for browsing commits, but for making commits, vimagit is a pretty cool magit-inspired vim-based git add -p type thing.

                                                                      (Though I keep using add -p anyway lol)

                                                                      1. 1

                                                                        Fugitive is amazing. I use it extensively at work.

                                                                        1. 1

                                                                          I’ve been using its most basic functionality (Gblame, and gutter highlighting) for at least 1 year now. Perhaps it’s time to invest more time in learning the ‘advanced’ features.

                                                                          1. 1

                                                                            Yeah! It’s got good diffing, committing, etc.

                                                                          2. 1

                                                                            If you like fugitive, I’d also recommend checking out gina.

                                                                            1. 1

                                                                              What does it do differently/better?

                                                                        1. 6

                                                                          I think the advice in this post is good advice. However, if you are using a job queue, then by definition your jobs all happen in the future, and you will always need to think about what’s going to happen to pending jobs when you deploy new code. Whether there are 2 affected jobs in the queue or 2000 is (“just”) a matter of degree.

                                                                          1. 2

                                                                            Yeah, thinking that you don’t have to deal with this problem seems like a real mistake. If you ever want to change the behavior of an existing job, you have to first be sure all existing ones are finished (which, realistically, means creating an entirely new job, deploying that and stopping using the old job, and once you’ve verified all the old ones are finished, you can get rid of that code).

                                                                          1. 5

                                                                            Continuing to tweak this Elm implementation of Peter Landin’s SECD machine that I made for Papers We Love Toronto last week: http://jamesmacaulay.github.io/elm-secd/.

                                                                            1. 5

                                                                              In my own code, if I ever have methods return self, it is because I am trying to implement some sort of chainable API. This pattern is popular when constructing objects in Rust, and is often called the “Builder” pattern. That is, instead of implementing a constructor that takes 5 different parameters like this:

                                                                              let mut my_obj = MyObj::new("some string", 1, SOME_ENUM, true, false);
                                                                              

                                                                              You use the “Builder” pattern to make it much more clear (also more verbose, but hey, “tradeoffs”):

                                                                              let my_obj = MyObj::new("some string")
                                                                                                                    .withPriority(1)
                                                                                                                    .withMode(SOME_ENUM)
                                                                                                                    .enableFoo()
                                                                                                                    .disableBar();
                                                                              

                                                                              The nice about this in Rust is, you can keep the mutability confined to object construction. After the object gets assigned to my_obj, it is considered immutable (you would have to write let mut my_obj to change this behavior).

                                                                              1. 19

                                                                                I like builders and have written APIs that provide builder patterns, but I really prefer option maps where the language makes it possible. For instance:

                                                                                let my_obj = MyObj::New("some string",
                                                                                                        {:priority 1
                                                                                                         :mode     SOME_ENUM
                                                                                                         :foo?     true
                                                                                                         :bar?     false})
                                                                                
                                                                                1. Option maps are usually shorter in languages with map literals.
                                                                                2. Option maps are data structures, not code. They’re easier to store and read from files. You can put them in databases or exchange them across the network. Over and over again I see boilerplate code that sucks in JSON and calls a builder fun for each key. This is silly.
                                                                                3. Builders in most languages (perhaps not Rust!) require an explicit freeze/build operation because they’re, well, mutable. Or you let people clobber them whenever, I guess. :-/
                                                                                4. Option maps compose better. You can write functions that transform the map, or add default values, etc, and call a downstream function. Composing builders requires yielding the builder back to the caller via a continuation, block, fun, etc.
                                                                                5. Option maps are obviously order-independent; builder APIs are explicitly mutating the builder, which means the order of options can matter. This makes composition in builders less reliable.

                                                                                Why not use option maps everywhere? I suspect it has to do with type systems. Most languages only have unityped maps where any key is allowed, but options usually have fixed names and specific but heterogenous types. The option map above has booleans, integers, and enums, for example.

                                                                                In languages like Java, it’s impossible to specify type constraints like “This map has a :foo? key which must be a boolean, and has a :mode key that can only be one of these three values”. Using a builder with explicit type signatures for each function lets you statically verify that the caller is using the correct keys and providing values of the appropriate type.^

                                                                                Of course, all this goes out the window when folks start reading config files at runtime, because you can’t statically verify the config file, so type errors will appear at runtime anyway, but you can certainly get some static benefit wherever the configuration is directly embedded in the code.

                                                                                ^Know what a heterogenous map is in Java? It’s an Object! From this perspective, builders are just really verbose option maps with static types.

                                                                                1. 1

                                                                                  I agree that it’s a shame to sacrifice the composability of option maps. I would prefer a builder API which is sugar on top of merging option maps, with an easy way of getting to the option maps when I want that composability.

                                                                                  You can also have builder APIs which are pure and return new objects instead of self. In Rubyland, ActiveRecord’s Relation API is like this, which is great because intermediary results can be shared:

                                                                                  posts = Post.where(user_id: 1).order("published_at DESC")
                                                                                  latest_posts = posts.limit(10)
                                                                                  favourites = posts.where(favourite: true)
                                                                                  

                                                                                  This provides one part of the composability you get from option maps, but not all of it. Unfortunately I don’t think the ActiveRecord::Relation API is built in a way that lets you build up relations with option maps when you want.

                                                                                2. 6

                                                                                  I’d argue that named parameters solve the opaque-list-of-arguments problem with much less complexity.

                                                                                  1. 6

                                                                                    As with all things, it depends on what kind of complexity. It increases complexity in the language for a decrease in complexity in your code. This may or may not be worth it, depending on how much you increase complexity in the language.

                                                                                    1. 4

                                                                                      less complexity

                                                                                      Questionable; have you seen Python’s positional/named parameter assignment rules? Granted, they’d be much simplified by killing the *args and **kwargs constructs, but at a language level, named parameters are definitely more complicated. On the other hand, they do make life somewhat simpler for language users. It’s a tradeoff.

                                                                                      Regardless, I think either is a perfectly acceptable solution to the problem.