Threads for weberc2

  1. 10

    I don’t understand this at all. It’s titled “the fundamental difference between Terraform and Kubernetes” but then goes on to explain that they’re identical.

    1. 6

      I think the fundamental difference they’re getting at is K8s continually evaluates reality vs desired and adjusts it as required. Terraform only does so when you run an apply. (Not sure that’s a fundamental difference, but that’s their terminology. 🤷🏻‍♂️)

      I guess if you ran while :; do terraform apply --auto-approve; done you could equate it to being the same as K8s.

      1. 8

        while :; do terraform apply --auto-approve;

        This is the most terrifying shell script fragment I’ve seen in recent memory. 😱

        Yes, in theory your TF code should be audited and have guard rails around destroying critical resources etc. etc. but…IME it’s usually at least partly the human in the loop that prevents really horrible, data-destroying changes from happening.

        Kubernetes, on the other hand, makes it (intentionally) difficult to create services that are “precious” and stateful, so you’re somewhat less likely to fire that particular footgun.

        …and lest it seem I’m dumping on TF and talking up K8s: I think Kubernetes gives you all kinds of other ways to complicate and break your own infrastructure. It just usually takes more than a single-line change anywhere in your dependency graph to potentially schedule a stateful node for deletion (and likely re-creation just afterward, but that doesn’t protect you from local state being lost).

        They’re also equally good at helping you create a bunch of “objects” for which your cloud provider can charge you a substantial monthly fee, which I think helps to explain their mutual popularity amongst the AWS/GCP/Azure/etc. set.

        1. 2

          Just noticed the typo in it, stops someone copy/pasting it I guess.

          I’m not convinced sticking TF in a while loop is a good choice, but that’s how my scaled out mental model of the two tools differs.

        2. 2

          Beyond that, Terraform also understands dependencies between services while k8s continuously tries to reconcile (so if you create some resource that depends on another, Terraform will wait for the first to be created before creating the second, while Kubernetes will immediately try creating both and the second will just fail until the first is created).

        3. 4

          They’re quite different. Here are some things you can do with Terraform and Kubernetes that aren’t symmetric, showing that they are distinct:

          • we can use the Kubernetes provider for Terraform to declare objects for a Kubernetes cluster, and apply Terraform multiple times against multiple Kubernetes clusters
          • we can apply Terraform from inside a Kubernetes Pod, regardless of which Terraform providers we are using
          • we can leave a Kubernetes cluster running for a week, constantly changing state, without interrupting coworkers (while Terraform requires a lock in order to apply state changes)
          1. 3

            Oh, I’m not claiming that they are identical. I just think the OP is: it’s of the form “the fundamental difference between things A and B is that A does X, while B does X”.

            I am satisfied by caius’s sibling comment that it’s trying to talk about the bandwidth difference: K8s’s feedback loop is very fast, while TF’s isn’t. But I don’t regard that difference as particularly fundamental, and I don’t think the ones you’ve identified strike me as fundamental either. So I’m asking: what is?

            I don’t use either tool regularly, and I don’t have great mental models of them, but just in case it helps clarify, I think what I’m looking for might be ownership. K8s materializes the “resources” it manages inside itself, while TF prods external systems into changing state.

            1. 2

              You could conceivably write a Terraform Custom Resource Definition for Kubernetes and make a controller that continuously applies it. 🙃

          1. 55

            The standard library in Go.

            1. 30

              I have done lots and lots of Java and Python in my career before I used go. I honestly find the go stdlib just okay. There is usually something that does the trick, but I am not a super fan. I am also not buying this consistency thing. I deal a lot with strings unfortunately and this mix of fmt, strings, strconv,bytes to do anything with strings is not intuitive. I understand where go is coming from historically and from a design philosophy yet I don’t find it that superior.

              (personally I would love to see a language that is a bit more high level/expressive like python, but with the go runtime/deployment model)

              1. 7

                I started a security project specifically because of high quality cryptography code in the standard library like no other language.

                1. 13

                  You mean the one where you can’t multiply a duration by a number, but you can multiply a duration by a duration?

                  1. 3

                    Maybe I’m missing something, but dur := time.Hour * 2, as well as dur := 2 * time.Hour compile just fine.

                    1. 6

                      The literal is being implicitly converted to a duration. Try it with a variable instead of 2.

                      1. 5

                        Got it. However, that’s not really a limitation of the standard library, but rather a limitation of the language that prevents implicit type casting.

                        1. 7

                          The point is that mathematically, multiplying a number with a duration should work, whereas multiplying a duration with a duration should not.

                          1. 2

                            It never occurred to me that people would expect to be able to multiply an int by a duration and not multiply two durations together. Personally I’m grateful that Go doesn’t implicitly convert ints to durations or vice versa–I suspect this has prevented quite a few bugs.

                            1. -5

                              Have you ever had physics in school? You might want to repeat it.

                              I’m not talking about implicit conversions.

                              1. 3

                                I think the physics repeat remark might be a little heated for this context: we can all take a breath here and try to understand each other.

                                I’m personally of the opinion that multiplying an int by a duration implicitly is a bit of an anti-feature: I expect it to work in loosey-goosey languages like Python or Ruby, I even expect it to work in languages like Rust where the Into trait lets someone, somewhere, define explicitly how the conversion should occur (this starts getting into the realm of the newtype pattern from eg. Haskell), but I don’t expect two disparate types to multiply or add together, no, regardless of what those are.

                                To be extra clear: I think Into is the correct way to solve for the expected ergonomics here, and wish more languages had this type of explicit control.

                                1. 12

                                  Well, thing is:

                                  • Adding two durations is obviously okay.
                                  • So is subtracting two durations.
                                  • Negative durations are okay too.
                                  • Adding a duration to itself n times is okay.
                                  • We just defined multiplication of durations by natural numbers. Therefore it is okay.
                                  • Since negative durations are a thing, we can extend this to relative numbers too.
                                  • Actually, multiplication can be extended to real numbers as well.
                                  • All real numbers except zero have an inverse, so it’s okay to divide durations by any non-zero number.

                                  On the other hand:

                                  • It is not okay to add (or subtract) a duration and a number together.
                                  • It is not okay to multiply (or divide) a duration by another duration.

                                  So if I want to be super-strict with my operations and allow zero implicit conversions, I would have the following functions:

                                  seconds s_add(seconds, seconds);
                                  seconds s_sub(seconds, seconds);
                                  seconds s_mul(seconds, double);
                                  seconds s_div(seconds, double);
                                  

                                  Or if we’re in something like ML or Haskell:

                                  s_add : seconds -> seconds -> seconds
                                  s_sub : seconds -> seconds -> seconds
                                  s_mul : seconds -> real -> seconds
                                  s_div : seconds -> real -> seconds
                                  

                                  Now the binary operators +, -, *, and / are functions just like any other. We can just overload them so they accept the right operands. We have such an overloading even in C: adding two floats together is not the same as adding two integer together at all, but the compiler knows which one you want by looking at the type of the operands. (It also has the evil implicit conversions, but that’s different.)

                                  So while a language that allows multiplying a duration by a number looks like it is implicitly converting the number to a duration before performing the multiplication, it absolutely does not. That’s just operator overloading: because you really want to multiply durations by ordinary numbers. And since multiplying two durations together makes no sense, you should get an error from your compiler if you try it.

                                  1. 7

                                    Again, multiplying a duration by a number is not “loosey-gooey”. Multiplying a duration by a duration is “loosey-gooey”, unless the result is a duration squared, which it isn’t.

                                    1. 1

                                      I think it depends on what you believe types are for—are they exactly units, or are they constraints (or both)?

                                      1. 3

                                        No matter if you treat types as units or constraints, you want to have operations that make sense. Multiplying 3 seconds by 5 hours doesn’t mean anything (except in the context of physics, where it can be an intermediate value).

                                        1. 1

                                          Agreed that you want operations that make sense, but if you think of types as units, then you probably want to be able to multiply ints and other types. If you think of them as constraints (especially for avoiding bugs) you probably don’t want to be able to multiply ints and arbitrary types. Personally, I’m more concerned with avoiding bugs rather than a strict adherence to mathematicians’ semantic preferences. There’s nothing fundamentally wrong with the latter, but it seems likely to produce more bugs.

                                          1. 3

                                            How exactly does allowing durations to be multiplied with each other, while not allowing them to be multiplied by integers, allow you to prevent bugs? If anything, I’d say it can introduce bugs.

                                            you probably don’t want to be able to multiply ints and arbitrary types.

                                            Where did I say anything about multiplying integers with arbitrary types?

                                            1. 1

                                              How exactly does allowing durations to be multiplied with each other, while not allowing them to be multiplied by integers, allow you to prevent bugs?

                                              It means we can’t accidentally multiply a duration field by some integer ID field (or a field of some other integer type) by accident. In general it stands to reason that the more precise you are about your types, the less likely you are to have bugs in which you mixed two things that ought not have been mixed, and Duration is a more precise type than int. I’m not familiar with any bugs arising from being too precise with types, and even if they exist I suspect they are rarer than the inverse.

                                              Where did I say anything about multiplying integers with arbitrary types?

                                              Presumably you aren’t advocating a type system that makes a special exception for durations and ints, right? Feel free to elaborate about what exactly you’re advocating rather than making us guess. :)

                                              1. 3

                                                It means we can’t accidentally multiply a duration field by some integer ID field

                                                That’s why you use a different type for the ID.

                                                In general it stands to reason that the more precise you are about your types, the less likely you are to have bugs in which you mixed two things that ought not have been mixed, and Duration is a more precise type than int.

                                                Preciseness is only good when the typing is correct.

                                                Presumably you aren’t advocating a type system that makes a special exception for durations and ints, right?

                                                No, I’m advocation for a system that allows you to define multiplication however it makes sense. Like in Python. Or Nim. Or even C++, though C++ is partially weakly typed because of the C heritage.

                                                1. 1

                                                  That’s why you use a different type for the ID.

                                                  I agree, I’m advocating for precise types. But in any case you seem to be okay with “untyped” ints for quantities/coefficients so we can use the example of mixing up coefficients of durations with coefficients of some other concept.

                                                  Preciseness is only good when the typing is correct.

                                                  Agreed, and Go gets the typing correct, because types aren’t units. 👍

                                                  No, I’m advocation for a system that allows you to define multiplication however it makes sense. Like in Python. Or Nim. Or even C++, though C++ is partially weakly typed because of the C heritage.

                                                  My background is in C++ and Python. Very little good comes out of operator overloading but it opens the door for all kinds of clever stuff. For example, Sqlalchemy overloads operators (such as ==) to allow for a cutesy DSL, but a bug was introduced when someone tried to use a variable of that type in a conditional. I’ve never heard of bugs resulting from a lack of overloading, and it’s easy to workaround by defining a Multiply() function that takes your preferred type. No surprises, precise, and correct. 💯

                                                  Moreover, the canonical datetime libraries for C++ and Python don’t give you back “DurationSquared” when you multiply two durations, nor do they allow you to divide a distance by a duration to get a Speed because types aren’t units–you could overload the multiplication operator to support duration * duration or overload the division operator to support distance / miles, but you have to model that for every combination of types (at least in mainstream languages like C++, Python, Go, etc) and for no benefit that I’m able to discern (apart from “to allow certain types to behave sort of like units”, which doesn’t seem like a meaningful goal unto itself).

                                    2. 3

                                      In rust

                                      • The Into trait does not do automatic coercion. The Deref trait does under the right circumstances, but you shouldn’t use it to do so here (it’s really just meant for “smart pointers”, though there is no good definition of what a smart pointer is other than “something that implements Deref”).

                                      • Traits like Add and Mul take both a lhs and a rhs type. For Add those would both be Duration. For Mul I would strongly expect it to take a Duration on one side and an int/float on the other.

                                      Multiplying two duration’s together makes little sense. What is “2 seconds * 10 seconds”? Units wise I get “20 seconds^2” (which unfortunately most type systems don’t represent well). Physical interpretation wise time^2 is mostly just an intermediate value, but you could visualize time as distances (e.g. with light seconds), in which case it would be an area. Or alternatively you might notice that you divide distance by it you get an acceleration (m/s^2). What it definitely isn’t is a duration.

                                      Multiplying a duration by a unit-less quantity (like an integer) on the other hand makes perfect sense “2 seconds * 10” is an amount of time 10 times as long. Hence why I would Duration to implement Mul with the lhs/rhs as ints.

                                    3. 1

                                      Sorry, my remark wasn’t meant to be provocative. I’ve just spent so much more time in the programming world than the math or physics worlds, hence “it never occurred to me”.

                          2. 2

                            You can find rough edges in every language and every (standard) library. This is unfortunately a fact of developer life.

                            1. 2

                              I wouldn’t call this a rough edge, but a fundamental flaw of the type system.

                            2. 2

                              In retrospect, time.Duration should have been an opaque type and not a named version of int64 (as the person who added Duration.Abs(), I’m well aware of the pitfalls), but there are no mainstream languages with the ability to multiply variables of type feet by feet and get a type square feet result, so I wouldn’t blame Go for that particularly.

                              1. 2

                                there are no mainstream languages with the ability to multiply variables of type feet by feet and get a type square feet result, so I wouldn’t blame Go for that particularly.

                                Well yes, but it should be an error.

                                1. 1

                                  There are also no mainstream languages where it’s an error. I agree though that it should have been type Duration struct { int64 } which would have prevented all arithmetic on durations.

                                  1. 2

                                    It’s an error in rust

                                    fn main() {
                                        let dt = std::time::Duration::from_secs(1);
                                        dt * 2; // ok ("warning: unused arithmetic operation" technically)
                                        dt * dt; // error: mismatched types. Expected `u32` found struct `Duration` (pointing at second operand)
                                    }
                                    

                                    https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=bfd82c951af32f237ff3fcd568be5f75

                                    1. 1

                                      In Rust, Duration is a struct, not a bare int. The multiplication works through operator overloading, which allows u32 but not another Duration. I take the point that this is better than Go.

                                      As I said above, it would be better if in Go Duration were type Duration struct { int64 }. Go doesn’t have operator overloading, so you wouldn’t be able to multiply at all, but you’d have to use methods, like d.Mul(3) etc. It would be worth it though because then those could saturate when they overflow instead of wrapping around. It’s a minor language wart.

                                    2. 2

                                      Python does it correctly.

                                      from datetime import timedelta
                                      hour = timedelta(hours=1)
                                      print(hour)
                                      print(3*hour)
                                      print(hour*hour)
                                      

                                      Output:

                                      1:00:00
                                      3:00:00
                                      TypeError: unsupported operand type(s) for *: 'datetime.timedelta' and 'datetime.timedelta'
                                      

                                      Attempt This Online!

                                      1. 2

                                        Yes, but Python itself does not use timedelta, which sucks.

                                        >>> time.sleep(datetime.timedelta(0,0,1))
                                        TypeError: 'datetime.timedelta' object cannot be interpreted as an integer
                                        
                              2. 1

                                I come from python world but would love to hear more about what’s so special about Go standard library

                                1. 4

                                  I would say the quality is more consistent across modules than Python’s, which feels like it evolved more organically. There’s also some foundational concepts like a stream of bytes that’s simpler and more composable than file-like objects in Python

                                  1. 2

                                    Python is 3 times the age of Go. 20 yrs from now I hope we say the Go stdlib is as consistent as it is now. I also hope to be retired by then and hope terminated before then.

                                    1. 3

                                      I remember when people were saying this about Go 5 and 10 years ago. It’s been almost 15 years and Go has done very well at consistency in its stdlib and elsewhere. When python was nearly 15 it’s standard library was already a mess—Go had the benefit of hindsight, specifically with respect to how “kitchen sink” languages like C++ turned out.

                                      1. 1

                                        Some of the worst things in Go’s standard library are old RPC formats and container types, but there’s not too much of it.

                                  2. 2

                                    It’s better organized and more cohesive. For example, what’s the difference between import os and import sys? I really couldn’t tell you. You just have to memorize it.

                                    The json module has load and loads, but I’m not aware of any other packages that follow that convention for file-like vs string input. Anyway, why not just have one function take both and branch on the type? Go is more consistent about using their file-like types (io.Reader/Writer) everywhere.

                                    Time in Python is 💩. No one ever wants a time without a time zone! Go libraries all take a time.Duration instead of this one taking seconds and that one taking milliseconds. Python has a timedelta type but no one uses it.

                                    The various urllibs are all strictly worse than their Go equivalents.

                                    Python does have better itertools and collections though. Now that Go has generics, hopefully, those will get ported over too.

                                    1. 2

                                      Honestly I hate the whole datetime.datetime.now() thing. I also don’t love that Python is so inconsistent with its casing conventions (e.g., testing uses assertEqual, datetime uses timedelta, and most other things use UpperCamelCase for types and snake_case for functions and methods). Also I’ve done a lot of subprocessing in Python and I still have to consult the docs every single time for subprocess.run() and friends–the arguments are just dizzying. Also, despite being a very dynamic language, Python doesn’t have anything as convenient as Go’s json.Marshal()–you have to write to_json() methods on every class that return a JSON-like dict structure (and to be quite clear, I have grievances with Go’s JSON package). Similarly, Python’s standard HTTP libraries are more tedious than those in Go–the canonical advice is just to import requests or similar, but this is a pain for simple scripts (e.g., I now have a build step for my AWS Lambda function which pretty much erases the benefit of using Python over Go for Lambda in the first place). These are just a few examples of issues with the Python stdlib off the top of my head, but there are lots more :)

                                1. 17

                                  Some of us are still advocating for more usage of Level 1. Modern servers are unbelievably powerful and reliable.

                                  1. 3

                                    Could you elaborate on this a bit more?

                                    1. 12

                                      For example, the rise of sqlite as an alternative to more complex DBs which run on separate machines. One way to simplify a system is to use parts which require less maintenance and administration.

                                      1. 3

                                        Right up until you need any kind of high availability, then you start adding replication layers to SQLite and grow something as complex as a traditional RDBMS.

                                        1. 3

                                          There’s a huge class of apps which don’t need high availability but would benefit hugely from a simplified deploy and cheap hosting costs. I think Mastodon or WordPress are perfect examples.

                                          1. 1

                                            I agree on blog hosting (if it’s down, I doubt many people care), I’m less sure with Mastodon, at least long term. If my email is down, that’s increasingly problematic because people use it for time-sensitive communication. I don’t think Mastodon is in the same space yet, but it aspires to be.

                                  1. 18

                                    I’ve been doing some back of the napkin math on my company’s cloud transition and containers are incredibly expensive. (An order of magnitude more expensive than virtual servers!)

                                    The joke of “Kubernetes was the Greek god of spending money on cloud services” is pretty accurate.

                                    On the other hand, increasing our headcount is more expensive than containers. We actually save money this way. And we’re unlikely to grow our headcount and business enough that switching to less expensive infrastructure would be cheaper in the long run.

                                    1. 12

                                      … I’m confused, how is “adopt containers in a ‘cloud’” an alternative to “hire staff” ?

                                      1. 7

                                        Depending on scale, you need to have skills and hours for:

                                        cloud containers:

                                        • containerization
                                        • orchestration
                                        • cloud networking (high level)
                                        • cloud security
                                        • access management

                                        physical hardware in a datacenter:

                                        • hardware build/buy, deploy, monitoring, maintenance
                                        • network setup, deploy, management, monitoring (low-level)
                                        • security
                                        • access management

                                        If you think that one of these requires skills and hours you don’t currently have, and you do for the other, then you need to hire people.

                                        1. 9

                                          Ah yes, the old “it’s the cloud or break ground on your own datacenter, there’s no in between” trope.

                                          1. 20

                                            That’s uncharitable. Everything I attributed to “physical hardware in a datacenter” applies equally to renting rackspace from an existing colo provider… which is what my employer does.

                                            You can also lease servers from many datacenters, pay them for deployment, and pay them for networking.

                                            1. 11

                                              It took me a while to figure out what parent is getting at but I think it’s a matter of walking a few miles in young people’s shoes. All this is happening in 2023, not 2003. Lots of people who are now in e.g. their late twenties started their careers at a time when deploying containers to the cloud was already the norm. They didn’t migrate from all that stuff in the second list to all that stuff in the first list, they learned all that stuff in the first list as the norm and maybe learned a little about the stuff in the second part in school. And lots of people who are past their twenties haven’t done all that stuff in the second list in like ten years. Hell, I could write pf and iptables rulesets without looking at the man pages once – now I’m dead without Google and I woke up to find nftables is a thing, like, years after it was merged.

                                              It’s not a dying art (infrastructure companies need staff, too!) but it’s a set of skills that software companies haven’t really dealt with in a while.

                                              1. 2

                                                I’m actually more skilled in running servers than containers. My company is transitioning to the cloud and I’m getting the crash course on The New Way. Docker and Dockerfiles are the currently bane of my existence.

                                                But I can’t ignore that containers allow a level of automation that’s difficult to achieve with virtual or physical ones. Monitoring is built in. Monit or systemd configs aren’t needed anymore. They’ve been replaced by various AWS services.

                                                And frankly, we can push the creation of Docker images down the stack to experienced developers and keep operations headcount lower.

                                                It’s more efficient to hire a developer like me who works part time on devops than hire a developer and an devops person.

                                                1. 1

                                                  I’m 100% not an infra guy so I’m probably way off but my (possibly incorrect) expectation is that a company that’s running cloud-hosted services deployed in containers & co. at the moment would also deploy them in containers in a non-cloud infrastructure, too. I mean, regardless of whether that’s a good idea or not in technical terms (which I suspect it is but I have no idea) it’s probably the only viable one, since hardly anything can be built and ran in another environment today. IMHO you’d need people doing devops either way. Tooling may be “just” a means to an end but it’s unescapable and we’re stuck with the ones we have no matter what we run them on.

                                                  That’s probably one reason why gains like the ones the author of the article wrote about are currently accessible only to companies running large enough and diverse enough arrays of services, who probably need, if not super-specialised, at least dedicated staff to manage their cloud infrastructure. In that case, you’re ultimately shifting staff from one infrastructure team to another, so barring some initial investments (e.g. maybe you need to hire/contract a network infra expert, and do a lot of one-off work like buy and ship cabinets and the like), it’s mostly a matter of infrastructure operation costs.

                                                  Smaller shops, or at least shops with less diverse requirements and/or lighter infrastructure requirements that can be (mostly?) added to the developers’ plates aren’t quite in the same position. In their case, owning infrastructure (again) probably translates into having a full-sized, competent IT department again to keep the wheels spinning on the hardware that developers deploy their containers on. So they’d be hiring staff again and… yeah.

                                              2. 1

                                                I mean, there are other options where you rent VMs or even physical servers, but those require additional skills as well that you have to hire for. If you’re alluding to a PaaS then you won’t need additional headcount, but you may well be spending more for your resources than you would in the cloud.

                                                1. 3

                                                  I’m coming at this with quite a bit of grey in my beard, but it makes me profoundly uncomfortable to think that the folks who are responsible for all of the cloud bits that “dsr” outlines would be uncomfortable handling the physical pieces. I get that it’s a thing, but having started from the other side (low-level), the idea that people are orchestrating huge networks without having ever configured subnets on e.g. an L3 switch… that freaks me out.

                                                  1. 4

                                                    Fun, isn’t it? I don’t (usually) feel like I’ve been at this that long, but a lot of fundamentals that I’d have expected as table stakes have been entirely abstracted away or simplified so much that people starting today just aren’t going to need to know them. (Or, if they do, are going to need a big crash course…)

                                                    OTOH I spend a lot of my time realizing that there’s yet another new thing I need to learn to stay current…

                                                    1. 3

                                                      I feel attacked xD

                                                      More seriously, I love programming, but years of family and friends asking me to help with their network issue over the phone or text just completely killed my will of doing this kind of configuration.

                                                      The exception being terraform, I was pleasantly surprised by how satisfying it was to be ablee to declare what you want and be able to inspect the plan before executing it. But that’s still pretty high-level I guess…

                                                  2. 1

                                                    I think even when colocating, you still are needing some extra level of expertise. There is most definitely more people who can get by with cloud hosting stuff who would be more overwhelmed by the issues coming with managing the hardware.

                                                    I think that if you have people in a team with that skillset, though, then it’s a different calculus. But it’s hard to overstate how little you have to think about the hardware with cloud setups. I mean you gotta decide on some specs but barely. And at least in theory it lets you ignore a level of the stack somewhat.

                                                    Most companies are filled with people who are merely alright at their jobs, and so when introducing a new set of problems you’re looking at pulling in new people and signing up for a new class of potential problems.

                                                2. 2

                                                  You need slightly less people if you don’t have servers (virtual or otherwise) to monitor and maintain.

                                                  As annoying as I’m finding The Cloud, containers natively support automation in a way servers do not. Linux automation isn’t integrated, it’s bolted on after the fact.

                                                  It’s easy to mistake something you’re familiar with as being simpler than something you aren’t.

                                              1. 7

                                                I’d love a no-build-system way of using typescript =/

                                                1. 6

                                                  If the TC39 proposal for erased type annotations progresses forward, that will make it far easier to just write TypeScript source and run that directly without any required tooling in the middle.

                                                  1. 6

                                                    This is one reason I’m pretty bullish on deno. The lack of tooling is actually more important than the stuff they give you.

                                                    1. 3

                                                      the project I work on is straight tsc.

                                                      We have an index.html, main.css and a tsconfig.json such as

                                                      {
                                                          "compilerOptions": {
                                                              "target": "ES2017",
                                                              "module": "none",
                                                              "strict": true,
                                                              "strictPropertyInitialization": false,
                                                              "sourceMap": true,
                                                              "removeComments": true,
                                                              "outFile": "./main.js",
                                                              "lib": [
                                                                  "dom",
                                                                  "es2017"
                                                              ]
                                                          },
                                                          "files": [
                                                              // … <skipped 283 lines>
                                                              "main.ts"
                                                          ]
                                                      }
                                                      

                                                      in which the order in “files” is meaningful.

                                                      Building is just running tsc.

                                                      The very few external libraries are <script… tags in the index.html

                                                      1. 3

                                                        That’s still “a build step”, in my potentially very wrong definition of build step. My ideal is to just include some tags in the HTML and reload the browser. Anything that I have to install locally and run to generate an output is a build step.

                                                        I think OPs definition is the same as mine, for what is worth.

                                                        1. 2

                                                          True, and I painfully remember this every time I get distracted during the 5-to-10 seconds build time, go look at something else, come back to the code 15 minutes later and I realize I’m not even sure if I did compile it or not.

                                                          That’s unavoidable as long as the browsers, in this case, can’t run Typescript directly. I’m just happy we stuck to the bare minimum. If it was just me I’d ditch Typescript entirely.

                                                          1. 2

                                                            FYI, you can pass the –watch flag to tsc and forget about it.

                                                            1. 1

                                                              It seems like swc might be a much faster typescript compiler. It doesn’t do the type checking, but assuming you’re using an editor that does type-checking as you go, then you probably don’t care much about type checking in the compile/run phase of your iteration loop? I haven’t looked into it personally since my TS projects are relatively small.

                                                              1. 2

                                                                I worked at a place that relied on editor lints for TS type checking and I wouldn’t do that again if I could help it. Things eventually became inconsistent across the (large) codebase because if you broke something in a file you weren’t looking at you didn’t notice the breakage. Maybe for a very small project, but I would rather set up a proper compilation step at the outset than deal with issues down the road.

                                                                1. 2

                                                                  Type checking in the editor and in the command line/CI is great together, but having only one, whichever it is, is miserable.

                                                                  1. 2

                                                                    I mean, you still typecheck in CI and your editor (not just lints); you just don’t do it each time you run.

                                                                    1. 1

                                                                      That would have been better, yes

                                                          2. 1

                                                            I’m pretty happy typechecking javascript files with tsc + jsdoc.

                                                            1. 1

                                                              Did you try Deno?

                                                              1. 2

                                                                By no build I mean not running anything locally, just script tags.

                                                            1. 11

                                                              But all the old WATs like ["10", "10", "10"].map(parseInt) are still there.

                                                              Could someone explain this to me? What the holy hell happens to make it produce the crazy result [10, NaN, 2] ⁉️

                                                              I had never seen this before and just had to try typing it in to see what happened … I guess I don’t know JS as well as I thought I did.

                                                              1. 18

                                                                I think map passes the value AND index of the array element to the mapper function, so you get the result of “10” in base 0 (defaults to base 10), base 1 (error because 1 is not a valid digit in base 1), and base 2 (which is 2).

                                                                1. 14

                                                                  In general in JS, if you see [].map(funcName), it’s going to bite you in the ass, and you should change it to [].map(x=>funcName(x)) as soon as possible. And do it even faster if it involves this.

                                                                  1. 7

                                                                    I understand why, but this shouldn’t be necessary though because it’s verbose and doesn’t meet expectations coming from many languages–introducing a point and needing arguments to get around what sometimes feels like a bug. This is why you’ll see separate functions like indexedMap, mapWithIndex, mapi, and the like in other languages so you’re not overloading the function arity.

                                                                    1. 1

                                                                      Oh yeah, it’s inarguably a bug in javascript, it’s just many decades too late to fix it.

                                                                    2. 2

                                                                      Is there are Clippy-like linter for JS/TS that could warn against mistakes like this one? Deno itself has lint, but that doesn’t seem to catch this one. Nor does eslint apparently.

                                                                      1. 5

                                                                        Neither do TS/flow. And there’s a reason they don’t: https://github.com/microsoft/TypeScript/wiki/FAQ#why-are-functions-with-fewer-parameters-assignable-to-functions-that-take-more-parameters

                                                                        It’s unfortunate but there’s not much to be done here. You’d have to craft a very strict, one-off eslint rule to prevent this error in your codebase at the cost of some performance and convenience (eg prevent passing anything but an arrow function to Array.map)

                                                                        An in-depth description of the problem is here, for anyone having trouble following along: https://jakearchibald.com/2021/function-callback-risks/

                                                                        1. 2

                                                                          Linters cannot rule out cases when the argument function is actually supposed to take an element and its index. But at least they could warn about a possible gotcha.

                                                                      2. 2

                                                                        this is typically why I favour lodash/fp versions as they are strictly limited to one argument for easy composition!

                                                                      3. 10

                                                                        Love letters like this make me think I should give JS another shot. Warnings like that remind me that I don’t want to. It’s an abusive relationship.

                                                                        1. 6

                                                                          See I disagree here - it’s very much a “know the APIs you’re using”.

                                                                          It is reasonable - and can be useful - for map() to pass things like the index as argument to the mapped function.

                                                                          It is reasonable - and absolutely useful - for parseInt to take a base argument.

                                                                          What we’re seeing here is when you try to use these two together.

                                                                          Imagine a statically typed language:

                                                                          int parseInt(string, base = 10);
                                                                          
                                                                          class Array<A> {
                                                                              Array<B> map<B>(B(*f)(A)) {
                                                                                  Array<B> result = [];
                                                                                  for (int i = 0; i < length; i++) {
                                                                                      result.append(f(this[i]))
                                                                                  }
                                                                                  return result
                                                                              }
                                                                              Array<B> map<B>(B(*f)(A, int))
                                                                                  Array<B> result = [];
                                                                                  for (int i = 0; i < length; i++) {
                                                                                      result.append(f(this[i], i))
                                                                                  }
                                                                                  return result
                                                                              }
                                                                          };
                                                                          

                                                                          here if you did [“10”, “10”, “10”].map(parseInt) you would call the second map, and so would get [parseInt(“10”, 0), parseInt(“10”, 1), parseInt(“10”, 2)]

                                                                          1. 11

                                                                            Of course, if you know you know, but for non-JS programmers this is very surprising because:

                                                                            • map passes multiple arguments
                                                                            • it’s not an error to call a function with the wrong number of arguments
                                                                            1. 8

                                                                              I get that it’s not the common map api in other languages, but coming in with “this is the API in some other unrelated language, therefore this is WAT” is simply not reasonable.

                                                                              For the latter: not needing exact parameter count is a fairly fundamental part of the language. Saying it’s surprising that map(parseInt) invokes the same behavior as anywhere else in the language is “surprising” is again not reasonable.

                                                                              JS has quirks, but labeling basic language semantics as WAT is tiresome.

                                                                              1. 13

                                                                                I get that it’s not the common map api in other languages, but coming in with “this is the API in some other unrelated language, therefore this is WAT” is simply not reasonable.

                                                                                It is still a reasonable criticism because map exists in a broader social context with widely known conventions. The criticism is that JS doesn’t obey what people would expect. And the resulting confusion is the empirical proof of the problem.

                                                                                In some cases, you might say, “Well ok, we know people will expect such and such, but such and such is actually a poor design because of X, so we’re going to fix it even if it’s going to cause some confusion”. That is, you can break with convention if you have a good reason. In the case of JS, this defense doesn’t hold up imo.

                                                                                Ramda’s solution to the problem, which is to add indexing only on explicit request, results in a cleaner, more composable API. Generously, you could argue that “just add i to every function” has practical convenience, despite wtfs like map(parseInt). But that is a debatable counterargument to the criticism. The criticism is at minimum reasonable, even if you don’t think it’s correct.

                                                                              2. 3

                                                                                Also, the fact that map() takes a function that expects 3 args (IIRC) but is commonly passed a function with one argument and things don’t blow up (neither at runtime nor at compile time in TypeScript) is pretty strange and probably the cause of a lot of these kinds of bugs. In general, JS/TS’s approach to “undefined” is difficult for me to intuit about and I’ve been using JS on and off for about 15 years.

                                                                                1. 1

                                                                                  map passes multiple arguments

                                                                                  It’s vaguely reasonable to not know this, but also the signature of map’s functor is on the first line or two of any documentation.

                                                                                  it’s not an error to call a function with the wrong number of arguments

                                                                                  Because variadic arguments (and the arguments array) are first class language features. This is where we get into “this is a core JS language feature, you really need to know it exists”

                                                                                  1. 1

                                                                                    Variadic functions are fine, the confusing thing is that all functions can receive 0-N args instead of only those that opt in. Yes this has been in JS from the start, but it’s unusual in casual JS use and in other popular languages.

                                                                                2. 4

                                                                                  It is reasonable - and can be useful - for map() to pass things like the index as argument to the mapped function.

                                                                                  It is not. You shouldn’t concern yourself with indices at all if you’re using map et al, and if you need that index, just zip the collection with its indices before mapping.

                                                                                  1. 1

                                                                                    Or you can remember that other languages have other idioms, and that the index can be useful in principle. There’s also an additional parameter which is the array being enumerated. Together these can be useful.

                                                                                    You my have a functional language puritanical belief about what the API should be, but that’s a subjective opinion, hence it is reasonable that the functor receive additional information about the iteration, especially in a language like JS where variadic functions are first class.

                                                                                    1. 2

                                                                                      I have the utmost respect for different languages having different idioms (I’ve used quite a lot of OSes and languages throughout the years and am myself bothered when people raised on a blend of Windows, Linux and C-style languages complain that things are just different to what they are used to.) but in this case, it’s just a fractal of bad design.

                                                                                      It’s not just because the map API is misleading, it’s because the extra arguments are thoroughly superfluous and tries to fit imperative idioms into a functional one.

                                                                                      But first and foremost, it’s a bad design because it never took into account how it would match the default parameter convention of JS.

                                                                                      One could also remark that parseInt is a strange global function with a strange name in an object-oriented language with some FP features.

                                                                                  2. 1

                                                                                    You are right. These are totally reasonable APIs. parseInt in particular is totally fine. For map, it’s a little quirk that’s different than maps in other languages, but it’s forgivable because it is useful.

                                                                                    It really bothers me because of how Javascript functions are called. As roryokane says, you can get around the API by defining an extra function that only takes one argument:

                                                                                    [“10”, “10”, “10”].map(n => parseInt(n))

                                                                                    And that works because Javascript functions will ignore extra arguments instead of throwing an error. Ultimately, it’s that looseness that bothers me.

                                                                                    1. 5

                                                                                      You’re complaining about dynamic typing then, not JS.

                                                                                      Plenty of languages have varargs, plenty of languages have default parameters. The reason map(parseInt) works is because there is no type checking beyond “can be called”.

                                                                                      If you do want “arguments must match exactly”, then all your common calls to map would need function wrappers, because they’d trigger errors from not handling all three arguments.

                                                                                      1. 11

                                                                                        You’re complaining about dynamic typing then, not JS.

                                                                                        No, I’m not. Python is dynamically typed, but it will throw an error if you provide an extra argument. Python also has varargs, but it’s opt in which I find reasonable. I want dynamic checks at run time, which this behavior doesn’t give me. (Or checks at compile time. Mostly I want to know if I screwed up.)

                                                                                        1. 3

                                                                                          Right, but parseInt taking an optional base argument is reasonable, and that makes the arity match; python wouldn’t raise an error there.

                                                                                          1. 4

                                                                                            Again, parseInt is fine. Default arguments are fine. I don’t like how you can pass extra arguments to a function and they get ignored. I want them to throw an error.

                                                                                            1. 3

                                                                                              parseInt takes 2 args, map provides 3, so it would error in python.

                                                                                            2. 1

                                                                                              There are a bunch of problems. First variadic functions are a first class and relatively fundamental concept in JS, so you’ve got a different language style. That’s just a basic language choice - you can disagree with it, but given that fact you can’t then say it’s unreasonable when variadic nature of calls comes into play.

                                                                                              Second, I could make a JS style map() function, and pass python’s int() function to it, and it would be called just as JS’s is, because the additional parameter is optional, and hence would be fine. The only difference is that python bounds checks the base and throws an exception.

                                                                                          2. 1

                                                                                            The issue here is that variadic functions are core to JS from day 1. We’ve generally decided that that is “bad” nowadays, but given the functions have always been variadic in JS, large swathes of APIs are designed around it.

                                                                                            1. 1

                                                                                              Yes, that’s why I try to avoid JavaScript. There are lots of decisions that were made that seemed reasonable in the past, but turned out to have negative consequences that persist. I’ve been burned by some of them and have a negative opinion of the language.

                                                                                      2. 6

                                                                                        map passes the index as a second argument; parseInt accepts a second argument.

                                                                                        1. 5

                                                                                          This is just not a WAT. What it is, is a classic example of people pretending reasonable behaviour and acting as though it is WAT. If you pass a function that takes multiple parameters (parseInt is in modern syntax: function parseInt(string, base=10)), and passing it to another function that will call it with multiple parameters, and then acting like the result is a weird behavior in the language, rather than a normal outcome that would occur in any language.

                                                                                          Start with:

                                                                                          function parseInt(string, base=10) -> int; // which is a fairly standard idiom across many languages for defining this function
                                                                                          

                                                                                          and then say “map passes the value and the index to the mapping function”, and ask what the outcome would be.

                                                                                          What we’re seeing here is a person saying “I am blindly assuming the same map API as other languages”, and then acting like the API not being identical is somehow a language WAT. It’s right up with the WATs claiming “’{}’ is undefined and ‘+{}’ is NaN”, or “typeof NaN == ‘number’”, etc

                                                                                          1. 11

                                                                                            Then again, your reply is a classic example of a language afficiando taking a clear WAT and explaining it as reasonable behaviour – even though it quite clearly is a bit of a problem for users of the standard map function coming from practically every other language.

                                                                                            Granted, like almost every other WAT, it’s a rather minor one for anyone who’s been writing JS/TS for more than a week. Still, I’d very much like a linter to automatically catch these for me. Even experienced people make dumb mistakes sometimes, and it’s just a complete waste of time and energy. Rust, a much stronger typed language (whose type checker already wouldn’t allow this), contains a linter that does catch problems similar to this one.

                                                                                            1. 1

                                                                                              Then again, your reply is a classic example of a language afficiando taking a clear WAT and explaining it as reasonable behaviour – even though it quite clearly is a bit of a problem for users of the standard map function coming from practically every other language.

                                                                                              I’m unsure what to say here. map in JS passes the index of the iteration, and the array being iterated. That is what it does. If you pass any function to map it will get those parameters. If the function you pass has default parameters, those will be filled out.

                                                                                              Similarly, parseInt takes an optional base that defaults to 10.

                                                                                              I get that people are quite reasonably tempted to do map(parseInt), but I cannot work out what JS is meant to do here different, unless people are saying map should explicitly check for parseInt being passed in?

                                                                                              1. 1

                                                                                                I suppose the simplest way to fix this would for map’s type to be like it is in Haskell, i.e.

                                                                                                (a -> b) -> [a] -> [b]

                                                                                                So the function map takes as argument takes just one argument, and map does not pass an index of the iteration.

                                                                                                I don’t doubt that there are valid reasons why this would be cumbersome in Javascript/Typescript, but I’m not familiar with them. Index of the iteration is not typically needed in functional style, so it’s kind of redundant and as shown here, potentially harmful.

                                                                                            2. 4

                                                                                              Start with:

                                                                                              function parseInt(string, base=10) -> int;
                                                                                              // which is a fairly standard idiom across many languages for defining this function
                                                                                              

                                                                                              and then say “map passes the value and the index to the mapping function”, and ask what the outcome would be.

                                                                                              Alas, that’s backwards. Things are surprising not when they are inexplicable in hindsight, but when they are not expected in advance. You have to start from what the user sees, then follow the network of common associations and heuristics to identify likely conclusions.

                                                                                              If the common associations lead to the correct conclusion, the interface is probably fine. If common associations lead to the wrong conclusion, there will be many mistakes — even by users who also know the correct rules.

                                                                                              So in our case, the user starts by seeing ths:

                                                                                              [10, 10, 10].map(parseInt)
                                                                                              

                                                                                              Now the user has to remember relevant facts about map and parseInt and come to the correct conclusion. Here’s a list of common associations that lead to the wrong answer.

                                                                                              • I can use parseInt(mystring) to mean parseInt(mystring, 10)
                                                                                              • I can use parseInt(mystring) without needing to remember parseInt(mystring, base) exists
                                                                                              • f is simply another way to write x => f(x)
                                                                                              • If the inputs to a .map() are all the same, the outputs are all the same
                                                                                              • [10, 10, 10].map(f) is normal code that does not require special attention.
                                                                                              1. 1

                                                                                                Alas, that’s backwards. Things are surprising not when they are inexplicable in hindsight, but when they are not expected in advance. You have to start from what the user sees, then follow the network of common associations and heuristics to identify likely conclusions.

                                                                                                parseInt takes a base argument. map provides the base. the semantics of both are reasonable. The same thing would happen in any other language.

                                                                                                Now the user has to remember relevant facts about map and parseInt and come to the correct conclusion.

                                                                                                Yes. the user should know the APIs that they’re using. The problem here is that many modern languages have a version of map that has a different API, and end users blindly assume that is the case.

                                                                                                1. 2

                                                                                                  Array.map() provides a third argument. Other languages would blow up when parseInt() was called with two arguments. You seem to argue elsewhere that JavaScript’s parseInt() accepts more than 2 arguments (because all functions in JavaScript accept ~arbitrarily large numbers of parameters), but that’s precisely what’s bizarre (and as many contend, error prone) about JavaScript–that we can call a function whose signature is function(a, b) with 3 arguments and it doesn’t blow up.

                                                                                                  The issue isn’t that people don’t understand map()‘s signature, it’s that JavaScript is unusually permissive about function calls which makes it easy (even for people who understand that JavaScript is unusually permissive about function calls) to make mistakes where they wouldn’t in other languages.

                                                                                                  1. 1

                                                                                                    No, you want the over application to work, because that’s how JS works, hence how APIs are designed. The alternative is that you would have to do (for example)

                                                                                                    someArray.map((value,a,b)=>value*2)
                                                                                                    

                                                                                                    I get that people don’t like JS functions being variadic, but they are, and that means APIs are designed around that variadic nature.

                                                                                                    1. 1

                                                                                                      I mean, the obvious alternative is to make map()’s functor accept one argument, but that’s beside the point. We were debating about whether Javascript was uniquely confusing and the answer is “yes, Javascript functions are (uniquely) variadic by default, and this seems to result in many bugs and WATs”. To add to the confusion, it also has a syntax for expressing that the programmer intends for the function to be variadic: function(…args).

                                                                                              2. 2

                                                                                                If you pass a function that takes multiple parameters (parseInt is in modern syntax: function parseInt(string, base=10)), and passing it to another function that will call it with multiple parameters, and then acting like the result is a weird behavior in the language, rather than a normal outcome that would occur in any language.

                                                                                                It seems like the Go compiler disagrees with you:

                                                                                                func CallWithThreeArgs(f func(int, int, int)) {
                                                                                                	f(0, 0, 0)
                                                                                                }
                                                                                                
                                                                                                func TakesTwoArgs(int, int) {}
                                                                                                
                                                                                                func main() {
                                                                                                        // cannot use TakesTwoArgs (value of type func(int, int)) as func(int, int, int) value in argument to CallWithThreeArgs
                                                                                                	CallWithThreeArgs(TakesTwoArgs)
                                                                                                }
                                                                                                

                                                                                                https://go.dev/play/p/BY7rRRqRMwt

                                                                                                As does the Rust compiler:

                                                                                                fn call_with_three_args(f: fn(i64, i64, i64)) {}
                                                                                                
                                                                                                fn takes_two_args(a: i64, b: i64) {}
                                                                                                
                                                                                                fn main() {
                                                                                                    //  note: expected fn pointer `fn(i64, i64, i64)`
                                                                                                    //              found fn item `fn(i64, i64) {takes_two_args}`
                                                                                                    call_with_three_args(takes_two_args);
                                                                                                }
                                                                                                

                                                                                                https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=93d4aead97995330669c6e48cf8c657a

                                                                                                Here’s Python:

                                                                                                def call_with_three_args(f):
                                                                                                  f(0, 0, 0)
                                                                                                  
                                                                                                def takes_two_args(a, b):
                                                                                                  pass
                                                                                                
                                                                                                // TypeError: takes_two_args() takes exactly 2 arguments (3 given) on line 2 in main.py
                                                                                                call_with_three_args(takes_two_args)
                                                                                                

                                                                                                https://trinket.io/python/63d966b40e

                                                                                                1. 1

                                                                                                  You’re right, calling a function with an incorrect number of parameters does fail. So let’s try what I said: calling a function assuming one API, when it has another. It’s a bit harder in statically typed languages because (A)->X and (A,B=default value)->X are actually different types. In C++

                                                                                                  The problem is you’ve misunderstood the claim. The claim isn’t “I can pass a function that takes N and expect it to be called with M arguments” it is “I can pass a function that takes a variable number of arguments, and that will work”. Referencing rust isn’t relevant as it has no concept of variadic functions or pseudo variadic with default parameters. C++ does, and I can make that happen with [](std::string, int = 10){...} which could be passed to a map the passes an index or one that does not, and both will work.

                                                                                                  Your example of python however is simply wrong. If python’s map passed the index:

                                                                                                  def map(array, fn):
                                                                                                    result = []
                                                                                                    for i in range(0, len(array)):
                                                                                                      result.append(fn(array[i], i))
                                                                                                    return result
                                                                                                  

                                                                                                  you could call that map function, passing int() as the functor, and it would be called. The only reason it would fail is int() bounds checks the base. The behaviour and language semantics are the same as in JS.

                                                                                                  Now you can argue about details of the map() API, but the reality is the JS is a language that allows variadic calling, so it is a reasonable choice to provide those additional parameters, You can argue much more reasonably that parseInt should be bounds checking the base and throwing an exception, but again the language semantics and behaviour are not weird.

                                                                                                  1. 1

                                                                                                    The problem is you’ve misunderstood the claim.

                                                                                                    Your claim was that any language would behave as JavaScript does when passing multiple parameters to a multiple parameter function.

                                                                                                    I can pass a function that takes a variable number of arguments, and that will work

                                                                                                    Ok, so you’re arguing that unlike other languages, all functions in JavaScript take a variable number of arguments which is just rephrasing the criticism that JavaScript is unusual (thus more programmer errors) and contradicting your claim that it’s behaving as any other language would do (e.g., “but again the language semantics and behaviour are not weird”).

                                                                                                    Your example of python however is simply wrong. If python’s map passed the index:

                                                                                                    Respectfully, you’re mistaken. Array.map() passes a third parameter to fn. If we update your Python example accordingly, it blows up as previously discussed:

                                                                                                    def map(array, fn):
                                                                                                      result = []
                                                                                                      for i in range(0, len(array)):
                                                                                                        result.append(fn(array[i], i, array)) // TypeError: int() takes at most 2 arguments (3 given)
                                                                                                      return result
                                                                                                    
                                                                                                2. 1

                                                                                                  I’ve never heard the acronym WAT before, but I would call JS’s “map” function a footgun for sure. It’s named after a classic/ubiquitous functional, uh, function dating back to early LISP, and has the same purpose, but passes different parameters. Yow.

                                                                                                  (But I have no problem with parseInt, or JS’s parameter passing in this instance. It’s all on map.)

                                                                                                3. 4

                                                                                                  Here’s a detailed answer adapted from a chat message I once sent to a coworker.

                                                                                                  Starting from this JavaScript console transcript, in which I’ve split out a strs variable for clarity:

                                                                                                  > const strs = ['10', '10', '10']
                                                                                                  > strs.map(parseInt) // gives the wrong result?
                                                                                                  [10, NaN, 2]
                                                                                                  

                                                                                                  The correct way to write this is to wrap parseInt in a single-argument anonymous function:

                                                                                                  > strs.map(x => parseInt(x))
                                                                                                  [10, 10, 10]
                                                                                                  

                                                                                                  strs.map(parseInt) gives unexpected results because of three factors:

                                                                                                  1. Array.prototype.map calls the passed function with multiple arguments:

                                                                                                    > strs.map((a, b, c) => [a, b, c])
                                                                                                    [
                                                                                                        ['10', 0, strs],
                                                                                                        ['10', 1, strs],
                                                                                                        ['10', 2, strs],
                                                                                                    ]
                                                                                                    

                                                                                                    The arguments are element, index, array.

                                                                                                  2. The parseInt function takes up to two arguments – string, radix:

                                                                                                    > parseInt('10') // parse with inferred radix of 10. That is, '10' in base 10 is…
                                                                                                    10
                                                                                                    > parseInt('10', 10) // parse with explicit radix of 10
                                                                                                    10
                                                                                                    
                                                                                                  3. When calling a function in JavaScript, any extra arguments are ignored.

                                                                                                    > const plusOne = (n) => n + 1
                                                                                                    > plusOne(1)
                                                                                                    2
                                                                                                    > plusOne(1, null, 'hello', {a: 123})
                                                                                                    2
                                                                                                    

                                                                                                  Thus, the incorrect version was calling parseInt like this:

                                                                                                  > parseInt('10', 0, strs) // parse with explicitly assumed radix due to `0`
                                                                                                  10
                                                                                                  > parseInt('10', 1, strs) // parse with invalid radix of 1
                                                                                                  NaN
                                                                                                  > parseInt('10', 1, strs) // parse with radix 2. That is, '10' in base 2 is…
                                                                                                  2
                                                                                                  
                                                                                                  1. 3

                                                                                                    Yeah, uh, much as I love JavaScript, parseInt() is probably the worst place to look for elegance in the design of its equivalent of a standard library. It doesn’t even necessarily default to a radix of 10.

                                                                                                  1. 80

                                                                                                    At 100 LOC, static types are mostly in the way

                                                                                                    At 10 000 LOC, static types help you along the way

                                                                                                    At 1 000 000 LOC, static types are the only sane way

                                                                                                    1. 12

                                                                                                      I think I agree with the idea. The numbers could be debated. Mine are much, much lower.

                                                                                                      Anecdotal evidence: my first attempt at an Early parser was in Lua. The recogniser went smoothly enough, but the parser was an utter failure. I couldn’t do it. At all. I kept getting stupid errors like “you’re feeding a function to an addition”, or “you’re trying to call a number”… And I had no idea where those errors came from. The size of my little tree search script? 50 lines. I had to rewrite it in Ocaml to even have a chance.

                                                                                                      As I said, my own numbers are much lower.

                                                                                                      1. 1

                                                                                                        I believe that Ocaml shines for writting parser/compiler (and especially parser/compiler of Ocaml). maybe we can say the right tool for the right job

                                                                                                        1. 1

                                                                                                          Indeed it wasn’t just static typing. But it remains at the top of my least. My subjective evaluation of what helped me, from the most important to least important, would probably look like the following:

                                                                                                          1. Static typing.
                                                                                                          2. Garbage collection (also present in Lua).
                                                                                                          3. Sum types (especially combined with GC).
                                                                                                          4. Pattern matching.
                                                                                                          5. Parametric polymorphism (a.k.a. generics).
                                                                                                          6. Local type inference (convenient, but by no means mandatory).
                                                                                                          7. Global type inference (it did help, but I’d say marginally so)

                                                                                                          I could have done it with just items 1 to 3. The rest just let me get there faster. But yeah, right too for the job: if you’re doing tree traversal OCaml is an obvious candidate.

                                                                                                          1. 1

                                                                                                            Yeah, sum types and exhaustive pattern matching are a real boon for writing parsers. The latter implies type checking.

                                                                                                        2. 19

                                                                                                          Couldn’t disagree more! At <100 LOC, I’m almost always begging for types because they can add much needed context for future developers having to touch my scripts. Understanding what values are present in my github.event object currently requires googling GitHub’s REST documentation, where as if the types were laid out for these objects it would be a lot easier to develop with. Actually typing this out has inspired me to look up typings for octokit, so I may port that 88 LOC JS to some TS.

                                                                                                          1. 6

                                                                                                            imo:

                                                                                                            At 100 LOC, static types are the only sane way

                                                                                                            At 10 000 LOC, static types are the only sane way

                                                                                                            At 1 000 000 LOC, static types are the only sane way

                                                                                                            Last year, I wrote a 125 line JavaScript program to allow users to manually select between light or dark color schemes on the website. The first pass was in plain JavaScript, and it was a struggle. When I introduced types with TypeScript, it revealed the distinction between the following concepts:

                                                                                                            // ColorScheme represents a concrete color scheme value that can be rendered.
                                                                                                            type ColorScheme = "light" | "dark"
                                                                                                            
                                                                                                            // ColorSchemePreference represents a user's choice of color scheme.
                                                                                                            type ColorSchemePreference = ColorScheme | "no-preference"
                                                                                                            

                                                                                                            Note that "no-preference" cannot be rendered. But it is a valid color scheme choice, for example, if the user hasn’t chosen a value yet, in which case the program should use a default color scheme value, such as "light".

                                                                                                            If I continued without types, the program would likely muddle through its logic, sans this key distinction, and would have depended on crude assertions or comments, such as:

                                                                                                            // At this point the color scheme c is guaranteed to be a concrete (i.e.
                                                                                                            // renderable) value, because we default to "light" when the user has no
                                                                                                            // preference.
                                                                                                            assert(c === "light" || c === "dark")
                                                                                                            renderColorScheme(c)
                                                                                                            

                                                                                                            or poorly used a null value to represent lack of preference:

                                                                                                            if (c === null) {
                                                                                                                c = "light" // default to "light" when there is no preference
                                                                                                            }
                                                                                                            renderColorScheme(c)
                                                                                                            
                                                                                                            1. 4

                                                                                                              This is the opinion I’ve come around to, as someone who reaches for Python first for scripts but who has also worked on a large production Python application. Python is great for smaller programs written by individuals. When the codebase gets larger, or when the developer becomes a team of developers, is when it starts being impractical for the types not to be (1) checked automatically by the computer and (2) spelled out in the source code for anyone reading.

                                                                                                              1. 4

                                                                                                                After implementing strict mypy compliance in a few repos, I’d probably use something like 5 LOC, 10 LOC and 100 LOC as the limits. By the time you reach 10,000 LOC the chore of introducing types (especially in highly abstract code, like an ORM or dispatcher) becomes huge. I’ve got an ~1,800 LOC Python program (old, from back in the 2.5 days or so) which is much more of a chore to work on than it could be.

                                                                                                                1. 3

                                                                                                                  You said it better in just three lines. I am gonna steal your comment!

                                                                                                                  1. 2

                                                                                                                    I think it’s also a question of when you will experience breakage. Will your code fail during compile time because you missed something that strong typing catches, or do you experience that breakage during runtime? Because the first thing will hopefully find all these spots simply because your compiler will “test” it for you during compilation, and the latter one requires you to actively run (coverage) all possible paths where something could be broken by your type changes.

                                                                                                                    Which to me essentially feels like nullpointer (un)safety and view-lifecycle state management in android: You change one thing, you have static types, but whether you actually didn’t get the lifecycle wrong, will only show up if you actually navigate to that part of your application (and push some buttons or rotate your android app). Same goes for possible nullpointer exceptions.

                                                                                                                    Of course you could test this out via Unit-Tests and coverage, but you will always miss a spot, and static typing will at least find this stuff without writing tests for function signature expectations. (Let’s not talk about runtime code loading, type erasure and other things that essentially break static types.)

                                                                                                                    1. 1

                                                                                                                      I may need to steal your comment. Thanks

                                                                                                                      1. 1

                                                                                                                        Honestly I find that even the 100 LOC static types are helpful, even if only to provide better editor support for the APIs I’m using and to make up for poor documentation (e.g., even the Python standard library documentation lists things like “file-like object” with no specifics about the APIs that are actually consumed). Plus even at the 100 LOC level, I’m always forgetting little things like awaiting async functions.

                                                                                                                        Also it’s worth noting that Python’s static types are more grating than necessary (both from a syntax perspective but also loading type stubs, etc). TypeScript is a lot more pleasant to work in (I say this as a Python dev of 15 years and very occasional JS/TS dev).

                                                                                                                      1. 3

                                                                                                                        This seems interesting. At first glance, I thought it was a more ergonomic syntax for Go (something like CoffeeScript for JavaScript back in the day); however, it seems like it’s a configuration language for Go. Which is neat, but there are already quite a few configuration languages with Go support (e.g., Starlark). The big thing that most of these fail at, however, is static types–it seems like it’s particularly easy to make type errors in configuration languages, and the usual dynamic typing guidance “just catch type errors with tests!” seems particularly unhelpful here (I really don’t want to have to write tests for my configuration if I can help it). Since I’ve dabbled with TypeScript recently for some web frontend stuff, I’ve come to the conclusion that it’s probably the best bet for an embedded scripting language in the general case (type system is solid, syntax is familiar, lots of existing high quality tooling, etc), provided of course that we can get a decent embeddable runtime for host languages.

                                                                                                                        That said, does anyone know how we can make tsc aware of host functions? E.g., if I bind a foo() func to the TS/JS runtime and invoke it in my program, how do I make tsc not complain that foo() isn’t defined/imported in my TS source code?

                                                                                                                        1. 7

                                                                                                                          expr is not really a configuration language. It is used to write expressions. It is useful if you want to integrate a rule system in an app (filtering a a subset of data, giving permissions for a resource). It is easy to learn because its scope is limited and it is fast because it compiles to bytecode and has an optimizing compiler. The author is also quite responsive. Thanks Anton!

                                                                                                                          1. 1

                                                                                                                            🤗

                                                                                                                        1. 18

                                                                                                                          I signed the offer letter for my next job a few hours ago so what I’m not doing this weekend is being stressed about employment :D

                                                                                                                          Aside from that I’ll probably just do some maintenance on my personal Minecraft server and document some of it in a blog post for future me.

                                                                                                                          1. 4

                                                                                                                            Congrats on the new job!

                                                                                                                          1. 22

                                                                                                                            I’m all for experimenting with software, and I know that sometimes a simpler tool is a better solution for simpler problems.

                                                                                                                            But this … this is PHP with go. More specifically, it’s 90s, early 2000s PHP, the worst kind of PHP. I can’t think of a single good reason to ever use this for anything, ever.

                                                                                                                            Again, experiments are valid, and sometimes people do stuff just because, and it’s all fine, and I don’t mean any moral or professional judgement of the author.

                                                                                                                            But damn this looks horrible.

                                                                                                                            1. 9

                                                                                                                              Sorry it’s not to your liking!

                                                                                                                              I don’t disagree that this is like PHP in some ways. The ability to add a file to the filesystem and automatically get a URL route in mod_php was a pretty nice experience, especially for quickly developing apps. But it also turns out to be helpful for long-term maintenance of a site. One of the challenges of using Go on the frontend is each project does its own project layout and organization.

                                                                                                                              As a former PHP developer who then switched to Rails briefly and then to Django for many years (and then to Go), I’m interested to hear what you don’t like about it. Maybe Pushup can avoid those fates. ;^)

                                                                                                                              1. 7

                                                                                                                                The mix of code and HTML, without a separation of templates and application logic, just gives me vietnam war flashbacks of horrible PHP code I’ve seen in the wild. And as much as this is not necessarily what people will do, if it’s allowed, someone will abuse it.

                                                                                                                                There’s also no concept or affordance for layers. Maybe it’s a personal bias, but I don’t care how small your project is, don’t query your database straight from the view/template. Even your exemple code is doing this, so, seems endorsed by the tool.

                                                                                                                                I also don’t love the syntax for code blocks, but that’s a purely aesthetic comment, I have no good reason for it.

                                                                                                                                All that aside, as I said, you do you, and as long as I am never asked to maintain it on production, I won’t harbor any hate towards your project =P

                                                                                                                                1. 4

                                                                                                                                  Had similar flashbacks when looking at the example in the repo. We used to call the files that contained a mix of HTML, CSS, JS, and PHP the “Da Vinci Code”.

                                                                                                                                  Totally agree that it’s a cool experiment. Also agree that maintaining it in production isn’t on the list of things I’d sign up for.

                                                                                                                                  1. 1

                                                                                                                                    The mix of code and HTML, without a separation of templates and application logic, just gives me vietnam war flashbacks of horrible PHP code I’ve seen in the wild. And as much as this is not necessarily what people will do, if it’s allowed, someone will abuse it.

                                                                                                                                    Isn’t that the default in most frameworks though? As much as better things exist, Rails still defaults to ERB for example

                                                                                                                                    1. 3

                                                                                                                                      I don’t know rails in detail, but for things like flask or Django, you’d have to go significantly out of your way to do the kind of mess PHP makes basically the path of least resistance.

                                                                                                                                      Take querying the database on templates. I don’t think it’s even possible to do so on flask, because templates are a separated language, and anything you pass to it must be serializable, which DB connections aren’t.

                                                                                                                                      You can have super messy, over complicated templates, sure. I certainly have done that and felt the pain, but the architecture of the framework either prevents or heavily steers you out of that.

                                                                                                                                      1. 1

                                                                                                                                        Take querying the database on templates. I don’t think it’s even possible to do so on flask, because templates are a separated language, and anything you pass to it must be serializable, which DB connections aren’t.

                                                                                                                                        You can always use app.jinja_env.globals.update to add your database’s API :)

                                                                                                                                        1. 1

                                                                                                                                          Sure, evil has no boundaries, the goal is just to make it more difficult =P

                                                                                                                                      2. 2

                                                                                                                                        Rails uses ERB for templates and Ruby for application logic.

                                                                                                                                      3. 1

                                                                                                                                        FWIW, people can and do abuse the separation of application logic from HTML, namely with insanely bloated HTML/JS monstrosities. A lot of web apps written in PHP feel a lot faster and less hostile, partly because PHP encourages you to keep the HTML somewhat manageable.

                                                                                                                                      4. 4

                                                                                                                                        I cut my teeth on PHP back in the mod_php era. In the early days of a project, this sort of file-based routing and “pushing everything into templates” was a nice experience, but as projects grew they became unmaintainable. Too much stuff lived scattered around templates, and presentation was mixed with other concerns. IMHO there’s a reason the PHP folks moved away from this sort of structure.

                                                                                                                                        That said, if this is working for you, I’m glad you’re building it. I think a diverse ecosystem is a good thing, but I suspect your page-based-routing design decision is going to seriously limit your project’s adoption.

                                                                                                                                        1. 4

                                                                                                                                          Just to add another point why 90s/2000s PHP was terrible is security-wise. By having the entire app’s filesystem serve up “scripts” you make it hard to protect against malicious upload attempts. Most larger web sites will end up with some way to host user-uploaded files, which requires at least a part of the file system to be writable to the application.

                                                                                                                                          In PHP it was often the case that the web server ran under the user who was able to upload to the site, which meant the entire file tree was writable (in principle). Then it becomes very easy for a malicious user to upload a .php file straight into the file tree, then execute it. And if there was a designated uploads directory, they’d upload a file via path injection a la ../../foo.php to place it outside the intended upload directory. Or if that wasn’t possible, they’d upload a .txt file or whatever and tricked running scripts into include()ing the file through path injection. Or a .htaccess file to make Apache execute the PHP scripts with another file extension. And so on and so forth.

                                                                                                                                          There are so many reasons that nobody but PHP used this approach of scattered files in the file system. Even CGI wasn’t this bad - you’d usually have a restricted read-only directory with cgi-bin files that was entirely separate from your web root.

                                                                                                                                          1. 5

                                                                                                                                            This does not apply here as the filesystem is compiled and served as an (immutable) app.

                                                                                                                                            1. 1

                                                                                                                                              Ah, indeed. I missed that part, thanks for pointing it out!

                                                                                                                                          2. 3

                                                                                                                                            The ability to add a file to the filesystem and automatically get a URL route in mod_php was a pretty nice experience, especially for quickly developing apps.

                                                                                                                                            That’s not PHP specific, all CGI is like that

                                                                                                                                            1. 2

                                                                                                                                              That’s not PHP specific, all CGI is like that

                                                                                                                                              cgi uses files as entry points, but you can also go to paths beyond the initial cgi path and route it internally to the script. See PATH_INFO. PHP can kinda do that too but it’d more often want mod_rewrite nonsense whereas with cgi it just works as part of the interface design.

                                                                                                                                          3. 4

                                                                                                                                            But this … this is PHP with go. More specifically, it’s 90s, early 2000s PHP, the worst kind of PHP.

                                                                                                                                            To my mind that was the worst PHP for most apps only because at the time PHP didn’t offer a path toward a more sustainable organizing model as an application grew (also security issues). At the same time, I think it was the best PHP to start a project with. I see the power of Pushup as being able to start projects simply and quickly while still being able to evolve them into a maintainable app.

                                                                                                                                            The distribution of application lifetimes seems something vaguely like a power law graph with a gap and bump up as the tail grows. Most projects live a few minutes or hours. A tiny fraction of those live for days. A tiny fraction of those live for weeks. The proportion that live for a decade or more is minuscule but at the same time it seems like a project that lives for more than a year or two will also live for a decade. We can predict the fate a huge portion of the left side of the graph because many projects are intended to only live a short time. However we’re very bad at predicting the right side of that graph. It’s a strangely common story to hear of a business running critical processes on an application built by a hobbyist when the business was just started. I see the value of Pushup in being able to start projects more quickly while still being able to evolve them as they continue to live on.

                                                                                                                                            1. 2

                                                                                                                                              I see the power of Pushup as being able to start projects simply and quickly while still being able to evolve them into a maintainable app.

                                                                                                                                              Is it there, though? Like, more than in PHP? If it grows badly, you’ll still have to refactor the shit out of all the pages into a coherent architecture. All the same opportunity for it to grow badly is there, same as with PHP.

                                                                                                                                              On the other hand, I’m kinda OCDish, so even with the smallest apps I go hard on proper architecture. Sometimes it’s an asset, but often it’s an obstacle, so maybe it does boils down to personal preference.

                                                                                                                                              1. 4

                                                                                                                                                Is it there, though? Like, more than in PHP?

                                                                                                                                                Probably not because PHP has grown a lot since the early 2000s. The gains seem to have been made by accepting frameworks of a comparable minimum weight and complexity as other languages. IMO Pushup keeps the initial bar much lower while not sacrificing anything on the upper end.

                                                                                                                                                All the same opportunity for it to grow badly is there, same as with PHP.

                                                                                                                                                I think it does provide the same opportunity for it to grow badly but I also think it provides more of an opportunity for it to grow well. Pushup provides an ability to pull in Go libraries and to write your own lower-level helper functions in Go when performance requires it in a way that is much more gradual than jumping to writing an extension in C. It also delivers a Go module that could be adopted wholesale into another application in a way that requires less of a deployment hassle than PHP where you likely have to reconfigure a reverse proxy in front of the app to overlay one app’s routing atop another app’s to give the appearance of a single application. Granted these things aren’t in the quickstart sales pitch and aren’t very clearly documented. More like implied, e.g.

                                                                                                                                                Pushup apps compile to pure Go, built on the standard net/http package. Fast static binary executables for easy deployment. Easy to integrate into larger Go apps

                                                                                                                                                So:

                                                                                                                                                > pushup new godemo
                                                                                                                                                > cd godemo
                                                                                                                                                > pushup build
                                                                                                                                                > grep 'func.*Respond' build/index.up.go 
                                                                                                                                                func (up *IndexPage) Respond(w http.ResponseWriter, req *http.Request) error {
                                                                                                                                                

                                                                                                                                                That function signature would be a familiar hook for most users of other Go frameworks.

                                                                                                                                                1. 2

                                                                                                                                                  but I also think it provides more of an opportunity for it to grow well.

                                                                                                                                                  Yeah, I think you have a point there.

                                                                                                                                            2. 0

                                                                                                                                              Just got my comfort seeing this reminds so many people of PHP.

                                                                                                                                            1. 35

                                                                                                                                              Networking is the place where I notice how tall modern stacks are getting the most.

                                                                                                                                              Debugging networking issues inside of Kubernetes feels like searching for a needle in a haystack. There are so, so many layers of proxies, sidecars, ingresses, hostnames, internal DNS resolvers, TLS re/encryption points, and protocols that tracking down issues can feel almost impossible.

                                                                                                                                              Even figuring out issues with local WiFi can be incredibly difficult. There are so many failure modes and many of them are opaque or very difficult to diagnose. The author here resorted to WireShark to figure out that 50% of their packets were re-transmissions.

                                                                                                                                              I wonder how many of these things are just inherent complexity that comes with different computers talking to each other and how many are just side effects of the way that networking/the internet developed over time.

                                                                                                                                              1. 4

                                                                                                                                                Considering most “container” orchestrators (at least the ones I’ve used) operate on virtual overlay networks and require a whole bunch of fuckery to get them to talk to each other, on top of whatever your observability-platform-of-the-week is, the complexity is both necessary and not. Container orchestration is a really bad way of handling dynamic service scaling IMO. For every small piece of the stack you need yet-another-container™️ which is both super inefficient (entire OS sans-kernel) and overcomplicated.

                                                                                                                                                1. 5

                                                                                                                                                  I’m not wed to containers, but they often seem like the least bad thing (depending on the workload and requirements). The obvious alternative is managing your own hosts, but that has its own pretty significant tradeoffs.

                                                                                                                                                  1. 4

                                                                                                                                                    Containers themselves are fine for a lot of cases. The networking layer (and also the storage/IO layer) are a large source of complexity that, IMO, is not great. It’s really unfortunate we’re to the point where we’re cramming everything on top of Linux userspace.

                                                                                                                                                    1. 2

                                                                                                                                                      There’s a bunch of different options that have varying degrees of pain to their respective usage, and different systemic properties between each of them.

                                                                                                                                                      1. 2

                                                                                                                                                        For me the killer feature is really supervision and restarting containers that appear to be dead, with the supervision done by a distributed system that can migrate the containers.

                                                                                                                                                  1. 3
                                                                                                                                                    1. 4

                                                                                                                                                      Aren’t *nix users the only people left who have a “desktop” anyway?

                                                                                                                                                      1. 1

                                                                                                                                                        The *nix users seem to be the only people left serious about anything related to computer science and software development. Is it just me or does it seem that *nix users are older leaving a generational gap. Who’s going to write software when the Millennials retire?

                                                                                                                                                        1. 4

                                                                                                                                                          GPT-6

                                                                                                                                                    1. 33

                                                                                                                                                      I think size of the program, and the team maintaining it, is an important factor in the static vs dynamic discussion.

                                                                                                                                                      I’m in the “I don’t make type errors, and if I do, I can shake them out with a few tests” camp for as long as I can comprehend what’s going on in the codebase.

                                                                                                                                                      But when the code grows to the point I can no longer remember where everything is, e.g. I can’t find all callers of a function, dynamism starts to become a burden. When I need to change a field of a struct, I have to find all uses of the field, because every missed one is a bug that’s going to show up later. At some point that becomes hard to grep for, and even impossible to account for in reflection-like code. It can degrade to a bug whack-a-mole, promote more and more defensive programming patterns, and eventually fear of change.

                                                                                                                                                      I’ve had good experiences with gradually-typed languages. They stretch this “size limit” of a program a lot, while still allowing use of duck typing where it helps, without bringing complexity of generic type systems.

                                                                                                                                                      1. 11

                                                                                                                                                        “Dynamic typing falls apart with large team/large codebase” is one of those cliché arguments that doesn’t really contribute usefully, though.

                                                                                                                                                        Also your presentation of it has multiple issues:

                                                                                                                                                        • Large team/large codebase projects fail all the time regardless of typing discipline. Static typing doesn’t appear to have a better track record of success there.
                                                                                                                                                        • Tooling for dynamically-typed languages has come a long way in the decades since this argument was first raised. You can just get an IDE and tell it to track down and rename references for you. And if your complaint is that it’s harder/impossible to do through “reflection-like code”, well, people can write metaprogram-y reflection stuff in statically-typed languages too.
                                                                                                                                                        • Ultimately, if your codebase has lots of functions or methods that are called from huge numbers of disparate places, to such a degree that you can’t safely work with it without an IDE doing full static analysis to track them all for you, that’s a code smell in any language, in any typing discipline.
                                                                                                                                                        1. 22

                                                                                                                                                          Static languages can verify all metaprogramming is type correct. IDE heuristics can not. In Rust you can write a macro and the compiler will expand and type check it. That kind of stuff is impossible in dynamic languages.

                                                                                                                                                          1. 10

                                                                                                                                                            Static languages can verify all metaprogramming is type correct.

                                                                                                                                                            This is probably going to get off-topic into arguing about the exact definition of “statically-typed”, but: I think that if you venture outside of languages like Rust (which seem to deliberately limit metaprogramming features precisely to be able to provide guarantees about the subset they expose), you’lll find that several languages’ guarantees about ahead-of-time correctness checks start being relaxed when using metaprogramming, runtime code loading, and other “dynamic-style” features. Java, for example, cannot actually make guarantees as strong as you seem to want, and for this among other reasons the JVM itself is sometimes referred to as the world’s most advanced dynamically-typed language runtime.

                                                                                                                                                            There also are plenty of things that seem simple but that you basically can’t do correctly in statically-typed languages without completely giving up on the type system. Truly generic JSON parsers, for example. Sure, you can parse JSON in a statically-typed language, but you either have to tightly couple your program to the specific structures you’ve planned in advance to handle (and throw runtime errors if you receive anything else), or parse into values of such ultra-generic “JSON object” types that the compiler and type system no longer are any help to you, and you’re effectively writing dynamically-typed code.

                                                                                                                                                            1. 5

                                                                                                                                                              for this among other reasons the JVM itself is sometimes referred to as the world’s most advanced dynamically-typed language runtime

                                                                                                                                                              Aren’t runtimes always “dynamically typed”? What does it mean for a runtime to be “statically typed”?

                                                                                                                                                              or parse into values of such ultra-generic “JSON object” types that the compiler and type system no longer are any help to you, and you’re effectively writing dynamically-typed code.

                                                                                                                                                              It sounds like you’re arguing that the worst case for static type systems is equivalent to the best case for dynamic type systems, which doesn’t seem like a ringing endorsement for dynamic type systems. That said, I don’t even think this is true for this JSON-parsing example, because you could conceive of a generic JSON parser that has different unmarshaling strategies (strict, permissive, etc). Further, as static type systems are adopted more widely, this sort of poorly-structured data becomes rarer.

                                                                                                                                                              1. 7

                                                                                                                                                                Aren’t runtimes always “dynamically typed”?

                                                                                                                                                                Some more so than others. Rust, for all its complexity as a language, is mostly shoving that complexity onto the compiler in hopes of keeping the runtime relatively simple and fast, because the runtime doesn’t have to do quite as much work when it trusts that there are classes of things the compiler simply prevents in advance (the runtime still does some work, of course, just not as much, which is the point).

                                                                                                                                                                But a language like Java, with runtime code loading and code injection, runtime reflection and introspection, runtime creation of a wide variety of things, etc. etc. does not get to trust the compiler as much and has to spend some runtime cycles on type-checking to ensure no rules are being broken (and it’s not terribly hard to deliberately write Java programs that will crash with runtime type errors, if you want to).

                                                                                                                                                                That said, I don’t even think this is true for this JSON-parsing example, because you could conceive of a generic JSON parser that has different unmarshaling strategies (strict, permissive, etc).

                                                                                                                                                                If you want truly generic parsing, you’re stuck doing things that the compiler can’t really help you with. I’ve seen even people who are quite adept at Haskell give up and effectively build a little subset of the program where everything is of a single JSON type, which is close enough to being dynamically typed as makes no difference.

                                                                                                                                                                Further, as static type systems are adopted more widely, this sort of poorly-structured data becomes rarer.

                                                                                                                                                                My experience of having done backend web development across multiple decades is that poorly-structured data isn’t going away anytime soon, and any strategy which relies on wishing poorly-structured data out of existence is going to fail.

                                                                                                                                                                1. 2

                                                                                                                                                                  Aren’t runtimes always “dynamically typed”?

                                                                                                                                                                  If you eschew these needlessly binary categories of static vs dynamic and see everything on a scale of dynamism then I think you’ll agree that runtimes are scattered across that spectrum. Many even shift around on that spectrum over time. For example, if you look at the history of JSR 292 for adding invokedynamic to the JVM you’ll find a lot of cases where the JVM used to be a lot less dynamically typed than it is today.

                                                                                                                                                                2. 4

                                                                                                                                                                  There’s no reason you can’t parse a set of known JSON fields into static members and throw the rest into an ultra-generic JSON object.

                                                                                                                                                                  1. 4

                                                                                                                                                                    Those are the options I said are available, yes.

                                                                                                                                                                    1. 3

                                                                                                                                                                      I mean, you can do both at once for the same value, getting the benefits of both.

                                                                                                                                                                  2. 3

                                                                                                                                                                    Dynlangs are definitely better for data that isn’t structured as well.

                                                                                                                                                                    C#’s dynamic keyword feels like a perfect fit for this situation without having to give up static typing everywhere else. Hejlsberg is ahead of the curve, per usual.

                                                                                                                                                                3. 7

                                                                                                                                                                  Fail is too harsh. Unless you’re writing some rocket navigation system, a project is not going to outright fail because of software defects. Run-time type errors merely add to other bugs that you will need to fix, and I argue that bugs caused by runtime type errors are less of a problem in small programs.

                                                                                                                                                                  I don’t know of any robust tooling for refactoring large JavaScript projects. Of course most languages have some type-system escape hatches, but I expect languages like JS to use hard-to-analyze type-erasing constructs much more often.

                                                                                                                                                                  I disagree that having callers beyond your comprehension is automatically a code smell. It’s a natural state of things for libraries, for example. Ideally libraries should have a stable API and never change it, but it’s not always that easy, especially for internal libraries and reusable core pieces of large projects that may need to evolve with the project.

                                                                                                                                                                  It’s not just about IDEs. Compilation will also track down all type errors for you, regardless of where and when these errors happen. When working with teams, it may be someone else working on some other component. In this case the types are a way to communicate and coordinate with others.

                                                                                                                                                                  You can make a mess in any language, but how easy is to make a mess varies between languages. Languages that prevent more errors will resist the mess for longer.

                                                                                                                                                                  1. 2

                                                                                                                                                                    I expect languages like JS to use hard-to-analyze type-erasing constructs much more often.

                                                                                                                                                                    Why do you expect this?

                                                                                                                                                                    I disagree that having callers beyond your comprehension is automatically a code smell.

                                                                                                                                                                    Even if it’s an internal library, why don’t other internal codebases have a single clear integration point with it? And why does everything else need to have lots of knowledge of the library’s structure? This definitely is a code smell to me – the Law of Demeter, at least, is being violated somewhere, and probably other design principles too.

                                                                                                                                                                    Languages that prevent more errors will resist the mess for longer.

                                                                                                                                                                    This is veering off into another clichéd and well-trod argument (“static typing catches/prevents more bugs”). I’ll just point out that while proponents of static typing often seem to take it as a self-evident truth, actually demonstrating its truth empirically has turned out to be, at the very least, extremely difficult. Which is to say: nobody’s managed it, despite it being such an “obvious” fact, and everybody who’s tried has run into methodological problems, or failed to prove any sort of meaningful effect size, or both.

                                                                                                                                                                    1. 2

                                                                                                                                                                      Why do you expect this?

                                                                                                                                                                      Because the flexibility is a benefit of dynamic languages. If you try to write code as-if it was strongly statically typed, you’re missing out on the convenience of writing these things “informally”, and you’re not getting compiler help to consistently stick to the rigid form.

                                                                                                                                                                      why don’t other internal codebases have a single clear integration point with it?

                                                                                                                                                                      The comprehension problems I’m talking about that appear in large programs also have a curse of being hard to explain succinctly in a comment like this. This is very context-dependent, and for every small example it’s easy to say the problem is obvious, and a fix is easy. But in larger programs these problems are harder to spot, and changes required may be bigger. Maybe the code is a mess, maybe the tech debt was justified or maybe not. Maybe there are backwards-compat constraints, interoperability with something that you can’t change, legacy codebase nobody has time to refactor. Maybe a domain-specific problem that really needs to be handled in lots of places. Maybe code is weirdly-shaped for performance reasons.

                                                                                                                                                                      The closest analogy I can think of is “Where’s Waldo?” game. If I show you a small Waldo picture, you’ll say the game is super easy, and obviously he’s right here. But the same problem in a large poster format is hard.

                                                                                                                                                                      1. 4

                                                                                                                                                                        Because the flexibility is a benefit of dynamic languages. If you try to write code as-if it was strongly statically typed, you’re missing out on the convenience of writing these things “informally”, and you’re not getting compiler help to consistently stick to the rigid form.

                                                                                                                                                                        You are once again assuming that statically-typed languages catch/prevent more errors, which I’ve already pointed out is a perilous assumption that nobody’s actually managed to prove rigorously (and not for lack of trying).

                                                                                                                                                                        Also, the explanation you give still doesn’t really make sense. Go look at some typical Python code, for example – Python’s metaprogramming features are rarely used and their use tends to be discouraged, and easily >99% of all real-world Python code is just straightforward with no fancy dynamic tricks. People don’t choose dynamic typing because they intend to do those dynamic tricks all the time. They choose dynamic typing (in part) because having that tool in the toolbox, for the cases when you need it or it’s the quickest/most straightforward way to accomplish a task, is incredibly useful.

                                                                                                                                                                        The comprehension problems I’m talking about that appear in large programs also have a curse of being hard to explain succinctly in a comment like this

                                                                                                                                                                        Please assume that I’ve worked on large codebases maintained by many programmers, because I have.

                                                                                                                                                                        And I’ve seen how they tend to grow into balls of spaghetti with strands of coupling running everywhere. Static typing certainly doesn’t prevent that, and I stand by my assertion that it’s a code smell when something is being called from so many disparate places that you struggle to keep track of them, because it is a code smell. And there are plenty of patterns for preventing it, none of which have to do with typing discipline, and which are well-known and well-understood (most commonly, wrapping an internal interface around a library and requiring all other consumers in the codebase to go through the wrapper, so that the consuming codebase controls the interface it sees and has onlyu a single point to update if the library changes).

                                                                                                                                                                        1. 3

                                                                                                                                                                          I’ve worked on large codebases maintained by many programmers, because I have. And I’ve seen how they tend to grow into balls of spaghetti with strands of coupling running everywhere. Static typing certainly doesn’t prevent that . . .

                                                                                                                                                                          No, definitely not, agreed. But static typing definitely improves many/most dimensions of project maintainability, compared to dynamic typing. This isn’t really a controversial claim! Static typing simply moves a class of assertions out of the domain of unit tests and into the domain of the compiler. The question is only if the cost of those changes is greater or lesser than the benefits they provide. There’s an argument to be made for projects maintained by individuals, or projects with lifetimes of O(weeks) to O(months). But once you get to code that’s maintained by more than 1 person, over timespans of months or longer? The cost/benefit calculus just doesn’t leave any room for debate.

                                                                                                                                                                          1. 3

                                                                                                                                                                            But static typing definitely improves many/most dimensions of project maintainability, compared to dynamic typing. This isn’t really a controversial claim!

                                                                                                                                                                            On the contrary, it’s a very controversial claim.

                                                                                                                                                                            Proponents of static typing like to just assert things like this without proof. But proof you must have, and thus far nobody has managed it – every attempt at a rigorous study to show the “obvious” benefits of static typing has failed. Typically, the ones that find the effect they wanted have methodological issues which invalidate their results, and the ones that have better methodology fail to find a significant effect.

                                                                                                                                                                            The cost/benefit calculus just doesn’t leave any room for debate.

                                                                                                                                                                            Again: prove it. WIth more than anecdata, because we both have anecdotes and that won’t settle anything.

                                                                                                                                                                        2. 3

                                                                                                                                                                          Because the flexibility is a benefit of dynamic languages. If you try to write code as-if it was strongly statically typed, you’re missing out on the convenience of writing these things “informally”, and you’re not getting compiler help to consistently stick to the rigid form.

                                                                                                                                                                          I see most typing errors as self-inflicted wounds at this point. Don’t have time or patience for things that can be prevented by the compiler happening at runtime.

                                                                                                                                                                          Dynlangs + webdev together is my kryptonite. If I had to do that all day I’d probably start looking for a new career. Just can’t deal with it.

                                                                                                                                                                      2. 1

                                                                                                                                                                        I don’t know of any robust tooling for refactoring large JavaScript projects

                                                                                                                                                                        Following up on this specifically: I’m an Emacs guy, not really an IDE person, so I don’t know the landscape that well. But everybody I know who goes the IDE route in Python uses PyCharm, so I looked up the rest of the JetBrains product line, and sure enough they have an IDE for JavaScript/TypeScript which claims to support refactoring.

                                                                                                                                                                        I assume it’s not the only such product out there.

                                                                                                                                                                      3. 4

                                                                                                                                                                        Large team/large codebase projects fail all the time regardless of typing discipline. Static typing doesn’t appear to have a better track record of success there.

                                                                                                                                                                        Yes, projects can fail for lots of reasons; no one is claiming that static typing will make a shitty idea commercially successful, for example :) But I do think static types help a lot within their narrow scope–keeping code maintainable, reducing bugs, preserving development velocity, etc. Of course, there’s no good empirical research on this, so we’re just going off of our collective experiences. 🤷‍♂️

                                                                                                                                                                        1. 3

                                                                                                                                                                          Large team/large codebase projects fail all the time regardless of typing discipline. Static typing doesn’t appear to have a better track record of success there.

                                                                                                                                                                          I think it pretty much does, actually. Static typing moves an enormous class of invariants from opt-in runtime checks to mandatory compile-time checks. Statically typed languages in effect define and enforce a set of assertions that can be approximated by dynamically typed languages but never totally and equivalently guaranteed. There is a cost associated with this benefit, for sure, but that cost is basically line noise the moment your project spans more than a single developer, or extends beyond a non-trivial period of time.

                                                                                                                                                                          1. 2

                                                                                                                                                                            I think it pretty much does, actually.

                                                                                                                                                                            As I said to your other comment along these lines: prove it. The literature is infamously full of people absolutely failing to find effects from static typing that would justify the kinds of claims you’re making.

                                                                                                                                                                        2. 13

                                                                                                                                                                          I always laugh when I see ruby code where the start of the method is a bunch of “raise unless foo.is_a? String”. The poor mans type checking all over the place really highlights how unsuitable these dynamic languages are for real world use.

                                                                                                                                                                          1. 7

                                                                                                                                                                            To be fair, any use of is_a? in ruby is a code smell

                                                                                                                                                                            1. 12

                                                                                                                                                                              Sure, it’s also a pattern I have seen in every Ruby codebase I have ever worked with because the desire to know what types you are actually working with is somewhat important for code that works correctly.

                                                                                                                                                                              1. 5

                                                                                                                                                                                Yeah, the need for ruby devs is much larger than the supply of good ones or even ones good enough to train the others. I’ve seen whole large ruby codebases obviously written by Java and C++ devs who never got ruby mentoring. I expect this is an industry wide problem in many stacks

                                                                                                                                                                            2. 6

                                                                                                                                                                              You seem to just be trolling, but I’ll play along, I guess.

                                                                                                                                                                              I’ve seen a bit of Ruby, and a lot of Python and JavaScript, and I’ve never seen this except for code written by people who were coming from statically-typed languages and thought that was how everyone does dynamic typing. They usually get straightened out pretty quickly.

                                                                                                                                                                              Can you point to some examples of popular Ruby codebases which are written this way? Or any verifiable evidence for your claim that dynamic languages are “unsuitable… for real world use”?

                                                                                                                                                                              1. 6

                                                                                                                                                                                I’m not trolling at all. I’ve been a Rails dev for the last 7 years and seen the same thing at every company. I don’t work on any open source code so I can’t point you at anything.

                                                                                                                                                                                I quite like Rails but I’m of the opinion that the lack of static type checking is a serious deficiency. Updating Rails itself is an absolute nightmare task where even the official upgrade guide admits the only way to proceed is to have unit tests on every single part of the codebase because there is no way you can properly verify you have seen everything that needs to change. I’ve spent a large chunk of time spanning this whole year working towards updating from Rails 5.1 to 5.2. No one else dared attempt it before I joined because it’s so extremely risky.

                                                                                                                                                                                I love a lot of things about Rails and the everything included design but I don’t see a single benefit to lacking types. Personally I see TypeScript as taking over this space once the frameworks become a little more mature.

                                                                                                                                                                                1. 3

                                                                                                                                                                                  You made a very specific assertion about how people write Ruby (lots of manual type-checking assertions). You should be able to back up that assertion with pointers to the public repositories of popular projects written in that style.

                                                                                                                                                                                  1. 8

                                                                                                                                                                                    I remembered hearing from my then-partner that Rails itself uses a lot of is_a?, and that seems true.

                                                                                                                                                                                     if status.is_a?(Hash)
                                                                                                                                                                                            raise ArgumentError, etc...
                                                                                                                                                                                    
                                                                                                                                                                                    1. 3

                                                                                                                                                                                      This is pretty misleading – a quick glance at some of the examples seems like many of them aren’t really checking argument types, and when they are, they’re often cases where a method accepts any of multiple types, and there’s branching logic to handle the different options.

                                                                                                                                                                                      Which is something you’d also see in a statically-typed language with sum types.

                                                                                                                                                                                      The proposition that this is a common idiom used solely as a replacement for static checking is thus stil unproved.

                                                                                                                                                                                      1. 1

                                                                                                                                                                                        Well yeah, and then there’s those that raise errors, or return some failure-signaling value.

                                                                                                                                                                                        I don’t know what projects to look at since I don’t use Ruby, but I found some more in ruby/ruby.

                                                                                                                                                                                    2. 6

                                                                                                                                                                                      ill concur with GP: this is a fairly common pattern to see in ruby codebases.

                                                                                                                                                                                      however, to be fair, it’sa pattern most often introduced after attending a talk by a static typing weenie…

                                                                                                                                                                                2. 5

                                                                                                                                                                                  Do you also laugh when you see “assert(x > 0);” in typed languages?

                                                                                                                                                                                  1. 7

                                                                                                                                                                                    I would, but it would be a sad laugh because I’m using a type system that can’t express a non-zero integer.

                                                                                                                                                                                    1. 3

                                                                                                                                                                                      I would love to see broader adaptation of refinement types that let you statically guarantee properties like integer values being bound between specific values.

                                                                                                                                                                                  2. 4

                                                                                                                                                                                    I’m in the “I don’t make type errors, and if I do, I can shake them out with a few tests” camp for as long as I can comprehend what’s going on in the codebase.

                                                                                                                                                                                    This is generally true for me, but writing tests or debugging stack traces makes for a slow iteration loop. A type error from a compiler usually contains better, more direct information so resolving these type errors is a lot faster. To the extent that I (a 15 year Pythonista) eventually began to prototype in Go.

                                                                                                                                                                                    That said, the biggest advantage for me for a static type checker is that it penalizes a lot of the crappy dynamic code (even the stuff that is technically correct but impossible to maintain/extend over time). A static type system serves as “rails” for less scrupulous team members. Of course, a lot of these less-scrupulous developers perceive this friction as a problem with static type systems rather than a problem with the way they hacked together their code, but I think Mypy and TypeScript have persuaded many of these developers over time to the extent that static types are much less controversial in most dynamic language communities.

                                                                                                                                                                                    Another big advantage is that your type documentation is always correct and precise (whereas docs in a dynamically typed language often go stale or simply describe something as “a file-like object” [does that mean it just has a read() method, or does it also need write(), close(), seek(), truncate(), etc?]). Further, because the type docs are precise, you can have thinks like https://pkg.go.dev complete with links to related types, even if those types are declared in another package, and you get all of this for free.

                                                                                                                                                                                    1. 4

                                                                                                                                                                                      I’m in the Type everything if it’s even kinda big camp now. There are too many things I need to think about during the day to remember the state and usage of every variable of every program I’ve ever written, used or inspected. Typings are rails for my logic. Typings are documentation. Types help my IDE help me. I will take every single shortcut I can when the timespan I or anyone else could be interacting with the code is longer than 10 minutes.

                                                                                                                                                                                      Retracing steps is just so tedious and frustrating when you had it all in your head before. It just sucks. I just wanna build stuff, not fill my head with crap my computer can do.

                                                                                                                                                                                      /rant

                                                                                                                                                                                    1. 12

                                                                                                                                                                                      I think everyone’s experience is going to be different, this is all highly subjective depending on what communities you want to interact with. That being said, I’m very pleasantly surprised at how smoothly the transition to Mastodon has gone for my professional/programming feed.

                                                                                                                                                                                      1. 14

                                                                                                                                                                                        I’m shocked that it worked (~70% of people I follow have moved to Mastodon, and it’s more active than Twitter now). It’s like the year of Linux desktop happening.

                                                                                                                                                                                        1. 9

                                                                                                                                                                                          It turns out all we need for the year of the Linux desktop to happen is for Elon Musk to buy a major competitor, say, Microsoft, or Apple. Doesn’t seem likely, but neither does a lot of stuff that is definitely happening in our timeline.

                                                                                                                                                                                          Maybe there is someone else (incredibly rich yet wildly incompetent and detached from reality) who could do Linux a similar service? It doesn’t literally have to be Elon Musk, it’s clear that wealth does not correlate with any ability or positive qualities whatsoever, there’s got to be hundreds of other (less famous?) plutocrats who also have the potential to destroy anything they touch. Thiel? DHH? Maybe a young con artist in the tradition of Theranos or FTX could convince investors to fund their joyride in the crumbling shell of a previously productive corporation.

                                                                                                                                                                                          1. 7

                                                                                                                                                                                            Doesn’t seem likely,

                                                                                                                                                                                            0% chance. Elon Musk bought Twitter for $44 billion. Apple and Microsoft are worth way more than that.

                                                                                                                                                                                            Apple market cap: $2.29 trillion (52 Twitters)

                                                                                                                                                                                            Microsoft market cap: $1.80 trillion (41 Twitters)

                                                                                                                                                                                            Even assuming either company would consider privatizing (they wouldn’t), even the top 10 richest people pooling their net worth couldn’t buy either of them.

                                                                                                                                                                                          2. 5

                                                                                                                                                                                            I’m on the one hand happy that it worked, but the move for me has been… spotty. Essentially my whole tech timeline moved, so that’s fine.

                                                                                                                                                                                            But I actively used Twitter to get into community I am very curious about. I have family in Botswana and so I used Twitter to stay up to speed on what happens in the region. All that migrated to about 0% and that’s a huge loss for me.

                                                                                                                                                                                          3. 3

                                                                                                                                                                                            I need to check it out again. When I’ve tried it in the past, it always felt like a bunch of people and bots shouting into the void–lots of content, but very little dialogue.

                                                                                                                                                                                            1. 7

                                                                                                                                                                                              lots of content, but very little dialogue

                                                                                                                                                                                              Twitter isn’t really a medium for dialogue anyway…

                                                                                                                                                                                              1. 1

                                                                                                                                                                                                Well, it’s not a platform that optimizes for constructive dialogue, so maybe a less ambiguous term would be “engagement”: there is a lot of engagement on Twitter, but very little on Mastodon (IME).

                                                                                                                                                                                              2. 4

                                                                                                                                                                                                Anecdotally, the Twitter Migration has caused a qualitative change, for better or worse. There is tons of dialogue on my instance.

                                                                                                                                                                                                1. 1

                                                                                                                                                                                                  My biggest challenge right now is that my instance got too popular I guess and now is constantly down. :(

                                                                                                                                                                                                  1. 1

                                                                                                                                                                                                    What’s the bottleneck? Database? Web server? Something else?

                                                                                                                                                                                                    1. 1

                                                                                                                                                                                                      Oh sorry I meant the instance I’m on. That is, I don’t know what the problem is.

                                                                                                                                                                                                2. 1

                                                                                                                                                                                                  If you’re active on Twitter I can recommend using one of the services that checks if your followers are also on a Fediverse instance, and allow you to easily import them.

                                                                                                                                                                                              1. 6

                                                                                                                                                                                                I bought an old Mac Mini for very cheap and put a big disk in it. I let Photos sync everything there and I back up my Photos library (and the rest of my iCloud stuff, which is getting close to 2TB now) to Backblaze.

                                                                                                                                                                                                I also let Google Photos take copies from the phone and occasionally check in on it to see if it’s working okay.

                                                                                                                                                                                                1. 1

                                                                                                                                                                                                  via cable?

                                                                                                                                                                                                  1. 1

                                                                                                                                                                                                    No all of this is without physically connecting anything

                                                                                                                                                                                                    1. 1

                                                                                                                                                                                                      How can the photos app sync with the mac mini then?

                                                                                                                                                                                                      1. 1

                                                                                                                                                                                                        iCloud syncs it

                                                                                                                                                                                                        1. 1

                                                                                                                                                                                                          Do you have to pay for an iCloud plan then? And if so, what happens when you run out of capacity in iCloud? Or is this syncing feature independent of the iCloud storage plans?

                                                                                                                                                                                                          1. 1

                                                                                                                                                                                                            Yes I pay for iCloud, for a family pack that gives us 2TB. By far I’m the biggest user and the capacity is almost all photos and videos from my various cameras. I’m happy paying for this because it means I get to provide others with a copy of their photos that won’t easily get lost.

                                                                                                                                                                                                            I’m not quite near the 2TB limit yet but eventually I’ll have to come up with a way to choose what I don’t want be in my primary Photos library and that I will just leave in one place to keep it backed up.

                                                                                                                                                                                                            I probably have quite a lot of video I could move out of my primary Photos library and just keep around - but I like that I keep accidentally coming across old photos and videos, so I hope they make a bigger plan soon.

                                                                                                                                                                                                            I used to use Dropbox Photos but they killed it. That was pretty good. Apple Photos is great for always having all my photos available on my phone, laptops, etc. - all indexed and catalogued automatically in some useful ways. Just like Google Photos. I don’t trust Apple or Google alone, but I like the iOS and MacOS Photos stuff enough to use it as my primary way to handle photos.

                                                                                                                                                                                                            Syncing is because of iCloud. I don’t have a 2TB phone to keep all my photos on and sync to elsewhere! Maybe one day.

                                                                                                                                                                                                            You can of course try the ways around using the system Apple provide but it’s always going to be clunky. The closest to the same experience is Google Photos, as far as I know. I think you can still sync Google Photos to Linux so that might be a way to do similar to iCloud + Apple Photos though not necessarily cheaper.

                                                                                                                                                                                                1. 4

                                                                                                                                                                                                  I tried to do something like this but I eventually caved and paid the Apple Tax.

                                                                                                                                                                                                  1. 2

                                                                                                                                                                                                    Same. And thus far I am very happy with the arrangement.

                                                                                                                                                                                                    $3/mo for 200 GB of storage that I can share with my family. Even taking ludicrous amounts of pictures of our kids, we have not come even close to hitting that limit.

                                                                                                                                                                                                    I don’t have to worry about creating, managing, or maintaining backups. And every photo I take is immediately and transparently backed up and synced to all my devices.

                                                                                                                                                                                                    Forgive me for sounding like a fanboy, but my experience with iCloud storage has been very positive.

                                                                                                                                                                                                    1. 3

                                                                                                                                                                                                      We’re already at the 200GB limit and I don’t think it would take long to hit the 2TB limit if we upgraded. I really just wish they would let me bring my own storage because otherwise my experiences with iCloud have been very positive.

                                                                                                                                                                                                  1. 4

                                                                                                                                                                                                    iCloud Photo Library with my main MacBook Pro set to sync all content locally, then Arq backs it up into Backblaze b2. (Along with the rest of the machine, including iCloud Drive.)

                                                                                                                                                                                                    1. 2

                                                                                                                                                                                                      How does this work? Does it have to go through iCloud to get to your MBP? And if so, are you constrained on iCloud capacity (we’re paying for 200GB and we’re already hitting that cap). If not, do you have to plug in a USB, or does it work automatically via the network?

                                                                                                                                                                                                      1. 1

                                                                                                                                                                                                        Syncs through iCloud yes. We have the family “everything” plan (Apple Premier?) so get 2TB cloud storage to use between us. Think my photo library is just over 300GB so far.

                                                                                                                                                                                                        If I had to plug the phone in, I’d never sync it.

                                                                                                                                                                                                      2. 1

                                                                                                                                                                                                        This is precisely what I do. I did recently switch from Backblaze B2 to MS OneDrive, as I needed the MS365 subscription for other (family) reasons, and it comes with 6 x 1TB Onedrive accounts. Two are used for backups.

                                                                                                                                                                                                        1. 1

                                                                                                                                                                                                          I’m curious why you use Backblaze B2 and not the Backblaze Personal Backup?

                                                                                                                                                                                                          1. 2

                                                                                                                                                                                                            I used to use their personal backup years ago when it first came out, switched to using Arq against One Drive and S3 I think it was, then switched to b2 because it’s cheaper (and easier to setup.) Stopped using One Drive when I left my previous job as it was the corporate account.

                                                                                                                                                                                                            I found backblaze personal backup didn’t backup system paths, which included homebrew (vague memory, might have been macports?) and I couldn’t restore a database I’d overwritten locally because it hadn’t been backed up. I understand why the client doesn’t do that, but it was a dealbreaker for me at the time. Arq also does client side encryption and multiple locations for me.

                                                                                                                                                                                                        1. 29

                                                                                                                                                                                                          Makes sense to me. Given that it’s a topic with interest that’s only about to grow.

                                                                                                                                                                                                          1. 3

                                                                                                                                                                                                            I’m all for a tag, but I suspect that normies aren’t going to stay on the fediverse. They’ll either go back to Twitter or some other corporate social media product. Fediverse just feels like people and bots shouting into the void with relatively little interaction/diaglogue. I’m sure you can curate your experience, but I don’t think most people want to go through the hassle. My suspicion is that the Fediverse enthusiasm will fade in a few months.

                                                                                                                                                                                                            1. 13

                                                                                                                                                                                                              Fediverse just feels like people and bots shouting into the void with relatively little interaction/diaglogue.

                                                                                                                                                                                                              I have the complete opposite experience. Maybe you are holding it wrong?

                                                                                                                                                                                                              My suspicion is that the Fediverse enthusiasm will fade in a few months.

                                                                                                                                                                                                              How is that relevant at all? We have tags for fortran or dragonflybsd which are niches of niches sure we can have one for fediverse.

                                                                                                                                                                                                              1. 2

                                                                                                                                                                                                                I have the complete opposite experience. Maybe you are holding it wrong?

                                                                                                                                                                                                                Maybe? I’ve tried it a lot on several different servers over the years, and tried to make it work, but there was rarely any interaction.

                                                                                                                                                                                                                How is that relevant at all? We have tags for fortran or dragonflybsd which are niches of niches sure we can have one for fediverse.

                                                                                                                                                                                                                My post literally opened with “I’m all for a tag”. 🙄 This bit was relevant because the parent claimed that fediverse was going to continue growing in popularity, and I was expressing that it’s unlikely to continue growing in popularity beyond the next month or two. You’re welcome to disagree, but I’m still on-topic.

                                                                                                                                                                                                              2. 4

                                                                                                                                                                                                                What do you mean by “normies”, if I might ask?

                                                                                                                                                                                                                1. 6

                                                                                                                                                                                                                  I assumed “normal people”/Non-tech people.

                                                                                                                                                                                                                  1. 4

                                                                                                                                                                                                                    People who stick to the mainstream as it pertains to some dimension. In this case the dimension is social media platforms, but it could be politics or something else.

                                                                                                                                                                                                                    1. 5

                                                                                                                                                                                                                      It is pseudo elitist speak of people who define their identity via the obscure technologies they use.

                                                                                                                                                                                                                      1. 0

                                                                                                                                                                                                                        It’s also popular among racists and otherwise antisocial online communities.

                                                                                                                                                                                                                        1. 7

                                                                                                                                                                                                                          You know who else drinks water? Hitler.

                                                                                                                                                                                                                          It’s a common phrase all over the Internet. I’m sure some racist somewhere has used it, but that doesn’t imply that it’s particularly affiliated with racists.

                                                                                                                                                                                                                          1. 5

                                                                                                                                                                                                                            Indeed; I’ve also heard it in LGBT+ & neurodivergent communities a fair bit.

                                                                                                                                                                                                                            It more broadly suggests “yes, we’re different, and that’s not a bad thing (maybe even a good one).”

                                                                                                                                                                                                                          2. 3

                                                                                                                                                                                                                            I get that terms like “normie”, “muggle”, or “civilian” may be derogatory depending on context but I’m curious: what racist & antisocial groups are using that term, and what groups do they target with it?

                                                                                                                                                                                                                            1. 6

                                                                                                                                                                                                                              I found this paper by googling “how to redpill normies”

                                                                                                                                                                                                                              Redpilling Normies: An Ethnography of Alt-Right 4chan Discourse.

                                                                                                                                                                                                                              Sounds like it should be a good entry point for your research.

                                                                                                                                                                                                                              1. 2

                                                                                                                                                                                                                                It really got moving on 4chan. Now, some people will say that not everyone on 4chan is that way, but if someone made a racist joke at Thanksgiving dinner and you laughed, it’s both of you. I don’t break bread with those types, personally.

                                                                                                                                                                                                                    1. 29

                                                                                                                                                                                                                      Why Twitter didn’t go down … yet

                                                                                                                                                                                                                      I was hoping for some insights into the failure modes and timelines to expect from losing so many staff.

                                                                                                                                                                                                                      This thread https://twitter.com/atax1a/status/1594880931042824192 has some interesting peeks into some of the infrastructure underneath Mesos / Aurora.

                                                                                                                                                                                                                      1. 12

                                                                                                                                                                                                                        I also liked this thread a lot: https://twitter.com/mosquitocapital/status/1593541177965678592

                                                                                                                                                                                                                        And yesterday it was possible to post entire movies (in few-minute snippets) in Twitter, because the copyright enforcement systems were broken.

                                                                                                                                                                                                                        1. 5

                                                                                                                                                                                                                          That tweet got deleted. At this point it’s probably better to archive them and post links of that.

                                                                                                                                                                                                                          1. 11

                                                                                                                                                                                                                            It wasn’t deleted - there’s an ongoing problem over the last few days where the first tweet of a thread doesn’t load on the thread view page. The original text of the linked tweet is this:

                                                                                                                                                                                                                            I’ve seen a lot of people asking “why does everyone think Twitter is doomed?”

                                                                                                                                                                                                                            As an SRE and sysadmin with 10+ years of industry experience, I wanted to write up a few scenarios that are real threats to the integrity of the bird site over the coming weeks.

                                                                                                                                                                                                                            1. 12

                                                                                                                                                                                                                              It wasn’t deleted - there’s an ongoing problem over the last few days where the first tweet of a thread doesn’t load on the thread view page.

                                                                                                                                                                                                                              It’s been a problem over the last few weeks at least. Just refresh the page a few times and you should eventually see the tweet. Rather than the whole site going down at once, I expect these kinds of weird problems will start to appear and degrade Twitter slowly over time. Major props to their former infrastructure engineers/SREs for making the site resilient to the layoffs/firings though!

                                                                                                                                                                                                                              1. 2

                                                                                                                                                                                                                                Not only to the infra/SREs but also to the backend engineers. Much of the built-in fault-tolerance of the stack was created by them.

                                                                                                                                                                                                                            2. 2

                                                                                                                                                                                                                              https://threadreaderapp.com/thread/1593541177965678592.html

                                                                                                                                                                                                                              I have this URL archived too, but it seems to still be working.

                                                                                                                                                                                                                              1. 1

                                                                                                                                                                                                                                hm, most likely someone would have a mastodon bridge following these accounts RT-ing :-)

                                                                                                                                                                                                                              2. 2

                                                                                                                                                                                                                                FWIW, I just tried to get my Twitter archive downloaded and I never received an SMS from the SMS verifier. I switched to verify by email and it went instantly. I also still haven’t received the archive itself. God knows how long that queue is…

                                                                                                                                                                                                                                1. 2

                                                                                                                                                                                                                                  I think it took about 2 or 3 days for my archive to arrive last week.

                                                                                                                                                                                                                              3. 2

                                                                                                                                                                                                                                oh, so they still run mesos? thought everyone had by now switched to k8s…

                                                                                                                                                                                                                                1. 13

                                                                                                                                                                                                                                  I used to help run a fairly decent sized Mesos cluster – I think at our pre-AWS peak we were around 90-130 physical nodes.

                                                                                                                                                                                                                                  It was great! It was the definition of infrastructure that “just ticked along”. So it got neglected, and people forgot about how to properly manage it. It just kept on keeping on with minimal to almost no oversight for many months while we got distracted with “business priorities”, and we all kinda forgot it was a thing.

                                                                                                                                                                                                                                  Then one day one of our aggregator switches flaked out and all of a sudden our nice cluster ended up partitioned … two, or three ways? It’s been years, so the details are fuzzy, but I do remember

                                                                                                                                                                                                                                  • some stuff that was running still ran – but if you had dependencies on the other end of the partition there was lots of systems failing health checks & trying to get replacements to spin up
                                                                                                                                                                                                                                  • Zookeeper couldn’t establish a quorum and refused to elect a new leader so Mesos master went unavailable, meaning you didn’t get to schedule new jobs
                                                                                                                                                                                                                                  • a whole bunch of business critical batch processes wouldn’t start
                                                                                                                                                                                                                                  • we all ran around like madmen trying to figure out who knew enough about this cluster to fix it

                                                                                                                                                                                                                                  It was a very painful lesson. As someone on one of these twitter threads posted, “asking ‘why hasn’t Twitter gone down yet?’ is like shooting the pilot and then saying they weren’t needed because the plane hasn’t crashed yet”.

                                                                                                                                                                                                                                  1. 8

                                                                                                                                                                                                                                    Twitter is well beyond the scale where k8s is a plausible option.

                                                                                                                                                                                                                                    1. 2

                                                                                                                                                                                                                                      I wonder what is the largest company that primarily runs on k8s. The biggest I can think of is Target.

                                                                                                                                                                                                                                      1. 3

                                                                                                                                                                                                                                        There’s no limit to the size of company that can run on kube if you can run things across multiple clusters. The problem comes if you routinely have clusters get big rather than staying small.

                                                                                                                                                                                                                                        1. 1

                                                                                                                                                                                                                                          Alibaba, probably.

                                                                                                                                                                                                                                          1. 1

                                                                                                                                                                                                                                            Oh, I didn’t realize that was their main platform.

                                                                                                                                                                                                                                          2. 1
                                                                                                                                                                                                                                            1. 2

                                                                                                                                                                                                                                              I was thinking about that too, but I’m guessing that CFA has a fraction of the traffic of Target (especially this time of year). Love those sandwiches though…

                                                                                                                                                                                                                                        2. 2

                                                                                                                                                                                                                                          Had they done so, I bet they’d already be down :D

                                                                                                                                                                                                                                          1. 1

                                                                                                                                                                                                                                            I work at a shop with about 1k containers being managed by mesos and it is a breath of fresh air after having been forced to use k8s. There is so much less cognitive overhead to diagnosing operational issues. That said, I think any mesos ecosystem will be only as good as the tooling written around it. Setting up load balancing, for instance . . . just as easy to get wrong as right.

                                                                                                                                                                                                                                        1. 21

                                                                                                                                                                                                                                          Oh is it time to hype dsls again? That makes sense as we’re starting to all get a little embarrassed about the levels of hype for functional programming.

                                                                                                                                                                                                                                          I guess next we’ll be hyping up memory safe object oriented programming.

                                                                                                                                                                                                                                          1. 16

                                                                                                                                                                                                                                            I’m just sitting here with my Java books waiting for the pendulum to swing back…

                                                                                                                                                                                                                                            1. 9

                                                                                                                                                                                                                                              I’m going to go long on eiffel books.

                                                                                                                                                                                                                                              1. 6

                                                                                                                                                                                                                                                I think a language heavily inspired by Eiffel, while fixing all of its (many, many) dumb mistakes, could go really far.

                                                                                                                                                                                                                                                1. 2

                                                                                                                                                                                                                                                  I’ve just started learning Eiffel and like what ive seen so far, just curious what do you consider its mistakes?

                                                                                                                                                                                                                                                  1. 8
                                                                                                                                                                                                                                                    1. CAT-calling
                                                                                                                                                                                                                                                    2. Bertrand Meyer’s absolute refusal to use any standard terminology for anything in Eiffel. He calls nulls “voids”, lambdas “agents”, modules “clusters”, etc.
                                                                                                                                                                                                                                                    3. Also his refusal to adopt any PL innovations past 1995, like all the contortions you have to do to get “void safety” (null safety) instead of just adding some dang sum types.
                                                                                                                                                                                                                                                  2. 1

                                                                                                                                                                                                                                                    Racket!

                                                                                                                                                                                                                                              2. 14

                                                                                                                                                                                                                                                I, personally, very much doubt full on OOP will ever come back in the same way it did in the 90s and early 2000s. FP is overhyped by some, but “newer” languages I’ve seen incorporate ideas from FP and explicitly exclude core ideas of OOP (Go, Zig, Rust, etc.).

                                                                                                                                                                                                                                                1. 5

                                                                                                                                                                                                                                                  I mean, all of those languages have a way to do dynamic dispatch (interfaces in Go, trait objects in Rust, vtables in Zig as of 0.10).

                                                                                                                                                                                                                                                  1. 13

                                                                                                                                                                                                                                                    And? They also all support first-class functions from FP but nobody calls them FP languages. Inheritance is the biggest thing missing, and for good reason.

                                                                                                                                                                                                                                                    1. 12

                                                                                                                                                                                                                                                      This, basically. Single dynamic dispatch is one of the few things from Java-style OO worth keeping. Looking at other classic-OO concepts: inheritance is better off missing most of the time (some will disagree), classes as encapsulation are worse than structs and modules, methods don’t need to be attached to classes or defined all in one batch, everything is not an object inheriting from a root object… did I miss anything?

                                                                                                                                                                                                                                                      Subtyping separate from inheritance is a useful concept, but from what I’ve seen the world seldom breaks down into such neat categories to make subtyping simple enough to use – unsigned integers are the easiest example. Plus, as far as I can tell it makes most current type system math explode. So, needs more theoretical work before it wiggles back into the mainstream.

                                                                                                                                                                                                                                                      1. 8

                                                                                                                                                                                                                                                        I’ve been thinking a lot about when inheritance is actually a good idea, and I think it comes down to two conditions:

                                                                                                                                                                                                                                                        1. The codebase will instantiate both Parent and Child objects
                                                                                                                                                                                                                                                        2. Anything that accepts a Parent will have indistinguishable behavior when passed a Child object (LSP).

                                                                                                                                                                                                                                                        IE a good use of Inheritance is to subclass EventReader with ProfiledEventReader.

                                                                                                                                                                                                                                                        1. 10

                                                                                                                                                                                                                                                          Take a cookie from a jar for using both LSP and LSP in a single discussion!

                                                                                                                                                                                                                                                          1. 4

                                                                                                                                                                                                                                                            Inheritance can be very useful when it’s decoupled from method dispatch.

                                                                                                                                                                                                                                                            Emacs mode definitions are a great example. Nary a class nor a method in sight, but the fact that markdown-mode inherits from text-mode etc is fantastically useful!

                                                                                                                                                                                                                                                            On the other hand, I think it’s fair to say that this is so different from OOP’s definition of inheritance that using the same word for it is just asking for confusion. (I disagree but it’s a reasonable argument.)

                                                                                                                                                                                                                                                            1. 2

                                                                                                                                                                                                                                                              Inheritance works wonderfully in object systems with multiple dispatch, although I’m not qualified to pinpoint what is it that makes them click together.

                                                                                                                                                                                                                                                              1. 1

                                                                                                                                                                                                                                                                I’ve lately come across a case where inheritance is a Good Idea; if you’re plotting another of your fabulous blog posts on this, I’m happy to chat :)

                                                                                                                                                                                                                                                                1. 1

                                                                                                                                                                                                                                                                  My impression is that inheritance is extremely useful for a peculiar kind of composition, namely open recursion. For example, you write some sort of visitor-like pattern in a virtual class, then inherit it, implement the visit method or what have you, and use this to recurse between the abstract behavior of traversing some structure, and your use-case-specific code. Without recursion you have to basically reimplement a vtable by hand and it sucks.

                                                                                                                                                                                                                                                                  Well, that’s my only use of inheritance in OCaml. Most of the code is just functions, sum types, records, and modules.

                                                                                                                                                                                                                                                                  1. 1

                                                                                                                                                                                                                                                                    Forrest for the trees? When you want to create a framework that has default behaviour that can be changed, extended or overridden?

                                                                                                                                                                                                                                                                  2. 4
                                                                                                                                                                                                                                                                    • obj.method syntax for calling functions — a decent idea worth keeping.
                                                                                                                                                                                                                                                                    • bundling behavior, mutable state, and identity into one package — not worth doing unless you are literally Erlang.
                                                                                                                                                                                                                                                                    1. 3

                                                                                                                                                                                                                                                                      IMO there is a fundamental difference between Erlang OO and Java OO to the point that bringing them up in the same conversation is rarely useful. Erlang actively discourages you from having pellets of mutable state scattered around your program: sure, threads are cheap, but that state clump is still a full-blown thread you need to care for. It needs rules on supervision, it needs an API of some kind to communicate, etc, etc. Erlang is at it’s best when you only use threads when you are at a concurrency boundary, and otherwise treat it as purely functional. Java, in contrast, encourages you to make all sorts of objects with mutable state all over the place in your program. I’d wager that MOST non-trivial methods in Java contain the “new” keyword. This results in a program with “marbled” state, which is difficult to reason about, debug, or apply any kind of static analysis to.

                                                                                                                                                                                                                                                                    2. 2

                                                                                                                                                                                                                                                                      In all honesty, you sound quite apologetic to what could be arguably considered objectively bad design.

                                                                                                                                                                                                                                                                      Attaching methods to types essentially boils down to scattering data (state) all over the code and writing non pure functions. Why honestly cannot understand how anyone would think this is a good idea. Other than being influenced by trends or cults or group thinking.

                                                                                                                                                                                                                                                                      Almost the same could be said about inheritance. Why would fiting a data model in a unique universal tree be a good idea? Supposedly to implicitly import functionality from parent classes without repeating yourself. Quite a silly way to save a line of code. Specially considering the languages that do it are rather verbose.

                                                                                                                                                                                                                                                                      1. 5

                                                                                                                                                                                                                                                                        Why honestly cannot understand how anyone would think this is a good idea. Other than being influenced by trends or cults or group thinking.

                                                                                                                                                                                                                                                                        Here’s a pro tip that has served me well over many years. Whenever I see millions of otherwise reasonable people doing a thing that is obviously a terribly stupid idea, it is always a lack of understanding on my part about what’s going on. Either I am blind to all of the pros of what they are doing and only see the cons, or what they’re doing is bad at one level but good at a different level in a way that outbalances it, or they are operating under constraints that I don’t see or pretend can be ignored, or something else along those lines.

                                                                                                                                                                                                                                                                        Billions of lines of successful shipped software have been written in object-oriented languages. Literally trillions of dollars of economic value have been generated by this software. Millions of software developers have spent decades of their careers doing this. The though that they are all under some sort of collective masochistic delusion simply does pass Hanlon’s Razor.

                                                                                                                                                                                                                                                                        1. 1

                                                                                                                                                                                                                                                                          To be honest, the more I study OOP (or rather, the hodgepodge of features and mechanisms that are claimed by various groups to be OOP), the less room I see for a genuine advantage.

                                                                                                                                                                                                                                                                          Except one: instantiation.

                                                                                                                                                                                                                                                                          Say you have a piece of state, composed of a number of things (say a couple integers, a boolean and a string), that represent some coherent whole (say the state of a lexer). The one weird trick is that instead of letting those be global variables, you put them in a struct. And now you can have several lexers running at the same time, isn’t that amazing?

                                                                                                                                                                                                                                                                          Don’t laugh, before OOP was popular very prominent people thought it was a good idea to have global state in Lex, Yacc, or error handling (errno). So here’s my current guess: the success we attribute to OOP doesn’t really come from any of its overly hyped features. It comes from a couple very mundane, yet very good programming practices it adopted along the way. People attributed to the hyped stuff (such as inheritance) a success they have earned mostly by avoiding global variables.

                                                                                                                                                                                                                                                                          Abstract data types are amazing, and used everywhere for decades, including good old C. The rest of OOP though? Contextual at best.

                                                                                                                                                                                                                                                                          1. 1

                                                                                                                                                                                                                                                                            It has been the opposite for me.

                                                                                                                                                                                                                                                                            • typecast everything to and from object in early versions of java
                                                                                                                                                                                                                                                                            • EJBs 2
                                                                                                                                                                                                                                                                            • Bower package manager. Its creator wrote on stack overflow that he was confused when he created the project and that it was essentially useless.
                                                                                                                                                                                                                                                                            • Ruby gems security incident
                                                                                                                                                                                                                                                                            • Left pad fiasco
                                                                                                                                                                                                                                                                            • Apache web server htaccess configs

                                                                                                                                                                                                                                                                            I could go on with more esoteric examples to an ever growing list.

                                                                                                                                                                                                                                                                            All these had criticism screaming long before they happened: why?

                                                                                                                                                                                                                                                                          2. 3

                                                                                                                                                                                                                                                                            Many decisions are only clearly good or bad in retrospect.

                                                                                                                                                                                                                                                                        2. 6

                                                                                                                                                                                                                                                                          Inheritance is the biggest thing missing, and for good reason.

                                                                                                                                                                                                                                                                          That reason being “inheritance was the very first mechanism for subtyping, ADTs, and code-reuse, and people using it got ideas for better mechanisms from it.” ;)

                                                                                                                                                                                                                                                                          1. 1

                                                                                                                                                                                                                                                                            Exactly!

                                                                                                                                                                                                                                                                          2. 3

                                                                                                                                                                                                                                                                            The first versions of Simula and Smalltalk didn’t have inheritance either. Self and other prototypal object-oriented languages don’t use traditional inheritance either. We still call all of them object-oriented.

                                                                                                                                                                                                                                                                            Honestly, it’s well beyond time that we retire all programming language paradigm terms. Modern languages simply aren’t organized into paradigms they way older simpler languages were.

                                                                                                                                                                                                                                                                            It’s like we’re looking at a Honda Accord and arguing over whether it’s a penny farthing or a carriage. The taxonomy no longer makes sense.

                                                                                                                                                                                                                                                                        3. 1

                                                                                                                                                                                                                                                                          Ah yes and that’s why it’s ripe to have a come back. :)

                                                                                                                                                                                                                                                                          Seriously though I expect that the next incarnation will be “oop without inheritance” or something. Probably combined with some large corporation “inventing” gc-less memory management.

                                                                                                                                                                                                                                                                          1. 2

                                                                                                                                                                                                                                                                            The good parts of OOP never really left. We already have that exact language: Rust. It has formal interfaces (Traits), encapsulation, polymorphism, and gc-less memory management.

                                                                                                                                                                                                                                                                            1. 10

                                                                                                                                                                                                                                                                              The main thing about OOP that needs to die is the idea that OOP is a coherent concept worth discussing on its own. Talk about the individual concepts as independent things! It’s much more productive.

                                                                                                                                                                                                                                                                              1. 1

                                                                                                                                                                                                                                                                                Talk about the individual concepts as independent things!

                                                                                                                                                                                                                                                                                IMO OOP these days really means inheritance and an object lifecycle. All the other concepts aren’t really unique to OOP.

                                                                                                                                                                                                                                                                                1. 3

                                                                                                                                                                                                                                                                                  I think “OOP” generally means “features of object-oriented languages that I don’t like” to a lot of people. The people using those languages don’t generally get into paradigm arguments.

                                                                                                                                                                                                                                                                                  (Personally, I consider inheritance to be common in OOP languages but not a particularly interesting or salient part of them. Many early OOP languages didn’t have inheritance and prototypal ones have an entirely different code reuse model.)

                                                                                                                                                                                                                                                                                  1. 1

                                                                                                                                                                                                                                                                                    For some people “OOP” means “features of languages I do like”. For instance I’ve seen people include templates/generics/parametric polymorphism and unnamed functions as core parts of OOP… having learned CamlLight (OCaml without the “O”) in college, I confessed I was quite astonished.

                                                                                                                                                                                                                                                                                  2. 2

                                                                                                                                                                                                                                                                                    You say that but it means different things to different people. I don’t disagree that your definition would be a good one if you could get people to agree on it, but I can’t assume that when other people say “OOP” that’s what they’re talking about.

                                                                                                                                                                                                                                                                            2. 1

                                                                                                                                                                                                                                                                              I think it will come back, rediscovered as something new by a new generation disillusioned with whatever has been the cool solves-everything paradigm of the previous half decade. Perhaps this time as originally envisaged with a “Scandinavian school” modeling approach.

                                                                                                                                                                                                                                                                              Of course it never left as the first choice for one genre of software… the creation of frameworks featuring default behavior that can be overridden, extended or changed.

                                                                                                                                                                                                                                                                              Those languages you mention (Go, Zig, Rust) are primarily languages solving problems in the computer and data sciences, computing infrastructure and technical capability spaces. Something is going to be needed to replace or update all those complex aging ignored line-of-business systems.

                                                                                                                                                                                                                                                                            3. 11

                                                                                                                                                                                                                                                                              There isn’t really any need to “hype” DSLs because they’re already widely used in all domains of programming:

                                                                                                                                                                                                                                                                              • front end: HTML / CSS / JavaScript, and most JS web frameworks introduce a new DSL (multiple JSX-like languages, Svelte, etc.)
                                                                                                                                                                                                                                                                              • back end: a bajillion SQL variants, a bazillion query languages like Redis
                                                                                                                                                                                                                                                                              • builds: generating Ninja, generating Make (CMake, Meson, etc.)
                                                                                                                                                                                                                                                                                • there at least 10 CI platforms with their own YAML DSLs, with vars, interpolation, control flow, etc.
                                                                                                                                                                                                                                                                              • In games: little scripting languages for every popular game
                                                                                                                                                                                                                                                                              • Graphics: scene description languages, shader languages
                                                                                                                                                                                                                                                                              • Compilers: LLVM has its own TableGen language, languages for describing compiler optimizations and architecture (in the implementation of Go, a famously “not DSL” language), languages for describing VMs (Ruby)
                                                                                                                                                                                                                                                                              • Machine Learning: PyTorch, TensorFlow, etc. (these are their own languages, on top of Python)
                                                                                                                                                                                                                                                                              • Distributed computing: at least 10 MapReduce-derived frameworks/languages; there are internal DSLs in Scala for example, as well as external ones
                                                                                                                                                                                                                                                                              • Mathematics and CS: Coq, Lem, etc.

                                                                                                                                                                                                                                                                              All of these categories can be fractally expanded, e.g. I didn’t mention the dozens of languages here: https://github.com/oilshell/oil/wiki/Survey-of-Config-Languages – many of which are commonly used and featured on this site

                                                                                                                                                                                                                                                                              If you think you don’t use DSLs, then you’re probably just working on a small part of a system, and ignoring the parts you’re not working on.

                                                                                                                                                                                                                                                                              ALL real systems use tons of DSLs. I think the real issue is to mitigate the downsides

                                                                                                                                                                                                                                                                              1. 1

                                                                                                                                                                                                                                                                                Oh yes but at the same time if you haven’t seen the hype for DSLs then you haven’t spent long enough in the industry to go through that part of the hype cycle. DSLs are what they are and it looks like we might be entering a hype cycle where people want to make them out to be much more.

                                                                                                                                                                                                                                                                                1. 3

                                                                                                                                                                                                                                                                                  I don’t agree, I’ve been in the industry for 20+ years, there are plenty of things more hyped than DSLs (cloud, machine learning, etc.)

                                                                                                                                                                                                                                                                                  DSLs are accepted standard practice, and widely used, but often poorly understood

                                                                                                                                                                                                                                                                                  I’m not getting much light from your comments on the subject – you’ve made 2 claims of hype with no examples

                                                                                                                                                                                                                                                                                  1. 2

                                                                                                                                                                                                                                                                                    Here’s an example of recent hype https://www.codemag.com/Article/0607051/Introducing-Domain-Specific-Languages

                                                                                                                                                                                                                                                                                    Here’s some hype from the year 2000 https://www.researchgate.net/publication/276951339_Domain-Specific_Languages

                                                                                                                                                                                                                                                                                    Arguably the hype for 4GLs was the prior iteration of that specific hype.

                                                                                                                                                                                                                                                                                    I’m not arguing that DSLs are bad - I’m saying that they’re one of the things on the roster of perfectly good things that periodically get trumpeted as the next big thing that will revolutionize computing. These hype cycles are characterized by attempts to make lots of DSLs when there isn’t a strong need for it or any real payoff to making a language rather than a library.

                                                                                                                                                                                                                                                                              2. 4

                                                                                                                                                                                                                                                                                I know it might sound a bit controversial, but the way I see it we need to reach a new level of abstraction in order for large-scale software development to be sustainable. Some people might say AI is the way forward, or some other new programming technique. Either way I don’t think we’ll get there by incrementally improving on the paradigms we have—in order to reach the next level we’ll have to drop some baggage on the way up.

                                                                                                                                                                                                                                                                                1. 4

                                                                                                                                                                                                                                                                                  I mean, humans aren’t getting better at groking abstraction, so I don’t know that “new levels of abstraction” are the way forward. Personally, I suspect it means more rigor about the software development process–if you’re building a tall tower, maybe the base shouldn’t be built with a “move fast and break things” mentality.

                                                                                                                                                                                                                                                                                  1. 3

                                                                                                                                                                                                                                                                                    Groking abstractions isn’t the problem, at the end of the day abstractions are just making decisions for the users of an abstraction. Over-abstraction is the root of many maintainability woes IMO, the more a programmer knows what’s actually going on underneath the better, but only to the degree that it’s relevant.

                                                                                                                                                                                                                                                                                  2. 3

                                                                                                                                                                                                                                                                                    I’ve heard it before. DSLs have their place, and some people love them while others hate them. This is one of a rotating cast of concepts that you’ll eventually see rehyped in 10 years.