help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Making a function than can only be used interactively


From: Christopher Dimech
Subject: Re: Making a function than can only be used interactively
Date: Mon, 4 Jul 2022 23:59:49 +0200


> Sent: Tuesday, July 05, 2022 at 9:18 AM
> From: "Stefan Monnier" <monnier@iro.umontreal.ca>
> To: "Christopher Dimech" <dimech@gmx.com>
> Cc: tsdh@gnu.org, help-gnu-emacs@gnu.org
> Subject: Re: Making a function than can only be used interactively
>
> > Another debate is that although one can declare a non-interactive function,
> > and an interactive function that can run non-interactively; there is no
> > construct that can define a purely interactive function.
>
> That's because an "interactive function" is just a normal function
> together with some auxiliary info to tell `call-interactive` how to call
> it "interactively".  Internally `call-interactively` will end up calling
> the function via `funcall`, i.e. "non-interactively".  So at
> a low-level, technically you just can't have a function that can be
> called interactively and not non-interactively.  You can try and kludge
> it up above if you really want to (like we've seen in a few different
> ways), but we're back to the question: what's the benefit?

Could be that the above is not fully understood.  Reporting warnings when
running a specific function non-interactively, when non-interactive call
is not recommended, would be the way to go.  But users have to program it
that way.


> > Does a function know whether it was run from lisp code or from the user in
> > an Emacs session?
>
> Trying to behave differently depending on who/how a function was called
> goes against the design principle of functions, so it tends to be kludgy
> and unreliable, like `called-interactively-p`.

Can't argue much with that.

> BTW, here's another way to make a function that "can't" be called
> non-interactively:
>
>     (defun foo (a b c &optional extra)
>       (interactive
>        (list ... 'dont-you-dare-call-me-non-interactively))
>       (unless (eql extra 'dont-you-dare-call-me-non-interactively)
>         (error "foo called non-interactively"))
>       ...)

Something like that could be enough.  Also a warning to warning buffer
might help.


> You can make it "more robust" with something like:
>
>     (defalias 'foo
>       (let ((witness (make-symbol "dont-you-dare-call-me-non-interactively")))
>         (lambda (a b c &optional extra)
>           (interactive
>             (list ... witness))
>           (unless (eql extra witness)
>             (error "foo called non-interactively"))
>           ...)))
>
> But again: is it really worth the trouble?  What is there to gain?
> Instead of beating the undesired callers with a stick, why not try and
> convince them to do something else with  carrot?
>
>         Stefan

You can gain an even bigger headache working with such code.






reply via email to

[Prev in Thread] Current Thread [Next in Thread]