[V] Re: beginning-of-defun bug
Andreas Roehler
andreas.roehler at online.de
Thu Oct 8 12:49:57 EDT 2009
Stephen J. Turnbull wrote:
> VETO
>
> Andreas Roehler writes:
> > Steve Youngs wrote:
> > > VETO
> > >
> > > * Andreas Roehler <andreas.roehler at online.de> writes:
> > >
> > > > FOR REVIEW
> > > > `beginning-of-defun' contains a bug sourcing redundancy.
> > >
> > > > With `beginning-of-defun' basically are to discriminate two cases:
> > > > if `beginning-of-defun-function' is set or not.
> > >
> > > > If not set, `beginning-of-defun-raw' is called, which
> > > > provides for an arguments default:
> > >
> > > > (unless arg (setq arg 1))
> > >
> > > > That's useful for the default routine, but not for
> > > > beginning-of-defun-function.
> > >
> > > > Python-mode for example sets `beginning-of-defun-function'
> > > > to `py-beginning-of-def-or-class'
> > >
> > > > (py-beginning-of-def-or-class &optional class count)
>
> Andreas, slow down
Here I am! :)
and think about what you're doing. You surely are
> familiar with this code:
>
> (defun beginning-of-defun (&optional arg)
> "Move backward to the beginning of a defun.
> With argument, do it that many times. [...]."
> ;; XEmacs change (for zmacs regions)
> (interactive "_p")
> (and (beginning-of-defun-raw arg)
> (progn (beginning-of-line) t)))
>
> (defun beginning-of-defun-raw (&optional arg)
> (interactive "p")
> (unless arg (setq arg 1))
> (if beginning-of-defun-function
> (funcall beginning-of-defun-function arg)
> ;; [...]
>
> Quite clearly, ARG is a count.
Which is taken by "P" too, if wanted indeed. Just not slyly sended.
Where is the problem after all?
beginning-of-defun-raw will be executed as before.
Well, there is one tiny thing, but it concerns more some habit than implementation:
Negative numeric argument works as before by M-x -1 beginning-of-defun for example.
But "M-x -" sends an error - which indeed is not a complete form...
Should the rest be accepted, there should be a way to serve that habit too.
>
> > > In my eyes, the bug is in #'py-beginning-of-def-or-class, in that it
> > > has its arguments backwards.
> >
> > No. At the contrary. It's vain, saying from the core side: we know
> > best how the prog-modes functions must define and use it's
> > arguments.
>
> That's true. We should presume `py-beginning-of-def-or-class' is
> designed correctly. But using it as a `beginning-of-defun-function'
> is wrong. A `beginning-of-defun-function' must be written to expect
> the same arguments as `beginning-of-defun' itself.
>
> > If you know a reason to fill in an argument for
> > beginning-of-defun-function at this place in advance, I'm
> > listening.
>
> ARG will *always* be passed to beginning-of-defun-function as a count.
> Furthermore, *all* movement commands behave this way. That
> consistency is not to be broken lightly.
>
> What do you expect to happen if somebody does C-u M-C-a in python,
> anyway? Are you doing something obnoxious like setting the UI to be
> "M-C-a moves to the beginning of a def, but C-u M-C-a move to the
> beginning of a class"? That violates the Principle of Least Surprise,
> because all other movement commands (and M-C-a in other modes) take
> that as a repeat count of 4.
>
> > If you don't want to change this wrongly set specification, we
> > can't use beginning-of-defun-function in python-mode for example.
>
> Of course you can.
>
> (defun py-beginning-of-defun-function (count)
> (py-beginning-of-def-or-class nil count))
> (setq beginning-of-defun-function #'py-beginning-of-defun-function)
>
> This is called "marshalling arguments", and it is done all the time
> precisely because API clients often have slightly different calling
> requirements from the API provider.
>
> Note how it generalizes to
>
> (defcustom py-bod-moves-by-class nil
>:group 'python-mode
>:type 'boolean)
> (defun py-beginning-of-defun-function (count)
> (py-beginning-of-def-or-class py-bod-moves-by-class count))
> (setq beginning-of-defun-function #'py-beginning-of-defun-function)
>
> You can say "inefficient because of the extra function call", but I
> don't know anybody fast enough to notice a single Lisp funcall in an
> interactive function. In loops it will surely be called as
> py-beginning-of-def-or-class, so no inefficiency there.
>
Why invent extras when cleaning up the base is possible?
Andreas
More information about the XEmacs-Patches
mailing list