[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