emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: RFC: String interpolation


From: Joost Kremers
Subject: Re: RFC: String interpolation
Date: Thu, 08 Dec 2016 15:43:04 +0100
User-agent: mu4e 0.9.18; emacs 25.1.50.3


On Thu, Dec 08 2016, Clément Pit--Claudel wrote:
Hi all,

Many languages are gaining literal string interpolations features of late (the latest example is Python; see https://www.python.org/dev/peps/pep-0498/). The TL;DR is that in Python 3.6 one can write this:

    value = 1.3
    print(f'The value is {value + 1:.2f}.')

This prints "The value is 2.30." Plenty of other languages have similar features.

It would be nice if Emacs offered something similar out of the box. It could be a reader macro, but a plain macro would do just as well, and indeed it's relatively easy to code something up (I attached an example implementation).

That's definitely something that would be great to have. I'm not sure I would have chosen the same syntax, though.

With the attached fmt.el, you can write things like this:

    (let ((a 12) (b 15))
      (fmt "$a + $b = $(+ a b)"))
    ⇒ "12 + 15 = 27"

That syntax looks great to me, and I don't really see any reason to make it much more complex.

    (let ((password "letmein"))
      (fmt "The password is ${password}"))
    ⇒ "The password is letmein"

Why the {}? Is there any context in which $<expr> is ambiguous such that ${<expr>} is needed to resolve it? Other than vectors, I mean, since you use [] for an optional format spec? Personally, I'd just say that vectors need to be written as (vector ...). []-vectors are constants anyway, so in such cases you might as well write the string directly.

    (let ((n 25) (price-per-unit 10.5))
(fmt "The price for $n units is €$[%.2f](* n price-per-unit)"))
    ⇒ "The price for 25 units is €262.50"

    (fmt "Here's a symbol: '${'a}; "
         "and a padded number: ‘$[%-6.3f]{1}’.")
    ⇒ "Here's a symbol: 'a; and a padded number: ‘1.000 ’."

    (fmt "Welcome to Emacs! "
"Press $[where-is]{'help-with-tutorial} to open the tutorial.")
    ⇒ "Welcome to Emacs! Press C-h t to open the tutorial."

    (fmt "Today is $[date|%Y-%m-%d](current-time).")
    ⇒ "Today is 2016-12-07."

I honestly must say I find these last two very confusing. I would simply write:

(fmt "Today is $(format-time-string \"%Y-%m-%d\" current-time)).")

The escaped double quotes are not perfect, but I find this much more readable and more pleasant to look at.

Perhaps you should also look at abo-abo's hydra package, since he does basically the same thing in his hydra doc strings. AFAICT, it works this way: % starts a placeholder, ` marks the start of the expression. If the expression is an s-expr, you can leave out the `. So your examples would be:


    (let ((a 12) (b 15))
      (fmt "$a + $b = $(+ a b)"))

 (fmt "%`a + %`b = %(+ a b)")

    (let ((password "letmein"))
      (fmt "The password is ${password}"))

 (fmt "The password is %`password")

    (let ((n 25) (price-per-unit 10.5))
(fmt "The price for $n units is €$[%.2f](* n price-per-unit)"))

(fmt "The price for %`n units is €%.2f(* n price-per-unit)")
    (fmt "Here's a symbol: '${'a}; "
         "and a padded number: ‘$[%-6.3f]{1}’.")

 (fmt "Here's a symbol: '%`'a; "
      "and a padded number: ‘%-6.3f`1’.")

(Though here you might as well forego fmt altogether).

    (fmt "Welcome to Emacs! "
"Press $[where-is]{'help-with-tutorial} to open the tutorial.")

 (fmt "Welcome to Emacs! "
"Press %(fmt-whereis 'help-with-tutorial) to open the tutorial.")

This one would require `fmt-whereis' to be an alias for your `fmt--printers-whereis'.

    (fmt "Today is $[date|%Y-%m-%d](current-time).")

(fmt "Today is %(format-time-string \"%Y-%m-%d\" (current-time)).")

One addition might be to let %n stand for the value of the symbol n, and only interpret what immediately follows % as a format spec when there is also a backtick. So

 (fmt "The value of x is: %x")

would refer to the value of the variable s, while

 (fmt "The value of x is: %x`x")

would format the value of x in hexadecimal.

So, summarized:

- %<expr> : format the value of <expr> where <expr> can be a symbol or an s-expr, possibly also a vector or a string (somewhat superfluously...)

- %<fspec>`<expr> : format <expr> according to <fspec>.

Of course, It might be easier to use a different symbol for %, I don't know. I have nothing against using $.

fmt expands the strings at compile time (so they must be constant strings).

I've occasionally appreciated the fact that I can pass a dynamically created format string to `format'... ;-) Ok, I could always use `format' in such cases.


--
Joost Kremers
Life has its moments



reply via email to

[Prev in Thread] Current Thread [Next in Thread]