bug#26338: 26.0.50; Collect all matches for REGEXP in current buffer

classic Classic list List threaded Threaded
31 messages Options
12
Reply | Threaded
Open this post in threaded view
|

bug#26338: 26.0.50; Collect all matches for REGEXP in current buffer

Philipp Stephani


Tino Calancha <[hidden email]> schrieb am Sa., 8. Apr. 2017 um 06:46 Uhr:


On Fri, 7 Apr 2017, Drew Adams wrote:

>>> Or an addition to cl-loop that would allow doing something like
>>>
>>>    (cl-loop for m being the matches of "foo\\|bar"
>>>             do ...)
>>>
>>> Then you could easily 'collect m' to get the list of matches if you want
>>> that.
>>
>> Your proposals looks nice to me ;-)
>
> (Caveat: I have not been following this thread.)
>
> I think that `cl-loop' should be as close to Common Lisp `loop'
> as we can reasonably make it.  We should _not_ be adding other
> features to it or changing its behavior away from what it is
> supposedly emulating.
>
> If you want, create a _different_ macro that is Emacs-specific,
> with whatever behavior you want.  Call it whatever you want
> that will not be confused with Common Lisp emulation.
>
> Please keep `cl-' for Common Lisp emulation.  We've already
> seen more than enough tampering with this - people adding
> their favorite thing to the `cl-' namespace.  Not good.
Drew, i respect your opinion; but so far the change
would just extend `cl-loop' which as you noticed has being already
extended before.
For instance, we have:
cl-loop for x being the overlays/buffers ...

Don't see a problem to have those things. 

I do. They couple the idea of an iterable with a looping construct, and such coupling is bad for various reasons:
- Coupling of unrelated entities is always an antipattern.
- For N iterables and M looping constructs, you need to implement N*M integrations.
Instead this should use an iterable, e.g. a generator function (iter-defun). cl-loop supports these out of the box.
Reply | Threaded
Open this post in threaded view
|

bug#26338: 26.0.50; Collect all matches for REGEXP in current buffer

Tino Calancha-2


On Sat, 8 Apr 2017, Philipp Stephani wrote:

>
>
> Tino Calancha <[hidden email]> schrieb am Sa., 8. Apr. 2017 um 06:46 Uhr:
>
>
>       On Fri, 7 Apr 2017, Drew Adams wrote:
>
>       >>> Or an addition to cl-loop that would allow doing something like
>       >>>
>       >>>    (cl-loop for m being the matches of "foo\\|bar"
>       >>>             do ...)
>       >>>
>       >>> Then you could easily 'collect m' to get the list of matches if you want
>       >>> that.
>       >>
>       >> Your proposals looks nice to me ;-)
>       >
>       > (Caveat: I have not been following this thread.)
>       >
>       > I think that `cl-loop' should be as close to Common Lisp `loop'
>       > as we can reasonably make it.  We should _not_ be adding other
>       > features to it or changing its behavior away from what it is
>       > supposedly emulating.
>       >
>       > If you want, create a _different_ macro that is Emacs-specific,
>       > with whatever behavior you want.  Call it whatever you want
>       > that will not be confused with Common Lisp emulation.
>       >
>       > Please keep `cl-' for Common Lisp emulation.  We've already
>       > seen more than enough tampering with this - people adding
>       > their favorite thing to the `cl-' namespace.  Not good.
>       Drew, i respect your opinion; but so far the change
>       would just extend `cl-loop' which as you noticed has being already
>       extended before.
>       For instance, we have:
>       cl-loop for x being the overlays/buffers ...
>
>       Don't see a problem to have those things. 
>
>
> I do. They couple the idea of an iterable with a looping construct, and such coupling is bad for various reasons:
> - Coupling of unrelated entities is always an antipattern.
> - For N iterables and M looping constructs, you need to implement N*M integrations.
> Instead this should use an iterable, e.g. a generator function (iter-defun). cl-loop supports these out of the box.
Then, you don't like (as Drew, but for different reasons) that we have:
cl-loop for x being the buffers ...

but it seems you are fine having iter-by clause in cl-loop, which seems an
Emacs extension (correctme if i am wrong).  So in principle, you are happy
with adding useful extensions to CL, not just keep it an emulation as
Drew wants.

Your point is about performance.  I am driven by easy to write code.
Maybe you can provide an example about how to write those things using
the iter-by cl-loop clause.
Reply | Threaded
Open this post in threaded view
|

bug#26338: 26.0.50; Collect all matches for REGEXP in current buffer

Tino Calancha-2
In reply to this post by Noam Postavsky-2
Noam Postavsky <[hidden email]> writes:

> On Fri, Apr 7, 2017 at 10:47 AM, Tino Calancha <[hidden email]> wrote:
>> +
>> +@example
>> +(cl-loop for x being the matches of "^(defun \\(\\S +\\)"
>> +         using '(group 1 limit 10)
>> +         collect x)
>> +@end example
>
> You can reuse the existing 'repeat N' clause instead of 'using (limit N)'.
>
> (cl-loop for x being the matches of "^(defun \\(\\S +\\)" using (group 1)
>          repeat 10
>          collect x)
Right! Thank you.
I fixed some other parts of the patch as well.
--8<-----------------------------cut here---------------start------------->8---
commit fc2eed78e8c5591c3aad358a885b4b5bae6c1041
Author: Tino Calancha <[hidden email]>
Date:   Sat Apr 8 22:49:10 2017 +0900

    New clause in cl-loop to iterate in the matches of a regexp
   
    Add new clause in cl-loop facility to loop over the matches for
    REGEXP in the current buffer (Bug#26338).
    * lisp/emacs-lisp/cl-macs.el (cl--parse-loop-clause): Add new clause.
    (cl-loop): update docstring.
    * doc/misc/cl.texi (For Clauses): Document the new clause.
    * etc/NEWS: Mention this change.

diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi
index 2339d57631..40b90d6003 100644
--- a/doc/misc/cl.texi
+++ b/doc/misc/cl.texi
@@ -2030,6 +2030,22 @@ For Clauses
 This clause iterates over a sequence, with @var{var} a @code{setf}-able
 reference onto the elements; see @code{in-ref} above.
 
+@item for @var{var} being the matches of @var{regexp}
+This clause iterates over the matches for @var{regexp} in the current buffer.
+By default, @var{var} is bound to the full match.  Optionally, @var{var}
+might be bound to a subpart of the match.
+For example,
+
+@example
+(cl-loop for x being the matches of "^(defun \\(\\S +\\)" using (group 1)
+         repeat 10
+         collect x)
+@end example
+
+@noindent
+collects the next 10 function names after point.
+This clause is an extension to standard Common Lisp.
+
 @item for @var{var} being the symbols [of @var{obarray}]
 This clause iterates over symbols, either over all interned symbols
 or over all symbols in @var{obarray}.  The loop is executed with
@@ -2487,8 +2503,8 @@ Other Clauses
 This package's @code{cl-loop} macro is compatible with that of Common
 Lisp, except that a few features are not implemented:  @code{loop-finish}
 and data-type specifiers.  Naturally, the @code{for} clauses that
-iterate over keymaps, overlays, intervals, frames, windows, and
-buffers are Emacs-specific extensions.
+iterate over keymaps, overlays, intervals, frames, windows, buffers, and
+matches for a regexp in the current buffer are Emacs-specific extensions.
 
 @node Multiple Values
 @section Multiple Values
diff --git a/etc/NEWS b/etc/NEWS
index e351abc159..b8298bf180 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -862,6 +862,10 @@ instead of its first.
 * Lisp Changes in Emacs 26.1
 
 +++
+** New clause in cl-loop to iterate in the matches for a regexp
+in the current buffer.
+
++++
 ** Emacs now supports records for user-defined types, via the new
 functions 'make-record', 'record', and 'recordp'.  Records are now
 used internally to represent cl-defstruct and defclass instances, for
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index ecb89fd51d..4710efd0a9 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -892,6 +892,7 @@ cl-loop
       the overlays/intervals [of BUFFER] [from POS1] [to POS2]
       the frames/buffers
       the windows [of FRAME]
+      the matches of/for REGEXP [using (group GROUP)]
   Iteration clauses:
     repeat INTEGER
     while/until/always/never/thereis CONDITION
@@ -1339,6 +1340,24 @@ cl--parse-loop-clause
   (push (list temp-idx `(1+ ,temp-idx))
  loop-for-steps)))
 
