
On 07/20/2015 03:52 PM, Eric V. Smith wrote:
On 07/20/2015 03:22 PM, Guido van Rossum wrote:
> So the idea is that > f'x:{a.x} y:{y}' > would translate to bytecode that does: > 'x:{a.x} y:{y}'.format(a=a, y=y) > > Correct?
That's exactly what I had in mind, at least. Indexing is supported in format strings too, so f'{a[1]}' also becomes '{a[1]}'.format(a=a), but I don't think there are any other strange cases here. I would vote for f'{}' or f'{0}' to just be a SyntaxError.
+1 on that last sentence. But I prefer a slightly different way of implementing (see my reply to Eric).
Right. And following up here to that email:
I was more thinking of translating that specific example to
'x:{} y:{}'.format(a.x, y)
which avoids some of the issues your example is trying to clarify.
That is better. The trick is converting the string "a.x" to the expression a.x, which should be easy enough at compile time.
It would still probably be best to limit the syntax inside {} to exactly what regular .format() supports, to avoid confusing users.
The expressions supported by .format() are limited to attribute access and "indexing". We just need to enforce that same restriction here.
Though the consistency argument can be played both ways -- supporting absolutely anything that is a valid expression would be more consistent with other places where expressions occur. E.g. in principle we could support operators and function calls here.
It would be easiest to not restrict the expressions, but then we'd have to maintain that restriction in two places.
And now that I think about it, it's somewhat more complex than just expanding the expression. In .format(), this: '{a[0]}{b[c]}' is evaluated roughly as format(a[0]) + format(b['c'])
So to be consistent with .format(), we have to fully parse at least the indexing out to see if it looks like a constant integer or a string.
So given that, I think we should just support what .format() allows, since it's really not quite as simple as "evaluate the expression inside the braces".
And thinking about it yet some more, I think the easiest and most consistent thing to do would be to translate it like: f'{a[0]}{b[c]}' == '{[0]}{[c]}'.format(a, b) So: f'api:{sys.api_version} {a} size{sys.maxsize}' would become either: f'api:{.api_version} {} size{.maxsize}'.format(sys, a, sys) or f'api:{0.api_version} {1} size{0.maxsize}'.format(sys, a) The first one seems simpler. The second probably isn't worth the micro-optimization, and it may even be a pessimization. Eric.