unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Temporary changing the behavior of a function
@ 2015-11-06 10:23 Marcin Borkowski
  2015-11-06 13:03 ` Stefan Monnier
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Marcin Borkowski @ 2015-11-06 10:23 UTC (permalink / raw)
  To: Help Gnu Emacs mailing list

Hi list,

so there is this function `foo', which calls the function `bar'.  The
function `bar' is responsible for asking the user for some value and
passing that value to the guts of `foo'.

Now I want to call `foo' in the Mafia-mode;-), i.e., it should ask no
further questions.  What do I do?  AFAIU, `cl-flet' won't help, since it
is lexical.  The best I can think of is to temporarily advice `bar' with
:override - but then, instead of a `let'-like, local construct, I have
to explicitly add and then remove the advice, right?

Any other ideas?

TIA,

-- 
Marcin Borkowski
http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski
Faculty of Mathematics and Computer Science
Adam Mickiewicz University



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Temporary changing the behavior of a function
  2015-11-06 10:23 Temporary changing the behavior of a function Marcin Borkowski
@ 2015-11-06 13:03 ` Stefan Monnier
  2015-11-06 16:06   ` Marcin Borkowski
  2015-11-06 15:01 ` Yuri Khan
  2015-11-06 18:06 ` Michael Heerdegen
  2 siblings, 1 reply; 6+ messages in thread
From: Stefan Monnier @ 2015-11-06 13:03 UTC (permalink / raw)
  To: help-gnu-emacs

> Now I want to call `foo' in the Mafia-mode;-), i.e., it should ask no
> further questions.  What do I do?  AFAIU, `cl-flet' won't help, since it
> is lexical.  The best I can think of is to temporarily advice `bar' with
> :override - but then, instead of a `let'-like, local construct, I have
> to explicitly add and then remove the advice, right?

   (defvar my-bar-is-silent nil)
   (defun my-bar-silencer (orig &rest args)
     (if my-bar-is-silent <dosomethinggrommit> (apply orig args)))
   (advice-add 'bar :around #'my-bar-silencer)

and then

   ... (let ((my-bar-is-silent t))
         (foo ...))


-- Stefan




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Temporary changing the behavior of a function
  2015-11-06 10:23 Temporary changing the behavior of a function Marcin Borkowski
  2015-11-06 13:03 ` Stefan Monnier
@ 2015-11-06 15:01 ` Yuri Khan
  2015-11-06 16:05   ` Marcin Borkowski
  2015-11-06 18:06 ` Michael Heerdegen
  2 siblings, 1 reply; 6+ messages in thread
From: Yuri Khan @ 2015-11-06 15:01 UTC (permalink / raw)
  To: Marcin Borkowski; +Cc: Help Gnu Emacs mailing list

On Fri, Nov 6, 2015 at 4:23 PM, Marcin Borkowski <mbork@mbork.pl> wrote:

> so there is this function `foo', which calls the function `bar'.  The
> function `bar' is responsible for asking the user for some value and
> passing that value to the guts of `foo'.
>
> Now I want to call `foo' in the Mafia-mode;-), i.e., it should ask no
> further questions.  What do I do?  AFAIU, `cl-flet' won't help, since it
> is lexical.  The best I can think of is to temporarily advice `bar' with
> :override - but then, instead of a `let'-like, local construct, I have
> to explicitly add and then remove the advice, right?
>
> Any other ideas?

Yes. In other languages, we recognize such a need as a “smell”, a sign
of possibly bad design.

“foo” should have optional arguments that can be passed by the calling
code, and if they are not set, only then ask “bar” for user-supplied
parameters.

Alternatively, “foo” should invoke “bar” and pass its result to
“foo-guts” (we usually call it “foo-impl” or “do-foo”), and
programmatic callers should call “foo-guts” directly with the right
arguments.

If “foo” is in a third-party library you cannot or would rather not
change, only then consider monkey-patching “bar” as a workaround.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Temporary changing the behavior of a function
  2015-11-06 15:01 ` Yuri Khan
@ 2015-11-06 16:05   ` Marcin Borkowski
  0 siblings, 0 replies; 6+ messages in thread
From: Marcin Borkowski @ 2015-11-06 16:05 UTC (permalink / raw)
  To: Yuri Khan; +Cc: Help Gnu Emacs mailing list


On 2015-11-06, at 16:01, Yuri Khan <yuri.v.khan@gmail.com> wrote:

