[HN Gopher] Strong static typing, a hill I'm willing to die on
       ___________________________________________________________________
        
       Strong static typing, a hill I'm willing to die on
        
       Author : tasn
       Score  : 321 points
       Date   : 2023-10-04 12:49 UTC (10 hours ago)
        
 (HTM) web link (www.svix.com)
 (TXT) w3m dump (www.svix.com)
        
       | bspammer wrote:
       | Asking someone to maintain an untyped codebase is like asking
       | them to play a game without telling them any of the rules.
        
         | globular-toast wrote:
         | I agree, for an _untested_ , untyped codebase. Unit tests are
         | more valuable than types IMO.
        
           | occz wrote:
           | Luckily, you don't have to trade off between them, and
           | neither replaces the other.
        
         | riskable wrote:
         | Your statement reminds me of the spoon scene in The Matrix:
         | Instead of trying to bend the code to fit within the confines
         | of its types simply try to realize the truth... Static types
         | are just _more code_. They 're extra conditions that we apply
         | to things like function signatures and variable definitions
         | instead of adding conditional checks where it matters.
         | 
         | "Aha!" you say, "but by enforcing conditional checks at
         | variable definition and inside function signatures we don't
         | _have_ to check them ourselves in our code and the compiler
         | itself can check them to ensure correctness and optimize
         | performance! "
         | 
         | ...and I'd agree with that sentiment but I'd also add that by
         | having to reason about your types _constantly_ you 're adding a
         | non-trivial amount of mental overhead when structuring your
         | code. For some people _that 's how they reason about their code
         | anyway_ but for others, having to consider whether or not a
         | number is a `u8`, `u32`, or `usize` adds a _lot_ of complexity
         | to the code that could very well be entirely unnecessary
         | depending on the use case.
         | 
         | Consider, for example a program that's meant to be executed on
         | the command line that takes two numbers and adds them together.
         | No matter what language you use you have to convert the raw
         | string input into a numerical type before performing the
         | addition.
         | 
         | In Python you have a simple function, `int()` that will happily
         | turn any string consisting of numbers into a proper integer
         | that can be used for math operations. If it gets something that
         | isn't a number it'll throw an exception which is trivially easy
         | to detect and wrap in a `try`/`except` block with a user-
         | friendly error message. If we wanted to support floating point
         | numbers we could _just use_ `float()` and the code would
         | otherwise be exactly the same.
         | 
         | In strongly-and-statically-typed languages this same process
         | involves _considerably_ more overhead. Before we can select a
         | function to convert a string into a number we must first pick a
         | numerical type and before we can do that we must think real
         | hard about how big of a number we 're going to support in this
         | application. Our function signature(s) could also get
         | complicated because, "wait: what _type_ of string are we going
         | to get from the command line? " Something as simple as adding
         | two numbers becomes complicated really quickly!
         | 
         | Comparing the two ways of handling things (strongly, statically
         | typed VS strongly, dynamically typed), Python ends up the clear
         | winner a lot of the time because you got the job done without
         | having to think as much, with less code that's super easy to
         | reason about _even though it didn 't use static typing_.
         | 
         | The other problem is that when you write such trivial programs
         | in strongly, statically-typed languages like C, C++, Rust, etc
         | it requires a lot more mental overhead to look at the code to
         | figure out what's going on/how it works (though with Rust, less
         | so because there's not 1001 awful ways to do things haha).
        
           | handsaway wrote:
           | > Before we can select a function to convert a string into a
           | number we must first pick a numerical type
           | 
           | Except this has literally nothing to do with static typing
           | and everything to do with whether or not the language you're
           | using cares about numeric types.
           | 
           | For instance in typescript you'd just have `number` as the
           | type. You could conceive of a dynamically typed language like
           | python where adding a u8 to a u32 would cause a runtime
           | error. In which case it sure would be nice to have the
           | compiler tell you to convert before you called a function.
           | 
           | >The other problem is that when you write such trivial
           | programs
           | 
           | If only I had a career writing trivial programs that would
           | make a lot of things easier.
        
           | valcron1000 wrote:
           | > In Python you have a simple function, `int()` that will
           | happily turn any string consisting of numbers into a proper
           | integer that can be used for math operations.
           | 
           | For starters this is not the case, it does not work on a
           | string of numbers:                      >>> int("123 890
           | 123")         Traceback (most recent call last):
           | File "<stdin>", line 1, in <module>         ValueError:
           | invalid literal for int() with base 10: '123 890 123'
           | 
           | > Before we can select a function to convert a string into a
           | number we must first pick a numerical type and before we can
           | do that we must think real hard about how big of a number
           | we're going to support in this application
           | 
           | Aren't you doing the exact same thing in Python by picking
           | `int()` over `float()`?
           | 
           | > what type of string are we going to get from the command
           | line?
           | 
           | Well, this might be the case for system languages, but most
           | have a single `String` type.
           | 
           | Here is the program you described in Python
           | def main():             n1 = input()             n2 = input()
           | sum = int(n1) + int(n2)             print(sum)
           | 
           | And here it's in Haskell                   main = do
           | n1 <- getLine           n2 <- getLine           let sum =
           | read n1 + read n2           print sum
           | 
           | Accepting a single line of numbers is not much different
           | main = do           nums <- words <$> getLine           let
           | res = sum $ map read nums           print res
           | 
           | I didn't think much about it, it's not a lot of code and I
           | guess it's easy to reason about?
        
       | frou_dh wrote:
       | Trust the science on this.
       | 
       | Wait, I've never looked at it. I guess that's why I used the word
       | trust. Surely it confirms my preferences.
        
       | Luctct wrote:
       | Is that a promise? Are you people really going to die? How soon?
       | Any chance you die by the end of this week?
        
         | dang wrote:
         | Hey, could you please review
         | https://news.ycombinator.com/newsguidelines.html and use HN in
         | the intended spirit? You broke that badly with this post, and
         | we're trying for something else here.
        
       | victorNicollet wrote:
       | I think there are at least two ways to write safe and robust
       | code, one being to rely on static types to provide automatic
       | guarantees, and another being to structure the program in a way
       | where tests reveal errors immediately. They are mutually
       | incompatible, and so different from one another that few people
       | can be experts at both, but I don't think one is objectively
       | inferior to the other.
       | 
       | Both styles require code to be disciplined, and undisciplined
       | code cannot be caught by compilers, linters or automatic tools,
       | it has to be through code review (or experience and sheer
       | willpower). It's easy to think of examples where a lack of static
       | types would allow brittle code to be written, but it's important
       | to question whether that brittle code may be considered
       | unacceptable by someone experienced in working without static
       | types, in the same way that code using a Dictionary<string,
       | object> instead of an actual type would be considered
       | unacceptable by a type-safety practitioner despite being
       | (technically) type-safe.
        
         | evrimoztamur wrote:
         | Why are they incompatible?
        
           | victorNicollet wrote:
           | For example, with static typing one would define many
           | different complex types over the program, in order to have
           | the compiler enforce the many different constraints (here the
           | value can be null, but not there ; these two values must be
           | provided together ; and so on). Things like structural typing
           | or algebraic data types even allows the creation of unnamed
           | types on the fly. When sum types are used, conditional
           | operators will be used to deconstruct these in a type-safe
           | way, resulting in many branches.
           | 
           | With dynamic typing, one would have only a small number of
           | very different types, because having many types increases the
           | risk of using the wrong one, and having similar types makes
           | it harder to notice that the wrong one is being used. The
           | types must be very simple, because deconstructing complex
           | types requires having branches, and branches should be kept
           | to a minimum because they are hard to cover properly with
           | unit tests.
        
       | kakadu wrote:
       | The embracing of Typescript and type hints pretty much solidifies
       | the case against dynamic typing for complicated projects.
       | 
       | We have projects in java7 still which span thousands of LoC and
       | juniors can just jump in using their IDE and make _some_ sort of
       | contribution.
       | 
       | With python this takes much longer.
        
         | dartos wrote:
         | Is typescript strong typing though?
         | 
         | I've been through several typescript projects where 'as unknown
         | as any' makes me wish we didn't even have typescript in the
         | first place.
         | 
         | If you can't trust the type system it's worse than not having
         | one :/
        
           | agos wrote:
           | if you abuse the type system enough, most languages will have
           | weaker typing.
           | 
           | "the language" is not enough per se, you have to use the
           | tools it gives you to gain some advantage: those projects
           | were clearly actively avoiding strong typing, for whatever
           | reason
        
             | dartos wrote:
             | In js land some packages don't have strong types or, worse,
             | wrong handmade types. 'as unknown as any' is kind of needed
             | in those cases.
        
           | Tade0 wrote:
           | > Is typescript strong typing though?
           | 
           | The term "strong typing" doesn't have a clear definition to
           | begin with.
           | 
           | Other terms which it often substitutes do, e.g. static
           | typing, sound type system, decidable type system etc.
        
           | master-lincoln wrote:
           | apparently the words strong and weak typing have no agreed
           | upon definition so they can not be meaningfully discussed
           | without stating your definition.
           | 
           | e.g.
           | https://perl.plover.com/yak/12views/samples/slide045.html
        
             | rpdillon wrote:
             | Wow, that's a fairly eye-opening post! I have always used
             | definition 5 for strong typing. I would love to know where
             | the other definitions come from.
        
           | ng12 wrote:
           | You can write bad code in any language.
        
             | master-lincoln wrote:
             | I think this comment doesn't add to the discussion. It's
             | like saying you can kill yourself in any vehicle. Might be
             | true (or maybe not), but doesn't add to the discussion of
             | vehicle safety.
        
             | junon wrote:
             | I'm tired of this adage. Yes, you can. Some languages make
             | it _way, way easier_ to write bad code, though.
        
             | poszlem wrote:
             | This is a thought-terminating cliche and does not add
             | anything to the discussion.
        
           | jrajav wrote:
           | I, too, find tools hard to use after I intentionally break
           | them.
           | 
           | It's unfortunate that Typescript even provides this casting
           | hack, though it's necessary for gradual, optional typing. The
           | very first thing I would do on such a project is spend the
           | time to fix those broken types, because it will pay back in
           | full in productivity after a short time.
        
         | [deleted]
        
         | chpatrick wrote:
         | Python is very much heading towards static typing although it
         | isn't as mature as TypeScript yet.
        
         | wait_a_minute wrote:
         | > We have projects in java7 still which span thousands of LoC
         | and juniors can just jump in using their IDE and make some sort
         | of contribution.
         | 
         | This seems to be a main reason certain people like it. It gives
         | a sense of productivity. However I think it is misguided. It's
         | a false sense of productivity. Can they commit? Maybe, yes.
         | Will it be right? Maybe, and more likely with types to
         | handhold. But does it mean they understand the data model and
         | the domain of the codebase they're working in? No. No typing
         | forces you to know what your code is actually doing.
         | 
         | It takes longer to be productive, but you'll be productive
         | because you know what you're doing. Not because the IDE held
         | your hand.
         | 
         | Widget factories or scrum farms will no doubt like the "ease"
         | of jumping into a codebase that has typing, but I'm not yet
         | convinced it's better or that much better for the experience
         | developer. I need to think on it more. For certain though I've
         | seen enough in my time to know that how quickly a junior can
         | "just jump in and make some sort of contribution" is not a good
         | measurement.
        
           | berkes wrote:
           | "Truly understanding what goes on" and "static typing" are in
           | no way correlated, let alone causations.
           | 
           | You are making a false dichotomy.
           | 
           | It's perfectly possible to work in a dynamic codebase without
           | understanding the domain, business, logic or big picture. And
           | it's just as perfectly possible to build a statically typed
           | codebase that forces you to understand the whole entirety
           | before being able to make a change.
           | 
           | Now, whether it's actually _good_ to enforce true
           | understanding of the Whole, before being able to work on a
           | subset, is another debate. One that, unsurprisingly, has long
           | been proven to be false. It 's why we consider modules,
           | functions, boundaries, coupling, classes, microservices,
           | layers, and so fort and so on.
        
           | BigJono wrote:
           | Dude, duck for cover, lol.
           | 
           | You're 100% right though.
        
           | marcosdumay wrote:
           | Nope. A new dev will need a lot longer to understand a large
           | python codebase than a java one.
           | 
           | In fact, if all the developers change, it's a virtual
           | certainty that none will ever understand the python code,
           | while the odds are about even for java.
           | 
           | (But then, the types aren't the only factor for that.)
        
           | master-lincoln wrote:
           | Your argument sounds like a language should make it hard to
           | understand parts of a codebase without understanding the
           | underlying parts as well. I would argue this goes against the
           | goal of abstracting problems to keep complexity manageable.
           | 
           | Of course abstractions can be misunderstood and misused, but
           | is that an argument for not having them?
        
       | germandiago wrote:
       | Clojure author Rich Hickey disagrees on this. He argues that not
       | only typing is what you need since many of the errors are not
       | typing errors and not even most are (not sure he said that last
       | thing exactly though, talking from the top of my head). The point
       | being that an alternative that can check that and more is better.
       | Also, he argued that types are key/values no matter the formal
       | type if it is the same thing in two systems.
       | 
       | So he created spec. Spec can check more invariants than just
       | typing. Truth to be told, Clojure is functional and one of the
       | goals is to generate test cases from those specs. So it is a bit
       | of a different story probably.
       | 
       | At the end we want correct software.
        
       | waffletower wrote:
       | I think there is strong religious orthodoxy surrounding static
       | typing in computer science, and this article reflects this
       | religiosity. Strong typing proponents often fail to acknowledge
       | alternative beliefs which assert that strong typing paradigms can
       | be less effective and efficient than dynamic typing for many
       | software development contexts. Rich Hickey, the creator of
       | Clojure, is a fairly prominent counter-voice of this debate and
       | provides some interesting context in this presentation:
       | https://www.youtube.com/watch?v=2V1FtfBDsLU&t=2227s
        
       | amelius wrote:
       | How long until Copilot can type-annotate any piece of dynamic
       | code, making the issue mostly irrelevant? Everybody sees the code
       | how they like to view it.
        
       | doktrin wrote:
       | I don't have much to say about the piece itself other than
       | express broad agreeement on what is a fairly common sensical
       | topic, but just gonna say it's interesting how many commenters
       | here are up pontificating on their soapbox while still clearly
       | confused about the distinction between strong and static typing.
        
       | hcks wrote:
       | The static typing hype bubble which started 10 years ago is soon
       | going to burst.
       | 
       | As a falloff expect decades of engineers lamenting overly
       | engineered, overly verbose, overly complex TS legacy apps.
        
         | awestroke wrote:
         | I've never met anybody who prefers JS over TS.
         | 
         | If anything, the dynamic typing bubble is bursting right now.
        
           | meiraleal wrote:
           | > I've never met anybody who prefers JS over TS.
           | 
           | It is because the enterprise TS supporters are too loud.
           | 
           | There are many here saying they consider people that dislike
           | TS to be idiots and they don't lower themselves to discuss
           | with those who think JS is preferable.
           | 
           | They don't wanna argue, we don't wanna argue. Life is great.
        
           | yakshaving_jgt wrote:
           | I prefer JS over TS, and I'm predominantly a Haskell
           | developer.
           | 
           | But then again, I suppose we haven't met.
        
           | panzagl wrote:
           | Have you met anybody who prefers JS over Java?
        
             | iopq wrote:
             | I do, because I don't enjoy having to throw some exception
             | I don't care about just because it's "checked"
        
           | ilrwbwrkhv wrote:
           | I prefer how much cleaner JS code is compared to TS. Some TS
           | errors are such an eyesore that I'm reminded of the ugliness
           | of Microsoft.
        
         | BigJono wrote:
         | And decades of startups created with the next
         | lisp/ruby/python/perl/JS. Sign me up for those. I for one would
         | rather eat a bullet than maintain any of the TS I'm watching
         | people write today.
         | 
         | I don't think we're near the peak yet. We're still on the way
         | up. I've seen $5M projects turn into $50M projects in the space
         | of 5 years and nobody else in my little consulting bubble has
         | noticed at all lol. It shouldn't take 100 devs to build a SaaS
         | with 5 forms and a dashboard but here we are...
        
       | pron wrote:
       | > Yes, typing can be a pain in languages that don't support
       | inference, e.g Java can be tedious
       | 
       | Java has had some type inference for almost 20 years, and local
       | variable type inference (i.e. `var person1 = newPerson();`) for
       | more than five.
        
         | tasn wrote:
         | I had no idea, thanks for letting me know. I'll update the post
         | now.
         | 
         | Java, I'm sorry for swearing at you all these years. :P
        
           | tstrimple wrote:
           | I've been in the same position. Modern Java is a solid
           | language. Most "enterprise" companies are still using Java 8
           | or if you're very lucky Java 12, so you really don't have
           | access to all of the modern functionality and because of that
           | I hated on Java for years. Java programming in the wild is a
           | crap shoot at best.
        
             | Zambyte wrote:
             | > or if you're very lucky Java 12
             | 
             | You mean 11, right? 12 was not an LTS release, and has been
             | out of support for years. The currently supported LTS
             | releases are 8, 11, 17, and the recent 21 release.
             | 
             | https://en.wikipedia.org/wiki/Java_version_history
        
       | beders wrote:
       | The author is basically wrong on all the points. I used to think
       | like that for decades, but in recent years changed my mind
       | completely.
       | 
       | Types lead to less bugs - nope, maybe marginally, but not
       | significantly (see research on that)
       | 
       | Types lead to a better development experience - nope, I have all
       | the definitions and vars in my REPL and so has my IDE. I get
       | completion on all symbols, I can look at call trees, usages,
       | refactor things with confidence, run functions in isolation,
       | replace them, wrap them, all from the REPL and _inside_ my
       | application.
       | 
       | We encode everything in the type system - you can't. You need to
       | do runtime validation.
       | 
       | And good luck untangling your type definitions when your
       | requirements change. That one is the killer. Static types are
       | premature concretions on the domain data model as you understand
       | them now. They will change and if you are unlucky you will have
       | to support multiple different variations of domain models in the
       | same runtime. Good luck with that. Especially if you use
       | inheritance.
       | 
       | Granted, static types give compilers great leverage to optimize
       | code, but, wouldn't you believe: there are dynamically typed
       | languages that have static types as a la card add-on.
       | 
       | But for many, many use-cases, especially enterprise development,
       | a dynamically typed, immutability-first, functional language pays
       | off dividends in the long run.
       | 
       | The categorical error that is made by many strong typing fans is
       | that they assume you would write the same code - just without
       | types. Well, you don't.
        
         | sanderjd wrote:
         | It's an inevitably frustrating debate because everyone has just
         | drawn totally different conclusions from their experiences. For
         | pretty much all your points, my conclusions are the exact
         | opposite. (Except for "You need to do runtime validation" - of
         | course that's true; but you absolutely can avoid doing _most_
         | runtime validation.)
         | 
         | Just to take one somewhat at random:
         | 
         | > _And good luck untangling your type definitions when your
         | requirements change._
         | 
         | I think it is exactly the opposite of the case that static
         | types make it harder to adapt to changing requirements. In
         | every dynamically typed system I've ever worked on, there have
         | been important assumptions about data structures - sometimes
         | checked dynamically in pre- or post- conditions, sometimes only
         | checked in tests, and often simply not checked at all -
         | scattered all around, such that changing requirements
         | necessitated reasoning through the impact of the change on all
         | these implicit assumptions. It was terrifying to make changes.
         | Sure, easy to make a change and start up the application with
         | the new code without a fuss. But to know whether the change
         | broke some obscure codepath I hadn't considered or been aware
         | of? Very difficult! I much prefer a static analysis pass
         | saying, "hey, you changed this interface, did you know this
         | codepath over here relied on that thing you changed?". Static
         | type systems are not the only way to accomplish this, but in my
         | view, they are a much less burdensome way to accomplish it than
         | the level of dynamic validation and testing necessary to do so
         | otherwise.
         | 
         | But again, it's just a frustrating debate, because clearly you
         | have the exact opposite experience! So where does it get us?
         | Nowhere really...
        
         | jjnoakes wrote:
         | > I have all the definitions and vars in my REPL and so has my
         | IDE. I get completion on all symbols, I can look at call trees,
         | usages, refactor things with confidence, run functions in
         | isolation, replace them, wrap them, all from the REPL and
         | inside my application
         | 
         | This is great, but it only works if you are executing the code
         | that you want to inspect/complete/refactor. In my experience,
         | that just doesn't scale well.
         | 
         | > You need to do runtime validation.
         | 
         | Type systems don't eliminate this, sure, but when used
         | correctly, they _drastically_ reduce it, which is extremely
         | useful.
         | 
         | > And good luck untangling your type definitions when your
         | requirements change.
         | 
         | That's the best part - the compiler tells me exactly what I
         | have to fix to get things working again. If I do the same thing
         | in a dynamic language, I have to track things down myself, wait
         | for unit tests to fail (hopefully I have 100% coverage...), and
         | pray that there isn't an escape.
        
       | at_a_remove wrote:
       | Big yawn. I'm comparatively old and have programmed computers for
       | a long, long time as one of those unfashionable "dark matter
       | developers." What a lot of people see as unassailable truths I
       | see as fads. Just as an example, I've never had to go wild about
       | types. One day I will set aside some time to see if they're worth
       | the overhead, but chances are I will not be a convert.
       | 
       | Only _this_ toolchain will be used because it is the only one
       | that makes _sense_. Everything will be so much easier if it we
       | just did it in the functional style. Large programming projects
       | can 't exist without Agile (I've actually heard someone say
       | this). J++! _X_ Will Eat The World. No comments! Verbose
       | comments! If we got the whole team on this one editor, imagine
       | the synergy. Silverlight will take over the interactive web.
       | 
       | If types turn into a big deal and remain that way say, fifteen
       | years from now, then it is probably a Good Idea But Not Strictly
       | Necessary. Whatever it is people are so bound up about, it is
       | likely that programming used to happen without it.
       | 
       | The only constants we have in programming are variables.
        
       | coldtea wrote:
       | > _The question around strong static typing is simple: would you
       | rather work a bit more and get invariants checked at compile-time
       | (or type-checking time for non-compiled languages), or work a bit
       | less and have them be enforced at runtime_
       | 
       | The latter. Other question?
        
       | andrewclunn wrote:
       | There are so many benefits for a front end application (written
       | in javascript) to just assume it will be the backend that does
       | type validation. A new field column added to a table? Cool,
       | update the api layer, but the javascript just gets "the object"
       | and now you have access to it immediately. No need to duplicate
       | your definitions in both code bases, and it's not like front end
       | security is real anyways. Sounds to me like a lot of "I learned
       | to code in some derivative of C" programmers couldn't possibly
       | consider that different languages could be optimized for
       | different use cases and just want all coding to be "what they're
       | used to." Then they moralize it and use shaming language to push
       | it on everyone else. F typescript. I use different languages for
       | different things, and strong typing makes a ton of sense IN MOST
       | INSTANCES, but certainly not all.
        
         | BigJono wrote:
         | People are conflating too many ideas. You're right that there's
         | a huge benefit to that, but it's contigent on you as the dev
         | being able to trust the types coming into your system, you need
         | good docs, and attention to detail as you code.
         | 
         | All the TS devs just conflate JS with "no types" and picture
         | drooling idiots that make random changes without knowing the
         | type of anything (probably because that's what they do without
         | 50 IDE popups to guide them). You're never going to convince
         | them of the values of dynamic typing because they have a
         | different mental model of it in their head.
        
       | rdtsc wrote:
       | That's why we like Python and Elixir but not Javascript which is
       | weakly typed. :-)
       | 
       | Since the author is willing to die for it, they might want to
       | know that they probably meant "dynamically typed". Some
       | dynamically typed languages are strong typed, too!
        
         | tasn wrote:
         | Author here. Please read the post, I actually said "Strong
         | static typing" in the post itself (starting from the first
         | paragraph), it just didn't look good in the title. :)
        
           | rdtsc wrote:
           | That's an important distinction. Why not just use "Static
           | Typing". Yeah, the word "strong" sounds strong and cool, but
           | since it's something you're betting your life on, it doesn't
           | hurt to be a bit more precise.
        
           | dartos wrote:
           | Yeah, but your first point is specifically a weakness of weak
           | types, not dynamic types.
           | 
           | I don't really see any arguments against dynamic typing in
           | there.
           | 
           | Most strong, dynamically typed languages also have good
           | developer tooling (elixir and dialyzer for example) and have
           | built in ways of describing data structures.
        
             | tasn wrote:
             | There's a section about catching everything at compile time
             | rather than runtime which is very much about. I think
             | there's a lot of value at knowing when things go bad at
             | compile time, rather than runtime.
        
           | js2 wrote:
           | Please add static to the title. Most of the comments are
           | referring to the current title and haven't read the article.
        
             | tasn wrote:
             | Yeah, I just did, thanks!
        
       | leroman wrote:
       | As an extension to this, strong typing is a gateway drug to
       | generics.
       | 
       | Strong typing really shines when you have generics, saving bugs
       | at one level above basic types..
        
         | hospitalJail wrote:
         | You got me to look up 'generics'.
         | 
         | I like the idea, feels very pythonic ironically. And I suppose
         | if you don't want the generic, I imagine there is probably some
         | subclass of that which is more restrictive.
         | 
         | Anyway, as a developer I love when people do this. As a
         | developer this sounds like a nightmare to maintain. My
         | coworkers have told me to limit the numbers of 'what ifs' and
         | just roll with it.
        
           | marcosdumay wrote:
           | > feels very pythonic ironically.
           | 
           | Look at duck typing.
        
           | leroman wrote:
           | You can think of generics a meta-language that restricts and
           | documents some behavior one level above the concrete types
           | that you might need.. Lots of benefits, code re-use,
           | documentation as code, less bugs..
           | 
           | Granted it's not always easy and straight forward but that
           | what senior developers in the team are for..
        
             | alickz wrote:
             | Swift makes good use of generics in my experience
             | 
             | https://docs.swift.org/swift-book/documentation/the-swift-
             | pr...
        
               | leroman wrote:
               | I haven't got a chance to use Swift but it looks nice!
        
       | mcv wrote:
       | I just had a moment today. I'm developing a front-end thing in
       | TypeScript. I'm messing around with dates across different data
       | types (date string, Moment, a Neo4j-compatible date type, and
       | Javascript's own Date type). Real fun, as you may understand.
       | Struggling to convert a specific type straight to a js Date, I
       | decide to just `new Date()` and add all the fields I need.
       | `jsDate.setMonth(convert(otherDate.month))`. Red squiggly line
       | appears underneath. I first realise it's a js Date, so I add a
       | -1: `jsDate.setMonth(convert(otherDate.month)-1)`, and the _red
       | squiggly line disappear_.
       | 
       | I feel a moment of horror. _Type coercion._ In front of my very
       | eyes! I quickly added proper conversion everywhere.
       | 
       | I have no problem with dynamic types, but type coercion is the
       | devil.
        
       | bluGill wrote:
       | The problem with strong types is how strong is right?
       | 
       | If you have a truck with a 1000 liter tank on the back the type
       | for the contents liter, or is it something liters_H2SO4 - if you
       | only need to go to a gauge liter is good enough, but if you are
       | doing anything else you do not want to mix the contents up with
       | liters_H2O. Note that is is very likely you will want to have
       | both in the same program in different areas! Of course we can
       | take the tank out of the truck and replace it with a box of iron
       | - so maybe we need an even more generic type that could be either
       | liters or kg?
        
       | craigmoliver wrote:
       | I don't care how many times I see this argument; strong typing is
       | correct. We need to keep beating this drum because every year
       | there are more and more new developers that know nothing. We need
       | to make good one that aren't ignorant of history and what
       | works...because the more things change the more they stay the
       | same.
        
       | AlchemistCamp wrote:
       | I have to wonder if the author has ever used a strong,
       | dynamically typed functional language like Clojure or Elixir or
       | if his dynamically typed language experience is limited to
       | JavaScript, Python and very similar languages.
       | 
       | It's very easy to make up one's mind about something and then
       | completely stop learning.
        
         | tomtheelder wrote:
         | I have worked extensively in Elixir and it only made me feel
         | more strongly that static typing is the way to go. The sheer
         | mental overhead caused by the lack of typing in Elixir is the
         | biggest productivity killer for me when working in that
         | language, and refactoring is almost as much of a nightmare as
         | it is in something like JS.
         | 
         | For me, strong and dynamic is the worst possible combination. I
         | actually need to be precise with types, but the language gives
         | me no help.
         | 
         | I think Elixir has the best combination of runtime and tooling
         | and ecosystem out there, and it's type system is the only thing
         | that prevents me from using it for nearly everything.
        
         | spprashant wrote:
         | Asking because I am curious to learn, how does a language being
         | functional matter here?
         | 
         | As I understand it Python is also strongly typed, while
         | JavaScript is not.
        
           | AlchemistCamp wrote:
           | In Python, variables are mutable and being a class-based OO
           | language, there's often a lot of state that isn't immediately
           | clear when inspecting nearby code.
           | 
           | By working with immutable structs and pattern matching, you
           | can get many (but not all) of the same guarantees you would
           | from static types.
        
       | ceving wrote:
       | Guy L. Steele: "Don't you think it is ironic that type theorists
       | who want to talk about strongly typed languages talk to
       | themselves with an untyped language"
       | 
       | https://youtu.be/dCuZkaaou0Q?feature=shared&t=539
        
         | mrkeen wrote:
         | No I don't.
         | 
         | Now go and rewrite your dynamic language's runtime in a dynamic
         | language.
        
         | ozr wrote:
         | There's been innumerable runtime errors, both tiny and world-
         | altering, as a result.
        
       | Tade0 wrote:
       | > or even worse not enforced even at runtime (JavaScript, I'm
       | looking at you... 1 + "2" == 12).
       | 
       | I'm having trouble taking seriously a post that beats this dead
       | horse.
       | 
       | Sure, it's there. It's even documented in the language
       | specification, but now that we have template literals it's rarely
       | used because truly, what is the expectation when using addition
       | on two variables of different types?
       | 
       | As for static typing:
       | 
       | Grug put it eloquently: https://grugbrain.dev/
       | 
       | > grug very like type systems make programming easier. for grug,
       | type systems most value when grug hit dot on keyboard and list of
       | things grug can do pop up magic. this 90% of value of type system
       | or more to grug
       | 
       | > big brain type system shaman often say type correctness main
       | point type system, but grug note some big brain type system
       | shaman not often ship code. grug suppose code never shipped is
       | correct, in some sense, but not really what grug mean when say
       | correct
       | 
       | In my opinion static typing is useful and I wouldn't start a
       | commercial project without it. That being said I think it's
       | productive to practice programming in dynamically typed
       | languages, because:
       | 
       | -You avoid the sort of type golf that happens with a sufficiently
       | powerful type system(I regret every use of the `infer` keyword in
       | TypeScript).
       | 
       | -The situation forces you to be radically explicit.
       | 
       | -You can explore situations that would normally be
       | hard/impossible to type.
        
       | graypegg wrote:
       | I still bemoan the half-assed RBS type system in Ruby 3. I think
       | Ruby actually had a cool chance to explore what inline type hints
       | would look like in a very meta-programming-y environment. While
       | RBS works, it's a hassle to keep updated, and I think adoption is
       | just going to remain low forever sadly.
       | 
       | Sorbet [0] is close, just wish the syntax wasn't as verbose as it
       | is.
       | 
       | Crystal Language [1] is even closer, I just wish it had better
       | IDE support.
       | 
       | [0] https://sorbet.org/
       | 
       | [1] https://crystal-lang.org/
        
         | berkes wrote:
         | I'm worried that the reluctance of the Ruby community to adopt
         | some typing, might push it further into obscuration.
         | 
         | For me, full time Rubyist for over a decade, it was enough to
         | "jump ship" to Rust and TypeScript. It's one more reason to
         | forego Ruby, I fear.
        
       | throwawaaarrgh wrote:
       | Typing is literally an architectural/design decision. There is no
       | such thing as one single type system that works for all use
       | cases.
       | 
       | It's like saying there's only one good kind of metal fastener for
       | construction. Sometimes you should use nails, sometimes screws,
       | sometimes bolts. It's not like one of those is always superior to
       | the others. You literally should not use a bolt all the time, nor
       | a screw, nor a nail. There are specific engineering requirements
       | and purposes to them all and you can't just mix and match based
       | on your personal preferences.
       | 
       | Well, let me correct myself: you _could_ just use one fastener
       | you prefer, but your building would fall apart six different ways
       | and be a huge pain in the ass to construct. Thankfully we have
       | building codes so people can 't just decide to do that.
        
         | berkes wrote:
         | I doubt anyone is arguing that our bash scripts should be
         | typed, or our quick "remove_currency_from_bank_csv.py" must be
         | statically typed.
         | 
         | The article puts a few cases forward. What the article is
         | discussing, however, is the majority of software. Built in
         | varying teams. Over long periods of time. Large software,
         | complex software.
        
       | irrational wrote:
       | I wonder if most opposition (or even ambivalence) towards strong
       | typing comes from never having used it. If your entire career has
       | been JavaScript, Python, shell scripts, etc.; then you have zero
       | experience with it.
        
         | ilaksh wrote:
         | I taught myself Turbo Pascal in middle school (34 years ago)
         | and C/C++ in high school. (Both typed).
         | 
         | Over the years, I have done programming with C, C++, Java, C#,
         | PHP, Python, OCaml, Lua, Nim, Golang, Rust, Objective-C, Flash,
         | Bash, D, Scala, TypeScript, assembly, PL/SQL, F#, and a few
         | that I am forgetting.
         | 
         | Compile time type checking can definitely make things easier.
         | 
         | But for dynamic languages that I have been programming in for
         | many years to have types shoehorned into them as an
         | afterthought feels like a kludge.
         | 
         | And it's a tradeoff. I got used to developing in Node or Python
         | with vim without auto completion (although I had those things
         | as a kid in IDEs for other languages and they can be great).
         | And without compile time type checks.
         | 
         | You can pass JSON around and literally never do a database
         | migration.
         | 
         | This stuff will lead to more runtime errors initially, but also
         | means more streamlined code. And you have to do thorough
         | testing regardless.
         | 
         | TypeScript might be a choice for a large project with several
         | developers. But I would also argue that an even better choice
         | would be just to use a different language that has the typing
         | system you want built in rather than awkwardly bolted on.
         | 
         | What I see in most TypeScript projects is a half-assed attempt
         | that still results in run time type errors, but with the added
         | "benefit" of an awkward bolted on typing system and the need
         | for more tools as well as losing any dynamic benefit.
         | 
         | They drop the idea of using JSON and make everything related to
         | the database compile time checked if possible. I'm not saying
         | that those checks can't be useful but if are going that route
         | it would make more sense to just drop the dynamic language.
         | 
         | Having all of the dynamism can be a convenience and save you
         | time and effort in other ways. But not if you treat it as a
         | poor man's static language and shoehorn in types in a half
         | assed way using a traditional database.
         | 
         | Part of this is that people think software engineering is about
         | your choice of stack or adding processes to development.
         | 
         | What matters most is probably the feedback loop between the
         | users and the developers. Starting with the requirements
         | engineering. Second to that would be details of the software
         | design and organization. Leveraging existing code effectively
         | can be key. Using descriptive but relatively concise
         | identifiers, short functions, good code organization.
         | 
         | But diving into and evaluating all of that stuff in detail
         | takes effort and a lot of skill and so many make snap
         | judgements based on surface level processes or tool selection.
        
         | siva7 wrote:
         | You probably mean static type checking. I've used strong typing
         | in the first half of my career and have no hard feelings about
         | it. So no, the opposition isn't about no experience with one or
         | the other.
        
         | randomdata wrote:
         | Python is strongly typed. If your entire career has been
         | Python, you will have a lot of experience with it.
         | 
         | Static typing, maybe not so much.
        
           | tonyedgecombe wrote:
           | I wonder if most opposition (or even ambivalence) towards
           | strict typing comes from never having used it. If your entire
           | career has been JavaScript, Python, shell scripts, etc.; then
           | you have zero experience with it.
           | 
           | @irrational Sorry for the plagiarism.
        
       | bjourne wrote:
       | The discussion over whether strong typing is better than weak
       | typing is settled [1], but not over whether static typing is
       | better than dynamic typing. Adherents of static typing thinks
       | that the compiler should check "correctness" by verifying type
       | invariants, adherents of dynamic typing think that is a waste of
       | time.
       | 
       | I'm firmly in the latter camp. Because the compiler can't check
       | _program correctness_ only _type correctness_. Type correctnes is
       | necessary for program correctness, but _NOT_ sufficient. Static
       | typing adherents fail to recognize this, thus falsely believing
       | that static typing guarantees them more than what it actually
       | does (blub).
       | 
       | Consider the article's birthdayGreeting example. Author is happy
       | that static typing catcges the birthdayGreeting("John", "20") bug
       | because "20" is not a number. But birthdayGreeting(" ", 123) is
       | not caught (" " is not a name) and neither is
       | birthdayGreeting("Anna," -12335). birthdayGreeting("Anna" 4.5),
       | though, is caught, which arguably is wrong since 4.5 is an age.
       | 
       | This is actually very important since "type bugs" are trivially
       | easy to catch, while "semantic bugs" can stay undetected for
       | years. An account balance stored as a uint that overflows, a
       | number that must be prime at a certain program location, but
       | isn't, a list that must not be empty, etc. No, not even dependent
       | types can guarantee these invariants.
       | 
       | If you don't believe me, read up on some catastrophic bugs. Those
       | that have caused space ships to explode and cars to crash. To the
       | best of my knowledge, _not a single one_ has been caused by bona
       | fide type errors. In the overwhelming majority of cases, the root
       | cause has been a semantic error.
       | 
       | [1] - Most people don't understand that typing is measured over
       | at least two axes, strong/weak and static/dynamic, and continue
       | to conflate weak typing with dynamic typing. C is statically
       | typed _and_ weakly typed. Python is strongly typed _and_
       | dynamically typed. Javascript is weakly typed _and_ dynamically
       | typed.
        
         | eyelidlessness wrote:
         | Many of your examples could definitely be caught by static
         | types, depending on the type system. But that's less important
         | than...
         | 
         | > This is actually very important since "type bugs" are
         | trivially easy to catch
         | 
         | This, IMO, is _exactly_ why I'm in the static type camp. It's
         | so trivial that you can do it declaratively, inline with the
         | code it's testing, with instant feedback, at every call site
         | and in every downstream expression /statement. A type
         | annotation doesn't mean my semantic/domain logic is sound, I
         | still have to test that. but it could replace dozens of trivial
         | tests _orthogonal_ to the logic I care about... tests which,
         | let's face it, few people are going to write exhaustively
         | otherwise.
        
           | perrygeo wrote:
           | The amount of runtime checks and/or tests required to emulate
           | the guarantees of static types is huge. It's perplexing that
           | some people would rather do that manually.
           | 
           | But to the point of triviality, static types tend to lull
           | developers into a false sense of security. There are limits
           | to their usefulness. You still need both runtime checks and
           | test-time assertions for your logic. You just need less of
           | them and they provide more value per line of code. But I've
           | never seen a type system capable of expressing the entire
           | problem domain in an ergonomic way. Not even close.
           | 
           | For my money, a combination of: static types, property-based
           | testing, unit/integration tests, and an end-to-end test
           | against prod are all required. You can compensate for the
           | lack of one by putting more effort into another but you're
           | really just shuffling the "correctness burden" from one place
           | to another. I like static types because it makes the rest of
           | testing easier. But at some point, you've got to roll up your
           | sleeves and make sure it works IRL.
        
             | prewett wrote:
             | In a dynamically language you _need_ 100% test coverage,
             | because misspelling a variable name turns into a runtime
             | error.
             | 
             | On large projects this can be a problem. I worked on a
             | Python server some years ago, and with every large program
             | that supports exceptions, there's a catch block somewhere
             | that silently eats the exceptions it doesn't process. Well,
             | some modules were loaded dynamically, so my first spelling
             | mistake (and second and third...) took quite a while to
             | debug because things just didn't work, the code didn't get
             | executed, but there were no errors. This also ate syntax
             | errors, too, since that is also an exception. So if you
             | edited the file, you had no idea if things actually still
             | worked (or even compiled!) until you tested the
             | functionality from the file.
        
             | sanderjd wrote:
             | I question this "false sense of security" point. In my
             | experience, people who prefer as much static analysis as
             | possible, mostly based on types, are also more likely to be
             | thinking about invariants and error cases more generally. I
             | would go further to say that anyone who has really adopted
             | a thinking-about-invariants-and-error-cases style of
             | programming has almost certainly become frustrated with the
             | amount of repetitive validation code required to accomplish
             | that in projects with no static analysis of types.
        
         | alpaca128 wrote:
         | > Because the compiler can't check program correctness only
         | type correctness
         | 
         | How is this evidence for it being a waste of time? No solution
         | is perfect yet many are worthwhile.
        
         | sanderjd wrote:
         | The specific examples you chose to illustrate this point are
         | interesting, because to me, it is clear that what you want is a
         | `Name` type that always represents a valid name and an `Age`
         | type that always represents a valid age. Then you can put the
         | validation in a single place (the constructors of those types)
         | and write many methods like `birthdayGreeting` that can happily
         | use values of those types without needing to take on the
         | responsibility of validating them.
         | 
         | I honestly don't know of a good way to implement this pattern
         | without type checking or at least optional type hints and
         | static analysis. Instead, you can do validation of the input
         | values in every single method, which is hugely burdensome, or
         | you can assume callers are passing you valid values and write
         | tests to make sure it isn't too catastrophic if they don't. I
         | don't find either of these solutions satisfying.
        
         | suby wrote:
         | You didn't provide an argument for why static typing is not
         | worthwhile, merely that it won't solve all of your problems --
         | thus, you concluded, dynamic typing is better.
         | 
         | Yet static typing does very much catch issues, so I really
         | don't see where you're coming from with this.
        
           | bjourne wrote:
           | If I'm being generous then maybe 5% of my developer time is
           | spent chasing type errors. And then most of those "type"
           | errors would be errors that no reasonable type system would
           | have a chance of catching - like keys missing from
           | associative arrays. I'm competent enough to not need the
           | compiler to tell me banalities like that age is a number or
           | name a string. The overhead of having to deal with types is
           | many times larger than those 5%.
        
             | _dain_ wrote:
             | _> And then most of those "type" errors would be errors
             | that no reasonable type system would have a chance of
             | catching - like keys missing from associative arrays._
             | 
             | what? in a language with ADTs and exhaustiveness checking,
             | accessing a key from an associative array will give you
             | back an Option type and the compiler will force you handle
             | the code path where the key is missing.
             | 
             | unless I've misunderstood what you meant, this is a
             | _canonical_ showcase of what modern static type systems are
             | good for.
             | 
             | and in your parent post:
             | 
             |  _> a list that must not be empty, etc. No, not even
             | dependent types can guarantee these invariants._
             | 
             | what do you call haskell's NonEmpty then? https://hackage.h
             | askell.org/package/semigroups-0.18/docs/src...
             | data NonEmpty a = a :| [a]
             | 
             | I think you're underestimating what static types can do.
             | it's funny you mention "blub" in that post ...
        
         | marwis wrote:
         | How does [1] in any way support the claim made in first
         | paragraph?
        
         | digging wrote:
         | I don't understand how you go from "this tool only does 90% of
         | the work I need it to" to "I'll do the whole thing by hand"
         | instead of "I'm fine doing 10% by hand".
        
         | kpozin wrote:
         | > read up on some catastrophic bugs. Those that have caused
         | space ships to explode and cars to crash.
         | 
         | One of the most famous type errors in recent history did in
         | fact crash a spaceship.
         | 
         | https://en.m.wikipedia.org/wiki/Mars_Climate_Orbiter#Cause_o...
        
         | MayeulC wrote:
         | > Those that have caused space ships to explode
         | 
         | It's funny you should mention this, as it immediately brings
         | [1] to my mind. This well-known incident was due to type-
         | checking, with acceptable ranges defined ahead of time for some
         | types (which resonates with your comment: make birthdayGreeting
         | accept ranges 1-150 or something, easy to do in ADA).
         | 
         | There are a few more well-publicized issues with spacecraft
         | that could have been caught with better type-checking,
         | including metric/imperial conversions (why not build the unit
         | into a type? Though the fault probably was with integration
         | testing for [2]).
         | 
         | Of course, you are right that type checking can't find every
         | code issue (especially algorithmic), it doesn't replace tests.
         | Instant feedback and type hints are invaluable during the
         | development phase, though.
         | 
         | In your example, one could probably replace the first name
         | string by a person type/object, by the way.
         | 
         | [1]: https://en.m.wikipedia.org/wiki/Ariane_flight_V88
         | 
         | [2]: https://en.m.wikipedia.org/wiki/Mars_Climate_Orbiter
        
           | bjourne wrote:
           | Neither of those were "bona fide _type errors_ ". The fact
           | that both errors ocurred _while using statically typed
           | languages_ shows that. The orbiter failed because inches were
           | interpreted as centimeters. But as both datums were stored as
           | floating point numbers, which they always would be, in any
           | reasonable implementation, static typing wouldn 't have
           | caught anything. The Ariane failure was due to a cast of a
           | double to a short resuling in an overflow. Again, not
           | something static typing can catch because it can't statically
           | check the value of an arbitrary double.
           | 
           | No, even more types is not the solution. It's not pratical to
           | wrap every measurement in a Meter or Inch type
           | (standardization is one issue, is my Meter type the same as
           | your Meter type?) and it doesn't significantly increase the
           | amount of invariants checked. You still have range issues and
           | you still won't get a statically check PrimeNumber type.
           | 
           | I'm not familiar with ADA, but VHDL has similar range
           | constraints which are runtime checked.
        
             | thfuran wrote:
             | >But as both datums were stored as floating point numbers,
             | which they always would be, in any reasonable
             | implementation
             | 
             | It doesn't strike me as inherently unreasonable to use
             | fixed point. At any rate, there are languages with built-in
             | unit systems, so you could declare something like float
             | length = 4.5 <m> and get an error if you try to add it to
             | something in a different unit without having to roll your
             | own dimensional analysis framework.
        
               | bjourne wrote:
               | Of course, fixed point would have been a reasonable
               | choice too. But here is my point. Someone who likes
               | testing could say "This bug would have been caught with
               | better testing". Someone who likes static typing could
               | say "This bug would have been caught if they had used an
               | esoteric type system with support for physical
               | quantities." ... Which no one uses. Thus, you have an
               | argument between something real and realistic, and
               | something imagined and unrealistic.
        
               | thfuran wrote:
               | That you aren't familiar with something hardly makes it
               | imaginary. That exact formulation of unit system is, I
               | think, pretty uncommon, but there are widely used
               | languages (vhdl) where uniting is more directly part of
               | the type system and widely used uniting systems as
               | libraries (boost) where it is not directly a language
               | feature.
        
             | vouwfietsman wrote:
             | > The fact that both errors ocurred while using statically
             | typed languages shows that
             | 
             | Obviously it doesn't, since you can make a statically typed
             | language program where every variable is a string map and
             | every function takes variable args, and have no help from
             | your compiler at any time because every type is always the
             | right type. Sounds stupid, but in fact this is what
             | happened in the examples.
             | 
             | The examples _are_ bona fide type errors, because even
             | though a statically typed language is used, multiple
             | different _types_ of numbers _got the same static type_
             | causing the issue. So the people here were offered the
             | solution to their problem from their domain (two types of
             | numbers), choose to use dynamic typing (make both a float
             | even though they 're different things), causing the
             | compiler to have no way of statically checking their code,
             | and that caused a bug. It's the opposite of a counter
             | example.
             | 
             | It is in fact _the absence of enough typing_ that caused
             | these issues. How much more typing do you need :)
        
             | nyssos wrote:
             | > But as both datums were stored as floating point numbers,
             | which they always would be, in any reasonable
             | implementation, static typing wouldn't have caught
             | anything.
             | 
             | Types are not runtime representations, and any good nominal
             | type system will allow you to avoid this sort of problem
             | easily. For example, this Haskell code
             | newtype Inches = Inches Double deriving Num         newtype
             | Centimeters = Centimeters Double deriving Num
             | a :: Centimeters         a = Centimeters 1.0              b
             | :: Inches         b = Inches 1.0              fine = a + a
             | alsoFine = b + b         mistake = a + b
             | 
             | will give this type error                   Couldn't match
             | expected type 'Centimeters' with actual type 'Inches'
             | In the second argument of '(+)', namely 'b'           In
             | the expression: a + b           In an equation for
             | 'mistake': mistake = a + b
             | 
             | but both `a` and `b` will be doubles at runtime.
        
               | bjourne wrote:
               | That is why I wrote "in any reasonable implementation".
               | Embedding physical quantities in the type system is
               | possible in many language but is not practical. Hence why
               | safety-critical software doesn't contain declarations
               | like yours. For example, what is the type of Inch * Inch?
               | What is the type of Inch / Inch? Sure, perhaps _if_ NASA
               | and their subcontractors had used a common well-developed
               | physical quantities library then the bug could have been
               | caught during compile-time. But I think it is a moot
               | point since most people don 't use such libraries.
        
               | esafak wrote:
               | > For example, what is the type of Inch * Inch?
               | 
               | An area, inch^2.
               | 
               | > What is the type of Inch / Inch?
               | 
               | A unitless ratio?
               | 
               | I don't understand why this is not practical in safety-
               | critical software. nyssos demonstrated what I believe is
               | the right way to do it.
        
               | bjourne wrote:
               | These semantics make the type incompatible with the Num
               | class and attempting to plug your type into, say, a run
               | of the mill ode solver likely won't do what you want. So
               | you have two options. 1) Rewrite all code to become
               | "quantity aware". Multiplying two Matrix[Inch] results in
               | a Matrix[Inch2] and so on. 2) Litter your code with
               | floatToInch and inchToFloat conversions. I think you can
               | see why both options suck? If you really can't, then
               | perhaps try finding some safety-critical software that
               | relies on "physical quantity types" in some form or
               | another?
        
               | esafak wrote:
               | In that case you could make the unit a property of the
               | matrix, and have the second matrix be unitless, or vice
               | versa. The point is you have to do a little more work,
               | and you may not be able to use your existing classes, but
               | it buys you safety.
               | 
               | What languages do you use for these things, so I can
               | understand how they deal with physical quantity types?
        
         | mrkeen wrote:
         | Thanks for mentioning blub I guess.
         | 
         | If you program in a dynamic language, then you have no choice
         | but to _perceive_ all bugs as runtime bugs. Because every bug
         | _you witnessed_ was a runtime bug, so why would types have
         | helped you?
         | 
         | When I program in a typed language, the compiler rejects
         | programs I write _all the time_. Things like: putting code that
         | can 't be rolled-back in the middle of a transaction.
        
         | scarmig wrote:
         | In principal, at least, you could encode all those constraints
         | in the birthday example into the type system. In practice, no
         | one does, partially because existing type systems aren't
         | ergonomic enough to express those constraints for developers to
         | want to use them.
        
         | tasn wrote:
         | > Consider the article's birthdayGreeting example. Author is
         | happy that static typing catcges the birthdayGreeting("John",
         | "20") bug because "20" is not a number. But birthdayGreeting("
         | ", 123) is not caught (" " is not a name) and neither is
         | birthdayGreeting("Anna," -12335). birthdayGreeting("Anna" 4.5),
         | though, is caught, which arguably is wrong since 4.5 is an age.
         | 
         | Author here. I think your examples illustrate my point rather
         | than provide a counter example.
         | 
         | I mentioned later in the post that we validate when creating
         | the type (from e.g. user input) so we know that the `Name` type
         | is always valid (and " ") is not a name. So the type ensures
         | that we have a valid name. So this will definitely be caught in
         | our codebase.
         | 
         | As for birthdayGreeting("Anna" 4.5) and
         | birthdayGreeting("Anna," -12335), number means a float in JS so
         | it actually would be valid, though admittedly I had full
         | integers in mind when writing this. Another example of where
         | stricter typing than what TS providers (which Rust does!) would
         | have helped better define the invariant.
         | 
         | So in short: the problem in the code there was that I was
         | trying to show a simple example, which means I didn't define
         | all the types as strictly as I normally would have, and it
         | surfaced more bugs that would have been caught with types.
        
       | ddellacosta wrote:
       | "Strong typing" was a poor choice of terminology here.
       | 
       | https://en.wikipedia.org/wiki/Strong_and_weak_typing
        
       | derbOac wrote:
       | Strong static typing is better when used well, but worse when
       | it's used poorly.
       | 
       | That last part is the catch, and I've seen plenty of people think
       | they're using it well when they're actually using it very, very,
       | very poorly.
       | 
       | Dynamic typing isn't just a convenience sometimes, sometimes it
       | helps compensate for poorly planned type structures.
       | 
       | Like a lot of things, there are tradeoffs in terms of what types
       | of errors you want to avoid more.
        
         | cocoacat wrote:
         | But in my experience I have also experienced the opposite. I
         | have seen people casually reuse variables by reassigning them
         | to a new type or developing a single function that returns
         | different types. With dynamically typed languages it sometimes
         | feels like you can take messy shortcuts because they let you.
        
       | hospitalJail wrote:
       | I think I agree.
       | 
       | Probably the biggest issue with python.
       | 
       | Seemingly random changes between float64 and object happen when
       | doing unit testing(pandas).
       | 
       | Can't remember the exact situation because I switched to While
       | permanently, but there was some For loop problem. If the data
       | came in as length 1, the for loop would read the individual chars
       | of the string. If it came in as >1 it would iterate through the
       | list.
       | 
       | 15 years ago when I started python, maybe it made sense. Probably
       | ~5-6 'oof that was a bug I wasted time' in 3 years professional
       | use. Today, I find myself forcing types to solve a bug, or at a
       | minimum checking the types as the program progresses.
        
         | ledauphin wrote:
         | yeah, this isn't Python, this is pandas. Run far away from
         | pandas if it's not too late.
        
         | nathan_compton wrote:
         | Pandas is a particularly absurd library.
        
           | falcor84 wrote:
           | Pandas's flexibility is amazing for exploration and
           | prototyping. I'm actually a huge fan of the gradual typing
           | approach, whereby you can start just messing around with
           | stuff in a notebook, and then add the types and the rest of
           | the structure once you are ready to solidify your design.
        
             | nathan_compton wrote:
             | Pandas is a shit show compared to dplyr in R and even
             | compared to polars.
        
             | reportgunner wrote:
             | This is not at all exclusive to pandas.
        
             | dist-epoch wrote:
             | > Pandas's flexibility
             | 
             | What you call flexibility I call non-readability:
             | df.ix[0]        df.loc["x"]        df.loc["x", :]
             | df.iloc[0]        df.x        df.x[0]        df["x"]
             | df[["x"]]        df[df["x"]]        df["x", 0]
             | df["x"][0]        df[:, 0]        # and probably a few more
             | I forgot
             | 
             | If you stop working with it for 2 months you forget what
             | each one is doing and when you are supposed to use it.
        
               | falcor84 wrote:
               | I'm not clear what your argument is. Many of your
               | examples are just syntactical sugar which you can very
               | easily ignore, and even prohibit in your linter.
               | 
               | Also, note that pandas's datafrimes shine when you focus
               | on column operations, if you're finding yourself
               | accessing individual elements by index often, that's
               | usually a sign that you should switch to a more
               | appropriate data structure.
        
               | dist-epoch wrote:
               | > I'm not clear what your argument is.
               | 
               | That when you look at online examples or other people's
               | code you will find all of these variants used.
        
               | falcor84 wrote:
               | Looking at random people's code online is like staring
               | into the abyss. I sometimes see APL code and find myself
               | running in circles and screaming for a bit before I
               | regain my composure, but I don't think that's reason
               | enough for me to complain about APL's design.
        
               | dist-epoch wrote:
               | There are alternatives to Pandas, for example Polars
               | doesn't have this problem.
               | 
               | Sure, doing an operation in Polars can be more verbose,
               | but it really does have just a few ways of doing things.
               | Which in the end is actually more productive, since you
               | don't need to always google the syntax.
        
         | dist-epoch wrote:
         | > If the data came in as length 1, the for loop would read the
         | individual chars of the string. If it came in as >1 it would
         | iterate through the list.
         | 
         | You probably did this:                 for name in ("John"):
         | # "J"         # "o"         # "h"         # "n"            for
         | name in ("John", "Sam"):         # "John"         # "Sam"
         | 
         | The correct form for the first one is this:                 for
         | name in ("John",):         # "John"
        
         | reportgunner wrote:
         | I don't understand how someone can use pandas if they have a
         | choice to use something else. It almost feels like a language
         | of it's own.
        
       | m0llusk wrote:
       | Seems like a matter of degree.
       | 
       | If taken to an extreme then nearly all parameters can be made
       | into unique types. Not just measures, but pixel height measures.
       | Not just pixel height measures, but help panel pixel height
       | measures. Not just help panel pixel height measures, but settings
       | help panel pixel height measures and so on. This may seem like a
       | great way to keep everything well sorted, but ends up being an
       | unhelpful mess that is difficult to maintain. So the question is
       | how exactly in a situation is best to define types, not whether
       | or not to have them or to make them static or whatever else.
       | 
       | And why exactly do you need types in the first place? Lots of
       | projects are messy and involve teams and have work handed off to
       | developers on a regular basis. In that kind of context which is
       | quite common types can be a life saver. There are also short term
       | one person projects that have a high expectation of all work
       | being thrown away soon after. Isn't defining a bunch of types
       | likely to be a waste of time if there is only a brief development
       | effort which is clear and not expected to ever be touched by
       | teams?
       | 
       | Most one size all solutions like static typing have some contexts
       | in which they are either a complete waste of time or need their
       | breadth to be carefully limited.
        
       | michaelfeathers wrote:
       | I always have trouble with takes like this because they are
       | context-free. There are a wide variety of project types and
       | development scenarios.
       | 
       | My nuanced take is that typing is an economic choice. If the cost
       | of failure (MTTR and criticality) are low enough it is fine to
       | use dynamic typing. In fact, keeping the cost of failure low (if
       | you can) gives you much more benefit than typing provides.
       | 
       | Erlang, a dynamic language used to create outrageously resilient
       | systems, is a great example of that for the domains where it can
       | be used.
       | 
       | I'm not a dynamic typing zealot (I like static typing a lot) but
       | I do think that dynamic typing is unfairly maligned.
       | 
       | The cost argument brings the decision down to earth.
        
       | KMag wrote:
       | Some early Lisps had both compiled and interpreted mode, where
       | the interpreter used dynamic scoping and the compiler used
       | lexical scoping. (Which, I presume, caused much developer
       | confusion when code worked fine in the interpreter and got very
       | strange behavior once compiled.) Something analogous (but more
       | sane) could be done with type systems.
       | 
       | I'm very much a fan of strong static typing, but I understand the
       | appeal of dynamic typing, particularly for small scripts and/or
       | prototypes.
       | 
       | Static type checkers (for most languages) are pretty simple
       | theorem provers. For statically typed languages, the compiler
       | (or, I suppose in rare cases, interpreter) rejects any program
       | that it can't prove is free of type errors. An alternative would
       | be to only reject programs that provably contain type errors. The
       | difference in allowed programs covers the cases where the type
       | checker can't prove either way.
       | 
       | So, I'd love a language with a type checker that when ahead-of-
       | time compiling code would refuse to emit libraries/binaries when
       | it couldn't statically prove types were used correctly. In
       | interpreted mode, it would only refuse to load code that it could
       | statically prove contained type errors. Maybe when used within an
       | interactive session, it would still allow (but warn) when code
       | provably has type errors.
       | 
       | As an added bonus, static type guarantees open up more
       | opportunities for the optimizer. A single language offering some
       | range of static guarantees would reduce the number of cases where
       | dynamically typed code gets re-written into a higher performance
       | statically typed language when re-factored into libraries.
       | 
       | If you prefer, go ahead and dynamically type your scripts, etc.
       | However, if/when it comes time to package up parts of your
       | program for wider re-use as libraries, please tighten up the
       | static guarantees of type safety.
        
       | davepeck wrote:
       | Back in the early 2000s, when I was a wee new SDE at Microsoft,
       | there was a shared whiteboard down the hall from my office on
       | which someone had scrawled:
       | 
       | "STRONG TYPING IS SO 90s!"
       | 
       | That missive stayed on the board for over a year. I still think
       | about it from time to time and remember that the tech world's
       | pendulum is always in motion.
       | 
       | Today? I adore TypeScript and I'm pretty excited about the PEP
       | 695 QOL improvements to type annotations in Python 3.12. Where
       | types and tools are concerned, we're in a much better place today
       | than when Nirvana was still the next big thing.
       | 
       | But I won't be surprised at all if in another decade I see
       | "STRONG TYPING IS SO 20s" marked on some corporate whiteboard in
       | Redmond. :-)
        
       | choeger wrote:
       | First of all: I always have and always will be a proponent of
       | statically strongly typed languages (although I would argue that
       | "statically strongly" is redundant here, there are only typed and
       | untyped languages, IMO).
       | 
       | But there's one cost that the author seems to miss and that I
       | didn't fully appreciate for some time. That's the cost of
       | composition. If you look at python you can pretty much compose
       | all possible packages on pypi in your project. All their means of
       | abstraction are usually fully compatible (except for
       | concurrency). Composition often only requires a little bit of
       | glue code.
       | 
       | In a statically typed language's ecosystem you will probably a
       | handful of fundamentally different means of abstraction like
       | functors vs. classes that simply don't compose well together.
       | Hence the fragmentation increases massively.
        
       | heisgone wrote:
       | Strong typing is what allowed me to be a developer. I was never a
       | great developer but I was good enough to be worth my salary. I
       | was not smart enough to maintain a complete mental model of a a
       | weak-typed software but I was able to do fairly complex stuff
       | with the safety net of strong typing. My software developer would
       | have ended much sooner (or never have been) without strong types.
       | I had not other choice but to live or die on that hill.
        
       | ctenb wrote:
       | > There are definitely uses for untyped languages (or language
       | variants), for example they are much nicer when using a REPL, or
       | for throwaway scripts in environments that are already hopelessly
       | untyped (e.g. the shell).
       | 
       | I think nushell disproves this example :)
        
       | mik1998 wrote:
       | Static typing is useful if you are building some program for
       | other people to run that you want to be reasonably robust.
       | However, it does not work well with interactive programming. If I
       | had to declare all the types every time I do something in
       | Mathematica, I'd be severely annoyed for no benefit.
       | 
       | Common Lisp seems to be the best of both worlds, with dynamic
       | strong typing in general and advanced compiler type inference
       | that can correctly point out mismatched types in most cases in
       | SBCL, leading to much easier time programming interactively.
        
         | loup-vaillant wrote:
         | You are complaining about _explicit_ typing.
         | 
         | Try ML (OCaml, F#...) or Haskell, they have type inference. No
         | need to declare types most of the time, but they're there,
         | checked at compile time.
        
       | DevKoala wrote:
       | The best engineers I've met are business objective driven. Strong
       | vs dynamic typing is often a secondary concern. I understand the
       | arguments for each approach, but I've never understood those who
       | are dogmatic about their preferences.
        
       | loup-vaillant wrote:
       | > _There are advantages to not using types, such as a faster
       | development speed_
       | 
       | In my experience, not even that. Static typing _speeds up_ my day
       | to day programming.
       | 
       | You touch this point on later with how IDEs can make your
       | experience nicer with static typing, but I see this even with a
       | REPL: statically detected type errors lead to meaningful error
       | message that are much closer to the actual root cause, and let me
       | fix it quicker than a runtime error would have.
       | 
       | It also liberates my brain from having to think so carefully
       | about types. The compiler is disciplined so I don't have to be. I
       | can move quicker, with the confidence that a huge class of errors
       | will be caught right away.
       | 
       | Static type systems are in my experience easier to use, speed up
       | development, and increase reliability. The costs? So far I've
       | seen only two: they may be harder to learn, and they're harder to
       | implement.
        
         | jodleif wrote:
         | Some would argue that exactly that thinking is what makes the
         | software cleaner and better- rather than mush-mash that passes
         | the compiler. I.e what I'm saying is that it might be good to
         | be thinking about exactly what you're passing in, out and why.
        
           | tines wrote:
           | Isn't this the same argument that says that we should all
           | write assembly, because you should have to think harder and
           | really know what you're doing?
        
           | AnimalMuppet wrote:
           | Of course it's good to think about what you're passing, and
           | why! Nobody disagrees with that.
           | 
           | The issue is, _can_ you think carefully enough, consistently
           | enough, so that you don 't need static types? Can your
           | coworkers - _all_ of them? What about future you, and your
           | future coworkers? What about that time that you 're in a
           | hurry, or going on vacation the next day, and you're not at
           | the top of your game?
           | 
           | If computers have taught us anything, it's that automatic
           | processes are more reliable than manual ones.
           | 
           | Personally, I just inherited a code base that is a decade
           | old. I haven't measured, but I'm pretty sure that it's more
           | than 100,000 lines. My current coworkers have two weeks
           | longer on the code base than I do. Static types make this a
           | _lot_ easier.
           | 
           | And, if your approach to static typing is "mush-mash that
           | passes the compiler", no, static typing may not save you. But
           | dynamic typing wouldn't, either, with that approach.
        
             | jodleif wrote:
             | Can't say I agree. Having spent about 50/50 of my career
             | doing weak/strong typing Im more and more convinced it's
             | very rarely I miss static type-checks. Though I have been
             | blessed with skilled coworkers and sane languages.
        
       | laserbeam wrote:
       | I work a lot in python. I hate it.
        
       | pphysch wrote:
       | I have come to believe that static typing zealots haven't worked
       | seriously on a large variety of (shipped) software projects. I
       | certainly was one when I was in school.
       | 
       | Static typing is a good choice when the system you are
       | implementing is already defined. It's great for implementing a
       | well-defined algorithm or protocol, or a well-studied domain like
       | game engines or financial exchanges or rocket ships. Basically,
       | wherever correctness is necessary and _possible_.
       | 
       | Static typing is a _bad_ choice when the system you are
       | implementing is largely undefined, or actively evolving. That is,
       | "the rest" of the software, where "software correctness" is
       | undefined. Which includes things like a business, a new video
       | game, a website, and scientific research. Because you will waste
       | time building an ontology of types that can't possibly be known
       | at the time, or worse, constrain the natural evolution of the
       | project.
       | 
       | CS students often get a warped perspective of software, where
       | everything is well-defined by their professor or some textbook or
       | RFC or some other smart bloke, and they just have to implement
       | it. In reality, the average software project is not this way.
       | 
       | The end result is Enterprise Java (formerly C macro hell). You
       | get a bunch of CS grads who think static typing is the only
       | answer working on some fuzzy business logic with Java. The
       | conclusion is an unspeakable monstrosity of bad abstractions (and
       | job security).
        
       | taeric wrote:
       | Strong static typing, where most of your data is going across the
       | wire as JSON, is a battle that is largely fought in incoherent
       | ways.
       | 
       | Yes, you should try and use all tools at your disposal. But you
       | should also find that most "data" is far more squishy than you
       | think it is. People don't fall back to phone numbers being
       | strings because they are lazy, they do it because too many of
       | them made the mistake of thinking they could make them a stronger
       | type at some point. Same for names. Or addresses. Or postal
       | codes. All of these things need to be taken from a user, and the
       | only real way we have to do that is by parsing text. And if you
       | make the mistake of making your system so it doesn't store the
       | preparsed text, you are almost certainly going to regret it at
       | some point.
       | 
       | Now, is it best to have a layer that keeps the original user
       | entered text and offers it as a typed set of data to the user in
       | the backend? I certainly think so, but there will be ROI
       | considerations as to how much that matters for your little part.
       | 
       | More, if you are doing evaluations of any heavy sort, you
       | probably want a translation layer to a SAT or other numerical
       | model for calculation. And in that world, the numbers are the
       | abstraction. Trying to do it another way will almost certainly
       | lead to pain. And again, you will do well to have translations
       | from problem to formulation, and from solution space to domain.
       | All of these can largely be helped with types, but far too often
       | the "types" that are focused on are not these.
        
         | galdosdi wrote:
         | > Strong static typing, where most of your data is going across
         | the wire as JSON, is a battle that is largely fought in
         | incoherent ways.
         | 
         | Is it really? Map<String,String> is a totally reasonable type
         | to use in certain cases.
        
         | bluGill wrote:
         | You should still use name and address as types not strings,
         | even though when you look deep you discover they are both
         | strings. It is [almost?] always an error to mix up name and
         | address fields and the type system can enforce this.
        
           | taeric wrote:
           | This is why I said it will be an ROI of where you are. In
           | your javascript just pulling the data out of form fields to
           | send to the backend? Probably not worth it. Somewhere between
           | taking it from the user and processing it? Probably worth it.
           | And sending it to another system? You almost certainly need a
           | translation between your types and theirs. But making a layer
           | that converts between every one of your types to every
           | possible external system? Probably not worth it.
        
         | tasn wrote:
         | Author here. One thing that we do at Svix that I alluded to in
         | one paragraph but I should probably have elaborated on further:
         | thanks to libraries like Serde and Pydantic, we actually follow
         | deserialization is validation (is that a term?), which means
         | that we validate all of the JSON data before even creating the
         | structures in our code.
         | 
         | I guess that's similar to the redis example I gave, but it
         | essentially means that even though we get sent JSON over the
         | wire, we validate it fully and when it gets to our code we know
         | it's a well formatted type. So our code can assume an email
         | type is a valid email, an ID type is a valid ID, etc.
        
           | funnymony wrote:
           | > deserialization is validation
           | 
           | I saw similar, catchy phrase: "parse, don't validate".
           | 
           | https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-
           | va...
        
           | taeric wrote:
           | Right, but you should also take pains to keep the original.
           | All too often the deserialization/validation can also alter
           | the data. In many places, this is fine, I think. In many
           | others, it leads to a ton of confusion.
           | 
           | Edit: I wrote "but you should", I really should have worded
           | that as "and you should". I am wanting to add to your point,
           | not contradict it.
        
             | tasn wrote:
             | Oh yeah, I agree, and I learned it the hard way. In many
             | cases you want to keep the customer format rather than the
             | canonical format. This is why I stopped using Postgres's
             | JSONB for customer data, and exclusively use String/JSON
             | nowadays.
        
           | williamdclt wrote:
           | > deserialization is validation (is that a term?)
           | 
           | "Parse, don't validate >> is a common Googleable idiom
        
           | davedx wrote:
           | It's absolutely a term, and the way to go
        
           | AdamN wrote:
           | What I like that you're doing and what I used to do with
           | Python annotations is that you strongly define types for your
           | higher level business logic - which may be encode quite
           | complex formats.
           | 
           | In many ways, your point is correct and kind of difficult to
           | argue against (i.e. I agree!).
           | 
           | What catches alot of people is they say how important types
           | are but then just use 3 or 4 primitive types and never build
           | custom types on top of them so they don't get much value out
           | of those types aside from preventing the absolute worst
           | runtime errors. The real value of types is having lots of
           | them and evolving them over time as your systems and
           | capabilities mature (US street address, US state, latitude,
           | ... the list goes on for any piece of software).
        
             | digging wrote:
             | Huh! That's given me a lot of insight into why I've had to
             | argue about typing in the past. Thanks for encapsulating
             | that for me.
             | 
             | I've had teammates "agree" and use types only to use the
             | most basic possible types and then confuse themselves later
             | (like, days later). But to me, because I _like_ static
             | typing, it comes very naturally to define types based on
             | business logic, which makes things very easy to work with.
             | And they 're just not thinking in that way. Now I wonder
             | how I can bring them around.
        
           | manicennui wrote:
           | This seems to be a common practice in Go and I've seen it
           | cause requests to be rejected because one unimportant field
           | is wrong. Were we to do this for truly important requests,
           | like lead traffic from third parties, we would lose a lot of
           | business.
        
             | mcesch wrote:
             | If the field is unimportant you'd represent it as such.
             | `Option` or `Maybe` or whatever the equivalent wrapper is
             | in your language of choice.
        
           | cbdumas wrote:
           | > we actually follow deserialization is validation (is that a
           | term?)
           | 
           | Perhaps you are thinking of this great blog post on the
           | subject https://lexi-lambda.github.io/blog/2019/11/05/parse-
           | don-t-va...
        
           | lucasyvas wrote:
           | This is correct - if it's going to error or panic, it should
           | do it at the boundary, not at a random place in the program.
           | It's also much faster to debug where the issue is this way.
        
       | stratigos wrote:
       | This article might be right in an academic sense. I suggest the
       | author and those who believe similarly that its a "hill to die
       | on" rethink their approach and spend 5-8 years doing professional
       | consulting (do not confuse consulting with staff augmentation).
       | You will indeed die on the hill as a business cannot expect
       | everyone it hires to believe the same thing, and you cannot
       | expect to force anyone to use strong typing properly. In short,
       | while you may believe this is the right path, most folks dont
       | care, and all that remains is an extremely complex,
       | antipatterned, mysterious ball of mud that no one wants to work
       | with because no one fully bought into the concept for which you
       | were willing to die.
        
       | cma256 wrote:
       | Static typing won there's no point arguing over it anymore. The
       | issue is the type systems. Someone writing Haskell will have a
       | very different opinion of types versus someone writing Rust
       | versus someone writing Typescript versus someone writing Bash.
       | 
       | That's why you see a negative reaction to static typing. Its the
       | developer experience. Its the error messages. Its the amount of
       | time and mental effort it takes to type something correctly.
       | 
       | If you told me I had to choose between dynamic Python or strict
       | Typescript I would choose Python. I love static typing. I hate
       | Typescript.
       | 
       | So don't die on a hill! Just make better type systems!
        
       | kmstout wrote:
       | I want different things at different times. When I'm first
       | exploring a problem space or figuring out an approach or fooling
       | around in a REPL, dynamic typing is great. In those
       | circumstances, the ability to quickly test (and reject!) ideas is
       | critical, and I don't usually find static typing worth the
       | friction. On the flip side, when I'm working on something longer
       | lived or mission critical, it's important to set the maintenance
       | brigade up for success. That means, among other things, useful
       | doc strings; detailed and informative design notes; and type
       | declarations with the right level of specificity.
       | 
       | Of course, the coin has a thin edge where the situation is a bit
       | of heads and a bit of tails. Count me a fan of gradual typing.
        
       | mtreis86 wrote:
       | What do you call the Common Lisp sort of typing where you can
       | drop hints wherever the machine is guessing at the type, and it
       | will yell at you if you do something dumb with those things. But
       | you don't have to drop hints at all and it will still compile. It
       | is strong when you turn it on but dynamic otherwise. Strongly
       | typed with inference, maybe?
        
         | Filligree wrote:
         | Gradual typing?
        
         | ctenb wrote:
         | I believe the term is gradual typing?
        
       | KaiserPro wrote:
       | Personally I think Strong Static typing is what's required. But
       | with an option to do dynamic typing to avoid faff in certain
       | parts. Strong typing on its own doesn't really solve the problem
       | that the author is describing.
       | 
       | c# pretty much has that nailed. You can do dynamic typing if you
       | want, but you're on your own if it fucks up. Moreover its obvious
       | when you're doing dynamic silliness.
       | 
       | Python is strongly typed, the problem is that its also duck typed
       | and everything is dynamic. Sure there is type hinting, but that's
       | mostly optional and pretty much broken as its not really
       | supported at run time. (unless I've missed something)
       | 
       | What I'd really like is something like perl's "use strict;" in
       | python.
       | 
       | however I don't see that coming anytime soon.
        
       | purpleblue wrote:
       | I did C/C++ for the first 15 years of my career. I generally
       | agree that strong typing is better for everyone.
       | 
       | But when I started working with python, I understood the beauty
       | in it. At first I couldn't believe you could have a system
       | running reliably that was being hit by millions of people around
       | the world, but then that's when I fully appreciated the power of
       | automated testing. I came from an enterprise shrinkwrap
       | environment with 1.5 hr dev cycles, so you can forgive me for not
       | understanding CD/CI at that point.
       | 
       | Yes, you can't detect when changes could cause bugs, but that's
       | where testing comes in. Where I worked, we had to have complete
       | code coverage so that every line of code was tested, and we
       | needed to have a very strong automated testing. Using that method
       | of testing, it made it a lot more predictable.
       | 
       | Sure, bugs can leak through, but having worked in C/C++ for so
       | long, I can assure you that static typing only fixes a certain
       | number of bugs, there are plenty more sources of bugs that just
       | types.
       | 
       | So for the record, I like static typing and generally agree with
       | using it, but I also see the beauty and simplicity in dynamic
       | typing like Python and it's not complete chaos and there are ways
       | to mitigate it.
        
       | mhandley wrote:
       | I wish the languages I use would not only provide static strong
       | typing, but also proper explicit support for units. Automated
       | dimensional analysis would prevent many of the bugs I've written
       | over the years, and there are so many times I've had to think
       | carefully whether a variable is in seconds, milliseconds or
       | microseconds to the point where I always define my own types of
       | these. Or whether a throughput count is in Mbits/second or
       | Bytes/second.
        
       | globular-toast wrote:
       | I wish people wouldn't conflate dynamic typing with weak typing.
       | Python, for example, is dynamically typed, but it's _strongly_
       | typed too. You don 't get bugs like `1 + "2" = "12"` in a
       | strongly typed language like Python.
       | 
       | You can still get runtime bugs, of course, but that kind of thing
       | would manifest as a TypeError or something. All of those bugs
       | could be caught with tests.
       | 
       | I like dynamically typed languages. They are simply the pragmatic
       | choice for the vast majority of code that will ever be written.
       | But being dynamic doesn't mean you can't do types. Python has
       | optional type hinting and checkers like mypy are very good.
       | Common Lisp has features that enable you to declare types and get
       | near-native speed binaries.
       | 
       | These days I do type my Python code for many of the reasons given
       | in the article, but I still enjoy using a dynamically typed
       | language underneath.
        
         | tonyedgecombe wrote:
         | >You don't get bugs like `1 + "2" = "12"` in a strongly typed
         | language like Python.
         | 
         | That's more about type coercion which you can avoid in dynamic
         | languages. See === vs == in JavaScript.
        
       | sakex wrote:
       | Not all type systems are born equal, for instance I'm amazed
       | daily at the lack of type safety in Java/Kotlin
        
       | mpweiher wrote:
       | Well, people have always been fanatical about thing a they are
       | attached to emotionally, rather than rationally.
       | 
       | Fact is: the "types lead to fewer bugs" claim is just a feeling,
       | it is "truthy".
       | 
       | https://blog.metaobject.com/2014/06/the-safyness-of-static-t...
       | 
       | And it's not for lack of trying. You might say the claim has been
       | disproven.
       | 
       | That said,I personally like static types, but primarily for the
       | documentation effect that is, maybe not entirely coincidentally,
       | the only positive effect for which there actually is solid
       | empirical evidence.
        
         | magicalhippo wrote:
         | The fact that strong static types makes the code self-
         | documenting is _the_ reason I vastly prefer it.
         | 
         | It makes me _so much more productive_ , by orders of magnitude.
         | And I say this as someone who has worked extensively in several
         | different languages which covers large parts of this spectrum,
         | like C, C++, Java, Python, JavaScript, TCL and others.
         | 
         | It makes it much easier for me to reason about code I have not
         | recently worked on, be it in the current project or in
         | dependencies. It also means I can be way more focused on the
         | problem at hand, since I'm not constantly having to go on
         | tangent goose chases to figure out what exactly I can do with
         | this object that some function returns.
         | 
         | Sure there's the good, fuzzy feeling when the compile doesn't
         | error out. But that's secondary.
        
         | fnfjfk wrote:
         | Academic papers are often very disconnected from industry
         | reality.
         | 
         | I've worked on reliability at a company everyone has heard of
         | for software that billions use daily. So many bugs would have
         | been blocked by having a type system at all (dynamic languages
         | on backend or JS on web) or by having a less bad type system
         | (changing ObjC to Swift and Java to Kt on mobile). Null
         | pointers/references alone have created so many bugs for us.
         | Bugs that could have been compiler errors.
        
         | mrkeen wrote:
         | > Well, people have always been fanatical about thing a they
         | are attached to emotionally, rather than rationally.
         | 
         | How would you feel if I claimed that you could make emotional
         | arguments _faster_ than you could make rational arguments?
         | 
         | Because that is how this debate _feels_!
         | 
         | I want the simple rationality of my compiler saying "no" if I
         | try to treat my hashmap like an Apple or a String.
        
         | unstruktured wrote:
         | The author of that link references the top 25 bugs, one (#12)
         | of which is Null pointer dereferencing- static typing outright
         | eliminates that bug.
         | 
         | Not to mention that range checking is also fixable by using
         | optionals rather than assuming the existence of a value.
        
         | purpleblue wrote:
         | It leads to fewer bugs of a certain type, but there are plenty
         | of bugs being generated in statically typed languages in
         | different ways.
        
           | mpweiher wrote:
           | The overall bug burden does not change.
           | 
           | Why this is we do not know. But we do know that it is true.
        
         | tomtheelder wrote:
         | Research on this topic is beyond impossible and should be
         | completely disregarded. You cannot possibly attempt to control
         | for variables sufficiently, and I don't think even the most
         | fervent supporters of type systems would argue that they are a
         | dominant factor in code quality and correctness.
        
         | Chabsff wrote:
         | "Types lead to fewer bugs _when making changes to long-lived
         | codebases_ " is not up for much of a debate in my opinion.
         | Preventing regressions is arguably a lot more important than
         | writing a correct first pass, which is what you are evaluating
         | when looking at non-evolving code.
         | 
         | Concretely-speaking, an example of a bug being preventd by a
         | typing system: Removing a field from an object in a large
         | vanilla JavaScript project is _inherently_ a minefield that has
         | caused many bugs in the past, whereas the same alteration in a
         | full Typescript project can be made with confidence.
        
           | mpweiher wrote:
           | It's no longer up for debate, true.
           | 
           | But not in the way you fervently want to believe.
           | 
           | Once again: people have tried to show the truth of this for a
           | long time, and they have consistently failed.
        
             | Chabsff wrote:
             | I'm arguing that the studies linked in that blog post are
             | fundamentally flawed because they only take into account
             | first-pass development, and fail to take long-term
             | maintainability into consideration. And this is silly
             | because that's where the main value of type systems reside.
             | 
             | > This paper presents an empirical study with 49 subjects
             | that studies the impact of a static type system for the
             | development of a parser over 27 hours working time.
        
               | mpweiher wrote:
               | That is not true.
               | 
               | There are some studies like that, but there are others as
               | well.
               | 
               | And remember that all these studies were trying to find a
               | positive effect, but failed to do so.
        
               | Chabsff wrote:
               | Well... It is true of everything in that blog post.
               | 
               | But I am wiling to have my mind changed. I would be
               | really interested in seeing a study that failed to find a
               | benefit of type systems for refactoring tasks in large
               | projects. The example I posted in my initial comment
               | seems pretty open-and-shut to me, so I'm curious.
        
               | mpweiher wrote:
               | > Well... It is true of everything in that blog post.
               | 
               | That turns out not to be the case.
               | 
               | > I would be really interested in seeing a study that
               | failed to find a benefit of type systems for refactoring
               | tasks in large projects.
               | 
               | You're inverting the burden of proof here. People who
               | claim that something is beneficial are the ones who have
               | to show that it is.
               | 
               | Making a claim and then shouting "prove me wrong!" is not
               | how science works. Not even computer science.
        
               | spion wrote:
               | https://www.bmj.com/content/363/bmj.k5094
        
               | [deleted]
        
               | boxed wrote:
               | And yet, if the signal was that strong, it should be
               | clear. It's not.
        
           | taeric wrote:
           | It... should be up for debate? I'm fine taking it as a given
           | in projects I'm running. But I do expect people that have the
           | ability to do so, to debate it. Preferably to study it and
           | find concrete evidence.
        
             | Chabsff wrote:
             | Admittedly, that was a bit hyperbolic on my part.
             | 
             | What I meant to convey is that the matter is settled enough
             | from my point of view that there needs to be a very strong
             | case being made for me to be willing to engage in that
             | conversation.
             | 
             | Thanks for pointing this out, I've amended the comment to
             | clarify a bit.
        
               | mpweiher wrote:
               | > the matter is settled enough
               | 
               | Based on what evidence?
               | 
               | Apart from emotion?
        
               | taeric wrote:
               | Charity to the idea, when boots are on the ground to do
               | the actual work is a terribly place for running that
               | debate. :D Is why I'm in agreement enough for projects
               | I'm working on. I am open to the idea that we find more
               | evidence and/or change our minds for the next project,
               | but "when in Rome" is a good reason to drop the debate
               | and basically declaim what your driving idea is at the
               | start.
        
           | nurple wrote:
           | "Types let me make changes to code I haven't taken the time
           | to understand" is hardly the proof you seem to think it it's.
           | 
           | Removing a field in a data structure is such a big problem,
           | even in typed systems, that the most ubiquitous serialization
           | IDLs, and customer-facing API conventions, don't even allow
           | it.
        
             | Chabsff wrote:
             | And I would contend that anyone claiming "I am capable of
             | taking everything about the code I am tasked to change into
             | consideration" is delusional when it comes to non-trivial
             | projects, including single-dev endeavors.
             | 
             | As far as serialization IDLs and API conventions go, they
             | have the very special constraint of having to provide both
             | forward and backwards compatibility across multiple
             | applications, making them a very poor universal example.
        
               | mpweiher wrote:
               | Is there anyone making that claim? Apart from straw-men?
               | 
               | As an example, I was once refactoring a Java system. The
               | compiler was happy after about a day, the unit tests
               | after three days.
               | 
               | So if you claim your type system is going to keep your
               | refactoring safe, I'd say that I'm not the one being
               | delusional.
               | 
               | And of course unit tests also tend to, _in practice_ ,
               | catch the errors that are caught by types. If you check
               | that a value is equal to 10 rather than 9, you've also
               | implicitly checked that it is not of type PinkElephant.
               | 
               | Now I perfectly understand the _feeling_ that people who
               | are used to the safety-net that static typing appears to
               | give have when encountering a code-base without types. I
               | have the same _feeling_ when encountering a code-base
               | without reasonably comprehensive unit tests (that fail
               | when I poke into the code-base).
               | 
               | The feeling is absolute terror.
               | 
               | I just contend, with reasonably good justification, that
               | this feeling is not particularly justified in the case of
               | static types, because the evidence is just not there.
               | 
               | I haven't checked what the evidentiary status is for unit
               | tests. But then again, I don't make these sorts of
               | categorical claims for unit tests. I just make claims for
               | _my experience_ with unit tests.
        
               | Chabsff wrote:
               | > Is there anyone making that claim? Apart from straw-
               | men?
               | 
               | For every intent and purpose, the person I'm replying to
               | is, with an equivalent level of straw-man-ness, which is
               | why I phrased it this way.
               | 
               | > So if you claim your type system is going to keep your
               | refactoring safe, I'd say that I'm not the one being
               | delusional.
               | 
               | No, I'm claiming that there are entire categories of bugs
               | that are protected this way, not that it provides
               | universal safety.
               | 
               | > And of course unit tests also tend to, in practice,
               | catch the errors that are caught by types. If you check
               | that a value is equal to 10 rather than 9, you've also
               | implicitly checked that it is not of type PinkElephant.
               | 
               | It provides that if and only if the code invoking the
               | tested function is called with arguments using the same
               | semantics as the ones exercised in the tests, which is
               | impossible to enforce in a dynamic language. I'd even go
               | so far as saying that it is axiomatically impossible for
               | unit testing to be a truly reliable tool in such
               | languages because of the lack of precondition
               | enforcement.
        
               | mpweiher wrote:
               | > the person I'm replying to is [making that claim]
               | 
               | Er, no. I certainly wasn't, and the person you were
               | replying to above that was making the opposite claim:
               | that it's harder than that.
               | 
               | And no, the type system doesn't really help all that
               | much, once you have unit tests. Because unlike the unit
               | tests, which checks values (and obviously the types as
               | well, incidentally) the type system only checks the
               | types.
               | 
               | So, trivially, if you mix up addition and subtraction,
               | your unit tests will rightfully balk, whereas your type
               | system is going to be "works for me".
               | 
               | As I wrote elsewhere in this thread, in my personal
               | experience the type system was happy during a large
               | refactor long before the unit tests were. Which means
               | that there was a lot of stuff that the type system
               | missed.
               | 
               | And so if you feel your type system is going to make your
               | refactors safe, well, good luck to you and the poor
               | people who have to use your code.
        
               | Chabsff wrote:
               | To address the unit test stuff: I'm not saying that type
               | systems replace unit tests. I'm saying that unit testing
               | in dynamically typed languages is fundamentally
               | deficient. Or in other words: unit tests are made more
               | reliable by type systems.
               | 
               | Unit tests can only check outputs for the inputs that are
               | provided during testing. Leaving the input unbounded
               | means that they can only provide guarantees for code that
               | conforms to the tested subset of inputs.
               | 
               | I may be able to test that `foo(3) == 4` and foo("foo")
               | == "bar", but since I can't guarantee that `foo({})`, or
               | literally anything else, will never be called, there will
               | always be holes in the safety net they provide. This is
               | something type systems _directly_ address.
               | 
               | > And so if you feel your type system is going to make
               | your refactors safe, well, good luck to you and the poor
               | people who have to use your code.
               | 
               | safer. It makes them safer, not automatically safe.
        
             | spion wrote:
             | I often rename a field in a typed language, just as a way
             | to ask the compiler which parts of the code are affected by
             | or use that field then I continue my reading there.
             | 
             | Its like a grep, except it can, for example, differentiate
             | between "name" (of user) and "name" (of project)
        
         | nercury wrote:
         | The argument for static types is that it makes type bugs
         | impossible because the types are static. There is no emotional
         | attachment other than rage when faced with "but but it does not
         | eliminate ALL the bugs!!!!!!".
        
           | mpweiher wrote:
           | Please read the article.
           | 
           | The objection is not that all bugs aren't eliminated. The
           | objection is that there is no empirical reduction in bugs.
        
         | miloignis wrote:
         | You're making a very strong statement, so we might as well look
         | at extreme cases, namely the formally verified middle-end of
         | CompCert:
         | https://users.cs.utah.edu/~regehr/papers/pldi11-preprint.pdf
         | 
         | I believe this would count as empirical evidence of very strong
         | static typing reducing bugs. I think this points to what many
         | other comments have been getting at, which is that typing is
         | not a binary yes/no question, but a large, multi-axis
         | (static/dynamic, strong/weak) spectrum with lots difference
         | between type systems, _as well as_ big differences in how
         | people apply those type systems to their problem. You could
         | still work in a static, strongly typed language and represent
         | everything as strings, converting back and forth as necessary,
         | but that 's essentially working in a dynamically typed
         | language. You could also take advantage of the tools the type
         | system gives you in order to reap the benefits, creating
         | classes representing the legal values and asserting important
         | invariants.
        
         | iopq wrote:
         | Heartbleed is not a type error in C, but it's a type error in
         | Rust
         | 
         | Rust has a more powerful type system that actually fixes MOST
         | of the memory bugs in production
        
           | mpweiher wrote:
           | And you simply can't have that sort of error in Smalltalk.
           | 
           | -\\_(tsu)_/-
        
             | jjnoakes wrote:
             | You absolutely can.
        
               | mpweiher wrote:
               | That turns out not to be the case.
               | 
               | Smalltalk is memory safe and dynamically type-safe. That
               | is, you cannot invoke an inappropriate operation. You can
               | _try_ to do that, but the system will refuse to do so.
        
               | jjnoakes wrote:
               | It's trivial to store sensitive data in a collection, for
               | example, and then index it with the wrong index when
               | trying to access and export adjacent non-sensitive data.
        
       | shafo wrote:
       | https://youtu.be/Xb0UhDeHzBM
        
         | j16sdiz wrote:
         | I think clojure spec is still typed. It is just not the type
         | other languages uses.
        
           | nightwolf wrote:
           | clojure.spec is explicitly not a type system:
           | 
           | https://clojure.org/about/spec#_expressivity_proof
        
       | xeckr wrote:
       | I gave TypeScript a shot on more than one occasion, and it always
       | ended in frustration after I inevitably encounter some obscure
       | ts(42069) error that I have to research, then find out that a
       | compiler bug is causing the error, and then get told "it's fine,
       | just add @ts-ignore to the top of the file! See, your code works
       | now!"
        
       | [deleted]
        
       | nurple wrote:
       | The social pressure to love static typing notwithstanding (think
       | less of me if you will), the reason I got turned off by it
       | eventually are the ivory towers that invariably get built up
       | around them. I've spent a decade each building software in both
       | paradigms and I now prefer not to use type systems.
       | 
       | I find dynamic typing similar to how unit testing is a forcing
       | function for writing composable code, it acts as a forcing
       | function to writing simple code; simple to read and simple to
       | comprehend.
       | 
       | The argument that it helps inexperienced developers approach the
       | codebase is, IMO, a poor one as it tends to incentivize an
       | iteration loop that lacks understanding and is simply trying to
       | make all the red go away. In fact I find that the type system is
       | often a barrier to truly understanding what's going on as it
       | effectively adds a very domain specific language to every project
       | that has to be learned on top of the language itself.
       | 
       | There are methods to solving the problems presented in TFA that
       | are just as robust as using types and which are simple to
       | understand. Can types be used in a simple way? Sure. Are they
       | ever? Not in my experience. I also don't like autocomplete, so
       | take that as you will.
       | 
       | I may just be a grizzled greybeard screaming "the code _is_ the
       | documentation", but perhaps that is born from my deep
       | dissatisfaction with the current breed of get-big-paycheck-
       | chatgpt-said-it's-right devs that are currently flooding the
       | industry.
        
         | [deleted]
        
         | spankalee wrote:
         | I really don't understand these lines of argument, because they
         | seem to me to be almost entirely _backwards_.
         | 
         | > I find dynamic typing ... acts as a forcing function to
         | writing simple code; simple to read and simple to comprehend.
         | 
         | I find the opposite true. Many super-dynamic patterns are hard
         | to type correctly. Good type systems tend to encourage simpler
         | patters so you get simpler types.
         | 
         | > The argument that it helps inexperienced developers approach
         | the codebase is, IMO, a poor one as it tends to incentivize an
         | iteration loop that lacks understanding and is simply trying to
         | make all the red go away.
         | 
         | Making the red go away is important because the red indicates a
         | problem! This is a lot easier than other ways of discovering
         | the error. Why would you want to discover the error later?
         | 
         | > I also don't like autocomplete, so take that as you will.
         | 
         | This is why I'm with commenters who say they don't trust people
         | who are against static typing... I'm extremely suspect of
         | computer programmers who don't want computers to help them
         | program.
        
           | zsyllepsis wrote:
           | > Making the red go away is important because the red
           | indicates a problem! This is a lot easier than other ways of
           | discovering the error. Why would you want to discover the
           | error later?
           | 
           | I don't think that's what the parent to your comment is
           | arguing. They are arguing that "making the red go away" isn't
           | the goal, rather that correctness is, and that it's easy to
           | conflate the too when you focus too much on the "red" part,
           | and don't pay attention to the "correct" part.
           | 
           | Worded another way, the mantra of "if it compiles it works"
           | can lead to a dangerous false sense of security if you don't
           | understand the limitations of your type system and what parts
           | of your program is may or may not cover completely.
        
         | koonsolo wrote:
         | > I also don't like autocomplete
         | 
         | You must have a crazy good memory. I switch between multiple
         | languages, and autocomplete lets me easily see what variant of
         | a function this library uses again.
         | 
         | You know everything by heart?
        
           | imran-iq wrote:
           | I also don't like autocomplete. The reason being that not
           | having it actually forces me to learn the libraries I am
           | using.
           | 
           | > You know everything by heart?
           | 
           | You eventually reach that point. Do you still look down to
           | see which keys you are typing?
           | 
           | This is also has the nice side effect of pushing you to use
           | libraries that are stable and have good documentation as you
           | can always reference them if need be.
        
             | [deleted]
        
             | lsaferite wrote:
             | My working memory has limits. I consume and use a lot of
             | information on an ongoing basis. The contextual shift from
             | codebase to codebase is already large, add in a language
             | change and I would venture to say that most people need a
             | little assistance to make sure they remember syntax and
             | specific method calls.
        
             | koonsolo wrote:
             | My memory is a leaking bucket. My typing however, is very
             | fast.
             | 
             | Take for example the substring function. I wouldn't know
             | which one it is for JavaScript, Haxe, ActionScript3, C#,
             | Java, Python, C, C++, PHP. I know I used it at one point
             | for all of them.
             | 
             | For languages like JavaScript, Java and C#, it's probably a
             | method, so you can start typing. Might be substring(),
             | might also be substr() or something like that.
             | 
             | For Haxe, I thought it was not a method so I think it's
             | either part of Std or StringTools.
             | 
             | If I use autocomplete, I have it in a few seconds, and I
             | can also see the documentation on the parameters. Is the
             | second parameter an index or a length? To be honest I have
             | no idea. And the good part is, thanks to autocomplete I
             | don't need to know.
             | 
             | Also, if you work in a big codebase, you can't know every
             | class. Needing to dig through code seems such a waste of
             | time.
        
           | leptons wrote:
           | I also hate autocomplete. It just gets in my way.
           | Autocomplete doesn't really work unless you already know what
           | you're going to code, and if you already know what you're
           | going to write the autocomplete prompt just gets in the way
           | and often messes with keyboard entry of what I was typing. I
           | just switch it off, it never saved me any time and just gets
           | kind of annoying.
        
             | spankalee wrote:
             | > Autocomplete doesn't really work unless you already know
             | what you're going to code
             | 
             | Say what? Autocomplete is a godsend for quickly working
             | with new APIs. If you're writing a function that takes some
             | objects that you're not familiar with autocomplete can
             | pretty quickly lead you down a good path.
        
               | leptons wrote:
               | That's not my experience. If I'm working with new APIs, I
               | have the docs up on one screen and the code on the other,
               | and I've probably already copied and pasted the function
               | and parameters into my code from the docs before
               | autocomplete can get in my way. You do read the docs,
               | don't you?
        
         | tasn wrote:
         | I think you make a good point about the ivory towers and the
         | social pressure being a turnoff for adopting certain
         | technologies. Though I also think this doesn't detract from
         | their potential technical merits. As in, a technology can be
         | both great, and have everyone about it be pretentious.
         | 
         | > I find dynamic typing similar to how unit testing is a
         | forcing function for writing composable code, it acts as a
         | forcing function to writing simple code; simple to read and
         | simple to comprehend.
         | 
         | I don't agree with this argument, I think it's akin to saying
         | "I like driving blindfold because it makes me drive slower".
         | You can use linters with limits on line length and number of
         | params if this is a goal for you, no need to go indirect with
         | the restrictions.
         | 
         | I agree that typing is not the only solution, I'm just saying
         | that I think the ROI is massive in types, so I think this
         | should be the first tool people go to. Almost no investment,
         | and a lot of benefit.
         | 
         | I agree with "code is the documentation", I even made a point
         | about documentation in the post, but I argue that typing is
         | part of the code. So "the code is the documentation, and typing
         | is part of the code" is how I'd phrase it.
        
           | sodapopcan wrote:
           | > > I find dynamic typing similar to how unit testing is a
           | forcing function for writing composable code, it acts as a
           | forcing function to writing simple code; simple to read and
           | simple to comprehend.
           | 
           | > I don't agree with this argument, I think it's akin to
           | saying "I like driving blindfold because it makes me drive
           | slower". You can use linters with limits on line length and
           | number of params if this is a goal for you, no need to go
           | indirect with the restrictions.
           | 
           | I was assuming this is more along the lines of writing clear
           | variables names and writing functions that make it obvious
           | what the return value is.
        
         | eyelidlessness wrote:
         | > I find dynamic typing similar to how unit testing is a
         | forcing function for writing composable code, it acts as a
         | forcing function to writing simple code; simple to read and
         | simple to comprehend.
         | 
         | If this were broadly true for most developers using dynamically
         | typed languages, it would be a very compelling argument indeed.
         | But I think there's pretty strong evidence the opposite is
         | generally true: actual types produced to document real world
         | dynamic code tend to be vastly more complex than the equivalent
         | functionality implemented with static types from the outset. In
         | the TypeScript ecosystem, DefinitelyTyped is an excellent
         | source of countless case studies. The types they provide are
         | typically _definitely not_ , as you put it, "used in a simple
         | way". That's not complexity inherent to the type system, or the
         | type definitions as provided; it's complexity inherent to the
         | dynamic code they describe.
         | 
         | Equivalent packages which were statically typed from the outset
         | tend to have much simpler interfaces _because_ the types are
         | defined upfront rather than retconned onto existing APIs. That
         | doesn't necessarily mean their interfaces are _absolutely
         | simple_ , but they're typically _relatively simple_ by
         | comparison.
         | 
         | I'd go so far as to say that you _can't know_ how simple or
         | complex an interface is without specifying it. If "the code is
         | the documentation" (which I agree is a great ideal!), then
         | interfaces without code specifying them are under-documented by
         | definition. The further the code specifying the interface is
         | from the interface itself, the more obscured your documentation
         | is.
        
           | hparadiz wrote:
           | Dynamically typed language have very clear rules. It's not
           | magic. If you know these rules nothing about dynamically
           | typed code is inherently problematic. It's the difference
           | between logic being in the code versus in the run time. You
           | accept hundreds of rule sets built into the run time all the
           | time.
        
             | MrJohz wrote:
             | All programming languages - all computers even - have very
             | clear rules. The complexity in software development usually
             | has less to do with getting a computer to understand its
             | own rules, and more to do with the boundaries between
             | humans and those rules: for example, encoding human ideas
             | into rigid computer rules, or trying as a human to
             | understand the computer rules that someone else has
             | written.
             | 
             | So when you say "if you know these rules nothing about
             | dynamically typed code is inherently problematic", my
             | intuition says "I probably don't know these rules". That
             | goes for some of the basic rules like "the first argument
             | to this function is the haystack, the second is the
             | needle", but it also goes from some of the more complex
             | rules like "functions that take a user ID can also take a
             | user object and extract the ID from that" or "the allowed
             | states for this FSM are X, Y, and Z, and are always written
             | in capital letters". More importantly, a lot of the rules
             | for my difference will not have been written by me, they'll
             | have been written by my colleagues, or else they were
             | written by me, but it was more than six months ago and my
             | memory is a bit hazy on the details.
             | 
             | The point the previous poster was making, I think, was that
             | while the rules may be very explicit (this is, after all,
             | what any programming language is: explicit rules for a
             | computer to follow), they can also be very complex. And,
             | more specifically, the DefinitelyTyped examples show that
             | the rules for dynamic software often tend to be very
             | complex, or at least, complex enough to present
             | difficulties when being modelled by a type system
             | explicitly designed to model dynamic code.
        
         | digging wrote:
         | > The argument that it helps inexperienced developers approach
         | the codebase is, IMO, a poor one as it tends to incentivize an
         | iteration loop that lacks understanding and is simply trying to
         | make all the red go away. In fact I find that the type system
         | is often a barrier to truly understanding what's going on as it
         | effectively adds a very domain specific language to every
         | project that has to be learned on top of the language itself.
         | 
         | This is very interesting and at first blush strikes me as
         | backward. I wish I could sit in your office and see this
         | happening, because I find it hard to imagine and I would love
         | to know what that looks like. (And I have way less experience
         | than you so I'm not saying it can't happen.)
         | 
         | Specifically, I find the domain-specific logic in my field is
         | impossible to grok in dynamically typed codebases, while
         | statically typed ones actually teach the developer what the
         | business logic is.
         | 
         | > I may just be a grizzled greybeard screaming "the code _is_
         | the documentation"
         | 
         | Also confusing to me! In all my experience, static typing is
         | what allows the code to be the documentation. Without it,
         | there's no way to know what properties this object has or why
         | we have a check for this certain property that I thought didn't
         | even exist on this object. (Other than comments - maybe I'm on
         | a weird team but I don't know anyone other than me who leaves
         | comments of any significance.)
        
           | spankalee wrote:
           | Comments are great, but they should usually explain why, not
           | what.
           | 
           | Good, long variable and function names, along with breaking
           | complex expressions into multiple statements with those nice
           | variables names can help the code itself describe the what of
           | the process. And then static types help describe the what of
           | the types of data even more.
           | 
           | That lets you save the comments for more useful things than
           | an ad-hoc type system, like "// We need to do this
           | because..."
        
             | hparadiz wrote:
             | Code coverage reports with complexity score for every
             | function is the best teacher for this. I particularly love
             | how Scrutinizer CI does this.
        
         | graypegg wrote:
         | The social pressure side, I totally get. People get very
         | defensive about this sort of thing, and act somehow personally
         | offended if anyone does the opposite.
         | 
         | I say that as someone that quite likes static types. I don't
         | care, do what you do!
        
         | ransom1538 wrote:
         | When I hit ctrl+save, the code should be instantly ready to
         | test, less than 200ms. Waiting for 30 seconds to see code is an
         | ETERNITY to people that code fast, 1k lines per day. I have
         | been on teams that wait 5m to test code, what a waste. Fast
         | feedback loops in code are critical, just like design, or
         | anything important. Types seem like some weird religion, the
         | people that use them cannot be talked out of it.
        
           | splintercell wrote:
           | I highly recommend you to check out ReScript. Amazingly fast
           | compile times.
           | 
           | Watching typescript teams spent 30 seconds on the recompile
           | is insane for me.
           | 
           | in fact, the whole ocaml family of programming languages are
           | mega fast.
           | 
           | The most important feature of a very fast compile time is
           | that you can load it with types after types and write in your
           | whole mental model, without worrying about your build process
           | slowing down.
        
         | Djeman wrote:
         | Code can not be documentation by meer definition. Code is
         | written in programming language and documentation in spoken
         | language. So documentation has important function of explaining
         | intention of code in non trivial sections. Of course you wont
         | give explanation of CRUD actions or other patterns you are
         | using but business rules get coded and people reading that code
         | need to know where rules come from and what are expectations
         | either directly in code or by reference. Otherwise you revert
         | to finding origin of code in source control and related task if
         | you are lucky to have that level of tracking.
        
         | busterarm wrote:
         | I was going to write a response pretty much exactly like yours.
         | 
         | Also, the domain we're in is engineering. There are no single
         | correct decisions and everything is about trade-offs. And
         | that's good because otherwise our jobs would be the first to be
         | automated out of existence. All of the discussion in this
         | thread about people "thinking less of" other engineers for
         | their opinions/experiences is fucking gross.
        
           | purplerabbit wrote:
           | Your bio says "most people are stupid" -- how'd you arrive at
           | that conclusion without judging people?
        
             | busterarm wrote:
             | There's a chasm of difference between blatantly self-
             | destructive life choices and forgetting that your
             | profession is about making decisions based on multiple
             | options.
             | 
             | Also you only half-quoted me.
             | 
             | It's "... and/or on drugs".
             | 
             | Also people being stupid doesn't mean that I don't consider
             | anything they say. Even a broken clock is right twice a
             | day.
        
           | enraged_camel wrote:
           | >> Also, the domain we're in is engineering. There are no
           | single correct decisions and everything is about trade-offs.
           | 
           | Yep. In my experience, hardliners tend to not be great
           | engineers, even if they have decades of experience.
        
             | JohnBooty wrote:
             | hardliners tend to not be great engineers
             | 
             | 100% agree.
             | 
             | "Strong opinions, weakly held" is okay with me though. I
             | don't call that "hardlining."
             | 
             | Although, sometimes it's hard to differentiate "strong
             | opinions, weakly held" from "strong opinions, strongly
             | held, not open to new ideas."
        
         | danenania wrote:
         | I'm fully a convert to static typing and don't think I'll ever
         | willingly do another project without it, but you make a really
         | good point about how people tend to _always_ go overboard with
         | types. I did this early on in a large TypeScript codebase while
         | learning TypeScript, and now I regret it. I 'm still far better
         | off than I'd be without static types though.
         | 
         | This also happens with tests. It's easy to get wrapped in
         | testing libraries and abstractions and spend way more time than
         | you need to.
         | 
         | The 80/20 rule applies in both areas. You get 80% of the
         | benefit with 20% of the abstraction. It's usually a mistake to
         | try to go beyond this.
         | 
         | Of any popular language I'm familiar with, I'd say Go is the
         | one that follows the 80/20 rule best. It encourages you to
         | focus on solving the problem rather than leading you down
         | rabbit holes of various kinds, including with types. That's not
         | to say Go doesn't have its issues, but it really is excellent
         | at discouraging over-engineering.
        
           | thegeekpirate wrote:
           | Heh, before reaching your last paragraph, I was going to
           | recommend Go as the remedy to your woes. Glad you've
           | discovered it yourself!
        
       | QuadrupleA wrote:
       | As a developer who's written hundreds of thousands of lines of
       | C++, Python, and JS - I don't know! It's not so clear cut. I'm
       | productive in all off them, although Python mostly wins. I
       | wouldn't write a game engine or a video codec with it though.
       | 
       | JavaScript is inconsistent and weird, but Netscape's legacy long
       | since stuck us all into it.
       | 
       | I can see in a very OOP-heavy style maybe, with huge nested
       | classes, that compile/parse time static typing saves a lot of
       | mistakes - but I've come to see OOP as mostly a disaster, and
       | simple functions and structured data almost always win the
       | simplicity and maintainability battle. And modern language
       | servers / IDEs can catch a lot of typing errors during JS /
       | Python development.
       | 
       | I'm persnickety about a lot of programming stuff, but never had a
       | strong opinion about static vs dynamic typing. Both have millions
       | of successful projects under their belt.
        
         | rdedev wrote:
         | In python I mostly code in functional style. Even then types
         | helps me a lot. I make a lot of typos or get the order of
         | arguments wrong. Typing helps me a lot here especially when I'm
         | doing ML. The last thing I want is my training code to crash
         | after it spent 30nmins processing the data. I find pythons
         | gradual typing a really good middle ground for quick
         | prototyping and the type annotate functions once they are
         | mature enough
        
           | boxed wrote:
           | > or get the order of arguments wrong
           | 
           | There's a simple fix for that, just do keyword argument only
           | everywhere you can.
           | 
           | For me the hill I'm willing to die on is that
           | labeled/named/keyword arguments are absolutely necessary and
           | most of the usefulness of types is in fact just a shitty
           | version of labeled arguments (god help you if you have a
           | function where two or more arguments have the same type!)
        
             | rdedev wrote:
             | The small downside to using kwargs is just the extra
             | letters needed to call the function but I can live with
             | that.
             | 
             | As for args with the same type, you can use phantom types I
             | guess but I haven't explored it much in python. I'm pretty
             | interested in the dfdx library in rust which can type
             | enforce matrix or vector operations on it's shape. Stuff
             | like that would really help me
        
               | boxed wrote:
               | It's an advantage imo. Makes the code more readable, and
               | much more robust against bad refactors.
        
         | BobbyJo wrote:
         | To be fair, C++ is a pretty rough language to be productive in
         | generally, type system aside. GC is the single largest
         | productivity enhancement a language can offer. I'd be way more
         | interested in how Golang, with it's much simpler syntax/types
         | (but they're still static) would compare. Even Java would be
         | better, as, even though it's very verbose, the cognitive load
         | for most tasks is a fraction of C++'s.
        
           | kagakuninja wrote:
           | My language evolution went C > C++ > Java > Scala
           | 
           | Java was a huge boost, by eliminating the cognitive load of
           | manual memory management.
           | 
           | Scala can be used as a "better Java" with less verbosity, but
           | also adds a number of extremely useful features; Java has
           | slowly added some of them into the language over the last 8
           | years.
        
             | sureglymop wrote:
             | Have you tried Kotlin? I personally like it a lot as an
             | alternative to Java and Scala. However, I hate any tooling
             | around the JVM based languages. I cannot waste my time
             | messing around with Maven, Gradle, etc.
        
               | kagakuninja wrote:
               | No, I am very happy with Scala, and intend to use it for
               | many years to come.
               | 
               | JVM tooling IMO is fantastic, it is one of the largest
               | open source communities, and there are many options if
               | you don't like Gradle or Maven. Also, as I understand it,
               | the dependency management systems found in languages like
               | Python and Node are horrible in comparison to the JVM,
               | where it is usually not a problem.
        
         | AdamN wrote:
         | You might like this video from WWDC a few years back on
         | protocol-oriented programming (Swift):
         | https://www.youtube.com/watch?v=p3zo4ptMBiQ
        
       | Draiken wrote:
       | The only thing that really frustrates me in this discussion is
       | that it's all about how people "feel" and without empiric
       | evidence.
       | 
       | The research out there found no meaningful difference between
       | both styles (unless there's newer research I haven't seen?) and
       | people keep taunting around how their preferred side is
       | undoubtedly the right one.
       | 
       | That's just like, your opinion man.
       | 
       | Personally I like typed languages but the type systems in
       | languages like TypeScript are simply insufficient. You still end
       | up with runtime bugs because you can't actually use those types
       | at runtime. You can't encode a lot of the runtime logic into the
       | type system so you're still manually checking impossibilities
       | everywhere. I find myself even having to create local variables
       | just to make typescript detect an obvious condition.
       | 
       | If a type system could basically remove the need for me to think
       | about runtime bugs, then that's an absolute killer feature that I
       | doubt anyone would argue against. But most languages don't
       | provide that, so you're stuck in this halfway point where you
       | have all this overhead, some benefits, but you still can't 100%
       | trust your types.
       | 
       | As for why there are no meaningful differences in bugs, speed,
       | etc my guess is that it all evens out. Without the type system
       | safety net you are much more likely to test your code and as a
       | result less bugs go in. On the other side people rely too much on
       | the type system that's not good enough and then still end up with
       | the same amount of runtime bugs. On one side you write code
       | faster, but you have to test more, so it also evens out with
       | writing more boilerplate, but with less tests.
       | 
       | I really wanted some hard research on this, but I know it's a
       | hard one.
        
         | ryandv wrote:
         | A 2018 study [0] found the following:
         | 
         | > Language design does have a significant, but modest effect on
         | software quality. Most notably, it does appear that disallowing
         | type confusion is modestly better than allowing it, and among
         | functional languages, static typing is also somewhat better
         | than dynamic typing. We also find that functional languages are
         | somewhat better than procedural languages.
         | 
         | > The languages with the strongest positive coefficients -
         | meaning associated with a greater number of defect fixes are
         | C++, C, and Objective-C, also PHP and Python. On the other
         | hand, Clojure, Haskell, Ruby and Scala all have significant
         | negative coefficients implying that these languages are less
         | likely than average to result in defect fixing commits.
         | 
         | > The data indicates that functional languages are better than
         | procedural languages; it suggests that disallowing implicit
         | type conversion is better than allowing it; that static typing
         | is better than dynamic; and that managed memory usage is better
         | than unmanaged.
         | 
         | Regarding your comments:
         | 
         | > Personally I like typed languages but the type systems in
         | languages like TypeScript are simply insufficient. You still
         | end up with runtime bugs because you can't actually use those
         | types at runtime.
         | 
         | That's because TypeScript is not actually strongly typed, it is
         | gradually typed; throw in a single "any" type into your TS and
         | all static guarantees are now off. I agree that TypeScript is
         | insufficient, and point to languages like Rust or Haskell (one
         | of the languages with the lowest defect rate in the study [0])
         | that actually do offer static guarantees, and where use of
         | untyped "escape hatches" is far less common and/or is far more
         | judiciously applied.
         | 
         | > If a type system could basically remove the need for me to
         | think about runtime bugs, then that's an absolute killer
         | feature that I doubt anyone would argue against. But most
         | languages don't provide that
         | 
         | Isn't this basically the promise of Haskell, Rust, et al? "If
         | it compiles, it works;" "guaranteed memory safety," etc?
         | 
         | [0]
         | https://developers.slashdot.org/story/18/01/01/0242218/which...
        
           | dang wrote:
           | That study dates from 2014 and was discussed here:
           | 
           |  _A Large-Scale Study of Programming Languages and Code
           | Quality in GitHub (2014)_ -
           | https://news.ycombinator.com/item?id=15378800 - Oct 2017 (66
           | comments)
           | 
           | It's also discussed prominently in Dan Luu's survey, linked
           | to here:
           | 
           | https://news.ycombinator.com/item?id=37770719
        
         | Hermitian909 wrote:
         | > I really wanted some hard research on this, but I know it's a
         | hard one.
         | 
         | I think we'll have to settle for judgment calls.
         | 
         | I tried going through some of the research we have on developer
         | productivity a few years back and it's almost all garbage or is
         | only truly applicable to juniors (e.g. when you're new you
         | _really_ benefit from quick feedback time on static errors).
         | 
         | The entire space suffers from the fact that good experimental
         | design is impossible to implement with anyone who's not a
         | college student (good luck getting professionals to follow your
         | rules for months) and the curse of dimensionality from the need
         | to disentangle individual variations, type of software
         | development, management style, and a thousand other things to
         | try and draw out a signal.
         | 
         | Sadly, many things and life can't be effectively measured.
        
         | d0mine wrote:
         | It looks like you think writing your program in the language
         | used to express types will magically remove "runtime bugs"
         | 
         | If the language is powerful enough to be able to write ordinary
         | programs, it is powerful enough to produce bugs.
         | 
         | Static typing can be effective at catching certain types of
         | bug, not all. It can improve readability sometimes (as a DSL
         | for static unit tests/executable docs).
         | 
         | In general, dynamic languages are more agile and you can write
         | more tests easier. Some of the tests you wouldn't need to write
         | in a statically typed language, therefore typing is still
         | useful though not as universally effective as one might
         | believe.
        
         | patrickthebold wrote:
         | Perhaps the issue is how people like to solve problems. I'm a
         | huge typescript fan, and I say a lot of the hard work is
         | designing the types. Then the code becomes 'the only thing that
         | makes sense given the types'. There may be some duality at
         | play, where otherwise designing the code is the hard work. And
         | the types become, 'anything that makes sense given the code'
         | 
         | And note the switch from 'only' to 'any'.
         | 
         | Anyway just hypothesising.
        
           | Draiken wrote:
           | I had to learn TS because that's the hype today, and went
           | into it after seeing some amazing F# talks on typing. I was
           | amazed at the way they used types to ensure your code was
           | actually correct. I was excited to be able to do that with
           | TS.
           | 
           | Then I found out the hard way that none of that works.
           | Basically it's all a lie. You can't use the types in runtime
           | so all that effort you put into the types doesn't actually
           | translate when you want to use the type system to full
           | effect. That was absolutely demoralizing.
           | 
           | For me, the white elephant in the room is that the language
           | doesn't really matter all that much. Good developers will
           | write good code and bad developers will write bad code.
           | 
           | Good developers might use meaningful types and bad developers
           | will use strings, records and numbers everywhere.
           | Guaranteeing a string is passed and not a number is not gonna
           | prevent many bugs. Guaranteeing a `PhoneNumber` is passed can
           | truly prevent bugs. But that's never the code that you
           | actually see in the wild (even in the article).
           | 
           | In the real world, most people can't even use half the type
           | system they claim is so great.
        
         | dgb23 wrote:
         | Exactly my thoughts!
         | 
         | The article and many commenters here all talk about programmer
         | ergonomics, productivity and "correctness".
         | 
         | The current research shows that these things are neither
         | improved nor weakened by static typing. There are (even recent)
         | papers on comparing typed vs dynamic language with no
         | meaningful results. So basically it's entirely subjective.
         | 
         | However there _is_ an actual effect of static typing that can
         | be trivially proven: It enables a programmer to write more
         | efficient code. That should be at the forefront of every
         | discussion around typing discipline, because everything else is
         | just _hot air_ at this point.
         | 
         | TypeScript (used in the article) is an example that is _not_
         | actually strongly typed (it's statically typed but weak) and it
         | doesn't even provide performance and memory layout guarantees,
         | because the types are just comments. So you pay all of the cost
         | of static typing without _any_ of the tangible benefits except
         | documentation.
         | 
         | To me it is surprising that we as a technical community
         | completely ignore actual evidence and take our cultural and
         | personal preferences as fact.
        
         | tasn wrote:
         | I think most people would agree that types prevent a lot of
         | bugs (and others posted research to support it in the thread),
         | so the question is less about that and more about the
         | subjective reasoning people have to decide the investment is
         | not worth it.
        
           | Draiken wrote:
           | >I think most people would agree that types prevent a lot of
           | bugs
           | 
           | Again, that's not what research shows. Type checking bugs are
           | most definitely not the most common ones and typing doesn't
           | really help with runtime bugs unless it's a strongly typed
           | language.
           | 
           | I'm all for types, but after using TypeScript and seeing
           | everyone (including the article) touting it as the solution,
           | it simply isn't all that better than vanilla JS.
           | 
           | I did spend countless hours having to wrangle typescript when
           | integrating with third party libraries, searching for types
           | that were not always there, manually extending/creating
           | library types and so on.
           | 
           | So no, it's not as clear cut as some say it is.
           | 
           | If we want to argue for types, then we should use strongly
           | typed languages that prevent these bugs (if you can manage to
           | create the right types, of course). Examples in TypeScript
           | are simply not going to cut it because that's a horrible
           | example of a typed language. I mean, it's not even a
           | language.
           | 
           | Edit: above all, hard research. If there's research for this,
           | why isn't that in the article?
        
             | chrisco255 wrote:
             | > Type checking bugs are most definitely not the most
             | common ones and typing doesn't really help with runtime
             | bugs unless it's a strongly typed language.
             | 
             | TypeScript actually performed quite well in the last
             | academic study I read on this debate (like 6 years ago).
             | 
             | The real problem with web APIs is that there is always some
             | lossy conversion between type systems as we cross
             | boundaries. So we can't really make some sort of closed
             | system assumption. A typical web app may interact with
             | dozens of API services, some run by third parties. And
             | maybe you can trust their API docs, but maybe not really,
             | and they're subject to updates anyways, so you always have
             | to be on your toes.
             | 
             | Even internally, you can't really control all the type info
             | from end to end. Even the most monolithic systems will have
             | some sort of abstraction leak when going from JSON ->
             | Object -> Relational storage. Even largely monolithic
             | systems will typically break off some functionality (like
             | email sending, websockets handling, etc) as a separate
             | service. The boundary creates a co-evolving connection
             | between separate services run by separate teams, with
             | separate upgrade cycles, even without full microservices
             | buy in. And that creates potential runtime type errors when
             | mapping between these layers.
             | 
             | Even if you've somehow plugged all those leaky abstractions
             | and your tight type system has handled all the edge cases
             | and is provably correct: the user will teach you otherwise
             | on the UI layer. User input can vary wildly, and everything
             | from device capabilities to personal disabilities to
             | network throttling to authentication to using weird ISO
             | characters to file sizes to strange input devices and
             | legacy systems with their own quirks, will completely throw
             | you off at some point.
             | 
             | So no matter how type safe your language is, you'll always
             | have to deal with the untyped and unpredictable user layer.
             | And the reason why JS has been so successful there is
             | because of how flexible it is. It's not as painful to make
             | quick tweaks with JS as it is with a type system like
             | Rust's, for example.
             | 
             | JS, for all its quirks, made a good amount of trade-offs
             | for its target platform.
             | 
             | Type errors are almost always the easiest types of errors
             | to fix. What really will get you is debugging
             | interdependent systems and services, and that pesky user
             | layer. But people will spend extraordinary amounts of time
             | maintaining complex type systems just so their OCD can be
             | satisfied about believing, that at least for a moment, if
             | their program compiles...that all is right with the world
             | for that brief moment just before you deploy to production.
             | 
             | Oh were that the case. I do think types are essential for
             | mission and life critical systems, but testing is even more
             | essential for those cases, so everything should already be
             | thoroughly covered. For consumer apps, however, is it worth
             | the cost in velocity?
        
             | marwis wrote:
             | > Again, that's not what research shows. Type checking bugs
             | are most definitely not the most common ones and typing
             | doesn't really help with runtime bugs unless it's a
             | strongly typed language.
             | 
             | Can you point to that research?
        
               | solumunus wrote:
               | > typing doesn't really help with runtime bugs unless
               | it's a strongly typed language
               | 
               | I'm skeptical of this research. Typescript prevents
               | runtime bugs for me day in day out. It also allows me to
               | produce much more elegant and flexible solutions which
               | would be infeasible in plain JavaScript. When people say
               | there is no significant benefit compared to JavaScript it
               | almost feels like I must be on a different planet or
               | something. I would love to see what kind of code these
               | people are working with, or how they're attempting to
               | leverage the type system.
        
               | Draiken wrote:
               | This was the last one I read:
               | http://danluu.com/empirical-pl/
               | 
               | If there's more, I hope people reply here with it!
        
               | dang wrote:
               | Discussed a bit in past threads:
               | 
               |  _The evidence behind strong claims about static vs.
               | dynamic languages_ -
               | https://news.ycombinator.com/item?id=16287083 - Feb 2018
               | (1 comment)
               | 
               |  _The empirical evidence that types affect productivity
               | and correctness_ -
               | https://news.ycombinator.com/item?id=8594769 - Nov 2014
               | (25 comments)
        
         | joekrill wrote:
         | > The research out there found no meaningful difference between
         | both styles (unless there's newer research I haven't seen?) and
         | people keep taunting around how their preferred side is
         | undoubtedly the right one.
         | 
         | Does it, though? I'm not sure the research shows any strong
         | evidence one way or the other. There's a decent review of
         | various studies here, for example:
         | https://danluu.com/empirical-pl/, that seem to indicate no real
         | conclusion.
        
       | lucasyvas wrote:
       | The dynamic typing crowd is frankly just flat out _wrong_ at this
       | point and someone has to say it - so, thank you Tom. This is
       | especially apparent with advancements of type inference in
       | compiled languages.
       | 
       | Beyond initial prototyping (which I _doubt_ will actually ever be
       | thrown away), what logical defence is there for catching obvious
       | bugs in production when they could have been caught at compile
       | time instead? Dynamic typing straight up hides unavoidable
       | realities of programming - you have to know what thing you have
       | to cover all the cases. I don 't just mean cases that "make the
       | compiler happy". These cases are most often not mutually
       | exclusive from the business domain - cases related to core
       | business logic are missed, which produce more bugs which makes
       | your software objectively worse for both the end user and
       | whatever business the software is sold by.
       | 
       | The complaints I hear are that it's too cumbersome or annoying to
       | satisfy these cases - my retort is to stop complaining because
       | most of us are paid to write _working_ software, not software _we
       | can pass off as being complete when it 's not_.
       | 
       | And don't suggest that tests cover this - they absolutely don't,
       | and testing such things is a total waste of time. The train has
       | left the station, best get aboard.
        
         | lisper wrote:
         | No one is against static typing. This thing that some people,
         | myself included, oppose -- with good reason -- is _mandatory_
         | static typing. The idea that anyone advocates giving up the
         | ability to catch bugs at compile time if it can be done at no
         | cost is a straw man.
        
           | berkes wrote:
           | Who is arguing for mandatory static typing?
           | 
           | Even the article we're discussing points out there are cases
           | for no- or dynamic typing.
        
             | lucasyvas wrote:
             | I am arguing for it, for one. There isn't a single good
             | reason that it should be optional in a _production_ code
             | base moving forward. If you started with a dynamically
             | typed language, you should be introducing type hinting and
             | enforcement at a CI /CD step as soon as yesterday.
        
         | PaulHoule wrote:
         | A counter is that nothing has replaced Python for data science.
         | I mean, Julia has talked a good game but gotten very little
         | traction.
        
           | lucasyvas wrote:
           | I would argue this is a false equivalency. The explanation is
           | that Python is too entrenched to replace, not that it is
           | somehow superior for this use case because it is dynamically
           | typed.
        
             | PaulHoule wrote:
             | Well... I'd phrase it like "no statically typed language
             | has proven it is superior or even applicable for this use
             | case yet". You can't say Julia hasn't given it a serious
             | try and hasn't gotten first-rate marketing treatment by
             | being name checked in "Ju-Py-Ter" notebooks and other
             | placements. Instead, Julia has serious deficiencies
             | 
             | https://news.ycombinator.com/item?id=32806179
             | 
             | It's certainly not proven a static language can't cover
             | this use case but in other areas static languages really
             | have proven their merit.
        
       | dep_b wrote:
       | I like a bit of Python or Elixir from time to time but truth to
       | be said there's never a moment I am happy I didn't have types to
       | worry about.
        
       | Animats wrote:
       | There's been considerable convergence on this. Most languages now
       | have some degree of type inference for statements now. Even C++
       | has "auto". That substantially reduced the amount of type
       | boilerplate in code. Remember having to write out long iterator
       | types in C++ "for" statements? We're past that.
       | 
       | As for function declarations and structure fields, that's where
       | you need type information to read the code. Once a program gets
       | beyond a few hundred lines or beyond one developer, some amount
       | of annotation is essential.
       | 
       | The main objections come from Python and Javascript users, of
       | course. Python retrofitted a very strange advisory typing system,
       | and Javascript retrofitted TypeScript. Both are bolt-on type
       | systems and are used in mixed typed/untyped environments. That is
       | painful.
       | 
       | LISP also got a type system retrofit decades ago, with "flavors"
       | and the Common LISP Object System, and that was ugly, too. The
       | lesson here is that retrofitting a type system creates a mess.
        
         | mjr00 wrote:
         | I actually think Python's type system is pretty good, given the
         | circumstances. It's got some nice features like Optional
         | forcing checks for None values before use, and structural
         | subtyping with typing.Protocol. Could it be better if Python
         | were designed with types from the ground up? Yeah, of course.
         | But given the requirements of integrating with all existing
         | Python code and not breaking any existing code I think it does
         | a decent job.
         | 
         | The bigger issue with Python and static typing is the ecosystem
         | and conventions that a lot of developers use, made worse by a
         | lot of these developers really being data scientists who are
         | writing Python. *args/**kwargs are heavily abused by people too
         | lazy to write proper method signatures. It's extremely common
         | in Python to have methods pass around DataFrames or
         | dictionaries as a grab-bag of stuff. Bonus points when methods
         | add and remove columns/fields so you don't know what's in the
         | data bag until you run the code (or read every line).
         | 
         | You can do this in almost any language, of course. Nothing
         | stops you from writing a C# program with every type being
         | `dynamic` or have all your Go methods accept `interface{}`. But
         | Python, for a long time, actively encouraged this approach, and
         | sadly there's still many beginner tutorials today that present
         | things like "just write a method that takes *kwargs and you
         | don't have to change the function signature!" as an advanced
         | language feature for smart people instead of an awful footgun.*
        
         | germandiago wrote:
         | Python and Typescript "type systems" were designed for gradual,
         | non green-field typing. It is essential to incremental
         | migration and totally understandable that it works this way.
        
         | spankalee wrote:
         | TypeScript's type system is flat out amazing though. I wish
         | more type systems were as expressive.
        
           | Byamarro wrote:
           | TS' type system is insane in what it's capable of expressing.
           | I've personally wrote a snake game using types alone (you see
           | a board, snake and snacks inside your editor type popups).
           | 
           | Despite that, TS is still quite cumbersome to use due to its
           | initial mission statements. I.e. `Object.keys(myObject)`
           | doesn't return `keyof (typeof myObject)`, so if you'd do
           | something like this: `Object.keys(myObject).forEach(key =>
           | myObject[key])` it'll throw an error that key is not
           | assignable to `myObject`. The reasons lie in design choices
           | made in order to be able to gradually migrate an untyped JS
           | codebase into a TS one. There's tons of issues like this,
           | some of them are just completely absurd and make developers
           | that try to achieve simple things throw their laptop out of
           | the window :D
        
             | spankalee wrote:
             | This is an old, old issue, and it's not due to migration
             | but due to inheritance.
             | 
             | `<T>keys(o: T) => keyof T` is actually quite incorrect,
             | because you can't guarentee that keys() doesn't return a
             | value not in `keyof T`, a key could be from a subclass of
             | T.
             | 
             | I think TypeScript is doing the right thing here in not
             | claiming something that's very easily violated.
        
       | zabzonk wrote:
       | i agree about strongly typed languages, but rather than:
       | 
       | let person1 = new_person();
       | 
       | i prefer the c++ way (which also supports type inference):
       | 
       | Person person1;
        
       | Veuxdo wrote:
       | Static type checking won the battle, but lost the war to
       | microservices, micro front-ends, micro-repos, and so on.
        
       | feoren wrote:
       | We want to identify and fix problems as early as possible;
       | ideally, before we even write them. Problems cost exponentially
       | more to fix the later you catch them, and the damage they can
       | cause only grows with time. Static typing lets you identify
       | problems earlier than dynamic typing, full stop. In fact I'd
       | rather have strong static typing and 0% test coverage than
       | dynamic typing and 100% test coverage -- in the latter case, I'm
       | catching problems much later, and I have the maintenance burden
       | of all those tests, 70% of which are only there to catch what
       | static typing would have already found.
       | 
       | The best mix for me is to lean heavily on the type system and
       | only lightly on tests, trying to write code that is simple and
       | "obviously correct". Obviously-correct code has already had its
       | problems ironed out in the first 6 or so bullets below, and there
       | is very little room for further bugs to hide. Of course even
       | "obviously correct code" can actually have bugs or be subtly
       | incorrect -- a better definition is that any surprises in such
       | code would _also_ be surprises to the tests. The tests are
       | nothing more than mirror images of the code, and therefore are
       | not helpful or necessary. Static typing helps me think about the
       | problem clearly, and helps me write  "obviously correct" code.
       | 
       | Here's my working list, in order of preference of when I'd like
       | to find the problem. Every time you drop down this list, the cost
       | to fix the problem gets multiplied by some small factor ~1.5 to
       | 3.
       | 
       | - Initial ideation ["Facebook for dogs? That idea sucks."]
       | 
       | - Requirements analysis ["That's not actually how we calculate
       | that metric."]
       | 
       | - Conceptual system design ["Wait, these parts don't fit together
       | like that."]
       | 
       | - Low-level design ["Crap, a loop won't work here, I need a
       | different flow."]
       | 
       | - Brain-to-fingers typing ["Whoops I almost typed 'elesif'"]
       | 
       | - Immediately post-typing [Red squiggly line under 'elesif']
       | 
       | - Re-reading ["Wait that should be i-1, not i"]
       | 
       | - Compile time ["SYNTAX ERROR: Unknown identifier 'elesif'"]
       | 
       | - Unit test time ["Assertion failed: expected 7, got 8"]
       | 
       | - Code review time ["You didn't handle the case where N is
       | negative"]
       | 
       | - Merge / integration test time ["Oh crap, David's commit broke
       | my commit! How the hell do I merge this?"]
       | 
       | - Internal manual testing time ["You need to tighten up the
       | graphics on level 3"]
       | 
       | - Production ["The users say the application keeps crashing when
       | they run this report! Fix it!"]
       | 
       | - Years later/never ["It turns out that the analysis code we've
       | used for the last 10 years had a major bug in it the whole time
       | and we've been giving wrong numbers to a regulatory agency that
       | has the power to shut down our company."]
        
         | boxed wrote:
         | > Problems cost exponentially more to fix the later you catch
         | them, and the damage they can cause only grows with time.
         | 
         | Citation needed.
         | 
         | This is ENORMOUSLY context dependent. Enough to invalidate the
         | entire point.
         | 
         | My day job is writing code that runs on a server I control.
         | Mistakes there are super cheap to fix. I get a nice crash in
         | sentry with stack and variables for all frames, I fix it,
         | deploy. Done.
         | 
         | If I was shipping code to Mars, well that's the opposite
         | situation.
         | 
         | CONTEXT MATTERS
        
           | feoren wrote:
           | >> Problems cost exponentially more to fix the later you
           | catch them, and the damage they can cause only grows with
           | time.
           | 
           | > Citation needed.
           | 
           | Really? Isn't this one of the most clear and repeatedly
           | demonstrated facts in all of software engineering? We don't
           | have a whole lot of clear-cut demonstrable facts in this
           | industry, but this is absolutely one of them.
           | 
           | How about this 2002 NIST report, Table 1-5 on page 1-13 is
           | "Relative Costs to Repair Defects when Found at Different
           | Stages of the Life-Cycle" and shows 1X at "Requirements", 90X
           | at "System Testing", 440X at "acceptance testing", and up to
           | 880X at "operation and maintenance".
           | 
           | (Warning: 300-page PDF)
           | 
           | https://www.nist.gov/system/files/documents/director/plannin.
           | ..
           | 
           | You can find thousands of people saying the same thing from
           | their personal experience with a quick Google. On the list of
           | uncontroversial statements about software engineering, this
           | is right at the top. Is our discipline so immature that we
           | can't even agree on this extremely basic fact?
           | 
           | Another (okay, they don't say "exponential" here, or try to
           | quantify it at all):
           | 
           | > The cost of finding and fixing bugs or defects is the
           | largest single expense element in the software lifecycle. ...
           | The earlier in the development lifecycle defects are found,
           | the more economical the overall delivery will be.
           | 
           | The Cost of Poor Software Quality in the US: A 2020 Report,
           | Consortium for Information & Software Quality
           | 
           | https://www.it-cisq.org/cisq-files/pdf/CPSQ-2020-report.pdf
           | 
           | > My day job is writing code that runs on a server I control.
           | Mistakes there are super cheap to fix.
           | 
           | That's good to hear, but mistakes caught before they get to
           | your server are even cheaper still. Perhaps your exponential
           | factors are smaller than NASA's, but it still clearly costs
           | you much more to fix a problem that made it to your
           | production server (and possibly impacted your users) than to
           | fix it immediately after typing it because your IDE showed
           | you a red squiggly line.
        
             | boxed wrote:
             | > Really? Isn't this one of the most clear and repeatedly
             | demonstrated facts in all of software engineering?
             | 
             | It's a repeated saying.
             | 
             | > You can find thousands of people saying the same thing
             | from their personal experience with a quick Google.
             | 
             | I know.
             | 
             | > That's good to hear, but mistakes caught before they get
             | to your server are even cheaper still
             | 
             | That's a nonsense statement. If they are caught AT NO COST
             | they are of course cheaper yea. But that's the thing. It's
             | all tradeoffs. Everything is about tradeoffs. What is the
             | marginal cost of finding bugs?
             | 
             | > than to fix it immediately after typing it because your
             | IDE showed you a red squiggly line.
             | 
             | Yea, that's nice. In that case the marginal cost is
             | approaching zero. But how many percentage of all bugs is
             | that? And what is the cost?
             | 
             | How many bugs will my IDE find if I switch from Python to
             | Haskell or Rust? And how will that impact my development
             | speed?
             | 
             | I write my frontend in Elm because that's code I ship to
             | users (via the browser) and THERE the costs are enormously
             | worse, often because the problems can be seen by customers
             | and not internal users (again: CONTEXT). I'm willing to
             | tolerate a big productivity cut for being sure the code is
             | correct there. But on my server? Nope. I am not willing to
             | leave an easy order of magnitude of development time on the
             | table for that type of safety.
             | 
             | And why stop at static typing? Why don't you run ALL your
             | code through Property Based Testing AND Mutation Testing
             | 100% before shipping? What's the marginal cost of catching
             | a bug then? Why not run ALL your code through a theory
             | prover like Coq?
             | 
             | Bugs are NOT always "cheaper" when found early. It's about
             | the COST of finding the bug early. Of course it is! If the
             | cost is a trillion dollars in programmer time to find a bug
             | that takes 1 second to fix in production at a cost of a few
             | dollars of programmer time, by definition it was NOT worth
             | it.
             | 
             | It's ALWAYS a tradeoff. Of course it is. Everything is.
             | 
             | It's maddening to me that people refuse to see this when
             | it's so blatantly obvious.
        
               | feoren wrote:
               | There's a reason I used the word "problem" and not "bug"
               | in my original post. In fact every time I found myself
               | writing "bug", I deleted it and wrote "problem" instead.
               | You're thinking very specifically about "bugs": clear
               | spots a codebase that are clearly causing some clear
               | error. That's actually a small percentage of the scope of
               | "problems" that I'm talking about. Problems can be: your
               | idea is bad, your architecture doesn't fit together, your
               | performance is bad, your calculations are wrong, etc.
               | Static typing, when done well, can help prevent many more
               | of these issues than that narrow definition of "bug".
               | Static typing helps you think clearly about your code.
               | 
               | > the marginal cost [of fixing a red squiggly] is
               | approaching zero. But how many percentage of all bugs is
               | that? And what is the cost?
               | 
               | The marginal cost of fixing a red squiggly underline is
               | indeed basically zero for typos, and typos are a class of
               | bugs I'd like my static type system to help me catch; and
               | it does, and dynamic type systems generally don't. So the
               | percentage of typos that become bugs is basically zero,
               | but that's partly _because of static typing_! When you
               | say  "the percentage of all bugs", your definition of
               | "bug" is a-priori excluding things that were caught
               | before they became bugs!
               | 
               | But you can also get a red squiggly underline because you
               | thought some variable was in scope when it's actually not
               | -- that bug _could have been caught earlier_. The cost of
               | fixing that bug is _not_ near zero: the structure of your
               | program is different between your brain and your code.
               | The easiest bug to fix is the one you never write in the
               | first place.
               | 
               | Or you get a red squiggly because you thought you could
               | pass an object of type X into a method you're relying on,
               | but you actually can't. Dynamic typing _will not help
               | you_ with this, and the cost of fixing that bug is _not
               | zero_ : again, your assumptions about how your program is
               | fitting together are incorrect. I'd much rather realize
               | that I can't use a method in exactly the way I thought
               | right at the moment of typing it than later during test
               | time. The latter requires writing and maintaining a test
               | in order to catch a problem _late_ that I could have
               | caught _early_ with _no test_.
               | 
               | > And why stop at static typing? Why don't you run ALL
               | your code through Property Based Testing AND Mutation
               | Testing 100% before shipping?
               | 
               | I directly addressed the subject of testing in my
               | original post. Static typing allows me to write many
               | fewer tests than dynamic typing.
               | 
               | > If the cost is a trillion dollars in programmer time to
               | find a bug that takes 1 second to fix in production at a
               | cost of a few dollars of programmer time, by definition
               | it was NOT worth it.
               | 
               | I just don't understand this hypothetical. Why would it
               | ever take a trillion dollars to prevent a bug that takes
               | 1 second to fix in production? This just doesn't jive
               | with any developer experience I've ever heard about, any
               | example I've ever read about, or anything I can even
               | imagine.
               | 
               | You seem to be operating under the assumption that
               | introducing static typing makes you slower at
               | programming, but we're claiming it's worth it. No, that's
               | not my claim. My claim is that above some level of
               | program complexity, static typing makes you _strictly
               | faster at programming_ , full stop. That level of program
               | complexity may not be your internal server or whatever,
               | but it definitely is most production-grade software out
               | there.
               | 
               | > It's ALWAYS a tradeoff. Of course it is. Everything is.
               | It's maddening to me that people refuse to see this when
               | it's so blatantly obvious.
               | 
               | This is generally true in engineering, but not always. It
               | is actually possible to simply advance the discipline.
               | When you're building a suspension bridge, there's a
               | tradeoff between Stainless Steel and High-Carbon Steel,
               | but there's not a tradeoff between Steel and Popsicle
               | Sticks. Unless, of course, you're building a toy or a
               | proof of concept. Dynamic typing is fine for toys and
               | proofs of concepts; nobody is disputing that.
               | Professional engineers don't spend most of their time
               | discussing the best way to build toys.
        
               | boxed wrote:
               | > Problems can be: your idea is bad, your architecture
               | doesn't fit together, your performance is bad, your
               | calculations are wrong, etc. Static typing, when done
               | well, can help prevent many more of these issues than
               | that narrow definition of "bug".
               | 
               | I don't see how static typing helps with "solving the
               | wrong problem" kind of issues at all. That's what asking
               | deep questions about the business is for. Maaaaybe DDD
               | can do something here, but that's hardly "static typing".
               | 
               | > I directly addressed the subject of testing in my
               | original post. Static typing allows me to write many
               | fewer tests than dynamic typing.
               | 
               | I noticed here that you didn't make any difference
               | between testing, PBT, MT and proof systems. That's pretty
               | bad. I won't conflate Haskell-style good type systems
               | with C-style horrible type systems, so you shouldn't do
               | the same with testing.
        
               | feoren wrote:
               | > I don't see how static typing helps with "solving the
               | wrong problem" kind of issues at all.
               | 
               | One example is F#'s unit of measure system, which can
               | statically verify dimensional agreement of arithmetic.
               | Another example would be differentiating between "Safe
               | Strings" and "Unsafe Strings" (say, untrusted user input)
               | and statically enforcing which are allowed in which
               | method. They won't tell you that "Facebook for Dogs" is a
               | bad idea, but they may reveal subject-matter errors in
               | the actual requirements themselves. Most test suites
               | wouldn't even catch these errors, because test assertions
               | are generally based on requirements. You could write your
               | own unit-verifier that you run in tests, but then you're
               | just reinventing static typing. In fact it's a common
               | criticism of test suites in dynamically typed languages
               | that they end up poorly reinventing checkers for the
               | guarantees already provided by a decent static type
               | checker.
               | 
               | > I noticed here that you didn't make any difference
               | between testing, PBT, MT and proof systems
               | 
               | I also didn't differentiate between the Late Middle Ages
               | and the Early Renaissance, because it was off topic. But
               | if you insist:
               | 
               | "Property-Based Testing" is a testing pattern, not a
               | different kind of test. Write tests and assertions as
               | appropriate for the thing you're testing. It seems to me
               | that you should have enough understanding of the likely
               | failure scenarios and edge cases of your code that you
               | don't need to be randomly generating inputs, but I can
               | see how it'd be useful. I test all sorts of invariants in
               | my tests. This just doesn't seem like a novel thing to
               | me.
               | 
               | "Mutation Testing" is basically testing your testing
               | methodology. Okay. You could also test your bus factor by
               | randomly shutting out one developer for a day each month
               | and seeing how you get on. Maybe good ideas for some
               | companies? If you find yourself trying to develop a
               | completely airtight testing process that will catch 100%
               | of bugs, it's probably because too many bugs are passing
               | your tests. Before you kill yourselves trying to develop
               | an airtight, mathematically-guaranteed strong test
               | system, may I suggest strong static type systems instead?
               | Just let the compiler do it.
               | 
               | "Proof systems" _are_ strong static type systems.
        
       | t43562 wrote:
       | I also don't want to get into a debate about something where
       | there's no chance of changing an opinion. An absolute position is
       | like a religion - it's the desire for everything to be simple,
       | for the removal of doubt and the need to think about each
       | situation on its merits.
       | 
       | I remember taking a badly written Python project which was
       | difficult to work on because it took hours to run and could fail
       | at the very end due to a syntax error or other trivial kind of
       | mistake. I needed some way to make it less difficult to change so
       | I could change it to something good. I tried applying type hints
       | because I thought this had minor impact for potentially some
       | gain. In this case it didn't and what helped was to take every
       | tiny bit that was unit-testable and make a test and then to mock
       | the part of the process that took all the time (it was an android
       | build system so I mocked the android build). Every bit of
       | refactoring-for-testability made it easier to do the next bit.
       | 
       | So to me I feel that writing tests has more value than any other
       | activity - I'm ready to use types when it makes my IDE work
       | better and when I think it stops me making a mistake I've made
       | before but for my money tests deliver more and I will rather work
       | on them than trying to build an elaborate type system that models
       | the problem well enough to prevent one from doing invalid things
       | under any circumstances. For me, the types/classes I create are
       | there to make my program understandable and manageable as it gets
       | bigger.
       | 
       | I find it useful to be able to choose where to put my effort.
       | When I worked on Java long ago I found the type system of the JDK
       | libraries horrendously overdesigned and hard to use - flexibility
       | is sometimes bad if you don't gain from it but are forced to pay
       | the price anyhow.
        
         | kagakuninja wrote:
         | Python is an example of adding types after the fact. I don't
         | know the specifics of your situation, but gradually typed
         | languages do not offer the same guarantees as languages that
         | have static type checking from the beginning.
         | 
         | Replacing types with tests adds giant amounts of boiler-plate
         | code, for little benefit.
        
           | t43562 wrote:
           | My experience is that tests model the expected behaviour and
           | that type systems cannot. Therefore I get lots of value out
           | of tests where types are an impediment.
           | 
           | Static typing from the beginning just sets me into a big
           | design up front problem where I try to anticipate the
           | flexibility that I will need and I start building lots of
           | boilerplate abstractions that end up never being used or
           | restricting me later.
           | 
           | I find it useful to write imperfect code with only the
           | constraint that it is testable and then revise the structure
           | and any types I need as it becomes evident that they are
           | valuable in the context.
        
       | Zambyte wrote:
       | I agree with the title, but not with the blog post. Strong typing
       | is great. There is little reason not to use strongly typed
       | systems.
       | 
       | The post adds "static" typing in too, modifying the argument.
       | Dynamically typed languages allow you to easily have a very
       | intimate understanding of your program; because you can write the
       | program and modify it while it's running using a REPL. The post
       | seems to conflate dynamically typed with untyped, which is very
       | much not the same thing. The two are actually incompatible ideas.
       | 
       | OP: I highly recommend you look into SICP if you want a concrete
       | counter argument to static typing for large systems. A main focus
       | of the course is controlling complexity through abstraction as
       | systems grow to be large, and the course was taught using Scheme,
       | which is a dynamically typed language.
        
       | vonwoodson wrote:
       | First off, I appreciate the edit. python is strong _dynamic_
       | typing, for example.
       | 
       | Second, it's a shame that the author doesn't really speak to
       | Haskell at all. Knowing that a variable is a `u16` is rarely
       | useful alone, relying on the meta of a variable name, for
       | example, to prevent me from adding `user_age` and
       | `number_of_legs`; they both are unsigned 16-bit `int`s, so the
       | compiler is cool with it. A better type system allows types to
       | hold semantic information beyond the bit-width or archaic and
       | usually unhelpful information for the computer and not the
       | developer. Relics of a past where 8k or RAM was all you could use
       | for your program.
       | 
       | Ironically, the advanced Haskell type system looks more like
       | dynamic typing specifically because the type inference is so
       | good. You can rely on the compiler (or interpreter) to tell you
       | what the type should be, often times allowing for much more
       | flexible types than you'd think possible.
       | 
       | Also, being able to derive classes like Show and Read is amazing.
       | 
       | So, +1 for loving types!
        
         | tubthumper8 wrote:
         | I'm sure the author is aware of these - many of the code
         | examples are in Rust which has newtypes and automatic deriving
         | of traits (ex. Display which is the equivalent of Haskell Show)
        
       | syndicatedjelly wrote:
       | Does mypy for Python offer a complete solution to introducing
       | static type checking to Python? What is mypy missing that a
       | language with strong static typing has?
        
       | [deleted]
        
       | terminatornet wrote:
       | It's a shame so many people have had bad experiences with static
       | typing due to Typescript. In languages like Rust and Elm, static
       | typing truly feels like a super power when I'm coding,
       | particularly when modeling my applications possible states.
       | 
       | This talk does a great job at articulating how to use types to
       | disallow invalid/illegal states.
       | 
       | https://www.youtube.com/watch?v=IcgmSRJHu_8
        
       | bluetomcat wrote:
       | Dynamic typing is polymorphism at the language level. In essence,
       | you expect most operators to behave sensibly with different
       | types. An expression such as "a + b" resembles a polymorphic
       | function such as "add(a, b)". You would expect it to work fine
       | most of the time, regardless of the types. And the types in a
       | dynamically-typed language usually aren't so many - you possibly
       | have booleans, numbers, strings, lists, maps, sets and objects.
        
         | Chabsff wrote:
         | The moniker you are looking for is "duck-typing". Polymorphism
         | is tightly tied to the notion of explicit interfaces.
        
           | jwilliamson wrote:
           | He's describing row polymorphism. Only some forms of
           | polymorphism require explicit interfaces.
        
       | incomingpain wrote:
       | I learnt to code in C. I know strong static typing.
       | 
       | I now program exclusively in python. I am never going back.
       | 
       | I have tried and do have some of the
       | 
       | def hello(world: str) -> str:
       | 
       | But to date I have not found a single example where this was
       | useful at all. In fact, I found some odd cases where it's
       | harmful.
       | 
       | No typing for me thanks.
        
       | EVa5I7bHFq9mnYK wrote:
       | Hmm, just a few years ago, before typescript, the prevailing
       | wisdom was that types are dead, this is a brave new world out
       | there, just need to create more unit tests.
        
       | strongly-typed wrote:
       | TIL I am a hill
        
       | revskill wrote:
       | THere's a trick i often do on my Typescript projects.
       | 
       | To know which other files is using current file, i just add an
       | additional property, then boom, the IDE go red on those files !
       | 
       | Without types, the best you can do is, search, search and search
       | !
        
         | 1-more wrote:
         | This is a whole vibe when working with an ML language. I
         | usually start at the bottom of the call stack and add the
         | property I need to the signature of that function, then I can
         | just follow "hey, you're calling it wrong--where is argument
         | xyz?" errors up to the top of the stack. Classic bop mode.
        
       | insanitybit wrote:
       | At this point it's beyond a hill I'm willing do die on. I'm not
       | really interested in discussing it. If you don't get it I
       | probably don't want to talk to you about it, I might even think
       | less of you as a software developer. The amount of pre-existing
       | respect for someone I'd need to have before I engage in a good-
       | faith discussion on "are types good" is pretty high.
       | 
       | edit: To clarify, I am on the "types good" side of things
        
         | edem wrote:
         | Same here. Whenever someone starts babbling about why
         | __language x__ is hard because of types or whatever, I just
         | disengage. I don't care what anyone thinks about types. I use
         | them, and I will keep using them no matter what.
        
         | yowlingcat wrote:
         | > The amount of pre-existing respect for someone I'd need to
         | have before I engage in a good-faith discussion on "are types
         | good" is pretty high.
         | 
         | I think that says more about the strength of your zeal than of
         | your argument.
        
         | pharmakom wrote:
         | Also on the "types good" side of the fence. HOWEVER, I also
         | believe that mainstream typed languages cannot represent some
         | situations very well. Often the only attempts to do so are in
         | some weird Haskell extension and it feels rather... inelegant.
         | Bottom line: types are better; but our current type-systems are
         | not the final word on types.
        
         | wiseowise wrote:
         | The only absolute truth there is. Static typing is
         | nonnegotiable.
        
           | dartos wrote:
           | There's strong typing and weak typing.
           | 
           | And then, kind of orthogonal to that, there's also static
           | typing and dynamic typing.
           | 
           | I think strong, dynamic typing is just as good as strong
           | static typing (weak typing is objectively bad)
           | 
           | As long as the types of your variables don't change from
           | under you, that's good, but I'm also okay with the compiler /
           | runtime figuring out what those types are for me.
        
             | chongli wrote:
             | With "dynamic typing" there is no compiler to figure out
             | the types for you. There is only the runtime to print a
             | stack trace (if you're lucky) and bail out. The whole point
             | of types is to be able to check things without running the
             | program, because exercising every possible code path
             | becomes increasingly untenable at scale.
             | 
             | A side (but many would also say critical) benefit of types
             | is that they act as a form of documentation that can never
             | go stale (because they are enforced by the compiler).
             | "Dynamic typing" does not offer this benefit whatsoever.
        
               | k__ wrote:
               | As far as I know, JS is weakly typed and Python is
               | strongly typed.
               | 
               | JS will convert types under your butt if you're not
               | careful, Python won't.
               | 
               | Sure, static typing (when done well) is superior to that,
               | but the title talks about strong typing.
        
               | dartos wrote:
               | Many dynamically typed languages have static analyzers,
               | but retain the flexibility of not needing to prescribe
               | types up front (it's impossible to know exactly what data
               | structure you need at the start of a project)
               | 
               | That's the crux of why I'm not all in on static typing
               | all the time. (Especially for networked programs that
               | expect a wide range of different kinds of input)
               | 
               | Having to prescribe the types I need before I actually
               | need them goes against how I tend to build.
        
               | sfn42 wrote:
               | Sounds like you'd like C#. It does type inference with
               | `var` and similar things, so you don't always have to
               | specify types explicitly, but everything does have a type
               | at compile time.
        
               | Smaug123 wrote:
               | (C#'s type inference is _so_ much worse than F# 's. I
               | find it deeply painful to go back.)
        
               | loup-vaillant wrote:
               | > _Many dynamically typed languages have static
               | analyzers, but retain the flexibility of not needing to
               | prescribe types up front_
               | 
               | Almost all static type systems have escape hatches that
               | let you go dynamic when you really really need it. Also,
               | I bet that most of your use cases for dynamic typing
               | could be solved with a simple tagged union. Most people
               | bemoaning the lack of flexibility of static typing just
               | don't know about how tagged unions can easily emulate
               | dynamic typing when we need it, such that we rarely even
               | need to reach for the actual escape hatches.
               | 
               | > _(it's impossible to know exactly what data structure
               | you need at the start of a project)_
               | 
               | Thankfully data structures are even _easier_ to change
               | with static typing: change it, gets a ton of type errors,
               | fix them, done. With dynamic typing you run the risk of
               | missing a call site.
               | 
               | > _Having to prescribe the types I need before I actually
               | need them goes against how I tend to build._
               | 
               | There's type inference for that. I personally take
               | advantage of it any chance I get.
        
               | pfdietz wrote:
               | Dynamic typing doesn't exclude the compiler from being
               | able to detect some things that would cause errors at run
               | time. It just means that these turn into compile time
               | warnings, not compile errors.
               | 
               | In Common Lisp, it's common practice to not accept code
               | unless all such warnings are gone.
        
               | chongli wrote:
               | That is static typing. You can add static types to a
               | dynamic language, but then you introduce a compilation
               | step. This is not an argument in favour of dynamic
               | typing. If your language requires a compilation step
               | anyway, then what you have is a static language with only
               | one type: the 'any' type.
               | 
               | Every argument I've seen in favour of dynamic typing is
               | some variation of "I like it this way." They're not
               | technical arguments because dynamic typing is a strict
               | subset of a statically typed language, equivalent to
               | passing a flag to turn the type checker off.
               | 
               | Sure, not every compiler offers such a flag, but that is
               | an argument against one particular static language (or
               | group of languages), not an argument against static types
               | itself.
        
               | marcosdumay wrote:
               | > There is only the runtime to print a stack trace
               | 
               | Types are not exclusively for verification, and even if
               | you decide it is, you can do a lot more with a type error
               | than exiting the program.
               | 
               | That stance most people keep repeating is actually
               | ridiculous. The most common usage of static type systems
               | is to verify badly-written ad-hock dynamic ones that
               | handle user errors.
        
           | IKantRead wrote:
           | Dynamic vs static typing is a similar level of design
           | decision as interpreted versus compiled. It's ridiculous to
           | try to claim one is universally better than the other as they
           | both have styles of programming and domains they are better
           | suited for.
           | 
           | I would never want a statically typed, compiled awk for
           | example.
           | 
           | I generally think large, production, multi-developer software
           | should be written in a statically typed, compiled language.
           | 
           | Strong vs Weak typing is a closer to a debate about having a
           | name spacing system or not. There is really no great reason
           | to have weak typing or not use a name spacing system.
        
             | wiseowise wrote:
             | It's not ridiculous at all.
             | 
             | Mainstream dynamically typed languages are moving in
             | statically typed direction. Python (Mypy, Pyright and
             | others), Ruby (Sorbent, Rbs), JavaScript (Typescript,
             | Flow). How many statically typed languages optionally
             | removed types?
        
               | IKantRead wrote:
               | It's a bit sad to me that people can only imagine writing
               | code for large production systems. Static types are
               | hugely beneficial in this area which is why we see this
               | trend.
               | 
               | Personally I think Python moving in the direction of
               | static typing is a mistake, dynamic typing _is_ very
               | useful for domains where python is strongest: modeling,
               | statistics, scientific computing etc. It 's also part of
               | the basic design of Python to be a dynamic language.
               | Likewise Ruby, with it's heavy use of metaprogramming,
               | also benefits tremendously from a lack of types.
               | 
               | But let me be clear: I do think statically typed
               | languages are a very good idea for large production
               | systems, I just personally do a lot of programming that's
               | not for these systems.
               | 
               | > How many statically typed languages optionally removed
               | types?
               | 
               | I wouldn't say "removed" types, but I've been in software
               | along enough to remember when dynamic typing was the big
               | hot thing and crusty old Java devs complained that we
               | couldn't possibly live without static type annotations. I
               | distinctly remember when C# introduced `var` (which is of
               | course really type _inference_ , not dynamic typing) to
               | appeal to devs that were growing weary of types.
               | 
               | There's a great example in SICP of implementing a full
               | object system in just a few lines of code that would not
               | be possible to implement as elegantly in a statically
               | typed language. Do I want that for a production system?
               | No. But there is, or at least used to be, a world of
               | computation being done for reasons other that quickly
               | getting PRs pushed out to prod.
        
               | wiseowise wrote:
               | Ok, maybe my previous message was too radical. Of course
               | there's a space for dynamic types (I use Clojure in free
               | time), but there's no reason for static types to obscure
               | your program. When I talk about static typing I mean
               | Ocaml, Haskell, Scala, F# where you program is statically
               | typed but you'll rarely see any types.
        
         | fargle wrote:
         | _and yet..._ here you are discussing it. ;)
         | 
         | discussions are a two-way street. if you aren't getting it,
         | then how do you expect someone else to "get" your position?
         | "The whole problem with the world is that fools and fanatics
         | are always so certain of themselves, and wiser people so full
         | of doubts"
         | 
         | -- Bertrand Russell
         | 
         | [edit: To clarify, i am on the "i like strong static typing
         | most of the time but also understand their pros/cons wrt.
         | dynamic languages" side of things]
        
         | yetanotherasian wrote:
         | How often do you write bash scripts or do you always write all
         | automation in some other language? Just curious how much your
         | conviction influences your behavior
        
           | insanitybit wrote:
           | I write code without static types all the time. Daily
           | probably. I am "pro types" in a hand wavy way. My conviction
           | is to no longer engaging in the debate.
        
             | scbrg wrote:
             | I'm glad to see that you've replaced debating type systems
             | with debating debating type systems. I'm sure it's a great
             | productivity improvement ;-P
        
               | insanitybit wrote:
               | It's not like I've barred myself from engaging in any
               | discussion where the word "type" shows up
        
           | bigstrat2003 wrote:
           | Speaking for myself, I never write bash scripts if I can help
           | it (though sometimes I can't help it). That isn't so much
           | because of typing, though... it's because bash is a fucking
           | horrible language that should have died 30 years ago. The
           | fact that there's no such thing as types in bash is just one
           | of many reasons why it sucks to use.
        
         | thefaux wrote:
         | > If you don't get it I probably don't want to talk to you
         | about it, I might even think less of you as a software
         | developer.
         | 
         | The feeling is mutual.
        
         | omnicognate wrote:
         | > The amount of pre-existing respect for someone I'd need to
         | have before I engage in a good-faith discussion on "are types
         | good" is pretty high.
         | 
         | > edit: To clarify, I am on the "types good" side of things
         | 
         | I agree. Python 1 would have been worthless if it didn't have
         | types.
        
         | codegeek wrote:
         | I don't necessarily die on that hill but I definitely want to
         | fight on that hill.
        
         | lasermike026 wrote:
         | Understand that there is no hope. You will die on that hill.
         | Get over it.
        
         | tasn wrote:
         | Author here. I ended the post with:
         | 
         | > I can see both side of the arguments on many topics, such as
         | vim vs. emacs, tabs vs. spaces, and even much more
         | controversial ones. Though in this case, the costs are so low
         | compared to the benefits that I just don't understand why
         | anyone would ever choose not to use types.
         | 
         | > I'd love to know what I'm missing, but until then: Strong
         | typing is a hill I'm willing to die on.
         | 
         | I genuinely want to know what I'm missing. I also outlined in
         | the post all of the arguments I usually see in favor of not
         | having types and why I disagree with them.
         | 
         | I'm happy, willing, and excited to hear what I'm missing.
        
           | 1-more wrote:
           | What does "strong" mean as regards typing. I've heard a few
           | different definitions so I'm curious what yours is in the
           | context of this article.
        
             | bigstrat2003 wrote:
             | As far as I'm aware, the generally accepted definition of
             | strong typing is: some object in memory has a type, and the
             | compiler (or interpreter) will not let you treat it as
             | another type without some kind of explicit instruction to
             | do so. This is in contrast to weak typing, where the
             | compiler/interpreter will happily try to treat a Bar object
             | as a Foo object if you do some Foo operation on it.
        
               | gpderetta wrote:
               | That's the definition of type-safety (or memory safety
               | that is pretty much equivalent). "strong typing" has no
               | generally accepted definition.
        
               | bigstrat2003 wrote:
               | Memory safety is definitely not equivalent. Memory safety
               | is more like not going past the end of an array, not
               | doing use after free, etc. I agree that what I said is
               | pretty much also the definition of type safety. But in my
               | experience it is _also_ the generally accepted definition
               | of strong typing.
        
               | 1-more wrote:
               | That seems to be a subset of static typing. Is there an
               | example of this that does not involve non-static typing?
        
           | user3939382 wrote:
           | There's a specific scenario where I have more sympathy for
           | weak typing, which is: I'm writing a small, focused utility
           | by myself whose scope can never expand and whose code will
           | never be collaborated on. I do have these, little shell
           | scripts. I write them, they work, I move on and use it for 10
           | years. No types in there, fine whatever.
           | 
           | As soon as there's any complexity at all or another person
           | involved that exception stops.
        
             | SAI_Peregrinus wrote:
             | I want a shell scripting language that allows a max line
             | length of (for example) 128 characters and a max script
             | length of (for example) 128 lines, with no `source`
             | equivalent. If the script expands to not be a "small,
             | focused" single-file script it should just fail to run at
             | all. Just enough for small utilities, but unusable for
             | giant monstrosities.
        
               | KMag wrote:
               | ... and unable to call external programs or communicate
               | with external programs via pipes / sockets / etc.?
               | 
               | Otherwise, if you're unable to source another script, you
               | could just have another script return a normal result in
               | addition to a JSON blob of the environment variable
               | changes the caller should make, which is probably worse
               | than just allowing sourcing.
               | 
               | Pipes allow arbitrarily complex networks of communicating
               | sequential processes. In some cases, networks of tiny
               | CSPs are cleaner, but without discipline, they can
               | rapidly become worse than huge monoliths.
        
             | racked wrote:
             | Indeed this. There are benefits. Less code, faster to
             | write.
        
             | KMag wrote:
             | Note that weak typing and dynamic typing are orthogonal. I
             | believe you're expressing sympathy for strong dynamic
             | typing: types are checked an enforced dynamically by the
             | runtime (such as Python raising an exception if you try to
             | add a string and an int), but there's no static type
             | analysis done at compile / load time. Python, JS, Ruby,
             | etc. are strong dynamically typed languages.
             | 
             | Also, type weakness is more a property of the runtime than
             | the language, but for those languages with specifications,
             | the language specification usually also specifies a large
             | amount of behavior for a compliant runtime.
             | 
             | The C runtime, will gladly (with UB nasal demon caveats)
             | allow you to treat an int as a pointer. There are static
             | type checks, but no hard limits on the type-confused
             | nonsense it will attempt to execute. C is statically typed,
             | but weakly typed.
             | 
             | Java, C#, etc. are strong statically typed. There are
             | static checks at compile time, and the runtimes do their
             | best (modulo escape hatches) to use dynamic runtime type
             | checks to plug the gaps in the static type systems. (For
             | any sufficiently complex sound/consistent type system in a
             | Turing-complete language, as per Godel's incompleteness
             | theorem and the halting problem, there will be some
             | programs that cannot statically type-check but still will
             | never encounter a type error, regardless of input. So, in
             | practice, there will always be escape hatches in the type
             | system to allow programs that are correct but not provable.
             | Hopefully most of these escape hatches are backed by
             | dynamic runtime checks.)
             | 
             | Of course, these categories are a partially-ordered
             | continuum, not clear binary distinctions. For some pairs of
             | languages, you can say one's statically enforced properties
             | are a superset of the other or that one runtime enforces a
             | strict superset of the other's dynamic checks. However,
             | it's often a case that you can't say one language strictly
             | offers stronger static type guarantees or one runtime
             | strictly enforces stronger dynamic type restrictions.
        
               | user3939382 wrote:
               | I'm aware of the difference, I was contemplating bash in
               | my comment. Some people construe it as strongly typed
               | though it's a little ambiguous, here's another discussion
               | about it https://news.ycombinator.com/item?id=12704050
        
             | AnimalMuppet wrote:
             | You are the other person. Come back in six months needing
             | to make a change, and it's almost like you're new to the
             | code.
             | 
             | Now, in general, I agree with you. If it's a one-off (or if
             | it's really never going to need maintenance), and if it's
             | small enough that you don't need types while writing it,
             | then sure, do whatever is easiest at the time. But "never
             | going to need maintenance" often turns out to be a lie, and
             | when that time comes, you may be happy for some types as
             | signposts to give a hint of what you were thinking all
             | those months or years ago.
        
               | BobbyJo wrote:
               | This is the trojan horse dynamic types use to get into
               | your castle :P
        
           | sumtechguy wrote:
           | Weak typing has its uses in one use case. Transition between
           | systems. Even then you usually want to know what the type is
           | (unless you really do not care about validation errors).
           | 
           | The reality is I never get to choose. I prefer strong typing.
           | But the projects I am on that ship sailed long ago 2
           | developers back who used this project as a resume builder.
        
           | a_c wrote:
           | I think you and parent are in agreement
        
           | packetlost wrote:
           | I'm also a pretty die-hard type-system user, but I've been
           | programming a lot of Lisp and FORTH lately. FORTH is just bad
           | at safety period. Lisp, on the other hand, I can see why
           | there really isn't a need for types. The macro system means
           | you can create arbitrary "compile-time" safety checks which
           | is, IMO, more powerful than just a type system. That being
           | said, I would still love a strongly, statically typed Lisp,
           | or at least one with a strong macro type system (before y'all
           | mention it, I'm not a fan of typed Racket).
        
             | gpderetta wrote:
             | wait, are you saying that any sufficiently complicated lisp
             | program contains an ad hoc, informally-specified, bug-
             | ridden, slow implementation of a static type system?
        
             | qazwse_ wrote:
             | I haven't used it, but I know that Coalton adds static
             | typing to Common Lisp, might be something you're interested
             | in.
             | 
             | https://github.com/coalton-lang/coalton
        
               | packetlost wrote:
               | I'm more into Scheme than CL, but am aware of Coalton. My
               | current lisp is Gerbil: https://cons.io which already has
               | a type annotation system and will be enhancing it for the
               | next major release (v19).
        
             | Zambyte wrote:
             | > Lisp, on the other hand, I can see why there really isn't
             | a need for types.
             | 
             | What Lisp are you using that doesn't have types?
        
               | packetlost wrote:
               | Well, every programming language must necessarily have
               | types to some degree, but they aren't necessarily static
               | or strong type systems. Most Lisps do not have a static
               | type system and even fewer have a "strong" type system.
        
               | Zambyte wrote:
               | > Well, every programming language must necessarily have
               | types to some degree
               | 
               | The vast majority yes, that's why I was a bit confused :D
               | 
               | There some languages that have no types. The only thing I
               | can think of though is a POSIX shell minus arrays. (Edit:
               | Assembly and Forth are two better examples)
               | 
               | > Most Lisps do not have a static type system
               | 
               | True
               | 
               | > and even fewer have a "strong" type system.
               | 
               | Common Lisp, Emacs Lisp, Scheme, Hylang, Clojure, and
               | Racket all feature strong typing. I'm curious where you
               | have found this trove of weakly typed Lisp dialects
        
               | packetlost wrote:
               | Lisps are not _statically_ typed typically and
               | "strongly" typed is poorly defined. I would not consider
               | most Lisp's type systems to be strong or particularly
               | expressive, but they don't need to be because it would
               | hurt the main benefit to the language: meta-programming.
               | I don't think a "strong" vs "weak" type system argument
               | is particularly valuable here, yes most prevent you from
               | inadvertently changing how a particular series of bytes
               | is interpreted, but their aggregates do not have any type
               | identity besides their own typically. This means you
               | cannot typically express and enforce an aggregate's
               | covariance or contravariance properties. There may be
               | ways to do so, but most do not provide utilities for it.
        
               | Zambyte wrote:
               | > I don't think a "strong" vs "weak" type system argument
               | is particularly valuable here, yes most prevent you from
               | inadvertently changing how a particular series of bytes
               | is interpreted [...]
               | 
               | I think that interpretation of the "strong" vs "weak"
               | scale is a valuable one within the context of the blog
               | post. The post is at least partially about how type
               | systems can help the programmer by making them aware of
               | certain kinds of errors (it is also about when: static vs
               | dynamic).
               | 
               | My understanding of the terms covariance and
               | contravariance are a bit shaky. Could you provide an
               | example in another language that you think cannot be
               | expressed using the provided utilities of most Lisp's?
               | 
               | You also mentioned that you don't think most Lisp's have
               | "expressive" type systems. What do you mean by that? When
               | I think of a type system as being expressive, I think of
               | it as having explicit rather than implicit types, which
               | is unrelated to the issue of strongly vs weakly typed and
               | static vs dynamic types. Do you mean more like how you
               | can describe / constrain the relationships between types
               | in certain strongly typed languages?
        
               | packetlost wrote:
               | > I think that interpretation of the "strong" vs "weak"
               | scale is a valuable one within the context of the blog
               | post. The post is at least partially about how type
               | systems can help the programmer by making them aware of
               | certain kinds of errors (it is also about when: static vs
               | dynamic).
               | 
               | Sure, agree. That's also the real point: type systems
               | primarily exist to make semantically impossible
               | computations unrepresentable in the language (at least,
               | without some extra song and dance). To this end, Lisps
               | have rather lackluster type systems, but they don't try
               | to encode much of the languages semantics into a type
               | system.
               | 
               | > My understanding of the terms covariance and
               | contravariance are a bit shaky. Could you provide an
               | example in another language that you think cannot be
               | expressed using the provided utilities of most Lisp's?
               | 
               | The wikipedia article on the topic is a great source: htt
               | ps://en.wikipedia.org/wiki/Covariance_and_contravariance_
               | ...
               | 
               | I'm actually _mostly_ concerned with type invariants (ex.
               | List[int]), which don 't really have much for
               | representation in Lisps from what I've seen. Further, see
               | above about using types to make compile-time
               | assertions/checks about the behavior at runtime.
               | 
               | > You also mentioned that you don't think most Lisp's
               | have "expressive" type systems. What do you mean by that?
               | When I think of a type system as being expressive, I
               | think of it as having explicit rather than implicit
               | types, which is unrelated to the issue of strongly vs
               | weakly typed and static vs dynamic types. Do you mean
               | more like how you can describe / constrain the
               | relationships between types in certain strongly typed
               | languages?
               | 
               | "Expressive" is a nothing word that doesn't have concrete
               | meaning in-context, similar to "strong" type system. That
               | being said, I would say Rust, OCaml, and TypeScript have
               | expressive type systems: the behavior of the language is
               | largely encoded as types. The implicit vs explicit nature
               | of types is not super consequential IMO, it has more to
               | do with how you primarily represent semantic meaning. In
               | lisp, it's symbols. In Rust, it's traits, enums, and
               | structs (+ the affine types, but that's not relevant
               | here).
        
               | gpderetta wrote:
               | Why dynamic typing is required for metaprogramming? D
               | (and rust and c++ to a significantly lesser extent) for
               | example has extremely strong metaprogramming capabilities
               | while being statically typed.
        
               | packetlost wrote:
               | I didn't say it was required, I said it hurts it in Lisps
               | case. One of Lisps strongest features is extreme
               | flexibility and homoiconicity. Strict typing would make
               | it clunkier, though maybe it's worth it for some
               | scenarios.
        
           | PrimeMcFly wrote:
           | In my experience whenever you put effort into making a post
           | like this, outlining the common arguments you hear and your
           | attempt at refuting them, people don't really pay attention
           | and will just repeat the arguments you already addressed,
           | ignoring your refutations.
        
           | insanitybit wrote:
           | Hey, I hear you, and I _commend_ you for your good faith
           | position of  "I want to hear both sides". I'm just not there
           | anymore. The arguments put forth ("the cost is worth it, it
           | makes up for itself", etc) are arguments I've had a million
           | times and I just no longer will engage.
        
             | junon wrote:
             | Same here. Been doing this for too long that I refuse to
             | even bother anymore.
        
             | tasn wrote:
             | Oh, apologies, I misread your comment. I thought you were
             | saying that you won't engage in this discussion because of
             | my strong stance on the topic. I'm a big fan of "Strong
             | beliefs, weakly held".
        
           | stratigos wrote:
           | Youre missing the perspective of a business owner and
           | operator that has to hire many people with diverse patterns
           | of thoughts and beliefs who will most likely work for their
           | organization for less than 24 months.
        
             | AlanYx wrote:
             | If you have a considerable amount of staff turnover, strong
             | typing is a godsend for a large codebase.
             | 
             | Having an order of magnitude more unit tests is another
             | option, but that undermines the alleged "less code" benefit
             | of weak typing.
        
           | randomdata wrote:
           | _> I just don 't understand why anyone would ever choose not
           | to use types._
           | 
           | Is there a language out there that gives you that choice?
           | 
           | I expect you mean choose not to use strong static typing as
           | per the original piece? Compatibility is a pretty good
           | reason. I'd like to see Javascript die in the fiery pits of
           | hell as much as the next guy, but its positioning means it is
           | almost inevitable that some system will make it the only
           | reasonable choice for you to choose if you want to build for
           | that system.
           | 
           | Typescript doesn't help. It adds static typing, but not
           | strong typing.
        
             | junon wrote:
             | Python and PHP both have type hints that are natively
             | ignored by the language if present, but can be checked if
             | you have enough of them, if that's what you mean.
        
               | randomdata wrote:
               | No, I mean it lacks strong typing. C and C++ also lack
               | strong typing even with static typing being a core
               | feature and checked at compile time.
        
               | junon wrote:
               | There's no agreed upon definition of "strong" vs "weak"
               | so you'll have to elaborate a bit.
        
               | randomdata wrote:
               | The only other use I'm familiar with where strong types
               | are used to describe the equivalent of static types, but
               | we've made clear distinction between the two here. What
               | other definition is there?
               | 
               | Usually: A strong type system does not allow types to
               | change after being established. A weak type system allows
               | types to change. This is also described in the original
               | article.
        
               | 1-more wrote:
               | How is that different from static typing?
        
               | SkyMarshal wrote:
               | My personal notion of a strong type system is one built
               | around function type signatures.
               | 
               | In order to have that, you need static typing of
               | variables and constants, like most statically typed
               | imperative languages have. But you also need a method to
               | specify required input types and expected output types of
               | all functions.
               | 
               | In a purely functional language like Haskell where there
               | are _only_ functions, and functions are first class and
               | can be both inputs to or outputs from other functions,
               | then the entire operation of the program is encapsulated
               | in its function type signatures.
               | 
               | The entire flow of data and logic through the program can
               | be type-checked by the compiler, and function
               | implementations checked against their type signatures.
        
               | AnimalMuppet wrote:
               | C++ has casts. I don't regard those as making it a "weak"
               | type system. I regard it as "strong type system with
               | escape hatches", which is not the same thing. A strong
               | type system should not be a straightjacket. (Languages
               | that try to make types bulletproof tend to get used less
               | than languages that allow escape hatches, and rightly so.
               | The language designer never knows what the union of all
               | use cases will be. Good language designers know that the
               | user may have a case the designer didn't think of, and
               | allow some flexibility to hopefully handle it.)
        
               | zabzonk wrote:
               | >A strong type system does not allow types to change
               | 
               | so... like in c++?
        
               | neverartful wrote:
               | No. C++ does allow types to change. That's exactly what
               | casts are for.
        
               | zabzonk wrote:
               | no. c++ allows you to convert a value of one type into a
               | value of another type (in a very limited number of cases)
               | but you cannot change the type of an object.
        
               | gpderetta wrote:
               | You can't change the type of an object in C++ so I'm not
               | sure how your definition applies.
               | 
               | Generally "strong" vs "weak" typing[1] is an ill-defined
               | an mostly useless definition.
               | 
               | [1] as opposed to static vs dynamic or safe vs unsafe.
        
               | syndicatedjelly wrote:
               | What about with type conversion?
               | 
               | https://en.cppreference.com/w/cpp/language/explicit_cast
        
               | gpderetta wrote:
               | Casts don't change the type of an object. They might
               | create a new object of another type from the first one.
               | 
               | edit: I guess what you want to say is that implicit casts
               | make a type system weak. But even there there is plenty
               | of wiggle room: I think that everybody agree that
               | implicitly converting the string "1" to an integer is bad
               | (which is not allowed in C++). Narrowing conversions are
               | arguably bad (they are sometimes allowed in C++), but
               | some other implicit conversions are hard to argue against
               | (int to long for example, or derived to base).
        
               | nyssos wrote:
               | > A strong type system does not allow types to change
               | after being established. A weak type system allows types
               | to change.
               | 
               | For dynamic types, sure, that's a reasonable enough
               | definition. But it doesn't really make sense for static
               | types: they're attached to expressions in your source
               | code, not runtime values.
        
               | pavlov wrote:
               | C++ lacks strong typing? I'm curious what the type system
               | is missing to qualify.
               | 
               | Or do you mean that the C-based escape hatches like
               | casting pointers make the type system inherently weak?
               | You don't have to use them though...
        
               | JonChesterfield wrote:
               | C++ has chosen a special place in the hellscape of
               | language design by allowing you to silence the compiler
               | using casts, where almost anything you do with the
               | resulting object is undefined behaviour no diagnostic
               | required.
               | 
               | Said UB is observationally indistinguishable from
               | miscompilation under some toolchains under some
               | optimisation controls.
               | 
               | It also has various bolt on weirdness like const doesn't
               | mean the thing won't be changed by some other pointer so
               | you can't constant propagate based on it, unless it's
               | written on the global, at which point attempts to mutate
               | it anyway may succeed under the usual UB challenges.
               | 
               | Maybe that's a "strong" type system, but you'd only
               | define it like that if you started by taking C++ as
               | axiomatically reasonable.
        
               | robertlagrant wrote:
               | You don't have to make type errors either :-)
        
               | AnimalMuppet wrote:
               | Sure. But you have to deliberately use a cast; people
               | rarely make deliberate type errors.
        
             | prewett wrote:
             | Static typing is already quite a help, as it makes whole
             | categories of errors compile-time errors.
             | 
             | > I'd like to see Javascript die in the fiery pits of hell
             | as much as the next guy
             | 
             | Part of the problem is that some of those "next guys" don't
             | have the experience and/or vision to realize that it needs
             | to die. Perhaps we should emulate Cato in our subsequent HN
             | posts:
             | 
             | And furthermore, I consider it necessary that Javascript be
             | replaced with WebAssembly so that we can use well-designed
             | languages in the browser.
        
           | ndr wrote:
           | Consider reading/watching Rich Hickey's talk Effective
           | Programs [0][1] and Maybe Not [2][3]
           | 
           | In [0] in particular there're slides 22/23, here is part of
           | the transcript but makes more sense with the slides on:
           | 
           | > And you can call them problems, and I'm going to call them
           | the problems of programming. And I've ordered them here [...]
           | I've ordered them here in terms of severity. And severity
           | manifests itself in a couple of ways. Most important, cost.
           | What's the cost of getting this wrong? At the very top you
           | have the domain complexity, about which you could do nothing.
           | This is just the world. It's as complex as it is. > > But the
           | very next level is the where we start programming, right? We
           | look at the world and say, "I've got an idea about how this
           | is and how it's supposed to be and how, you know, my program
           | can be effective about addressing it". And the problem is, if
           | you don't have a good idea about how the world is, or you
           | can't map that well to a solution, everything downstream from
           | that is going to fail. There's no surviving this
           | misconception problem. And the cost of dealing with
           | misconceptions is incredibly high. > >So this is 10x, a full
           | order of magnitude reduction in (?) severity before we get to
           | the set of problems I think are more in the domain of what
           | programming languages can help with, right? And because you
           | can read these they'll all going to come up in a second as I
           | go through each one on some slide so I'm not going to read
           | them all out right now. But importantly there's another break
           | where we get to trivialisms of problems in programming. Like
           | typos and just being inconsistent, like, you thought you're
           | going to have a list of strings and you put a number in
           | there. That happens, you know, people make those kinds of
           | mistakes, they're pretty inexpensive.
           | 
           | [0] Video: https://www.youtube.com/watch?v=2V1FtfBDsLU
           | 
           | [1] Slides and transcript: https://github.com/matthiasn/talk-
           | transcripts/blob/master/Hi...
           | 
           | [2] Video https://www.youtube.com/watch?v=YR5WdGrpoug
           | 
           | [3] Slides and transcript https://github.com/matthiasn/talk-
           | transcripts/blob/master/Hi...
        
         | bcrosby95 wrote:
         | I don't use dynamically typed languages because they're
         | dynamically typed. I use them for other reasons and they happen
         | to be dynamically typed.
         | 
         | I'm not going to argue that these features are only possible
         | because of dynamic typing, but regardless, statically typed
         | languages tend not to have them.
         | 
         | Elixir may get "some form" of typing, but it likely won't be
         | traditional static typing.
        
           | syndicatedjelly wrote:
           | What are those features?
        
             | bcrosby95 wrote:
             | STM, REPL, and data driven nature of Clojure. I know most
             | people don't use STM in Clojure, but I find it to be a
             | killer feature for some projects. Combined with pervasive
             | immutability and it enables concurrent designs that are
             | very difficult to pull off in other languages.
             | 
             | For Elixir, the concurrency model and supervisor trees.
             | It's a perfect fit for some problems, and in general as a
             | small company, the projects we use Elixir on greatly
             | simplifies our production environment which is always a
             | win.
             | 
             | Most of my focus when designing a project is to enable
             | people with less experience than me to contribute in a bug-
             | free fashion in the face of concurrency and parallelism.
             | Sometimes that involves picking a funny language, sometimes
             | it doesn't.
        
         | AlchemistCamp wrote:
         | This is a very arrogant and dismissive attitude to take.
         | Consider that both pg and DHH prefer dynamic typing. Maybe you
         | can think less of them as devs, but what each built is
         | undeniable.
         | 
         | What have _you_ built or added to the field that justifies such
         | a lack of tolerance of those who don't subscribe to your point
         | of view?
        
           | insanitybit wrote:
           | I reject the idea that pg/DHH should be treated with any
           | authority here, and I reject the idea that I need to prove my
           | authority to you.
           | 
           | That said, yes, of _course_ my post is arrogant and
           | dismissive. I am outright saying I won 't engage in a
           | conversation. I'm comfortable with that.
        
         | fsdjkflsjfsoij wrote:
         | This is basically where I am at. Most libraries and
         | applications are trivially typed even in languages with
         | relatively poor type systems like Go and Java. The necessity,
         | or even benefit, of weak and/or dynamic typing is extremely
         | rare and most languages have workarounds or escape hatches for
         | those exceedingly rare cases.
         | 
         | Dynamic typing also makes a ton of optimizations basically
         | impossible and even after monumental efforts languages like
         | Javascript are still quite slow, inconsistent and memory
         | inefficient outside of trivial benchmarks.
        
           | vasergen wrote:
           | > Javascript are still quite slow
           | 
           | Can you describe your usecase for which JavaScript is slow?
           | There are many languages that are slower than js like python
           | or elixir, but they are doing just fine, that's why I won't
           | agree that js is slow, but sure there are cases for which js
           | just wasn't designed, and any CPU intensive task will be
           | slow, but there are ways to get around it as well.
        
           | diggan wrote:
           | > Javascript are still quite slow, inconsistent and memory
           | inefficient outside of trivial benchmarks.
           | 
           | I thought this meme was dead already. Of course, you might
           | not be able to squeeze out the same amount of performance
           | compared to a brilliantly written C or Rust program, but for
           | what it is, JavaScript is pretty damn fast already.
           | 
           | DOM manipulation on the other hand, is still a very common
           | bottleneck people come across when writing typical JavaScript
           | code.
        
             | fsdjkflsjfsoij wrote:
             | > but for what it is, JavaScript is pretty damn fast
             | already.
             | 
             | It's fast compared to other dynamically typed language
             | implementations but it's still very slow compared to
             | basically all of the popular statically typed languages.
        
               | wilde wrote:
               | JustJS would like a word https://www.techempower.com/benc
               | hmarks/#section=data-r20&tes...
        
               | fsdjkflsjfsoij wrote:
               | Trivial benchmarks where all of the significant data
               | structures and networking are done in C++ and the tiny
               | amount of Javascript is just passing some strings around.
               | I guess it's "fast" if you can restrict yourself to
               | little more than hello world where you do nothing more
               | than pass a few strings to functions written in faster
               | languages.
               | 
               | Notice that in the Java, C#, Go, Rust, Swift or Ocaml
               | benchmarks almost all of the underlying data structures
               | and much of the networking stack are built in the
               | respective language. This is not possible with
               | Javascript, Python, Ruby etc. because it would be
               | ludicrously slow and extremely memory inefficient.
        
               | cogman10 wrote:
               | > It's fast compared to other dynamically typed language
               | implementations
               | 
               | true
               | 
               | > it's still very slow compared to basically all of the
               | popular statically typed languages.
               | 
               | Not true.
               | 
               | The main slowdown for javascript (AFAIK) is the checks
               | the optimizer has to put into place to ensure the
               | assumptions it's made about the type are still valid. If,
               | however, those assumptions are valid then javascript ends
               | up emitting pretty much the same assembly that you'd see
               | for and highly optimized statically typed language. In
               | fact, there are some circumstances where it can beat a
               | language like C++ or Rust due to the fact that it has to
               | incorporate runtime information into optimizations.
               | 
               | With C++ or rust, if you add dynamic dispatch, unless you
               | are doing PGO and whole program optimization, you are
               | pretty much sunk with 2 memory lookups on every function
               | call. This is the case where javascript can end up
               | beating C++/Rust.
               | 
               | (All of this is talking about hot code after warmup.
               | During the initial execution javascript will almost
               | certainly always be slower).
               | 
               | Part of the proof of this was asm.js, the precursor to
               | wasm. V8 at the time it was introduced could execute
               | asm.js nearly as fast as what firefox could do with it's
               | optimized asm.js compiler. That is, when you stripe out
               | all the actions that make javascript slow, it very often
               | ends up being just as fast as a compiled language.
               | 
               | What stuff ends up making it slow? Generally speaking,
               | stuff that makes the types unpredictable (adding fields,
               | removing fields, sending in a number and a string and
               | expecting the VM to be able to handle both).
               | 
               | You can see a lot of this writeup around the discussions
               | about why Dart was originally "optionally typed".
               | Basically, the entire selling point to make dart fast was
               | simply to remove the abilities to dynamically change
               | types like you have in javascript. With that, the VM
               | authors at the time were capable of making a VM that's
               | every bit as fast as what Java has.
        
               | gpderetta wrote:
               | > With C++ or rust, if you add dynamic dispatch, unless
               | you are doing PGO and whole program optimization, you are
               | pretty much sunk with 2 memory lookups on every function
               | call. This is the case where javascript can end up
               | beating C++/Rust.
               | 
               | GCC at least is capable of speculative devirtualization
               | by using local heuristics, without PGO. And of course it
               | is capable of devirtualizing in many cases when the
               | knowledge actual type can be constant-propagated.
               | 
               | Also note that the vast majority of calls are not dynamic
               | in C++ (as opposed to most dynamic languages), so
               | devirtualization is significantly less impactful.
        
               | fsdjkflsjfsoij wrote:
               | > That is, when you stripe out all the actions that make
               | javascript slow, it very often ends up being just as fast
               | as a compiled language.
               | 
               | ok...
               | 
               | > In fact, there are some circumstances where it can beat
               | a language like C++ or Rust due to the fact that it has
               | to incorporate runtime information into optimizations.
               | 
               | People used to make the same claim about Java and in
               | every single example I've ever seen the Java/Javascript
               | is extremely optimized, performance isn't consistent
               | across VM versions, and the C++/Rust is extremely naive
               | (usually allocating unnecessarily and not using arenas in
               | hot paths that are allocation heavy).
        
               | PH95VuimJjqBqy wrote:
               | absolutely spot on, there was a time when Hotspot was
               | going to bring Java to the promised land.
               | 
               | It never happened.
        
               | PH95VuimJjqBqy wrote:
               | I think what cracks me up about this conversation is that
               | it's an almost verbatim repeat of a conversation I had on
               | reddit a few weeks ago.
               | 
               | There's a certain segment of the developer population
               | that I don't think realizes just how fast C and C++ are.
               | Javascript is _relatively_ fast when compared to other
               | dynamic languages, but not when compared to C, C++,
               | FORTRAN, etc.
        
           | da4c30ff wrote:
           | The take I have is that with a dynamically typed language you
           | still have a static analysis step. It's just that the
           | analysis happens in your and other developers' brain and it
           | is objectively worse. I honestly can't think of a single
           | thing in favor of dynamic typing.
           | 
           | I write Clojure in my day job and it's insane how often we
           | have issues where it would have been immediately caught by a
           | static type check.
        
             | waffletower wrote:
             | May I interest you in some unmentioned static analyzer
             | possibilities for Clojure: https://github.com/clj-
             | kondo/clj-kondo https://github.com/jonase/eastwood You seem
             | dissatisfied with Clojure in your day job -- I am sure that
             | there are others that would be happier in your situation.
        
               | da4c30ff wrote:
               | I'm aware of these, but thank you nevertheless. Clojure
               | has plenty of nice things balancing the scales, so it's
               | not all pain and misery!
        
             | stefcoetzee wrote:
             | I'd love to learn more. Are you part of a large team
             | (enterprise or SMB, whatever you can share)?
             | 
             | How have you experienced using Type Clojure, spec, Malli,
             | etc. to determine correctness?
             | 
             | I've only worked on solo projects with Clojure, with most
             | of it fitting into my head. I imagine with teams of size N
             | > 1 things can change quite a bit.
        
         | [deleted]
        
         | jerf wrote:
         | There's a temporal component to the argument. Strong typing in
         | the 1990s wasn't very good. Dogma at the time resulted in very
         | rigid designs. The verbosity of it all was staggering.
         | Incorrectly-used Hungarian notation ran rampant and made
         | everything hard to read while still not helping anything [1].
         | The costs were a lot higher than it is today and the benefits a
         | lot less.
         | 
         | Nowadays, the static typing is _much_ nicer, with both higher
         | benefits and lower costs, and it makes the costs /benefits
         | analysis much more likely to come out in favor of static types.
         | 
         | In the late 1990s when I was cutting my teeth, I did a lot of
         | Python, and I was almost 100% dynamic language until ~2015. In
         | hindsight, I might do the same again even if thrust back in
         | time. There just isn't a _great_ static option back then. (I 'm
         | not saying 2015 is the year it became practical, I'm saying
         | that's when _I_ finally moved into static languages. 2010-2015
         | or so I was in Erlang, doing things that most other languages
         | couldn 't do at the time, so that forced me into a dynamic
         | language. C# was looking pretty good in that time frame too, it
         | just wouldn't have run the systems I had on anything like the
         | resources I had at the time. It could probably easily do it in
         | 2023 though.)
         | 
         | Now I even prototype in static systems, and it's a better
         | experience than prototyping in Python was. Like, by quite a
         | lot, honestly. In the end, I don't find it that much of an
         | impediment to make sure that if I want to call a method on a
         | thing, that the method actually exists.
         | 
         | Dynamic typing will never disappear; there's a certain small
         | size of task for which it'll always be more advantageous than
         | static typing, and while said tasks may be small, there's a lot
         | more of them than there are large tasks, so it's a completely
         | valid and sizable niche. But I do think over the next 10-20
         | years we're going to see the "scripting" languages return back
         | to "scripting" and away from "systems".
         | 
         | I think that in the end, the dynamic scripting languages being
         | used for large tasks will be seen as a reaction to a
         | misdiagnosis of the problems in the 1990s. The code was
         | atrocious in the 1990s not because it was statically typed, and
         | therefore the solution is to go dynamically typed. The code was
         | atrocious in the 1990s because it was _poorly_ statically
         | typed, and the solution was to get better. That said,  "getting
         | better" did take a long time, and for many legitimate reasons.
         | 
         | (Much ink is spilled on the so-called rapid pace of
         | technological innovation in our industry, but programming
         | languages move on decadal scales. Programming languages still
         | have only barely grappled with a multicore world, and haven't
         | grappled with a heterogenous computing world at _all_ (GPUs on
         | one end, efficiency cores on the other). Things are not always
         | in as much motion as we fancy.)
         | 
         | [1]: Particularly, Hungarian notation is supposed to
         | _supplement_ the type, not just reiterate it. If you 're in a
         | language where you can't easily declare "a width is an int",
         | then Hungarian notation suggests calling a width variable
         | something like "wdthDialog", so that you stand a chance of
         | noticing that you passed a "hghtDialog" in the wrong place. But
         | the way it was used a lot of the time is you got "u16Width"
         | instead, where u16 meant unsigned 16 bit int... but that's
         | already in the type. Using it that way just adds an extra layer
         | of hierglyphicness to the already ugly code. One of the several
         | innovations that made static typing languages more feasible is
         | that in most languages designed in the last couple of decades,
         | you can declare something like this with something like "type
         | Width int", and then you don't need to label any variables with
         | it at all, the compiler enforces it.
        
           | justincredible wrote:
           | [dead]
        
         | pfdietz wrote:
         | Strong static typing is useful in the environment where the
         | code is not adequately tested. That's because tests adequate to
         | make the code bulletproof will also detect the problems strong
         | static typing could detect, rendering SST superfluous.
         | 
         | So, how often is poorly tested code out there? From the
         | popularity of strong static typing, it must be ubiquitous.
        
           | d3w4s9 wrote:
           | No. It is useful in almost every environment other than
           | things like REPL. I can write TypeScript for hours without
           | writing any tests, run it and fix a few minor logic bugs and
           | code is production level, which is great for prototyping. No
           | chance with plain JavaScript without typing -- it would be at
           | least a day or two and I would constantly run into stupid
           | typos or other errors that can only be found at runtime.
        
           | sneed_chucker wrote:
           | Yeah, big piles of untyped Django spaghetti need a behemoth
           | suite of integration tests in order to remotely approach the
           | sort of runtime guarantees that typed languages give you for
           | free.
           | 
           | When you use a typed language, you can use your integration
           | tests to actually verify business logic, exception handling,
           | etc. instead of having to write a dozen test cases to make
           | sure that doThing(table, index,*kwargs) doesn't blow up when
           | 'table' is a list or 'index' is bytes...
        
             | pfdietz wrote:
             | If you adequately test your code for logic bugs, you test
             | the type correctness _for free_. So, yeah, writing those
             | logic tests is hard. But at least they are finding bugs
             | that static type checking never will (absent the
             | unrealistic scenario of proving your program correct via a
             | type system.)
             | 
             | (It won't find latent bugs that can't currently be
             | exercised, so the testing can't be one and done.)
        
               | _dain_ wrote:
               | you can't ensure that you hit every possible case in your
               | test suite. type errors can still slip through in
               | production, just like logic bugs do. it happens all the
               | time in real-life code. that "adequately" is a no-true-
               | scotsman.
               | 
               | if you use a static type system you can _guarantee_ there
               | will be no type errors at runtime. why on earth wouldn 't
               | you choose that? you can still write logic tests!
               | 
               | and when you leverage the type system to make illegal
               | states unrepresentable, you can make certain classes of
               | logic error impossible as well. some of your tests become
               | tautologies and you can delete them.
        
               | pfdietz wrote:
               | You are assuming type errors are caught by tests
               | explicitly written to detect them, as opposed to being
               | found by other kinds of tests. For example, property
               | based tests, with automated generation of inputs to a
               | program or module, don't explicitly test for type errors,
               | but are still (in my experience) quite good at hunting
               | them out.
               | 
               | What testing cannot find are latent errors not exercised
               | by the program. Do I care about these, though? Arguably
               | these would be found by testing internal interfaces and
               | elimination of code not reachable by tests.
               | 
               | The general argument I am trying to make is that the
               | marginal value obtained by strong static typing declines
               | as testing increases, and that in the limit goes to zero.
               | If a program is adequately tested, is it still worth
               | doing? This is not clear to me, and the arguments given
               | here have not convincingly demonstrated that it is worth
               | it.
               | 
               | Also: if you find yourself in a situation where strong
               | static typing seems useful, you should be alarmed. It
               | means you aren't testing your code very thoroughly.
        
               | _dain_ wrote:
               | _> You are assuming type errors are caught by tests
               | explicitly written to detect them, as opposed to being
               | found by other kinds of tests._
               | 
               | I am not assuming that.
               | 
               | honest question: what language do you have in mind when
               | you think "static types"? your perspective is so starkly
               | different to mine, you seem to be operating under totally
               | different assumptions about what types can and can't do.
               | 
               | I mean this sentence:
               | 
               |  _> Also: if you find yourself in a situation where
               | strong static typing seems useful, you should be alarmed.
               | It means you aren't testing your code very thoroughly. _
               | 
               | is just baffling to me. it's so self-evidently absurd
               | that I can't even argue against it. what is there even to
               | say?
               | 
               | have you even used a modern statically typed language,
               | with type inference, generics, null safety, algebraic
               | data types, pattern matching, etc? I cannot imagine
               | trying to maintain a big codebase without them. they
               | don't slow me down, they speed me up. they aren't just
               | about catching trivial int-instead-of-string bugs, they
               | are are core tool for _modelling_ data and business
               | logic. they let me define problems out of existence (see
               | e.g. this series of posts
               | https://fsharpforfunandprofit.com/posts/designing-with-
               | types... for an introduction).
               | 
               | and then there's rust and newer-generation languages with
               | borrow checkers and affine/linear types, ruling out
               | entire classes of memory and concurrency bugs ... your
               | test suite cannot rule out data races, but rustc sure
               | can.
               | 
               | you are making the same arguments people were making in
               | the 2000s when most static languages sucked because they
               | didn't have these features. I don't want to go back to a
               | time before sum types.
               | 
               |  _> What testing cannot find are latent errors not
               | exercised by the program. Do I care about these, though?_
               | 
               | you should, because in production your program must
               | endure orders of magnitude more variety in inputs,
               | uptime, and runtime conditions than the test suite can
               | exercise. it can and will get into weird states you
               | didn't anticipate. yes, you can fuzz, yes you can
               | property test, I know all about that. those things are
               | good. but I don't get why you wouldn't _also_ use a
               | static type system to _provably_ rule out classes of
               | problem across _all possible_ code paths. why settle for
               | less?
        
           | xmcqdpt2 wrote:
           | High test coverage is useful in the environment where the
           | code is not adequately typed. That's because static types
           | adequate to make the code bulletproof will also detect the
           | problems unit tests could detect, rendering high unit test
           | coverage superfluous.
           | 
           | So, how often is poorly typed code out there? From the
           | popularity of test coverage tools, it must be ubiquitous.
        
             | pfdietz wrote:
             | The turned-around argument has a problem: testing should
             | reveal type bugs, but static typing (of the kind typically
             | discussed for mainstream languages) can't reveal non-type
             | bugs.
             | 
             | In a situation where extreme levels of testing occurs, the
             | extra assurance from strong typing is minimal. In a
             | situation where strong typing is enforced, extra testing is
             | still very useful.
        
           | user3939382 wrote:
           | Integration tests are different, but I tend to believe that a
           | strong enough type system should be able to negate the need
           | for unit tests completely.
           | 
           | If anyone can think of something a unit test could test for
           | that an arbitrarily* complex/strong type system couldn't I'd
           | be interested to hear it. It's possible, I just can't think
           | of any.
        
             | bluGill wrote:
             | Unit tests and types solve somewhat different problems. You
             | can force a unit test to check everything a type system
             | does with effort (mostly by throwing wrong types at your
             | API and verifying you get an error), but I'm not sure how
             | you would use the type system to enforce sort() actually
             | sorts. Sure sort can take a listOfFoo and return a
             | sortedListOfFoo - but that doesn't verify sortedListOfFoo
             | is actually sorted - and in many cases I want an API that
             | is find with listOfFoo but should handle sortedListOfFoo as
             | well.
        
               | skulk wrote:
               | With dependent types you can encode any proposition in
               | first-order logic (?). You can indeed define an array
               | type that is necessarily sorted. It won't be pretty but
               | it's possible.
               | 
               | More info here: https://en.wikipedia.org/wiki/Curry%E2%80
               | %93Howard_correspon...
        
             | pfdietz wrote:
             | When I say adequately tested, I mean much more than unit
             | tests. Unit tests aren't going to give you bulletproof
             | code. They don't detect bugs that arise from interactions
             | at a higher level.
             | 
             | An arbitrarily complex type system, with dependent types,
             | could detect any bug, since it's formally equivalent to
             | requiring the program be proved correct. But using such a
             | type system is so onerous that I don't know anyone who
             | realistically does it in production.
             | 
             | If you wrote such types, you're basically giving a formal
             | specification of what the program is supposed to do. That
             | could then be used, and likely much more easily, for high
             | volume property-based testing.
        
             | _dain_ wrote:
             | I like type systems as much as anyone but I can't see how
             | your type system will check that sin(pi) == 0
             | 
             | if you have a type system expressive enough to do things
             | like that, you've basically got another turing-complete
             | layer on top of your existing language, which is itself ...
             | dynamically typed.
        
           | yakshaving_jgt wrote:
           | > Strong static typing is useful in the environment where the
           | code is not adequately tested. That's because tests adequate
           | to make the code bulletproof will also detect the problems
           | strong static typing could detect, rendering SST superfluous.
           | 
           | Ok, but it's cheaper to not have to write those tests than it
           | is to write those tests.
        
             | pfdietz wrote:
             | Yes. It's cheaper to have a lower assurance your program is
             | correct than to have a higher assurance. The claim I'm
             | making is that at the high end, the extra assurance from
             | strong static typing becomes minimal.
        
               | yakshaving_jgt wrote:
               | > Yes. It's cheaper to have a lower assurance your
               | program is correct than to have a higher assurance.
               | 
               | That's quite clearly not what I'm saying.
        
           | ozr wrote:
           | Ubiquitous is a good guess.
        
           | soggybutter wrote:
           | Good tests only render SST superfluous insofar as the person
           | writing the tests is capable of never making a mistake. The
           | thing about good static type systems is they don't typically
           | make mistakes in the domain they work in. The fact that you
           | don't have to muddy your test with a bunch of type checking
           | logic and instead focus on the thing actually being tested is
           | just the cherry on top.
        
           | dolmen wrote:
           | The point of static typing is that the compiler does checks
           | before your program even starts. And that avoids to write lot
           | of coverage tests that are needed (but usually just ignored)
           | with languages that massively use loosely typed data
           | containers (variables).
        
             | pfdietz wrote:
             | Sure, if you're going to be in an environment where the
             | code is going to be bad because of inadequate testing (and
             | I admit this is quite common, due to the cost of the
             | testing needed), static typing lets it be somewhat less
             | bad. It's just important to understand it's a band-aid, not
             | a panacea.
        
               | marcosdumay wrote:
               | Testing is a bandaid that only pretends to show that your
               | code is correct.
               | 
               | Static verification (what includes static types) is the
               | real deal.
               | 
               | That said, WTF is there with people insisting that types
               | must be either static or dynamic, and that dynamic types
               | are useless?
        
               | pfdietz wrote:
               | Static typing, as done in mainstream languages, doesn't
               | show your program is correct. Is you compiler written in
               | a mainstream language correct just because it compiles?
               | Of course not. Don't point to academic curiosities with
               | dependent types if they aren't actually used. Extensive
               | testing, on the other hand, _is_ used in the  "real
               | world" for assurance.
        
               | marcosdumay wrote:
               | Every code out there on the real world is full of
               | baindaids and duct tape. Yet, the actual amount varies a
               | lot, as does the centrality of the patched things.
        
               | yakshaving_jgt wrote:
               | This is the classic "Uncle Bob" style false dichotomy.
               | 
               | Whoever said you can only pick one of the two approaches?
        
           | mejutoco wrote:
           | That is a very original take, but I think you have it
           | reversed. Typing removes the possibility of _some_ errors.
           | Those are tests you do not _need_ to write (you can still
           | write them if you want), thus having more time and attention
           | to write tests that matter. Typing is a baseline, and
           | anything over that baseline you can deal with with tests.
           | 
           | It is like the things you already trust when you code. Let's
           | say, that the file system works, that the network stack of
           | your OS works, or that the cpu works. You can rely on them to
           | use your time for the things that matter. This is a much
           | better model than simply testing everything yourself since,
           | as the tests number increase, any change to the codebase
           | involves more and more test changes.
           | 
           | > Strong static typing is useful in the environment where the
           | code is not adequately tested. That's because tests adequate
           | to make the code bulletproof will also detect the problems
           | strong static typing could detect, rendering SST superfluous.
           | 
           | Your logic is the same as follows: seat belts are useful in
           | an environment where drivers are not driving adequately.
           | That's because adequate drivers will drive in a way to avoid
           | any danger that the seat belt would prevent, rendering seat
           | belts superfluous.
           | 
           | Ultimately, the problem is adequate drivers (as in described
           | above) or bulletproof tests do not exist, they are just a
           | concept. A test can prove the presence of an error, not the
           | lack of errors, and the argument only works in absolutes.
        
             | pfdietz wrote:
             | You seem to be thinking that testing for type errors is
             | something additional to general testing. It's not. With
             | sufficiently strong logic testing, the testing for type
             | errors comes along for free.
             | 
             | The analogy with driving doesn't make much sense. After
             | all, accidents sometimes happen without the driver being to
             | blame, and the marginal cost of putting on a seat belt is
             | very low.
        
               | mejutoco wrote:
               | With sufficiently adequate drivers seatbelts are
               | superfluous indeed.
               | 
               | Apart from an analogy is a template of your argument. It
               | is the logic of the argument itself.
               | 
               | Errors also happen sometimes without type systems being
               | to blame (they only catch a subset of errors).
               | 
               | The marginal costs of a type system is usually very low
               | too, so it seems to be a great fit.
        
           | Kuinox wrote:
           | Tests is testing your program against samples, where strong
           | typing make your program incorrect on a whole spectrum of
           | samples.
        
           | ShellfishMeme wrote:
           | Strong types aren't just a correctness guarantee, they also
           | help to discover structure and interfaces that previously
           | were implicit.
           | 
           | If a developer can jump into an unknown part of a codebase
           | and quickly see that following a certain structure will
           | automatically make their code work for them without needing
           | to read all the code first and double checking if it's just a
           | random convention versus a strict interface so they don't
           | reinvent the wheel or build code that doesn't fit in with the
           | existing structure, then that's worth a lot and something you
           | cannot simply cover with tests.
        
         | brightball wrote:
         | I'm firmly in camp "it depends" but it was nice almost talking
         | to you. :-)
        
         | c048 wrote:
         | People that still want to try and fight it either:
         | 
         | - Use notepad for development (don't laugh, I've actually
         | encountered a dev who's choice IDE was notepad).
         | 
         | - Never worked with more than 1 person on a project.
         | 
         | - Never worked on anything but tiny projects.
         | 
         | - Never re-opened a project after having worked on a different
         | project for several weeks.
        
           | Qwertious wrote:
           | You should legitimately try a project in notepad. Not
           | Notepad++, specifically Notepad. Probably a very short
           | project, but you should give it a shot. It'll give you a bit
           | of a perspective. And some real appreciation for Notepad++.
        
             | bluGill wrote:
             | I've been forced to use ed (serial connection to an
             | embedded device that didn't support TERM), what does
             | notepad give?
        
         | manicennui wrote:
         | This is the sort of position that is baffling to me. Software
         | engineers claim to be very logical, but this boils down to a
         | preference being stated as some kind of objective truth. Show
         | the evidence (not anecdotes) that static typing gives benefits
         | that are worth the cost. My anecdotal evidence is that I rarely
         | come across problems in production code that would be solved by
         | static typing and people make the same sorts of logic mistakes
         | in languages like Java and Typescript.
        
           | manicennui wrote:
           | Arguably, nullability and mutability are issues that cause
           | far, far more issues than dynamic typing.
        
             | tubthumper8 wrote:
             | Null reference errors are examples of errors that can be
             | caught before runtime by a static type system. The fact
             | that static type systems like Java don't catch this is
             | evidence that static vs. dynamic is not a binary - some
             | static type systems are better than others.
        
         | bitblender wrote:
         | I don't consider it productive to be personal about technical
         | topics. It's best to divorce yourself and the other party from
         | the issue to limit as much bias as possible. You don't need to
         | worry about the good-faithness of an objective, egalitarian
         | discussion. It's never truly objective, but you can at least
         | catch yourself saying things like "I might think less of you as
         | a developer" and recognize that's a preconceived notion. In
         | some cases, it may be turn out to be accurate, but it's
         | definitely not always. Dynamically typed languages have had an
         | important role historically in software. We should not
         | categorically denounce people who prefer it as lesser
         | developers. I also generally prefer static types.
        
           | mvdtnz wrote:
           | I think you're being a bit too sensitive, and it's not
           | personal. Someone is espousing a (bad) technical opinion
           | about their field of work, it's not unreasonable to say you
           | respect them less in their field of work. That's not
           | personal.
           | 
           | It's like if you met a builder who refused to use a hammer
           | and insisted on bashing nails in with the back of their
           | drill. It's not "personal" to say you'd respect that person
           | less as a builder, regardless of how much you'd enjoy having
           | a drink with them.
        
             | bitblender wrote:
             | It is "personal" if you attach someone's technical opinion
             | to broader implications about their own competence. If you
             | disagree with a technical opinion, say so and move on,
             | there is no reason to even discuss someone's own personal
             | skillset, experience, or value as a developer. It's a silly
             | fallacy to automatically label people who disagree with you
             | as incompetent. All it does is foster bias and stifle
             | actual discussion. The responses to this post are evidence
             | that this is not as cut and dry as the original posts
             | suggests, so I suggest we try our best not to cover our
             | ears and embrace tribalism just because we think less of
             | someone's opinion. I don't think I'm being oversensitive by
             | saying this is unproductive dogmatism. It is my honest
             | opinion, yet I do not extrapolate to mean anything about
             | the proponents' value as a developer. Unconscious bias is a
             | pervasive problem for everyone, especially when it comes to
             | binary holy wars like static vs. dynamic types. This is
             | more akin to a builder who uses a nail gun rather than a
             | hammer. Hammer enthusiasts can either acknowledge that both
             | approaches have tradeoffs or they can petulantly insist
             | that people who don't use their methods aren't "real"
             | builders.
        
               | mvdtnz wrote:
               | I'm sorry but this is a discussion about their
               | competence. You can't separate someone's opinions on
               | technical topics from their competence in the very
               | technical field you're discussing. If a cartographer has
               | the "opinion" that the world is flat then that directly
               | speaks to their competence as a cartographer.
        
               | bitblender wrote:
               | For starters, "the world is flat" is falsifiable and
               | trivially disproven with evidence. "Dynamic types are
               | better" is neither of these. If you're going to pin
               | someone's professional value to a single technical
               | opinion, you should at least be able to back it up with
               | data.
        
           | insanitybit wrote:
           | I explicitly said "as a developer" because it's not a
           | personal judgment. You can be a good person and also have a
           | terrible take as a software engineer.
           | 
           | > We should not categorically denounce people who prefer it
           | as lesser developers
           | 
           | I don't think you've justified this point. I'm comfortable
           | with my position on this.
        
             | bitblender wrote:
             | Again, I don't mean "personal" in the sense that you are
             | making a statement about someone's worth as a person. It's
             | "personal" because you extrapolate information about an
             | individual person's technical skills from a single opinion
             | than you have any real factual justification to do so.
             | People will always find ways to defy your preconceived
             | notions.
        
             | PH95VuimJjqBqy wrote:
             | to add, I agree with you mostly.
             | 
             | I don't necessarily think it makes someone a "lesser
             | developer" if they prefer untyped languages, but I DO think
             | they've either had to maintain anything long term or it
             | stayed relatively small.
             | 
             | Whether that makes them lesser or not isn't really for me
             | to say, but I can say I'm definitely on board with the idea
             | that types increase productivity the longer a system is
             | maintained. Unless used poorly, types don't automatically
             | mean you use them well, but they make it a hell of a lot
             | easier to do the right thing.
        
             | eduction wrote:
             | What you say is true, but it's also true that the person
             | you are replying specifically made their remarks about
             | productivity - you're both talking about what is best at
             | work.
             | 
             | It seems reasonable to argue that statements that you won't
             | even discuss X any more and would rather judge the person
             | as less competent professionally are unproductive. Not
             | saying I agree, btw. But it does seem like a pretty basic
             | point. One of you is talking about preserving your sanity
             | and the other about output. It's not necessarily a
             | disagreement even.
        
               | PH95VuimJjqBqy wrote:
               | > any more and would rather judge the person as less
               | competent professionally
               | 
               | That is absolutely NOT what the other poster said. They
               | said they _MAY_ judge them that way.
        
               | eduction wrote:
               | Fair point, you're right!
               | 
               | I still think it's reasonable to argue that's not a
               | "productive" approach, but like I said, that's not my own
               | opinion, I just think it's a reasonable argument.
        
           | HideousKojima wrote:
           | Nah, someone opposed to typing is either a shit developer
           | and/or a madman who codes too clever by half mad shenanigans
           | that take advantage of the lack of strong typing. I wouldn't
           | want to have to maintain or depend on code written by either.
           | 
           | For the very rare cases where a lack of strong typing is
           | needed, most languages with strong typing offer ways to
           | handle that (i.e. the Object and Dynamic types in C#)
        
           | loup-vaillant wrote:
           | Some prejudices _are_ rational. To paraphrase, it would take
           | an enormous amount of prior trust and respect before I even
           | humour someone trying me to convince me the sky is green with
           | a straight face.
           | 
           | Some issues are settled enough that there is no need to
           | discus them any further. It is _okay_ to automatically mark
           | people on the wrong side of such issues... let's say ill-
           | informed.
           | 
           | Static typing, I believe, is close to being one of those
           | issues.
        
             | jimbokun wrote:
             | If your prejudice prevents you from having a conversation
             | with Matz or Jose Valim or Van Rossom or the creators of
             | Julia about software development, you may want to
             | reconsider your prejudice as a hard and fast rule.
             | 
             | You can't honestly believe no one who likes to develop in a
             | dynamically typed language has nothing interesting to say
             | about software development?
        
               | mcronce wrote:
               | I can't (or, more accurately, _don 't_) believe that, but
               | I can certainly believe they have nothing interesting to
               | say about the topic of static vs dynamic typing.
        
               | _a_a_a_ wrote:
               | I'm very much with you on static typing but you've closed
               | your mind with a slam. Please don't.
        
               | lovich wrote:
               | An open mind is like a fortress with its gates unbarred
               | and unguarded.
               | 
               | It is both useful and allowed to have a certain level of
               | belief that won't be crossed without heavy effort. The OP
               | didn't even say they were closed to the conversation
               | completely, but that a random person with no pre built
               | trust isn't going to get the time of day from them to
               | rehash the same settled argument.
        
               | _a_a_a_ wrote:
               | "Matz or Jose Valim or Van Rossom or the creators of
               | Julia"
               | 
               | from memory Matz -> ruby, Valim-> elixir, Van Rossum ->
               | python, and 'the creators of Julia' -> julia
               | 
               | Not 'random persons' then
        
               | yetanotherloser wrote:
               | To be honest, I think dynamic typing must contain a mind
               | trap. Very smart people fall in.
        
               | wredue wrote:
               | These people opinions are based on bad information.
               | 
               | Beliefs inform decisions and other beliefs
               | 
               | I disagree with them on a huge number of fundamental
               | things in software. Most of their fundaments are claims
               | with no evidence. Due to that, I simply do not care about
               | what they have to say most of the time.
        
               | scns wrote:
               | Python got type hints bolted on. A type system for Elixir
               | is being worked on. Dynamic typing was a prerequisite for
               | Erlang to enable hot-code-reloading. Julia is can be
               | typed for an extra speedup. Stripe built a type checker
               | for Ruby called Sorbet.
        
               | adgjlsfhk1 wrote:
               | Julia generates fast code without type annotations
               | (except for your data types).
        
               | sundarurfriend wrote:
               | > (except for your data types)
               | 
               | This confused me for a moment, but I think you mean
               | annotating the types of the fields in your `struct`s,
               | right?
               | 
               | An addition to that: any non-constant global variables
               | (if you must have those) should also be type annotated.
        
               | insanitybit wrote:
               | If I have pre-existing respect for someone I will hear
               | them about. But the bar for that conversation is high.
        
               | betenoire wrote:
               | I'm not sure what is worse, loving dynamic languages or
               | having all these pre-existing conditions
        
               | insanitybit wrote:
               | Doesn't everyone have those? Like, I'm unlikely to really
               | engage with someone about my health unless they're a
               | doctor or otherwise have some area of expertise. Or if
               | it's just a casual, friendly conversation, to kill some
               | time.
        
               | betenoire wrote:
               | Everyone has biases. But you aren't describing a bias,
               | you are describing a refusal to engage with people below
               | you. Speak for yourself, I don't have that.
        
               | insanitybit wrote:
               | "Below you" is a bit of an exaggeration, I think. I said
               | that I might think less of someone as a software engineer
               | if they express an opinion that I think is particularly
               | bad. Hardly egregious, in my opinion. I also might not -
               | it frankly depends a lot on the situation.
        
               | sixstringtheory wrote:
               | We're all humans and life is very complicated with many
               | facets. If we all looked hard enough I'm sure we could
               | find a person you'd refuse to engage in a debate with
               | over their "thing."
               | 
               | But that wouldn't be a wise use of time in my opinion.
               | And that's what they're ultimately driving at: we all
               | have limited time to expend, so do it in things that
               | matter to you. I believe "matters to you" is a bias.
        
               | _dain_ wrote:
               | idk about the others but much of Guido's development
               | energies the past few years have been spent building
               | Python's gradual static typing system.
        
             | SAI_Peregrinus wrote:
             | I'd love a dynamically typed scripting language with the
             | following two properties: no "import" mechanism to split
             | code over multiple files, and no way to execute more than
             | (say) 256 lines of at most 128 bytes each in the file.
             | 
             | Dynamic types are nice for quick & short scripts, and
             | actively detrimental for anything long and complex. Why not
             | enforce that? As soon as it gets so long it doesn't run you
             | know it's time to rewrite in a statically typed language.
             | Instead all existing scripting languages allow unlimited
             | growth in code size, making it easy for programs to grow
             | beyond the point where the language is useful.
        
               | gls2ro wrote:
               | > Dynamic types are nice for quick & short scripts
               | 
               | A long list of big products and companies are there to
               | disagree with this. I am not saying that dynamic is
               | better or worse. But saying that dynamic languages are
               | only good for quick short scripts is a wrong
               | generalization that has not one exception but many
               | exceptions.
        
             | kdmccormick wrote:
             | I think this is OK as long as you keep your mind open to
             | situations that you have not considered.
             | 
             | Imagine someone is working in a relatively niche new
             | programming language ecosystem which is dynamically typed,
             | allowing the language to have some richness that modern
             | type systems don't support. I don't have an example because
             | I don't know of any such language in 2023... BUT back in
             | the 70s and 80s this would have been Lisp. Lisp couldn't
             | have been strictly typed back then because, AFAICT, type
             | systems hadn't advanced enough to express the sort of
             | metaprogramming that made Lisp unique and awesome. This was
             | at a time when most popular languages were strictly typed.
             | 
             | I would hope that you would keep your mind open to whatever
             | that maps to in the 2020s.
             | 
             | Now, if someone says "I like JS over TS because types are
             | annoying and slow me down", then yeah, I don't have much
             | patience for that either.
        
               | digging wrote:
               | You make points that seem great to me although I know
               | almost nothing about Lisp or 20th century programming.
               | 
               | The thing is, I've yet to encounter a single instance of
               | such an argument today. Every single time it ends up
               | being "I like JS over TS because types are annoying and
               | slow me down". It hadn't even occurred to me that
               | laziness and sloppiness weren't the the only reasons to
               | write in dynamically typed language.
               | 
               | I suppose what I'm saying is I'm quite interested in
               | seeing what kind of evolution some dynamically typed
               | language could offer in the future. Although with no
               | signs of its coming, I'm going to stick to TS because
               | it's objectively better for anything but very small
               | projects.
        
               | hansvm wrote:
               | TS is an interesting example to pick when trying to argue
               | that types are better. You have all the same downsides
               | people pick on when arguing against strong, static
               | typing, but since the type system isn't sound you still
               | can't rely on the input to a function being the type you
               | expect (and the problem is worse anywhere you inevitably
               | interact at least a little with the JS world outside your
               | TS bubble).
               | 
               | At best it's a form of documentation that enables some
               | simple linting rules and a bit of jump-to-definition
               | magic. Like, that's a benefit (mostly -- I tend to think
               | that type signatures implying more guarantees than they
               | provide is a recipe for inadvertently relying on
               | falsehoods), but it's not as clear-cut of a win as you
               | see in other statics/dynamic tradeoffs.
        
               | uoaei wrote:
               | It sounds like you have an implicit prejudice against
               | those who do not "keep [their] mind open to situations
               | that [they] have not considered", since the way you
               | phrased your concern is moral in nature. You see it as
               | morally bad not to have an open mind in that way.
        
               | mvdtnz wrote:
               | As Carl Sagan said: it's good to have an open mind, but
               | not so open your brains fall out.
        
               | kdmccormick wrote:
               | Yeah, sure, I do in fact think it is virtuous to be aware
               | that we don't always have complete information and that
               | we should be willing to revise our opinions when new
               | information is encountered. Is that controversial?
        
               | uoaei wrote:
               | No, no, not controversial. I intended to make it easier
               | to understand the point by demonstrating for the more
               | literal-minded that using moral language sets up two
               | halves of a dichotomy, one preferred to the other, so
               | that such prejudices needn't be _personal_ but rather
               | merely moral. The difference is of course that which side
               | of a moral dichotomy is a choice that can be reversed
               | (e.g. making an effort to open the mind) while personal
               | matters are immutable in those people.
        
               | monocasa wrote:
               | Python fits that niche now. Half the way tensorflow, et
               | al work is by doing brain surgery on the AST in a way
               | that resembles hey day Lisp's 'even the code is just
               | s-expressions, process it as much as you want to the
               | point of 80/20ing your way to your own compiler'.
        
               | mikelevins wrote:
               | Imagine working on a networked system that uses types to
               | make it impossible to express operations that violate
               | data security and integrity constraints, and where such
               | constraints control whether data is allowed to be read or
               | written from or to a given endpoint. Imagine further that
               | the types governing permission to read or write depend on
               | environmental state that can change at any time--for
               | example, as soon as a specific person changes roles, the
               | set of ports they are allowed to read and write changes.
               | 
               | The type system enforces those permissions: writing to an
               | impermissible destination is a type error. The types
               | applicable to an entity are not necessarily knowable at
               | compile time; some of them might change at any time.
               | 
               | I had a job working on such a system. It supported a type
               | system implemented in Haskell with both static and
               | dynamic type disciplines, where values were tagged with
               | base types designed to be checked dynamically in
               | hardware.
               | 
               | Was the programming language dynamically typed? Yes. Was
               | the programming language statically typed? Yes.
        
             | klyrs wrote:
             | > To paraphrase, it would take an enormous amount of prior
             | trust and respect before I even humour someone trying me to
             | convince me the sky is green with a straight face.
             | 
             | Don't venture into tornado country; your doubt may be your
             | downfall.
        
             | soperj wrote:
             | > To paraphrase, it would take an enormous amount of prior
             | trust and respect before I even humour someone trying me to
             | convince me the sky is green with a straight face.
             | 
             | But people regularly say the sky is blue, and it's clear as
             | day that it's not when the earth has turned and your side
             | isn't facing the sun.
        
               | bluGill wrote:
               | The sky is still blue, the lack of light means you cannot
               | tell, but the color is still there.
        
               | stouset wrote:
               | The sky isn't inherently blue. It's essentially
               | colorless.
               | 
               | Only due to Rayleigh scattering do we perceive it as
               | blue, but that's not due to the absorption and reflection
               | of different wavelengths we associate with innate color.
               | Note that the color changes depending on the angle of the
               | sun, even to the point that it's purple and red at a few
               | times during the day.
        
               | quonn wrote:
               | Perhaps, only because the sky is blue we perceive blue as
               | blue. If the sky were red we would perhaps perceive all
               | red like we do blue.
               | 
               | Our perception of the important colors (sky blue, ocean
               | blue, vegetation green, ...) probably evolved along with
               | our physical needs.
        
               | soperj wrote:
               | no... the sky is clear, and it's the refraction of light
               | through the atmosphere that's confusing you.
        
               | bluGill wrote:
               | As someone who would die without an atmosphere the
               | distinction is meaningless.
        
               | soperj wrote:
               | you're going to die regardless. The sky still isn't blue,
               | which is quite obvious at night, or during sunsets and
               | sunrise.
        
               | digging wrote:
               | I don't think that's a statement that most would agree
               | with. What is the sky? Sure the atmosphere can be called
               | blue, but the sky is what's visually above the earth. At
               | night, that's black space. The atmosphere is mostly
               | transparent at night.
        
           | ilaksh wrote:
           | As someone who usually prefers JavaScript over TypeScript but
           | has used many typed languages over the years and generally
           | finds then easier to work with in a way, I agree that one
           | should not pre-judge based on something like that.
           | 
           | But he's just being honest. Many developers have been making
           | that judgement for many months or even years.
        
         | bennyelv wrote:
         | Amen!
         | 
         | I'm currently responsible for a very large system built in raw
         | javascript where function definitions like this one in the
         | article: function birthdayGreeting1(...params)
         | 
         | ...are the religion.
         | 
         | It's awful. I hold the people responsible in very little
         | regard.
        
         | nkozyra wrote:
         | I'm baffled it's even a debate. Who wouldn't want strong
         | typing? What's the argument?
        
           | digging wrote:
           | Mostly, it boils down to selfishness and "laziness".
           | (Although I try to be very careful about that term, because I
           | do not believe in it as generally used. I use it here to
           | define: an unwillingness to plan ahead and to have to learn
           | something new. Not applied as a global personality trait but
           | only used in context.)
        
         | throw1234651234 wrote:
         | I think this is especially true for line of business
         | applications that have the following qualities:
         | 
         | 1. It's simple. Let's not lie, let's not pretend. It's CRUD.
         | You can put in K8S, you can add AI, it can be behind an API
         | Gateway, you can make it all Event Driven, you can use CQRS for
         | every entity because you really, really want to feel clever.
         | But it's still CRUD.
         | 
         | 2. Other people are working on it, many other people.
         | 
         | 3. People from other companies are interfacing with it.
         | 
         | So knowing what to expect trumps everything. Types help with
         | that. They help a lot.
        
         | iopq wrote:
         | There's ONE argument that I'm partial to:
         | 
         | if you get the static type system wrong once, there's no going
         | back
         | 
         | Take for example, Rust: mut, Send, Copy, Drop, Debug, dyn have
         | all their warts because they are special and you can't fix them
         | because you'll break previous code.
         | 
         | In a gradual typing language you could potentially bolt-on your
         | own type system as a package where it just runs the type
         | checker if you want one. It just so happens people who favor
         | these gradual typing systems don't do a good job of creating
         | those typing systems because they are not that into types in
         | the first place.
         | 
         | But in theory, this kind of a system would let you not worry
         | about types when prototyping the system, then put some bounds
         | later based on your requirements.
        
         | zare_st wrote:
         | I'm not sure what I'm reading here.
         | 
         | Types are integral part of standard programming languages. If
         | you mean "types bad" as in BASIC/Javascript variables, then yes
         | I fully agree. These languages were never meant to be a
         | solution for professional software engineering.
         | 
         | Once a language has proper types, it can be "weak typed" by not
         | forcing "strong typing" by being dynamically typed in nature.
         | If the language has normal preprocessor support, the static
         | type system can be added on the project level. And then in
         | essence you get a strong typed environment in a very thin
         | programming language such as C.
         | 
         | Let's take a big C or C++ software project, the process behind
         | it. Of course, the project is in those languages because it
         | requires native opaque pointers and hardware access. The
         | project has coding style, it has arbitrary rules. Although
         | there is little to stop anyone from making a mess in C or C++
         | code there is entire code infrastructure and CI/CD chain around
         | it. Lets say the rule is no void pointers without encompassing
         | struct that's a type that can be checked via macro system. If
         | you wrongly use the type struct, you get stopped by the project
         | build. If you go around the rule, you get stopped by a code
         | analysis after commit (and get in trouble for doing that).
        
         | [deleted]
        
         | flohofwoe wrote:
         | So... about the _strong_ part in  'strong static typing':
         | 
         | Many years ago I thought that it's a good idea for a game math
         | library to have separate strong types for 'point' (a location
         | in 3D space) and 'vector' (a direction and magnitude in 3D
         | space), and allow/disallow certain operations (e.g. 'point +
         | vector => point' 'vector + vector => vector', 'point - point =>
         | vector', while 'point + point' is illegal).
         | 
         | Sounds absolutely great in theory, but in practice it was a
         | royal PITA to work with, but it took me much too long to
         | realize this (how can it be such a hassle when in theory it's
         | such a good idea!)
         | 
         | I soon went back to a general 4D vector class (where a 'point'
         | is defined by .w = 1.0, and a 'vector' by .w = 0.0), and some
         | debug-mode runtime validation (which catches things like trying
         | to add a point to a point).
         | 
         | Of course strong typing also often makes perfect sense, for
         | instance in a 3D rendering API it should be a compilation error
         | to provide a texture-handle where a buffer-handle is expected,
         | but after this experience with points vs vectors (which
         | should've been a classic showcase for strong typing) I would
         | never again "die on that hill" :)
         | 
         | TL;DR: static typing: yes! strong typing: it depends.
        
           | [deleted]
        
           | sneed_chucker wrote:
           | That's not a shortcoming of strong or static typing, that's
           | just you realizing that your initial data model was flawed
           | and that you either needed to unify them into a single type
           | (like you did) or utilize an abstract class/interface.
           | 
           | The good thing about stricter typing systems is that it
           | forces you to handle all the cases when you're doing a
           | refactor like this before it compiles.
           | 
           | When changes to the data model happen in large codebases of
           | dynamic code, it frequently gets shipped in a non complete
           | state and turns into a production runtime error later down
           | the line.
        
           | Someone wrote:
           | > For things like kilometers versus hours I'm still
           | undecided.
           | 
           | Those help you more if you do a lot of math involving both
           | them, but that's also when it becomes a nightmare in most
           | programming languages because of an explosion in the number
           | of types.
           | 
           | Let's say your code computes                 3km x 4hours
           | 
           | If so, you need a _"km hour"_ type.
           | 
           | In many languages, you also have to write code to make that
           | happen, and to make it have the same type as
           | 4hours x 3km
           | 
           | Even if you don't ever store values with those types in
           | variables, you also may need types for _per km_ , _per hour_
           | , _km2_ and _hour2_ for expressing the types of intermediate
           | values (for example, in a physics computation, you may
           | encounter _[?](3km2 /4hour2_ to compute a velocity in _km
           | /hour_)
           | 
           | And that's ignoring that you may
           | 
           | - encounter minutes, meters, yards, etc.
           | 
           | - want to use algorithms that compute _exp(3km)_ or
           | _log(4hours)_. What types do these have? Here, you probably
           | want to forget about string typing values.
        
             | flohofwoe wrote:
             | Apologies, I edited my post while you wrote your reply and
             | removed the kilometers vs hours thing. But your reply makes
             | perfect sense, and I think this "type explosion" is my main
             | gripe with too extremist strong typing.
        
         | asdajksah2123 wrote:
         | I think the conversation becomes a lot easier once you
         | recognize that there is no such thing as untyped data.
         | 
         | There's only explicit typing and implicit typing.
         | 
         | So the only real argument you're having with someone is when
         | writing a piece of code, do they want the caller of the code or
         | the input of the code's data type to be known or they want the
         | data type to be a mystery to be figured out, occasionally in
         | production when shit hits the fan.
        
         | stratigos wrote:
         | Unfortunately this attitude is not profitable, and also smacks
         | of someone who works on their own island and costs a business
         | more than they add value given their inability to work as a
         | team. This attitude might find a way to be profitable when held
         | by a university professor, though that does not mean its
         | desirable.
        
           | insanitybit wrote:
           | This is not a "work" attitude. I would never impose my
           | opinions on a team. I've worked professionally in many
           | languages with a variety of type systems. In virtually all
           | cases I have reviewed very positive feedback throughout my
           | career, _in particular_ in terms of my ability to work well
           | with others, to mentor, etc.
        
         | waffletower wrote:
         | In my country, the United States, we have broad protections for
         | religious beliefs.
        
         | scarythrowaway wrote:
         | I mean, that's one reason I like dynamic typing, I get to avoid
         | a bunch of psycho cargo culters for free.
         | 
         |  _cries at the thought of insanitybit not respecting me_
        
         | optymizer wrote:
         | I find it interesting that people in this thread seem to have
         | absolute certainty that "types good" is true, while to me those
         | two words together are largely non-sensical, just like "bytes
         | good" wouldn't make much sense to debate.
        
           | prewett wrote:
           | After you repeatedly waste a bunch of time debugging things
           | that static typing would have caught on the first compile,
           | and you start developing a "types good" attitude. If you just
           | do simple React development, you might not ever run into the
           | problem. But once your programs get to a couple thousand
           | lines, you start occasionally forgetting what your function
           | takes and passing in the wrong things, which then get passed
           | around for a while and throw an exception long after the
           | problem happened. This results in very unfun print-debugging,
           | particularly in a recursive descent parser or an algorithm
           | that processes a lot of data.
        
             | leptons wrote:
             | >But once your programs get to a couple thousand lines, you
             | start occasionally forgetting what your function takes and
             | passing in the wrong things, which then get passed around
             | for a while and throw an exception long after the problem
             | happened.
             | 
             | I've been writing code for 40 years, I can't estimate how
             | many loc I've written, but likely over a million. One of my
             | personal projects is currently over 65k loc vanilla js, and
             | I never once had a problem with not knowing what type a
             | function took. If you're so bad at naming things and
             | knowing what a function does, I guess maybe types can help
             | you. But not everyone needs it.
        
               | optymizer wrote:
               | I'll take the time to reply to both of you, because you
               | seem to have opposing views.
               | 
               | I think such a debate is largely unproductive. Like
               | anything else, types have value (ha) and successfully
               | capitalizing on that value depends on the context of the
               | project, which includes things like developer experience,
               | tooling, project complexity, requirements, deadlines etc.
               | 
               | The only productive outcome of these debates is that each
               | developer gets to slowly and frustratingly build a list
               | of pros and cons as they go through the arguments
               | presented by either side debating this topic. In
               | addition, developers who completely disregard either the
               | cons or the pros are necessarily making subjective
               | decisions with incomplete data, and the project gets to
               | pay the price. Just because the developer is personally
               | OK with all of their projects paying that price, doesn't
               | mean it's the best decision for a project.
               | 
               | My experience has been that when starting out, projects
               | get the most value out of not having types, and as they
               | grow in scope and size, and the cons of not having types
               | start creeping up, that's the point when gradually
               | transitioning the code to being strongly typed allows the
               | project to maintain its velocity _and_ quality.
        
         | KronisLV wrote:
         | > At this point it's beyond a hill I'm willing do die on. I'm
         | not really interested in discussing it. If you don't get it I
         | probably don't want to talk to you about it, I might even think
         | less of you as a software developer.
         | 
         | That's a pretty strong take! I don't think there are many
         | things that I feel similarly about... maybe if someone
         | suggested that they don't need test environments and can just
         | deploy changes to prod without testing or CI/CD and just see
         | what happens, when it'd be my employment on the line, but even
         | that's a pretty contrived and out there example.
         | 
         | > The amount of pre-existing respect for someone I'd need to
         | have before I engage in a good-faith discussion on "are types
         | good" is pretty high.
         | 
         | My problem is that not all type systems and the way you use
         | them are equal.
         | 
         | When working with back end code, I really like .NET or even
         | Java having a type system there for me. I know that people
         | suggest that they have their own shortcomings (type erasure,
         | NPEs, no multiple inheritance, even smaller things like C#
         | enums not supporting methods) and that there are better options
         | out there, but generally you can turn off the part of your
         | brain that'd worry about the language too much and just deal
         | with the domain problem at hand. Something like JetBrains are
         | also excellent, because with the type system suddenly the tool
         | also can reason about the language constructs you're using and
         | give you all sorts of good suggestions and refactoring options.
         | 
         | Whereas with something like TypeScript in combination with
         | React, there are times where you fight the type system instead.
         | That's just the impression that I got working on a few projects
         | for a while, in comparison to React with JS (perhaps the code
         | was also a bit too clever), while with Angular it felt more
         | coherent to me (despite Angular being more complex otherwise
         | and not really my first choice). In the end, I gravitate
         | towards Vue with JS for my personal stuff, but it's not like
         | you can just say no to TypeScript when you need to maintain
         | something long term.
         | 
         | I can't actually remember who said that they ditched TypeScript
         | for similar reasons, but the argument was basically that a non-
         | insignificant part of their codebase was there just to satisfy
         | the type system. TypeScript does what it's supposed to... but
         | it feels like it could be easier.
        
           | xxs wrote:
           | >maybe if someone suggested that they don't need test
           | environments and can just deploy changes to prod without
           | testing or CI/CD and just see what happens
           | 
           | That's actually not hard, you need to be able to run in dry
           | mode, and run the same in an existing instance (in parallel),
           | then compare the results. If you are happy you can continue
           | with the roll up, disabling the dry mode.
        
           | mcv wrote:
           | I'm pretty agnostic about the whole thing. The topic has been
           | done to death already. Types are great, but some ways of
           | handling types can get in the way sometimes, and the
           | excessive type declarations in older Java was just painful.
           | Dynamic types can work fine too, but they work better in
           | smaller projects than in bigger ones. Types do give you a lot
           | more to hold onto, even if they're only compile-time types
           | like Typescript. In large, complex projects where you're
           | juggling a lot of different types, you want to know what
           | you've got in your hands.
           | 
           | That's pretty much my take. I don't hate anyone for having
           | different ideas about it. But if you're going to use
           | Typescript, don't use 'any'. At all. Unless you really don't
           | know and the next step is figuring out what type you've got.
        
           | insanitybit wrote:
           | > That's a pretty strong take!
           | 
           | Not even one of my spicier takes, just one of the few that I
           | simply don't care to engage with further.
           | 
           | > My problem is that not all type systems and the way you use
           | them are equal.
           | 
           | We agree. Some type systems suck so badly that I can see why
           | people would be tempted to believe that all type systems
           | suck.
        
             | KronisLV wrote:
             | > Some type systems suck so badly that I can see why people
             | would be tempted to believe that all type systems suck.
             | 
             | But that's my point: people say that exact thing about Java
             | and .NET, while I find them _usable_. Meanwhile TypeScript
             | has cool stuff like union types and other stuff to the
             | point where you can get pretty clever with it
             | (https://codegolf.stackexchange.com/questions/237784/tips-
             | for...), which many would describe as the type system being
             | objectively _better_ , yet it's also more _difficult_ for
             | me to use.
             | 
             | In my mind, a good type system would let you do both basic
             | stuff easily without too much work (to make sure that
             | refactoring doesn't make you shoot yourself in the foot)
             | and also encourage you to write the simplest code that you
             | can get away with, while allowing you to get clever in the
             | select few places where that is actually needed.
             | 
             | Which is funny, because adjacent to that, Java and .NET
             | (web) frameworks can be a masterclass in incidental
             | complexity, even though for me the type systems don't get
             | in the way too much.
             | 
             | Edit: actually, I think I'll migrate a JS project to TS,
             | this time in Vue. Perhaps Vue 3 will be a pleasant
             | experience and if it won't, then I'll have a concrete list
             | of things that caused me to feel this way.
        
               | satvikpendem wrote:
               | Vue is not too great with TypeScript in my experience.
               | That's one of the reasons why I switched from Vue to
               | React.
        
               | mcv wrote:
               | I thought Vue 3 was supposed to be native Typescript.
        
         | nsajko wrote:
         | You're confusing _static typing_ with the _existence_ of a type
         | system. As an example, Julia has a rich type system, but the
         | language is dynamically typed.
        
         | patrickthebold wrote:
         | I'm with you, especially in my professional life. That said, I
         | think Clojure is interesting and Rich Hickey has some good
         | talks in support of dynamic typing.
        
         | TheBlight wrote:
         | Not really interested in discussing it. _posted on discussion
         | forum_ ;)
        
         | auggierose wrote:
         | I don't know, that is so last millennium. If you prove your
         | software correct, you won't need a static type system, it just
         | gets in your way. And that's a hill _I_ am willing to die on.
        
         | WirelessGigabit wrote:
         | I actually like this approach. I believe in mentoring. I
         | believe in building bridges. But if we're on opposite sides of
         | the Grand Canyon, it's not worth my time.
        
         | ActorNightly wrote:
         | Here is a fun fact that you don't realize.
         | 
         | Say you can do the project in 2 ways.
         | 
         | First way is to use a strongly typed language, think about the
         | data, and design your code in the appropriate way. You code it
         | up, go through the loop of compiling and fixing errors, and get
         | your code to run.
         | 
         | The second way is to write your code in Python, without
         | worrying about strong types. You complete the code quite a bit
         | faster, but since you also want your code to be correct, you
         | spend time writing an end to end test suit for your code.
         | 
         | The second approach is not only faster (since you are writing
         | tests in both cases), its overall better. Spending time writing
         | tests allows you to essentially validate things that modern
         | mainstream strongly typed languages can't catch at compile time
         | (for example, what happens when the input is unicode strings?).
         | It also forces you to think about end to end behavior and
         | making sure that is correct, rather than just the behavior
         | within your code.
         | 
         | Strong typing is a simply hand-holding tool for programmers. If
         | you cannot write correct code without it, you are on a fast
         | track to being replaced by AI eventually. The future of
         | programming is not going to be designing data structures and
         | types, its going to be using English to generate large chunks
         | of code in most likely Python, and then tweak fine details in
         | those.
        
           | _dain_ wrote:
           | why can't I write it in a statically-typed language and also
           | write end-to-end tests?
           | 
           | also it's pretty ridiculous to say "static type systems are
           | handholding" and then say the remedy is to write your code
           | with AI ..
        
             | ActorNightly wrote:
             | You can, but the reason you do this in practice is because
             | the static typing languages are often not sufficient or
             | strong enough. And if you are writing tests, you may as
             | well do everything through testing and focus on rapid dev
             | rather than worrying about types.
        
           | gdcbe wrote:
           | Call me sceptical, but I don't buy it. What makes you certain
           | that's the (one) future... Also programming is a super broad
           | field, and more then a field is almost more like a medium
           | then a field.
           | 
           | I honestly don't know if we'll still program by hand or not,
           | but I do look skeptical at people who are very certain we
           | won't. Don't think that's the first time in history people
           | make that prediction...
        
             | ActorNightly wrote:
             | Compilation at its core is a translation problem. Right
             | now, it would be fairly trivial to train an LLM to
             | essentially be a compiler. And, you can already prompt LLMs
             | on generating code for a wide array of things.
             | 
             | As far as adoption, there is a reason why dynamic type
             | languages that feature a lot more natural syntax (Node,
             | Python) are used WAY more than others.
        
           | gwervc wrote:
           | Except the kind of people "saving time" writing in a dynamic
           | language will skip the step of writing tests as well since it
           | can be viewed as lost time.
        
           | cjfd wrote:
           | I think this is completely false. It completely breaks down
           | as soon as you get into your first refactoring that is a bit
           | larger than completely trivial. Typically the mess one ends
           | up is one or more of the following. (1) Nothing is refactored
           | because people do not dare to do it. (2) Not just some but
           | most of the uncommon code paths are broken. (3) Tools that
           | are used to interact with a running application are regularly
           | in a broken state. You want to prevent these problems with
           | 100% test coverage. As such this may be a laudable goal on
           | occasion but I do notice that the code described in (2) and
           | (3) are highly non-trivial to cover 100%. I also have to
           | wonder what mythical developer is does not have the
           | discipline to use static typing but does have the discipline
           | to attain 100% code coverage. I first want to see such a
           | developer before I believe in his/her existence.
        
             | ActorNightly wrote:
             | >It completely breaks down as soon as you get into your
             | first refactoring that is a bit larger than completely
             | trivial.
             | 
             | This is, in fact, MUCH easier to do with a strong test
             | suite that only cares about input and output rather than
             | internals.
             | 
             | The most common approach to starting a refactoring project
             | is write or enhance a test suite to the point where there
             | is no undefined behavior, either the program works or
             | handles the appropriate errors.
             | 
             | You don't need to aim for 100% test coverage either, you
             | just need your tests to cover all possible inputs
             | (including fuzzing).
        
           | jghn wrote:
           | Using your example - have a type that that enforces Unicode
           | strings (or vice versa)
        
         | mpweiher wrote:
         | Well, getting this personal about a purely emotional preference
         | might make people think less of a person that does that, with
         | significantly better justification.
         | 
         | To be clear: people have tried to show the long-claimed safety
         | benefits for a long time, and they just refuse to appear.
        
         | [deleted]
        
         | halfmatthalfcat wrote:
         | I've worked with my fair share of vanilla JS devs who refuse to
         | acknowledge the benefit of more statically typed variants of
         | the language. Most of them bemoan the upfront cost of typing
         | everything without realizing the benefits of it. I absolutely
         | think less of them as developers.
        
           | leptons wrote:
           | I absolutely realize the benefits of it, and I also recognize
           | it doesn't cure all. Everything has trade-offs. There were
           | plenty of amazingly complex and large projects written in
           | vanilla JS before typescript ever existed, and somehow they
           | aren't falling apart and crippled. It really depends on the
           | developers involved more than the language or the dogma.
        
           | giraffe_lady wrote:
           | Not liking typescript is not the same thing as denying that
           | types are valuable.
           | 
           | TS has a very complex type system in exchange for relatively
           | weak guarantees about correctness. That's a tradeoff you can
           | choose to take or leave depending on the problem at hand, and
           | holding that position is not the same as believing types have
           | no value.
           | 
           | Unless you're talking about elm or rescript or something then
           | sure sure. But usually when people say things like this they
           | mean typescript.
        
             | smallerfish wrote:
             | Typescript's typing system is great and (for me) makes
             | frontend development tolerable. It's annoying that it's
             | optional. tsconfig and the related ecosystem is a disaster.
             | 
             | I still have hopes that Kotlinjs can fix the distribution
             | size and the tooling around binding to js libraries.
        
             | [deleted]
        
             | junon wrote:
             | This is pretty much my take, too. I don't hate the idea of
             | TS, but TS is so painful to work with, and it's owned by a
             | company I really don't like, too.
        
               | dmix wrote:
               | OP is saying it's provides weak guarantees which is a
               | result of the fact they made it _easy_ to adopt and
               | implement among legacy untyped code. It 's the opposite
               | of painful to work with for typing systems, compared to
               | something like Rust which has stronger guaruntees and
               | more predictable patterns but hard requirements the full
               | stack is type. The result in TS is plenty of "any"s
               | everywhere and in legacy code some situations where it's
               | mostly just a thing veneer of type safety.
               | 
               | But all of that makes plenty of sense because in the
               | early days it was rare to work on a real life production
               | JS project that was pure TS from day one in addition to
               | having TS only libraries.
               | 
               | These days it's everywhere and the work has been done to
               | move away from rampant anys in popular libraries. The
               | tooling is also mature and it's rare to find major JS
               | libraries not already packaged with types or a @types
               | import. Turbo moving away from TS was the rare exception.
        
               | arp242 wrote:
               | > The tooling is also mature these days
               | 
               | Well:                 % cat a.ts
               | console.log('Hello, world!')            % time tsc a.ts
               | tsc a.ts  2.39s user 0.10s system 232% cpu 1.066 total
               | 
               | More than a second to compile a "hello, world" (or 2.4s
               | in CPU time) is orders of magnitudes slower than any
               | other compiler or interpreter that I know of. It's a
               | ridiculous start-up time.
               | 
               | esbuild is not an alternative as it doesn't check types.
               | 
               | What I want is "GET /foo.js" to "just" compile TS "on the
               | fly" in dev; it's a simple "just works" kind of setup,
               | but not possible with TS.
               | 
               | Or for a simple system, just "roll your own":
               | for f in *.ts; tsc $f >|$f:r.js            watch-files
               | *.js --run tsc            (for f in *.ts; tsc $f) |
               | minify >production.js
               | 
               | Doesn't need to be shell, can be a simple JS script or
               | whatever. You really shouldn't need millions of lines to
               | call a compiler _even in simple scenarios_.
               | 
               | What exists now is an explosion of complexity to deal
               | with all this and I guess these systems are "mature",
               | kind of, but for a lot of systems it's massive overkill
               | (and even for larger systems it's not particularly great
               | IMO). Besides, it's really a bad fix for more fundamental
               | problems.
               | 
               | Personally I wouldn't call TypeScript mature until
               | compile times are roughly within the range of literally
               | ever other compiler that has ever seen wide-spread
               | adoption (and with that I don't mean "parallelize to 32
               | cores so my threadriper over 9000 can compile things in
               | 0.1s). It doesn't need to be fast: just not a huge
               | outlier.
        
               | zdragnar wrote:
               | You can still use tsc for type checking via editor
               | language server and quality gates (with the noEmit flag)
               | and get stupid fast compilation with swc or esbuild.
               | 
               | Explosion of complexity and "bad fix for fundamental
               | problems" sounds a lot like you just have an axe to
               | grind.
               | 
               | Many other popular languages have multiple build systems
               | and tools to choose from as well; it isn't a particularly
               | novel challenge.
        
               | arp242 wrote:
               | _Points out real-world practical problems_
               | 
               |  _" You just have an axe to grind!"_
               | 
               | Hmkay.
               | 
               | I just want things to compile, with errors, like
               | literally everything else works. It's really not a huge
               | ask. I don't want complex bespoke setups with multiple
               | compilers and background processes and whatnot. The
               | classic JS/TS response is "here is the happy path with
               | all this tooling, but if you want something outside of
               | that then there is something wrong with you".
               | 
               | I guess the "axe" that I'm "grinding" is that I'm having
               | a lot of difficulty using TS in a way that fits with my
               | sensibilities and preferences. e.g. I don't like errors
               | in my editor and prefer to explicitly call the compiler
               | (for any environment). I suppose I could get all of this
               | to work how I want it to with wrapper scripts or whatnot:
               | but it's complex, time-consuming, and isn't needed for
               | anything else.
               | 
               | Based on previous conversations about this at least one
               | person will say something along the lines of "zomg what
               | kind of crusty old backend unix beard doesn't use VSCode
               | and want errors in their editor, you just need to get
               | with the times as you're stuck in the past!!!1" but
               | again: it works for literally everything else (including
               | other compile-to-JS tools), and is not that "obscure" of
               | a work-flow, IMHO, and we're back to a few paragraphs
               | ago: "move outside the happy path and you're screwed".
        
               | zdragnar wrote:
               | I mentioned using tsc with the noEmit flag for quality
               | gating, which is the same workflow you would use.
               | 
               | `tsc --noEmit a.ts` (possibly flipping the position of
               | the flag, I forget if it is sensitive).
               | 
               | That'll check the types without spending unnecessary time
               | compiling with the slower tooling.
               | 
               | From there, esbuild or swc binaries compile the code as
               | desired. They use the same tsconfig file that tsc does,
               | so no need for any extra complexity. They build so fast
               | that you'll not mind having a separate command, I
               | promise.
               | 
               | You could even combine the two into a simple one-liner if
               | you wanted.
               | 
               | Compared to, say, java where you have to fight over maven
               | or Gradle or ant, plus endless config options in XML or
               | groovy or whatever, typescript _really_ isn 't much to
               | complain about.
               | 
               | Hell, trying to set up a clojure full stack project is a
               | nightmare of conflicting opinions over tooling between
               | lein and shadowjs or whatever.
               | 
               | Of the big languages, C# is about the only one with a
               | "one true way", and of the smaller ones, they simply
               | haven't yet developed a big enough base to grow
               | contentious enough to have divergent solutions.
        
               | dmix wrote:
               | Yep almost every (serious) TS dev only uses --noEmit for
               | development by default because they use VSCode/IDEs as
               | their typechecking engines and then have something like
               | esbuild for delivering the content to the browser
               | locally. I've never had performance issues with either
               | step and I use both daily.
               | 
               | The raw output speeds aren't a very good 'practical real
               | world example' as the OP described it.
               | 
               | If anything in dev ESLint (+ Copilot) is the slow ones
               | that I sometimes noticed, but there is already Rust
               | driven replacements maturing in the pipeline as we speak.
        
               | arp242 wrote:
               | The performance of "tsc --noEmit a.ts" is identical, and
               | it makes no difference vs. just typing "tsc a.ts", and it
               | doesn't really solve "compile on demand" (with type
               | checks) in any case.
               | 
               | I looked in to this some time ago, because I couldn't
               | believe it was this slow, and tsc just has a huge startup
               | cost. Once it gets going it's alright (I think? Don't
               | quote me) but to get started takes a long time. It's
               | actually already improved because not too long ago it was
               | more like 3 seconds (probably because of the
               | parallelisation, which is kind of cheating IMO).
               | 
               | I don't know about Java as I never really used it, but
               | complex build systems are not unique to TS of course, but
               | what they are in TS is _mandatory_ for any reasonable
               | experience because it works around the fact the compiler
               | is so damn slow. That 's a huge difference you can get
               | started without too much effort, and you can do "smart"
               | things fairly easily as I mentioned in my earlier
               | comment.
               | 
               | > they simply haven't yet developed a big enough base to
               | grow contentious enough to have divergent solutions.
               | 
               | C, C++, Go, Rust, Python, Ruby, PHP don't have a "big
               | enough base"? Ehhh
               | 
               | And my entire point is that TS LACKS "divergent
               | solutions". Because it's so slow lots of solutions are
               | simply not practical.
        
               | jdeisenberg wrote:
               | You might want to look into ReScript (https://rescript-
               | lang.org/). It has strong static typing with type
               | inference, and it is very fast.
        
               | arp242 wrote:
               | Yep, Rescript is nice, but also comparatively obscure.
               | It's okay for personal projects; in company setting:
               | maybe? It's certainly more complex.
        
               | 2c2c2c wrote:
               | This take is common, but personally never understood it.
               | The typing is optional. Use it for the easy stuff and
               | enjoy the low hanging fruit
        
               | junon wrote:
               | If the tooling is a pain to use, slow, and owned by a
               | crappy corporation, and I'm not going to use the types
               | anyway, then I have _even less_ of a reason to use it...
        
             | rafaelmn wrote:
             | Typescript can be very complex - it can also be incredibly
             | simple - it's up to you how far you want to take it.
             | 
             | Sure it can be an adventure to express something fully in
             | it - but this is true for any type system I've seen.
             | 
             | And I haven't seen another type system that's integrated
             | into a dynamic ecosystem as well (IMO python is 5 years
             | behind in terms of type checking experience) and that lets
             | you chose the level of type sophistication that makes
             | sense.
             | 
             | Static typing, code analysis, automated testing, etc. are
             | all great tools that become counterproductive past a
             | certain point. Where that point is highly depends on what
             | you're doing and typescript is one of the most flexible
             | type systems at letting you make that choice. I'd say a lot
             | of people are terrible at recognizing when they went too
             | far with it for no practical gain.
             | 
             | My only problem with it is that they can't fix the shit JS
             | semantics.
        
               | giraffe_lady wrote:
               | I am professionally familiar with typescript and
               | explicitly not making a concrete argument for or against
               | it right now.
               | 
               | I'm just pointing out that having an opinion about
               | typescript is not the same thing as having an opinion
               | about types. Something I think people are
               | (intentionally?) conflating in these comments.
        
               | rmilejczz wrote:
               | I think it's just a path a lot of developers have
               | traveled, starting with JavaScript and moving to
               | TypeScript. If you've gone through that pipeline than you
               | probably feel very strongly about the benefits that
               | TypeScript provides and it's the fulcrum for your opinion
               | on static vs dynamic typing
               | 
               | Too many web developers, basically, I don't think the
               | conflation is intentional
        
               | PH95VuimJjqBqy wrote:
               | I think you have to give typescript a bit of a pass in
               | terms of types. MS had unique constraints when designing
               | it originally, so it's never going to meet the
               | expectations of more hardcore "typists", but I think
               | they've done a great job given the unique challenges. Not
               | perfect for sure, but it's one of the few newer
               | technologies where I think it's a clear win.
        
           | arp242 wrote:
           | Are these people who used types but didn't like it, or people
           | who never really used it and refuse to even try it?
           | 
           | IMHO these are markedly different scenarios: the first is
           | essentially just a difference of opinion, the second is a
           | rather myopic attitude.
        
           | digging wrote:
           | > bemoan the upfront cost
           | 
           | This applies to much more than static typing as well.
           | Anything built, can be built well or it can be built quickly.
           | 
           | Although I often have to make trade-offs for immediate gain
           | at work, there is a big difference between the quality of my
           | work over time vs the quality of other devs who default to
           | immediate returns. I will say in their defense, they play a
           | role in the team. But I wouldn't want to work on a team where
           | avoiding upfront costs was the expectation rather than the
           | exception.
        
           | lo_zamoyski wrote:
           | Have they considered languages with type inference?
        
           | waffletower wrote:
           | And I definitely think less of you as you as a developer as
           | you openly admit to dogmatic and myopic prejudice regarding
           | the nuances of typing systems and the complexity of software
           | development contexts.
        
             | lijok wrote:
             | Interesting. Would you have had the same response if GP
             | stated:
             | 
             | "I've worked with my fair share of vanilla JS devs who
             | refuse to acknowledge the benefit of testing. Most of them
             | bemoan the upfront cost of testing everything without
             | realizing the benefits of it. I absolutely think less of
             | them as developers."
        
               | waffletower wrote:
               | Again another binary dichotomy that doesn't neatly fit
               | reality. I imagine the number of developers that would
               | unilaterally dismiss all testing practices is very small.
        
             | halfmatthalfcat wrote:
             | I mean, I'm not going to say it to someone's face but I'll
             | definitely be judging them. Most of those who have pushed
             | back against typescript have done so for similarly dogmatic
             | reasons or even straight ignorance (I dont want to learn
             | something new), so I'm not sure who is really the winner or
             | loser in this situation.
        
           | manicennui wrote:
           | The problems with JS go far beyond its dynamic typing.
        
           | ecshafer wrote:
           | This sounds like its just Typescript evangelizing. But while
           | I love types, Typescript kind of sucks and sucks the fun out
           | of writing Javascript. If I am going to add a compilation
           | step to get types, I would rather write Scala or F# and
           | compile to JS, then you also get rid of all of the warts of
           | JS that Typescript _doesn 't_ get rid of.
        
             | IshKebab wrote:
             | I agree Typescript doesn't solve all the warts. But it does
             | solve a lot.
             | 
             | The really issue with compile-to-Javascript languages is
             | debugging. Have fun stepping through your incomprehensible
             | generated code in dev tools.
             | 
             | (Except Dart which has really good Dev tools support; I
             | guess they can poke the right people to make it work.)
        
         | JonChesterfield wrote:
         | It _really_ matters which static type system is in question.
         | 
         | SML or Haskell? Yep, like those ones. The languages would not
         | be so useful without their compile time type checking.
         | 
         | C? Not worth the trouble. C++? Not worth the tarpit or the
         | trouble.
         | 
         | Python? Definitely not keen, that language was much better
         | without the annotations.
         | 
         | Typescript people really like but I haven't played with. I'm
         | pleasantly surprised that unsound static + sound dynamic works
         | well.
         | 
         | Type annotations are not inherently good. Some type systems add
         | a lot of value, some really don't.
        
           | oldpersonintx wrote:
           | [dead]
        
           | chongli wrote:
           | This is not about type annotations, it's about type systems.
           | You can write Haskell programs without any type annotations.
           | Your program will type check and compile just fine. The value
           | comes from the checks (as well as the inference,
           | documentation, optimization, and everything else a modern
           | type system gives you), which you don't have to write
           | yourself, you get them for free.
           | 
           | People who say they prefer dynamic languages are really just
           | saying 'no' to all these free benefits.
        
             | JonChesterfield wrote:
             | If your language is wholly type inferred, and the type
             | system is expressive enough to deal with whatever one
             | wishes to write, it is indeed "free". If you ignore compile
             | time performance, run time performance, and that you're
             | writing in something between Idris and vapourware.
             | 
             | Otherwise the cost is merely being unable to write anything
             | that the type checker does not understand, and however long
             | your compiler takes to do the checks on what it does
             | understand.
             | 
             | Also a fair chance the whole program must type check before
             | you can see the results of changing a subset. In the worst
             | case you get to hunt down all the unused variables before
             | it'll run the test suite.
             | 
             | I prefer dynamic languages. That makes me a heathen on
             | these boards, to be ignored or chastised for my stupidity.
             | Regardless, those benefits do not come for free.
        
             | WJW wrote:
             | Even though I usually fall more on the "types good" side of
             | the discussion, the advantages you listed are not free at
             | all. They come at the cost of at least:
             | 
             | - having a compile step in between writing and running your
             | code. This drastically slows down the feedback loop of
             | development. The more your compiler has to check for you,
             | the slower it gets.
             | 
             | - being able to run your program in a half-broken state.
             | This may not seem like much of an advantage, but sometimes
             | it is good to just be able to run a broken piece of code to
             | see _how_ it crashes. This is especially important when
             | learning to program, but is still very beneficial when
             | learning a new language or framework, or sometimes for
             | debugging.
             | 
             | - As someone who has contributed to the main Haskell
             | compiler, I can definitely confirm that a more complicated
             | type system can slow down development of the language
             | itself too. It takes significantly more effort to grok all
             | the possible interactions as the codebase of the compiler
             | grows.
             | 
             | Don't get me wrong, I think encoding and enforcing program
             | properties with types is a great idea that will grow
             | further in the future. But the dynamic languages gained
             | popularity for good reasons, and some of those reasons are
             | still valid today.
        
           | ActorNightly wrote:
           | >SML or Haskell? Yep, like those ones
           | 
           | Not strong enough.
           | 
           | If you are proponent of strong typing, you need something
           | that is effectively a theorem prover. I.e when you define a
           | type, you define the scope of the data it can hold,
           | operations on that data, and the resultant types of those
           | operations. That way, when you code compiles, it is by
           | definition "correct".
           | 
           | When you accept anything less then that, you are basically
           | making a statement that you are willing to forgo some of that
           | correctness for convenience, which is fine, but that means
           | that no language out there is really good or bad.
        
             | DonaldPShimoda wrote:
             | Theorem provers' type systems are not necessarily
             | _stronger_ than SML 's or Haskell's; they are _more
             | expressive_ , which is a separate thing entirely.
             | 
             | That said, your position is also just weird to me. Yes,
             | theorem provers have nice type systems that are wonderfully
             | expressive. The trade-off is that some _common_ programming
             | patterns become difficult to use or are even impossible.
             | 
             | When it comes to everyday programming, I don't think
             | theorem provers are at a point where they are particularly
             | useful. Not everything needs to be proved formally, and I
             | don't think this position is at odds with the belief that
             | static type systems are generally "better" than dynamic
             | ones.
        
               | ActorNightly wrote:
               | > The trade-off is that some common programming patterns
               | become difficult to use or are even impossible.
               | 
               | Not really. Strong and expressive typing at its core is
               | simply creating data packaging containers that have
               | defined operations on them. It says nothing about logic.
               | You may be referring to the functional programming aspect
               | that comes with strong typed languages, which is related
               | but not the same as strong typing.
               | 
               | The point is that typing is just a tool that a programer
               | can use, whether its built into the language or ran
               | statically like MyPy. You can take a piece of code in C,
               | and write a test suite on input and output of that piece
               | of code, and accomplish much of the same thing that
               | typing accomplishes. However, in the case of
               | strict+explicit typing, the idea is that you wouldn't
               | need tests in the first place, because your code would be
               | correct by nature of compilation.
        
               | DonaldPShimoda wrote:
               | No, you are wrong.
               | 
               | Some theorem provers, such as Coq, are not Turing-
               | complete. This means you cannot write some programs, and
               | in particular you cannot write infinite loops in Coq.
               | Infinite loops are a common pattern (e.g., a REPL or a
               | GUI display waiting for input).
               | 
               | This is a trade-off, as I said. You gain the expressive
               | type system, but lose the ability to implement certain
               | programming patterns. It has nothing to do with the
               | strength of the type system.
               | 
               | ---
               | 
               | > whether its built into the language or ran statically
               | like MyPy.
               | 
               | All (true) type-checking is static, so MyPy "running
               | statically" is not a noteworthy feature to distinguish it
               | from other type checkers. I guess this point may seem
               | trivial to some, but the broader context of this
               | conversation involves conflation of the terms "static
               | type system" and "strong type system", so your misuse of
               | the word "statically" here seems worth pointing out.
               | 
               | That said, whether you use an external tool to check your
               | types or the type-checker is built into the compiler is
               | irrelevant, and I'm not sure why you brought it up at
               | all.
               | 
               | ---
               | 
               | > You can take a piece of code in C, and write a test
               | suite on input and output of that piece of code, and
               | accomplish much of the same thing that typing
               | accomplishes.
               | 
               | Depending on the perspective, this is factually
               | incorrect.
               | 
               | Type-checking is an ahead-of-time operation that
               | guarantees the absence of certain classes of errors at
               | run-time. Writing tests to check for the absence of such
               | errors is not equivalent, because you have not _proved_
               | anything; you merely gain confidence. They are
               | semantically distinct, even if you write many tests to
               | gain a lot of confidence.
        
               | ActorNightly wrote:
               | >Some theorem provers, such as Coq, are not Turing-
               | complete. This means you cannot write some programs, and
               | in particular you cannot write infinite loops in Coq.
               | 
               | You are talking about languages, Im talking about the
               | concept. The modern theorem provers aren't up to the
               | task. Due to Rices theorem, you cannot "fully prove" a
               | program, so a language that does this couldn't even
               | exist. The strict typing however can be applied to
               | subsets of the programming space, namely the data
               | processing pipeline, whereas higher level stuff like the
               | actual server code that does have an infinite loop to
               | listen to requests can be written in whatever.
               | 
               | The point is that no language recommended for strong type
               | safety today is anywhere fully complete to include the
               | rigor of something like a theorem prover, and anything
               | less then that is basically your own opinion on what is
               | "good enough".
               | 
               | >Type-checking is an ahead-of-time operation that
               | guarantees the absence of certain classes of errors at
               | run-time.
               | 
               | Run time errors are no different than compile time errors
               | as far as testing is concerned. Its not like the computer
               | blows up when you have a seg fault. And you absolutely
               | can prove what you need for operation.
               | 
               | Say your input to your code is an HTTP request of length
               | x. And output is some data processing on that request.
               | You can write a test suite that is basically like this
               | 
               | 1. Ensure that code returns a well defined error for x
               | values outside of given range.
               | 
               | 2. For all valid ranges in x, test all possible values of
               | every byte in that range, and ensure correct behaviour.
               | 
               | While overkill, this will absolutely exercise every
               | single piece of your code and prove correctness. You can
               | also couple this with checking things like memory access
        
             | JonChesterfield wrote:
             | SML is good enough for theorem proving. That's what it was
             | written for. Though you probably want convenience libraries
             | on top, maybe the one called HOL.
        
           | yxhuvud wrote:
           | 100% this. Developer experience in a language is a so much
           | bigger question than if it has static types or not.
        
           | xigoi wrote:
           | > C? Not worth the trouble. C++? Not worth the tarpit or the
           | trouble.
           | 
           | The OP said _strong_ static type system, so C and C++ are out
           | of the question.
        
         | oldpersonintx wrote:
         | [dead]
        
         | RHSeeger wrote:
         | Sometimes the question isn't "are types good", it's "are the
         | costs associated with static types worth it for this particular
         | use case". And the answer is almost always yes; but the
         | "almost" there is important.
        
         | msla wrote:
         | Similarly, choosing between 'int' and 'long' isn't part of a
         | type system, unless the only semantics your data has is being
         | an integer of a given width. Types are semantic, and telling me
         | "height is 32 bits" tells me jack shit about units of measure
         | or anything else.
        
         | sbjs wrote:
         | Yeah I've been in that camp since like 2016. TypeScript is
         | basically an essential for me now, and I don't debate it with
         | anyone. If they don't get it, it just gives me a baseline
         | understanding of how little experience they have in real world
         | software development.
        
         | leptons wrote:
         | Trigger warning: I love to write assembly language.
         | 
         | I probably love assembly language more than C#, or C++, or any
         | of the strongly typed languages I use.
         | 
         | Assembly language has no types. It doesn't pretend types even
         | exist.
         | 
         | Are you going to look down on me because I like to write
         | assembly language?
        
         | oweiler wrote:
         | God, what has become of healthy discussions? People getting
         | more and more toxic these days...
        
           | insanitybit wrote:
           | I'm all for healthy discussions, but I think it's fair to say
           | "I've had this discussion enough times, unless you're really
           | bringing something new to the table, I'm opting out".
        
           | digging wrote:
           | Is it really a healthy discussion? At least with respect to
           | JS vs TS (which is the most common argument as it's a choice
           | every front end team has to make), it's blogs saying "fuck
           | types, I like JS only." I'm not going to step in and tell
           | another team what to use but whining about the difficulty of
           | static typing is just not a productive conversation. I've
           | been converted by the top level comment; I'm not longer
           | interested in entertaining the discussion.
        
       | sproketboy wrote:
       | [dead]
        
       | booleandilemma wrote:
       | I don't think the opinion is even controversial at this point.
       | Even the hardcore JS developers I know have come around to using
       | TypeScript.
       | 
       | If you can't at least admit to the benefits of static types in
       | 2023 then you probably don't have experience building or
       | maintaining large software systems or working with a team of 15+
       | people, many of whom you've only met over Slack.
        
       | hangonhn wrote:
       | Does anyone here know how Standard ML inferred types? I really
       | loved coding in SML and its strongly type checking system. The
       | amount of bugs I produced was noticeably less. What I'm wondering
       | is why we can't use a similar system as SML to infer the types.
       | Other languages haven't adopted a similar system so there must be
       | some kind of trade off. What was the downside?
        
         | valcron1000 wrote:
         | Look up 'Hindley-Milner type system'. AFAIK, one feature that
         | break this system is subtyping which is very common in many
         | programming languages.
        
         | nyssos wrote:
         | > Does anyone here know how Standard ML inferred types?
         | 
         | SML uses Hindley-Milner (with some modifications to support
         | imperative code). Many statically typed functional languages
         | descend from it: Haskell and OCaml are the most prominent.
         | 
         | > Other languages haven't adopted a similar system so there
         | must be some kind of trade off. What was the downside?
         | 
         | If you're asking why existing popular languages don't adopt it:
         | they can't. HM type inference requires a HM type system, and
         | they've committed to a different one. At best you could get
         | good inference on a HM-typed fragment within the language
         | (though even that would mean making a lot of painful tradeoffs)
         | but it would break down the moment it made contact with
         | existing code.
         | 
         | If you're asking why HM languages didn't become more popular?
         | Historical accident, in my opinion. I don't think it has much
         | to do with the type system, given how fundamentally awful
         | Java's is.
        
         | mrkeen wrote:
         | > What I'm wondering is why we can't use a similar system as
         | SML to infer the types.
         | 
         | We can and do! Use SML!
         | 
         | People just don't find out about the good type systems because
         | the market is crowded out by mainstream shit.
         | 
         | And people write pieces about how good this shit is: "I was
         | going to add an Int to a String but the compiler stopped me!
         | Less [sic] bugs!". With arguments like that, why would you
         | switch camps?
         | 
         | Or sometimes you get fed shit and get told it's inference: "I
         | can replace the first word on the line with 'var'!".
         | 
         | So what are the downsides?
         | 
         | Inference doesn't play well with inheritance or mutability.
         | 
         | If you read Effective Java and see the points about avoiding
         | mutation and inheritance, then these downsides may very well
         | seem like upsides to you.
         | 
         | Why did you stop coding in SML?
        
           | hangonhn wrote:
           | SML has never been used in any of the jobs I've had. I
           | definitely have a very functional programming bend to my
           | preferences. The closest I've come to doing something like
           | SML for work is to use Clojure.
        
       | yc-kraln wrote:
       | The example from the article without any explicit arguments
       | reminds me very much of objective c's message passing concept,
       | which I actually quite liked and used very much. So, I guess the
       | answer is: there is no objectively correct way to do things,
       | except if the thing you are trying to do is get "engagement" then
       | take an extremely strong stance on something which has no
       | objectively correct answer.
        
       | alexvitkov wrote:
       | You're not "moving faster" if a typo is a runtime error and
       | you're not "more productive" if you can't change a function
       | signature without having to grep your codebase to find all
       | callsites and pray you fixed them all.
       | 
       | Types are good, but as with anything else people take it too far.
       | Making it your life goal to encode all business logic in the type
       | system results in an even more incomprehensible mess than not
       | having types at all. If the type name can't fit on one line in
       | the error message, you've gone too far.
        
         | ranting-moth wrote:
         | I've seen some insane Typescript type definitions. To be fair,
         | they were defined to work with historic vanilla JS code where
         | so many things could have been stuffed in the poor variable.
         | 
         | I'm forever grateful for Typescript, but I wouldn't be
         | surprised to see some of that code in a future research paper
         | titled "The era when types went too far".
        
           | alexvitkov wrote:
           | I'm mostly fine with bad TS definitions since the types are
           | cosmetic and you can always 'as unknown as whatever' your way
           | out of an insane type definition. If someone nests 5 generics
           | in Rust/C++ you'll have a much worse time.
        
             | sonusario wrote:
             | Do you still find this true when taking type aliases into
             | account?
        
           | globular-toast wrote:
           | The first time I saw this pattern play out was with CSS vs
           | table layouts.
           | 
           | A lot of web devs these days don't remember a time before CSS
           | but, back then, we used to use tables for page layout. This
           | was really an abuse of the `table` element of HTML, which was
           | designed to display tabular data, but it was basically the
           | only way to achieve many layouts like having a side menu bar,
           | for example.
           | 
           | Abusing `table` was bad for many reasons, including
           | accessibility. People started to care about the semantic web
           | and remembered that HTML is a markup language for content,
           | not a style language for layout. So people advocated for
           | using CSS for layout and reserving `table` for actual table
           | data.
           | 
           | But gradually this rule became both simpler and more
           | ridiculously followed. People started talking about "using
           | divs instead of table". They would look at a page source and
           | if they saw `div` it would get a nod, but if they saw `table`
           | the developer would be relentlessly abused because `table` is
           | old-fashioned. Eventually, of course, someone reinvented
           | tables using divs and CSS.
           | 
           | And then people realised the pendulum had swung too far.
        
             | timsneath wrote:
             | There's an irony that this comment is posted on HackerNews,
             | where the entire page of comments is hosted in a big
             | <table> for layout. Not sure if this is good or bad!
        
               | BLanen wrote:
               | Bad, tables are bad for tree-based data.
        
           | david422 wrote:
           | > I've seen some insane Typescript type definitions.
           | 
           | That's just because the code is bad, not because the type is
           | bad.
           | 
           | That's literally just the definition of, this code is so bad,
           | let's just not type it.
        
             | digging wrote:
             | Agreed. I've left a few `any`s or `as unknown as X` in
             | place before and typically leave a comment alongside it.
             | Something to the effect of: "This code is bad and will take
             | too long to refactor. Every time you trace a bug back to
             | this code, please adjust the logic and typing a little bit
             | to prevent the kind of bug you encountered. Eventually we
             | can replace this bad code with good code."
        
         | vonwoodson wrote:
         | You know, I'd always been like "`from pdb import set_trace:
         | set_trace()` and you can interactively edit. I don't care what
         | the type is because I can interact with my running program
         | better than a compiler" (followed by intense nerd chortling).
         | 
         | You know, until the program is non-trivial: passing data
         | between systems on a queue; using async, threading, and/or
         | multiprocessing; compiled binary critical-performance
         | libraries... and I'm left wishing I'd written the whole thing
         | in Erlang.
        
         | duped wrote:
         | > if you can't change a function signature without having to
         | grep your codebase to find all callsites
         | 
         | Every time I see a developer make this complaint about static
         | typing I wonder what the hell they're doing with their type
         | definitions and architecture where this is actually a problem.
         | 
         | > and pray you fixed them all.
         | 
         | If this isn't detected for you at compile/build time you're not
         | using static typing
        
           | _dain_ wrote:
           | The comment you're replying to is criticizing dynamic typing
           | here, not static typing.
        
         | Double_a_92 wrote:
         | > you can't change a function signature without having to grep
         | your codebase to find all callsited and pray you fixed them
         | all.
         | 
         | I really wonder how people can actually work like that. Is
         | there some overarching methodology like super strict tests with
         | 100% code coverage or so?
        
           | emerongi wrote:
           | Tools like https://comby.dev/ help with the refactoring
           | itself, but I'm never really 100% confident.
        
           | JonChesterfield wrote:
           | Regex find and replace across a codebase works fine,
           | especially if the functions aren't overload sets.
        
             | thfuran wrote:
             | If you have a tiny codebase maybe, but if there are a
             | couple million lines, it's likely that a pretty significant
             | number of functions are sharing names.
        
               | JonChesterfield wrote:
               | Those would be the overload sets
        
         | globular-toast wrote:
         | > You're not "moving faster" if a typo is a runtime error and
         | you're not "more productive" if you can't change a function
         | signature without having to grep your codebase to find all
         | callsites and pray you fixed them all.
         | 
         | I don't see how either of these things relate to type
         | discussions. A typo can certainly lead to incorrect code in the
         | most strongly typed, staticest language there is (otherwise,
         | what the hell is writing code even for?) What's worse: a
         | runtime error or no error that produces the wrong result?
         | Running a Python project might be quicker than compiling a C++
         | project. Dynamically typed languages can do better than
         | grepping for function calls.
        
       | tabtab wrote:
       | Although a lot depends on personal preference, in general "root"
       | infrastructure is best on strong typing, while "glue-ish" scripts
       | best as dynamic.
        
       | [deleted]
        
       | jillesvangurp wrote:
       | This debate is a lot older than typescript vs. javascript and
       | dates back to at least the nineties when languages such as
       | python, perl, and others were creeping into production systems.
       | Before that there were already things like tcl/tk and a few other
       | things of course. And of course people were messing around with
       | things like Basic as well.
       | 
       | A lot of the arguments against typing are a bit stale.
       | 
       | - We have transpilers now. Even most javascript coders use a
       | transpiler or at least a minifier. The overhead of a type checker
       | in such a tool chain is pretty minimal. Especially on a modern
       | laptop.
       | 
       | - We have type inference and a few other modern compiler features
       | now. Typing is a lot less verbose in e.g. Kotlin than it is in
       | Java. Java now has a little bit of type inference but it is still
       | pretty verbose in comparison. A lot of the typing is just added
       | by tools as well.
       | 
       | - A lot of languages like python, ruby, and others have types
       | now. And spin off languages that have better typing (e.g. Mojo,
       | Crystal) and preserve most of the original languages perceived
       | elegance. Just goes to show that typing can be done without too
       | much compromises.
        
       | todd8 wrote:
       | I understand that modern type systems can do anything (that can
       | be computed) since they are Turing complete. So are Java generics
       | and C++ templates and Lisp's macro systems, but I don't want
       | these things.
       | 
       | I've written a number of Turing machine programs; yeah it's
       | impressive that an imaginary machine that is so simple can run
       | any program that runs on any other computer, but it's no fun
       | writing code for a Turing machine. For the Theory of Computing
       | studying Turing machines is important.
       | 
       | If I don't want Turing complete type systems, what do I want?
       | Well, first off, the bugs I find in my programs that are more
       | troubling don't seem to be stopped by strong type systems. What I
       | want is to be able to declare assertions in my code. For example,
       | I'd like to tell the compiler that the variable _year_ must
       | always satisfy (2000  < _year_ < 3000) and that in a certain
       | block of code that _x_ and _y_ are always within 0.5 of each
       | other. I want the compiler to ensure that these invariants are
       | satisfied by a combination of compile time and run time checks
       | generated by the compiler.
       | 
       | The problem is that we can't expect programmers to use Turing
       | machine like type declarations, because the programmer must now
       | program the type system without bugs to ensure that the types in
       | the program carry enough information that higher level assertions
       | can be made about the original program's correctness.
       | 
       | TLDR, I want to work with higher level assertions about the code
       | than that provided by complex types.
        
         | kazinator wrote:
         | [delayed]
        
       | ranger207 wrote:
       | Dynamic typing is fine for exploring. If I'm trying out a new API
       | and don't want to look at the documentation every 30 seconds (or
       | more realistically the documentation is terrible) then writing a
       | simple service in Python is a great way to gain experience.
       | Someone mentioned Julia; I think that most of the stuff you're
       | going to be doing with Julia is exploring so it's fine that it's
       | dynamic. But, for anything actually intended to be used, all the
       | advantages of strong static typing come into play. The problem
       | arises when people start out exploring a problem with a dynamic
       | language, get something working, and then try to expand that
       | dynamic program into something production-ready.
        
       | Chabsff wrote:
       | While I agree with most of the post, it's just the tip of the
       | iceberg of the discussion. Stuff like interfaces, traits,
       | generics, concepts, inference, duck-typing, implicit conversions,
       | etc. all fuzzyfy the notion of "Strong Typing" in various ways,
       | some more than others.
       | 
       | The real discussion is not about types vs no-types, it's about
       | the role and place for each of these bending of the rule and
       | their associated tradeoff in different contexts. Op even takes
       | inference for granted towards the end of the post, but make no
       | mistake, that's a form of weak(er) typing.
       | 
       | For example, writing template code in C++ without frequent use of
       | type inference (aka. auto) can be an absolute nightmare (I
       | suspect that extends to generics programming at large, but C++ is
       | where I have the most experience here), and the legibility gains
       | from making use of it for iterators is broadly acknowledged as
       | being easily worth the obfuscation for scope-limited variables.
       | But there's also a strong case being made to avoid its use
       | entirely in most other contexts.
        
         | kagakuninja wrote:
         | C++ templates are a nightmare, because it is also a compile-
         | time macro system. The cryptic, giant error messages from
         | forgetting a > were legendary. Maybe this has improved, I
         | haven't used C++ in a long time.
         | 
         | Java by contrast has a greatly simplified generic system; Scala
         | improves on that with robust type inference, making generics
         | pretty trivial to write and use.
        
           | Chabsff wrote:
           | 100% agreed on all points. But even in these languages,
           | writing generics remains greatly facilitated by the use of
           | type inference, which is all I'm saying.
        
       | cmrdporcupine wrote:
       | It's interesting we've gotten to this place where the discussion
       | happens like it is on this forum, where acceptance of strong
       | static typing is pretty high.
       | 
       | 10 years ago the bias was strongly the other way. And in many
       | shops I've worked in, there was an _intense_ hatred of having to
       | declare types.
       | 
       | I like to think it's the development of better/smarter type
       | systems in mainstream programming languages (vs say Java which is
       | what was dominant then), as well as maybe maturing of software
       | engineer practices.
       | 
       | But I also fear it's just the trend-pendulum ticking.
       | 
       | That and I notice a _lot_ of Python jobs out there, which is an
       | ecosystem I 've kept away from for the last 10 years precisely
       | because my professional experiences with large dynamic-typed
       | late-bound Python codebases was terrifying. Beyond NumPy & ML
       | related projects, I fear that this might be indicative that the
       | _" types are just getting in my way"_ crowd is still very
       | influential...
       | 
       | Finally I also think it's important to distinguish two concept
       | that get mixed up -- type vs binding: static typing vs dynamic
       | typing and early-binding vs late-binding. It so happens that most
       | languages that emphasize static typing emphasize early-binding,
       | and vice-versa; but it's entirely possible to have very strong
       | types but still introduce sloppy late binding decision behaviour
       | that ends in all sorts of runtime exceptions. Java is/was
       | notorious for this. Reading configuration files to drive
       | application behaviour, or doing things like the Rust Axum
       | framework's "axum::extract::State" stuff, which can blow up at
       | runtime; they're not strictly type issues, but get mixed up in
       | some of the things people are talking about here.
        
         | syndicatedjelly wrote:
         | What were the arguments back then that supported the opposite
         | bias?
        
           | cmrdporcupine wrote:
           | "Move-fast & break things." "Test-first-design & aggressive
           | unit testing is the solution."
           | 
           | To be charitable, perhaps that the type system was getting in
           | the way, physically of what they wanted to accomplish
           | conceptually.
           | 
           | I actually think it has more to do with object-oriented
           | programming as it was propagated through C++ and Java. We
           | were told (and believed) that OO abstractions would solve
           | many software complexity problems. The focus of a lot of
           | programming work was/is on bringing these OO design patterns
           | into play. In large part the OO thing is about a kind of
           | dynamic dispatch. And yet languages like Java imposed a very
           | rigid way of doing OO, and made some of the patterns awkward
           | to express.
           | 
           | So if you believe in your heart in the promise of OO, but
           | find that your OO experience is relatively handicapped by
           | your static type system, one then blames the type system.
           | Ruby was maybe the best example of where this line of thought
           | was going/coming-from?
           | 
           | I think we are getting past this by getting (somewhat) past
           | OO as a dominant design methodology. But also by adopting
           | languages with richer static type systems.
        
       | karmakaze wrote:
       | I'm also on the side of static typing being beneficial. I would
       | always however consider the case at hand individually rather than
       | reject it offhand because it lacks it. e.g. a complex distributed
       | working system written with say Elixir or Erlang isn't easily
       | replaced with typescript. Not all systems are better with any
       | static typed language than any without.
       | 
       | Once you reach a certain size of developers, add static typing if
       | available, e.g. TypeScript, Sorbet, etc
        
       | vouwfietsman wrote:
       | Couldn't agree more. I suspect in the future software
       | professionals will be apalled by the abuse of freedom that we
       | currently have in languages.
       | 
       | The more freedom we take away, the higher quality software we
       | produce. Looking at you, Rust.
        
         | goalieca wrote:
         | This is an old thought but one which favours declarative
         | languages over procedural ones.
        
           | vouwfietsman wrote:
           | No it's not, I had it just now.
        
         | [deleted]
        
         | wait_a_minute wrote:
         | > The more freedom we take away, the higher quality software we
         | produce.
         | 
         | How are you measuring this?
        
           | vouwfietsman wrote:
           | Every fortnight during a full moon.
           | 
           | All kidding aside, obviously I don't. That shouldn't detract
           | from my statement at all though, nobody measures anything
           | about software. We're all in the dark. Thats actually
           | reinforcing my beliefs: we are in the dark because software
           | is unmeasurable _because_ of the freedoms taken by
           | programmers that fail to abstract or fail to be formalized.
           | 
           | Formalizing software, and then starting to measure changes
           | rigourously, is the first step we have to take towards
           | becoming a mature industry.
           | 
           | Formalization is the oposite of freedom. People think
           | software is like art, where freedom of expression broadens
           | horizons. This is no longer true, most software is not art,
           | most software is buttons that make money when clicked.
        
             | marcosdumay wrote:
             | > People think software is like art, where freedom of
             | expression broadens horizons
             | 
             | Artists live by constraints. Nobody prefer a blank canvas.
        
               | xigoi wrote:
               | > Nobody prefer a blank canvas.
               | 
               | Abstract art enjoyes would like to have a word with you.
        
               | esafak wrote:
               | Joke's on them; that's not art :)
               | 
               | What's next, sit silently behind the piano for four and a
               | half minutes and call it a musical performance??
        
               | xigoi wrote:
               | > Nobody prefer a blank canvas.
               | 
               | Abstract art enjoyers would like to have a word with you.
        
       | okeuro49 wrote:
       | I agree, and I think the industry does too. Types are being
       | retrofitted onto languages, like PHP, or added as a superset of
       | the language, like with Typescript.
        
       | thot_experiment wrote:
       | It seems like such a weird thing to have a super strong opinion
       | on. Sure if you only ever do one specific thing maybe there's an
       | argument to be made that one is better than the other. I think
       | there are just some problems that are best solved with statically
       | typed langs, and some are better solved with dynamically typed
       | langs. IIRC research shows it's a wash.
        
       ___________________________________________________________________
       (page generated 2023-10-04 23:02 UTC)