Interview gone wrong
139 points by ashu1461 6 days ago | 200 comments
  • taxman22 4 days ago |
    Any time you use language specific tricks in an interview, you’re probably going to confuse your interviewer and not do well.
    • necovek 4 days ago |
      I disagree: if you are demonstrating your mastery of a language (and with Python, these things are important: using appropriate syntax is the difference between dog slow code and fast code), you should use idiomatic patterns like the above.

      Another of Python features is a great REPL: when unsure or confused by an interviewer, I'd just fire python from shell and type in 'x' == 'x' == 'x' to confirm and demonstrate it does the right thing (or write tests).

      Obviously, the interviewer should be careful not to sidetrack the candidate much, and let them do the work and attempt to help only if things don't work out.

      • mozman 4 days ago |
        In the real world you iterate, profile, and optimize
        • necovek 4 days ago |
          I am definitely a subscriber to not doing premature optimization, but in Python, there is a huge difference between

            found = searched_key in list(large_dict)
          
          vs

            found = searched_key in large_dict
          
          But also compare:

            searched_key in large_dict.keys()  # O(1)
          
          and

            searched_value in large_dict.values()  # O(n)
          • carlmr 3 days ago |
            So much this. Write code that you can reasonably expect to not be slow af, while not sacrificing readability. Then profile and optimize if necessary.
      • nerdponx 4 days ago |
        In this case the candidate evidently didn't understand it either, but was repeating a pattern they had seen before, which IMO is a form of anti-mastery: don't do things that you don't understand, especially when you're supposed to be demonstrating your skill and understanding.
        • necovek 4 days ago |
          Having a candidate understand all of the edge cases of a language syntax is a very high bar to clear: there is a lot of programmer between a "master" and "anti-master".

          I've used Python for 20+ years, and while I'd confidently use a == b == c or 1 < a < 10, I didn't know the specifics and wouldn't use it in cases like 10 > a < 8 (or really, any other case chaining supports).

          I believe myself to be an expert at Python and I'll explain differences between different loop types (while/for, ranges/iterators/generators, list comprehensions, functools, external C libraries like pandas or numpy), I think I wouldn't be confused only because I am aware I don't know the details and have a quick way to prove it works.

          • nerdponx 4 days ago |
            Maybe I interpreted the article differently than you did.

            I got the impression that the candidate was repeating the x == y == z pattern because they'd seen it in other people's code and was pretty sure it worked, not because they knew about comparison chaining. At minimum I'd expect a candidate to be able to clarify that (x == y) == z is not the same thing, not just "idk it works whenever I do it". My reaction to that was: at some point, you do need to at least be able to reason about your own code.

            In a more generous light, yes, I agree with everything you wrote. The precise details of comparison chaining are out of scope and I'm sure that most Python developers (myself included) don't know or remember them.

            • necovek 4 days ago |
              I agree that anyone (including an obviously juniorish candidate) using it should be able to explain it to an extent, but maybe not if you confidently and wrongly claim it doesn't work as an interviewer :)
      • sgarland 3 days ago |
        This is my opinion as well, but unfortunately isn’t always held by others. I once interviewed and by dint of knowing Python’s itertools module, absolutely destroyed the interviewer’s questions that they clearly thought would take some time to do.

        I was told later that while I “obviously knew Python quite well, it didn’t give a good signal for my capabilities.”

        • carlmr 3 days ago |
          >I once interviewed and by dint of knowing Python’s itertools module, absolutely destroyed the interviewer’s questions that they clearly thought would take some time to do.

          If I see such a situation I usually ask the interviewer whether they want a concise solution using libraries or they want to see how I would do this if I had to do it from scratch.

          Or I just offer both, I show that I can do it, but that I know it would be easier to do with x.

          I think this is a great opportunity to show you're a good communicator as well as a problem solver.

          • sgarland 3 days ago |
            Fair point.
    • throwaway313373 4 days ago |
      But it's not a "trick", it's just a normal Python code.

      I don't think that anyone who main programs in Python would perceive it as some kind of cool/unusual trick and not just normal code.

    • phrenq 4 days ago |
      I suspect the interviewer would have likely been fine if they’d been able to explain chained comparisons and how they work. I would probably consider the interviewer using them without understanding them to be a negative signal.
      • selcuka 4 days ago |
        It is possible that the candidate would normally use it from muscle memory, but got confused under the stress of the interview.
        • phrenq 3 days ago |
          Fair enough. In general, I think the interview is a pretty lousy way to measure how good a software developer is.
    • recursive 4 days ago |
      If you're used to python, you wouldn't consider it to be a trick.

      If you're giving interviews, and evaluating code in a language you don't know, don't be so confident it's wrong. Ask the candidate how it works.

      • nerdponx 4 days ago |
        In this case the candidate also didn't know.
      • ball_of_lint 4 days ago |
        I've used python for ~2y now and I'd balk at and rewrite this statement, considering it unclear at best.
        • recursive 3 days ago |
          That's an entirely reasonable point of view.

          The important part here is that there are a substantial fraction of python developers that don't share your sentiment.

    • Waterluvian 4 days ago |
      “Language specific tricks” are the entire value proposition of there being more than one language.
    • Der_Einzige 4 days ago |
      My usage of "yield" (alongside knowledge of "prange" from numba) in an interview instead of return has sealed the deal on a 200K offer (ML role circa 2020).

      "Confusing" the interviewer is a totally valid strategy! It's the only strategy when python async is involved!

    • jyounker 3 days ago |
      It's not a trick though. It's normal Python code. It's so common that you don't even think about it. It's just how equality comparisons work in the language.
  • Kim_Bruning 4 days ago |
    This mirrors mathematical notation for things like ranges or equality checks

    5 < x <= 25

    x == y == 10

    • murderfs 4 days ago |
      Unfortunately, it's more permissive than mathematical notation: `3 > 1 < 2` evaluates to True.
      • solveit 4 days ago |
        I think mathematicians looking at that expression would curl their lips in mild disgust, but also evaluate it to True.
      • throwaway313373 4 days ago |
        I can think of some more interesting examples when it violates intuition gained from mathematical notation.

        When looking at `a == b == c` we naturally assume that not only `a == b` and `b == c` but also `a == c` because equality is assumed to be transitive.

        The problem is that in Python we can make `==` operator to do literally whatever we want, so in Python `==` doesn't have to be transitive.

        You may argue that no reasonable person would define equality in such way that is not transitive.

        To which I would reply that approximate comparison of floating point numbers looks perfectly reasonable to me.

            EPSILON = 10**-9
        
            class Foo:
                def __eq__(self, other):
                    return other.bar - EPSILON <= self.bar <= other.bar + EPSILON
        • Kim_Bruning 2 days ago |
          I love the fact that you defined Foo.__eq__ by means of a chaining comparison!
      • jyounker 3 days ago |
        As someone who trained in mathematics, I would 100% say that mathematicians would evaluate it as true. It's not the cleanest way to write it, but intent is clear.
  • mlinhares 4 days ago |
    Stopped judging candidates on "style" due to stuff like this. I only comment if the code doesn't work, if it works i don't really bother to correct code style or provide feedback on it.

    45 minutes interviews aren't really the place to evaluate this.

    • pavel_lishin 4 days ago |
      It sounds like the author wasn't nitpicking style - they thought the code literally wouldn't work.

      (But, the intent on the interviewee's part was definitely clear - I'd definitely let this pass.)

      • Izkata 4 days ago |
        The blog itself isn't clear, and I think that's confusing some of the people here:

        > The candidate this time was programming in python

        But the code blocks aren't in python. But in the paragraph afterwards they capitalize "True" which is a python thing. Then afterwards mention they're using javascript as their reference, which uses "true" instead and the code blocks could be javascript.

        It feels like the author has more language confusion going on than just this one feature of python.

      • mlinhares 3 days ago |
        That's why i put "style" in quotes, the interviewer didn't know about the feature but still decided it was "wrong" or "ugly" even though the code works.
    • vdvsvwvwvwvwv 3 days ago |
      Linters are for this.

      You need to detect if someone is humble and smart enough to fit in to how you do things as a team, whatever that is.

      Not reject someone for not hitting a style guide on a piece of paper tucked behind a hidden secret door. (As I was once!)

  • Buttons840 4 days ago |
    Python evaluates `2 == 2 == 2` to true. JavaScript evaluates the same to false. Somehow we've decided that Python is the weird one it seems.
    • throwaway313373 4 days ago |
      To be fair, there are edge cases [0] when it does look weird.

      [0] https://github.com/satwikkansal/wtfpython?tab=readme-ov-file...

    • recursive 4 days ago |
      Not in my browser console. (but it's true for a different reason)
    • pcthrowaway 4 days ago |
      1 == 1 == 1 is actually true in Javascript due to type coercion

      You're probably thinking `1 === 1 === 1` which is indeed false

      • dartharva 4 days ago |
        I tried 2 == 2 == 2 in my browser's (Chrome) console and it evaluated to false.
        • Buttons840 4 days ago |
          I stealth edited my post. Sorry.
  • zitterbewegung 4 days ago |
    I'm confused about this blog post. Python is mostly C inspired but actually more pseudocode inspired (which helps its popularity) which is why chained expressions exist.

    Also, why would you conduct an interview in a language where even if you don't know the syntax (and this is obscure) you could have looked it up or disallowed the interview to be done in Python? I think the due diligence with this issue is more to the interviewer than Python.

    • whack 4 days ago |
      > Also, why would you conduct an interview in a language where even if you don't know the syntax (and this is obscure) you could have looked it up or disallowed the interview to be done in Python?

      The norm in most of my interviews has been that candidates can solve coding problems in whatever language they are most comfortable with. For most languages like Python etc, it would be a mistake to reject a candidate just because they don't have experience with that specific language.

      • userbinator 4 days ago |
        The norm in most of my interviews has been that candidates can solve coding problems in whatever language they are most comfortable with.

        I assume they've already filtered out candidates whose "most comfortable language" isn't the one they're hiring for, or they're going to have a difficult time when they come across the one who wants to use APL or x86 Asm.

        • titanomachy 4 days ago |
          I always interview for generalist jobs in python, but most jobs I’ve done use other languages.
        • lvturner 4 days ago |
          I heard a tale of a candidate white boarding in an obscure language (in a bit of an attempt to hide a deficiency), unfortunately for the candidate the interviewer happened to be well versed in the language and saw right through the charade.
          • 8n4vidtmkvmk 4 days ago |
            Hah. Even if the interviewer didn't see through the charade they have plenty of time to check the code after the fact. Once or twice a candidate has done something I didn't know about so I just googled it. Nice little learning opportunity for me.
    • awesome_dude 4 days ago |
      Mate, let's be honest, we've all been in interviews where the interviewer had a serious misunderstanding of the language the job was supposedly using, let alone some other language.
  • throwaway313373 4 days ago |
    I don't know why didn't the candidate just explain to the interviewer what chain expressions are.
    • Buttons840 4 days ago |
      Sounds like he didn't know the details, but had seen this pattern in Python code and knew it worked. When asked, he was confused about the exact details of why it worked.
  • Buttons840 4 days ago |
    Why did the author consider this an "interview gone wrong"? What was "wrong" about?
    • necovek 4 days ago |
      Interviewer made a mistake and confused/sidetracked a candidate in a short interview.
      • Buttons840 4 days ago |
        The interviewer made no mistake though, they made an observation; they were confused by the boolean expression. The candidate said they understood the interviewers concerns and was also confused, and didn't have an immediate answer. This is all normal and healthy, and something you'd commonly see in healthy and competent development teams.

        The only thing I see that's wrong is that the interviewer thinks something went wrong.

        • necovek 4 days ago |
          Mistake:

          > ...the statement even though logical, is not technically right because if we start from the left cell[0][0] == cell[1][1] would evaluate to True and then True == cell[2][2] would evaluate to False given that the cell contains a char.

          Interviewer seemed confident ("is not technically right") which confused the candidate:

          > I told the candidate about the same and he agreed but he was confused at the same time

          Candidates are already in a high stress situation, you don't want to add to it unless you really know what you are doing (i.e. you are specifically looking for deep language mastery).

          Interviewer has correctly realized they've done this and learned from it: kudos to them even if too late for this candidate :)

        • wiseowise 4 days ago |
          Interviewer made a mistake, stop rationalizing.
          • Buttons840 3 days ago |
            But is it "wrong" to make a mistake?
            • necovek 3 days ago |
              You said earlier:

              > The interviewer made no mistake though

              So is it wrong to admit that you made a mistake? :)

              And no, it's ok to make mistakes, but it is even better if we admit to them and learn from them (and the faster we do that, the better it is).

      • blitzar 3 days ago |
        If the interviewer is a good interviewer - they inadvertently gave the candidate an oportunity to demonstrate a range of skills.

        An outstanding candidate when questioned would mention that in most languages this evalates to that, but in python it evaluates to this, and offer an alternate method chaining and's on the spot in response to the confustion.

        If they are a bad interviewer - they would allow their ego to derail the interview.

        • necovek 3 days ago |
          An outstanding candidate might be an average candidate in a wrong setting.

          With my last job, I fumbled an easy question for me that I usually wouldn't, but it was a 10pm interview after I got up at 4am that morning and have almost fallen asleep when putting my kids to sleep at 9pm. I got the job (and then got promoted twice in 18 months), but if interviewer "inadvertently" confused me on top of my mental state, it might have been game over for me (and them, since I turned out to be an "outstanding" candidate).

    • Retr0id 4 days ago |
      everyone knows the purpose of an interview is to prove that the interviewer knows more than the interviewee, thus the interview failed
  • int_19h 4 days ago |
    In this respect, Python makes a lot more sense since that is how you'd normally write such an equality in math, and generally how people chain them: A=B=C means A=B and B=C.

    Part of the problem here is that we treat true/false as "just another value" in programming, and thus the usual operators are used to compare them. In math notation, if you wanted to compare the result of comparison A=B to a Boolean value C, you'd normally write something like (A=B)≡C, using different operators for equality and equivalence.

    Interestingly, programming languages haven't always treated Booleans in this way. If you look at ALGOL 60, it starts by cleanly separating expressions into arithmetic and logical ones, and defines completely different sets of operators for each (the reference language also uses = for numeric comparisons and ≡ for Booleans; and boolean inequality is, of course, just XOR).

    • analog31 4 days ago |
      Indeed, and likewise, I think Pascal would have thrown a compile-time error due to a type mismatch.
    • throwaway313373 4 days ago |
      I think that the main issue here is not treating true/false as values but allowing them to be implicitly converted or compared to numbers with the assumption that true equals 1 and false equals 0.

      I think that Rust got this right. It doesn't allow you to add integer to boolean or multiply boolean by float etc, because it is unclear what does it even mean mathematically.

      Also, most languages implicitly assume that any value of any type is either "truthy" or "falsy" thus you can do something like `while(1) { do_stuff() }`. Rust doesn't allow this BS, `if` and `while` expect a boolean so you have to provide a boolean.

      • flakes 4 days ago |
        A lot of languages have no boolean primitive to begin with. Often in older languages, the values for `true` and `false` are aliases for `0` and `1` respectively. Perl and earlier versions of C, Python, and JavaScript are notable.

        Perl is probably the most awkward due to context-sensitive casting. e.g. the string `"0"` in a boolean context evaluates as an integer, and the boolean interpretation for `0` is false.

        • erik_seaberg 4 days ago |
          Sometimes Perl uses "0E0" as a value that is equal to zero yet not false. Javascript has even more cases where equality isn't transitive.
        • int_19h 3 days ago |
          JavaScript had Booleans as a primitive type as far back as I can remember. The problem, rather, is that it's altogether too eager to convert everything into everything else.
      • int_19h 4 days ago |
        That resolves the problem for other types, but you still have the case of (a == b == c) being parsed and evaluated as ((a == b) == c) if all three are booleans, which is still not an intuitive interpretation. I think the PL either has to ban such construct outright and require parentheses, or treat it as an n-ary operator like Python does (albeit perhaps with a few more constraints on what you can chain, for the sake of readability).
    • the5avage 4 days ago |
      I think it makes sense in python for ==, <=, >=

      I cannot see it for !=

      "a != b != c" is not equal to "not (a == b == c)" which is a bit strange imo

      • irishsultan 3 days ago |
        I don't see how you could interpret "a != b != c" as equivalent to "not (a == b == c)" in the first place. In the first expression a doesn't equal b and b doesn't equal c (no restriction on a and c). In the second expression you could have a == b, but b != c (and vice versa), clearly that's not equivalent to the first expression.
        • the5avage 3 days ago |
          "a == b" is the same as "not (a != b)"

          Maybe I'm simple minded though.

          • int_19h 3 days ago |
            If you treat each "!" as a NOT, then (a != b != c) has two NOTs, but !(a == b == c) has a single one, so this is a bit like expecting that !(a && b) is the same as (!a && !b).
          • Doxin 2 days ago |
            "a == b == c" translates to "a == b and b == c", similarly "a != b !=c" translates to "a != b and b != c"
  • tasty_freeze 4 days ago |
    The candidate was writing an accounting program in COBOL and he wrote "ADD 2 TO SUM.". None of the handful of languages I kind of know support that syntax. It turns out that COBOL actually supports this nonsense. I explained to the candidate that when he is writing valid COBOL syntax, it is confusing to people who don't know COBOL and he agreed.

    This is a fail for the interviewer, not the interviewee, nor for Python.

  • encomiast 4 days ago |
    I know the point of the piece is the python syntax here, but I got stuck on: "judge things like code quality / speed / conciseness etc."

    Do people generally write concise code on right off the bat when confronted with a new problem? I've always taken the same approach I would with writing: get something that works; refactor for concision. Maybe everyone else is playing 3D chess and I'm still on Chutes and Ladders?

    • tbrownaw 4 days ago |
      There are degrees of conciseness.

      I've seen real code that looks like

          if(bool_var == false) {
            other_bool_field = true;
          } else if(bool_var == true) {
            other_bool_field = false;
          }
      
      Which I suppose could be called anti-concise.
      • andrewflnr 4 days ago |
        Yes, even the "unconcise" first draft of anyone who cares enough to be here on HN is much better than some of the code out there.

        There's a basic level of concision you'll have by default if you actually understand the problem and the tools. You won't go away out of the way to complicate things. Maybe it's still a far cry from optimal, and definitely not code golf, but enough that I'd be worried if I saw even a first draft without it.

      • BrandoElFollito 3 days ago |
        yes, when writing this as other_bool_variable=!bool_var you make it much better because the code speaks for itself ("other_bool_variable is the opposite of bool_variable").

        The risk is that you may end with such concise code that nobody understands what it does. I went that dark path with perl 20 years ago, form "oh what a cool language for someone who comes from C" to "let's squeeze that in half a line, and either do no understand what it does, or add three lines of comments to explain".

        But yes, there is a good middle-groud somewhere

      • spacebanana7 3 days ago |
        When I see code like that, I wonder whether a beginner is trying to fix a bug where they unexpectedly copied by reference rather than value.
      • sangpal 3 days ago |
        I wouldn't consider if (bool) or x = !bool to be concise coding. That's just regular code.
    • awesome_dude 4 days ago |
      Yeah - when I went through University the mantra I was taught was

      1. Get it working

      2. Get it working well

      If you're faced with an unfamiliar domain, you don't rock up to it and throw all the super optimised fastest code at it. in fact I would view someone who did as having done the test before (making it worthless).

    • nerdponx 4 days ago |
      Everyone thinks differently. "thing1 == thing2 == thing3" is a pretty natural expression of the idea here IMO.
    • jbverschoor 4 days ago |
      But the code doesn’t work. That should be problem nr 1 for such a simple problem.

      Syntactical sugar doesn’t matter anymore at that stage

      • encomiast 4 days ago |
        Maybe I misunderstood the piece, but it seems the last sentence, "Well the code is indeed correct" suggests it _did_ work (although I'm also a little confused about what it means when all values are '-' which I interpreted as 'no piece played').
        • jbverschoor 3 days ago |
          The code might compile, but it does not functionally with in an empty game state. Resulting in an always win for the first player if he does not play on any diagonal
    • userbinator 4 days ago |
      Do people generally write concise code on right off the bat when confronted with a new problem?

      As someone who has been on the interviewer side: this is an indicator of how much the interviewee "thinks first"; the ones who immediately start spewing tons of code are usually those who don't really have a good understanding of what they're trying to do.

      • bowsamic 4 days ago |
        Thinking first is a very Cartesian approach to development and not necessarily the best way. Many people think through a more engaged approach of doing
      • davedx 4 days ago |
        As someone who's done a lot of interviews on both sides: I get where you're coming from but don't really think it's as universal as you think. Some people gain understanding through doing; and there's nothing wrong with that?
      • huhtenberg 3 days ago |
        Exactly, amen to that.

        Think first, code second.

      • dkdbejwi383 3 days ago |
        Thinking by doing is also valid.

        I code similarly to how I write, which is similar to how I draw etc. I start with very rough ideas and sketches, then I gradually iterate over those, refining ideas and throwing bits away. And eventually I have a working version/first draft/etc

        I just can't get things done if I were to try and think of the entire solution first before getting anything down on paper. Maybe that's an ADHD thing, needing to let the idea take form lest it runs away and I get lost in the weeds

        It's less "spewing tons of code" though and more starting with an outline, stub functions and comments to break up the steps before filling those out.

    • atoav 4 days ago |
      There are problems I have encountered a billion times and of course I have an elegant concise solution for it, if I am an experienced programmer.

          if any([a in ["-h", "--help"] for a in args]):
              display_help()
      
      Would be one of those. Generally I learned that it can be beneficial to treat things as lists early on, e.g. if you have a program that takes one input file it costs you next to nothing to allow the input to be mutiple files as well.
      • ckastner 3 days ago |
        That still looks like something that a novice might trip over when reading this. Just describing what it does is already a bit convoluted: it tests whether any value of a list of booleans, produced by a generator expression by testing membership of a value in some other list, is True.

        I would have gone with the following, as it requires less mental unpacking:

          if set(args) & set(["-h", "--help"]):
              display_help()
        
        Also, note that any() works with any iterable, the outer brackets are not needed given the list expression.

          if any(a in ["-h", "--help"] for a in args):
              display_help()
        • dijksterhuis 3 days ago |
          on my phone and a bit discombobulated today, so we’ll see how i go with this

          > That still looks like something that a novice might trip over when reading this.

          my experience with “juniors” who start with python is that they think in lists and dictionaries. they don’t think in terms of set theory. that’s just the way python is taught.

          i would definitely set interview questions where a “decent” solution involves using sets and see who gets it without iterating over lists (ha, setting an interview question on sets… geddit? i’ll see myself out).

          > Just describing what it does is already a bit convoluted

          yeah, but python only/main “juniors” primarily think in terms of lists, see above.

          so, between making sure all juniors can read the code versus doing it succinctly, but juniors all need to learn about sets — practicality wins out quite often.

          > I would have gone with the following, as it requires less mental unpacking:

          > if set(args) & set(["-h", "--help"]):

          > display_help()

          if i were reviewing this code i’d ask you to switch it to

              if set(args).intersection(set(["-h", "--help"])):
          
          it is more verbose and more brackets, but it is more explicit and obvious what is happening to some junior who has never dealt with sets before (hmm what’s an intersection? should probably google it)

          & is also used for the bitwise AND operator. plus some other stuff in various frameworks like django. so could lead to some confusion.

          > Also, note that any() works with any iterable, the outer brackets are not needed given the list expression.

          i generally HATE the overuse of generator expressions in python. everyone writes absolutely everything as an inline generator expression, making it hard to test.

          but, rant aside, yes, this is probably the one i would pick during a review (likely after a discussion about how using the intersection method makes things less legible and then this gets suggested somewhere).

          people don’t realise not every genexp needs to be a list. easy mistake to make with the “everything is a list or a dict” mental model.

          • Izkata 3 days ago |
            ".intersection()" takes any iterable, it can be:

                if set(args).intersection(["-h", "--help"]):
            
            Also python has had a special syntax for sets since 2.7 (I think), though I haven't seen it used very often:

                if {"-h", "--help"}.intersection(args):
            • atoav 2 days ago |
              It makes so much sense to think about this as sets, thanks
        • nerdponx 3 days ago |
          Being extremely pedantic, omitting the outer ()s is legal for a generator comprehension. That is, the following are equivalent:

            foo(x for x in xs)
          
            foo((x for x in xs))
          
            gen = (x for x in xs)
            foo(gen)
          
          But these are not the same as:

            foo([x for x in xs]
          
            lst = [x for x in xs]
            foo(lst)
          
          It doesn't matter in this tiny example, but the difference between generators and lists can be very very important when working on very large amounts of data (e.g. processing a big text corpus), or a potentially-infinite stream of data.
      • nerdponx 3 days ago |
        Fun Python fact time!

        `any` works on arbitrary iterables, so you can use a generator comprehension instead of a list comprehension:

          if any((a in ["-h", "--help"] for a in args)):
              display_help()
        
        Which algorithmically is a wash, because the time you save not-materializing the list, you waste in the overhead of iterating through a generator (and it's all +/- nanoseconds in recent versions of Python anyway). However, Python has a special syntax that allows you to omit a layer of parentheses when a generator comprehension is the only argument to a function, leaving us with the very elegant (IMO) syntax:

          if any(a in ["-h", "--help"] for a in args):
              display_help()
        
        This works for any(), all(), str.join(), and others. Yet another demonstration of why I think the iteration protocol is one of the best features in Python (and underappreciated as such).
        • atoav 3 days ago |
          ah cool, I didn't realize
    • blitzar 3 days ago |
      if you know the domain for the task at hand (+a few very basic soft skills) you can learn a lot from watching and discussing with a candidate while they are doing the task.

      In reality - tasks like these are garbage leet-code samples; candidated who have been grinding examples rapidly regurgitate the best solution from the forums and impress the interviewer, but would fail if asked a basic question on what they produced. Those that solve it reasonably from first principles fail the task.

    • eterevsky 3 days ago |
      I also judge code quality at the interviews that I perform. I just give the candidates time to improve their code after they come up with something working.
  • cplat 4 days ago |
    If your knowledge of Python comes from JavaScript, I would not blame Python for it. It's the failure of the person to not "read the instructions" and assume instead. Maybe conduct interviews in languages that you're familiar with?
    • grujicd 3 days ago |
      If you were programming long enough, you easily had contact with dozens of languages. How do you pick up a new language? You can't really treat it as your first one. Especially if you need it "for yesterday". You won't read about "if" or "for". No, you scan for what's different from what you already know. If you're lucky you'll find "python for javascript programmers", but that probably won't go into non-core details like this. In practice, you learn basics first and start coding. Then you find a piece of code somewhere that you don't understand. That's a learning opportunity! However, it's easy if it's a function since it's easily googlable. Operators are harder to search for, for instance in new versions of C# you have operators like "?." (just an example). Since googling is hard you go to some "operators documentation" and try to find it there. And hope that it covers the new version. For cases like this story it's even harder because it describes a concept (chaining) and you maybe don't even know which name is used for that.

      At least ChatGPT recognized and explained it correctly, so it makes picking up new features easier than it used to be. I'm making a mental note to ask LLMs whenever I encounter unknown constructs.

      • skydhash 3 days ago |
        If it’s a language I don’t know, I’d still read a book or check the doc for a tour of the syntax. I can scan one in a couple of hours and get an overview I can refer to later for a more specific question. Even if I needed it for yesterday.
  • polyomino 4 days ago |
    This is a tangent, but checking if all the elements in the diagonal position are the same is not sufficient. You also need to check that any of the elements are not '-'.
    • bowmessage 4 days ago |
      That’s… what the article says.
      • cpfohl 4 days ago |
        To be fair to parent I read the whole thing and also missed that.
      • nothrabannosir 4 days ago |
        That’s not what the article says. The last paragraph:

          if (cell[0][0] == cell[1][1] == cell[2][2]) {
              return Winner
          }
        
        > Well the code is indeed correct . Well done, Python… for finding yet another way to confuse us all.

        The code is incorrect: if all entries are '-' there is no winner. Even ignoring the braces…

        • freehorse 4 days ago |
          You do not know how the game was implemented to assume that.
    • solveit 4 days ago |
      Depends how the flow goes. It's reasonable to only check the diagonal when one player has actually played on the diagonal, in which case this is fine.
  • noncoml 4 days ago |
    I am idiot but I would, and have in the past, have wasted the whole interview time argue in that I am right and he is wrong.

    Yes, John, some switches do start sending the packet before finish receiving it. It’s called cut-though switching. Hope you googled it. And yes it was worth losing the job offer over it.

    • the5avage 4 days ago |
      I would say if you know you have to later work with the guy and he will be higher up than you this is actually smart.
    • blitzar 3 days ago |
      John says you were wrong then and you are still wrong now. When talking about the problem domain John also mentions some switches do start sending the packet before finish receiving, it's called cut-though switching.
      • noncoml 3 days ago |
        Didn’t get you..
  • reader9274 4 days ago |
    If you know nothing about Python or coding, and you see a=b=c, you'd think that's true when all three a,b,c are the same. Python does that beautifully here, and that's the intent. It's not Python that's confusing, it's your previous experience with other languages that's confusing you.
    • toomanyrichies 4 days ago |
      > It's not Python that's confusing, it's your previous experience with other languages that's confusing you.

      "There are no children here at the 4H club either! Am I so out of touch?

      No... it's the children who are wrong."

      -Principal Skinner, "The Simpsons"

      EDIT to clarify- I'm just being silly, not suggesting anyone is right or wrong here.

    • Terr_ 4 days ago |
      Yeah, the behavior is arguably much less confusing than the alternative of:

          5==5==5   # All three the same
          (5==5)==5
          true==5
          false
      
      Or

          1==2==false # All three different, in a troublesome way
          (1==2)==false
          false==false
          true
      • zdragnar 4 days ago |
        I dunno, I'd expect the right hand expression (2 == false) to be resolved first, then compared to 1.

        Compare this with

            a = b = c = 5
        
        You evaluate the innermost (i.e. the tail) expression first, and work your way out to the head. As a sexpr it is a little more obvious that way:

            (= a (= b (= c 5)))
        
        An argument could easily be made that python is making up special rules for the equality operator by treating the duplication of the operator as merging the expressions into one.

        Instead of what you would expect, per the rules of literally every other expression, 5 == 5 == 5:

            (== 5 (== 5 5))
        
        It gets rewritten as

            (== 5 5 5)
        
        Which one is "unexpected" is really a matter of perspective: are you reading with the rules of English or the rules of your programming language as your context?

        I do concede one caveat to this argument: mathematical operators tend to change operator precedence around to avoid making mathematical mistakes. I am mildly of the opinion that this itself was a mistake. Most calculators don't do it, so it's not like anyone would be* that* thrown off by it.

        • furyofantares 4 days ago |
          > An argument could easily be made that python is making up special rules for the equality operator by treating the duplication of the operator as merging the expressions into one.

          I guess the argument could be made but it would be wrong. All the comparison operators can be chained in python. a < b < c, for example, or even a == b <= c < d.

        • pansa2 4 days ago |
          > You evaluate the innermost (i.e. the tail) expression first, and work your way out to the head. As a sexpr it is a little more obvious that way: `(= a (= b (= c 5)))`

          That's not true in Python though.

              a = b = c = <expression>
          
          is equivalent to:

              temp = <expression>; a = temp; b = temp; c = temp
          
          I don't know why that order of evaluation was chosen.
    • ball_of_lint 4 days ago |
      Most programming languages ought not to be optimized for a non-programmer to read, but rather for someone who writes code to read.

      There's a lot of options for a language to deal with a statement like this. It could be a syntax error, a compile or lint warning, it could work by doing order of operations and comparing the boolean from one compare with the third element, or it could work in the way you described.

      I'd prefer languages that I work with to chose earlier options from that list. In most languages this sort of statement is usually a bug, and deserves explicit parenthesis to clarify the order of operations. I really don't want to have to pull out an operator precedence chart in order to read your code, much less have to look up some esoterica about this specific language.

      • throwaway313373 4 days ago |
        "someone who writes code" is very vague. For someone who writes code primarily in Python this behavior is less surprising than the rest that you described.
        • ball_of_lint 3 days ago |
          Intentionally so.

          I've worked primarily in Python for the last two years and I'd still have to look at a reference to be certain of what exactly this code does. And would probably rewrite it to the expanded, parenthesized form unless the company linter insisted.

      • atoav 4 days ago |
        I'd argue that many programming languages are not optimized for "people who read code" but they are optimized for programs who read code (compilers, interpreters) and programmers can stockholm-syndrome themselves into believing that it is targeted at them.
        • James_K 3 days ago |
          Code optimised for an interpreter is often also optimised for the programmer, whose primary job is interpreting code. What makes natural language intuitive is that it doesn't have to be precise. You can assume language does what it is intended to do. A programmer, by contrast, must know exactly what the program does. You cannot assume it does what you want it to do because the computer doesn't know what you want it to do. A language cannot be made less precise by the addition of new rules; it is only made more complicated as there is more to remember. In this example, the person writing the ternary expression had to learn that it exists. If it didn't exist, there would have been less learning to do. Perl is the limit of this process – a language with many rules to appear natural and human-like that it's almost impossible to actually read.

          Each rule of a language is a cognitive burden. It can only justify itself if the thing it replaces is a greater burden.

      • the5avage 4 days ago |
        > I really don't want to have to pull out an operator precedence chart in order to read your code

        Hard disagree here. I write code for people who can read the language. This includes operator precedence.

        • shkkmo 3 days ago |
          The more complex an expression grows, the less well it works to rely on operator precedence to indicate structure to the reader.

          Additionally, I think assuming the reader is aware of every. nuance of the language is an extremely bad idea unless you are and will always be the only developer. If you are doing anything weird or tricky or rare, I'd highly recommend linking the documentation or providing an explanation.

        • nmeofthestate 3 days ago |
          >I write code for people who can read the language

          Programming languages often have syntax that's acknowledged as a source of confusion and bugs and better avoided. The line is not hard and fast, but I write C++ and there's "C++", and then there's "the C++ subset that you should use" (I probably couldn't write C++ code without tools slapping me for using the wrong parts). Operator precedence is debatable but our tools force the use of parentheses to disambiguate.

          • stavros 3 days ago |
            This is true, and, in this case, "confusion avoided" and "what Python does" coincide. The "double equals doing the right thing" is only confusing if you're both unfamiliar with Python and familiar with language design, which is a very small set of people.

            People unfamiliar with programming will assume that "if a == b == c" is only true if all three things are the same, and people familiar with Python will know that that is, indeed, what it means.

      • dagw 3 days ago |
        Most programming languages ought not to be optimized for a non-programmer to read

        Python 'won' mostly because non-programmers could look at it, more or less understand what was going on, and feel that this was something they probably could learn.

    • alkonaut 4 days ago |
      What does A == B == C even mean? I mean I know what mathematically A=B=C means. That A, B and C are all equivalent.

      But then is the mathematical '=' really a binary operator that maps two numerical inputs to a boolean output? It feels then as an abuse of notation if (A=B)=C doesn't allow A=B to change type?

      Because I don't really have much use for a symbol that is some times doing a binary mapping from numbers to booleans and some times becomes some sort of ternary operator which maps 3 inputs to one boolean.

      • joveian 3 days ago |
        Maybe consider chained comparison operators early textual replacement along the lines of the C preprocessor, although the exact textual replacement would involve temporary variables to avoid multiple side effects and be more complicated than just "(a) == (b) and (b) == (c)". (a==b)==c does not expand, only the version without parentheses expands, so you can still do the boolean comparison if you want.
    • TrainedMonkey 3 days ago |
      I have some experience in computer language design. The issue here is that `a==b==c` expression is magical - that is it does not follow from extending comparison binary operator. Specifically, `==` is a binary operator that that compares an expression before and after and returns a boolean. In this case, A==B==C is a trinary comparison operator. This is normally ok, except it's rare and the symbol it is using is overloaded with binary comparison operator, so the people will be confused.

      This actually gets weirder - in python you can make an arbitrary long comparison operator - it's called comparison chaining - https://www.programiz.com/online-compiler/6uyqb52IVH8if . It works with a lot of operators - https://www.geeksforgeeks.org/chaining-comparison-operators-...

      Once you know how it works and are used to it, I think it makes the code easier to parse... but there are heavy downsides. For example, it's not clear how short circuiting works. I've used python a bunch and logically I expect ```side_effect3()``` to not be evaluated if results of 1 and 2 are not equal: ```side_effect1() == side_effect2() == side_effect3()```. However, I do not know that for sure, while in other languages I would be able to reason about this from basic principles.

      • Ukv 3 days ago |
        > the symbol it is using is overloaded with binary comparison operator, so the people will be confused

        I think most people would expect expressions like `5 < x < 10` to work as they do in math, without necessarily thinking about it in terms of being an overloaded binary operator. The result in other languages that `5 < 12 < 10` = `true < 10` = `true` is more surprising, just that we've (perhaps by being bitten by it early on) gotten used to it.

        • redditor98654 3 days ago |
          Yeah, but should that math equivalence hold for programming though? Programming is different. x=x+1 is perfectly legal in programming but does not make sense in algebra math and could confuse mathematicians.
          • lordnacho 3 days ago |
            Maybe = should actually be := which it is in some languages?

            x = x + 1 sounds wrong if you are in math mode

            x := x + 1 is uncommon in math and you can take it to mean "set x to whatever is currently x, plus one"

            But it's also true that you need to be able to accept certain conventions when changing fields.

          • Ukv 3 days ago |
            > should that math equivalence hold for programming though?

            It's not a hard rule that overrides all other considerations, but I do think Python's choice to follow math is the right decision here.

            I'd claim if you teach someone `<` then show them `5 < x < 10` for the first time, they're far more likely to go with the math interpretation than the C one. That is, beyond the fact that someone's familiarity with math reinforces this intepretation, the reason for math using this interpretation in the first place is because it aligns with intuition.

            It's also just pretty useful. It's common to want to check if a number is between some bounds, like `0 <= i < len`, or that multiple things are equal. In cases where you really do want the C behavior, I'd say you should already write that as `(x == y) == z` for clarity anyway, regardless of whether the language lacks chaining and thus lets you omit the parentheses.

      • sampo 3 days ago |
        • andreasmetsala 3 days ago |
          Is “let me check the docs” an appropriate thing to say in an interview setting?
          • natebc 3 days ago |
            yes.
          • acdha 3 days ago |
            It’s what you’d do on the job, right? A place which dings you for checking your work is broken.

            I’d expect a raised eyebrow if it was some very basic question about something you’ve claimed to be an expert in but given how many, many bugs over the years stem back to confusion about order of evaluation I would consider it a minor plus if someone said “I think I know but I want be certain”, and a major one if they paired that with mention of defensive coding practices like adding tests covering cases where it’d matter and structuring the code so there are no side effects hidden in the test (e.g. the code as written is fine but if it was f1() == f2() == f3() I’d probably write it as a clearer multi-line if block when there are side effects to those calls to make obvious when I’m intentionally not doing them in every case).

          • bityard 3 days ago |
            It absolutely is.
          • ljm 3 days ago |
            I'd prefer a candidate to check the docs or look something up if they were unsure, because that would also provide useful information to me as an interviewer.

            Although I'd also want that benefit of the doubt for myself. I'm quite familiar with how Ruby handles collections, for example, but if I tried to use `slices.Collect` in Go the same way as `Enumerable#collect` in Ruby I'd end up stuck and would need clarification.

          • dsr_ 3 days ago |
            Yes.

            Extra points if you are familiar enough with the documentation to find the answer quickly.

        • renegade-otter 3 days ago |
          It's a completely useless question - it's language trivia. It's like asking "what happens if you do X in database Y version Z and up". Who cares? It's something you figure out when you get there. There are tons of examples of something like this where it's language-dependent, so don't even bother memorizing this stuff.

          I once passed an interview where it was all just Spring documentation questions. I had never built a Spring app in my life, I just "read the docs" five times.

      • phkahler 3 days ago |
        >> but there are heavy downsides. For example, it's not clear how short circuiting works.

        Opinion: Code that depends on side effects like that in a conditional is BAD. It is not an optimization, it's an obfuscation.

      • ashu1461 2 days ago |
        Agree, also by reasoning from basic principles adding extra brackets ( ) should not change the output result - at least this is what our brain is programmed to believe, but in the case of chained operations it will.

        Example

        (a==b)==c would be different from a==b==c

    • tmtvl 3 days ago |
      Yet another way in which Lisp is vastly superior to any and all blub languages:

        (= 2
           (+ 1 1)
           (sqrt 4))
        ; => t
      
        (< most-negative-fixnum 0 most-positive-fixnum)
        ; => t
      • Aachen 3 days ago |
        I have no idea what this does or if you are joking. Could use some explanation
        • gus_massa 3 days ago |
          In Lisp, you put the "operator" first, so instead of

            2 + 3 + 4
          
          you write

            (+ 2 3 4)
          
          
          This is nice for associative operations like + or *, very very very slightly confusing for - and /

          ---

          You use the same style for comparisons, so instead of

            2 == 3 == 4
          
          you write

            (== 2 3 4)
          
          
          To support the fist "infix" syntax, you need some magic in the == operator. But the second "prefix" syntax is totally natural and you need no magic in the parser or the operator.
          • tmtvl 3 days ago |
            > very very very slightly confusing for - and /

            It's fine if you DNF it:

              (- a b c) => (+ a (- b) (- c))
              (/ a b c) => (* a (/ 1 b) (/ 1 c))
          • Aachen 3 days ago |
            I knew that Lisp does this operator first thing, it's everything around this that I'm not familiar with. What does ; do? Is the => an arrow or greater than or equal to? What is t? Do I guess correctly that most-negative-fixnum is like INT_MIN?
            • tmtvl 3 days ago |
              The semicolon is Lisp syntax for comments. T is the way you write true in Lisp. Most-negative-fixnum is the most negative number Lisp can represent without promotion to bignum (so it can be int_min if int is roughly equivalent to size_t).
        • ahoka 3 days ago |
          In the Lisp family of languages these comparisons are not implemented as operators, but functions.

          The functions behave like:

          = all the same

          /= all different

          < monotonically increasing

          > monotonically decreasing

          <= monotonically nondecreasing

          >= monotonically nonincreasing

          Also * is product and + is sum.

      • ahoka 3 days ago |
        So Python is a Lisp?
    • quietbritishjim 3 days ago |
      > If you know nothing about Python or coding, and you see a=b=c, you'd think that's true when all three a,b,c are the same.

      Sure, that's true if you literally know nothing about coding. But that is not a very common audience for reading code. You only need to spend about 10 minutes coding to realise that the compiler follows fixed rules rather than making an LLM-like guess as to the meaning. If you get that far then most people (admittedly after a bit more 10 minutes) go on to realise that the only way to know what code does is carefully pick it apart step by step, rather than glance at it and guess yourself.

      I love Python dearly, but this rule was a misstep on my opinion.

    • ninetyninenine 3 days ago |
      The problem isn’t meaning or intent its inconsistency of operator behavior.

      1 + 1 + 1 has different operator behavior then 1 == 1 == 1. The operations here are not consistent and it’s not clear what happens if I overload the operators.

      On the surface level python looks more beautiful. But mathematically speaking python is actually more ugly and more inconsistent with weird rules to make things look a certain way.

    • eacapeisfutuile 3 days ago |
      If you know nothing about Python or coding it is not really relevant as the code is probably read and written more by those who know coding and/or Python?
  • Animats 4 days ago |
    I remember when that went into Python. It seemed too cute. There was a lot of that around the Python 3.4, 3.5 era.

    The case where all items are the same type is reasonable, but if implicit type conversions are invoked, it gets really complicated. Whatever the types are, Python will probably do something. Just not necessarily what you want.

    I could see having this if there was a compile-time constraint that all variables be the same type. That would disallow the bad cases.

    • whatshisface 4 days ago |
      In defense of Python here, a==b==c -> (a ==_string b) ==_bool c is an extremely confusing way to write (predicate) nxor c. A principle here could be "operators that look the same shouldn't do different things when they're written close together."
    • devanl 4 days ago |
      This feels a bit like a case of a "Python from 10 years ago in my head" vs "Python from 10 years ago in reality" meme.

      Chained comparisons have been in Python since I started using it at 2.1. It looks to me like they've been there since at least 1.4:

      https://docs.python.org/release/1.4/tut/node40.html#SECTION0...

      • Animats 4 days ago |
        Ah. I'm thinking of [1] from 2016, when there was a plan to add short-cut evaluation to short-cut comparisons. That avoids evaluating all the terms when not necessary. But that was deferred.

        [1] https://peps.python.org/pep-0535/

        • DonHopkins 4 days ago |
          That's so lazy!
    • selcuka 4 days ago |
      > Whatever the types are, Python will probably do something. Just not necessarily what you want.

      Are you sure you are not confusing it with PHP? Python is not statically typed, but it is strongly typed. There is no implicit type conversion unless it's safe to do so (such as between a float and an int).

      For example, print(1 > "foo") will raise a TypeError, and print("1" == 1) will print False.

      • Animats 4 days ago |
        In Python, "==" calls "__eq__", a class function. The left argument to "==" determines which class is involved. The right argument is just passed into the selected class member function. There's an asymmetry there. Operators are not necessarily commutative.

        This can lead to some strange operator semantics in mixed-mode expressions. Whether chained expressions left-associate or right-associate matters.

        numpy.array operations do a lot of implicit conversions. You can use Python arrays on many operations that expect a numpy.array. Mixing them works. Mostly.

            python3
            Python 3.10.12 (main, Sep 11 2024, 15:47:36) [GCC 11.4.0] on linux
            Type "help", "copyright", "credits" or "license" for more information.
            >>> import numpy
            >>> a1 = numpy.array([1,2,3])
        
            >>> a2 = [1,2,3]
            >>> a1 == a2
            array([ True,  True,  True])
            >>> a2 == a1
            array([ True,  True,  True])
            >>> a1 == a2 == a1
            Traceback (most recent call last):
              File "<stdin>", line 1, in <module>
              ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
            >>> a2 == a2 == a2
            True
            >>> a1 == a1 == a1
            Traceback (most recent call last):
              File "<stdin>", line 1, in <module>
              ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
  • alkh 4 days ago |
    In my mind,I just automatically translate a EXPRESSION1 b EXPRESSION2 c as (a EXPRESSION1 b) and (b EXPRESSION2 c), so there's no ambiguity. But I agree, it can be very confusing,so I tend to write code that is easy to read without being a master. For example, what would have guessed this evaluates to:

    False is False is False. If you thought, True, you were right :)

    I would recommend to take a look at one of my favourite repos for more[1].

    [1]https://github.com/satwikkansal/wtfpython

  • WalterBright 4 days ago |
    D solved the problem with what happens with (a == b == c) in an unusual way. It gives an error message. Both the C way and the Python way are considered wrong. You're going to have to add ( ) to clarify.
    • throwaway313373 4 days ago |
      Rust also gives a custom error message [0] that explicitly explains that "comparison operators cannot be chained" and shows you how to rewrite the expression using `&&`.

      Which makes me wonder whether they came up with this idea themselves or if they borrowed it from D.

      In any case, I think that this is the only reasonable solution for new languages. Because if you go with C way it will be surprising for people who expect Python way and vice versa. So, making this syntax illegal is the only way to uphold the principle of least astonishment [1].

      [0] https://play.rust-lang.org/?version=stable&mode=debug&editio...

      [1] https://en.wikipedia.org/wiki/Principle_of_least_astonishmen...

      • WalterBright 4 days ago |
        I gave several presentations that included this back in the 2010-2012 timeframe, and it had already been in the language for maybe a decade.

        When I implemented it, I had seen many knock-down drag-out debates about which was the best way to deal with it, and none of them mentioned simply making it illegal.

        It was another one of those features that were based on my experience designing aircraft systems.

        Another one adopted by pretty much all languages since D is the _ in numeric literals (although C++ used a backtick). It was just something that was obviously right once you saw it. But I didn't originate it, I cribbed it from Ada. I've always had a soft spot for Ada.

    • _niki_s_ 3 days ago |
      you can't just add () to clarify, you have to duplicate `b` too and that is not good transformation if `b` is function call
  • anonymous3411 4 days ago |
    Is nobody going to point out that the code will return that there’s a winner even when all 3 cells are empty? (Even with the fancy python chaining?)
  • andrewstuart 4 days ago |
    >> I have a very basic question which I usually ask in a interview which is to implement a tic tac toe game. I like this because the logic is straightforward and it helps to judge things like code quality / speed / conciseness etc.

    "I like this because the logic is straightforward and it helps to judge things like code quality / speed / conciseness etc."

    No, it doesn't.

    Everyone who comes up with their own pet way of evaluating and interviewing thinks - nay has the unshakable belief - that their way of evaluating developers is 100% spot on. However it's always something they just made up, justify with plain old words and never science.

    • imiric 4 days ago |
      How did you get "unshakable belief" from that paragraph?

      Interviewing is inherently messy, imprecise and unscientific. The process involves a lot of guesswork and feeling, rather than accurate measurements of any kind. It creates a fictional work environment that is often stressful for candidates, so any signal you may get out if it is also inaccurate.

      It's natural for interviewers to have a preference for certain questions, topics or ways of conducting an interview. You're free to disagree, of course, but claiming that your way is superior is silly.

  • teekert 4 days ago |
    I'd be more confused about the curly brackets, I only know python and have never seen them used like that? My brain goes like: Here comes a set or dict.

    Also, why not do `all(cell[0][0],cell[1][1]),cell[2][2])` if you want to have True when all 3 are True?

    Perhaps I'm missing something, I don't exactly consider myself a 1337 coder.

    • pansa2 3 days ago |
      > I'd be more confused about the curly brackets, I only know python and have never seen them used like that?

      Yeah, that’s C/C++/JavaScript/… syntax, it’s not valid Python.

      > why not do `all(cell[0][0],cell[1][1]),cell[2][2])` if you want to have True when all 3 are True?

      We want to test whether all three are the same, not whether they’re all True.

  • joeevans1000 4 days ago |
    Did he get the job?
    • the5avage 4 days ago |
      No, because when all cells are empty he returns "Winner".

      The interviewer also lost his job, since he didn't spot it nor does he know basic python syntax.

      • blitzar 3 days ago |
        The interviewer got a promotion, since he didn't spot it nor does he know basic python syntax.
  • laurentlb 4 days ago |
    Python chained operators can be confusing, especially as it allows you to write things like: — x < y > z — a in b not in c

    WalterBright mentioned that D will give you an error. When designing Starlark (a derivative of Python), I also decided to give an error for this, by making the comparison operators non associative.

    https://github.com/bazelbuild/starlark/blob/master/design.md...

    I agree this Python feature can look cute, but I've found it's rarely useful and can easily be avoided.

    • jeroenhd 3 days ago |
      I find these expressions a lot more readable for bound checks (like `if 0 <= n < len(something):`) compared to the imperative `if (n >= 0 && n < something.length)`. This was especially true when I used it for homework, where constraints described in mathematical form were a lot more common than when dealing with real life software.

      The way it works in Python allows for some hilariously unreadable code, but the concept itself is good. I think it just needs more constraints to maintain readability, such as not allowing flipping the comparison sign (like in x<y>z).

      Banning these chained comparison operators is not necessarily a bad idea as comparison operators can easily cause confusion in that manner, but the reason they cause confusion is that many programming languages use mathematical symbols differently than actual math. A=B=C is perfectly understandable and more readable than A=B ∧ B=C. Restraining ourselves to "operand operator operand" as the only infix expression model made sense decades ago when computers had storage counted in kilobits. Today, we can let go of the limitations of yore and use mathematical expressions in a way that plain sense.

      • Izkata 3 days ago |
        If you write the bounds check in the same order it's really not that bad: (0 <= n && n < something.length)
  • pzo 3 days ago |
    Worth to keep in mind that python first appeared in 1991 and predates even Java, JavaScript, PHP, Ruby
    • otherme123 3 days ago |
      And the nerve to put Javascript as the example about how equality should work, a language known for:

        0 == '' evaluates to True
        0 == '0' evaluates to True
        false == 'false' evaluates to False
        false == '0' evaluates to True
        ' \t\r\n ' == 0 evaluates to True
      
      and the === operator you need to overcome the above. I don't have anything against JS and I understand why it is done that way, but if some language has weird and confusing comparison operators is JS.
      • vdvsvwvwvwvwv 3 days ago |
        It is merely syntatically confusing.

        Make == be ~~ or .fuzzyCompare()

        And === be ==

        And you are fixed.

        • otherme123 3 days ago |
          Paraphrasing: "Well done, Javascript… for finding yet another way to confuse us all."

          I don't know many programming languages, but of the few I know any of them has a === because == is so confusing that you don't know exactly if (or when) it would bite you. You can't attack any language for their comparison operators from the Javascript camp.

          It that blog post removed the sentence "And this is how it would definitely happen if the code was written in javascript" they would be fine. But you actually don't know what would definitely happen in Javascript with the line in question "cell[0][0] == cell[1][1] == cell[2][2]", unless you know 100% what is in these cells. For example:

          cell[0][0] is "0", cell[1][1] is 0, cell[2][2] is true

          and "cell[0][0] == cell[1][1] == cell[2][2]" evaluates to True.

          • Izkata 3 days ago |
            > cell[0][0] is "0", cell[1][1] is 0, cell[2][2] is true

            If those values came from <input> elements, the second and third examples aren't possible without having manually converted it beforehand. Input values are always strings, even a checkbox. That's where javascript's conversion rules and lax equality came from, an attempt to have sane defaults for simple uses: If a string is being compared to a number, the string is likely from an input and the number was typed into the code, so convert the string to a number before comparison.

      • billpg 3 days ago |
        "Test two values for equality, but this time we mean it."
      • Izkata 3 days ago |
        The basic rule is "if there's a number on either side, convert the other side to a number before doing the comparison". I think false == '0' is the only one that fails that test, unless you think of false as a special case of 0 which makes false == 'false' the one that fails with that rule.
  • dzonga 3 days ago |
    python was pleasant in the python 2 days. Now there's so many confusing ways to do one simple thing.

    and one thing Golang has made inroads is there's only one way to do something.

    and ruby is pleasurable because the interface is consistent i.e everything is an object.

    • throwaway313373 3 days ago |
      What does the feature discussed in TFA (chained comparisons) have to do with Python 2 vs Python now.

      As another commenter pointed out [0] this feature existed since 1.4 [1].

      Also, I don't understand why so many people seem to be so confused/surprised by it. I can't be 100% sure because it was a long time ago, but I think that a lot of tutorials/introductory articles mention it. Like, "Hey, did you know that Python has this cool syntaxic sugar for this thing? Fascinating!". I think that I learned about chained comparisons long before I wrote my first line of Python.

      [0] https://news.ycombinator.com/item?id=42038451

      [1] https://docs.python.org/release/1.4/tut/node40.html#SECTION0...

      • carlmr 3 days ago |
        I wrote Python for years before seeing it somewhere, going huh, and then I thought it's quite neat.

        I still don't think it's that confusing. It does what you think it should if you're reading pseudocode, which is after all kind of Python's MO.

  • vdvsvwvwvwvwv 3 days ago |
    Unit tests should be part of the interview too. As should googling the behaviour live. Missed opportunities to go beyond the bland exercise to see what it is like pairing up with this person.
  • some1else 3 days ago |
    Regardless of the naive algorithm, wouldn't this also match empty cells?
  • froh 3 days ago |
    wouldn't it be lovely if someone, somehow pointed out that it should be

       if a == b == c != "-": return Winner
    
    ?

    so three empty fields in a row don't "win" the game?

  • VoodooJuJu 3 days ago |
    >Well done, Python… for finding yet another way to confuse us all.

    Would have liked to see some humility from the author, especially since he's an interviewer, but instead he deflects the fault onto Python as being confusing, rather than attributing the fault to himself and his own lack of understanding.

    Unfortunately, this kind of blame game is par for the course with enginerds. I say this all the time: engineers really should do a sales or customer service job before getting into engineering. This will help you build empathy, which will build your social skills and kindle some humility within you. These traits will give you an edge over other nerds and take you further in your career.

  • librasteve 3 days ago |
    Raku (https://raku.org) supports the same design as Python3 ...

      0 < 5 < 100;     #True
      10 == 10 == 10;  #True
    
    The Chaining Binary Precedence is specified for this https://docs.raku.org/language/operators#Chaining_binary_pre...

    That means you can make your own chaining comparison ops (or overload the current ones) with something like:

      multi infix:<~=>(Rat $l, Rat $r) { ($l-$r) < 0.1 ?? True !! False }
            is equivalent('<');
    
    Much of Raku such as the default use of Rationals (Rat) is intended to make the language more approachable for non CS experts, so yes:

      0.1 + 0.2 = 0.3 # True
  • ubermonkey 3 days ago |
    I don't code for a living anymore, but I think if I were writing Python I would probably AVOID using that idiom because of how jarring it could be to people who are unfamiliar with it, mostly due to how strange it is coming from other languages.

    There doesn't seem to be a great upside to using it, and adding confusion to the codebase for whatever poor bum has to work on it later is bad karma.

  • andrelaszlo 3 days ago |
    Fascinating, the task was supposed to be straightforward and a way to judge code quality etc. Yet, when the candidate solved it in a simple way, they were told they had a bug that they didn't have. This is okay of course, coding is hard. It could have been an interesting opportunity for discussion, I guess.

    What's interesting to me is the conclusion that it's somehow Python's fault. I wonder if that attitude would work if it came from the candidate.

    I think we should be more careful with tests like this. They need to be done with more humility, so it's great that the post was written!

  • trustinmenowpls 3 days ago |
    Yea, after spending a lot of time coding in python and then switching to js, this definitely caused some heads catching moments.