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 <leebr...@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@python.org > https://mail.python.org/mailman/listinfo/python-ideas > Code of Conduct: http://python.org/psf/codeofconduct/ >
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/