[Python-ideas] String interpolation for all literal strings
Guido van Rossum
guido at python.org
Fri Aug 7 12:13:13 CEST 2015
On Fri, Aug 7, 2015 at 11:50 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On 7 August 2015 at 19:03, Nathaniel Smith <njs at pobox.com> wrote:
> > On Fri, Aug 7, 2015 at 1:49 AM, Guido van Rossum <guido at python.org>
> wrote:
> >> On Fri, Aug 7, 2015 at 9:33 AM, Nick Coghlan <ncoghlan at gmail.com>
> wrote:
> >>>
> >>> We could potentially make f-strings translation friendly by
> >>> introducing a bit of indirection into the f-string design: an
> >>> __interpolate__ builtin, along the lines of __import__.
> >>
> >>
> >> This seems interesting, but doesn't it require sys._getframe() or
> similar
> >> again? Translations may need to reorder variables. (Or even change the
> >> expressions? E.g. to access odd plurals?)
> >>
> >> The sys._getframe() requirement (if true) would kill this idea
> thoroughly
> >> for me.
> >
> > AFAICT sys._getframe is unneeded -- I understand Nick's suggestion to
> > be that we desugar f"..." to:
> >
> > __interpolate__("...", locals(), globals())
> >
> > with the reference to __interpolate__ resolved using the usual lookup
> > rules (locals -> globals -> builtins).
>
> Not quite. While I won't be entirely clear on Eric's latest proposal
> until the draft PEP is available, my understanding is that an f-string
> like:
>
> f"This interpolates \{a} and \{b}"
>
> would currently end up effectively being syntactic sugar for a
> formatting operation like:
>
> "This interpolates " + format(a) + " and " + format(b)
>
> While str.format itself probably doesn't provide a good signature for
> __interpolate__, the essential information to be passed in to support
> lossless translation would be an ordered series of:
>
> * string literals
> * (expression_str, value, format_str) substitution triples
>
> Since the fastest string formatting operation we have is actually
> still mod-formatting, lets suppose the default implementation of
> __interpolate__ was semantically equivalent to:
>
> def __interpolate__(target, expressions, values, format_specs):
> return target % tuple(map(format, values, format_specs)
>
> With that definition for default interpolation, the f-string above
> would be translated at compile time to the runtime call:
>
> __interpolate__("This interpolates %s and %s", ("a", "b"), (a, b),
> ("", ""))
>
> All of those except for the __interpolate__ lookup and the (a, b)
> tuple would then be stored on the function object as constants.
>
> An opt-in translation interpolator might then look like:
>
> def __interpolate__(target, expressions, values, format_spec):
> if not all(expr.isidentifier() for expr in expressions):
> raise ValueError("Only variable substitions are permitted
> for il8n interpolation")
> if any(spec for spec in format_specs):
> raise ValueError("Format specifications are not permitted
> for il8n interpolation")
> catalog_str = target % tuple("${%s}" % expr for expr in
> expressions)
> translated = _(catalog_str)
> values = {k:v for k, v in zip(expressions, values)}
> return string.Template(translated).safe_substitute()
>
> The string extractor for the il8n library providing that
> implementation would also need to know to do the transformation from
> f-string formatting to string.Template formatting when generating the
> catalog strings
>
OK, that sounds reasonable, except that translators need to control
substitution order, so s % tuple(...) doesn't work. However, if we use
s.format(...) we can use "This interpolates {0} and {1}", and then I'm
satisfied. (Further details of the signature of __interpolate__ TBD.)
--
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20150807/622c99b3/attachment-0001.html>
More information about the Python-ideas
mailing list