+               ((memq word '(match matches))
+ (let* ((_ (or (and (not (memq (car cl--loop-args) '(of for)))
+                                   (error "Expected `of'"))))
+                       (regexp `(if (stringp ,(cadr cl--loop-args))
+                                    ,(cl--pop2 cl--loop-args)
+                                  (error "Regexp must be an string")))
+                       (group
+                        (if (eq (car cl--loop-args) 'using)
+                            (if (and (= (length (cadr cl--loop-args)) 2)
+                                     (eq (cl-caadr cl--loop-args) 'group))
+                                (cadr (cl--pop2 cl--loop-args))
+                              (error "Bad `using' clause"))
+                          0)))
+                  (push (list var nil) loop-for-bindings)
+                  (push `(re-search-forward ,regexp nil t) cl--loop-body)
+                  (push (list var `(match-string-no-properties ,group))
+                        loop-for-sets)))
+
        ((memq word hash-types)
  (or (memq (car cl--loop-args) '(in of))
                     (error "Expected `of'"))
--8<-----------------------------cut here---------------end--------------->8---
In GNU Emacs 26.0.50 (build 14, x86_64-pc-linux-gnu, GTK+ Version 3.22.11)
 of 2017-04-08
Repository revision: 4fbfd7ad53810153371a588a9bd1a69230f60dd5



Reply | Threaded
Open this post in threaded view
|

bug#26338: 26.0.50; Collect all matches for REGEXP in current buffer

Philipp Stephani
In reply to this post by Tino Calancha-2


Tino Calancha <[hidden email]> schrieb am Sa., 8. Apr. 2017 um 15:42 Uhr:


On Sat, 8 Apr 2017, Philipp Stephani wrote:

>
>
> Tino Calancha <[hidden email]> schrieb am Sa., 8. Apr. 2017 um 06:46 Uhr:
>
>
>       On Fri, 7 Apr 2017, Drew Adams wrote:
>
>       >>> Or an addition to cl-loop that would allow doing something like
>       >>>
>       >>>    (cl-loop for m being the matches of "foo\\|bar"
>       >>>             do ...)
>       >>>
>       >>> Then you could easily 'collect m' to get the list of matches if you want
>       >>> that.
>       >>
>       >> Your proposals looks nice to me ;-)
>       >
>       > (Caveat: I have not been following this thread.)
>       >
>       > I think that `cl-loop' should be as close to Common Lisp `loop'
>       > as we can reasonably make it.  We should _not_ be adding other
>       > features to it or changing its behavior away from what it is
>       > supposedly emulating.
>       >
>       > If you want, create a _different_ macro that is Emacs-specific,
>       > with whatever behavior you want.  Call it whatever you want
>       > that will not be confused with Common Lisp emulation.
>       >
>       > Please keep `cl-' for Common Lisp emulation.  We've already
>       > seen more than enough tampering with this - people adding
>       > their favorite thing to the `cl-' namespace.  Not good.
>       Drew, i respect your opinion; but so far the change
>       would just extend `cl-loop' which as you noticed has being already
>       extended before.
>       For instance, we have:
>       cl-loop for x being the overlays/buffers ...
>
>       Don't see a problem to have those things. 
>
>
> I do. They couple the idea of an iterable with a looping construct, and such coupling is bad for various reasons:
> - Coupling of unrelated entities is always an antipattern.
> - For N iterables and M looping constructs, you need to implement N*M integrations.
> Instead this should use an iterable, e.g. a generator function (iter-defun). cl-loop supports these out of the box.
Then, you don't like (as Drew, but for different reasons) that we have:
cl-loop for x being the buffers ...

I don't like it, but it's there and cannot be removed for compatibility reasons, so I'm not arguing about it. I'm arguing against adding more such one-off forms.
 

but it seems you are fine having iter-by clause in cl-loop, which seems an
Emacs extension (correctme if i am wrong).  So in principle, you are happy
with adding useful extensions to CL, not just keep it an emulation as
Drew wants.

Yes, I don't care about Common Lisp. The iter-by clause is less of a problem than 'buffers' etc. because it's not a one-off that couples a looping construct with some random semantics.
 

Your point is about performance.

No, I care mostly about clarity, simplicity, and good API design, including separation of concerns.
 
  I am driven by easy to write code.
Maybe you can provide an example about how to write those things using
the iter-by cl-loop clause.

Sure:
 (require 'generator)
(iter-defun re-matches (regexp)
  (while (re-search-forward regexp nil t)
    (iter-yield (match-string 0))))
(iter-do (m (re-matches (rx digit)))
  (print m))
(cl-loop for m iter-by (re-matches (rx digit))
do (print m))

Reply | Threaded
Open this post in threaded view
|

bug#26338: 26.0.50; Collect all matches for REGEXP in current buffer

Tino Calancha-2


On Sat, 8 Apr 2017, Philipp Stephani wrote:

>
>
> Tino Calancha <[hidden email]> schrieb am Sa., 8. Apr. 2017 um 15:42 Uhr:
>
>
>       On Sat, 8 Apr 2017, Philipp Stephani wrote:
>
>       >
>       >
>       > Tino Calancha <[hidden email]> schrieb am Sa., 8. Apr. 2017 um 06:46 Uhr:
>       >
>       >
>       >       On Fri, 7 Apr 2017, Drew Adams wrote:
>       >
>       >       >>> Or an addition to cl-loop that would allow doing something like
>       >       >>>
>       >       >>>    (cl-loop for m being the matches of "foo\\|bar"
>       >       >>>             do ...)
>       >       >>>
>       >       >>> Then you could easily 'collect m' to get the list of matches if you want
>       >       >>> that.
>       >       >>
>       >       >> Your proposals looks nice to me ;-)
>       >       >
>       >       > (Caveat: I have not been following this thread.)
>       >       >
>       >       > I think that `cl-loop' should be as close to Common Lisp `loop'
>       >       > as we can reasonably make it.  We should _not_ be adding other
>       >       > features to it or changing its behavior away from what it is
>       >       > supposedly emulating.
>       >       >
>       >       > If you want, create a _different_ macro that is Emacs-specific,
>       >       > with whatever behavior you want.  Call it whatever you want
>       >       > that will not be confused with Common Lisp emulation.
>       >       >
>       >       > Please keep `cl-' for Common Lisp emulation.  We've already
>       >       > seen more than enough tampering with this - people adding
>       >       > their favorite thing to the `cl-' namespace.  Not good.
>       >       Drew, i respect your opinion; but so far the change
>       >       would just extend `cl-loop' which as you noticed has being already
>       >       extended before.
>       >       For instance, we have:
>       >       cl-loop for x being the overlays/buffers ...
>       >
>       >       Don't see a problem to have those things. 
>       >
>       >
>       > I do. They couple the idea of an iterable with a looping construct, and such coupling is bad for various reasons:
>       > - Coupling of unrelated entities is always an antipattern.
>       > - For N iterables and M looping constructs, you need to implement N*M integrations.
>       > Instead this should use an iterable, e.g. a generator function (iter-defun). cl-loop supports these out of the box.
>       Then, you don't like (as Drew, but for different reasons) that we have:
>       cl-loop for x being the buffers ...
>
>
> I don't like it, but it's there and cannot be removed for compatibility reasons, so I'm not arguing about it. I'm arguing against
> adding more such one-off forms.
I see.  Thanks for the clarification.

>  
>
>       but it seems you are fine having iter-by clause in cl-loop, which seems an
>       Emacs extension (correctme if i am wrong).  So in principle, you are happy
>       with adding useful extensions to CL, not just keep it an emulation as
>       Drew wants.
>
>
> Yes, I don't care about Common Lisp. The iter-by clause is less of a problem than 'buffers' etc. because it's not a one-off that
> couples a looping construct with some random semantics.
Some people like it and refer about that as the 'expressivity' of the loop
facility.  I guess it's a matter of taste, don't need to use such
constructs if you don't like it.  Some people do.
   
>
>       Your point is about performance.
>
>
> No, I care mostly about clarity, simplicity, and good API design, including separation of concerns.
Expressibity and readability might be some kind of clarity.
I totally agree about API design and separation of concerns.

>  
>         I am driven by easy to write code.
>       Maybe you can provide an example about how to write those things using
>       the iter-by cl-loop clause.
>
>
> Sure:
>  (require 'generator)
> (iter-defun re-matches (regexp)
>   (while (re-search-forward regexp nil t)
>     (iter-yield (match-string 0))))
> (iter-do (m (re-matches (rx digit)))
>   (print m))
> (cl-loop for m iter-by (re-matches (rx digit))
> do (print m))
Thank you very much for your examples.  They are nice.  I am not
as familiar as you with generators.  I must study them more.

Between A) and B), the second looks at least as simple and clear as
the first one, and probably more readable.

A)
(iter-defun re-matches (regexp)
   (while (re-search-forward regexp nil t)
     (iter-yield (match-string-no-properties 1))))

(cl-loop for m iter-by (re-matches "^(defun \\(\\S +\\)")
          collect m)

B)
(cl-loop for m the matches of "^(defun \\(\\S +\\)"
          collect m)
Reply | Threaded
Open this post in threaded view
|

bug#26338: 26.0.50; Collect all matches for REGEXP in current buffer

Tino Calancha-2
In reply to this post by Drew Adams


On Fri, 7 Apr 2017, Drew Adams wrote:


> Put all this stuff - and more - into an `eloop' macro.
> Since it will be so much better and more Emacsy, with
> specifics that are especially useful for Emacs, it is
> what users will (eventually) use instead of `cl-loop'.
>
> Since it will do everything that `cl-loop' does (and
> more), eventually only the rare user who needs, or for
> some reason really wants, code that is CL or close to
> it will use `cl-loop'.  Everyone else will use `eloop'.
> No problem.
I guess that might cause a lot of duplication of code.
IMO experts CL lispers will be more sad with this emulation
for the lack of returning multiple values than for the addition
of some extensions.  They can chose not to use them if they
don't like them.
Just one opinion too.



Reply | Threaded
Open this post in threaded view
|

bug#26338: 26.0.50; Collect all matches for REGEXP in current buffer

Noam Postavsky-2
In reply to this post by Philipp Stephani
Philipp Stephani <[hidden email]> writes:

>>> - Coupling of unrelated entities is always an antipattern.
>>> - For N iterables and M looping constructs, you need to implement
>>> N*M integrations.
>
> Yes, I don't care about Common Lisp. The iter-by clause is less of a
> problem than 'buffers' etc. because it's not a one-off that couples a
> looping construct with some random semantics.

It's sort of related to Drew's concerns in that Emacs deals with the N*M
problem by setting M=1, hence why only cl-loop gets the pressure to add
more enhancments.

There are some practical problem with iter-defun though: it has several
bugs on which there doesn't seem to be any movement[1][2][3], it's
reported to be slow[4], and cl-loop's iter-by keyword is not documented
at all (that could be easily fixed, at least).  I wonder if streams[5]
is a better direction.  It already has stream-regexp, though it returns
match-data rather than a matched string.

(package-install 'stream)
(require 'stream)
(require 'seq)

(seq-do (lambda (m)
          (set-match-data m)
          (print (match-string 0)))
        (stream-regexp (current-buffer) (rx digit)))

(cl-loop with matches = (stream-regexp (current-buffer) (rx digit))
         for m = (stream-pop matches) while m
         do (set-match-data m) (print (match-string 0)))

[1]: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=26073
[2]: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=25965
[3]: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=26068
[4]: http://lists.gnu.org/archive/html/emacs-devel/2017-03/msg00264.html
[5]: https://elpa.gnu.org/packages/stream.html



Reply | Threaded
Open this post in threaded view
|

bug#26338: 26.0.50; Collect all matches for REGEXP in current buffer

Drew Adams
In reply to this post by Tino Calancha-2
> > Put all this stuff - and more - into an `eloop' macro.
> > Since it will be so much better and more Emacsy, with
> > specifics that are especially useful for Emacs, it is
> > what users will (eventually) use instead of `cl-loop'.
> >
> > Since it will do everything that `cl-loop' does (and
> > more), eventually only the rare user who needs, or for
> > some reason really wants, code that is CL or close to
> > it will use `cl-loop'.  Everyone else will use `eloop'.
> > No problem.
>
> I guess that might cause a lot of duplication of code.

Why? The implementation of `cl-loop' or `eloop' could
leverage the implementation of the other, or they could
both leverage the implementation of a helper macro or
function.

> IMO experts CL lispers will be more sad with this emulation
> for the lack of returning multiple values than for the addition
> of some extensions.  They can chose not to use them if they
> don't like them.  Just one opinion too.

It's not about expert CL users.  It's about whether we want
to provide a CL emulation library or not, regardless of how
complete that emulation might be.

If we go the way we're headed, `cl-*' loses all meaning.
It's just a namespace that happens to also include some
constructs that emulate CL constructs, along with lots of
other stuff that does not.

AND along with stuff that kind of emulates but also kind of
does not, i.e., does something that confuses things by seeming,
in some cases, to emulate CL functionality but in other cases
(for the same construct) does something completely un-CL.

I do, completely, see the advantage of adding helpful
functionality, building on CL constructs.  I disagree that
that should be done to what are supposed to be CL-constuct
emulations.

I do not understand the reticence to do such enhancement in
separate, non-`cl-' functions and macros.  What would be
lost in doing that?  And wrt implementation, IMO that would
end up being simpler, not more complex.  The `cl-' emulation
code is already quite complex.  Separating out non-`cl-'
features from it could only make it simpler.

And any Emacs feature that builds on and enhances an existing
`cl-' feature need not continue to emulate all of the `cl-'
behavior - it has no such obligation.  It can still leverage
commonalities that would be factored out to serve as helpers
for both `cl-' and non-`cl-'.

What's the downside to what I'm suggesting?



Reply | Threaded
Open this post in threaded view
|

bug#26338: 26.0.50; Collect all matches for REGEXP in current buffer

Philipp Stephani
In reply to this post by Noam Postavsky-2


<[hidden email]> schrieb am Sa., 8. Apr. 2017 um 17:37 Uhr:
Philipp Stephani <[hidden email]> writes:

>>> - Coupling of unrelated entities is always an antipattern.
>>> - For N iterables and M looping constructs, you need to implement
>>> N*M integrations.
>
> Yes, I don't care about Common Lisp. The iter-by clause is less of a
> problem than 'buffers' etc. because it's not a one-off that couples a
> looping construct with some random semantics.

It's sort of related to Drew's concerns in that Emacs deals with the N*M
problem by setting M=1, hence why only cl-loop gets the pressure to add
more enhancments.

There are some practical problem with iter-defun though: it has several
bugs on which there doesn't seem to be any movement[1][2][3],

That's unfortunate, because it's a really well-designed library. Stefan has apparently resumed work on these issues (e.g commit 89898e43c7ceef28bb3c2116b4d8a3ec96d9c8da), so let's hope they will be fixed eventually.
 
it's
reported to be slow[4], and cl-loop's iter-by keyword is not documented
at all (that could be easily fixed, at least).  I wonder if streams[5]
is a better direction. 

Maybe, though I'd be hesitant to add yet another library for the same thing to Emacs, and I much prefer generator.el's interface.
Reply | Threaded
Open this post in threaded view
|

bug#26338: 26.0.50; Collect all matches for REGEXP in current buffer

Philipp Stephani
In reply to this post by Tino Calancha-2


Tino Calancha <[hidden email]> schrieb am Sa., 8. Apr. 2017 um 17:20 Uhr:

>
>       Your point is about performance.
>
>
> No, I care mostly about clarity, simplicity, and good API design, including separation of concerns.
Expressibity and readability might be some kind of clarity.

Yes, but it seems we mean different things with these words. "Readability" for me means (among other things) that each logical entity has a single purpose. The single purpose of the (already way too complex) cl-loop macro is iterating over things. It doesn't concern itself with the things it should iterate over and where they come from.
 
I totally agree about API design and separation of concerns.
>  
>         I am driven by easy to write code.
>       Maybe you can provide an example about how to write those things using
>       the iter-by cl-loop clause.
>
>
> Sure:
>  (require 'generator)
> (iter-defun re-matches (regexp)
>   (while (re-search-forward regexp nil t)
>     (iter-yield (match-string 0))))
> (iter-do (m (re-matches (rx digit)))
>   (print m))
> (cl-loop for m iter-by (re-matches (rx digit))
> do (print m))
Thank you very much for your examples.  They are nice.  I am not
as familiar as you with generators.  I must study them more.

Between A) and B), the second looks at least as simple and clear as
the first one, and probably more readable.

I disagree. (A) clearly separates the generation of the stream of objects to iterate over from the iteration, (B) doesn't. (A) is extensible to any kind of iteration as long as it can be expressed using generators (or lists, vectors, ...), while for (B) you need a new keyword for every new thing to iterate over.
 

A)
(iter-defun re-matches (regexp)
   (while (re-search-forward regexp nil t)
     (iter-yield (match-string-no-properties 1))))

(cl-loop for m iter-by (re-matches "^(defun \\(\\S +\\)")
          collect m)

B)
(cl-loop for m the matches of "^(defun \\(\\S +\\)"
          collect m)
Reply | Threaded
Open this post in threaded view
|

bug#26338: 26.0.50; Collect all matches for REGEXP in current buffer

Lars Ingebrigtsen
In reply to this post by Tino Calancha-2
Tino Calancha <[hidden email]> writes:

> we have `count-matches' in replace.el, which returns the
> number of matches of a regexp.  Why not to have an standard
> function `collect-matches' as well?

A bunch of discussion then followed, and several patches, but it seemed
like many people just thought that this didn't seem generally useful
enough...  and I agree.  Gathering regexp matches from a buffer is a
three-liner, and chopping out parts of that is easy enough with seq-take
and friends, so adding separate functionality for this just doesn't seem
warranted, in my opinion.

So I'm closing this bug report.

--
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



12