emacs-devel
[Top][All Lists]
Advanced

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

Re: Improve `replace-regexp-in-string' ergonomics?


From: Dmitry Gutov
Subject: Re: Improve `replace-regexp-in-string' ergonomics?
Date: Thu, 23 Sep 2021 01:23:07 +0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0

On 22.09.2021 23:18, Lars Ingebrigtsen wrote:

But if we target thread-first instead and make the new function accept
STRING in the first position, all optional arguments would be still
available.

Yes, I've always found it weird that these functions have the object to
be worked upon as the last non-optional parameter.  I had to look it up
for years when using `replace-regexp-in-string'.  And it didn't help
that Emacs took this function from XEmacs, which had the string in a
different position...  But I don't remember where...

*Lars says "apt install xemacs21"*

I misremembered:

`replace-in-string' is a compiled Lisp function
   -- loaded from "/build/xemacs21-rcHAYB/xemacs21-21.4.24/lisp/subr.elc"
(replace-in-string STR REGEXP NEWTEXT &optional LITERAL)

So it has the placement of STRING that seems logical, I think.

On the other hand, changing the placement in a new function like this
will probably be even more confusing.

Adding a new function is the only time we *can* change the arguments order. If we subsequently obsolete the current function, it could fly.

It's not the wildest among the alternatives anyway -- the idea about the argument being a list takes the first place, I think. And either could work, ultimately.

If we want to be able to use threading macros more consistently, it seems functions should expect the "main" argument in either the first or the last position, across the standard library. Or at least portions of it.

For example, in Clojure:

  By convention, core functions that operate on sequences expect the
  sequence as their last argument. Accordingly, pipelines containing
  map, filter, remove, reduce, into, etc usually call for the ->> macro.

  Core functions that operate on data structures, on the other hand,
  expect the value they work on as their first argument. These include
  assoc, update, dissoc, get and their -in variants. Pipelines that
  transform maps using these functions often require the -> macro.

(https://clojure.org/guides/threading_macros)

It seems to me, with penchant for optional arguments, it's generally harder to put the "main" argument into the last position in our case. I could be wrong, though. But STRING being in neither first or last position makes threading macro decidedly less useful.

                (regexp-replace "'" "\""
                                ",[[:space:]]" " "
                                "\\]" ")"
                                "\\[" "("
                                results)))
Or some variation thereupon with some more ()s to group pairs.

I'm not sure how to also make it accept "normal" convention, and we
probably don't want to always have to wrap the args in an alist, even
when only one replacement is needed.

No, that's the problem.  We could hack it up by doing a &rest in
reality, and then checking if the first parameter is a list, but yuck.

Probably check that the number of &rest arguments divides by two as well. Or three, or four? FIXEDCASE, LITERAL and SUBEXP could apply to a single replacement. At best, it will create an ambiguity (do those args apply to all steps, or do I need to repeat them?), but at worst it can limit the applicability of the approach (when steps need different values of these). Threading solves it.

      (setq author (regexp-remove "[ \t]*[(<].*$" author))
      (setq author (regexp-remove "\\`[ \t]+" author))
      (setq author (regexp-remove "[ \t]+$" author))
      (setq author (regexp-replace "[ \t]+" " " author))

IDK, if that leads to no increase in efficiency, then probably not?
Replacing with "" is an established pattern by now.

It helps with readability -- the function says what the intention is.

True. I'm not sold, though.



reply via email to

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