* RFC: String interpolation
@ 2016-12-08 1:13 Clément Pit--Claudel
2016-12-08 8:27 ` Andreas Schwab
` (5 more replies)
0 siblings, 6 replies; 86+ messages in thread
From: Clément Pit--Claudel @ 2016-12-08 1:13 UTC (permalink / raw)
To: Emacs developers
[-- Attachment #1.1.1: Type: text/plain, Size: 2750 bytes --]
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).
With the attached fmt.el, you can write things like this:
(let ((a 12) (b 15))
(fmt "$a + $b = $(+ a b)"))
⇒ "12 + 15 = 27"
(let ((password "letmein"))
(fmt "The password is ${password}"))
⇒ "The password is letmein"
(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."
There's also an fmt-message macro that just calls ‘message’ on the interpolated string. The prototype that I attached supports a range of placeholders:
* $a, $a-b, $abc-123-def expand to the values of the corresponding variables
* ${a}, ${123}, ${[x y z]}, ${(+ 1 2)} expand to the value of the corresponding ELisp forms
* $(+ 1 2), $(buffer-file-name), $(current-column) are a shorthand for ${(…)}
* $[%.2f](+ 1 2) and $[%S]{'(1 2 3)} feed the result of evaluation through format, with the given specifier
* $[whereis]{…}' and $[date|%Y-%m-%d]{…} feed the result of evaluating "…" through a custom formatting function, with an optional format specifier
* $$ produces a literal $ sign
fmt expands the strings at compile time (so they must be constant strings). For example, (fmt "$a + $b = $[%.2f](+ a b)") more or less expands to
(concat (fmt--print a) " + " (fmt--print b) " = " (fmt--print (+ a b) 'format "%.2f"))
(fmt--print is a thin wrapper that sets print-depth and print-length).
I'd like some feedback on the following:
* Should this go into MELPA, ELPA, or core?
* What do we think of the syntax? An alternative to $[…]{…} would be ${…}%… (which is a bit trickier to parse, and makes it hard to have custom formatters).
Cheers,
Clément.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.1.2: fmt.el --]
[-- Type: text/x-emacs-lisp; name="fmt.el", Size: 5277 bytes --]
;;; fmt.el --- Macro-based string interpolation library -*- lexical-binding: t; -*-
;; Copyright (C) 2016 Clément Pit-Claudel
;; Author: Clément Pit-Claudel <clement.pitclaudel@live.com>
;; Keywords: convenience, extensions
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(defconst fmt--sigil ?$)
;;; Printing utilities
(defun fmt--print (e &optional printer format-sequence)
"Print E with PRINTER according to optional FORMAT-SEQUENCE.
With no FORMAT-SEQUENCE, use princ. With no PRINTER, use FORMAT."
(let ((print-quoted t)
(print-length nil)
(print-level nil))
(if format-sequence
(funcall (or printer 'format) format-sequence e)
(prin1-to-string e t))))
;;; Specialized printers
(defun fmt--printers-str (_format-string v)
"Format V as a string, but return \"\" if V is nil."
(if v (format "%s" v) ""))
(defun fmt--printers-whereis (_format-string function)
"Show a keybinding for FUNCTION."
(substitute-command-keys (concat "\\[" (symbol-name function) "]")))
(defvar fmt--printers-alist '(("str" . fmt--printers-str)
("date" . format-time-string)
("where-is" . fmt--printers-whereis))
"An alist mapping printer names to formatting functions.
Each formatting function should take a value and a format
sequence, and return a string.")
(defun fmt--get-printer (name)
"Find printer for NAME."
(or (cdr (assoc name fmt--printers-alist))
(error "Unrecognized printer: %S" name)))
;;; Compiling format strings
(defun fmt--read-delimited ()
"Read a string enclosed in a pair of delimiters."
(let ((start (point)))
(forward-list)
(buffer-substring-no-properties (1+ start) (1- (point)))))
(defun fmt--read-format-sequence ()
"Read a []-delimited format sequence, such as `[.2f]'."
(when (eq (char-after) ?\[)
(let ((str (fmt--read-delimited)))
(if (string-match-p "^%" str)
(list ''format str)
(let* ((parts (split-string str "|")))
(list (list 'quote (fmt--get-printer (car parts)))
(mapconcat #'identity (cdr parts) "|")))))))
(defun fmt--read-braces ()
"Read a {}-delimited form, such as `{12}'."
(pcase-let* ((start (point))
(expr (fmt--read-delimited))
(`(,obj . ,count) (read-from-string expr)))
(prog1 obj
(unless (= count (length expr))
(error "Expecting \"}\", but got %S instead"
(buffer-substring (+ start count 1) (point-max)))))))
(defun fmt--read-var-name ()
"Read an alphanumeric+dashes variable name, such as `ab0-cd'."
(let ((start (point)))
(if (> (skip-chars-forward "-[:alnum:]") 0)
(intern (buffer-substring-no-properties start (point)))
(error "Invalid fmt string when reaching %S"
(buffer-substring (point) (point-max))))))
(defun fmt--read ()
"Read one form, a lone sigil, or a variable, plus an optional format.
Returns a list (FORM PRINTER FORMAT-SEQUENCE)."
(let* ((format-sequence (fmt--read-format-sequence))
(next-char (char-after)))
(apply #'list
(cond
((equal next-char ?\() (read (current-buffer)))
((equal next-char ?\{) (fmt--read-braces))
((equal next-char fmt--sigil) (forward-char) (char-to-string fmt--sigil))
(t (fmt--read-var-name)))
format-sequence)))
(defun fmt--compile (expr)
"Parse and compile a format expression EXPR."
(with-temp-buffer
(insert expr)
(goto-char (point-min))
(let ((chunks nil)
(str-start (point))
(sigil-str (char-to-string fmt--sigil)))
(while (search-forward sigil-str nil t)
(let ((str (buffer-substring-no-properties str-start (1- (point)))))
(push str chunks)
(push `(fmt--print ,@(fmt--read)) chunks)
(setq str-start (point))))
(push (buffer-substring-no-properties str-start (point-max)) chunks)
(nreverse (seq-remove (lambda (x) (equal x "")) chunks)))))
;;; Public API
(defun fmt--1 (expr)
"Compile a format expressions EXPR."
(unless (stringp expr)
(error "`fmt' requires a constant string"))
(fmt--compile expr))
(defmacro fmt (&rest exprs)
"Compile a sequence of format expressions EXPRS."
(cons 'concat (apply #'append (mapcar #'fmt--1 exprs))))
(defmacro fmt-message (exprs)
"Display one or more messages EXPRS.
EXPRS is compiled as a format expression."
`(message "%s" (fmt ,@exprs)))
(provide 'fmt)
;;; fmt.el ends here
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 1:13 RFC: String interpolation Clément Pit--Claudel
@ 2016-12-08 8:27 ` Andreas Schwab
2016-12-08 8:38 ` Joost Kremers
2016-12-08 18:25 ` Clément Pit--Claudel
2016-12-08 9:02 ` Philippe Vaucher
` (4 subsequent siblings)
5 siblings, 2 replies; 86+ messages in thread
From: Andreas Schwab @ 2016-12-08 8:27 UTC (permalink / raw)
To: Clément Pit--Claudel; +Cc: Emacs developers
On Dez 08 2016, Clément Pit--Claudel <clement.pit@gmail.com> wrote:
> 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.
(format "The value is %.2f." (1+ value))
Andreas.
--
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 8:27 ` Andreas Schwab
@ 2016-12-08 8:38 ` Joost Kremers
2016-12-08 9:05 ` Philippe Vaucher
2016-12-08 18:25 ` Clément Pit--Claudel
1 sibling, 1 reply; 86+ messages in thread
From: Joost Kremers @ 2016-12-08 8:38 UTC (permalink / raw)
To: Andreas Schwab; +Cc: Clément Pit--Claudel, Emacs developers
On Thu, Dec 08 2016, Andreas Schwab wrote:
> On Dez 08 2016, Clément Pit--Claudel <clement.pit@gmail.com>
> wrote:
>
>> 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.
>
> (format "The value is %.2f." (1+ value))
Well, yes, but if you have a longish string and more than
two-three values to fill, it can be difficult to see what value
goes where and what the resulting string will look like.
It may not be a must-have, but it's certainly a nice-to-have,
IMvHO.
--
Joost Kremers
Life has its moments
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 8:27 ` Andreas Schwab
2016-12-08 8:38 ` Joost Kremers
@ 2016-12-08 18:25 ` Clément Pit--Claudel
1 sibling, 0 replies; 86+ messages in thread
From: Clément Pit--Claudel @ 2016-12-08 18:25 UTC (permalink / raw)
To: Andreas Schwab; +Cc: Emacs developers
[-- Attachment #1.1: Type: text/plain, Size: 539 bytes --]
On 2016-12-08 03:27, Andreas Schwab wrote:
>> It would be nice if Emacs offered something similar out of the box.
>
> (format "The value is %.2f." (1+ value))
Andreas, the implementation I posted uses format under the hood, so I'm not sure what you meant to say :/ The Python RFC that introduced this change has a discussion of pros and cons of the two approaches (including values to be formatted inside the string or not)
In any case, Emacs' format is a function, not a macro: format strings are parsed at runtime, AFAICT.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 1:13 RFC: String interpolation Clément Pit--Claudel
2016-12-08 8:27 ` Andreas Schwab
@ 2016-12-08 9:02 ` Philippe Vaucher
2016-12-08 18:22 ` Clément Pit--Claudel
2016-12-08 14:43 ` Joost Kremers
` (3 subsequent siblings)
5 siblings, 1 reply; 86+ messages in thread
From: Philippe Vaucher @ 2016-12-08 9:02 UTC (permalink / raw)
To: Clément Pit--Claudel; +Cc: Emacs developers
[-- Attachment #1: Type: text/plain, Size: 211 bytes --]
>
> With the attached fmt.el, you can write things like this:
>
I can't really comment on the core inclusion but I just wanted to say nice
work! At a quick glance the implementation looks very clean.
Philippe
[-- Attachment #2: Type: text/html, Size: 460 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 1:13 RFC: String interpolation Clément Pit--Claudel
2016-12-08 8:27 ` Andreas Schwab
2016-12-08 9:02 ` Philippe Vaucher
@ 2016-12-08 14:43 ` Joost Kremers
2016-12-08 18:37 ` Clément Pit--Claudel
2016-12-08 15:51 ` Drew Adams
` (2 subsequent siblings)
5 siblings, 1 reply; 86+ messages in thread
From: Joost Kremers @ 2016-12-08 14:43 UTC (permalink / raw)
To: Clément Pit--Claudel; +Cc: Emacs developers
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
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 14:43 ` Joost Kremers
@ 2016-12-08 18:37 ` Clément Pit--Claudel
2016-12-08 20:04 ` Stefan Monnier
2016-12-09 8:57 ` Joost Kremers
0 siblings, 2 replies; 86+ messages in thread
From: Clément Pit--Claudel @ 2016-12-08 18:37 UTC (permalink / raw)
To: Joost Kremers; +Cc: Emacs developers
[-- Attachment #1.1: Type: text/plain, Size: 2312 bytes --]
On 2016-12-08 09:43, Joost Kremers wrote:
>> (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
Yes, unfortunately: you can include virtually anything in a Lisp variable name.
(let* ((a 1)
(b 2.0)
(a/b (/ a b)))
(fmt "$a/$b = ${a/b}"))
> 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.
I really dislike the escaped quotes, but it might just be me :)
This was inspired from Python's per-type format string, but I'm open to better syntax suggestions :)
> 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 `.
Thanks for the reference! Do you know how it knows where to stop after a backtick?
> 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 $.
Thanks, that's a nice syntax too. I used $ based on a quick review of https://en.wikipedia.org/wiki/String_interpolation . I'm a bit worried about the lack of delimiter after `, though; maybe it would help to see what the example above (with $a/$b and $a/b) would look like in that syntax.
>> 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.
Yes; otherwise, fmt becomes a thinly veiled eval, and that isn't great.
Cheers and thanks for the feedback!
Clément.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 18:37 ` Clément Pit--Claudel
@ 2016-12-08 20:04 ` Stefan Monnier
2016-12-09 8:57 ` Joost Kremers
1 sibling, 0 replies; 86+ messages in thread
From: Stefan Monnier @ 2016-12-08 20:04 UTC (permalink / raw)
To: emacs-devel
>>> 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.
> Yes; otherwise, fmt becomes a thinly veiled eval, and that isn't great.
Not only that, but if it's a function it doesn't have access to the
variables in the lexical scope of the caller.
Stefan
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 18:37 ` Clément Pit--Claudel
2016-12-08 20:04 ` Stefan Monnier
@ 2016-12-09 8:57 ` Joost Kremers
1 sibling, 0 replies; 86+ messages in thread
From: Joost Kremers @ 2016-12-09 8:57 UTC (permalink / raw)
To: Clément Pit--Claudel; +Cc: Emacs developers
On Thu, Dec 08 2016, Clément Pit--Claudel wrote:
> On 2016-12-08 09:43, Joost Kremers wrote:
>>> (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
>
> Yes, unfortunately: you can include virtually anything in a Lisp
> variable name.
>
> (let* ((a 1)
> (b 2.0)
> (a/b (/ a b)))
> (fmt "$a/$b = ${a/b}"))
My initial thinking was that you could simply take everything up
to the next whitespace character to be part of the symbol, but
obviously I didn't realise that it should be possible *not* to
have whitespace immediately after the value of a symbol. But I see
your point now.
>> 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.
>
> I really dislike the escaped quotes, but it might just be me :)
Oh, I'm sure you're not the only one. :-) I'm not a big fan,
either, but I can live with them. It'd be nice to have two
different string delimiters, as in Python (actually, Python has
three...) but that's not something a package can fix.
Anyway, your current implementation handles
"$[date|%Y-%m-%d](current-time)" as well as the format that I
prefer, so no-one loses out.
> This was inspired from Python's per-type format string, but I'm
> open to better syntax suggestions :)
I was hoping to provide some, but looking at it now, I doubt I
was... :-)
>> 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 `.
>
> Thanks for the reference! Do you know how it knows where to
> stop after a backtick?
From a quick look at the code, I believe the assumption is that
symbols only contain lower and uppercase letters, digits and the
characters - and / . So that won't work. The relevant code seems
to be here:
https://github.com/abo-abo/hydra/blob/master/hydra.el#L636
> I'm a bit worried about the lack of delimiter after `, though;
maybe it would help to see what the example above (with $a/$b and
$a/b) would look like in that syntax.
AFAICT it won't work. "%`a/b" would refer to the symbol `a/b',
which is fine, but "%`a/%`b" would refer to a symbol `a/' and a
symbol `b', but the former doesn't exist. And `a/b' only happens
to work because / is included in the regexp used to parse hydra
doc strings. Other characters won't work at all.
>>> 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.
>
> Yes; otherwise, fmt becomes a thinly veiled eval, and that isn't
> great.
True.
--
Joost Kremers
Life has its moments
^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: RFC: String interpolation
2016-12-08 1:13 RFC: String interpolation Clément Pit--Claudel
` (2 preceding siblings ...)
2016-12-08 14:43 ` Joost Kremers
@ 2016-12-08 15:51 ` Drew Adams
2016-12-08 18:21 ` Clément Pit--Claudel
` (2 more replies)
2016-12-08 19:05 ` Stefan Monnier
2016-12-09 19:19 ` Ted Zlatanov
5 siblings, 3 replies; 86+ messages in thread
From: Drew Adams @ 2016-12-08 15:51 UTC (permalink / raw)
To: Clément Pit--Claudel, Emacs developers
1. http://stackoverflow.com/q/37102254/729907
"Lisp string formatting with named parameters."
2. Common Lisp `format':
https://en.wikipedia.org/wiki/Format_(Common_Lisp)
http://www.lispworks.com/documentation/lw50/CLHS/Body/f_format.htm
If Emacs extends `format', I'd vote for it to follow Common Lisp.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 15:51 ` Drew Adams
@ 2016-12-08 18:21 ` Clément Pit--Claudel
2016-12-08 20:38 ` Richard Stallman
[not found] ` <<E1cF5SK-0000HO-EL@fencepost.gnu.org>
2 siblings, 0 replies; 86+ messages in thread
From: Clément Pit--Claudel @ 2016-12-08 18:21 UTC (permalink / raw)
To: Drew Adams, Emacs developers
[-- Attachment #1.1: Type: text/plain, Size: 254 bytes --]
On 2016-12-08 10:51, Drew Adams wrote:
> 1. http://stackoverflow.com/q/37102254/729907
>
> "Lisp string formatting with named parameters."
This doesn't do the same thing, does it? AFAICT it's just named placeholders, not evaluated expressions.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 15:51 ` Drew Adams
2016-12-08 18:21 ` Clément Pit--Claudel
@ 2016-12-08 20:38 ` Richard Stallman
[not found] ` <<E1cF5SK-0000HO-EL@fencepost.gnu.org>
2 siblings, 0 replies; 86+ messages in thread
From: Richard Stallman @ 2016-12-08 20:38 UTC (permalink / raw)
To: Drew Adams; +Cc: clement.pit, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> If Emacs extends `format', I'd vote for it to follow Common Lisp.
That could have many meanings. I hope you don't mean switching from %
to ~ to introduce special constructs. That would be extremely painful
and I am firmly against it.
If what you mean is not an incompatible change in Emacs, then I have
no opinion about it a priori.
--
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.
^ permalink raw reply [flat|nested] 86+ messages in thread
[parent not found: <<E1cF5SK-0000HO-EL@fencepost.gnu.org>]
* RE: RFC: String interpolation
[not found] ` <<E1cF5SK-0000HO-EL@fencepost.gnu.org>
@ 2016-12-08 22:04 ` Drew Adams
0 siblings, 0 replies; 86+ messages in thread
From: Drew Adams @ 2016-12-08 22:04 UTC (permalink / raw)
To: rms, Drew Adams; +Cc: clement.pit, emacs-devel
> > If Emacs extends `format', I'd vote for it to follow Common Lisp.
>
> That could have many meanings. I hope you don't mean switching from %
> to ~ to introduce special constructs. That would be extremely painful
> and I am firmly against it.
>
> If what you mean is not an incompatible change in Emacs, then I have
> no opinion about it a priori.
1. I was speaking only generally, there.
2. If the same name (`format') is kept, then yes, it would need to
be a compatible change. If another name (e.g. `cl-format') were
used then it can (and if prefix `cl-' is used then it should)
use % etc. It would be possible to either or both.
I find Common Lisp `format' to be good. In general, the more Emacs
Lisp `format' were to move toward it, the better, I think.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 1:13 RFC: String interpolation Clément Pit--Claudel
` (3 preceding siblings ...)
2016-12-08 15:51 ` Drew Adams
@ 2016-12-08 19:05 ` Stefan Monnier
2016-12-08 19:31 ` Clément Pit--Claudel
2016-12-09 19:19 ` Ted Zlatanov
5 siblings, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2016-12-08 19:05 UTC (permalink / raw)
To: emacs-devel
> (let ((a 12) (b 15))
> (fmt "$a + $b = $(+ a b)"))
Looks good.
> (concat (fmt--print a) " + " (fmt--print b) " = " (fmt--print (+ a b) 'format "%.2f"))
I'm surprised, I'd have expected to expand to a call to (format ...).
At least that's what my own take on it did (see below; incidentally it
looks otherwise eerily similar to yours in syntax).
FWIW, I don't much like adding extra cases, so I'd stick to a minimal
solution at least until we have enough experience with it to be sure
which extra cases are worth the trouble.
> * Should this go into MELPA, ELPA, or core?
I think it might be worth thinking about it in the larger context of other
special formatting we might have in strings. I'm thinking here about
things like docstrings and their \\[...] and stuff. If we could
imagine a path where those could end up merging, it would be great.
Stefan
(defmacro preformat (string)
(let ((strs '())
(i 0)
(args '()))
(while (string-match "%\\(?:\\(%\\)\\|\\[\\([^]]+\\)]\\)?" string i)
(let ((end (match-end 0)))
(if (match-beginning 1)
;; An "escaped" %.
(progn
(push (substring string i end) strs)
(setq i end))
(push (substring string i (1+ (match-beginning 0))) strs)
(push (if (match-beginning 2) (match-string 2 string) "s") strs)
(if (and (eq ?\{ (aref string end))
(string-match "{\\([^}]+\\)}" string end))
(progn
(push (intern (match-string 1 string)) args)
(setq i (match-end 0)))
(let ((ee (read-from-string string end)))
(push (car ee) args)
(setq i (cdr ee)))))))
(push (substring string i) strs)
`(format ,(mapconcat #'identity (nreverse strs) "")
,@(nreverse args))))
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 19:05 ` Stefan Monnier
@ 2016-12-08 19:31 ` Clément Pit--Claudel
2016-12-08 21:31 ` Stefan Monnier
0 siblings, 1 reply; 86+ messages in thread
From: Clément Pit--Claudel @ 2016-12-08 19:31 UTC (permalink / raw)
To: emacs-devel
[-- Attachment #1.1: Type: text/plain, Size: 1679 bytes --]
On 2016-12-08 14:05, Stefan Monnier wrote:
>> (let ((a 12) (b 15))
>> (fmt "$a + $b = $(+ a b)"))
>
> Looks good.
Thanks :)
>> (concat (fmt--print a) " + " (fmt--print b) " = " (fmt--print (+ a b) 'format "%.2f"))
>
> I'm surprised, I'd have expected to expand to a call to (format ...).
> At least that's what my own take on it did (see below; incidentally it
> looks otherwise eerily similar to yours in syntax).
Neat, it looks like they do almost exactly the same, right? Except % vs. $. The nice part about not constructing a top-level call to format is that the full format string doesn't need to be reparsed every time. You could even imagine getting rid of format entirely, and parsing even the format sequences at compile time.
> FWIW, I don't much like adding extra cases, so I'd stick to a minimal
> solution at least until we have enough experience with it to be sure
> which extra cases are worth the trouble.
Sounds reasonable. I'm happy to drop the extended format codes with "|" in them. Since ELisp variable names routinely include slashes and colons, I think having {} is useful (looks like your implementation supported that too?). Being able to specify a format string is nice too.
>> * Should this go into MELPA, ELPA, or core?
>
> I think it might be worth thinking about it in the larger context of other
> special formatting we might have in strings. I'm thinking here about
> things like docstrings and their \\[...] and stuff. If we could
> imagine a path where those could end up merging, it would be great.
Indeed!
> (defmacro preformat (string)
...
This looks good too, thanks!
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 19:31 ` Clément Pit--Claudel
@ 2016-12-08 21:31 ` Stefan Monnier
2016-12-10 16:01 ` Clément Pit--Claudel
0 siblings, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2016-12-08 21:31 UTC (permalink / raw)
To: emacs-devel
> Neat, it looks like they do almost exactly the same, right? Except % vs. $.
Pretty much, yes.
> The nice part about not constructing a top-level call to format is that the
> full format string doesn't need to be reparsed every time.
Indeed. But the Elisp interpreter is slow compared to the `format`
parser, so I'd expect the use of a single `format` call to be more
efficient (both in code size and execution time). That's just a gut
feeling, tho, I have no hard data to back it up (my implementation uses
a single `format` call partly because of that gut feeling but also
because it seemed easier).
> You could even imagine getting rid of format entirely, and parsing
> even the format sequences at compile time.
My gut says that the resulting Elisp code would probably be even larger
and slower.
> Sounds reasonable. I'm happy to drop the extended format codes with "|" in
> them. Since ELisp variable names routinely include slashes and colons,
> I think having {} is useful (looks like your implementation supported that
> too?). Being able to specify a format string is nice too.
I added supported for {..} not so much because of slashes and such, but
simply to resolve the ambiguity between "%{a}b" and "%{ab}".
Stefan
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-08 1:13 RFC: String interpolation Clément Pit--Claudel
` (4 preceding siblings ...)
2016-12-08 19:05 ` Stefan Monnier
@ 2016-12-09 19:19 ` Ted Zlatanov
2016-12-09 22:45 ` Clément Pit--Claudel
2016-12-10 14:11 ` Lars Ingebrigtsen
5 siblings, 2 replies; 86+ messages in thread
From: Ted Zlatanov @ 2016-12-09 19:19 UTC (permalink / raw)
To: emacs-devel
On Wed, 7 Dec 2016 20:13:41 -0500 Clément Pit--Claudel <clement.pit@gmail.com> wrote:
CP> With the attached fmt.el, you can write things like this:
CP> (let ((a 12) (b 15))
CP> (fmt "$a + $b = $(+ a b)"))
CP> ⇒ "12 + 15 = 27"
...
CP> (fmt "Welcome to Emacs! "
CP> "Press $[where-is]{'help-with-tutorial} to open the tutorial.")
CP> ⇒ "Welcome to Emacs! Press C-h t to open the tutorial."
I'd rather see either something like Mustache templates or simply using
the format-spec.el that comes with Emacs. The advantage in my opinion
(informed by many years of using Perl, where string interpolation is a
way of life) is that clarity is improved by separating the format spec
from the data that fills it out, and it's very tempting to stuff logic
into strings but maintenance is unpleasant.
format-spec examples of the two usages quoted:
(let ((a 12) (b 15))
(format-spec "%a + %b = %u" (format-spec-make ?a a
?b b
?u (+ a b)))
(format-spec "Welcome to Emacs! Press %w to open the tutorial"
(format-spec-make ?w (with-temp-buffer
(where-is 'help-with-tutorial t)
(buffer-string))))
CP> (fmt "Today is $[date|%Y-%m-%d](current-time).")
CP> ⇒ "Today is 2016-12-07."
I see no advantage to this versus `format-time-string'. It's ambiguous
and the time zone can't be specified without making it more complicated.
This one in particular is heading in the direction of the way Ansible
integrates Jinja templates, which I think is not great compared to a
more Lispy approach.
Ted
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-09 19:19 ` Ted Zlatanov
@ 2016-12-09 22:45 ` Clément Pit--Claudel
2016-12-11 2:53 ` Ted Zlatanov
2016-12-11 17:38 ` Stefan Monnier
2016-12-10 14:11 ` Lars Ingebrigtsen
1 sibling, 2 replies; 86+ messages in thread
From: Clément Pit--Claudel @ 2016-12-09 22:45 UTC (permalink / raw)
To: emacs-devel
[-- Attachment #1.1: Type: text/plain, Size: 2062 bytes --]
On 2016-12-09 14:19, Ted Zlatanov wrote:
> On Wed, 7 Dec 2016 20:13:41 -0500 Clément Pit--Claudel <clement.pit@gmail.com> wrote:
> I'd rather see either something like Mustache templates or simply using
> the format-spec.el that comes with Emacs. The advantage in my opinion
> (informed by many years of using Perl, where string interpolation is a
> way of life) is that clarity is improved by separating the format spec
> from the data that fills it out, and it's very tempting to stuff logic
> into strings but maintenance is unpleasant.
Thanks for the feedback! Can you share concrete examples in which this makes maintenance harder?
The approach I outlined is significantly influenced by the direction that Python is taking (see the PEP I linked to in the original message).
> (let ((a 12) (b 15))
> (format-spec "%a + %b = %u" (format-spec-make ?a a
> ?b b
> ?u (+ a b)))
Thanks. Are there benefits of this over just (format "%s + %s = %s" a b (+ a b))? The names ?a and ?b seem redundant, and ?u doesn't carry specific meaning. (FWIW, Python has template strings for that purpose, but virtually no one uses them, AFAICT).
Also: how does format-spec deal with formatting sequences, like %-3.2d?
> I see no advantage to this versus `format-time-string'. It's ambiguous
> and the time zone can't be specified without making it more complicated.
Yup; it's unfortunate that ELisp's notion of date doesn't come with a timezone.
> This one in particular is heading in the direction of the way Ansible
> integrates Jinja templates, which I think is not great compared to a
> more Lispy approach.
I have no strong feelings either way. I like the way Python is going, so it feels natural to suggest the same direction for Emacs. I view it as a convenient DSL for producing strings, just like the loop macro is a good DSL for iterating and accumulating results — and we're a Lisp, so we're good at DSLs :)
Clément.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-09 22:45 ` Clément Pit--Claudel
@ 2016-12-11 2:53 ` Ted Zlatanov
2016-12-11 18:46 ` Lars Ingebrigtsen
2016-12-11 17:38 ` Stefan Monnier
1 sibling, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2016-12-11 2:53 UTC (permalink / raw)
To: emacs-devel
On Fri, 9 Dec 2016 17:45:16 -0500 Clément Pit--Claudel <clement.pit@gmail.com> wrote:
CP> On 2016-12-09 14:19, Ted Zlatanov wrote:
>> On Wed, 7 Dec 2016 20:13:41 -0500 Clément Pit--Claudel <clement.pit@gmail.com> wrote:
>> I'd rather see either something like Mustache templates or simply using
>> the format-spec.el that comes with Emacs. The advantage in my opinion
>> (informed by many years of using Perl, where string interpolation is a
>> way of life) is that clarity is improved by separating the format spec
>> from the data that fills it out, and it's very tempting to stuff logic
>> into strings but maintenance is unpleasant.
CP> Thanks for the feedback! Can you share concrete examples in which
CP> this makes maintenance harder?
Just imagine *any* Perl code "@{[ inside here ]}" and you're ready.
Things like embedded hash slices, in-place sorts or Schwarzian
transforms...
(let ((a 12) (b 15))
(format-spec "%a + %b = %u" (format-spec-make ?a a
?b b
?u (+ a b)))
CP> Thanks. Are there benefits of this over just (format "%s + %s = %s" a b (+ a
CP> b))? The names ?a and ?b seem redundant, and ?u doesn't carry specific meaning.
Yes, of course. It's the same as positional vs. named arguments to
functions. In (format "%s %s %s" x y z) you have to remember each
parameter, and if you want to repeat x twice you have to write it two
times.
To take a step back, imagine a spectrum. At one end is (format "%s %s
%s" ...) which is fast, easy to implement, familiar to those who know
sprintf, and anonymizes the template data, filtering it through a type
expression. This is extremely popular and is not going away.
The middle of the spectrum are things like Mustache {{ foo }} and
`format-spec' which separate the format from the data but have an alias
for each data item. And at the other end we see your approach and
Ansible+Jinja and Perl etc. which directly refer to the variables in
scope and basically try to reinvent the language in a "portable" format
that can be embedded in a string. If you're set on doing this, please
just fall through to the underlying language, e.g.
"$(format \"%3.2s\" myvar) $(myothervar)"
CP> Also: how does format-spec deal with formatting sequences, like %-3.2d?
It doesn't. You would convert that before passing it to the function.
You can consider that a deficiency (if you prefer the printf style) or
good (if you like the Mustache style).
>> This one in particular is heading in the direction of the way Ansible
>> integrates Jinja templates, which I think is not great compared to a
>> more Lispy approach.
CP> I have no strong feelings either way. I like the way Python is going, so it
CP> feels natural to suggest the same direction for Emacs. I view it as a convenient
CP> DSL for producing strings, just like the loop macro is a good DSL for iterating
CP> and accumulating results — and we're a Lisp, so we're good at DSLs :)
I think it's good to experiment. As currently proposed, I wouldn't want
to *maintain* code that used your approach. But I could be wrong about
it, and my advice was based on personal intuition and experience. So I
hope you found it useful rather than discouraging :)
Ted
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-09 22:45 ` Clément Pit--Claudel
2016-12-11 2:53 ` Ted Zlatanov
@ 2016-12-11 17:38 ` Stefan Monnier
2016-12-11 17:53 ` Clément Pit--Claudel
1 sibling, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2016-12-11 17:38 UTC (permalink / raw)
To: emacs-devel
> Thanks for the feedback! Can you share concrete examples in which this
> makes maintenance harder?
I think the simple fact that it makes
highlighting/completion/indentation more complex (not to mention the
potential to have format-strings within format-strings within...) is
a good hint that you don't want to encourage writing code within the
format string: it works fine for very simple pieces of code, but for
anything more significant you're better off writing the code outside the
string (and then referring to that code from the string).
Stefan
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-09 19:19 ` Ted Zlatanov
2016-12-09 22:45 ` Clément Pit--Claudel
@ 2016-12-10 14:11 ` Lars Ingebrigtsen
2016-12-10 14:25 ` Clément Pit--Claudel
1 sibling, 1 reply; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-10 14:11 UTC (permalink / raw)
To: emacs-devel
Ted Zlatanov <tzz@lifelogs.com> writes:
> The advantage in my opinion (informed by many years of using Perl,
> where string interpolation is a way of life) is that clarity is
> improved by separating the format spec from the data that fills it
> out, and it's very tempting to stuff logic into strings but
> maintenance is unpleasant.
Yeah, I'm similarly unenthusiastic about string interpolation. It's not
that I love format strings -- first adding a %d somewhere in the string
and then figuring out where in the argument list to put the thing to be
output there isn't a great interface, either.
So I see the charms: Just write
"This number is $variable".
But then you get to all the niggling little details involved: Well, how
about if I wanted an "s" after $variable... Uhm, OK, then the syntax is
"This number is ${variable}s".
Ok, but variable is a floating point number, and I only wanted two
decimals, so... er...
(let ((pvar (format "%.2f" variable)))
"This number is ${pvar}s"
(You see the equivalent type of code in all languages that have "simple"
string interpolation, like PHP, all the time.)
Ok, but perhaps we can just allow random expressions instead of just
variables, so we have
"This number is ${(format \"%.2f\" (/ variable 0.3))}s"
BEHOLD THE PRETTY!
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-10 14:11 ` Lars Ingebrigtsen
@ 2016-12-10 14:25 ` Clément Pit--Claudel
2016-12-10 15:39 ` Lars Ingebrigtsen
0 siblings, 1 reply; 86+ messages in thread
From: Clément Pit--Claudel @ 2016-12-10 14:25 UTC (permalink / raw)
To: emacs-devel
[-- Attachment #1.1: Type: text/plain, Size: 485 bytes --]
On 2016-12-10 09:11, Lars Ingebrigtsen wrote:
> Ok, but variable is a floating point number, and I only wanted two
> decimals, so... er...
>
> (let ((pvar (format "%.2f" variable)))
> "This number is ${pvar}s"
>
> (You see the equivalent type of code in all languages that have "simple"
> string interpolation, like PHP, all the time.)
I thought I adressed this case specifically in my proposal :/
(fmt "This number is $[%.2f]{pvar}s")
Cheers,
Clément.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-10 14:25 ` Clément Pit--Claudel
@ 2016-12-10 15:39 ` Lars Ingebrigtsen
2016-12-10 15:49 ` Clément Pit--Claudel
0 siblings, 1 reply; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-10 15:39 UTC (permalink / raw)
To: Clément Pit--Claudel; +Cc: emacs-devel
Clément Pit--Claudel <clement.pit@gmail.com> writes:
>> (let ((pvar (format "%.2f" variable)))
>> "This number is ${pvar}s"
>>
>> (You see the equivalent type of code in all languages that have "simple"
>> string interpolation, like PHP, all the time.)
>
> I thought I adressed this case specifically in my proposal :/
>
> (fmt "This number is $[%.2f]{pvar}s")
Sure, you can add special cases to your domain-specific language to do
any formatting you want to. Do you have a $[%] code for "strip out all
the blanks from a string"? :-)
The problem with string interpolation is, in general, that it isn't very
general. And it isn't "composable": Once you hit a case that isn't
covered, you have to rewrite the entire expression to a different form
(i.e., traditional format strings with arguments afterwards), and I know
from experience that people are loath to do that. Instead the temporary
variables start popping up, obfuscating the code.
So... I'm kinda on the "meh" side of the string interpolation debate.
As Ted alluded to, there's a different, template based method that I
think is more promising and is growing more popular in newer languages.
In Emacs Lisp, you'd have either have a macro like
(with-format ((zot "foo")
(thing (funcall '+ 3.42423 4)))
"This is %{thing}.2f and %{zot}ss")
or
(fmt "This is %{thing}.2f and %{zot}ss"
zot
(thing (funcall '+ 3.42423 4)))
That is, named format arguments with format specs. You get all the
advantages of normal format (i.e., the parameters are real code, not
weirdly formatted things inside a string), but you don't have to match
up the order of the parameters to the order of the % directives.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-10 15:39 ` Lars Ingebrigtsen
@ 2016-12-10 15:49 ` Clément Pit--Claudel
2016-12-10 16:01 ` Yuri Khan
` (2 more replies)
0 siblings, 3 replies; 86+ messages in thread
From: Clément Pit--Claudel @ 2016-12-10 15:49 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: emacs-devel
[-- Attachment #1.1: Type: text/plain, Size: 973 bytes --]
On 2016-12-10 10:39, Lars Ingebrigtsen wrote:
> As Ted alluded to, there's a different, template based method that I
> think is more promising and is growing more popular in newer languages.
I don't know: Python has had it for a while, no one uses it, and they are now introducing interpolation…
> (with-format ((zot "foo")
> (thing (funcall '+ 3.42423 4)))
> "This is %{thing}.2f and %{zot}ss")
This looks fine too, but the repetition bothers me (I don't really see what benefit there is to naming all arguments). So I still find
"This is %(funcall '+ 3.42423 4).2f and "foo"s"
more readable.
But in any case, what you're suggesting is just a limited form of interpolation, right? IIUC it's actually already offered in s.el. With the fmt that I suggested, you'd write this:
(let ((zot "foo")
(thing (funcall '+ 3.42423 4)))
(fmt "This is $[%.2s]{thing} and ${zot}s"))
Or would with-format behave differently?
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-10 15:49 ` Clément Pit--Claudel
@ 2016-12-10 16:01 ` Yuri Khan
2016-12-10 17:58 ` Clément Pit--Claudel
2016-12-11 17:47 ` Stefan Monnier
2016-12-11 9:35 ` Richard Stallman
2016-12-11 18:41 ` Lars Ingebrigtsen
2 siblings, 2 replies; 86+ messages in thread
From: Yuri Khan @ 2016-12-10 16:01 UTC (permalink / raw)
To: Clément Pit--Claudel; +Cc: Lars Ingebrigtsen, Emacs developers
On Sat, Dec 10, 2016 at 10:49 PM, Clément Pit--Claudel
<clement.pit@gmail.com> wrote:
>> (with-format ((zot "foo")
>> (thing (funcall '+ 3.42423 4)))
>> "This is %{thing}.2f and %{zot}ss")
>
> This looks fine too, but the repetition bothers me (I don't really see what benefit there is to naming all arguments). So I still find
>
> "This is %(funcall '+ 3.42423 4).2f and "foo"s"
>
> more readable.
If this wasn’t Emacs, I would name lack of localizability as a
drawback of including code as part of strings. But that’s moot because
no one writes localizable software in Elisp.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-10 16:01 ` Yuri Khan
@ 2016-12-10 17:58 ` Clément Pit--Claudel
2016-12-11 17:47 ` Stefan Monnier
1 sibling, 0 replies; 86+ messages in thread
From: Clément Pit--Claudel @ 2016-12-10 17:58 UTC (permalink / raw)
To: Yuri Khan; +Cc: Lars Ingebrigtsen, Emacs developers
[-- Attachment #1.1: Type: text/plain, Size: 563 bytes --]
On 2016-12-10 11:01, Yuri Khan wrote:
> If this wasn’t Emacs, I would name lack of localizability as a
> drawback of including code as part of strings. But that’s moot because
> no one writes localizable software in Elisp.
It's an excellent point nonetheless; thanks for mentioning it!
(though part of me wonders if this wouldn't help with localizability, too: assuming fmt was extended to support compile-time constants, I could imagine that the ability to include code in strings may make translation easier)
Thanks for the insight!
Clément.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-10 16:01 ` Yuri Khan
2016-12-10 17:58 ` Clément Pit--Claudel
@ 2016-12-11 17:47 ` Stefan Monnier
2016-12-11 19:31 ` Yuri Khan
1 sibling, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2016-12-11 17:47 UTC (permalink / raw)
To: emacs-devel
>> "This is %(funcall '+ 3.42423 4).2f and "foo"s"
> If this wasn’t Emacs, I would name lack of localizability as a
> drawback of including code as part of strings.
Note that with if the macro internally uses just a single `format` call,
then the above gets macro-expanded into something like
(format "This is %s and %ss" ...)
which is as amenable to localization as your typical printf.
> But that’s moot because no one writes localizable software in Elisp.
Sad but true.
Stefan
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-11 17:47 ` Stefan Monnier
@ 2016-12-11 19:31 ` Yuri Khan
2016-12-11 20:12 ` Stefan Monnier
0 siblings, 1 reply; 86+ messages in thread
From: Yuri Khan @ 2016-12-11 19:31 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Emacs developers
On Mon, Dec 12, 2016 at 12:47 AM, Stefan Monnier
<monnier@iro.umontreal.ca> wrote:
>>> "This is %(funcall '+ 3.42423 4).2f and "foo"s"
>> If this wasn’t Emacs, I would name lack of localizability as a
>> drawback of including code as part of strings.
>
> Note that with if the macro internally uses just a single `format` call,
> then the above gets macro-expanded into something like
>
> (format "This is %s and %ss" ...)
>
> which is as amenable to localization as your typical printf.
Technically yes, but one normally gives out original format strings
for localization, not results of macro expansion. And that means
localizers need to be careful not to break the code embedded therein.
And that, in turn, is just not a reasonable expectation.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-11 19:31 ` Yuri Khan
@ 2016-12-11 20:12 ` Stefan Monnier
0 siblings, 0 replies; 86+ messages in thread
From: Stefan Monnier @ 2016-12-11 20:12 UTC (permalink / raw)
To: Yuri Khan; +Cc: Emacs developers
> Technically yes, but one normally gives out original format strings
> for localization, not results of macro expansion.
Hmm... I don't think this could work for Lisp (and not just Emacs Lisp)
in general. More specifically, in the case of Lisp, I'd expect that the
format strings used for localization could come from anywhere between
the source code and the fully macro-expanded code, and it would be under
the control of each macroexpander to use the string before or after
its expansion.
Stefan
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-10 15:49 ` Clément Pit--Claudel
2016-12-10 16:01 ` Yuri Khan
@ 2016-12-11 9:35 ` Richard Stallman
2016-12-11 16:29 ` Clément Pit--Claudel
2016-12-11 18:42 ` Lars Ingebrigtsen
2016-12-11 18:41 ` Lars Ingebrigtsen
2 siblings, 2 replies; 86+ messages in thread
From: Richard Stallman @ 2016-12-11 9:35 UTC (permalink / raw)
To: Clément Pit--Claudel; +Cc: larsi, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> I don't know: Python has had it for a while, no one uses it, and they are now introducing interpolation…
> > (with-format ((zot "foo")
> > (thing (funcall '+ 3.42423 4)))
> > "This is %{thing}.2f and %{zot}ss")
> This looks fine too, but the repetition bothers me (I don't really see what benefit there is to naming all arguments). So I still find
> "This is %(funcall '+ 3.42423 4).2f and "foo"s"
> more readable.
Is there a reason why people are writing (funcall '+ 3.42423 4)
rather than (+ 3.42423 4)?
--
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-11 9:35 ` Richard Stallman
@ 2016-12-11 16:29 ` Clément Pit--Claudel
2016-12-11 18:42 ` Lars Ingebrigtsen
1 sibling, 0 replies; 86+ messages in thread
From: Clément Pit--Claudel @ 2016-12-11 16:29 UTC (permalink / raw)
To: rms; +Cc: larsi, emacs-devel
[-- Attachment #1.1: Type: text/plain, Size: 259 bytes --]
On 2016-12-11 04:35, Richard Stallman wrote:
> Is there a reason why people are writing (funcall '+ 3.42423 4)
> rather than (+ 3.42423 4)?
I wondered too :) But Lars' examples were written that way, so I did the same to ease comparison.
Clément.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-11 9:35 ` Richard Stallman
2016-12-11 16:29 ` Clément Pit--Claudel
@ 2016-12-11 18:42 ` Lars Ingebrigtsen
2016-12-12 19:41 ` Richard Stallman
1 sibling, 1 reply; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-11 18:42 UTC (permalink / raw)
To: Richard Stallman; +Cc: Clément Pit--Claudel, emacs-devel
Richard Stallman <rms@gnu.org> writes:
> Is there a reason why people are writing (funcall '+ 3.42423 4)
> rather than (+ 3.42423 4)?
Yes. It's a long form that everybody knows the meaning of, and that
looks awkward when you put it into a format string.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-11 18:42 ` Lars Ingebrigtsen
@ 2016-12-12 19:41 ` Richard Stallman
0 siblings, 0 replies; 86+ messages in thread
From: Richard Stallman @ 2016-12-12 19:41 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: clement.pit, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> > Is there a reason why people are writing (funcall '+ 3.42423 4)
> > rather than (+ 3.42423 4)?
> Yes. It's a long form that everybody knows the meaning of, and that
> looks awkward when you put it into a format string.
Some forms of code look good with short forms and bad with long ones.
Looking at them with long forms makes them look bad, but they might
be useful anyway.
--
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-10 15:49 ` Clément Pit--Claudel
2016-12-10 16:01 ` Yuri Khan
2016-12-11 9:35 ` Richard Stallman
@ 2016-12-11 18:41 ` Lars Ingebrigtsen
2016-12-11 21:05 ` Helmut Eller
2 siblings, 1 reply; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-11 18:41 UTC (permalink / raw)
To: Clément Pit--Claudel; +Cc: emacs-devel
Clément Pit--Claudel <clement.pit@gmail.com> writes:
>> (with-format ((zot "foo")
>> (thing (funcall '+ 3.42423 4)))
>> "This is %{thing}.2f and %{zot}ss")
>
> This looks fine too, but the repetition bothers me (I don't really see what benefit there is to naming all arguments). So I still find
>
> "This is %(funcall '+ 3.42423 4).2f and "foo"s"
>
> more readable.
Yeah, the repetition isn't nice, but it's all a choice of how explicit
and how little magic you want to have. In the `with-format' you're
taking things explicitly out of the lexical/dynamic space the values may
live in an put it into the lexical form.
The other approach I mentioned is less explicit:
(fmt "This is %{thing}.2f and %{zot}ss"
(thing (funcall '+ 3.42423 4)))
If the named parameter mentioned isn't part of the value alist, then
it's taken as a variable in its lexical/dynamic space, but if it does,
then we use the value provided in the alist.
Lisp has traditionally erred on the side of explicitness, but there's a
movement towards more magic these days.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-11 18:41 ` Lars Ingebrigtsen
@ 2016-12-11 21:05 ` Helmut Eller
2016-12-11 21:26 ` Lars Ingebrigtsen
0 siblings, 1 reply; 86+ messages in thread
From: Helmut Eller @ 2016-12-11 21:05 UTC (permalink / raw)
To: emacs-devel
On Sun, Dec 11 2016, Lars Ingebrigtsen wrote:
> The other approach I mentioned is less explicit:
>
> (fmt "This is %{thing}.2f and %{zot}ss"
> (thing (funcall '+ 3.42423 4)))
>
> If the named parameter mentioned isn't part of the value alist, then
> it's taken as a variable in its lexical/dynamic space, but if it does,
> then we use the value provided in the alist.
Keyword paramaters are also an option:
(fmt "This is %{thing}.2f and %{zot}ss" :thing (funcall '+ 3.42423 4))
Helmut
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-11 21:05 ` Helmut Eller
@ 2016-12-11 21:26 ` Lars Ingebrigtsen
2016-12-12 2:39 ` Stefan Monnier
0 siblings, 1 reply; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-11 21:26 UTC (permalink / raw)
To: Helmut Eller; +Cc: emacs-devel
Helmut Eller <eller.helmut@gmail.com> writes:
> Keyword paramaters are also an option:
>
> (fmt "This is %{thing}.2f and %{zot}ss" :thing (funcall '+ 3.42423 4))
Yeah, that's prettier.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-11 21:26 ` Lars Ingebrigtsen
@ 2016-12-12 2:39 ` Stefan Monnier
2016-12-12 9:44 ` Lars Ingebrigtsen
2016-12-12 16:39 ` Helmut Eller
0 siblings, 2 replies; 86+ messages in thread
From: Stefan Monnier @ 2016-12-12 2:39 UTC (permalink / raw)
To: emacs-devel
>> Keyword paramaters are also an option:
>> (fmt "This is %{thing}.2f and %{zot}ss" :thing (funcall '+ 3.42423 4))
> Yeah, that's prettier.
FWIW, I don't see why that's preferable to
(let ((thing (funcall '+ 3.45453 4)))
(preformat "This is %[2f]{thing} and %{zot}ss"))
-- Stefan
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 2:39 ` Stefan Monnier
@ 2016-12-12 9:44 ` Lars Ingebrigtsen
2016-12-12 13:03 ` Stefan Monnier
` (3 more replies)
2016-12-12 16:39 ` Helmut Eller
1 sibling, 4 replies; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-12 9:44 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>>> Keyword paramaters are also an option:
>>> (fmt "This is %{thing}.2f and %{zot}ss" :thing (funcall '+ 3.42423 4))
>> Yeah, that's prettier.
>
> FWIW, I don't see why that's preferable to
>
> (let ((thing (funcall '+ 3.45453 4)))
> (preformat "This is %[2f]{thing} and %{zot}ss"))
I think it's preferable in a code life cycle perspective. You frequently
start out with
(fmt "This is %{thing}.2f")
because you have something in a variable you want to output. But then
you see that you have to alter it before display, so then you have
(let ((thing-formatted (replace-regexp-in-string " +" " " thing)))
(fmt "This is %{thing-formatted}.2f"))
That is, you're forced to both name and introduce a new temporary
variable, and you have to alter the format statement itself. (This is
what PHP programmers do all the time, and it kinda sucks.)
With the optional keyword arguments, you just add it:
(fmt "This is %{thing}.2f"
:thing (replace-regexp-in-string " +" " " thing))
This sucks slightly less, in my opinion.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 9:44 ` Lars Ingebrigtsen
@ 2016-12-12 13:03 ` Stefan Monnier
2016-12-12 14:47 ` Lars Ingebrigtsen
2016-12-12 13:40 ` Clément Pit--Claudel
` (2 subsequent siblings)
3 siblings, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2016-12-12 13:03 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: emacs-devel
> (let ((thing-formatted (replace-regexp-in-string " +" " " thing)))
> (fmt "This is %{thing-formatted}.2f"))
>
> That is, you're forced to both name and introduce a new temporary
> variable, and you have to alter the format statement itself. (This is
> what PHP programmers do all the time, and it kinda sucks.)
I see no need for renaming and altering the format statement itself:
(let ((thing (replace-regexp-in-string " +" " " thing)))
(fmt "This is %{thing}.2f"))
> (fmt "This is %{thing}.2f"
> :thing (replace-regexp-in-string " +" " " thing))
>
> This sucks slightly less, in my opinion.
I still don't see much difference.
Stefan
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 13:03 ` Stefan Monnier
@ 2016-12-12 14:47 ` Lars Ingebrigtsen
2016-12-12 15:04 ` Stefan Monnier
0 siblings, 1 reply; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-12 14:47 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
> I see no need for renaming and altering the format statement itself:
>
> (let ((thing (replace-regexp-in-string " +" " " thing)))
> (fmt "This is %{thing}.2f"))
Ah, but then a typical programmer would just say
(setq thing (replace-regexp-in-string " +" " " thing))
(fmt "This is %{thing}.2f")
because programmers like setq more than introducing new, nesting
bindings. And then they later want the original value of the variable
later, anyway, and then they finally rewrite it to use a let for or a
new variable name.
I've been doing PHP for decades. Typical work flow. :-)
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 14:47 ` Lars Ingebrigtsen
@ 2016-12-12 15:04 ` Stefan Monnier
2016-12-12 15:26 ` Lars Ingebrigtsen
0 siblings, 1 reply; 86+ messages in thread
From: Stefan Monnier @ 2016-12-12 15:04 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: emacs-devel
> Ah, but then a typical programmer would just say
>
> (setq thing (replace-regexp-in-string " +" " " thing))
> (fmt "This is %{thing}.2f")
>
> because programmers like setq more than introducing new, nesting
> bindings.
Then you should fix your programmers.
> I've been doing PHP for decades.
Time to take a break from such madness.
Stefan
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 15:04 ` Stefan Monnier
@ 2016-12-12 15:26 ` Lars Ingebrigtsen
2016-12-12 17:05 ` Stefan Monnier
2016-12-12 17:12 ` Lars Ingebrigtsen
0 siblings, 2 replies; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-12 15:26 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
> Then you should fix your programmers.
Or we can, as we have the opportunity to here, fix the language.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 15:26 ` Lars Ingebrigtsen
@ 2016-12-12 17:05 ` Stefan Monnier
2016-12-12 17:12 ` Lars Ingebrigtsen
1 sibling, 0 replies; 86+ messages in thread
From: Stefan Monnier @ 2016-12-12 17:05 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: emacs-devel
>> Then you should fix your programmers.
> Or we can, as we have the opportunity to here, fix the language.
I really don't have a strong preference about the issue at hand, to tell
you the truth.
But I don't think we should shy away from relying on `let` just on the
premise that Elisp programmers will use `setq` instead. Doing that will
simply make it more likely that those programmers won't learn to use
`let`.
Stefan
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 15:26 ` Lars Ingebrigtsen
2016-12-12 17:05 ` Stefan Monnier
@ 2016-12-12 17:12 ` Lars Ingebrigtsen
2016-12-12 17:23 ` Stefan Monnier
1 sibling, 1 reply; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-12 17:12 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
If we take one step back and look at our objectives and options here,
this is how I see it:
1) It is somewhat attractive to be able to drop variables into
formatting strings: Quite a lot of popular programming languages allow
this.
2) It is not that attractive to extend this to general programming
constructs, because code inside strings is just ... bad.
4b) But people sometimes need to tweak the look of the values before they
are printed, and forcing people to switch between paradigms is also bad.
4d) Introducing new variables, or values visible outside of the
formatting statement is bad, because things that belong inside the
formatting statement belong inside, not outside (for readability and
maintainability).
Solution:
Allow 1), and provide 4b) by putting the extra code inside the
formatting statement, but not inside the string itself.
Ergo:
(fmt "This is %{thing}s and %{zot}.2f"
:thing (replace-regexp-in-string " +" " " thing))
If, however, you don't mind 4d) at all, and think that introducing new
bindings is a spiffy way to do programming (shades of the fabulous
interface that `url-retrieve' has now), then I guess I can't really say
much more than: ¯\_(ツ)_/¯
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 9:44 ` Lars Ingebrigtsen
2016-12-12 13:03 ` Stefan Monnier
@ 2016-12-12 13:40 ` Clément Pit--Claudel
2016-12-12 14:43 ` Lars Ingebrigtsen
2016-12-12 17:46 ` Paul Eggert
2016-12-12 19:43 ` Richard Stallman
3 siblings, 1 reply; 86+ messages in thread
From: Clément Pit--Claudel @ 2016-12-12 13:40 UTC (permalink / raw)
To: emacs-devel
[-- Attachment #1.1: Type: text/plain, Size: 229 bytes --]
On 2016-12-12 04:44, Lars Ingebrigtsen wrote:
> (fmt "This is %{thing}.2f"
> :thing (replace-regexp-in-string " +" " " thing))
>
> This sucks slightly less, in my opinion.
How so? (this is a sincere question)
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 13:40 ` Clément Pit--Claudel
@ 2016-12-12 14:43 ` Lars Ingebrigtsen
2016-12-12 14:54 ` Clément Pit--Claudel
0 siblings, 1 reply; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-12 14:43 UTC (permalink / raw)
To: Clément Pit--Claudel; +Cc: emacs-devel
Clément Pit--Claudel <clement.pit@gmail.com> writes:
> On 2016-12-12 04:44, Lars Ingebrigtsen wrote:
>> (fmt "This is %{thing}.2f"
>> :thing (replace-regexp-in-string " +" " " thing))
>>
>> This sucks slightly less, in my opinion.
>
> How so? (this is a sincere question)
Sorry, I thought all the paragraphs above that one explained why I
thought it sucked slightly less? :-)
You don't introduce any new variables, alter any variables, or alter the
format statement. I think that's less suckitude.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 14:43 ` Lars Ingebrigtsen
@ 2016-12-12 14:54 ` Clément Pit--Claudel
2016-12-12 17:14 ` Stefan Monnier
0 siblings, 1 reply; 86+ messages in thread
From: Clément Pit--Claudel @ 2016-12-12 14:54 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: emacs-devel
[-- Attachment #1.1: Type: text/plain, Size: 569 bytes --]
On 2016-12-12 09:43, Lars Ingebrigtsen wrote:
> You don't introduce any new variables, alter any variables, or alter the
> format statement. I think that's less suckitude.
I don't understand. You're comparing this:
(let ((thing (replace-regexp-in-string " +" " " thing)))
(fmt "This is %[.2f]{thing}.2f"))
to this:
(fmt "This is %{thing}.2f"
:thing (replace-regexp-in-string " +" " " thing))
right?
Admittedly the form below doesn't rebind "thing", but it now has ":thing" and "thing" meaning different things.
Cheers,
Clément.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 14:54 ` Clément Pit--Claudel
@ 2016-12-12 17:14 ` Stefan Monnier
0 siblings, 0 replies; 86+ messages in thread
From: Stefan Monnier @ 2016-12-12 17:14 UTC (permalink / raw)
To: emacs-devel
> (fmt "This is %{thing}.2f"
> :thing (replace-regexp-in-string " +" " " thing))
I think the above is clearly better than `preformat` under one
condition: make it a function rather than a macro.
The downside (other than performance, tho that can be compounded by
a compiler-macro) is that
(fmt "This is %{thing}.2f")
won't work any more, you'll need
(fmt "This is %{thing}.2f" :thing thing)
instead.
Stefan
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 9:44 ` Lars Ingebrigtsen
2016-12-12 13:03 ` Stefan Monnier
2016-12-12 13:40 ` Clément Pit--Claudel
@ 2016-12-12 17:46 ` Paul Eggert
2016-12-12 18:33 ` Lars Ingebrigtsen
2016-12-12 19:51 ` Ted Zlatanov
2016-12-12 19:43 ` Richard Stallman
3 siblings, 2 replies; 86+ messages in thread
From: Paul Eggert @ 2016-12-12 17:46 UTC (permalink / raw)
To: Lars Ingebrigtsen, Stefan Monnier; +Cc: emacs-devel
Why not just extend "format" so that it allows trailing "...%" in the
format string to mean "argument value spliced here"? After the argument
you can continue on with the format, which must start with the rest of
the conversion specification. E.g.:
(format "Altitude= %" alt ".2f, direction = %" dir ".2f.")
might output "Altitude = 300.57, direction = 240.93."
That way, you can easily replace the expressions without giving them names:
(format "Altitude= %" (+ alt 100) ".2f, direction = %" (- dir) ".2f.")
This should provide the desired benefits without having to do anything
fancy with variable scoping or changing the lexer or whatever.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 17:46 ` Paul Eggert
@ 2016-12-12 18:33 ` Lars Ingebrigtsen
2016-12-12 19:51 ` Ted Zlatanov
1 sibling, 0 replies; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-12 18:33 UTC (permalink / raw)
To: Paul Eggert; +Cc: Stefan Monnier, emacs-devel
Paul Eggert <eggert@cs.ucla.edu> writes:
> Why not just extend "format" so that it allows trailing "...%" in the
> format string to mean "argument value spliced here"? After the
> argument you can continue on with the format, which must start with
> the rest of the conversion specification. E.g.:
>
> (format "Altitude= %" alt ".2f, direction = %" dir ".2f.")
>
> might output "Altitude = 300.57, direction = 240.93."
>
> That way, you can easily replace the expressions without giving them names:
>
> (format "Altitude= %" (+ alt 100) ".2f, direction = %" (- dir) ".2f.")
Hm, that's a solution I don't think I've seen in any other languages? I
think this looks kinda attractive...
The readability is somewhat hindered by all the quote marks, but if you
format it differently
(format "Altitude= %"
(+ alt 100)
".2f, direction = %"
(- dir)
".2f.")
it's perhaps clearer. But the "%" on one line and the ".2f" on the next
is perhaps not optimal? Hm... What about something like... er...
(format "Altitude= %.2f%" (+ alt 100) ", direction = %.2f%" (- dir) ".")
Does that look clearer?
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 17:46 ` Paul Eggert
2016-12-12 18:33 ` Lars Ingebrigtsen
@ 2016-12-12 19:51 ` Ted Zlatanov
2016-12-12 20:41 ` Paul Eggert
1 sibling, 1 reply; 86+ messages in thread
From: Ted Zlatanov @ 2016-12-12 19:51 UTC (permalink / raw)
To: emacs-devel
On Mon, 12 Dec 2016 09:46:05 -0800 Paul Eggert <eggert@cs.ucla.edu> wrote:
PE> Why not just extend "format" so that it allows trailing "...%" in the format
PE> string to mean "argument value spliced here"? After the argument you can
PE> continue on with the format, which must start with the rest of the conversion
PE> specification. E.g.:
PE> (format "Altitude= %" alt ".2f, direction = %" dir ".2f.")
PE> might output "Altitude = 300.57, direction = 240.93."
I like how this separates expressions from strings. It might be more
readable if the % begins the next string:
(format "Altitude= " alt "%.2f, direction = " dir "%.2f.")
It has some downsides: it only works in one function; `(apply 'format ...)`
can become surprising; and repeating a parameter requires duplicating
the code.
Ted
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 19:51 ` Ted Zlatanov
@ 2016-12-12 20:41 ` Paul Eggert
2016-12-12 23:40 ` Paul Eggert
0 siblings, 1 reply; 86+ messages in thread
From: Paul Eggert @ 2016-12-12 20:41 UTC (permalink / raw)
To: emacs-devel; +Cc: Lars Ingebrigtsen
On 12/12/2016 11:51 AM, Ted Zlatanov wrote:
> I like how this separates expressions from strings. It might be more
> readable if the % begins the next string:
>
> (format "Altitude= " alt "%.2f, direction = " dir "%.2f.")
Unfortunately although this syntax is clean it would not be upward
compatible, as 'format' currently silently discards excess trailing
arguments. In contrast, Lars's suggestion:
> (format "Altitude= %.2f%" alt ", direction = %.2f%" dir ".")
is upward compatible. Also, I suspect that Lars's suggestion will be
less error-prone than mine, as it would be more likely to diagnose stray
occurrences of "%" at the end of a format.
> It has some downsides: it only works in one function; `(apply 'format ...)`
> can become surprising; and repeating a parameter requires duplicating
> the code.
True for repeating a nontrivial parameter. However, that is not common
and 'let' should be good enough for that, e.g., (let ((dup (complicated
expression))) (format "appearance1 = %f%" dup ", appearance2 = %g%." dup)).
I'm not sure what is meant mean by 'only works in one function'.
format-message should behave like 'format', and any function that calls
'format' or 'format-message' will get the extended behavior for free.
For example, (message ...) would get the extended behavior.
(apply 'format FMT ...) would not get the extended behavior unless FMT
itself uses the extension, and this should be good enough to avoid most
surprises.
Ah, perhaps you're thinking about mixed forms like (format "x = %1d, y =
%2d%" EX WYE ", z = %3d" ZEE)? To avoid confusion, the extension could
work only if the format string has just one conversion specifier, at the
end (just before the "%" at end of string). The idea would be to
encourage people to write either the extended (format "x = %1d%" EX ", y
= %2d%" WYE ", z = %3d%" ZEE) or the traditional (format "x = %1d, y =
%2d, z = %3d" EX WYE ZEE) instead of trying to write a confusing mixture
of the two.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 20:41 ` Paul Eggert
@ 2016-12-12 23:40 ` Paul Eggert
2016-12-13 17:42 ` Richard Stallman
0 siblings, 1 reply; 86+ messages in thread
From: Paul Eggert @ 2016-12-12 23:40 UTC (permalink / raw)
To: emacs-devel; +Cc: Lars Ingebrigtsen
[-- Attachment #1: Type: text/plain, Size: 335 bytes --]
Attached is a proposed patch to implement string interpolation in
'format' and friends. It uses gotos; although I could rewrite it to use
flags instead, that would bloat the patch considerably and the
surrounding code is already goto-plagued. It needs documentation of
course (which will be more work than the code, I expect ...).
[-- Attachment #2: 0001-Add-string-interpolation-to-format.patch --]
[-- Type: application/x-patch, Size: 6785 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 23:40 ` Paul Eggert
@ 2016-12-13 17:42 ` Richard Stallman
2016-12-13 18:05 ` Paul Eggert
0 siblings, 1 reply; 86+ messages in thread
From: Richard Stallman @ 2016-12-13 17:42 UTC (permalink / raw)
To: Paul Eggert; +Cc: larsi, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
We have seen various proposals for what string interpolation should do.
What spec does your patch implement?
--
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-13 17:42 ` Richard Stallman
@ 2016-12-13 18:05 ` Paul Eggert
2016-12-13 23:55 ` Lars Ingebrigtsen
2016-12-14 17:00 ` Richard Stallman
0 siblings, 2 replies; 86+ messages in thread
From: Paul Eggert @ 2016-12-13 18:05 UTC (permalink / raw)
To: rms; +Cc: larsi, emacs-devel
On 12/13/2016 09:42 AM, Richard Stallman wrote:
> We have seen various proposals for what string interpolation should do.
> What spec does your patch implement?
It implements Lars's proposal here:
http://lists.gnu.org/archive/html/emacs-devel/2016-12/msg00504.html
His example:
(format "Altitude= %.2f%" (+ alt 100) ", direction = %.2f%" (- dir) ".")
might generate:
"Altitude= 400.57, direction = -240.93."
The idea is that if a format string's first conversion specifier is
followed by "%" and end-of-string, the value to be formatted is followed
by another format string that continues the first string. This is an
extension to the current behavior of 'format', where the trailing "%" is
an error.
Similar rules apply to other formatting functions like 'message'. For
example, this code in org-clock.el:
(message (concat "Clock stopped at %s after "
(org-minutes-to-clocksum-string (+ (* 60 h) m))
"%s")
te (if remove " => LINE REMOVED" ""))
could be rewritten this way:
(message "Clock stopped at %s%" te
" after %s%" (org-minutes-to-clocksum-string (+ (* 60 h)
m))
"%s" (if remove " => LINE REMOVED" ""))
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-13 18:05 ` Paul Eggert
@ 2016-12-13 23:55 ` Lars Ingebrigtsen
2016-12-14 0:07 ` Paul Eggert
2016-12-14 17:00 ` Richard Stallman
1 sibling, 1 reply; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-13 23:55 UTC (permalink / raw)
To: Paul Eggert; +Cc: rms, emacs-devel
Paul Eggert <eggert@cs.ucla.edu> writes:
> (message (concat "Clock stopped at %s after "
> (org-minutes-to-clocksum-string (+ (* 60 h) m))
> "%s")
> te (if remove " => LINE REMOVED" ""))
>
> could be rewritten this way:
>
> (message "Clock stopped at %s%" te
> " after %s%" (org-minutes-to-clocksum-string (+ (* 60 h) m))
> "%s" (if remove " => LINE REMOVED" ""))
I've been trying out this syntax a bit (just rewriting a few statements
to see whether they look better or worse than the old statements :-)),
and I think I kinda like it.
It seems clean and there's no "magic", so there are no corner cases that
I can see.
The number of ""s may be an impediment against using it in some cases,
though. If you look at a simple format statement today:
(message "The time is %d in the %s bit of %s" clock part country)
I don't think you'd want to rewrite that to
(message "The time is %d%" clock " in the %s%" part " bit of %s%" country)
Or would you? (The final "%" is optional, of course.") It has the
advantage that you don't have to count to match up variables with
formatting statements, but it's not as immediately clear what the
resulting string will end up looking like.
Hm...
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-13 23:55 ` Lars Ingebrigtsen
@ 2016-12-14 0:07 ` Paul Eggert
2016-12-14 0:10 ` John Wiegley
` (2 more replies)
0 siblings, 3 replies; 86+ messages in thread
From: Paul Eggert @ 2016-12-14 0:07 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: rms, emacs-devel
On 12/13/2016 03:55 PM, Lars Ingebrigtsen wrote:
> I don't think you'd want to rewrite that to
>
> (message "The time is %d%" clock " in the %s%" part " bit of %s%" country)
>
> Or would you? (The final "%" is optional, of course.")
Apparently some people prefer this style -- it's what started the
thread, after all.
A minor point: in the currently-proposed implementation, that final "%"
is not allowed. It is easy to add support for it as a further (very
small) extension.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-14 0:07 ` Paul Eggert
@ 2016-12-14 0:10 ` John Wiegley
2016-12-14 0:14 ` Lars Ingebrigtsen
` (2 more replies)
2016-12-14 0:21 ` Clément Pit--Claudel
2016-12-14 14:10 ` Lars Ingebrigtsen
2 siblings, 3 replies; 86+ messages in thread
From: John Wiegley @ 2016-12-14 0:10 UTC (permalink / raw)
To: Paul Eggert; +Cc: Lars Ingebrigtsen, rms, emacs-devel
>>>>> "PE" == Paul Eggert <eggert@cs.ucla.edu> writes:
PE> Apparently some people prefer this style -- it's what started the thread,
PE> after all.
What if we did something a little more implicit:
For a format string, the number of occurrences % in that string determines how
many arguments it "consumes". Once that many arguments have been consumed, the
process restarts.
This way you could just say:
(format "This %d" 10 " and this %d" 20)
Or:
(format "This %d and %d" 10 20 " and this %d" 30)
Or:
(format "This %d and %d and %d" 10 20 30)
Then there is no reason to assign a special meaning to "%" at the end of a
format string.
--
John Wiegley GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com 60E1 46C4 BD1A 7AC1 4BA2
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-14 0:10 ` John Wiegley
@ 2016-12-14 0:14 ` Lars Ingebrigtsen
2016-12-14 0:17 ` Paul Eggert
2016-12-14 0:24 ` Drew Adams
2 siblings, 0 replies; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-14 0:14 UTC (permalink / raw)
To: emacs-devel
John Wiegley <jwiegley@gmail.com> writes:
> This way you could just say:
>
> (format "This %d" 10 " and this %d" 20)
It's slightly ambiguous, because that's a valid (if odd) statement in
Emacs today:
(format "This %d" 10 " and this %d" 20)
=> "This 10"
We may not care, though.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-14 0:10 ` John Wiegley
2016-12-14 0:14 ` Lars Ingebrigtsen
@ 2016-12-14 0:17 ` Paul Eggert
2016-12-14 0:26 ` John Wiegley
2016-12-14 0:24 ` Drew Adams
2 siblings, 1 reply; 86+ messages in thread
From: Paul Eggert @ 2016-12-14 0:17 UTC (permalink / raw)
To: Lars Ingebrigtsen, rms, emacs-devel
On 12/13/2016 04:10 PM, John Wiegley wrote:
> This way you could just say:
>
> (format "This %d" 10 " and this %d" 20)
>
> Or:
>
> (format "This %d and %d" 10 20 " and this %d" 30)
>
> Or:
>
> (format "This %d and %d and %d" 10 20 30)
Although that would work, it's an incompatible change to documented
behavior. The manual currently says that excess arguments are ignored,
which means that currently all three expressions have well-defined (and
differing) behaviors.
A few months ago I changed 'message' in an incompatible way, figuring
that almost nobody would care. Boy, was I wrong! That being said, I
agree that the above style is simpler and would be easy to implement,
and I can do it that way if you prefer.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-14 0:17 ` Paul Eggert
@ 2016-12-14 0:26 ` John Wiegley
2016-12-14 1:48 ` Drew Adams
0 siblings, 1 reply; 86+ messages in thread
From: John Wiegley @ 2016-12-14 0:26 UTC (permalink / raw)
To: Paul Eggert; +Cc: Lars Ingebrigtsen, rms, emacs-devel
>>>>> "PE" == Paul Eggert <eggert@cs.ucla.edu> writes:
PE> Although that would work, it's an incompatible change to documented
PE> behavior. The manual currently says that excess arguments are ignored,
PE> which means that currently all three expressions have well-defined (and
PE> differing) behaviors.
PE> A few months ago I changed 'message' in an incompatible way, figuring that
PE> almost nobody would care. Boy, was I wrong! That being said, I agree that
PE> the above style is simpler and would be easy to implement, and I can do it
PE> that way if you prefer.
I see. Personally, I don't think we need to extend format at all. How many
others really want this extension?
--
John Wiegley GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com 60E1 46C4 BD1A 7AC1 4BA2
^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: RFC: String interpolation
2016-12-14 0:26 ` John Wiegley
@ 2016-12-14 1:48 ` Drew Adams
2016-12-14 2:48 ` Elias Mårtenson
2016-12-14 13:52 ` Lars Brinkhoff
0 siblings, 2 replies; 86+ messages in thread
From: Drew Adams @ 2016-12-14 1:48 UTC (permalink / raw)
To: John Wiegley, Paul Eggert; +Cc: Lars Ingebrigtsen, rms, emacs-devel
> I see. Personally, I don't think we need to extend format at all.
> How many others really want this extension?
Not I. Not in the ways discussed so far, at least. Current
`format' is better (for me).
(On the other hand, if someone were to work toward a `cl-format',
even one that was partial and could be extended later, I'd likely
welcome that.)
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-14 1:48 ` Drew Adams
@ 2016-12-14 2:48 ` Elias Mårtenson
2016-12-14 3:33 ` Drew Adams
2016-12-14 13:52 ` Lars Brinkhoff
1 sibling, 1 reply; 86+ messages in thread
From: Elias Mårtenson @ 2016-12-14 2:48 UTC (permalink / raw)
To: Drew Adams; +Cc: John Wiegley, Lars Ingebrigtsen, Paul Eggert, rms, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 687 bytes --]
On 14 December 2016 at 09:48, Drew Adams <drew.adams@oracle.com> wrote:
> > I see. Personally, I don't think we need to extend format at all.
> > How many others really want this extension?
>
> Not I. Not in the ways discussed so far, at least. Current
> `format' is better (for me).
>
> (On the other hand, if someone were to work toward a `cl-format',
> even one that was partial and could be extended later, I'd likely
> welcome that.)
>
There is one available on MELPA already, under the name ‘cl-format’.
Some basic testing seems to suggest that it works reasonably well:
ELISP> *(cl-format nil "~{~s~^, ~}" '(1 2 3 4))*
"1, 2, 3, 4"
Regards,
Elias
[-- Attachment #2: Type: text/html, Size: 1292 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: RFC: String interpolation
2016-12-14 2:48 ` Elias Mårtenson
@ 2016-12-14 3:33 ` Drew Adams
2016-12-14 3:52 ` Elias Mårtenson
0 siblings, 1 reply; 86+ messages in thread
From: Drew Adams @ 2016-12-14 3:33 UTC (permalink / raw)
To: Elias Mårtenson
Cc: John Wiegley, Lars Ingebrigtsen, Paul Eggert, rms, emacs-devel
>> (On the other hand, if someone were to work toward a `cl-format',
>> even one that was partial and could be extended later, I'd likely
>> welcome that.)
>
> There is one available on MELPA already, under the name ‘cl-format’.
> Some basic testing seems to suggest that it works reasonably well:
> (cl-format nil "~{~s~^, ~}" '(1 2 3 4)) --> "1, 2, 3, 4"
Great. Perhaps the author will agree to including it in GNU Emacs
(signing papers etc.).
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-14 3:33 ` Drew Adams
@ 2016-12-14 3:52 ` Elias Mårtenson
0 siblings, 0 replies; 86+ messages in thread
From: Elias Mårtenson @ 2016-12-14 3:52 UTC (permalink / raw)
To: Drew Adams; +Cc: John Wiegley, Lars Ingebrigtsen, Paul Eggert, rms, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 720 bytes --]
The author is Andreas Politz <politza@fh-trier.de>.
According to the comments in the file, it's based on the GNU CLISP
implementation.
Regards,
Elias
On 14 December 2016 at 11:33, Drew Adams <drew.adams@oracle.com> wrote:
> >> (On the other hand, if someone were to work toward a `cl-format',
> >> even one that was partial and could be extended later, I'd likely
> >> welcome that.)
> >
> > There is one available on MELPA already, under the name ‘cl-format’.
> > Some basic testing seems to suggest that it works reasonably well:
> > (cl-format nil "~{~s~^, ~}" '(1 2 3 4)) --> "1, 2, 3, 4"
>
> Great. Perhaps the author will agree to including it in GNU Emacs
> (signing papers etc.).
>
[-- Attachment #2: Type: text/html, Size: 1221 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-14 1:48 ` Drew Adams
2016-12-14 2:48 ` Elias Mårtenson
@ 2016-12-14 13:52 ` Lars Brinkhoff
2016-12-14 13:57 ` Lars Brinkhoff
1 sibling, 1 reply; 86+ messages in thread
From: Lars Brinkhoff @ 2016-12-14 13:52 UTC (permalink / raw)
To: emacs-devel
Drew Adams writes:
> On the other hand, if someone were to work toward a `cl-format', even
> one that was partial and could be extended later, I'd likely welcome
> that.
I have a pretty complete Common Lisp FORMAT implemented in Emacs Lisp.
It's part of my emacs-cl.
https://github.com/larsbrinkhoff/emacs-cl/blob/master/src/cl-format.el
^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: RFC: String interpolation
2016-12-14 0:10 ` John Wiegley
2016-12-14 0:14 ` Lars Ingebrigtsen
2016-12-14 0:17 ` Paul Eggert
@ 2016-12-14 0:24 ` Drew Adams
2 siblings, 0 replies; 86+ messages in thread
From: Drew Adams @ 2016-12-14 0:24 UTC (permalink / raw)
To: John Wiegley, Paul Eggert; +Cc: Lars Ingebrigtsen, rms, emacs-devel
> What if we did something a little more implicit:
>
> For a format string, the number of occurrences % in that string determines
> how many arguments it "consumes". Once that many arguments have been
> consumed, the process restarts.
See also http://www.gigamonkeys.com/book/a-few-format-recipes.html.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-14 0:07 ` Paul Eggert
2016-12-14 0:10 ` John Wiegley
@ 2016-12-14 0:21 ` Clément Pit--Claudel
2016-12-14 14:10 ` Lars Ingebrigtsen
2 siblings, 0 replies; 86+ messages in thread
From: Clément Pit--Claudel @ 2016-12-14 0:21 UTC (permalink / raw)
To: emacs-devel
[-- Attachment #1.1: Type: text/plain, Size: 548 bytes --]
On 2016-12-13 19:07, Paul Eggert wrote:
> On 12/13/2016 03:55 PM, Lars Ingebrigtsen wrote:
>> I don't think you'd want to rewrite that to
>>
>> (message "The time is %d%" clock " in the %s%" part " bit of %s%" country)
>>
>> Or would you? (The final "%" is optional, of course.")
>
> Apparently some people prefer this style -- it's what started the thread, after all.
I'm not sure. I started the thread, but I don't think I'd use this style much — the extra percent signs and quotes make it look a bit cluttered :/
Clément.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-14 0:07 ` Paul Eggert
2016-12-14 0:10 ` John Wiegley
2016-12-14 0:21 ` Clément Pit--Claudel
@ 2016-12-14 14:10 ` Lars Ingebrigtsen
2 siblings, 0 replies; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-14 14:10 UTC (permalink / raw)
To: Paul Eggert; +Cc: rms, emacs-devel
Paul Eggert <eggert@cs.ucla.edu> writes:
>> I don't think you'd want to rewrite that to
>>
>> (message "The time is %d%" clock " in the %s%" part " bit of %s%" country)
>>
>> Or would you? (The final "%" is optional, of course.")
>
> Apparently some people prefer this style -- it's what started the
> thread, after all.
Well, no -- that's not the style that started the thread. :-)
What some people would like is something that looks like
(message "The time is $clock in the $part bit of $country")
which is very different visually and comprehension wise: You see pretty
much immediately what the result is going to look like by looking at the
source code, while that's not true for the interpolated version at the
time, which has a lot more visual noise.
But, as I've said, I have reservations (and no enthusiasm) about simple
string interpolation, and I have some doubts that the style at the top
will satisfy the craving for simple string interpolation.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-13 18:05 ` Paul Eggert
2016-12-13 23:55 ` Lars Ingebrigtsen
@ 2016-12-14 17:00 ` Richard Stallman
1 sibling, 0 replies; 86+ messages in thread
From: Richard Stallman @ 2016-12-14 17:00 UTC (permalink / raw)
To: Paul Eggert; +Cc: larsi, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> (format "Altitude= %.2f%" (+ alt 100) ", direction = %.2f%" (- dir) ".")
That interface seems pretty clean.
--
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 9:44 ` Lars Ingebrigtsen
` (2 preceding siblings ...)
2016-12-12 17:46 ` Paul Eggert
@ 2016-12-12 19:43 ` Richard Stallman
2016-12-12 21:11 ` Lars Ingebrigtsen
2016-12-13 1:04 ` Ted Zlatanov
3 siblings, 2 replies; 86+ messages in thread
From: Richard Stallman @ 2016-12-12 19:43 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: monnier, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> (let ((thing-formatted (replace-regexp-in-string " +" " " thing)))
> (fmt "This is %{thing-formatted}.2f"))
> That is, you're forced to both name and introduce a new temporary
> variable, and you have to alter the format statement itself. (This is
> what PHP programmers do all the time, and it kinda sucks.)
> With the optional keyword arguments, you just add it:
> (fmt "This is %{thing}.2f"
> :thing (replace-regexp-in-string " +" " " thing))
If we are going to allow referencing variables, and referencing
keyword arguments, we should distinguish them in the syntax.
Perhaps write a colon to reference a keyword argument,
like this:
> (fmt "This is %{:thing}.2f"
> :thing (replace-regexp-in-string " +" " " thing))
Another syntactical issue is that '%{thing}.2f' has a problem:
Does it mean %{thing} formatted according to '.2f', or
%{thing} followed by the text '.2f'?
Using the syntax '%[.2f]{thing}' is superior because it avoids
any syntactic ambiguity.
--
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 19:43 ` Richard Stallman
@ 2016-12-12 21:11 ` Lars Ingebrigtsen
2016-12-13 17:41 ` Richard Stallman
2016-12-13 1:04 ` Ted Zlatanov
1 sibling, 1 reply; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-12 21:11 UTC (permalink / raw)
To: Richard Stallman; +Cc: monnier, emacs-devel
Richard Stallman <rms@gnu.org> writes:
> > (fmt "This is %{:thing}.2f"
> > :thing (replace-regexp-in-string " +" " " thing))
>
> Another syntactical issue is that '%{thing}.2f' has a problem:
> Does it mean %{thing} formatted according to '.2f', or
> %{thing} followed by the text '.2f'?
>
> Using the syntax '%[.2f]{thing}' is superior because it avoids
> any syntactic ambiguity.
Hm... I don't think there's any ambiguity, really. The syntax for
format specs is still %<stuff><letter>. So %{thing}.2f is unambiguously
the value of `thing' formatted as a floating point with two decimal
places.
I mean, %{thing}.2f isn't a valid formatting directive today, so I'm
afraid I don't quite see the ambiguity. Unless I'm missing something
here...
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 21:11 ` Lars Ingebrigtsen
@ 2016-12-13 17:41 ` Richard Stallman
2016-12-13 17:43 ` Lars Ingebrigtsen
0 siblings, 1 reply; 86+ messages in thread
From: Richard Stallman @ 2016-12-13 17:41 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: monnier, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> I mean, %{thing}.2f isn't a valid formatting directive today, so I'm
> afraid I don't quite see the ambiguity.
Perhaps I misunderstood that proposal. Would %{thing} by itself be
valid?
--
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-13 17:41 ` Richard Stallman
@ 2016-12-13 17:43 ` Lars Ingebrigtsen
2016-12-14 17:01 ` Richard Stallman
0 siblings, 1 reply; 86+ messages in thread
From: Lars Ingebrigtsen @ 2016-12-13 17:43 UTC (permalink / raw)
To: Richard Stallman; +Cc: monnier, emacs-devel
Richard Stallman <rms@gnu.org> writes:
> Perhaps I misunderstood that proposal. Would %{thing} by itself be
> valid?
No.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-13 17:43 ` Lars Ingebrigtsen
@ 2016-12-14 17:01 ` Richard Stallman
0 siblings, 0 replies; 86+ messages in thread
From: Richard Stallman @ 2016-12-14 17:01 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: monnier, emacs-devel
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> > Perhaps I misunderstood that proposal. Would %{thing} by itself be
> > valid?
> No.
That means I made a mistake. It's not ambiguous, but it is rather
ugly to put the format spec after the interpolated value.
The syntax with square-brackets before the interpolated value is
cleaner.
--
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 19:43 ` Richard Stallman
2016-12-12 21:11 ` Lars Ingebrigtsen
@ 2016-12-13 1:04 ` Ted Zlatanov
1 sibling, 0 replies; 86+ messages in thread
From: Ted Zlatanov @ 2016-12-13 1:04 UTC (permalink / raw)
To: emacs-devel
On Mon, 12 Dec 2016 12:41:38 -0800 Paul Eggert <eggert@cs.ucla.edu> wrote:
PE> I'm not sure what is meant mean by 'only works in one function'. format-message
PE> should behave like 'format', and any function that calls 'format' or
PE> 'format-message' will get the extended behavior for free. For example, (message
PE> ...) would get the extended behavior.
I mean that if any string could use that syntax at the expression reader
level, it would be essentially a new macro syntax that can make strings
anywhere. I think that's more useful to more people than just `format'
and friends. Maybe #["format" "parameters" "here"] or something like that.
Ted
^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: RFC: String interpolation
2016-12-12 2:39 ` Stefan Monnier
2016-12-12 9:44 ` Lars Ingebrigtsen
@ 2016-12-12 16:39 ` Helmut Eller
1 sibling, 0 replies; 86+ messages in thread
From: Helmut Eller @ 2016-12-12 16:39 UTC (permalink / raw)
To: emacs-devel
On Sun, Dec 11 2016, Stefan Monnier wrote:
>>> Keyword paramaters are also an option:
>>> (fmt "This is %{thing}.2f and %{zot}ss" :thing (funcall '+ 3.42423 4))
>> Yeah, that's prettier.
>
> FWIW, I don't see why that's preferable to
>
> (let ((thing (funcall '+ 3.45453 4)))
> (preformat "This is %[2f]{thing} and %{zot}ss"))
Rust also uses "named arguments" (aka keyword paramaters) for their fmt
macro. Maybe the Rust designers could explain why. See:
https://doc.rust-lang.org/std/fmt/
Helmut
^ permalink raw reply [flat|nested] 86+ messages in thread
end of thread, other threads:[~2016-12-14 17:01 UTC | newest]
Thread overview: 86+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-12-08 1:13 RFC: String interpolation Clément Pit--Claudel
2016-12-08 8:27 ` Andreas Schwab
2016-12-08 8:38 ` Joost Kremers
2016-12-08 9:05 ` Philippe Vaucher
2016-12-08 18:25 ` Clément Pit--Claudel
2016-12-08 9:02 ` Philippe Vaucher
2016-12-08 18:22 ` Clément Pit--Claudel
2016-12-08 14:43 ` Joost Kremers
2016-12-08 18:37 ` Clément Pit--Claudel
2016-12-08 20:04 ` Stefan Monnier
2016-12-09 8:57 ` Joost Kremers
2016-12-08 15:51 ` Drew Adams
2016-12-08 18:21 ` Clément Pit--Claudel
2016-12-08 20:38 ` Richard Stallman
[not found] ` <<E1cF5SK-0000HO-EL@fencepost.gnu.org>
2016-12-08 22:04 ` Drew Adams
2016-12-08 19:05 ` Stefan Monnier
2016-12-08 19:31 ` Clément Pit--Claudel
2016-12-08 21:31 ` Stefan Monnier
2016-12-10 16:01 ` Clément Pit--Claudel
2016-12-09 19:19 ` Ted Zlatanov
2016-12-09 22:45 ` Clément Pit--Claudel
2016-12-11 2:53 ` Ted Zlatanov
2016-12-11 18:46 ` Lars Ingebrigtsen
2016-12-11 18:56 ` Clément Pit--Claudel
2016-12-11 19:34 ` Lars Ingebrigtsen
2016-12-11 17:38 ` Stefan Monnier
2016-12-11 17:53 ` Clément Pit--Claudel
2016-12-10 14:11 ` Lars Ingebrigtsen
2016-12-10 14:25 ` Clément Pit--Claudel
2016-12-10 15:39 ` Lars Ingebrigtsen
2016-12-10 15:49 ` Clément Pit--Claudel
2016-12-10 16:01 ` Yuri Khan
2016-12-10 17:58 ` Clément Pit--Claudel
2016-12-11 17:47 ` Stefan Monnier
2016-12-11 19:31 ` Yuri Khan
2016-12-11 20:12 ` Stefan Monnier
2016-12-11 9:35 ` Richard Stallman
2016-12-11 16:29 ` Clément Pit--Claudel
2016-12-11 18:42 ` Lars Ingebrigtsen
2016-12-12 19:41 ` Richard Stallman
2016-12-11 18:41 ` Lars Ingebrigtsen
2016-12-11 21:05 ` Helmut Eller
2016-12-11 21:26 ` Lars Ingebrigtsen
2016-12-12 2:39 ` Stefan Monnier
2016-12-12 9:44 ` Lars Ingebrigtsen
2016-12-12 13:03 ` Stefan Monnier
2016-12-12 14:47 ` Lars Ingebrigtsen
2016-12-12 15:04 ` Stefan Monnier
2016-12-12 15:26 ` Lars Ingebrigtsen
2016-12-12 17:05 ` Stefan Monnier
2016-12-12 17:12 ` Lars Ingebrigtsen
2016-12-12 17:23 ` Stefan Monnier
2016-12-12 13:40 ` Clément Pit--Claudel
2016-12-12 14:43 ` Lars Ingebrigtsen
2016-12-12 14:54 ` Clément Pit--Claudel
2016-12-12 17:14 ` Stefan Monnier
2016-12-12 17:46 ` Paul Eggert
2016-12-12 18:33 ` Lars Ingebrigtsen
2016-12-12 19:51 ` Ted Zlatanov
2016-12-12 20:41 ` Paul Eggert
2016-12-12 23:40 ` Paul Eggert
2016-12-13 17:42 ` Richard Stallman
2016-12-13 18:05 ` Paul Eggert
2016-12-13 23:55 ` Lars Ingebrigtsen
2016-12-14 0:07 ` Paul Eggert
2016-12-14 0:10 ` John Wiegley
2016-12-14 0:14 ` Lars Ingebrigtsen
2016-12-14 0:17 ` Paul Eggert
2016-12-14 0:26 ` John Wiegley
2016-12-14 1:48 ` Drew Adams
2016-12-14 2:48 ` Elias Mårtenson
2016-12-14 3:33 ` Drew Adams
2016-12-14 3:52 ` Elias Mårtenson
2016-12-14 13:52 ` Lars Brinkhoff
2016-12-14 13:57 ` Lars Brinkhoff
2016-12-14 0:24 ` Drew Adams
2016-12-14 0:21 ` Clément Pit--Claudel
2016-12-14 14:10 ` Lars Ingebrigtsen
2016-12-14 17:00 ` Richard Stallman
2016-12-12 19:43 ` Richard Stallman
2016-12-12 21:11 ` Lars Ingebrigtsen
2016-12-13 17:41 ` Richard Stallman
2016-12-13 17:43 ` Lars Ingebrigtsen
2016-12-14 17:01 ` Richard Stallman
2016-12-13 1:04 ` Ted Zlatanov
2016-12-12 16:39 ` Helmut Eller
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).