1. 1

    The anecdote about the challenge of converting GOTO statements to functions and loops made me think of something I’m working on - refactoring a large amount of global Sass and CSS in an old Rails app. You can’t change one part without breaking other places, or even add new styles without countering the existing.

    Maybe many problems that make large codebases hard to work with come down to (the lack of) local reasoning, whether that’s CSS styles, global data, etc.

    1. 1

      I think that’s exactly right, and it matches my own experience with large, old CSS codebases as well. I am grateful that there are a bunch of things landing in CSS lately and in the years ahead which will help with that, because it is a real, and difficult problem. I think it is also the fruit of very reasonable design choices: the cascade is, at least in theory, designed to enable you to do minimal work in the smallest number of places… but in practice it often ends up having the opposite effect because of how organically design tends to evolve over time in an app or site.

      1. 2

        Good point! The cascade means CSS is non-local by design, and probably made a lot of sense when the web was intended to be small documents with a little bit of styling.

    1. 1

      An unsolvable problem! I wonder what happened since then! /s

      1. 2

        I see your /s, but to quote from the Go generics proposal:

        We believe that this design permits different implementation choices. Code may be compiled separately for each set of type arguments, or it may be compiled as though each type argument is handled similarly to an interface type with method calls, or there may be some combination of the two.

        In other words, this design permits people to stop choosing slow programmers, and permits the implementation to decide between slow compilers (compile each set of type arguments separately) or slow execution times (use method calls for each operation on a value of a type argument).

        1. 2

          Rust chose a similar path, where you can have monomorphized generic calls or use trait objects for dynamic dispatch, and it’s clear in the code which one you’re using.

          1. 0

            Let’s be realistic: The specialization path will win, because the Go compiler isn’t that fast to begin with (and everyone seems to be fine with that), and for generic methods (which are currently left out) you will need it anyway.

            1. 3

              How is the Go compiler not fast? It is faster than Haskell, OCaml, Rust, C++? What are you comparing it to?

              1. 1

                [Genuine question, not sarcastic or in point-scoring mode:] Is it fast because it’s faster than those at the same tasks, or because it does so much less? I would assume that a large part of why it’s so much faster is because it’s just doing so many fewer things, but I would also be willing to believe that there are things that would let it be faster if it were doing the same things, if someone made a case for why that would be so.

                1. 0

                  D was a magnitude faster a while back. And that’s with putting all things in favor of Go:

                  • Before the Go compiler was migrated to Go (and got slower).
                  • Assuming that 1 line of Go is equivalent to 1 line of D (which is silly).
                  • Pretending the emitted code is of comparable quality (it isn’t).
                  1. 0

                    So was Turbo Pascal, so is tcc, so is Oberon, …

                    But just because there are things that are faster doesn’t mean that something isn’t fast. A Tesla Roadster is generally considered pretty fast. New Horizons is a lot faster, but does that mean the Tesla Roadster is slow?

                    In both the cohort of compiled languages that are currently popular (and it is) and the cohort of languages that came out around that time, the go compiler ranks among the fastest.

                    1. 1

                      I think the important point is that the balance between “Go people claiming things” and “Go people actually delivering” is out of whack when it comes to “Go compiles fast”.

                      both the cohort of compiled languages that are currently popular (and it is)

                      Given that logic, McDonalds must have the best food ever invented!

                      the cohort of languages that came out around that time

                      Find me a language from the 70ies that compiles slower.

          1. 6

            To my lasting sorrow, above all others, my long-dreamed-of attempt to build a great research writing environment. Maybe I’ll get back to it someday. But at the current phase of life, the sheer scope of it—something which can be basically an Integrated Research Environment, which can robustly handle reference management, authoring, publishing, etc.—is just waaaaaay beyond what I can do in my limited side time.

            1. 5

              I’ll note (in contrast with some of the takes offered in sibling comments) that Mitchell didn’t suggest permanently banning language from your lexicon. He says to try it for a week, as a way of forcing yourself to think about what you actually mean. A week!

              Shorthands are useful, but once they become the only way we talk about certain things, they can end up obscuring and confusing things. Jargon is useful! Jargon has limits! Both of these can be true at the same time!

              1. 2

                Resting—in whatever form that happens to take on a given day. Likely contenders for various restful-to-me activities this week:

                • running
                • working on my intentionally-bespoke site generator
                • composing some new music
                • producing some music I composed earlier this year in Logic Pro with some actually good virtual instruments
                • writing, including the end-of-year summary I do every year
                • playing D&D with my wife and daughters
                • finishing a couple of books I started earlier this fall
                • journaling some personal and-of-year reflections and setting goals and adoration for 2021
                1. 2

                  I wonder how much of the need for tools like this is driven by poor chimeric package management on the ambient system. For example, I use NixOS, and while I could probably learn to use and like niv, I usually use a shell.nix with direnv’s Nix integration, which tends to give me shorter and simpler code with which to manage my toolchain.

                  1. 2

                    I don’t doubt there’s some of that, but I think there are some orthogonal pieces in play here. Managing my own system is one thing; managing a shared library or app across many different people’s machines is another; doing it transparently so most of those folks don’t have to think about managing it on a day to day basis is yet a further step.

                  1. 1

                    What was wrong with nvm that necessitated this competing with it?

                    1. 5

                      I think that’s more of a confrontational take than we’ve had with Volta—we all have used and were in many ways inspired by nvm, rvm, nodenv, pyenv, rbenv, etc. There were a few things we wanted to do differently and in some cases improve upon, though. One of the biggest is how global installs are handled. Another is the idea of having your toolchain management be declarative (like .nvmrc files!)—but in a way that can be managed for a whole organization, transparently. That latter bit was a key requirement for us at LinkedIn, and none of the tools in the space quite hit the mark.

                      The last bit is speed! Volta has had “being fast enough that it’s effectively invisible” as one of the key goals from the start, and it shows. You never notice it’s there unless we’re giving you a nice message that we’re installing a tool your project is missing. Key hot paths are consistently in the 10–20ms range to do all of Volta’s work. We consistently hear people say things like “I forgot it was there” or “Is it even doing anything?”

                      1. 3

                        One big benefit of Volta is that it runs on Windows. That in and of itself is enough reason to go with it for me.

                        1. 1

                          Oh yes! I’ve gotten so used to this with the tools I use that I often forget it’s not actually the norm, and in this case it was particularly problematic because nvm-windows has completely different semantics and behavior than the Unix-y nvm.

                      1. 1

                        Offtopic comment, but your website has great typography!

                        1. 1

                          Thank you! It’s a minor obsession of mine!

                        1. 2

                          Love this!

                          This is very similar implementation to my sums-up library for creating sum types in this manner: https://github.com/hojberg/sums-up where you implement sum types like so:

                          class Maybe<T> extends SumType<{ Just: [T], Nothing: [] }> {
                            public static Just = <T>(t: T) => new Maybe("Just", t);
                            public static Nothing = <T>(t: T) => new Maybe("Nothing");
                          }
                          
                          const x = Just(4);
                          
                          x.caseOf({
                            Just: (n) => {... },
                            Nothing: () => {... },
                          });
                          

                          My library misses the mark on a few things and you have a lot of niceties in here that I really like. The static match function for instance is really cool for point free as well as avoiding constructors for variants that do not carry data.

                          I’ve attempted a few times to get the constructors autogenerated, but haven’t been successful. That’s the missing piece in my mind for something like this to be truly ergonomic.

                          Thanks for this write-up! Sum Types are such a fantastic data modeling tool that is finally starting to get the popularity it deserves.

                          Edit: I’d love to connect and compare notes. I feel like there’s a really good library in here somewhere that could benefit from your experience.

                          1. 1

                            Ah, very neat—I actually ran into sums-up a couple months ago after bumping into dfreeman’s seidr library, and really liked the API for it. There are a bunch of other great options in this space, too. A friend and I built True Myth for Maybe and Result a few years ago, and I definitely thought about the problem of being able to generate the constructors and pattern-matching along the way. The obvious other big influence here is fp-ts.

                            At some point having a bunch of folks sit down and hammer out the TS equivalent of the Fantasy Land stuff would be super neat. I’m buried right now, but feel free to shoot me an email (linked at the bottom of the post), always happy to connect!

                            Edit: just realized that’s your library seidr, and that dfreeman had forked it!

                            1. 1

                              Nice! Yeah dfreeman has helped and contributed a lot on both libraries.

                              Would be really cool to try and get folks together. I’ll try and set something up in the next couple of months.

                          1. 22

                            I’ve come to the same conclusions. For me, the magic combination of features needed in a static type system is almost the same:

                            • type inference everywhere (or almost everywhere)
                            • algebraic data types (i.e. Sum/tagged union types, must be parameterizable i.e. generics, and have pattern matching)
                            • soundness
                            • immutability by default

                            These are not always enough by themselves. You need libraries and frameworks that build on these things in the right way. But when they are present, it seems the ecosystem naturally gets it right.

                            I think the key thing is this set of features enables you to “make illegal states unrepresentable” - and makes it less painful than the alternative ways of coding.

                            This doesn’t mean I only use languages like this. I actually use Python mainly, and it also has a completely different set of features that has its own set of advantages. In some cases these features produce ecosystems that are hard for statically typed languages to rival (e.g. the Django ecosystem).

                            But I do think if you only have experience of C/C++/C#/Java/TypeScript, you don’t know enough about type systems to dismiss the advantages of things like Elm/Haskell/OCaml/ReScript/Rust, which really do put you into a different world.

                            1. 5

                              I think the key thing is this set of features enables you to “make illegal states unrepresentable”…

                              For me, this was how the value of static typing really “clicked” in my brain. I had understood very generally why people liked it for years, but it never seemed like that big a deal until I learned about sum types (although I guess enums started me down that line of thought).

                              1. 3

                                Fwiw, TypeScript does actually have just about rich enough types to support for nice things like sum types - not directly but there’s an okay way to encode it.

                                1. 6

                                  With TypeScript, it’s the lack of soundness that lets you down, combined with the number of type annotations needed to get you to the point where you are confident that the compiler will always have your back. You start in a very different place to something like Elm. YMMV etc.

                                  1. 5

                                    Yes. I think the richness of TS’ types still make it a meaningful win over JS, especially where they’ve pushed it over the last few years, but I also consistently miss the soundness of Rust, Elm, etc. when working with it.

                                    1. 1

                                      I don’t feel that on a day to day basis the unsoundness is causing me big problems. It just means the type system has loopholes: you don’t poke them on purpose and it doesn’t come up. null safety is a much bigger deal and tsc gets that right.

                                      It’s like, even in Haskell I can accidentally write an infinite loop and it’ll almost certainly type check since let x = x in x has type forall a. a. IME that’s about 50% “just don’t do that, then” plus 50% “explicit recursion is slightly perilous so write everything as map+foldr invocations”.

                                  2. 2

                                    I went through a similar process, from being a massive Smalltalk fan (and implementing an AoT-compiled Smalltalk) to working on a language with a static type system. The things that make me hate static types in languages were largely coming from the Pascal view of the world, where the types aren’t sufficiently expressive to check the invariants that I do get wrong or to be able to understand things that I knew were correct. In languages like Pascal (and, often, C++), I need type-system escapes because I can’t express exactly what I want in the type system and so it raises false positives (this is safe, but you need a reinterpret_cast) and false negatives (this is unsafe, but the type system still allows it).

                                    My list (i.e. what we’ve converged on for Verona, which is not what I originally wanted but what other people have convinced me that I now want) is similar to yours:

                                    • Complete type inference within a function, but fully specified types on function boundaries. Global type inference is both complex for the compiler and for the programmer, because I have to run the type inference algorithm in my head over the whole program to understand the types at a specific point.
                                    • No magic types (anything that has a type that can be inferred should have a type that I can write down using the language syntax. If it’s hard for the reader to figure out a type then I should be able to write it explicitly.
                                    • Structural types. Concrete types that implement a set of methods implement any interface that matches that set of methods.
                                    • Algebraic types. Union and intersection types are both incredibly useful. Union types let me pass around something that must be one of a small set of things. Intersection types on interfaces let me match on things that implement multiple behaviours easily. That gives me most of what I enjoy from dynamic languages in the Smalltalk family but in a way that is much easier to optimise.
                                    • Flow sensitivity. If I write if (x is T) then I shouldn’t need to cast x to T in the body of that if statement. Any code in blocks that are dominated by that check should assume that the type of x is T. The same applies to pattern matching on types. If I nest pattern matching on interface types, the type in the nested block should be an intersection type of both interfaces.
                                    • Immutability and ownership as first-class components of the type system. If I want an immutable string, I can write imm & String (intersection type that must be both immutable and String). In Verona, ownership is tied to regions. Any pointer is either imm (can’t be modified by anyone), iso (is the only pointer from outside a region to the sentinel object that dominates all objects in a region), mut (is an interior pointer to an object in a region, can be stored only on the stack or in a field of another object in the region), or readonly (may be any of the above, but I cannot modify it via this pointer).
                                    • Generics.
                                    • Rich compile-time reflection in the language, which I can use to implement run-time reflection on the types and properties that I want (ideally using standard-library types).

                                    I’m not a fan of immutability by default because it then requires a lot of careful optimisation in the compiler to figure out when it’s safe to do in-place mutation and that leads to performance that’s very hard to reason about. The Verona model for immutability is that every object is created mutable (either as the sentry of a new region or in the same region as some other object) but if you have an iso pointer to the sentinel of a region, you can freeze that region. You then get an immutable object graph, which may contain cycles. Immutability is a distinct property to the object type.

                                    This system makes it very easy to express the invariant that any only immutable objects can be shared between threads (which is the number one property I want my type system to enforce) and makes it cheap to pass complex (possibly cyclic) object graphs between threads without needing any type-system escapes (this is possible in Rust only by using unsafe crates - even passing a DAG between two threads in Rust requires using something like the RC trait, which is implemented in unsafe).

                                  1. 1

                                    Great article, but I’m not really sure the current react-alike path we (industry-wide) appear to be on is the correct one. It seems to be we’re going through a lot of trouble to pretend things aren’t the way they are, rather than just embracing it and developing disciplines around managing it.

                                    1. 2

                                      I think it’s right to be skeptical. React and its variants are solving real problems for certain classes of UI problems, but to date nobody really knows what a DAW or CAD program written with reactive patterns would look like or how well that would work out.

                                      My personal approach to this is to offer good “escape hatches” for dropping to a lower level when the reactive layer isn’t the best fit. In current Druid, this is the “Command” mechanism, which is clunky but lets you apply imperative UI patterns pretty easily. In the Crochet prototype, I offer the low level tree mutation API, which is probably no worse than imperative DOM mutation, though almost certainly faster. And it might be possible to layer interesting things on top of that.

                                      1. 1

                                        I don’t think reactive is necessarily the wrong way to go about building GUIs, but I think it requires a stronger “framework” (probably not the best term) than an embedded DSL, be it in Swift, JSX, or Rust. Not only that, I believe that certain things (one example being modals) should never be shoehorned into the twin-trees paradigm we see in react where the call graph / container hierarchy and screen-space-subdivision tend to be the same set of of entities.

                                        I don’t think it necessarily requires a separate implementation language, but it should be more than you expect to always have available in a general-purpose language as we see them today. It should have declarative options to describe structures and hierarchies, and the concept of context (be it via component hierarchy or call hierarchy) should be built-in, alongside the assumption of cyclic invalidation/validation cycle. Add a well-thought-out (and typed) event system including observables. Think of a mix between Flex’s MXML and [Bindable] system, and React’s declarative functionalish strategy (within a single component), but implemented mostly at build-time like Svelte.

                                        When you build around an established component lifecycle with language support for (in)validation of computed state (and rendered output), I believe a lot of the things people have been told to hate about “OOP” will once again become benefits, rather than risks and complications.

                                      2. 1

                                        Two thoughts here:

                                        1. “Developing disciplines around managing it” has severe limitations. I find systems thinking an illuminating lens here: it’s far more productive to make both cars and roads safer than to lean on the idea of trying to “develop disciplines” around better drivers. There is only so much you can do on the latter front. There’s a lot you can do on the former front. I’m increasingly of the view that the same goes for language design, framework design, etc.

                                        2. We did try the path of “embracing” the way things are in web UI programming (and other kinds of UI programming, too). At least on the web, where I have fairly deep experience with it… it was terrible. My experience trying to pick up UIKit didn’t make me think that was going to be a better experience than writing raw imperative DOM, either. Approaches like React are much more tractable in practice. (That includes my favorites on the web, Elm and Glimmern.b. that latter links to a post I wrote doing a deep dive on how it works.)

                                        1. 2

                                          To be clear, I use React all the time, have done for years now. If I were to green-field some web stuff right now I’d use Svelte, now it’s grown some TypeScript. Compared to DOM, React is ambrosia from heaven (or at least it was, until they started trying to turn JS into OCaml, but I digress). But it’s not so great when compared to Adobe Flex, for example.

                                      1. 3

                                        I have to read this it breaks the tag record!

                                        1. 3

                                          He also talks about Haskell and lenses, so I could have upped it further!

                                          1. 2

                                            Next time :) It is almost 5k words, very dense, and with tons of links to other resources, so does cover quite a bit of ground.

                                        1. 2

                                          Interesting work. I’m thinking about a comparison with Adapton-style algorithms. In particular, Adapton implementations tend to store cache information at each node of the graph of cells, rather than relying on a global invalidation signal.

                                          1. 1

                                            That’s actually how the Glimmer implementation works as well. (As the callout at the end of the post notes, Glimmer is actually directly inspired by Adapton.) Each node gets a “tag,” which is a reference back to the node and its current and previous clock values. The functions I described as markAsUsed and markAsChanged are actually consumeTag and dirtyTagFor respectively. Those cache current and previous clock values for that node. You still need some degree of global invalidation for this use case—so “dirtying” any tag does that—because you have to schedule a re-render of the UI, but there’s no global cache.

                                            An earlier draft included those details, but it got so far into the weeds that it became very difficult to keep the big picture in view, so I ended up cutting them.

                                          1. 7

                                            Note that I updated the title in response to some comments on that other website, because it was misleading the discussion. Ended up being a hotter take than I actually intended!

                                            1. 4

                                              Not at all involved with apple stuff, but I found https://nooverviewavailable.com/ a neat idea (via https://atp.fm/episodes/349 )

                                              1. 3

                                                Yes! I meant to include that in a footnote in the post! Editing it in now; thanks for the reminder!

                                              1. 1

                                                Default output:

                                                ╭──chris@cdk-rmbp-13 ~
                                                ╰→ 
                                                

                                                In a Git dir:

                                                ╭──chris@cdk-rmbp-13 ~/S/c/v3 (master=)
                                                ╰→ 
                                                

                                                The = after the branch name changes to include , , <> for “you should pull”, “you can push”, “you have conflicts”; != for “uncommitted changes”, ? for “untracked files”, and % for “stashed”.

                                                1. 3

                                                  This appears to be a podcast. It appears to have an rss feed which allows it to be consumed using a podcast client: https://newrustacean.com/feed.xml

                                                  Why make it so hard / impossible to find any reference to the feed when browsing the website?

                                                  1. 2

                                                    That’s an interesting question from a discoverability point of view! I already subscribe to New Rustacean (I think I stumbled across Chris Krycho’s work via Twitter), so I was curious to see how easy it’d be to find it on the website.

                                                    Like you, I couldn’t find an obvious link from the show notes to the whole podcast feed, but when I found the homepage (https://newrustacean.com/), I saw lots of ways to get to the podcast, including the RSS feed.

                                                    If I remember right, the website is built using Rust’s standard documentation tooling. A neat hack, but a little twisted. I don’t know how easy it is to change the base templates to include the appropriate link(s). However,tThe lack of discoverability on the show notes might be useful feedback for him to receive.

                                                    Some searching later

                                                    Ah yes, here’s the repo: https://github.com/chriskrycho/newrustacean.com. You could raise an issue, or contact him directly via another mechanism?

                                                    1. 1

                                                      when I found the homepage (https://newrustacean.com/)

                                                      I failed to find the homepage. I clicked on the big logo in the top left corner and assumed that that had taken me to the homepage, but in fact it took me to https://newrustacean.com/show_notes/index.html.

                                                      You could raise an issue, or contact him directly via another mechanism?

                                                      He appears to have authored this thread, so I assume he will see these comments…

                                                      1. 2

                                                        Oh! Certainly not an intended outcome—just a side effect of assuming (incorrectly!) that most people would end up seeing the home page. I’d not realized—literally until this post!—that the docs don’t have a way to link you back to the home page. If you have a GH account, I’d love it if you opened an issue, and I’ll figure out a way to get the RSS feed link into the show notes version of the page.

                                                        Things like this are definitely the downside to a choice I made really early on because I thought it would be helpful for a bunch of things about the show (as indeed it has).

                                                  1. 2

                                                    Off the top of my head:

                                                    • desktop or mobile app development: I just started learning Swift and macOS and iOS, and it’s fascinating to be learning UI stuff and being a novice all over again after more than a decade of doing web UI work

                                                    • assembly: I did a small amount of it in my first job, and I can read enough to get by in a desperate pinch, but I couldn’t write it to save my life

                                                    • GPU or graphics anything: I’ve never touched any of it, and I wouldn’t even know where to start

                                                    • compilers: I have some understanding conceptually, but in practice, I’ve never so much as written a parser

                                                    • APL and friends: formal verification sounds super interesting, but I’ve never done it

                                                    • good performance tuning on the web: I can do a fair bit of optimization and analysis in C-or-similar contexts, but deep performance tuning on the web is, ironically, something I don’t have almost any experience in—despite having spent the last years doing web dev full time and having been doing it at least part time for longer than anything else

                                                    • advanced FP, much less dependent types: most production Haskell might as well be gibberish to me, and the kinds of proofs and formalisms you can express in F* or Idris blow my mind

                                                    • SQL optimization: I’ve written a fair bit of MySQL and PostgreSQL over the years, but if you wanted me to tune a query… nope. I hear there are reports you can ask the SQL engines to run? 😆

                                                    • logic programming: just a big ¯\_(ツ)_/¯ here: I know it exists, and that’s the extent of my knowledge of it

                                                    • hardware: I did some electronics work for my bachelors (physics), and that’s the extent of my knowledge

                                                    • OS implementation: hazards of being self-taught; I have essentially no OS implementation knowledge

                                                    • networking: anything beyond the basics; off the top of my head I couldn’t tell you the difference between TCP and UDP, and the details of how HTTP vs. HTTP/2 works is just a “huh” at this point

                                                    • machine learning: there’s some linear algebra and derivatives and stuff I hear?

                                                    • mathematical formalisms: both on the linear algebra side and the set theory side, I’m just mostly ignorant of this side of things yet. (Sadly in the linear algebra case: it’s the only math class I ever dropped, because I had a horrid teacher—the kind who was misgrading my homework assignments.)

                                                    1. 2
                                                      • going to church as usual tomorrow
                                                      • reading The Fifth Season
                                                      • sleeping
                                                      • working to be kind to my kids and my wife even though I feel slightly miserable.

                                                      On that last note: burnout is bad, and recovering from it is hard. 😭

                                                      1. 5

                                                        A list of things I want to in my free time:

                                                        • organize content for first episode of a podcast I’d like to start in 2019
                                                        • contact people to encourage them to attend or speak at the conference I’m excitedly attending next summer
                                                        • write some code which communicates to programmers some different forms of logic
                                                        • read some of the several math/logic/philosophy books I got in the last 1-2 months
                                                        • add timings/bookmarks to a meetup video I uploaded months ago
                                                        • plan a virtual conference event for a prog lang for the 2019 year
                                                        • plan an organized effort for documenting a prog lang

                                                        Ah, it’s nice to be relatively healthy again.

                                                        1. 1

                                                          What’s the podcast going to be about?

                                                          I’d love to do one again but my day job leaves too little personal time and I really need to focus like hell on upping more core development skills.

                                                          1. 4

                                                            PureScript, but will likely be about FP in general with a bias towards Pure FP, type theory, algebra, logic, and maybe some other related things.

                                                            1. 3

                                                              Is there a mailing list I can join to be notified if/when the first episode is released?

                                                              1. 2

                                                                No, I was planning on just posting to social media, like Twitter and Reddit and their Discourse for that lang. Is there anywhere else I should post? Or do you feel an email list is different enough that I should adopt one? I’ve never done an email list before.

                                                                1. 2

                                                                  I’d love to be notified somehow, and I’m apt to miss it in the channels you mentioned unless I’m already following you there. At a minimum, setting up a Twitter account specifically for the show would be a start; but you can set up a free ‘subscribe to get info when I launch’ kind of email list page on the domain you’ll have for it, too, and that’d be grand.

                                                                  1. 2

                                                                    Basically I just want to be notified when it’s available, otherwise I’ll forget to listen. I don’t want to follow on Twitter because I closed my account months ago. It’s too toxic a platform.

                                                                    1. 1

                                                                      https://www.pure-pandemonium.club/ I can’t figure out how to get an email list, but I might do that if you can recommend an easy way to do it.

                                                                      1. 1

                                                                        I can’t give step-by-step instructions (because I don’t remember, and you’ll figure it out I think), but you could set up Feedburner. You’ll need a feed.xml file. I don’t remember whether or not you’ll need a sitemap.xml file, but you ought to have one anyway for SEO. Feedburner seems to have an “I am a podcaster” option, but I don’t know what it does.

                                                                        I remember it being easy to set up. Any time I write a blog post on my own site, my subscribers get an email with the content of that post, and a link to view the original page.

                                                                        1. 2

                                                                          Here’s an RSS feed for the blog posts: https://www.pure-pandemonium.club/index.xml I’ll set up a separate RSS feed for the audio files.

                                                                          As far as email notifications, it looks like ifttt.com makes it super easy to get an email notification for new RSS feed items. And mailchimp.com has an RSS-to-email thing, too: https://mailchimp.com/features/rss-to-email/ I’ll take a look at that and other options then post here the solution I find.

                                                                          Looks like Hugo gave me a sitemap.xml file, too, FWIW: https://www.pure-pandemonium.club/sitemap.xml

                                                                          It would be really nice to have RSS feed subscriber analytics, but I don’t know how to do that. I don’t want to use Feedburner for various reasons, so perhaps I can just set up something like https://github.com/portable-cto/rss-to-email on a FaaS…

                                                                          1. 2

                                                                            In the meantime, send an email to mgmt @ pure-pandemonium.club from the email you want to be notified at, then I’ll add it to the notification list when I’ve found one.