[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)