[HN Gopher] Writing code for both computers and humans
       ___________________________________________________________________
        
       Writing code for both computers and humans
        
       Author : pfrrp
       Score  : 47 points
       Date   : 2023-11-10 20:02 UTC (1 days ago)
        
 (HTM) web link (www.tonymottaz.com)
 (TXT) w3m dump (www.tonymottaz.com)
        
       | orn688 wrote:
       | I agree with the author that this is a reasonable way to indicate
       | their intent. But I've seen so many accidentally ineffectual code
       | snippets that if I saw this code I'd be inclined to delete it
       | unless there was also a comment expressing its purpose.
        
         | HuangYuSan wrote:
         | And a comment on its own would be enough anyway
        
           | earthboundkid wrote:
           | Yeah, ideally you'd have some kind of static typing to
           | restrict the code to only use Number, and then a comment that
           | says what the function does in case of NaN.
        
             | carapace wrote:
             | Yeah!
             | 
             | There was a thread the other day about a linter that
             | flagged useless code and all the odd bugs it caught, and I
             | think it would have flagged this snippet, eh?
             | 
             | "Interesting bugs caught by no-constant-binary-expression"
             | 
             | https://news.ycombinator.com/item?id=38196644
             | 
             | https://eslint.org/blog/2022/07/interesting-bugs-caught-
             | by-n...
        
       | jinwoo68 wrote:
       | I don't think what the author says is the intent of the code.
       | isNaN() returns true not just for NaN but for anything that is
       | "not a number"[1]. For example, it returns true for things like
       | "hello".
       | 
       | So it just canonicalizes everything that is not a number into
       | NaN.
       | 
       | [1] https://developer.mozilla.org/en-
       | US/docs/Web/JavaScript/Refe...
        
         | abecedarius wrote:
         | There's a whole set of different floating-point values which
         | are NaN, and this canonicalizes them into one particular NaN,
         | as I understand it.
         | 
         | I'm not even sure that covering type conversions was intended
         | here.
        
         | anonzzzies wrote:
         | This is my issue with js; isNaN looks related to NaN in a 1-1
         | mapping as in, testing 'x is NaN' but it doesn't. So the naming
         | is confusing as it does more than that, isNotNumeric() or so.
        
           | jalk wrote:
           | Seems like the author fell into this trap
        
           | eloisant wrote:
           | Yes, even better "isNumber()" because a function that tests a
           | negative can cause confusion and mistakes.
        
           | tetha wrote:
           | I am ready to oppose any `isFoo` function that doesn't return
           | a boolean. If you ask "Is this a Nan", why would you expect
           | 42 as an answer? Or, "hello". Kinda feels like "Are you at
           | home?" - "Kitchen". It eventually becomes a "yes" through
           | more thought, but eh...
           | 
           | I'd much rather call this "normalizeNaN" or something.
        
             | Jtsummers wrote:
             | `isNaN` does return a boolean though, it doesn't return a
             | normalized value.
        
         | stinos wrote:
         | Funny. If this is effectively so, the code is actually fairly
         | ok and clearly expresses the intent for humans yet the OP
         | claiming exactly that managed to still misunderstand the code
         | because they made up a precondition ('defaultValue is going to
         | be a number') probably exactly because they refused to 'To
         | answer this question, you need to start looking around for
         | clues' so they missed the clue [1]; or maybe rather the clue
         | is: dynamically typed so expecting a number is a wrong
         | assumption. Still I'd argue a comment explaining why it's in
         | this particular case fine that any non-sane input translates to
         | NaN and not an error might be worth it Well, unless that is
         | clear from the surrounding code :)
        
           | cxr wrote:
           | > dynamically typed so[...]
           | 
           | People accustomed to strongly typed languages and thinking
           | mostly of monolithic apps always pin things on dynamic typing
           | even where it's not the cause. It's not about dynamic typing
           | in this case.
           | 
           | What's going on here is partially because of separate
           | compilation and partially because of mobile code (as Lars Bak
           | explains[1]). Even if developing in a strongly typed
           | language, the machinery would still have to take care to deal
           | with the same thing. In fact, this isn't even JS; this file
           | is TypeScript--and this expression being strongly typed is
           | almost certainly exactly _why_ this code was written this
           | way: because `useControlledState <number>` demands it. If
           | `useControlledState` were just vanilla JS and no one were
           | doing typechecking during development and build, there would
           | have been no problem with passing something else as an
           | argument, because it will of course evaluate to NaN anyway
           | when undergoing the number treatment.
           | 
           | (This is kind of subtle, but it's not _that_ subtle. Too many
           | people make this mistake, and there 's probably something
           | that needs to be done about that; "because dynamic languages"
           | has become something of a thought-terminating cliche that
           | leads people to the wrong conclusions--as demonstrated even
           | in the interview, at the point where Bak felt prompted to
           | point this out.)
           | 
           | 1. Inside V8 -- A Javascript Virtual Machine. Going Deep:
           | Expert to Expert. Accessed July 3, 2020.
           | <https://channel9.msdn.com/Shows/Going+Deep/Expert-to-
           | Expert-...>.
        
             | stinos wrote:
             | Funny. Seems I fell into the same trap I just sketched,
             | making wrong assumptions because of not looking around in
             | the code. But to be honest from your explanation I still
             | cannot tell whether I merely used incorrect terminology wrt
             | dynamic typing (but the general principle still holding) or
             | whether this code guarantees that defaultValue is in fact
             | always a numeric type?
        
               | cxr wrote:
               | _This_ code doesn 't. It guarantees that within
               | `useControlledState`[1], `defaultValue` is either NaN, an
               | actual number, a number-like string, or something else
               | that can be coerced into one[2]. If `defaultValue` is,
               | for example, `true` or even an empty array, then the
               | result of the expression `isNaN(defaultValue) ? NaN :
               | defaultValue` will pass through `true` or the empty
               | array.
               | 
               | 1. <https://github.com/adobe/react-
               | spectrum/blob/main/packages/%...>
               | 
               | 2. whether one of those non-numbers is prevented from
               | actually making an appearance at this point for other
               | _reasons_ is a different question, but the fact remains
               | that one making its way through is not something that
               | would be stopped from proceeding further by the isNaN
               | check here
               | 
               | (Addendum to, I hope, clarify: I'll reiterate that it's
               | the type annotations on the `useControlledState` call
               | site parameterized as `useControlledState<number>` (and
               | the TypeScript team's decision to type `isNaN` to take
               | only parameters with a number type) that "guarantees"
               | `defaultValue` is a number. But that guarantee is a soft
               | one, i.e. not a guarantee at all, precisely because of
               | mobile code and separate compilation; I can contrive a
               | project right now that uses the Adobe Spectrum library
               | and pass whatever I want to it--it's not like the Adobe
               | devs' compilers are going to be able to stop me.)
        
             | cxr wrote:
             | PS: Gilad Bracha makes a similar point in this interview
             | about pluggable types:
             | 
             | Newspeak and Pluggable Types. Software Engineering Radio.
             | IEEE Computer Society. <https://www.se-
             | radio.net/2009/07/episode-140-newspeak-and-pl...>.
        
             | mrkeen wrote:
             | > because it will of course evaluate to NaN anyway when
             | undergoing the number treatment.
             | 
             | The point of typing is to make sure this situation doesn't
             | happen.
             | 
             | I write a method to accept Number inputs. I don't want to
             | do the work (whether it's thinking or writing tests) to
             | make it a pleasant experience for someone to pass non-
             | Number inputs to my function (intentionally by mistake).
        
               | cxr wrote:
               | Did you take note of the context in which this
               | conversation is taking place? Because it doesn't make
               | sense as a response within that context.
        
         | laurentlb wrote:
         | Thanks, your explanation makes a lot more sense. A short
         | comment would be useful in the original code.
         | 
         | Written as is, the original code looks surprising. I've seen
         | this kind of easily simplifiable multiple times in large
         | codebases, after years of refactoring and automated
         | transformations.
        
         | lo_zamoyski wrote:
         | Yeah, indeed, and this makes a whole lot more sense.
         | 
         | I can sympathize with the argument of the OP, but I wouldn't
         | exaggerate its profundity either. The intent was opaque enough
         | for the OP that he got it completely wrong, and even under the
         | OP's assumptions, the intent was still more opaque than
         | necessary. Furthermore, you're still passing around `NaN`,
         | which is sort of an analogue of passing around `null`. This
         | example suggests that perhaps a better language construct ought
         | to be used, like the `Option` type.
        
         | layer8 wrote:
         | Even if the author was right about the intent, I would disagree
         | with them that "this is how to write code with empathy for
         | other programmers", because the code would just make me think
         | "I must be missing something" (and indeed the author did miss
         | something).
         | 
         | My theory, by the way, was that the expression is normalizing
         | the possible NaN representations to a definite one, possibly to
         | prevent transporting information via the NaN representation.
         | 
         | Such "what the ...?" code should have a comment explaining the
         | intent (e.g. "replace non-numeric values by NaN"). If it is
         | used in multiple places, that's a good opportunity to define a
         | function for it, so the intent only needs to be documented in a
         | single place. (In programming languages with annotations as a
         | language construct, annotations could alternatively also be
         | used for referencing the documentation of a coding pattern from
         | multiple places.)
        
           | josephg wrote:
           | Yeah I absolutely agree. The intent of that code isn't clear
           | - and if you need more proof, look how many different
           | opinions there are in this thread about what that code is
           | trying to do!
           | 
           | Anyway, if they're trying to coerce non-numbers into NaN, I'd
           | write it like this:                   typeof defaultValue ===
           | "number" ? defaultValue : NaN
           | 
           | I think that's much more clear about the intent. I wouldn't
           | be confused by that code like I was confused by the code
           | cited in the article.
        
       | rco8786 wrote:
       | I don't know if that was the real intent of this code,
       | considering all the weird nuance around NaN in Javascript -
       | however I agree with the point the author makes, and will take it
       | one step further:
       | 
       | We should be building these semantics directly into our
       | languages, not relying on programmers to strictly follow a "best
       | practice". In this case, it would be making values non-nullable
       | and baking in Result/Option/etc style types that force
       | programmers into handling the null (or NaN) case.
        
       | lordwiz wrote:
       | This communicates an important idea, Well-written code is not
       | only correct and efficient, but it is also readable,
       | maintainable, and understandable to other programmers.
       | 
       | This culture should be encouraged more to make other developer's
       | life easier, The thing I do nowadays is that I would often switch
       | perspectives now and then, When switching perspectives, if i
       | become confused, i would work on making the code more meaningful.
       | 
       | Even if we are doing a solo project, if we come back to the code
       | after a long while, the code should be greeting us with wide open
       | hands rather than looking like an unexplored jungle.
        
         | cratermoon wrote:
         | When I'm programming I try to keep in mind what my future self
         | would need. I take notes when I'm programming, and put those
         | notes into the repo if it's a personal project, or in a
         | separate repo just for the project. Mostly those notes are of
         | little value to anyone by myself, but having them around lets
         | me condense my thoughts down to comments or documents useful
         | for other team members. With a little work, I can turn my notes
         | into a variety of other kinds of useful documentation:
         | references, explanations, FAQs, runbooks, etc.
        
       ___________________________________________________________________
       (page generated 2023-11-11 23:01 UTC)