
On Mon, Jul 20, 2015 at 9:52 PM, Eric V. Smith <eric@trueblade.com> 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.
I wonder if we could let the parser do this? consider f'x:{ as one token and so on?
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'])
Oooh, this is very unfortunate. I cannot support this. Treating b[c] as b['c'] in a "real" format string is one way, but treating it that way in an expression is just too weird.
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".
Alas. And this is probably why we don't already have this feature.
Not sure what you mean by "implicit merging" -- if you mean literal concatenation (e.g. 'foo' "bar" == 'foobar') then I think it should be allowed, just like we support mixing quotes and r''.
If I understand it, I think the concern is:
f'{a}{b}' 'foo{}' f'{c}{d}'
would need to become: f'{a}{b}foo{{}}{c}{d}'
So you have to escape the braces in non-f-strings when merging strings and any of them are f-strings, and make the result an f-string. But I think that's the only complication.
That's possible; another possibility would be to just have multiple .format() calls (one per f'...') and use the + operator to concatenate the pieces. -- --Guido van Rossum (python.org/~guido)