GNU bug report logs -
#38252
27.0.50; Gnus server definitions and generic function specializers
Previous Next
To reply to this bug, email your comments to 38252 AT debbugs.gnu.org.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
larsi <at> gnus.org, monnier <at> iro.umontreal.ca, bug-gnu-emacs <at> gnu.org
:
bug#38252
; Package
emacs
.
(Sun, 17 Nov 2019 22:32:02 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Eric Abrahamsen <eric <at> ericabrahamsen.net>
:
New bug report received and forwarded. Copy sent to
larsi <at> gnus.org, monnier <at> iro.umontreal.ca, bug-gnu-emacs <at> gnu.org
.
(Sun, 17 Nov 2019 22:32:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
I'm working on changing Gnus servers into structs, and replacing the
nnoo.el architecture with generic functions, and while I think I've got
a workable roadmap I'm running into some practical confusions. Stefan
I'm ccing you directly because I suspect you're the only one who knows
the answers to my questions :)
The approach is this: Change the server interface functions in
gnus-int.el into generic functions. Provide a generalizer that
recognizes current Gnus servers, and dispatches to the current function
definitions (using `gnus-get-function' and all that). Gradually change
the in-tree backends to be defined with cl-defstruct, and use normal
dispatching-on-struct for those. Eventually the legacy generalizer would
be left in place just to deal with old-style out-of-tree backends.
As an example, here's what `gnus-request-list' currently looks like:
--8<---------------cut here---------------start------------->8---
gnus-int.el:
(defun gnus-request-list (gnus-command-method)
(funcall (gnus-get-function gnus-command-method 'request-list)
(nth 1 gnus-command-method)))
nnimap.el:
(deffoo nnimap-request-list (&optional server)
<get IMAP group list>)
--8<---------------cut here---------------end--------------->8---
Afterward it would look like this:
--8<---------------cut here---------------start------------->8---
gnus-int.el:
(cl-defgeneric gnus-request-list (server)
"Docs and stuff.")
(cl-defmethod gnus-request-list ((server gnus-server-legacy))
(funcall (gnus-get-function server 'request-list)
(nth 1 server)))
nnimap.el:
(cl-defmethod gnus-request-list ((server gnus-server-imap))
<get IMAP group list>)
--8<---------------cut here---------------end--------------->8---
The nnimap version will dispatch on the `gnus-server-imap' defstruct,
that happens automatically. What I need is to be able to write a
generalizer/specializer that will recognize a legacy server (if calling
it "legacy" is annoying I can find something else) and dispatch on it.
The docstring of `cl-generic-define-generalizer' is gnomic, though I
found some better information in the docstring of
`cl-generic-generalizers', and looked at some of the existing
generalizer definitions.
Here's what I've worked up so far:
--8<---------------cut here---------------start------------->8---
(cl-generic-define-generalizer gnus-legacy-server-generalizer
90 (lambda (name &rest _) `(???)
(lambda (tag &rest _) (when (eq (car-safe tag) 'gnus-legacy-server)
(list tag))))
(cl-defmethod cl-generic-generalizers :extra "gnus-legacy-server" (thing)
"Dispatch on old-style Gnus server definitions."
(when wut?
(list gnus-legacy-server-generalizer)))
--8<---------------cut here---------------end--------------->8---
What I'm trying to do is fairly simple: if the argument is a list, and
the head of the list is a symbol that can be assoc'd into
`nnoo-definition-alist', and the second element is a string, then it's a
gnus-legacy-server. I just don't know where that test is supposed to go,
or why.
I understand this will probably be inefficient and ugly, but I hope that
before too long it would be a rare case that the generalizer is checked
at all.
Thanks,
Eric
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#38252
; Package
emacs
.
(Mon, 18 Nov 2019 02:04:01 GMT)
Full text and
rfc822 format available.
Message #8 received at 38252 <at> debbugs.gnu.org (full text, mbox):
> I'm ccing you directly because I suspect you're the only one who knows
> the answers to my questions :)
I doubt it, there's a lot of people around here more familiar with
CLOS-style programming than I.
> --8<---------------cut here---------------start------------->8---
> gnus-int.el:
> (cl-defgeneric gnus-request-list (server)
> "Docs and stuff.")
>
> (cl-defmethod gnus-request-list ((server gnus-server-legacy))
> (funcall (gnus-get-function server 'request-list)
> (nth 1 server)))
Why not just:
(cl-defmethod gnus-request-list (server)
(funcall (gnus-get-function server 'request-list)
(nth 1 server)))
which means "use it as a fallback". The downside is that it will be
used for non-legacy servers if there is no specific implementation for
that server, but presumably you can detect it and signal an appropriate
error somewhere inside gnus-get-function.
> What I'm trying to do is fairly simple: if the argument is a list, and
> the head of the list is a symbol that can be assoc'd into
> `nnoo-definition-alist', and the second element is a string, then it's a
> gnus-legacy-server.
Why not just use a `cons` specializer?
IIUC all the non-legacy servers will use structs, so you don't need to
use a specializer that's so specific that it has to check "if the
argument is a list, and the head of the list is a symbol that can be
assoc'd into `nnoo-definition-alist', and the second element is
a string".
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#38252
; Package
emacs
.
(Mon, 18 Nov 2019 03:19:02 GMT)
Full text and
rfc822 format available.
Message #11 received at 38252 <at> debbugs.gnu.org (full text, mbox):
On 11/17/19 21:03 PM, Stefan Monnier wrote:
>> I'm ccing you directly because I suspect you're the only one who knows
>> the answers to my questions :)
>
> I doubt it, there's a lot of people around here more familiar with
> CLOS-style programming than I.
>
>> --8<---------------cut here---------------start------------->8---
>> gnus-int.el:
>> (cl-defgeneric gnus-request-list (server)
>> "Docs and stuff.")
>>
>> (cl-defmethod gnus-request-list ((server gnus-server-legacy))
>> (funcall (gnus-get-function server 'request-list)
>> (nth 1 server)))
>
> Why not just:
>
> (cl-defmethod gnus-request-list (server)
> (funcall (gnus-get-function server 'request-list)
> (nth 1 server)))
>
> which means "use it as a fallback". The downside is that it will be
> used for non-legacy servers if there is no specific implementation for
> that server, but presumably you can detect it and signal an appropriate
> error somewhere inside gnus-get-function.
>
>> What I'm trying to do is fairly simple: if the argument is a list, and
>> the head of the list is a symbol that can be assoc'd into
>> `nnoo-definition-alist', and the second element is a string, then it's a
>> gnus-legacy-server.
>
> Why not just use a `cons` specializer?
>
> IIUC all the non-legacy servers will use structs, so you don't need to
> use a specializer that's so specific that it has to check "if the
> argument is a list, and the head of the list is a symbol that can be
> assoc'd into `nnoo-definition-alist', and the second element is
> a string".
Okay, perhaps I was overthinking this. I don't want to assume that the
fallback is an old-style server (we might want to use the fallback for
other purposes), but you're right that 'cons is pretty much sufficient.
If anyone feeds a cons value into a Gnus server interface function that
*isn't* a server definition, that falls into "serves you right"
territory.
But just so I don't feel like I wasted my afternoon: how *would* one
write the generalizer I'm talking about?
Thanks,
Eric
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#38252
; Package
emacs
.
(Mon, 18 Nov 2019 04:37:02 GMT)
Full text and
rfc822 format available.
Message #14 received at 38252 <at> debbugs.gnu.org (full text, mbox):
> But just so I don't feel like I wasted my afternoon: how *would* one
> write the generalizer I'm talking about?
Ah, that part.
I guess It could look like (guaranteed 100% untested):
(defvar gnus--legacy-server-tag (make-symbol "gnus-legacy-server"))
(cl-generic-define-generalizer gnus-legacy-server-generalizer
90 (lambda (varname &rest _)
`(and (consp ,varname)
(symbolp (car ,varname))
(assq (car ,varname) nnoo-definition-alist)
(stringp (cadr ,varname))
gnus--legacy-server-tag))
(lambda (tag &rest _)
(when (eq tag gnus--legacy-server-tag) (list tag))))
(cl-defmethod cl-generic-generalizers ((_ (eql gnus-legacy-server)))
"Dispatch on old-style Gnus server definitions."
(list gnus-legacy-server-generalizer))
-- Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#38252
; Package
emacs
.
(Mon, 18 Nov 2019 20:44:01 GMT)
Full text and
rfc822 format available.
Message #17 received at 38252 <at> debbugs.gnu.org (full text, mbox):
On 11/17/19 23:36 PM, Stefan Monnier wrote:
>> But just so I don't feel like I wasted my afternoon: how *would* one
>> write the generalizer I'm talking about?
>
> Ah, that part.
> I guess It could look like (guaranteed 100% untested):
>
> (defvar gnus--legacy-server-tag (make-symbol "gnus-legacy-server"))
> (cl-generic-define-generalizer gnus-legacy-server-generalizer
> 90 (lambda (varname &rest _)
> `(and (consp ,varname)
> (symbolp (car ,varname))
> (assq (car ,varname) nnoo-definition-alist)
> (stringp (cadr ,varname))
> gnus--legacy-server-tag))
> (lambda (tag &rest _)
> (when (eq tag gnus--legacy-server-tag) (list tag))))
>
> (cl-defmethod cl-generic-generalizers ((_ (eql gnus-legacy-server)))
> "Dispatch on old-style Gnus server definitions."
> (list gnus-legacy-server-generalizer))
That's perfect, thanks. I don't need tested code, I just needed to
understand the logic of which bit is responsible for what. I wonder if
it would be useful to have an example of this, either in the manual or
cl-generic.el code comments?
There's still a lot of work to do before struct servers and cons servers
can coexist within Gnus, but it's nice to have this piece of the puzzle
solved.
This bug report was last modified 5 years and 213 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.