_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: https://mail.python.org/mailman/options/python-dev/guido%40python.org
_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev
We should probably set the state of both this and the related circuit
breaking protocol PEPs to Deferred so folks know neither of us is
actually working on them.
While I still think there's merit to the idea of making it easier to
write concise data cleanup pipelines in Python, I find the argument
"The currently proposed spelling doesn't even come close to reading
like executable pseudo code" to be a compelling one.
I think a big part of the problem is that these kinds of data cleanup
operations don't even have a good *vocabulary* around them yet, so
nobody actually knows how to write them as pseudo code in the first
place - we only know how to express them in particular programming
languages.
Trying to come up with pseudo code for the example cases Raymond mentioned:
timeout if defined, else local_timeout if defined, else global_timeout
price * (requested_quantity if defined, else default_quantity)
name if not defined, else name.strip()[4:].upper()
user if not defined, else name.first_name.upper()
And that's not actually that different to their current spellings in Python:
timeout if timeout is not None else local_timeout if local_timeout
is not None, else global_timeout
price * (requested_quantity if requested_quantity is not None else
default_quantity)
name if name is None else name.strip()[4:].upper()
user if user is None else name.first_name.upper()
One key aspect that Python does miss relative to the pseudocode
versions is that we don't actually have a term for "expr is not None".
"def" is used specifically for functions, so "defined" isn't reference
right. References to "None" are bound like anything else, so "bound"
isn't right. "exists" probably comes closest (hence the title of the
withdrawn PEP 531).
That said, if we did decide to allow "def" in a conditional expression
to mean "defined" in the "lhs is not None" sense, it would look like:
timeout if def else local_timeout if def else global_timeout
price * (requested_quantity if def else default_quantity)
name if not def else name.strip()[4:].upper()
user if not def else user.first_name.upper()
Cheers,
Nick.
P.S. Compared to this, our last symbolic feature addition (matrix
multiplication), was a relatively straightforward transcription of "⋅"
to "@", just as regular multiplication is a transcription of "×" to
"*".
--
Nick Coghlan | ncog...@gmail.com | Brisbane, Australia
New syntax often look unusual. "lambda" and "yield" also didn't "look
like Python".
But there are other considerations.
1. Languages that has the ?? and ?. operators usually have a single
special (or at least a one obvious) value that is served for signaling
"there-is-no-a-value". The None in Python is not so special. It can be
used as a common object, and other ways can be used for denoting an
"absent" value. The need of None-specific operators in Python is lower.
2. Python already have other ways for handling "absent" values: the
short-circuit "or" and "and" operators which return the one of
arguments, getattr() with the default value, the hack with default class
attributes, exception handling. The need of the proposed operators in
Python is lower.
3. These languages usually have borrowed the syntax of the ternary
operator from C: "... ? ... : ...". Thus the syntax with "?" looks more
natural in them. But in Python it looks less natural.
I'm -1 for accepting this syntax in 3.7. In future all can be changed.
I like much of the thinking in Random's approach. But I still think None isn't quite special enough to warrant it's own syntax.However, his '(or None: name.strip()[4:].upper())' makes me realize that what is being asked in all the '?(', '?.', '?[' syntax ideas is a kind of ternary expression. Except the ternary isn't based on whether a predicate holds, but rather on whether an exception occurs (AttributeError, KeyError, TypeError). And the fallback in the ternary is always None rather than being general.I think we could generalize this to get something both more Pythonic and more flexible. E.g.:val = name.strip()[4:].upper() except NoneThis would just be catching all errors, which is perhaps too broad. But it *would* allow a fallback other than None:val = name.strip()[4:].upper() except -1I think some syntax could be possible to only "catch" some exceptions and let others propagate. Maybe:val = name.strip()[4:].upper() except (AttributeError, KeyError): -1I don't really like throwing a colon in an expression though. Perhaps some other word or symbol could work instead. How does this read:val = name.strip()[4:].upper() except -1 in (AttributeError, KeyError)Where the 'in' clause at the end would be optional, and default to 'Exception'.I'll note that what this idea DOES NOT get us is:val = timeout ?? local_timeout ?? global_timeoutThose values that are "possibly None" don't raise exceptions, so they wouldn't apply to this syntax.
Not really related but the PEP says that arguments in Python are evaluated before the function (as a reason to reject the idea of None-aware function call) but this is not the case:
>>> import dis>>> dis.dis(lambda : f()(g()))1 0 LOAD_GLOBAL 0 (f)3 CALL_FUNCTION 0
6 LOAD_GLOBAL 1 (g)9 CALL_FUNCTION 0
12 CALL_FUNCTION 1
Of course they're evaluated prior to the function *call*, but the pep
says they're evaluated prior to the function *itself* [i.e. arg = g();
func = f(); func(arg)].
_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: https://mail.python.org/mailman/options/python-dev/dev-python%2Bgarchive-30976%40googlegroups.com
> I don’t know whether I like any of this <wink> but I think a more
> natural spelling would be:
>
> val = name.strip()[4:].upper() except (AttributeError, KeyError) as -1
>
> which could devolve into:
>
> val = name.strip()[4:].upper() except KeyError as -1
>
> or:
>
> val = name.strip()[4:].upper() except KeyError # Implicit `as None`
Of all the proposed spellings for the idea, this one feels most "normal" to
me, too (I'm -0 on the idea as a whole).
> I would *not* add any spelling for an explicit bare-except equivalent.
> You would have to write:
>
> val = name.strip()[4:].upper() except Exception as -1
Wouldn't that really need to be this instead, for a true 'except:' equivalence:
val = name.strip()[4:].upper() except BaseException as -1
Tres.
--
===================================================================
Tres Seaver +1 540-429-0999 tse...@palladion.com
Palladion Software "Excellence by Design" http://palladion.com
_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: https://mail.python.org/mailman/options/python-dev/dev-python%2Bgarchive-30976%40googlegroups.com
I think the OP may be confusing "evaluating the function" with
"calling the function".
If the function being called is determined by some computation,
that computation may be performed before its arguments are
evaluated (and is probably required to be, by the "left to
right" rule). But the arguments will always be evaluated
before the actual call happens.
--
Greg
_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: https://mail.python.org/mailman/options/python-dev/dev-python%2Bgarchive-30976%40googlegroups.com
Right, but if the function is evaluated before either of those things
happen, then it can indeed short-circuit the argument evaluation.
The OP isn't confusing anything; it's Eric who is confused. The quoted
paragraph of the PEP clearly and unambiguously claims that the sequence
is "arguments -> function -> call", meaning that something happens after
the "function" stage [i.e. a None check] cannot short-circuit the
"arguments" stage. But in fact the sequence is "function -> arguments ->
call".
On Thu, Nov 30, 2017 at 11:54:39PM -0500, Random832 wrote:
> The OP isn't confusing anything; it's Eric who is confused. The quoted
> paragraph of the PEP clearly and unambiguously claims that the sequence
> is "arguments -> function -> call", meaning that something happens after
> the "function" stage [i.e. a None check] cannot short-circuit the
> "arguments" stage. But in fact the sequence is "function -> arguments ->
> call".
I'm more confused than ever. You seem to be arguing that Python
functions CAN short-circuit their arguments and avoid evaluating them.
Is that the case?
If not, then I fail to see the difference between
"arguments -> function -> call"
"function -> arguments -> call"
In *both cases* the arguments are fully evaluated before the function is
called, and so there is nothing the function can do to delay evaluating
its arguments.
If this is merely about when the name "function" is looked up, then I
don't see why that's relevant to the PEP.
What am I missing?
You're completely missing the context of the discussion, which was the
supposed reason that a *new* function call operator, with the proposed
syntax function?(args), that would short-circuit (based on the
'function' being None) could not be implemented. The whole thing doesn't
make sense to me anyway, since a new operator could have its own
sequence different from the existing one if necessary.
I really like this one. It's way more general. I can see a use for
IndexError as well (lists don't have the dict.get() method).
Also I would prefer not to use "as" this way. In the context of an
exception, "as" already binds the exception to a variable so it's confusing.
What about:
val = name.strip()[4:].upper() except Exception: -1
_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: https://mail.python.org/mailman/options/python-dev/dev-python%2Bgarchive-30976%40googlegroups.com
That happens to be the exact syntax recommended by PEP 463 (modulo
some distinguishing parentheses).
https://www.python.org/dev/peps/pep-0463/
ChrisA