> On Fri, Nov 6, 2015 at 4:23 PM, Marcin Borkowski <mbork@mbork.pl> wrote:
>
>> so there is this function `foo', which calls the function `bar'.  The
>> function `bar' is responsible for asking the user for some value and
>> passing that value to the guts of `foo'.
>>
>> Now I want to call `foo' in the Mafia-mode;-), i.e., it should ask no
>> further questions.  What do I do?  AFAIU, `cl-flet' won't help, since it
>> is lexical.  The best I can think of is to temporarily advice `bar' with
>> :override - but then, instead of a `let'-like, local construct, I have
>> to explicitly add and then remove the advice, right?
>>
>> Any other ideas?
>
> Yes. In other languages, we recognize such a need as a “smell”, a sign
> of possibly bad design.
>
> “foo” should have optional arguments that can be passed by the calling
> code, and if they are not set, only then ask “bar” for user-supplied
> parameters.
>
> Alternatively, “foo” should invoke “bar” and pass its result to
> “foo-guts” (we usually call it “foo-impl” or “do-foo”), and
> programmatic callers should call “foo-guts” directly with the right
> arguments.
>
> If “foo” is in a third-party library you cannot or would rather not
> change, only then consider monkey-patching “bar” as a workaround.

All agreed, and that was my first thought, too.  Of course, both `foo'
and `bar' are in some library I cannot change ATM.  (That will wait
until I sign the FSF papers;-).)

OTOH, I /can/ imagine that the author did not anticipate such use: `foo'
is called only once in the whole (big) library, and then by another
interactive command, for which the user interaction is fine.

Thanks anyway,

-- 
Marcin Borkowski
http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski
Faculty of Mathematics and Computer Science
Adam Mickiewicz University



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Temporary changing the behavior of a function
  2015-11-06 13:03 ` Stefan Monnier
@ 2015-11-06 16:06   ` Marcin Borkowski
  0 siblings, 0 replies; 6+ messages in thread
From: Marcin Borkowski @ 2015-11-06 16:06 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: help-gnu-emacs


On 2015-11-06, at 14:03, Stefan Monnier <monnier@iro.umontreal.ca> wrote:

>> Now I want to call `foo' in the Mafia-mode;-), i.e., it should ask no
>> further questions.  What do I do?  AFAIU, `cl-flet' won't help, since it
>> is lexical.  The best I can think of is to temporarily advice `bar' with
>> :override - but then, instead of a `let'-like, local construct, I have
>> to explicitly add and then remove the advice, right?
>
>    (defvar my-bar-is-silent nil)
>    (defun my-bar-silencer (orig &rest args)
>      (if my-bar-is-silent <dosomethinggrommit> (apply orig args)))
>    (advice-add 'bar :around #'my-bar-silencer)
>
> and then
>
>    ... (let ((my-bar-is-silent t))
>          (foo ...))

Thanks!  Of course, I can see some performance penalty, but since it is
an interactive command, this doesn't bother me at all.

> -- Stefan

Best,

-- 
Marcin Borkowski
http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski
Faculty of Mathematics and Computer Science
Adam Mickiewicz University



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Temporary changing the behavior of a function
  2015-11-06 10:23 Temporary changing the behavior of a function Marcin Borkowski
  2015-11-06 13:03 ` Stefan Monnier
  2015-11-06 15:01 ` Yuri Khan
@ 2015-11-06 18:06 ` Michael Heerdegen
  2 siblings, 0 replies; 6+ messages in thread
From: Michael Heerdegen @ 2015-11-06 18:06 UTC (permalink / raw)
  To: help-gnu-emacs

Marcin Borkowski <mbork@mbork.pl> writes:

> so there is this function `foo', which calls the function `bar'.  The
> function `bar' is responsible for asking the user for some value and
> passing that value to the guts of `foo'.
>
> Now I want to call `foo' in the Mafia-mode;-), i.e., it should ask no
> further questions.  What do I do?  AFAIU, `cl-flet' won't help, since it
> is lexical.  The best I can think of is to temporarily advice `bar' with
> :override - but then, instead of a `let'-like, local construct, I have
> to explicitly add and then remove the advice, right?

Apart from what already had been suggested, there are two more dirty
alternatives:

 - Use `cl-letf' to create dynamical bindings on the place
 (symbol-function 'SYMBOL), instead of using `cl-flet'.  A common trick
 in such situations.

 - If `bar' asks always the same questions, you can push your "answers"
 to `unread-command-events'.  Just a workaround, but can save you from
 advising at all.


Michael.




^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-11-06 18:06 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-11-06 10:23 Temporary changing the behavior of a function Marcin Borkowski
2015-11-06 13:03 ` Stefan Monnier
2015-11-06 16:06   ` Marcin Borkowski
2015-11-06 15:01 ` Yuri Khan
2015-11-06 16:05   ` Marcin Borkowski
2015-11-06 18:06 ` Michael Heerdegen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).