-
Notifications
You must be signed in to change notification settings - Fork 211
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
Distinguish repr
away from str
and use it for nested types
#536
Comments
Let me reiterate my main point very briefly:
|
Thanks, I didn't realize that. Looking at the Starlark spec, the precise behavior of str and repr for each type does seem to be underspecified. That said, I'm not sure we can reasonably change the behavior of repr for built-in types at this point; we could ask our friends on the Bazel team (@brandjon @tetromino) to evaluate how much damage this change would cause in Google's large corpus. For user-defined types, we could define a Reprable interface, analogous to fmt.GoStringer method, which would allows a type to define a variant string representation for But before we add more API, I would like to have a more coherent understanding of the theory of repr vs str and any invariants that we should be striving to establish or maintain. |
Thanks for consideration. The current state is that I think this is the summary of the philosophy of Python:
The first step might be to formalize the above (because it does fully hold at the moment) a. b. And the next step would be to add the ability to override the latter one through a new interface. |
One more thing regarding this:
For any implementers of custom types, this surely had to hold true as the following:
(because what else were they supposed to apply?) So this makes it even more attractive to define the existing |
Also important to mention: |
Right, but those delegations are straightforward and unambiguous, and orthogonal to the question of the desired behavior of str and repr. |
I have implemented my suggestion - it's actually really straightforward and doesn't modify any existing behavior or API (no effect on unittests), just replaces the checks for "is it the Of course no obligation to do anything with this code, it just also illustrates my proposal well. But do let me know if I should open a pull request. Any suggestions for how to name the interface are very welcome; consider the current naming mostly a placeholder. |
Mm I should note - the commit does affect the behavior of the bytestring type in some cases. I was debating back and forth whether it should be string-like in this context because this distinction is applied inconsistently at the moment. This may need to be formalized first as well. |
So pushed an alternate commit that doesn't touch bytestrings and should actually have 0 effect on existing behavior. |
Bazel's Starlark (very similarly to Python) has a separation between
str
andrepr
and consistently usesrepr
for nested objects.For example, this always holds for lists, no matter what
foo
is:However in starlark-go
str
andrepr
are backed by the exact same interface:starlark-go/starlark/library.go
Line 963 in e6e8e7c
starlark-go/starlark/library.go
Line 1096 in e6e8e7c
With the only 2 exceptions to this being hardcoded - only strings and bytestrings use a different code path inside
str
that doesn't simply usevalue.String()
.So, except for strings, it is basically
repr([foo]) == '[' + str(foo) + ']'
This can lead to some limitations and confusion.
Consider a
Label
object like in Bazel, per issue #535.For Bazel compatibility, the following would need to hold:
print(Label("//:hi"))
prints//:hi
print([Label("//:hi")])
prints[Label("//:hi")]
With starlark-go, I am pretty sure there is only one shared implementation allowed for
str
andrepr
so I would have to choose one of the below options if I were to try to implement such aLabel
, both very suboptimal:print(Label("//:hi"))
printsLabel("//:hi")
print([Label("//:hi")])
prints[Label("//:hi")]
print(Label("//:hi"))
prints//:hi
print([Label("//:hi")])
prints[//:hi]
Actually we can simplify this even further and don't need to talk about "labels". It is not even possible to implement an object like the native
str
. You are forced to choose between one of these suboptimal options:print(MyStr("hi"))
prints"hi"
- badprint([MyStr("hi")])
prints["hi"]
- goodprint(MyStr("hi"))
printshi
- goodprint([MyStr("hi")])
prints[hi]
- badI think at the very least, the
repr
-like behavior would need to be chosen for the list case, rather than thestr
-like behavior, even if the two aren't allowed to have a separate interface that backs them.The text was updated successfully, but these errors were encountered: