[Python-ideas] Proposal for an inplace else (?=) operator

Robert Vanden Eynde robertve92 at gmail.com
Sat Sep 22 08:35:25 EDT 2018


That's an idea that could be added to my thread "dialects of python" in
order to compile some fancy or specific syntax to regular python.

Le sam. 22 sept. 2018 à 13:53, Lee Braiden <leebraid at gmail.com> a écrit :

> Could I get some feedback on this?  I'd like to know if anyone thinks it
> might make it through the pep process before spending too much (more) time
> on it.  That said, it seems valuable to me, and I'm willing to put in the
> time, of course, IF it has a chance.
>
> ---------------------------
>
> Problem:
>
>     Due to (biggest python WTF) (Problem 1), which prevents actual default
> argument values being set in a function signature, many
>     functions look like:
>
>         > def teleport(from, to, passenger, hitchhiker=None,
> food_accessory=None, comfort_accessory=None):
>         >     if hitchhiker is None:
>         >         hitchhiker = Fly()
>         >
>         >     if food_accessory is None:
>         >         food_accessory = Cheeseburger()
>         >
>         >     if comfort_accessory is None:
>         >         comfort_accessory = Towel()
>         >
>         >     ...
>
>     This None checking and setting is unwieldy (Problem 2) boilerplate,
> which is responsible for many extra lines of code in python
>     (Problem 3), and tends to distract from the real code (Problem 4) in a
> function.
>
>     To reduce boilerplate, a ternary or binary expression can be used:
>
>         > def teleport(from, to, passenger, hitchhiker=None,
> accessories=[]):
>         >     hitchhiker = hitchhiker if hitchhiker or Fly()
>     # Existing Solution A
>
>         > def teleport(from, to, passenger, hitchhiker=None,
> accessories=[]):
>         >    hitchhiker = hitchhiker or Fly()
>     # Existing Solution B
>
>     These help, but are still quite repetitive:
>
>     * Existing Solution A is often avoided simply because many Pythonistas
> dislike tenery expressions (perhaps due to
>       readability or hidden code branch concerns), and can quickly become
> unwieldy when the new value (Fly()) is a more
>       complex expression, such as a list comprehension:
>
>         > def teleport(from, to, passenger, hitchhiker=None,
> accessories=[]):
>         >    hitchhiker = hitchhiker if hitchhiker or filter(lambda h: not
> h.already_hitching(), available_hitchhikers)[0]
>
>     * Existing Solution B is less unwieldy (solving Problem 2), yet still
> suffers from repetition (Problems 2, 3, and 4).
>
>     In a similar scenario, when we want to populate an empty list (say,
> accesories), we could write:
>
>         > accessories |= [Cheeseburger(), Towel()]
>      # Almost-Solution C
>
>     However, this is not actually a solution, because:
>
>         * The inplace-or (|=) operator is not provided for None in python:
>
>           > food_accessor = None
>           > food_accessory |= Cheeseburger()
>
>           Traceback (most recent call last):
>           File "<stdin>", line 1, in <module>
>           TypeError: unsupported operand type(s) for |=: 'NoneType' and
> 'Cheeseburger'
>
>           This could be added, but would not solve the issue, because:
>
>         * If an non-default (non-None) argument value WERE provided, we be
> would modifying
>           the argument unintentionally:
>
>             > class Larry:
>             >     def __ior__(self, other):
>             >         print("{} modified".format(self))
>             >
>             > teleport(..., hitchhiker=Larry(), ...)
>             <__main__.Larry object at 0x7f1ad9828be0> modified
>
>     And so Problems 1,2,3, and 4 are compounded.
>
> Proposal:
>
>     The addition of a ?= operator could provide an elegant solution:
>
>         > def teleport(from, to, hitchiker=None, food_accessory=None,
> comfort_accessory=None):
>         >     hitchhiker ?= Fly()
>         >     food_accessory ?= Cheeseburger()
>         >     comfort_accessory ?= Towel()
>
>     In these examples,
>
>         > a = None
>         > a ?= b
>
>         > c = [1, 2]
>         > c ?= d
>
>     Would be equivalent to (assuming ?= was called __ielse__):
>
>         > class ExtendedNone(NoneType)
>         >     def __ielse__(self, other):
>         >         return other
>         >
>         > class ielse_list(list):
>         >     def __ielse__(self, other):
>         >         return self
>         >
>         > None = ExtendedNone()
>         >
>         > a = None
>         > a = a.__ielse__(b)
>         >
>         > c = iff_list([1, 2])
>         > c = a.__ielse__(d)
>
>     Although explicitly provided for list above, this ielse operator could
> be defined
>     (again, as `return other` for NoneType only, but defaulted to `return
> self` for
>     all other values of `a`, requiring very little implementation effort
> or intrusion
>     into other types.
>
> Possible interaction with typing
>
>     It may be also possible to define a ? suffix on function arguments, so
> that:
>
>         > def func(a?):
>         >     a ?= [1,2]
>
>      greatly shorting the current verbose form:
>
>          > from typing import Optional
>          >
>          > def func(a = None : Optional[Any])):
>          >     a = [1,2] if a is None else a
>
>     and equivalent to:
>
>         > from typing import Optional
>         >
>         > def func(a: Optional[Any]):
>         >     a = a.__ielse__([1,2])
>
> Possible alternatives:
>
>     * The __ielse__ name is highly debatable.  Alternatives such as
> __iif__ (inplace if), __imaybe__, __isomeor__ (borrowing from Rusts's
> Some/None terminology, and reflecting the intended use as in relation to
> None types, DB nulls, and similar void-like values).
>
>     * The ? function argument suffix is not necessary to implement the
> core ?= proposal.
>
>     * If the ? function argument suffix  is implemented, implementation
> via typing.Optional is not necessary; it could also be simply implemented
> so that:
>
>         > def f(a?):
>         >     ...
>
>     is equivalent to:
>
>         > def f(a=None):
>         >     ...
>
>
> ---------------------------
>
> Feedback would be much appreciated.
>
> --
> Lee
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180922/ebf281fd/attachment-0001.html>


More information about the Python-ideas mailing list