[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