Most active commenters

    183 points sebg | 23 comments | | HN request time: 1.542s | source | bottom
    1. benob ◴[] No.43644247[source]
    TIL that in python, 1--2==3
    replies(1): >>43644397 #
    2. plus ◴[] No.43644383[source]
    For those who are curious, `...` is a placeholder value in Python called Ellipsis. I don't believe it serves any real purpose other than being a placeholder. But it is an object and it implements `__eq__`, and is considered equal to itself. So `...==...` evaluates to `True`. When you prefix a `True` with `-`, it is interpreted as a prefix negation operator and implicitly converts the `True` to a `1`, so `-(...==...)` is equal to `-1`. Then, you add another prefix `-` to turn the `-1` back into `1`.

    `--(...==...)--(...==...)` evaluates to `2` because the first block evaluates to 1, as previously mentioned, and then the next `-` is interpreted as an infix subtraction operator. The second `-(...==...)` evaluates to `-1`, so you get `1 - -1` or `2`.

    When chaining multiple together, you can leave off the initial `--`, because booleans will be implicitly converted to integers if inserted into an arithmetic expression, e.g. `True - -1` -> `1 - -1` -> `2`.

    > There should be one-- and preferably only one --obvious way to do it.

    This article is obviously completely tongue-in-cheek, but I feel the need to point out that this sentence is not meant to be a complete inversion of the Perl philosophy of TIMTOWTDI. The word "obvious" is crucial here - there can be more than one way, but ideally only one of the ways is obvious.

    replies(4): >>43644629 #>>43644877 #>>43646795 #>>43648139 #
    3. seplox ◴[] No.43644397[source]
    It's not a python thing. 1-(-2), distribute the negative.
    replies(1): >>43644519 #
    4. qsort ◴[] No.43644519{3}[source]
    In most C-like languages that would be a syntax error. E.g. in C and C++ as a rule you tokenize "greedily", "1--2" would be tokenized as "1", "unary decrement operator", "2", which is illegal because you're trying to decerment an rvalue.

    Python doesn't have "--", which allows the tokenizer to do something else.

    replies(2): >>43645088 #>>43646211 #
    5. pletnes ◴[] No.43644629[source]
    Numpy actively uses … to make slicing multidimensional arrays less verbose. There are also uses in FastAPI along the lines of «go with the default».
    6. elijahbenizzy ◴[] No.43644636[source]
    Ok do this but for JavaScript
    replies(1): >>43644806 #
    7. mariocesar ◴[] No.43644782[source]
    If you're curious, the code in ellipsis results in executing:

        print('hello, world')
    replies(1): >>43645158 #
    8. voidUpdate ◴[] No.43644806[source]
    https://en.wikipedia.org/wiki/JSFuck
    9. callamdelaney ◴[] No.43644820[source]
    I think we're really starting to over crowd pythons syntax and I'm not a fan.
    replies(2): >>43645190 #>>43648514 #
    10. abuckenheimer ◴[] No.43644877[source]
    excellent explanation, to add to this since I was curious about the composition, '%c' is an integer presentation type that tells python to format numbers as their corresponding unicode characters[1] so

    '%c' * (length_of_string_to_format) % (number, number, ..., length_of_string_to_format_numbers_later)

    is the expression being evaluated here after you collapse all of the 1s + math formatting each number in the tuple as a unicode char for each '%c' escape in the string corresponding to its place in the tuple.

    [1] https://docs.python.org/3/library/string.html#format-specifi...

    11. nyrikki ◴[] No.43645088{4}[source]
    In C, that is really because Unary minus (negation) has precedence over binary operations.

        +a - b; // equivalent to (+a) - b, NOT +(a - b)
        -c + d; // equivalent to (-c) + d, NOT -(c + d)
    
    
    https://en.cppreference.com/w/cpp/language/operator_arithmet...

        +-e; // equivalent to +(-e), the unary + is a no-op if “e” is a built-in type
         // because any possible promotion is performed during negation already
    
    The same doesn't apply to, !! Which is applied as iterated binary operations (IIRC)

    I am pretty sure the decriment operator came around well after that quirk was established.

    replies(1): >>43645741 #
    12. mturmon ◴[] No.43645158[source]
    Thank you!

    I noticed some ** and * in the thing sent to eval(), which (given that the building blocks are small integers) seemed related to prime factorizations.

    The initial %c is duplicated 21 times (3*7, if I read correctly), and then string-interpolated (%c%c%c...) against a long tuple of integers. These integers themselves are composed of products of factors combined using * and **.

    There is also one tuple "multiplication" embedded within that long tuple of integers -- (a,b)*2 = (a,b,a,b). That is for the 'l' 'l' in "hello".

    It's all very clever and amusingly mathy, with a winking allusion to the construction of natural numbers using sets. It made me Godel.

    13. noddleah ◴[] No.43645190[source]
    you're telling me you never program in python elliptically??
    14. MadVikingGod ◴[] No.43645386[source]
    This behavior can be replicated with any class that has two special methods: __neg__ that returns -1 and __sub__ that accepts ints and returns 1-other.

    For example if you make this class:

      class _:
           def __neg__(self):
               return -1
           def __sub__(self, other):
               return 1-other
    
    You get similar behavior:

      >>> --_()
      1
      >>> _()--_()
      2
    
    Fun python for everyone.
    15. seanhunter ◴[] No.43645741{5}[source]
    Peter van der Linden’s book “Expert C Programming” (which is awesome btw) says that one of them (Kernighan, Richie or maybe Ken Thompson I forget) realised early on that the c compiler had the wrong operator precedence for bit twiddling and unary and boolean operators but “at that stage we had a few thousand lines of C code and thought it would be too disruptive to change it”
    16. maxloh ◴[] No.43645744[source]
    You can do this on JavaScript too.

      alert(1)
      // equals to:
      [][(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[+!+[]]]+[+!+[]]+([]+[]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[!+[]+!+[]]])()
    
    https://jsfuck.com/
    replies(1): >>43647152 #
    17. j2kun ◴[] No.43646211{4}[source]
    Also worth noting that `1 - -2` works and produces 3 in C because the space breaks the operator.
    18. nomel ◴[] No.43646795[source]
    Expanding on this a little, I will be replacing all occurrences of 2 with two blobs fighting, with shields:

        >>> 0^((...==...)--++--(...==...))^0
        2
    19. ◴[] No.43647152[source]
    20. rmah ◴[] No.43648139[source]
    >> There should be one-- and preferably only one --obvious way to do it.

    Except for package management, of course. There, we need lots and lots of ways.

    replies(1): >>43648967 #
    21. acbart ◴[] No.43648514[source]
    Pretty sure this would have been possible in Python 2.6. The Ellipsis object has been around for a very long time.
    22. blooalien ◴[] No.43648967{3}[source]
    And apparently string formatting which should have an ever growing number of ways to handle it. :shrug: