-
Notifications
You must be signed in to change notification settings - Fork 157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Specify evaluation order of function arguments #13
Comments
I think that's a good solution. Buildifier can automatically move the arguments (order should be: positional, then named, then |
Stylistically speaking, I think user code should not rely on the order of argument evaluation (except of course that it's deterministic). The only circumstance in which I could imagine encouraging such a dependency is if that order is left-to-right, as in Starlark-in-Java. I also think it's rare that this will come up in practice. I've always understood the calling semantics of Python functions (at least in Python 3) to be: 1) gather the positional args (including *args) and populate the params, then 2) gather the keyword args (including **kargs) and populate more params. This order is important to understanding how conflicts are handled -- you'd get different results if you populated the keywords first, then skipped over params that were already filled in when populating positionals. So it doesn't surprise me that this separation is reflected in Python 3's evaluation order. I don't feel super strongly about prohibiting keyword args after *args in the caller. Though I guess that would prohibit calls like
|
A style rule we can all agree on, in any language.
How would you declare such a function? I think you would have to use **kwargs for the optional sep parameter, which is quite unnatural. |
Indeed, that would be an awkward situation. But I think if the aim was to provide that interface to the caller, then the awkwardness would not deter a user from writing that function definition. |
I think the simplest is to forbid it.
|
I think you are proposing that we statically disallow
If you plan to make Buildifier replace |
On a related note, this code: I think it would be simpler if we forced the argument order fully:
This would allow an implementation to have 4 fields (one for each kind of argument), and not worry about relative order of items between the different kinds of arguments. |
That also sounds good to me. |
When we removed support for keyword-only parameters, I had the notion that at some point in the future, when Python 2 syntactic compatibility is no longer a goal, we could add them back. I'm ok with the extra restrictions described in this thread, but we should ask whether we intend to relax these constraints later on (well after 1.0). If so, it may affect what assumptions interpreter authors rely on today. I used to think that ideally Starlark would support the same parameter and argument features as Python 3. But it turns out that's a moving target. More recent versions of Python 3 support multiple unpacking expressions, and a draft pep introduces positional-only parameters [1]. I agree that some call syntaxes like Allowing *args/**kargs only at the end (for both calls and definitions) is similar to how C-style languages put varargs at the end. It's easier to represent and work with in the interpreter. It avoids catering to use cases we don't fully understand or endorse. I do wish we had an easy way to support both positional-only params and keyword-only params, but it's probably not worth the complication. [1] I laughed out loud when I saw the token separating positional-only params from the rest. |
Keyword-only syntax is for the definition site. The proposal here is for the call site. I don't think it will interact. Whether an argument is optionally named or mandatory named makes no difference on the call site. I still expect we'll want keyword-only arguments at some point (especially since we use that in rules and other builtins). |
Added a fix to buildifier: |
Wait, this feature was removed from Bazel? I just spent two hours working on google/starlark-go#62! D'oh. Should I assume then that any uses I encounter with Blaze are neglected BUILD files? |
Sadly yes, keyword-only params in function definitions were removed because they aren't syntactically supported in Python 2. IIRC the only thing that can come after |
I see. Why does Python2 syntax matter? |
It's a design decision to keep Starlark in the intersection of Python 2 and Python 3 syntax. This is so we can imperfectly benefit from existing Python tooling, until Starlark tooling is more mature. We could revisit this later on. |
For a long time, Python 2 syntactic compatibility was critical. |
Marking this issue as approved (#13 (comment)). For discussion about Python 2 syntax, see #27 |
f(*args, k=v) is a now an error. Use f(k=v, *args). Arguments are evaluated left-to-right, as in Python2 (but not Python3). See bazelbuild/starlark#13 for spec change. Change-Id: I267823df2cbae55a1edac4a5627a04b3e9f82c94
The spec says:
Marking as done. |
See bazelbuild/starlark#13 PiperOrigin-RevId: 342319595
f(*args, k=v) is a now an error. Use f(k=v, *args). Arguments are evaluated left-to-right, as in Python2 (but not Python3). See bazelbuild/starlark#13 for spec change.
Reported by @alandonovan
The text was updated successfully, but these errors were encountered: