Skip to content
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

dict.update should return None, not self #18

Closed
alandonovan opened this issue Nov 29, 2018 · 6 comments
Closed

dict.update should return None, not self #18

alandonovan opened this issue Nov 29, 2018 · 6 comments

Comments

@alandonovan
Copy link
Contributor

In .bzl files, the expression dict(a=1).update(b=2) evaluates to {a: 1, b: 2} but according to
https://github.com/bazelbuild/starlark/blob/master/spec.md#dictupdate
it should return None.

Both Pythons and Starlark-in-Go return None:

$ python # 2 or 3

x = {}
x.update(k=1)
x
{'k': 1}

$ starlark # in Go

x = {}
x.update(k=1)
x
{"k": 1}

The Java standalone interpreter gives a strange error --- I have no idea what it means:
% blaze-bin/third_party/bazel/src/main/java/com/google/devtools/skylark/Skylark

x = {}
x.update(k=1)
parameter 'other' has no default value, in method call update(int k) of 'dict'

Googlers: see L23 of dart_dev_ctx.bzl in cr/223363742 for a real-world example.

@laurentlb
Copy link
Contributor

Thanks!
That's a bug in Bazel.

@brandjon
Copy link
Member

brandjon commented Nov 29, 2018 via email

@laurentlb
Copy link
Contributor

Error message is bad, but the .update() method doesn't accept keyword arguments: https://docs.bazel.build/versions/master/skylark/lib/dict.html#update

If you do: x.update({"k": 1}), you'll see that update() returns None as expected.

cr/223363742 boils down to:

SomeInfo = provider(
    fields = {
        "...": "...",
    }.update(other_fields),

This is confusing, because update returns None. In other words, the dictionary is created, modified and thrown away.

@alandonovan
Copy link
Contributor Author

Error message is bad, but the .update() method doesn't accept keyword arguments:
https://docs.bazel.build/versions/master/skylark/lib/dict.html#update

So it seems like the resolution is to make the Java impl and its doc match what the spec doc says:
https://github.com/bazelbuild/starlark/blob/master/spec.md#dictupdate

This is confusing, because update returns None. In other words, the dictionary is created, modified and thrown away.

Yes, it's an easy trap to fall into. Do you have a lint check for it? The deprecated {} + {} wasn't so bad after all. :(

@laurentlb
Copy link
Contributor

make the Java impl and its doc match what the spec doc says

Right. Good enough, it's just a new feature and not a breaking change.

In the future, we can indeed extend the linter to catch this kind of things. Right now, we focus on the deprecated features, and help users migrate their code.

bazel-io pushed a commit to bazelbuild/bazel that referenced this issue Mar 18, 2019
Closes [dict.update should return None, not self #18](bazelbuild/starlark#18)

dict.update() method should now accept keyword args just like dict(...)

**Example of usage:**
```
>> a = dict(a=1)
..
>> a.update(b=2)
..
None
>> a.update({'c': 3})
..
None
>> a
..
{"a": 1, "b": 2, "c": 3}
```

Closes #7684.

PiperOrigin-RevId: 239018051
@laurentlb
Copy link
Contributor

Fixed in Bazel

bazel-io pushed a commit to bazelbuild/bazel that referenced this issue Mar 18, 2019
In particular, add tests with both a positional argument and keyword arguments (to show that the keyword arguments win).

bazelbuild/starlark#18

RELNOTES: None.
PiperOrigin-RevId: 239024409
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants