Subject: bug#15117: 24.3.50; doc of `(forward|backward)-*': state return value

From: Juanma Barranquero <[email-masked]>
Date: Tue, 11 Feb 2014 18:36:46 +0100

On Tue, Feb 11, 2014 at 7:43 AM, Drew Adams <[email-masked]> wrote:

> That is anyway *not* a criterion I use for whether a Lisp
> function should have a defined and documented return value.

The only criteria that make sense IMHO about whether a function should
have a defined and documented return value are:

- That the return value is useful and non-trivial.
- That it is somewhat related to the function's purpose.

As an example, goto-char has a documented return value, POSITION,
identical to its only argument. I suppose it is so for historical
reasons and I'm not proposing to undocument it, but if goto-char were
introduced now, I would, because the only thing you gain from it is
saving a `let' binding every now and then (perhaps 100 times out of
~12,000 calls to goto-char in the sources).

> Agreed; it is.  And the resulting position is thus an important part
> of its effect.  And it is handy to use that value directly.

The result of goto-char is NOT "the resulting position". Try

  (with-temp-buffer (goto-char 1000)) => 1000

or

  (let ((p (point-marker))) (eq p (goto-char p))) => t

The result of goto-char is *its argument*, even if it does not make sense.

> Are you arguing not to document `goto-char's return value, as well?
> And so to discourage its use?  After all, one doesn't need to depend
> on it - it's certainly enough to depend on the side effect and then
> call `point' to get the new position.

As said above, I would, if it were a new function, yes.

> If so, go for it.  Then what have you gained?  Greater liberty
> for the implementation to change?  Bof.  More readable code?  Bof.

Your "bof" is my "hell, yeah".

> Code that is more functional or side-effect free?  Certainly not.

I wouldn't presume to make a side-effect function side-effect free.
That'd be weird ;-)

> Whether something constitutes a "side effect"
> is relative.

I don't think so.

>  If, for some special (good) reason, code should not rely on the
>  return value of some function, then this fact should be stated
>  explicitly in the doc: "This function is used only for its side
>  effects; the return value is undefined."  This is Lisp, not C -
>  return values are the norm, not the exception.

Not documenting a return value is, in fact, a way of saying "this
function is used only for its side effects; the return value is
undefined". It's just that it is a way of saying it that you dislike,
but it has a long history.

> It is not because a function performs side effects that its
> return value should not be counted on (and so documented).

No, it is because it is trivial, or irrelevant, or an accident of
implementation.

> It's all about what we want for programmers.  Should they get
> a useful return value for the given function or not?  That's
> the only question.

The answer to that question is already there: some do (return a useful
value), some don't. What you're saying instead is that, in your
opinion, *most* functions should have its return value documented,
because that's more "lispy". But Elisp is not just a lisp, it's the
high-level implementation language of a text editor, and as such,
there are many functions intended to produce side effects in the text;
that they return a value is a consequence of these functions being
implemented in lisp, which does not have a concept of not returning
anything at all.

> Consider `when', for instance.  I, for one, adopt the convention
> often used with Common Lisp of NOT using the return value.  Why?
> To signal the programmer intention that what is happening is for
> the side effects and not for the return value - i.e., that in
> that particular context, the return value is not important. IOW,
> this is to help readers of the code; nothing more.

I do, too. But in fact, I think that function is an argument for my
position, not yours, exactly because of this:

> If you were to argue that we should not document the return
> value of `when' or `unless' you would get no argument from
> me.  (Well, actually, I would again suggest saying explicitly
> that one should not count on the return value.)

Exactly. I would prefer that `when' and `unless' had their return
values undefined, and people had to use (if X Y nil) or (if X nil Y).

> In the case of the motion functions, there is a useful value
> to return: the destination position.  And my question about
> that is "Why not?".  I've seen no response to that question,
> so far.  Why not?

See above. If the function is moving the point in a non trivial way,
it makes sense to return the new position. If not, not. There's
nothing special about motion functions.

> I'm not sure the resulting position is particularly useful in
> the case of `recenter', but if you proposed returning it and
> documenting that, I might not object.  Why not?  I don't have
> a great reason why not for `recenter' - do you?

recenter does not move the point. It could return `point', but, what for?

> Look at those functions.  See if you would really argue that
> we should not document their return values and let users
> depend on them.  See if you want to shout "side effects!"
> or some other battle cry as a reason for making such a change.

Drew, I didn't enter the discussion to defend function purity, just to
try to understand why did you define obvious side-effects as "no side
effects". That said, I do think that in many cases documenting the
return value has as a net negative effect in that it does not add
value and limits implementation. But there's nothing new there, we've
had this discussion before.

> Please answer the
> question of why we should not let users write code that
> counts on the moved-to position as a return value.

I think it is a good idea to encourage the users to use functions that
return the position as their *main* effect.

    J