From 90aeb241dc515ce7b5eb546566cbabca4421b66e Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Sat, 11 Nov 2023 13:55:30 +0000 Subject: [PATCH 01/22] Syntactic sugar PEP draft --- peps/pep-9999.rst | 233 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 peps/pep-9999.rst diff --git a/peps/pep-9999.rst b/peps/pep-9999.rst new file mode 100644 index 00000000000..489998cd5e0 --- /dev/null +++ b/peps/pep-9999.rst @@ -0,0 +1,233 @@ +PEP: 9999 +Title: Syntactic sugar for named arguments +Author: Joshua Bambrick , Chris Angelico +Sponsor: Guido van Rossum +Discussions-To: https://discuss.python.org/t/syntactic-sugar-to-encourage-use-of-named-arguments/36217 +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 28-Oct-2023 +Post-History: 14-Oct-2023 + +Abstract +================== + +This PEP proposes introducing syntatic sugar ``f(x=)`` for the common +pattern where a named argument is the same as the name of the variable +corresponding to its value ``f(x=x)``. + +Motivation +================== +Keyword argument syntax can become needlessly repetitive and verbose. + +Consider the following call: +:: + + my_function( + my_first_variable=my_first_variable, + my_second_variable=my_second_variable, + my_third_variable=my_third_variable, + ) + +The case of a keyword argument name matching the variable name of its value is prevalent among all major Python libraries. This verbosity and redundancy discourages use of named arguments and reduces readability by increasing visual noise. + +Rationale +================== +There are two ways to invoke a function with arguments: by position and by keyword. Keyword arguments confer many benefits by being explicit, thus increasing readability and minimising the risk of inadvertent transposition. On the flipside, positional arguments are often used simply to minimise verbosity and visual noise. + +We contend that a simple syntactic sugar used to simplify this common pattern which would confer numerous benefits: + +Encourages use of named variables +------------------------------------ +This syntax would encourage the use of named variables, thereby increasing readability (*explicit is better than implicit*) and reducing bugs from argument transposition. + +Reduces verbosity +------------------------------------ +By minimising visual noise and in some cases lines of code, we can increase readability (*readability counts*). + +Encourages consistent variable names +------------------------------------ +A common problem is that semantically identical variables have different names depending on their contexts. This syntax would encourage authors to use the same variable name when calling a function as the argument name, which would increase consistency of variable names used and hence also *readability*. + +Naturally extends to dictionaries +------------------------------------ +This syntax offers a natural way to support this syntactic sugar for dictionary construction where a similar pattern occurs (dictionary keys are identical the names of the variables assigned as their values), ``{"x": x, "y": y}`` or ``dict(x=x, y=y)``. With this feature, this can now also be trivially written as ``dict(x=, y=)``. Whether to further support similar syntax in dictionary literals is an open question out of the scope of this PEP. + +Specification +================== + +The proposed syntactic sugar is very simple. Instead of: +:: + + my_function(param1=param1, param2=param2) + +You may instead write: +:: + + my_function(param1=, param2=) + + +Precedence +================== +Python already possesses a very similar feature in f-string interpolation where ``f'{x=}'`` is effectively expanded to ``f'x={x}'`` [1]_. + +Several modern languages offer similar features during function invocation, sometimes referred to as 'punning'. For example: + +* In Ruby, ``f(x:, y:)`` is syntactic sugar for ``f(x: x, y: y)`` [2]_ +* In ReasonML, ``f(~x, ~y)`` is syntactic sugar for ``f(~x=x, ~y=y)`` [3]_ +* In SystemVerilog, ``(.mult, .mop1, .data);`` is syntactic sugar for ``(.mult(mult), .mop1(mop1), .data(data));`` [4]_ + +Outside of function invocation, even more languages have similar features: + +* In OCaml, ``let+ x in …`` is syntactic sugar for ``let+ x = x in …`` [5]_ +* In JavaScript, ``{ x, y }`` is syntactic sugar for ``{x: x, y: y}`` [6]_ +* In Rust, ``User { x, y }`` is shorthand for ``User {x: x, y: y}`` [7]_ + +Applicability +================== +We analysed popular Python libraries using `this script `__ to compute: + +* Number of keyword arguments were of the form ``f(x=x)`` at invocation +* Percentage of keyword arguments had the form ``f(x=x)`` at invocation +* Number of lines of code could be saved by using this syntactic sugar to reduce the need for line wraps + +===================================================================== ================ ============== =============== ===================== +Statistic `cpython `__ `numpy `__ `pandas `__ `scikit-learn `__ +===================================================================== ================ ============== =============== ===================== +Number of keyword arguments of the form ``f(x=x)`` at invocation 4,225 2,768 13,235 8,342 +Percentage of keyword arguments of the form ``f(x=x)`` at invocation 11.06% 13.17% 17.24% 18.64% +Lines saved 290 247 935 794 +===================================================================== ================ ============== =============== ===================== + +.. _a: https://github.com/python/cpython/pull/111423/ +.. _b: https://github.com/numpy/numpy/pull/25021/ +.. _c: https://github.com/pandas-dev/pandas/pull/55744/ +.. _d: https://github.com/scikit-learn/scikit-learn/pull/27680/ + +Based on this, the ``f(x=x)`` keyword argument pattern is widespread, accounting for 10-20% of all keyword argument uses. + +Syntax Selection +======================== +While this feature has been proposed on numerous occasions with several different forms [8]_ [9]_ [10]_ [11]_ [12]_, [13]_ we have opted to advocate for the ``f(x=)`` form. + +Justification +-------------------------------------------- +* This feature has been proposed frequently over a ten year period with the ``f(x=)`` or ``f(=x)`` being by far the most common syntax [8]_ [9]_ [13]_. This is a strong indicator that it is the obvious notation. +* The proposed syntax closely matches the f-string debug ``f'{var=}'`` syntax (established Pythonic style) and serves an almost identical purpose. +* The proposed syntax is exactly analogous to the Ruby keyword argument syntactic sugar [2]_. +* The syntax is easy to implement as it is simple syntactic sugar. +* When compared to the prefix form (see `Rejected Alternatives`_), this syntax communicates "here is a parameter, go find its argument" which is more appropriate given the semantics of named arguments + +Rejected Alternatives +-------------------------------------------- +Many alternative syntaxes have been proposed however no syntax other than ``f(=x)`` or ``f(x=)`` has garnered significant support. We here enumerate some of the most popular proposed alternatives and why we ultimately reject them. + +``f(=x)`` +''''''''''''''''''''''''''''''''''''''''''''' +In favour of this form: + +* It is more similar to the established ``*args`` and ``**kwargs`` syntax for function calls +* It draws more attention to itself when arguments are arranged vertically. In particular, if the arguments are of different lengths it is harder to find the equal sign at the end. Moreover, since Python is read left to right, the use of this feature is clearer to the reader earlier on. + +On the contrary: + +* While the prefix version is visually louder, in practice, there is no need for this feature to shout its presence any more than a typical named argument. By the time we read to the ``=`` it is clear that the value is filled in automatically just as the value is clear in the typical keyword argument case. +* Semantically, this form communicates 'here is a value, fill in the parameter' which is not what we want to convey. +* Less similar to f-string syntax +* Less obvious that arbitrary expressions are invalid, e.g.`` f(=a+b)`` + + +``f(%x)`` or ``f(:x)`` or ``f(.x)`` +''''''''''''''''''''''''''''''''''''''''''''' +Several flavours of this syntax have been proposed with the prefix form substituting another character for ``=``. However, no such form has gained traction and choice of symbol seems arbitrary compared to ``=``. Additionally, there is less precedent in terms of existing language features (such as f-string) or other languages (such as Ruby). + + +``f(a, b, *, x)`` +''''''''''''''''''''''''''''''''''''''''''''' +On a few occasions the idea has been floated to borrow the syntax from keyword-only function definitions. This is less arbitrary than ``f(%x)`` or variants, but no less so than ``f(x=)``. + +However, we object that: + +* For any given argument, it is less clear from local context whether it is positional or named. The ``*`` could easily be missed in a long argument list and named arguments may be read as positional or vice versa. +* It is unclear whether keyword arguments for which the value was not elided may follow the ``*``. If so, then their relative position will be inconsistent but if not, then an arbitrary grouping is enforced between different types of keyword arguments. + + +Objections +================== + +There are only a few hard objections to the introduction of this syntactic sugar. Most of those not in favour of this feature are simply in the camp of 'I wouldn't use it'. However over the extensive conversations about this feature, the following objections were the most common: + +The syntax is ugly +-------------------------------------------- +This objection is by far the most common. On the contrary, we argue that: + +* This objection is is subjective and many community members disagree +* This is already established syntax used in f-strings +* Programmers will, as ever, adjust over time + +The feature is confusing +-------------------------------------------- +We argue that: + +* Introducing new features typically has this temporary impact +* The syntax is very similar to the established ``f'{x=}'`` syntax +* The feature and syntax are familiar from other popular modern languages +* The expansion of ``x=`` to ``x=x`` is in fact a trivial feature and inherently significantly less complex than ``*arg`` and ``**kwarg`` expansion +* This particular syntactic form has been independently proposed on numerous occasions, indicating that it is the most obvious [8]_ [9]_ [13]_ + +The feature is not explicit +-------------------------------------------- +This is based on a misunderstanding of the Zen of Python. Keyword arguments are fundamentally more explicit than positional ones where argument assignment is only visible at the function definition. On the contrary, the proposed syntactic sugar contains all the information as is conveyed by the established keyword argument syntax but without the redundancy. Moreover, the introduction of this syntactic sugar incentivises use of keyword arguments, making practical Python code more explicit. + +The feature adds another way of doing things +-------------------------------------------- + +The same argument can be made against all syntax changes. This is a simple syntactic sugar, much as ``x += 1`` is sugar for ``x = x + 1``. This isn't tantamount to a 'new way' of passing arguments but a more readable notation for the same way. + +Renaming the variable in the calling context will break the code +-------------------------------------------- + +An ``NameError`` would make the mistake abundantly clear. Moreover, text editors could highlight this based on static analysis ‒ f(x=) is exactly equivalent to writing ``f(x=x)``. If ``x`` does not exist, editors currently have no problem highlighting that issue. + +Recommendations +======================== +As with any other language feature, the programmer should be judicious about whether using this feature improves their code based on the context. We do not advocate for enforcing a rule of using this feature in all cases where it may be applicable. + +Reference Implementation +======================== +A proposed implementation for `cpython is here `_. + +References +======================== + +.. [1] Issue 36817: Add = to f-strings for easier debugging. - Python tracker + https://bugs.python.org/issue36817 +.. [2] Ruby keyword argument syntactic sugar + https://www.ruby-lang.org/en/news/2021/12/25/ruby-3-1-0-released/#:~:text=Other%20Notable%20New%20Features +.. [3] ReasonML named argument punning + https://reasonml.github.io/docs/en/function#:~:text=Named%20argument%20punning +.. [4] SystemVerilog Implicit Port Connections + http://www.sunburst-design.com/papers/CummingsDesignCon2005_SystemVerilog_ImplicitPorts.pdf +.. [5] OCaml Short notation for variable bindings (let-punning) + https://v2.ocaml.org/manual/bindingops.html#ss:letops-punning +.. [6] JavaScript Object Initializer + https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer +.. [7] Rust Using the Field Init Shorthand + https://doc.rust-lang.org/book/ch05-01-defining-structs.html#using-the-field-init-shorthand-when-variables-and-fields-have-the-same-name +.. [8] Short form for keyword arguments and dicts (2013) + https://mail.python.org/archives/list/python-ideas@python.org/thread/SQKZ273MYAY5WNIQRGEDLYTKVORVKNEZ/#LXMU22F63VPCF7CMQ4OQRH2CG6H7WCQ6 +.. [9] Keyword arguments self-assignment (2020) + https://mail.python.org/archives/list/python-ideas@python.org/thread/SIMIOC7OW6QKLJOTHJJVNNBDSXDE2SGV/ +.. [10] Shorthand notation of dict literal and function call (2020) + https://discuss.python.org/t/shorthand-notation-of-dict-literal-and-function-call/5697/1 +.. [11] Allow identifiers as keyword arguments at function call site (extension of PEP 3102?) (2023) + https://discuss.python.org/t/allow-identifiers-as-keyword-arguments-at-function-call-site-extension-of-pep-3102/31677 +.. [12] Shorten Keyword Arguments with Implicit Notation: foo(a=a, b=b) to foo(.a, .b) (2023) + https://discuss.python.org/t/shorten-keyword-arguments-with-implicit-notation-foo-a-a-b-b-to-foo-a-b/33080 +.. [13] Syntactic sugar to encourage use of named arguments (2023) + https://discuss.python.org/t/syntactic-sugar-to-encourage-use-of-named-arguments/36217 + +Copyright +======================== + +This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive. From 8c09f77a00494a7a7728d9c044a5d039f868593f Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Mon, 27 Nov 2023 21:57:15 +0000 Subject: [PATCH 02/22] Address comments --- peps/pep-9999.rst | 191 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 135 insertions(+), 56 deletions(-) diff --git a/peps/pep-9999.rst b/peps/pep-9999.rst index 489998cd5e0..5978894befb 100644 --- a/peps/pep-9999.rst +++ b/peps/pep-9999.rst @@ -1,6 +1,7 @@ PEP: 9999 Title: Syntactic sugar for named arguments -Author: Joshua Bambrick , Chris Angelico +Author: Joshua Bambrick , + Chris Angelico Sponsor: Guido van Rossum Discussions-To: https://discuss.python.org/t/syntactic-sugar-to-encourage-use-of-named-arguments/36217 Status: Draft @@ -29,29 +30,48 @@ Consider the following call: my_third_variable=my_third_variable, ) -The case of a keyword argument name matching the variable name of its value is prevalent among all major Python libraries. This verbosity and redundancy discourages use of named arguments and reduces readability by increasing visual noise. +The case of a keyword argument name matching the variable name of its value is +prevalent among all major Python libraries. This verbosity and redundancy +discourages use of named arguments and reduces readability by increasing visual +noise. Rationale ================== -There are two ways to invoke a function with arguments: by position and by keyword. Keyword arguments confer many benefits by being explicit, thus increasing readability and minimising the risk of inadvertent transposition. On the flipside, positional arguments are often used simply to minimise verbosity and visual noise. +There are two ways to invoke a function with arguments: by position and by +keyword. Keyword arguments confer many benefits by being explicit, thus +increasing readability and minimising the risk of inadvertent transposition. On +the flipside, positional arguments are often used simply to minimise verbosity +and visual noise. -We contend that a simple syntactic sugar used to simplify this common pattern which would confer numerous benefits: +We contend that a simple syntactic sugar used to simplify this common pattern +which would confer numerous benefits: Encourages use of named variables ------------------------------------ -This syntax would encourage the use of named variables, thereby increasing readability (*explicit is better than implicit*) and reducing bugs from argument transposition. +This syntax would encourage the use of named variables, thereby increasing +readability (*explicit is better than implicit*) and reducing bugs from argument +transposition. Reduces verbosity ------------------------------------ -By minimising visual noise and in some cases lines of code, we can increase readability (*readability counts*). +By minimising visual noise and in some cases lines of code, we can increase +readability (*readability counts*). Encourages consistent variable names ------------------------------------ -A common problem is that semantically identical variables have different names depending on their contexts. This syntax would encourage authors to use the same variable name when calling a function as the argument name, which would increase consistency of variable names used and hence also *readability*. - -Naturally extends to dictionaries ------------------------------------- -This syntax offers a natural way to support this syntactic sugar for dictionary construction where a similar pattern occurs (dictionary keys are identical the names of the variables assigned as their values), ``{"x": x, "y": y}`` or ``dict(x=x, y=y)``. With this feature, this can now also be trivially written as ``dict(x=, y=)``. Whether to further support similar syntax in dictionary literals is an open question out of the scope of this PEP. +A common problem is that semantically identical variables have different names +depending on their contexts. This syntax would encourage authors to use the same +variable name when calling a function as the argument name, which would increase +consistency of variable names used and hence also *readability*. + +Applicability to dictionary construction +---------------------------------------- +This syntax offers a natural way to support this syntactic sugar for dictionary +construction where a similar pattern occurs (dictionary keys are identical the +names of the variables assigned as their values), ``{"x": x, "y": y}`` or +``dict(x=x, y=y)``. With this feature, this can now also be trivially written as +``dict(x=, y=)``. Whether to further support similar syntax in dictionary +literals is an open question out of the scope of this PEP. Specification ================== @@ -67,15 +87,18 @@ You may instead write: my_function(param1=, param2=) -Precedence +Prior Art ================== -Python already possesses a very similar feature in f-string interpolation where ``f'{x=}'`` is effectively expanded to ``f'x={x}'`` [1]_. +Python already possesses a very similar feature in f-string interpolation where +``f'{x=}'`` is effectively expanded to ``f'x={x}'`` [1]_. -Several modern languages offer similar features during function invocation, sometimes referred to as 'punning'. For example: +Several modern languages offer similar features during function invocation, +sometimes referred to as 'punning'. For example: * In Ruby, ``f(x:, y:)`` is syntactic sugar for ``f(x: x, y: y)`` [2]_ * In ReasonML, ``f(~x, ~y)`` is syntactic sugar for ``f(~x=x, ~y=y)`` [3]_ -* In SystemVerilog, ``(.mult, .mop1, .data);`` is syntactic sugar for ``(.mult(mult), .mop1(mop1), .data(data));`` [4]_ +* In SystemVerilog, ``(.mult, .mop1, .data);`` is syntactic sugar for + ``(.mult(mult), .mop1(mop1), .data(data));`` [4]_ Outside of function invocation, even more languages have similar features: @@ -85,11 +108,14 @@ Outside of function invocation, even more languages have similar features: Applicability ================== -We analysed popular Python libraries using `this script `__ to compute: +We analysed popular Python libraries using +`this script `__ +to compute: * Number of keyword arguments were of the form ``f(x=x)`` at invocation * Percentage of keyword arguments had the form ``f(x=x)`` at invocation -* Number of lines of code could be saved by using this syntactic sugar to reduce the need for line wraps +* Number of lines of code could be saved by using this syntactic sugar to + reduce the need for line wraps ===================================================================== ================ ============== =============== ===================== Statistic `cpython `__ `numpy `__ `pandas `__ `scikit-learn `__ @@ -104,58 +130,91 @@ Lines saved 290 .. _c: https://github.com/pandas-dev/pandas/pull/55744/ .. _d: https://github.com/scikit-learn/scikit-learn/pull/27680/ -Based on this, the ``f(x=x)`` keyword argument pattern is widespread, accounting for 10-20% of all keyword argument uses. +Based on this, the ``f(x=x)`` keyword argument pattern is widespread, accounting +for 10-20% of all keyword argument uses. -Syntax Selection +Proposed Syntax ======================== -While this feature has been proposed on numerous occasions with several different forms [8]_ [9]_ [10]_ [11]_ [12]_, [13]_ we have opted to advocate for the ``f(x=)`` form. - -Justification --------------------------------------------- -* This feature has been proposed frequently over a ten year period with the ``f(x=)`` or ``f(=x)`` being by far the most common syntax [8]_ [9]_ [13]_. This is a strong indicator that it is the obvious notation. -* The proposed syntax closely matches the f-string debug ``f'{var=}'`` syntax (established Pythonic style) and serves an almost identical purpose. -* The proposed syntax is exactly analogous to the Ruby keyword argument syntactic sugar [2]_. +While this feature has been proposed on numerous occasions with several +different forms [8]_ [9]_ [10]_ [11]_ [12]_, [13]_ we have opted to advocate +for the ``f(x=)`` form for the following reasons: + +* This feature has been proposed frequently over a ten year period with the + ``f(x=)`` or ``f(=x)`` being by far the most common syntax [8]_ [9]_ [13]_. + This is a strong indicator that it is the obvious notation. +* The proposed syntax closely matches the f-string debug ``f'{var=}'`` syntax + (established Pythonic style) and serves an almost identical purpose. +* The proposed syntax is exactly analogous to the Ruby keyword argument + syntactic sugar [2]_. * The syntax is easy to implement as it is simple syntactic sugar. -* When compared to the prefix form (see `Rejected Alternatives`_), this syntax communicates "here is a parameter, go find its argument" which is more appropriate given the semantics of named arguments - -Rejected Alternatives --------------------------------------------- -Many alternative syntaxes have been proposed however no syntax other than ``f(=x)`` or ``f(x=)`` has garnered significant support. We here enumerate some of the most popular proposed alternatives and why we ultimately reject them. +* When compared to the prefix form (see `Rejected Alternatives`_), this syntax + communicates "here is a parameter, go find its argument" which is more + appropriate given the semantics of named arguments +* `A poll of Python developers `__ + indicates that this is the most popular syntax of those proposed. + +Rejected Ideas +============================= +Many alternative syntaxes have been proposed however no syntax other than +``f(=x)`` or ``f(x=)`` has garnered significant support. We here enumerate some +of the most popular proposed alternatives and why we ultimately reject them. ``f(=x)`` -''''''''''''''''''''''''''''''''''''''''''''' +------------------------------ In favour of this form: -* It is more similar to the established ``*args`` and ``**kwargs`` syntax for function calls -* It draws more attention to itself when arguments are arranged vertically. In particular, if the arguments are of different lengths it is harder to find the equal sign at the end. Moreover, since Python is read left to right, the use of this feature is clearer to the reader earlier on. +* It is more similar to the established ``*args`` and ``**kwargs`` syntax for + function calls +* It draws more attention to itself when arguments are arranged vertically. In + particular, if the arguments are of different lengths it is harder to find the + equal sign at the end. Moreover, since Python is read left to right, the use + of this feature is clearer to the reader earlier on. On the contrary: -* While the prefix version is visually louder, in practice, there is no need for this feature to shout its presence any more than a typical named argument. By the time we read to the ``=`` it is clear that the value is filled in automatically just as the value is clear in the typical keyword argument case. -* Semantically, this form communicates 'here is a value, fill in the parameter' which is not what we want to convey. +* While the prefix version is visually louder, in practice, there is no need for + this feature to shout its presence any more than a typical named argument. By + the time we read to the ``=`` it is clear that the value is filled in + automatically just as the value is clear in the typical keyword argument case. +* Semantically, this form communicates 'here is a value, fill in the parameter' +* which is not what we want to convey. * Less similar to f-string syntax * Less obvious that arbitrary expressions are invalid, e.g.`` f(=a+b)`` ``f(%x)`` or ``f(:x)`` or ``f(.x)`` -''''''''''''''''''''''''''''''''''''''''''''' -Several flavours of this syntax have been proposed with the prefix form substituting another character for ``=``. However, no such form has gained traction and choice of symbol seems arbitrary compared to ``=``. Additionally, there is less precedent in terms of existing language features (such as f-string) or other languages (such as Ruby). +------------------------------ +Several flavours of this syntax have been proposed with the prefix form +substituting another character for ``=``. However, no such form has gained +traction and choice of symbol seems arbitrary compared to ``=``. Additionally, +there is less precedent in terms of existing language features (such as +f-string) or other languages (such as Ruby). ``f(a, b, *, x)`` -''''''''''''''''''''''''''''''''''''''''''''' -On a few occasions the idea has been floated to borrow the syntax from keyword-only function definitions. This is less arbitrary than ``f(%x)`` or variants, but no less so than ``f(x=)``. +------------------------------ +On a few occasions the idea has been floated to borrow the syntax from +keyword-only function definitions. This is less arbitrary than ``f(%x)`` or +variants, but no less so than ``f(x=)``. However, we object that: -* For any given argument, it is less clear from local context whether it is positional or named. The ``*`` could easily be missed in a long argument list and named arguments may be read as positional or vice versa. -* It is unclear whether keyword arguments for which the value was not elided may follow the ``*``. If so, then their relative position will be inconsistent but if not, then an arbitrary grouping is enforced between different types of keyword arguments. +* For any given argument, it is less clear from local context whether it is + positional or named. The ``*`` could easily be missed in a long argument list + and named arguments may be read as positional or vice versa. +* It is unclear whether keyword arguments for which the value was not elided may + follow the ``*``. If so, then their relative position will be inconsistent but + if not, then an arbitrary grouping is enforced between different types of + keyword arguments. Objections ================== -There are only a few hard objections to the introduction of this syntactic sugar. Most of those not in favour of this feature are simply in the camp of 'I wouldn't use it'. However over the extensive conversations about this feature, the following objections were the most common: +There are only a few hard objections to the introduction of this syntactic +sugar. Most of those not in favour of this feature are simply in the camp of 'I +wouldn't use it'. However over the extensive conversations about this feature, +the following objections were the most common: The syntax is ugly -------------------------------------------- @@ -172,33 +231,51 @@ We argue that: * Introducing new features typically has this temporary impact * The syntax is very similar to the established ``f'{x=}'`` syntax * The feature and syntax are familiar from other popular modern languages -* The expansion of ``x=`` to ``x=x`` is in fact a trivial feature and inherently significantly less complex than ``*arg`` and ``**kwarg`` expansion -* This particular syntactic form has been independently proposed on numerous occasions, indicating that it is the most obvious [8]_ [9]_ [13]_ +* The expansion of ``x=`` to ``x=x`` is in fact a trivial feature and inherently + significantly less complex than ``*arg`` and ``**kwarg`` expansion +* This particular syntactic form has been independently proposed on numerous + occasions, indicating that it is the most obvious [8]_ [9]_ [13]_ The feature is not explicit -------------------------------------------- -This is based on a misunderstanding of the Zen of Python. Keyword arguments are fundamentally more explicit than positional ones where argument assignment is only visible at the function definition. On the contrary, the proposed syntactic sugar contains all the information as is conveyed by the established keyword argument syntax but without the redundancy. Moreover, the introduction of this syntactic sugar incentivises use of keyword arguments, making practical Python code more explicit. +This is based on a misunderstanding of the Zen of Python. Keyword arguments are +fundamentally more explicit than positional ones where argument assignment is +only visible at the function definition. On the contrary, the proposed syntactic +sugar contains all the information as is conveyed by the established keyword +argument syntax but without the redundancy. Moreover, the introduction of this +syntactic sugar incentivises use of keyword arguments, making practical Python +code more explicit. The feature adds another way of doing things -------------------------------------------- -The same argument can be made against all syntax changes. This is a simple syntactic sugar, much as ``x += 1`` is sugar for ``x = x + 1``. This isn't tantamount to a 'new way' of passing arguments but a more readable notation for the same way. +The same argument can be made against all syntax changes. This is a simple +syntactic sugar, much as ``x += 1`` is sugar for ``x = x + 1`` when ``x`` is an +integer. This isn't tantamount to a 'new way' of passing arguments but a more +readable notation for the same way. Renaming the variable in the calling context will break the code --------------------------------------------- +------------------------------------------------------------------------ -An ``NameError`` would make the mistake abundantly clear. Moreover, text editors could highlight this based on static analysis ‒ f(x=) is exactly equivalent to writing ``f(x=x)``. If ``x`` does not exist, editors currently have no problem highlighting that issue. +A ``NameError`` would make the mistake abundantly clear. Moreover, text editors +could highlight this based on static analysis ‒ f(x=) is exactly equivalent to +writing ``f(x=x)``. If ``x`` does not exist, editors currently have no problem +highlighting that issue. Recommendations -======================== -As with any other language feature, the programmer should be judicious about whether using this feature improves their code based on the context. We do not advocate for enforcing a rule of using this feature in all cases where it may be applicable. +================================================ +As with any other language feature, the programmer should be judicious about +whether using this feature improves their code based on the context. We do not +advocate for enforcing a rule of using this feature in all cases where it may be +applicable. Reference Implementation -======================== -A proposed implementation for `cpython is here `_. +================================================ +A proposed implementation for +`cpython is here `_. References -======================== +================================================ .. [1] Issue 36817: Add = to f-strings for easier debugging. - Python tracker https://bugs.python.org/issue36817 @@ -220,7 +297,8 @@ References https://mail.python.org/archives/list/python-ideas@python.org/thread/SIMIOC7OW6QKLJOTHJJVNNBDSXDE2SGV/ .. [10] Shorthand notation of dict literal and function call (2020) https://discuss.python.org/t/shorthand-notation-of-dict-literal-and-function-call/5697/1 -.. [11] Allow identifiers as keyword arguments at function call site (extension of PEP 3102?) (2023) +.. [11] Allow identifiers as keyword arguments at function call site (extension + of PEP 3102?) (2023) https://discuss.python.org/t/allow-identifiers-as-keyword-arguments-at-function-call-site-extension-of-pep-3102/31677 .. [12] Shorten Keyword Arguments with Implicit Notation: foo(a=a, b=b) to foo(.a, .b) (2023) https://discuss.python.org/t/shorten-keyword-arguments-with-implicit-notation-foo-a-a-b-b-to-foo-a-b/33080 @@ -230,4 +308,5 @@ References Copyright ======================== -This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive. +This document is placed in the public domain or under the CC0-1.0-Universal +license, whichever is more permissive. From 308d274d837dc173538e89e1dbee16f977788a05 Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Mon, 27 Nov 2023 23:38:30 +0000 Subject: [PATCH 03/22] Fix lint --- peps/pep-9999.rst | 50 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/peps/pep-9999.rst b/peps/pep-9999.rst index 5978894befb..f04650acb3d 100644 --- a/peps/pep-9999.rst +++ b/peps/pep-9999.rst @@ -4,21 +4,21 @@ Author: Joshua Bambrick , Chris Angelico Sponsor: Guido van Rossum Discussions-To: https://discuss.python.org/t/syntactic-sugar-to-encourage-use-of-named-arguments/36217 -Status: Draft +Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 28-Oct-2023 Post-History: 14-Oct-2023 Abstract -================== +======== This PEP proposes introducing syntatic sugar ``f(x=)`` for the common pattern where a named argument is the same as the name of the variable corresponding to its value ``f(x=x)``. Motivation -================== +========== Keyword argument syntax can become needlessly repetitive and verbose. Consider the following call: @@ -36,7 +36,7 @@ discourages use of named arguments and reduces readability by increasing visual noise. Rationale -================== +========= There are two ways to invoke a function with arguments: by position and by keyword. Keyword arguments confer many benefits by being explicit, thus increasing readability and minimising the risk of inadvertent transposition. On @@ -47,13 +47,13 @@ We contend that a simple syntactic sugar used to simplify this common pattern which would confer numerous benefits: Encourages use of named variables ------------------------------------- +--------------------------------- This syntax would encourage the use of named variables, thereby increasing readability (*explicit is better than implicit*) and reducing bugs from argument transposition. Reduces verbosity ------------------------------------- +----------------- By minimising visual noise and in some cases lines of code, we can increase readability (*readability counts*). @@ -74,7 +74,7 @@ names of the variables assigned as their values), ``{"x": x, "y": y}`` or literals is an open question out of the scope of this PEP. Specification -================== +============= The proposed syntactic sugar is very simple. Instead of: :: @@ -88,7 +88,7 @@ You may instead write: Prior Art -================== +========= Python already possesses a very similar feature in f-string interpolation where ``f'{x=}'`` is effectively expanded to ``f'x={x}'`` [1]_. @@ -107,7 +107,7 @@ Outside of function invocation, even more languages have similar features: * In Rust, ``User { x, y }`` is shorthand for ``User {x: x, y: y}`` [7]_ Applicability -================== +============= We analysed popular Python libraries using `this script `__ to compute: @@ -134,7 +134,7 @@ Based on this, the ``f(x=x)`` keyword argument pattern is widespread, accounting for 10-20% of all keyword argument uses. Proposed Syntax -======================== +=============== While this feature has been proposed on numerous occasions with several different forms [8]_ [9]_ [10]_ [11]_ [12]_, [13]_ we have opted to advocate for the ``f(x=)`` form for the following reasons: @@ -147,20 +147,20 @@ for the ``f(x=)`` form for the following reasons: * The proposed syntax is exactly analogous to the Ruby keyword argument syntactic sugar [2]_. * The syntax is easy to implement as it is simple syntactic sugar. -* When compared to the prefix form (see `Rejected Alternatives`_), this syntax +* When compared to the prefix form (see `Rejected Ideas`_), this syntax communicates "here is a parameter, go find its argument" which is more appropriate given the semantics of named arguments * `A poll of Python developers `__ indicates that this is the most popular syntax of those proposed. Rejected Ideas -============================= +============== Many alternative syntaxes have been proposed however no syntax other than ``f(=x)`` or ``f(x=)`` has garnered significant support. We here enumerate some of the most popular proposed alternatives and why we ultimately reject them. ``f(=x)`` ------------------------------- +---------- In favour of this form: * It is more similar to the established ``*args`` and ``**kwargs`` syntax for @@ -179,11 +179,11 @@ On the contrary: * Semantically, this form communicates 'here is a value, fill in the parameter' * which is not what we want to convey. * Less similar to f-string syntax -* Less obvious that arbitrary expressions are invalid, e.g.`` f(=a+b)`` +* Less obvious that arbitrary expressions are invalid, e.g. ``f(=a+b)`` ``f(%x)`` or ``f(:x)`` or ``f(.x)`` ------------------------------- +----------------------------------- Several flavours of this syntax have been proposed with the prefix form substituting another character for ``=``. However, no such form has gained traction and choice of symbol seems arbitrary compared to ``=``. Additionally, @@ -192,7 +192,7 @@ f-string) or other languages (such as Ruby). ``f(a, b, *, x)`` ------------------------------- +----------------- On a few occasions the idea has been floated to borrow the syntax from keyword-only function definitions. This is less arbitrary than ``f(%x)`` or variants, but no less so than ``f(x=)``. @@ -209,7 +209,7 @@ However, we object that: Objections -================== +========== There are only a few hard objections to the introduction of this syntactic sugar. Most of those not in favour of this feature are simply in the camp of 'I @@ -217,7 +217,7 @@ wouldn't use it'. However over the extensive conversations about this feature, the following objections were the most common: The syntax is ugly --------------------------------------------- +------------------ This objection is by far the most common. On the contrary, we argue that: * This objection is is subjective and many community members disagree @@ -225,7 +225,7 @@ This objection is by far the most common. On the contrary, we argue that: * Programmers will, as ever, adjust over time The feature is confusing --------------------------------------------- +------------------------ We argue that: * Introducing new features typically has this temporary impact @@ -237,7 +237,7 @@ We argue that: occasions, indicating that it is the most obvious [8]_ [9]_ [13]_ The feature is not explicit --------------------------------------------- +--------------------------- This is based on a misunderstanding of the Zen of Python. Keyword arguments are fundamentally more explicit than positional ones where argument assignment is only visible at the function definition. On the contrary, the proposed syntactic @@ -255,7 +255,7 @@ integer. This isn't tantamount to a 'new way' of passing arguments but a more readable notation for the same way. Renaming the variable in the calling context will break the code ------------------------------------------------------------------------- +---------------------------------------------------------------- A ``NameError`` would make the mistake abundantly clear. Moreover, text editors could highlight this based on static analysis ‒ f(x=) is exactly equivalent to @@ -263,19 +263,19 @@ writing ``f(x=x)``. If ``x`` does not exist, editors currently have no problem highlighting that issue. Recommendations -================================================ +=============== As with any other language feature, the programmer should be judicious about whether using this feature improves their code based on the context. We do not advocate for enforcing a rule of using this feature in all cases where it may be applicable. Reference Implementation -================================================ +======================== A proposed implementation for `cpython is here `_. References -================================================ +========== .. [1] Issue 36817: Add = to f-strings for easier debugging. - Python tracker https://bugs.python.org/issue36817 @@ -306,7 +306,7 @@ References https://discuss.python.org/t/syntactic-sugar-to-encourage-use-of-named-arguments/36217 Copyright -======================== +========= This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive. From 3c340b1b0873745501d6ed23f30cd3b5b4a5148a Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Mon, 27 Nov 2023 23:44:19 +0000 Subject: [PATCH 04/22] Consistent bullet list format --- peps/pep-9999.rst | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/peps/pep-9999.rst b/peps/pep-9999.rst index f04650acb3d..c95c95a2124 100644 --- a/peps/pep-9999.rst +++ b/peps/pep-9999.rst @@ -95,16 +95,16 @@ Python already possesses a very similar feature in f-string interpolation where Several modern languages offer similar features during function invocation, sometimes referred to as 'punning'. For example: -* In Ruby, ``f(x:, y:)`` is syntactic sugar for ``f(x: x, y: y)`` [2]_ -* In ReasonML, ``f(~x, ~y)`` is syntactic sugar for ``f(~x=x, ~y=y)`` [3]_ +* In Ruby, ``f(x:, y:)`` is syntactic sugar for ``f(x: x, y: y)`` [2]_. +* In ReasonML, ``f(~x, ~y)`` is syntactic sugar for ``f(~x=x, ~y=y)`` [3]_. * In SystemVerilog, ``(.mult, .mop1, .data);`` is syntactic sugar for - ``(.mult(mult), .mop1(mop1), .data(data));`` [4]_ + ``(.mult(mult), .mop1(mop1), .data(data));`` [4]_. Outside of function invocation, even more languages have similar features: -* In OCaml, ``let+ x in …`` is syntactic sugar for ``let+ x = x in …`` [5]_ -* In JavaScript, ``{ x, y }`` is syntactic sugar for ``{x: x, y: y}`` [6]_ -* In Rust, ``User { x, y }`` is shorthand for ``User {x: x, y: y}`` [7]_ +* In OCaml, ``let+ x in …`` is syntactic sugar for ``let+ x = x in …`` [5]_. +* In JavaScript, ``{ x, y }`` is syntactic sugar for ``{x: x, y: y}`` [6]_. +* In Rust, ``User { x, y }`` is shorthand for ``User {x: x, y: y}`` [7]_. Applicability ============= @@ -112,10 +112,10 @@ We analysed popular Python libraries using `this script `__ to compute: -* Number of keyword arguments were of the form ``f(x=x)`` at invocation -* Percentage of keyword arguments had the form ``f(x=x)`` at invocation +* Number of keyword arguments were of the form ``f(x=x)`` at invocation. +* Percentage of keyword arguments had the form ``f(x=x)`` at invocation. * Number of lines of code could be saved by using this syntactic sugar to - reduce the need for line wraps + reduce the need for line wraps. ===================================================================== ================ ============== =============== ===================== Statistic `cpython `__ `numpy `__ `pandas `__ `scikit-learn `__ @@ -149,7 +149,7 @@ for the ``f(x=)`` form for the following reasons: * The syntax is easy to implement as it is simple syntactic sugar. * When compared to the prefix form (see `Rejected Ideas`_), this syntax communicates "here is a parameter, go find its argument" which is more - appropriate given the semantics of named arguments + appropriate given the semantics of named arguments. * `A poll of Python developers `__ indicates that this is the most popular syntax of those proposed. @@ -164,7 +164,7 @@ of the most popular proposed alternatives and why we ultimately reject them. In favour of this form: * It is more similar to the established ``*args`` and ``**kwargs`` syntax for - function calls + function calls. * It draws more attention to itself when arguments are arranged vertically. In particular, if the arguments are of different lengths it is harder to find the equal sign at the end. Moreover, since Python is read left to right, the use @@ -178,8 +178,8 @@ On the contrary: automatically just as the value is clear in the typical keyword argument case. * Semantically, this form communicates 'here is a value, fill in the parameter' * which is not what we want to convey. -* Less similar to f-string syntax -* Less obvious that arbitrary expressions are invalid, e.g. ``f(=a+b)`` +* Less similar to f-string syntax. +* Less obvious that arbitrary expressions are invalid, e.g. ``f(=a+b)``. ``f(%x)`` or ``f(:x)`` or ``f(.x)`` @@ -220,21 +220,21 @@ The syntax is ugly ------------------ This objection is by far the most common. On the contrary, we argue that: -* This objection is is subjective and many community members disagree -* This is already established syntax used in f-strings -* Programmers will, as ever, adjust over time +* This objection is is subjective and many community members disagree. +* This is already established syntax used in f-strings. +* Programmers will, as ever, adjust over time. The feature is confusing ------------------------ We argue that: -* Introducing new features typically has this temporary impact -* The syntax is very similar to the established ``f'{x=}'`` syntax -* The feature and syntax are familiar from other popular modern languages +* Introducing new features typically has this temporary impact. +* The syntax is very similar to the established ``f'{x=}'`` syntax. +* The feature and syntax are familiar from other popular modern languages. * The expansion of ``x=`` to ``x=x`` is in fact a trivial feature and inherently - significantly less complex than ``*arg`` and ``**kwarg`` expansion + significantly less complex than ``*arg`` and ``**kwarg`` expansion. * This particular syntactic form has been independently proposed on numerous - occasions, indicating that it is the most obvious [8]_ [9]_ [13]_ + occasions, indicating that it is the most obvious [8]_ [9]_ [13]_. The feature is not explicit --------------------------- From b376af704b31d47c4e929db7fb5e2f0add16020c Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Mon, 27 Nov 2023 23:48:22 +0000 Subject: [PATCH 05/22] Minor language tweak --- peps/pep-9999.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/peps/pep-9999.rst b/peps/pep-9999.rst index c95c95a2124..84b1eae7adc 100644 --- a/peps/pep-9999.rst +++ b/peps/pep-9999.rst @@ -163,8 +163,8 @@ of the most popular proposed alternatives and why we ultimately reject them. ---------- In favour of this form: -* It is more similar to the established ``*args`` and ``**kwargs`` syntax for - function calls. +* The prefix operator is more similar to the established ``*args`` and + ``**kwargs`` syntax for function calls. * It draws more attention to itself when arguments are arranged vertically. In particular, if the arguments are of different lengths it is harder to find the equal sign at the end. Moreover, since Python is read left to right, the use From c644e16a22564c7a9fe85a8d064508fed9259a9a Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Mon, 27 Nov 2023 23:54:19 +0000 Subject: [PATCH 06/22] Assign number 736 --- peps/{pep-9999.rst => pep-736.rst} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename peps/{pep-9999.rst => pep-736.rst} (99%) diff --git a/peps/pep-9999.rst b/peps/pep-736.rst similarity index 99% rename from peps/pep-9999.rst rename to peps/pep-736.rst index 84b1eae7adc..b57475bcce2 100644 --- a/peps/pep-9999.rst +++ b/peps/pep-736.rst @@ -1,4 +1,4 @@ -PEP: 9999 +PEP: 736 Title: Syntactic sugar for named arguments Author: Joshua Bambrick , Chris Angelico From 3dba8e6ae702a0c54c06949531df5370673924a3 Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Tue, 28 Nov 2023 00:01:04 +0000 Subject: [PATCH 07/22] Fix creation date --- peps/{pep-736.rst => pep-0736.rst} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename peps/{pep-736.rst => pep-0736.rst} (99%) diff --git a/peps/pep-736.rst b/peps/pep-0736.rst similarity index 99% rename from peps/pep-736.rst rename to peps/pep-0736.rst index b57475bcce2..f651eb218b0 100644 --- a/peps/pep-736.rst +++ b/peps/pep-0736.rst @@ -7,7 +7,7 @@ Discussions-To: https://discuss.python.org/t/syntactic-sugar-to-encourage-use-of Status: Draft Type: Standards Track Content-Type: text/x-rst -Created: 28-Oct-2023 +Created: 27-Nov-2023 Post-History: 14-Oct-2023 Abstract From 8f545acc1b871f789cdaa72d750e937970aaea8f Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Tue, 28 Nov 2023 00:07:30 +0000 Subject: [PATCH 08/22] Add python version --- peps/pep-0736.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index f651eb218b0..04bd4f7e978 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -8,6 +8,7 @@ Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 27-Nov-2023 +Python-Version: 3.13 Post-History: 14-Oct-2023 Abstract From 2ed5ab2759041e206c7a0f11d7bcce649ba0317f Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Tue, 28 Nov 2023 00:14:45 +0000 Subject: [PATCH 09/22] Update codeowners --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 03d9c709e9f..93176f2f6f9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -611,6 +611,7 @@ peps/pep-0730.rst @ned-deily peps/pep-0731.rst @gvanrossum @encukou @vstinner @zooba @iritkatriel peps/pep-0732.rst @Mariatta peps/pep-0733.rst @encukou @vstinner @zooba @iritkatriel +peps/pep-0736.rst @gvanrossum # ... # peps/pep-0754.rst # ... From 1db1ed21c3570e2201a789d72c9dd53f53107260 Mon Sep 17 00:00:00 2001 From: Joshua Bambrick Date: Tue, 28 Nov 2023 12:16:11 +0000 Subject: [PATCH 10/22] Minor tweaks --- peps/pep-0736.rst | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index 04bd4f7e978..7008b7a3444 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -7,7 +7,7 @@ Discussions-To: https://discuss.python.org/t/syntactic-sugar-to-encourage-use-of Status: Draft Type: Standards Track Content-Type: text/x-rst -Created: 27-Nov-2023 +Created: 28-Nov-2023 Python-Version: 3.13 Post-History: 14-Oct-2023 @@ -259,16 +259,15 @@ Renaming the variable in the calling context will break the code ---------------------------------------------------------------- A ``NameError`` would make the mistake abundantly clear. Moreover, text editors -could highlight this based on static analysis ‒ f(x=) is exactly equivalent to -writing ``f(x=x)``. If ``x`` does not exist, editors currently have no problem -highlighting that issue. +could highlight this based on static analysis ‒ ``f(x=)`` is exactly equivalent +to writing ``f(x=x)``. If ``x`` does not exist, modern editors have no problem +highlighting the issue. Recommendations =============== -As with any other language feature, the programmer should be judicious about -whether using this feature improves their code based on the context. We do not -advocate for enforcing a rule of using this feature in all cases where it may be -applicable. +As with any other language feature, the programmer should exercise their own +judgement about whether to use it in any given context. We do not recommend +enforcing a rule to use the feature in all cases where it may be applicable. Reference Implementation ======================== From 383cf5dea686c51b5a76581dd1ddab41cd69f878 Mon Sep 17 00:00:00 2001 From: Joshua Bambrick Date: Tue, 28 Nov 2023 12:20:24 +0000 Subject: [PATCH 11/22] Credit Hels15 --- peps/pep-0736.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index 7008b7a3444..b2c82ad5694 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -271,7 +271,7 @@ enforcing a rule to use the feature in all cases where it may be applicable. Reference Implementation ======================== -A proposed implementation for +A proposed implementation provided by @Hels15 for `cpython is here `_. References From 05227d2ca158fc9993abbc557bd401f2a6a9bb40 Mon Sep 17 00:00:00 2001 From: Joshua Bambrick Date: Tue, 28 Nov 2023 12:21:33 +0000 Subject: [PATCH 12/22] Reword implementation --- peps/pep-0736.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index b2c82ad5694..7b100d754b5 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -271,8 +271,8 @@ enforcing a rule to use the feature in all cases where it may be applicable. Reference Implementation ======================== -A proposed implementation provided by @Hels15 for -`cpython is here `_. +`A proposed implementation `_ +for cpython has been provided by @Hels15. References ========== From e18228bb59077731efe0ba37778132f5cc936af1 Mon Sep 17 00:00:00 2001 From: Joshua Bambrick Date: Tue, 28 Nov 2023 12:40:20 +0000 Subject: [PATCH 13/22] Fix spelling error --- peps/pep-0736.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index 7b100d754b5..aebdb46d46f 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -14,7 +14,7 @@ Post-History: 14-Oct-2023 Abstract ======== -This PEP proposes introducing syntatic sugar ``f(x=)`` for the common +This PEP proposes introducing syntactic sugar ``f(x=)`` for the common pattern where a named argument is the same as the name of the variable corresponding to its value ``f(x=x)``. From 18d700a0f968d424d65faa0ad6de4422e9c3adaf Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Sat, 2 Dec 2023 14:27:23 +0000 Subject: [PATCH 14/22] Add new lines after headings --- peps/pep-0736.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index aebdb46d46f..94b2d7343a1 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -20,6 +20,7 @@ corresponding to its value ``f(x=x)``. Motivation ========== + Keyword argument syntax can become needlessly repetitive and verbose. Consider the following call: @@ -38,6 +39,7 @@ noise. Rationale ========= + There are two ways to invoke a function with arguments: by position and by keyword. Keyword arguments confer many benefits by being explicit, thus increasing readability and minimising the risk of inadvertent transposition. On @@ -49,17 +51,20 @@ which would confer numerous benefits: Encourages use of named variables --------------------------------- + This syntax would encourage the use of named variables, thereby increasing readability (*explicit is better than implicit*) and reducing bugs from argument transposition. Reduces verbosity ----------------- + By minimising visual noise and in some cases lines of code, we can increase readability (*readability counts*). Encourages consistent variable names ------------------------------------ + A common problem is that semantically identical variables have different names depending on their contexts. This syntax would encourage authors to use the same variable name when calling a function as the argument name, which would increase @@ -67,6 +72,7 @@ consistency of variable names used and hence also *readability*. Applicability to dictionary construction ---------------------------------------- + This syntax offers a natural way to support this syntactic sugar for dictionary construction where a similar pattern occurs (dictionary keys are identical the names of the variables assigned as their values), ``{"x": x, "y": y}`` or @@ -90,6 +96,7 @@ You may instead write: Prior Art ========= + Python already possesses a very similar feature in f-string interpolation where ``f'{x=}'`` is effectively expanded to ``f'x={x}'`` [1]_. @@ -109,6 +116,7 @@ Outside of function invocation, even more languages have similar features: Applicability ============= + We analysed popular Python libraries using `this script `__ to compute: @@ -136,6 +144,7 @@ for 10-20% of all keyword argument uses. Proposed Syntax =============== + While this feature has been proposed on numerous occasions with several different forms [8]_ [9]_ [10]_ [11]_ [12]_, [13]_ we have opted to advocate for the ``f(x=)`` form for the following reasons: @@ -156,12 +165,14 @@ for the ``f(x=)`` form for the following reasons: Rejected Ideas ============== + Many alternative syntaxes have been proposed however no syntax other than ``f(=x)`` or ``f(x=)`` has garnered significant support. We here enumerate some of the most popular proposed alternatives and why we ultimately reject them. ``f(=x)`` ---------- + In favour of this form: * The prefix operator is more similar to the established ``*args`` and @@ -185,6 +196,7 @@ On the contrary: ``f(%x)`` or ``f(:x)`` or ``f(.x)`` ----------------------------------- + Several flavours of this syntax have been proposed with the prefix form substituting another character for ``=``. However, no such form has gained traction and choice of symbol seems arbitrary compared to ``=``. Additionally, @@ -194,6 +206,7 @@ f-string) or other languages (such as Ruby). ``f(a, b, *, x)`` ----------------- + On a few occasions the idea has been floated to borrow the syntax from keyword-only function definitions. This is less arbitrary than ``f(%x)`` or variants, but no less so than ``f(x=)``. @@ -219,6 +232,7 @@ the following objections were the most common: The syntax is ugly ------------------ + This objection is by far the most common. On the contrary, we argue that: * This objection is is subjective and many community members disagree. @@ -227,6 +241,7 @@ This objection is by far the most common. On the contrary, we argue that: The feature is confusing ------------------------ + We argue that: * Introducing new features typically has this temporary impact. @@ -239,6 +254,7 @@ We argue that: The feature is not explicit --------------------------- + This is based on a misunderstanding of the Zen of Python. Keyword arguments are fundamentally more explicit than positional ones where argument assignment is only visible at the function definition. On the contrary, the proposed syntactic @@ -265,12 +281,14 @@ highlighting the issue. Recommendations =============== + As with any other language feature, the programmer should exercise their own judgement about whether to use it in any given context. We do not recommend enforcing a rule to use the feature in all cases where it may be applicable. Reference Implementation ======================== + `A proposed implementation `_ for cpython has been provided by @Hels15. From 3465bc7b6c9ac5da97bbf0a850e4ec27374d6412 Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Sat, 2 Dec 2023 14:30:13 +0000 Subject: [PATCH 15/22] Address more comments --- peps/pep-0736.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index 94b2d7343a1..a1303037124 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -6,7 +6,6 @@ Sponsor: Guido van Rossum Discussions-To: https://discuss.python.org/t/syntactic-sugar-to-encourage-use-of-named-arguments/36217 Status: Draft Type: Standards Track -Content-Type: text/x-rst Created: 28-Nov-2023 Python-Version: 3.13 Post-History: 14-Oct-2023 @@ -326,5 +325,5 @@ References Copyright ========= -This document is placed in the public domain or under the CC0-1.0-Universal -license, whichever is more permissive. +This document is placed in the public domain or under the +CC0-1.0-Universal license, whichever is more permissive. From f34fa7149acc8425a1b0644ffa815638cfff68b5 Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Sat, 2 Dec 2023 14:33:39 +0000 Subject: [PATCH 16/22] Add new sections --- peps/pep-0736.rst | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index a1303037124..31048357a37 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -92,6 +92,16 @@ You may instead write: my_function(param1=, param2=) +Backwards Compatibility +======================= + +Only new syntax is added which was previously a syntactic error. No existing +syntax is modified. Changes are fully backwards compatible. + +Security Implications +===================== + +There are no security implications for this change. Prior Art ========= @@ -192,7 +202,6 @@ On the contrary: * Less similar to f-string syntax. * Less obvious that arbitrary expressions are invalid, e.g. ``f(=a+b)``. - ``f(%x)`` or ``f(:x)`` or ``f(.x)`` ----------------------------------- @@ -202,7 +211,6 @@ traction and choice of symbol seems arbitrary compared to ``=``. Additionally, there is less precedent in terms of existing language features (such as f-string) or other languages (such as Ruby). - ``f(a, b, *, x)`` ----------------- @@ -220,7 +228,6 @@ However, we object that: if not, then an arbitrary grouping is enforced between different types of keyword arguments. - Objections ========== From eb071f1aca4148cacd74a959c816263084ddc1ec Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Sat, 2 Dec 2023 15:07:42 +0000 Subject: [PATCH 17/22] Add @Rousav to CODEOWNERS --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3bfda92166e..f760c8188c8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -613,7 +613,7 @@ peps/pep-0732.rst @Mariatta peps/pep-0733.rst @encukou @vstinner @zooba @iritkatriel peps/pep-0734.rst @ericsnowcurrently peps/pep-0735.rst @brettcannon -peps/pep-0736.rst @gvanrossum +peps/pep-0736.rst @gvanrossum @Rosuav peps/pep-0737.rst @vstinner # ... # peps/pep-0754.rst From 9fb89307377ae6f456501a1ebb95a90d5e633f3f Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Sat, 2 Dec 2023 15:53:01 +0000 Subject: [PATCH 18/22] Add How to Teach This --- peps/pep-0736.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index 31048357a37..9e74e54ec62 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -103,6 +103,15 @@ Security Implications There are no security implications for this change. +How to Teach This +================= + +Programmers may learn about this feature as an optional abbreviated syntax where +keyword arguments are taught. The +`Python Glossary `__ and +`Tutorial `__ +may be updated accordingly. + Prior Art ========= From d9972d3309430e9494be01a9ae7765e11fd2797e Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Sat, 2 Dec 2023 16:01:58 +0000 Subject: [PATCH 19/22] More descriptive title --- peps/pep-0736.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index 9e74e54ec62..7daa2241f7a 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -1,5 +1,5 @@ PEP: 736 -Title: Syntactic sugar for named arguments +Title: Shorthand syntactic sugar for keyword arguments at invocation Author: Joshua Bambrick , Chris Angelico Sponsor: Guido van Rossum From f1bf3cef16600f814d687e1f8d96fc571528c48f Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Sat, 2 Dec 2023 17:00:47 +0000 Subject: [PATCH 20/22] Simplify title --- peps/pep-0736.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index 7daa2241f7a..f3364587c00 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -1,5 +1,5 @@ PEP: 736 -Title: Shorthand syntactic sugar for keyword arguments at invocation +Title: Shorthand syntax for keyword arguments at invocation Author: Joshua Bambrick , Chris Angelico Sponsor: Guido van Rossum From e3d6c16e4e4fb93407253abb7145c1bf656b9d9d Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Sat, 2 Dec 2023 18:03:30 +0000 Subject: [PATCH 21/22] Expand on specification --- peps/pep-0736.rst | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index f3364587c00..391f726c32b 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -82,21 +82,36 @@ literals is an open question out of the scope of this PEP. Specification ============= -The proposed syntactic sugar is very simple. Instead of: +We propose to introduce syntactic sugar such that, if the value of a keyword +argument is omitted from a function invocation, the argument's value is inferred +to be the variable matching that name at the invocation scope. + +For example, the function invocation: :: - my_function(param1=param1, param2=param2) + my_function(my_first_variable=, my_second_variable=, my_third_variable=) -You may instead write: +Will be interpreted exactly equivalently to following in existing syntax: :: - my_function(param1=, param2=) + my_function( + my_first_variable=my_first_variable, + my_second_variable=my_second_variable, + my_third_variable=my_third_variable, + ) + +If no variable matches that name in the invocation scope, a ``NameError`` is +raised in an identical manner as would be with the established expanded syntax. + +This proposal only pertains to function invocations; function defintions are +unaffected by the syntax change. All existing valid syntax is unchanged. Backwards Compatibility ======================= -Only new syntax is added which was previously a syntactic error. No existing -syntax is modified. Changes are fully backwards compatible. +Only new syntax is added which was previously syntactically erroreous. No +existing valid syntax is modified. As such, the changes proposed are fully +backwards compatible. Security Implications ===================== From a415683a4662114b48b99395e47e91776154bc9b Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Sat, 2 Dec 2023 18:37:10 +0000 Subject: [PATCH 22/22] Minor language and formatting tweaks --- peps/pep-0736.rst | 51 ++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index 391f726c32b..4b54fd474a4 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -72,12 +72,12 @@ consistency of variable names used and hence also *readability*. Applicability to dictionary construction ---------------------------------------- -This syntax offers a natural way to support this syntactic sugar for dictionary -construction where a similar pattern occurs (dictionary keys are identical the -names of the variables assigned as their values), ``{"x": x, "y": y}`` or -``dict(x=x, y=y)``. With this feature, this can now also be trivially written as -``dict(x=, y=)``. Whether to further support similar syntax in dictionary -literals is an open question out of the scope of this PEP. +This syntax can be applied to dictionary construction where a similar +pattern frequently occurs (where dictionary keys are identical the names of the +variables assigned as their values), ``{"x": x, "y": y}`` or ``dict(x=x, y=y)``. +With this feature, this can now also be trivially written as ``dict(x=, y=)``. +Whether to further support similar syntax in dictionary literals is an open +question out of the scope of this PEP. Specification ============= @@ -133,7 +133,7 @@ Prior Art Python already possesses a very similar feature in f-string interpolation where ``f'{x=}'`` is effectively expanded to ``f'x={x}'`` [1]_. -Several modern languages offer similar features during function invocation, +Several modern languages provide similar features during function invocation, sometimes referred to as 'punning'. For example: * In Ruby, ``f(x:, y:)`` is syntactic sugar for ``f(x: x, y: y)`` [2]_. @@ -141,7 +141,7 @@ sometimes referred to as 'punning'. For example: * In SystemVerilog, ``(.mult, .mop1, .data);`` is syntactic sugar for ``(.mult(mult), .mop1(mop1), .data(data));`` [4]_. -Outside of function invocation, even more languages have similar features: +Beyond function invocation specifically, more languages offer similar features: * In OCaml, ``let+ x in …`` is syntactic sugar for ``let+ x = x in …`` [5]_. * In JavaScript, ``{ x, y }`` is syntactic sugar for ``{x: x, y: y}`` [6]_. @@ -154,10 +154,11 @@ We analysed popular Python libraries using `this script `__ to compute: -* Number of keyword arguments were of the form ``f(x=x)`` at invocation. -* Percentage of keyword arguments had the form ``f(x=x)`` at invocation. -* Number of lines of code could be saved by using this syntactic sugar to - reduce the need for line wraps. +* The number of keyword arguments were of the form ``f(x=x)`` at invocation. +* The percentage of keyword arguments which had the form ``f(x=x)`` at + invocation. +* The number of lines of code which could be saved by using this syntactic sugar + to reduce the need for line wraps. ===================================================================== ================ ============== =============== ===================== Statistic `cpython `__ `numpy `__ `pandas `__ `scikit-learn `__ @@ -172,8 +173,8 @@ Lines saved 290 .. _c: https://github.com/pandas-dev/pandas/pull/55744/ .. _d: https://github.com/scikit-learn/scikit-learn/pull/27680/ -Based on this, the ``f(x=x)`` keyword argument pattern is widespread, accounting -for 10-20% of all keyword argument uses. +Based on this, we note that the ``f(x=x)`` keyword argument pattern is +widespread, accounting for 10-20% of all keyword argument uses. Proposed Syntax =============== @@ -194,7 +195,7 @@ for the ``f(x=)`` form for the following reasons: communicates "here is a parameter, go find its argument" which is more appropriate given the semantics of named arguments. * `A poll of Python developers `__ - indicates that this is the most popular syntax of those proposed. + indicates that this is the most popular syntax among those proposed. Rejected Ideas ============== @@ -221,7 +222,7 @@ On the contrary: this feature to shout its presence any more than a typical named argument. By the time we read to the ``=`` it is clear that the value is filled in automatically just as the value is clear in the typical keyword argument case. -* Semantically, this form communicates 'here is a value, fill in the parameter' +* Semantically, this form communicates 'here is a value, fill in the parameter'. * which is not what we want to convey. * Less similar to f-string syntax. * Less obvious that arbitrary expressions are invalid, e.g. ``f(=a+b)``. @@ -231,9 +232,9 @@ On the contrary: Several flavours of this syntax have been proposed with the prefix form substituting another character for ``=``. However, no such form has gained -traction and choice of symbol seems arbitrary compared to ``=``. Additionally, -there is less precedent in terms of existing language features (such as -f-string) or other languages (such as Ruby). +traction and the choice of symbol seems arbitrary compared to ``=``. +Additionally, there is less precedent in terms of existing language features +(such as f-string) or other languages (such as Ruby). ``f(a, b, *, x)`` ----------------- @@ -256,8 +257,8 @@ Objections ========== There are only a few hard objections to the introduction of this syntactic -sugar. Most of those not in favour of this feature are simply in the camp of 'I -wouldn't use it'. However over the extensive conversations about this feature, +sugar. Most of those not in favour of this feature are in the camp of 'I +wouldn't use it'. However, over the extensive conversations about this feature, the following objections were the most common: The syntax is ugly @@ -266,7 +267,7 @@ The syntax is ugly This objection is by far the most common. On the contrary, we argue that: * This objection is is subjective and many community members disagree. -* This is already established syntax used in f-strings. +* A nearly-identical syntax is already established for f-strings. * Programmers will, as ever, adjust over time. The feature is confusing @@ -274,7 +275,7 @@ The feature is confusing We argue that: -* Introducing new features typically has this temporary impact. +* Introducing new features typically has this impact temporarily. * The syntax is very similar to the established ``f'{x=}'`` syntax. * The feature and syntax are familiar from other popular modern languages. * The expansion of ``x=`` to ``x=x`` is in fact a trivial feature and inherently @@ -290,8 +291,8 @@ fundamentally more explicit than positional ones where argument assignment is only visible at the function definition. On the contrary, the proposed syntactic sugar contains all the information as is conveyed by the established keyword argument syntax but without the redundancy. Moreover, the introduction of this -syntactic sugar incentivises use of keyword arguments, making practical Python -code more explicit. +syntactic sugar incentivises use of keyword arguments, making typical Python +codebases more explicit. The feature adds another way of doing things --------------------------------------------