all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Dmitry Gutov <dgutov@yandex.ru>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 22336@debbugs.gnu.org, Stefan Monnier <monnier@IRO.UMontreal.CA>
Subject: bug#22336: 25.0.50; cl-generic.el features are not documented in ELisp manual
Date: Sat, 23 Jan 2016 20:02:36 +0300	[thread overview]
Message-ID: <56A3B22C.80902@yandex.ru> (raw)
In-Reply-To: <83d1ss5uhz.fsf@gnu.org>

On 01/23/2016 03:51 PM, Eli Zaretskii wrote:

>    (defmacro cl-defgeneric (name args &rest options-and-methods)
>      "Create a generic function NAME.
>    DOC-STRING is the base documentation for this class.  A generic
>    function has no body, as its purpose is to decide which method body
>    is appropriate to use.  Specific methods are defined with `cl-defmethod'.
>    With this implementation the ARGS are currently ignored.
>    OPTIONS-AND-METHODS currently understands:
>    - (:documentation DOCSTRING)
>    - (declare DECLARATIONS)
>    - (:argument-precedence-order &rest ARGS)
>    - (:method [QUALIFIERS...] ARGS &rest BODY)
>    BODY, if present, is used as the body of a default method.
>
>    \(fn NAME ARGS [DOC-STRING] [OPTIONS-AND-METHODS...] &rest BODY)"
>
> It says a generic function has no body, but the usage info does
> mention body, and the last part of the doc string says BODY if present
> is used as the default method.  Or is that the body of :method?

BODY is "&rest BODY" from the advertised arglist you can see using `M-x 
describe-function'. It's also visible above in the last line of the 
docstring. The phrase "generic function has no body" is trying to say, 
apparently, that a generic function is not really a function (but more 
like a multi-dimensional hash-table), and the default method, which you 
_can_ provide inside the cl-defgeneric form, is the default value in 
that table.

Usage example:

(cl-defgeneric foo (a)
   10)

(cl-defmethod foo ((a integer))
   (* 20 a))

(foo 'a)
10

(foo 4)
80

> Anyway, specific methods can evidently be defined by cl-defgeneric as
> well, whereas the doc string says they should be defined by
> cl-defmethod.  The semantics of :method is never described at all (and
> I saw no examples of its usage to inspire me, AFAIR).

Is the can/should distinction a problem? Yes, when in doubt, 
cl-defmethod should be used, but one can define them inline as well.

I think the semantics are easy to guess, but I probably glanced at CL's 
documentation as well at some point:

(cl-defgeneric foo (a)
   (:method ((s string)) "stringy!")
   (:method ((a array)) :four)
   10)

(foo "s")
"stringy!"

(foo [1 2 3])
:four

TBH, I haven't used this even once in practice.

> "_The_ dispatch argument", in singular means only one such argument is
> possible, which is of course false.

Indeed. There's a case to be made for discouraging multiple-argument 
dispatch ("implemented rather naively"), but the docstring should be 
corrected anyway.

> The &context dispatch has a
> slightly different syntax, but it isn't mentioned here at all, which
> makes the description of (VAR TYPE) incorrect in that case.

Also true.

> Some omissions are very hard to restore.  The most striking example is
> TYPE, about which the doc string says nothing at all, and the
> commentary says just "plain old types".  How could you arrive at the
> long list that's now in the manual, let alone the type hierarchy that
> goes with it, except by reading the sources?

No idea. I was only vaguely aware, if that, of being able to dispatch on 
atomic types, before reading the manual. Thanks for that.

But the docstrings don't mention any of the possible values of TYPE 
(except (eql ...)), not just "plain old" ones. So I'm not clear on what 
exactly you consider an omission here. cl-defmethod docstring should 
probably enumerate the possible types (aside from the mentioned ones, 
TYPE can be (head ...) or a name of cl-struct, like the commentary says).

> As another example, the ":extra STRING" feature is mentioned, but
> without any details; I couldn't understand how to use it in practice
> (it is not used in the tests, either).

I don't know either.

> And I don't recommend believing the commentary too much, either.
> E.g., what it says about &context in several places is contradictory:
>
>    ;;   E.g. (foo &context (major-mode (eql c-mode))) is an arglist specifying
>    ;;   that this method will only be applicable when `major-mode' has value
>    ;;   `c-mode'.
>
> and then:
>
>    ;; - then define a context-rewriter so you can write
>    ;;   "&context (major-mode c-mode)" rather than
>    ;;   "&context (major-mode (derived-mode c-mode))".

Apparently, you can use both forms:

(cl-defmethod bar (&context (major-mode emacs-lisp-mode))
   'elisp)

(cl-defmethod bar (&context (major-mode (eql c-mode)))
   'c)

> and even
>
>    ;; TODO:
>    ;;
>    ;; - A way to dispatch on the context (e.g. the major-mode, some global
>    ;;   variable, you name it).

Yup, this should just be removed.

> which makes you think it isn't even implemented...  Also, there's
> something about derived-mode there, but it's so contrived and devoid
> of examples, that I didn't even put that in the manual.

Good call.

> There were others I was only too happy to forget.

Thanks. I think fixing just the things you've mentioned will already be 
a step forward.





  reply	other threads:[~2016-01-23 17:02 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-09  9:06 bug#22336: 25.0.50; cl-generic.el features are not documented in ELisp manual Eli Zaretskii
2016-01-09 10:07 ` Eli Zaretskii
2016-01-16  8:25 ` Eli Zaretskii
2016-01-22 21:17   ` Eli Zaretskii
2016-01-23  5:29     ` Dmitry Gutov
2016-01-23  6:06       ` Eli Zaretskii
2016-01-23  8:20         ` Dmitry Gutov
2016-01-23 12:51           ` Eli Zaretskii
2016-01-23 17:02             ` Dmitry Gutov [this message]
2016-01-23 17:21               ` Eli Zaretskii
2016-01-24  0:45                 ` Dmitry Gutov
2016-01-24  0:48                   ` Dmitry Gutov
2016-01-24  5:03               ` Stefan Monnier
2016-01-24 14:34                 ` Eli Zaretskii
2016-01-24 23:00                   ` Stefan Monnier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56A3B22C.80902@yandex.ru \
    --to=dgutov@yandex.ru \
    --cc=22336@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    --cc=monnier@IRO.UMontreal.CA \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.