[HN Gopher] We don't need runtime type checks
       ___________________________________________________________________
        
       We don't need runtime type checks
        
       Author : brentroose
       Score  : 11 points
       Date   : 2022-03-03 07:52 UTC (15 hours ago)
        
 (HTM) web link (stitcher.io)
 (TXT) w3m dump (stitcher.io)
        
       | jmyeet wrote:
       | Some thoughts:
       | 
       | > Because, here's the thing about runtime type checks: they are a
       | debugging device, not so much a safety net.
       | 
       | Yes, knowing why something crashed is a debugging tool and a
       | pretty useful one at that.
       | 
       | But what are you gaining by turning off the runtime type checker?
       | It's not clear. PHP in particular tends to be IO not CPU bound
       | and the people who have CPU performance issues with PHP are so
       | few. What problem is being solved here?
       | 
       | But the author seems to be arguging for static type checking in
       | PHP. You won't get an argument against this from me. I consider
       | dynamic typing a false economy and anathema to a large multi-
       | developer code base.
       | 
       | Oh and Hack is a superior PHP too.
        
         | qiskit wrote:
         | > But what are you gaining by turning off the runtime type
         | checker? It's not clear.
         | 
         | Only possibilities are a tiny boost in speed or a tiny
         | improvement in memory footprint? Can't think of anything else.
         | 
         | > PHP in particular tends to be IO not CPU bound and the people
         | who have CPU performance issues with PHP are so few. What
         | problem is being solved here?
         | 
         | Excellent point.
         | 
         | > I consider dynamic typing a false economy and anathema to a
         | large multi-developer code base.
         | 
         | Catch and fix as much as you can statically. Common sense to
         | me. But there are those who passionately argue otherwise.
        
       | egeozcan wrote:
       | That works wonderful as long as you have a flexible type system
       | like Typescript. For me io-ts[0] has been a godsend when I want
       | runtime type-checking on io boundaries (and you may have a lot of
       | them in a front-end application).
       | 
       | [0]: https://github.com/gcanti/io-
       | ts/blob/master/index.md#typescr...
        
         | purplerabbit wrote:
         | These sorts of libraries are great in my experience. Here's a
         | comparison of some of the more popular ones:
         | 
         | https://github.com/colinhacks/zod#comparison
        
       | raxxorrax wrote:
       | I often think people don't have a problem with static types and
       | instead would miss the implicit type conversion dynamic typing
       | provides.
        
         | paskozdilar wrote:
         | I love Python because you can just do                   foo =
         | "bar"
         | 
         | and be done with it. The interpreter knows it's a string
         | variable. But I don't really care about runtime dynamic typing
         | - I can't wait for Go to get parametric polymorphism,
         | interfaces and runtime type dispatching can be quite clumsy. I
         | would be perfectly fine with typed function arguments in a
         | Pythonic language and being able to only call functions that
         | fit the variable type (which is what I end up doing anyway with
         | typehints and mypy).
         | 
         | I think Go made a right decision there - they kept the static
         | typing but added a walrus := operator for automatic type
         | inference. Every function has a type signature so the type
         | inference algorithm is pretty trivial, and the language still
         | feels like Python:                   result, err :=
         | FunctionThatMayFail()
        
         | david422 wrote:
         | Do you mean something like passing a string to a function and
         | later passing a number and have it still act appropriately?
        
           | dboreham wrote:
           | Welcome to JavaScript.
        
         | convolvatron wrote:
         | those a pretty orthogonal issues, you can make a system
         | arbitrarily static or dynamic with or without implicit
         | conversion
        
         | DonaldPShimoda wrote:
         | > miss the implicit type conversion dynamic typing provides
         | 
         | Implicit type conversion is not an inherent property of dynamic
         | typing. For example, Python does not do implicit type
         | conversion except in arithmetic. You can't do, e.g., `4 +
         | "hello"`.
         | 
         | Leaving that aside, though... I'm actually not convinced
         | implicit type conversions are much of a win, _especially_ when
         | it comes to types other than the simple arithmetic ones (and
         | those can often be handled in explicit type-checking anyway,
         | through a numerical type hierarchy). I would rather be forced
         | to handle explicit conversion everywhere I want it than
         | accidentally forget about some edge case and end up with an
         | unintended implicit conversion that causes unexpected behavior
         | at run time.
        
           | chriswarbo wrote:
           | > Python does not do implicit type conversion except in
           | arithmetic. You can't do, e.g., `4 + "hello"`
           | 
           | Interestingly, PHP uses separate operators for numerical
           | addition (+) and string concatenation (.), so it's actually a
           | bit more explicit than e.g. Javascript (where 'x + y' could
           | result in normal numerical addition, or normal string
           | concatenation, or implicit conversion to a numerical
           | addition, or implicit conversion to a string concatenation!)
        
             | throw_m239339 wrote:
             | > Interestingly, PHP uses separate operators for numerical
             | addition (+) and string concatenation (.), so it's actually
             | a bit more explicit than e.g. Javascript (where 'x + y'
             | could result in normal numerical addition, or normal string
             | concatenation, or implicit conversion to a numerical
             | addition, or implicit conversion to a string
             | concatenation!)
             | 
             | Only because Rasmus didn't know how to design and implement
             | a "proper" programming language. This isn't a intended
             | feature, it just made parsing easier for him.
        
               | onaworkcomputer wrote:
               | Rasmus borrowed this distinction from Larry Wall, since
               | PHP was originally implemented in Perl (which also uses +
               | for addition and . for string concatenation).
               | 
               | The neat thing about PHP and the + operator is that you
               | can sometimes trick the interpreter into doing math on
               | the underlying bytes of the string: http://dominic-
               | mulligan.co.uk/wp-content/uploads/2015/05/SRE...
        
               | TazeTSchnitzel wrote:
               | There's nothing improper about having a separate operator
               | for concatenation.
        
               | throw_m239339 wrote:
               | > There's nothing improper about having a separate
               | operator for concatenation.
               | 
               | Only to monopolize that operator to then have to use "->"
               | for method call. C/C++ do that because of dereferencing.
               | There is no need for that in PHP OO, all objects are
               | passed by pointer to functions or methods.
        
               | giaour wrote:
               | Meh, other languages manage to assign multiple meanings
               | to single tokens and depend on context to resolve
               | ambiguity. PHP's issue here is that it refuses to do so,
               | which is how we ended up with the backslash as a
               | namespace delimiter.
        
         | 89vision wrote:
         | I think scala strikes a pretty good balance here. It's
         | statically typed, but the compiler will attempt to infer types
         | if not explicitly defined. If you want an implicit type
         | conversion the type conversion function needs to be defined and
         | in scope
        
       | afc wrote:
       | > When type errors occur in production, the end result is the
       | program crashing, nothing you can do about it.
       | 
       | Uh, you can catch the type error and recover (e.g., as with any
       | other runtime failures, fail the incoming request that triggered
       | the failure, unwinding the stack and reclaiming memory).
       | 
       | And, even if you didn't, crashing may be the ideal reaction:
       | https://github.com/alefore/weblog/blob/master/software-corre...
       | 
       | There are many reasons to prefer static type checks; I just find
       | this specific argument against runtime type checks flawed. Yeah,
       | static type checks are vastly better than runtime type checks;
       | but runtime type checks are vastly better than, uh, no type
       | checks.
        
         | hurril wrote:
         | This is a false premise or at least a false dichotomy.
         | 
         | Discovering that the car you ordered is a pizza is not
         | something you just... abort and undo/ redo. It's: wtf did you
         | do? My age is "pizza", your name is the function "not", your
         | account balance is a database connection. It's ridiculous to
         | say the least and using a tool that makes that > 0% probability
         | is just awful.
         | 
         | There are so many different typing systems, conflating all of
         | them into "static type checking" in order to have something to
         | pit against "runtime checks" is just not serious.
        
           | afc wrote:
           | > Discovering that the car you ordered is a pizza is not
           | something you just... abort and undo/ redo. It's: wtf did you
           | do? My age is "pizza", your name is the function "not", your
           | account balance is a database connection. It's ridiculous to
           | say the least and using a tool that makes that > 0%
           | probability is just awful.
           | 
           | Agree, which is why I think the author proposal of just
           | ignoring them (he's using this as an argument to say that
           | runtime type checks are useless, cause they crash the
           | program) makes no sense.
           | 
           | In practice, if the car I ordered is a pizza, I want to know!
           | In production, thanks to unit/integration tests with
           | reasonable coverage, dynamically typed languages will
           | typically exhibit typing errors in very unusual
           | circumstances, typically in branches or combinations that are
           | rarely exercised (otherwise the testing infrastructure would
           | have uncovered the bug), typically much later after the code
           | was written. So, yeah, I don't think any proposal of "just
           | get rid of the checks" deserves to be taken seriously.
           | 
           | But neither do I think your implicit proposal of "just crash
           | everything cause somewhere some very unusual request received
           | the wrong type" makes sense, at least not for large scale
           | reliable software. Just cancel the very unusual request (and
           | recover safely, and make sure to log the very unexpected
           | situation), but don't turn a single request failure into a
           | huge outage.
           | 
           | I think languages should aim to detect these inconsistencies
           | statically, at compile time, as much as feasible. Failing
           | that, they should aim to detect them at "test time". Failing
           | that, at runtime.
        
           | AndrewDucker wrote:
           | If you order a pizza and get a calzone then you refuse the
           | transaction and raise an error, you don't just fall over in a
           | heap on the floor.
        
             | [deleted]
        
             | adhesive_wombat wrote:
             | Don't you tell me what to do, you're not my supervisor!
        
       | TazeTSchnitzel wrote:
       | Runtime checks are what really differentiates PHP's approach from
       | other languages. It gives the type signatures teeth (ensuring
       | they don't lie) and keeps dynamic typing under control (types
       | enforced at function boundaries), which is really important in a
       | language where many operators and functions will return one type
       | most of the time and a different type the rest of the time. It
       | also means type information can be relied upon by the compiler to
       | produce more optimal code. In this respect it has a particular
       | edge over TypeScript, which throws away all the types when
       | producing JavaScript and thus the JS engine has to try to
       | reconstruct them if it wants to do optimisations.
        
       | michaelmior wrote:
       | There are many scenarios in dynamic languages where an
       | "incorrect" (i.e. unexpected) type could be provided, but the
       | program would not crash and potentially produce incorrect results
       | or at the very least, hide where the real error occurs.
       | 
       | For example, assume you have Python code to sum up an array (yes,
       | I know there's a builtin, but it's an easy example):
       | def calc_sum(arr):             functools.reduce(lambda x, y: x +
       | y, arr[1:], arr[0])
       | 
       | If we call this with an array of numbers, we get the expected
       | result. However, we can call the function with other types
       | without a crash.                   calc_sum([1, 2, 3]) => 6
       | calc_sum(['a', 'b', 'c']) => 'abc'         calc_sum('abc') =>
       | 'abc'
       | 
       | If we get such an input, likely something wrong happened earlier
       | in the stack. If we had a type check, we would find the problem
       | quickly. Without a type check, the problem will pop up somewhere
       | else since we expect the return value to be an integer, but it
       | ends up being a string. Or we might actually have a sequence of
       | events that does not result in a crash at all.
       | 
       | The example is a bit contrived and perhaps doesn't make the
       | strongest argument for runtime type checking, but it at least
       | suggests scenarios where we might detect bugs earlier.
        
       ___________________________________________________________________
       (page generated 2022-03-03 23:02 UTC)