[HN Gopher] Elliptical Python Programming
       ___________________________________________________________________
        
       Elliptical Python Programming
        
       Author : sebg
       Score  : 131 points
       Date   : 2025-04-10 12:53 UTC (10 hours ago)
        
 (HTM) web link (susam.net)
 (TXT) w3m dump (susam.net)
        
       | benob wrote:
       | TIL that in python, 1--2==3
        
         | seplox wrote:
         | It's not a python thing. 1-(-2), distribute the negative.
        
           | qsort wrote:
           | 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.
        
             | nyrikki wrote:
             | 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_arithme
             | t...                   +-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.
        
               | seanhunter wrote:
               | 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"
        
             | j2kun wrote:
             | Also worth noting that `1 - -2` works and produces 3 in C
             | because the space breaks the operator.
        
       | plus wrote:
       | 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.
        
         | pletnes wrote:
         | Numpy actively uses ... to make slicing multidimensional arrays
         | less verbose. There are also uses in FastAPI along the lines of
         | <<go with the default>>.
        
         | abuckenheimer wrote:
         | 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...
        
         | nomel wrote:
         | Expanding on this a little, I will be replacing all occurrences
         | of 2 with two blobs fighting, with shields:
         | >>> 0^((...==...)--++--(...==...))^0         2
        
         | rmah wrote:
         | >> 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.
        
       | elijahbenizzy wrote:
       | Ok do this but for JavaScript
        
         | voidUpdate wrote:
         | https://en.wikipedia.org/wiki/JSFuck
        
       | mariocesar wrote:
       | If you're curious, the code in ellipsis results in executing:
       | print('hello, world')
        
         | mturmon wrote:
         | 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.
        
       | callamdelaney wrote:
       | I think we're really starting to over crowd pythons syntax and
       | I'm not a fan.
        
         | noddleah wrote:
         | you're telling me you never program in python elliptically??
        
         | acbart wrote:
         | Pretty sure this would have been possible in Python 2.6. The
         | Ellipsis object has been around for a very long time.
        
       | MadVikingGod wrote:
       | 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.
        
       | maxloh wrote:
       | You can do this on JavaScript too.                 alert(1)
       | // equals to:       [][(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[
       | ])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+
       | !+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!
       | +[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+(
       | [][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[
       | +[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]
       | +[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!
       | +[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+!+[]]+(!!
       | []+[])[+[]]]+[])[+!+[]+[+!+[]]]+[+!+[]]+([]+[]+[][(![]+[])[+!+[]]
       | +(!![]+[])[+[]]])[+!+[]+[!+[]+!+[]]])()
       | 
       | https://jsfuck.com/
        
       ___________________________________________________________________
       (page generated 2025-04-10 23:00 UTC)