* How to shadow a function temporarily? (flet and cl-flet)
@ 2014-01-26 14:11 Alex Kost
2014-01-26 14:50 ` Stefan Monnier
2014-01-26 19:03 ` Marcin Borkowski
0 siblings, 2 replies; 16+ messages in thread
From: Alex Kost @ 2014-01-26 14:11 UTC (permalink / raw)
To: help-gnu-emacs
[-- Attachment #1: Type: text/plain, Size: 575 bytes --]
Hello, I have 2 questions.
1. The main question is: how can I override a function with another
compatible function (with the same args) temporarily?
I want something like this:
(let-shadow ((+ '-))
(+ 3 2)) ; should return 1, not 5
2. If there is no such macro, I can use `flet' for my purposes, but it
is obsolete and `cl-flet' doesn't do what I need (see attached example).
According to (info "(cl) Obsolete Macros"), `flet' makes a dynamic
binding (unlike `cl-flet'). So the second question is: how can I avoid
using obsolete `flet` if I need a dynamic binding?
[-- Attachment #2: Type: application/emacs-lisp, Size: 327 bytes --]
[-- Attachment #3: Type: text/plain, Size: 15 bytes --]
--
Alex Kost
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
2014-01-26 14:11 How to shadow a function temporarily? (flet and cl-flet) Alex Kost
@ 2014-01-26 14:50 ` Stefan Monnier
2014-01-26 19:24 ` Alex Kost
2014-01-26 19:03 ` Marcin Borkowski
1 sibling, 1 reply; 16+ messages in thread
From: Stefan Monnier @ 2014-01-26 14:50 UTC (permalink / raw)
To: help-gnu-emacs
> 1. The main question is: how can I override a function with another
> compatible function (with the same args) temporarily?
Be careful with "temporarily": it can be interpreted as "lexically" or
"dynamically". From your example, it seems you want "dynamically".
Note, tho, that
(defun 8+ (arg)
(+ 8 arg))
(flet ((+ (&rest args)
(apply '- args)))
(8+ 3)) ; => 5
will give you 11 when byte-compiled. IOW, you had better look for
another solution to your problem. One option could be something along
the following lines:
(defvar my-plus-is-subtraction nil)
(defun 8+ (arg)
(funcall (if my-plus-is-subtraction #'- #'+) 8 arg))
(let ((my-plus-is-subtraction t))
(8+ 3)) ; => 5
-- Stefan
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
[not found] <mailman.12843.1390745495.10748.help-gnu-emacs@gnu.org>
@ 2014-01-26 16:22 ` Emanuel Berg
2014-01-26 19:25 ` Alex Kost
2014-01-26 18:32 ` Emanuel Berg
2014-01-26 19:36 ` Barry Margolin
2 siblings, 1 reply; 16+ messages in thread
From: Emanuel Berg @ 2014-01-26 16:22 UTC (permalink / raw)
To: help-gnu-emacs
Alex Kost <alezost@gmail.com> writes:
> 1. The main question is: how can I override a
> function with another compatible function (with the
> same args) temporarily?
Why do you want to do that? It might help if you tell
us, because there might be other (better) ways to do
what you want.
I don't know of an interface to do that, if you want to
do it habitually, but on a per function-basis, you can
use fset to redefine (set) the functions of symbols:
(fset '+ (lambda (&rest args) (apply '- args)))
And it is "temporary" in the sense that it works as
long as you don't reset it. But if you go around
mucking about like that, I don't know what will break
first - Emacs or your mind. So I don't think you have
to worry about the "temporary" aspect :)
--
underground experts united:
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
[not found] <mailman.12843.1390745495.10748.help-gnu-emacs@gnu.org>
2014-01-26 16:22 ` Emanuel Berg
@ 2014-01-26 18:32 ` Emanuel Berg
2014-01-26 19:38 ` Alex Kost
2014-01-26 19:36 ` Barry Margolin
2 siblings, 1 reply; 16+ messages in thread
From: Emanuel Berg @ 2014-01-26 18:32 UTC (permalink / raw)
To: help-gnu-emacs
Alex Kost <alezost@gmail.com> writes:
> 1. The main question is: how can I override a
> function with another compatible function (with the
> same args) temporarily?
;;;; dynamic (Emacs wide)
;; first store the correct functions so we have them
;; (note: "subr" as in "subroutine", not "subtract")
(setq addition-fun (symbol-function '+)) ; #<subr +>
(setq subtraction-fun (symbol-function '-)) ; #<subr ->
;; change + to do subtraction
(fset '+ subtraction-fun)
(+ 1 2 3) ; -4
;; revert
(fset '+ addition-fun)
(+ 1 2 3) ; 6
;;; lexical
(cl-labels ((+ (&rest args) (apply '- args)))
(+ 1 2 3) ) ; -4
(+ 1 2 3) ; still 6
--
underground experts united:
http://user.it.uu.se/~embe8573
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
2014-01-26 14:11 How to shadow a function temporarily? (flet and cl-flet) Alex Kost
2014-01-26 14:50 ` Stefan Monnier
@ 2014-01-26 19:03 ` Marcin Borkowski
2014-01-26 19:31 ` Alex Kost
1 sibling, 1 reply; 16+ messages in thread
From: Marcin Borkowski @ 2014-01-26 19:03 UTC (permalink / raw)
To: help-gnu-emacs
Dnia 2014-01-26, o godz. 18:11:11
Alex Kost <alezost@gmail.com> napisał(a):
> Hello, I have 2 questions.
>
> 1. The main question is: how can I override a function with another
> compatible function (with the same args) temporarily?
>
> I want something like this:
>
> (let-shadow ((+ '-))
> (+ 3 2)) ; should return 1, not 5
>
> 2. If there is no such macro, I can use `flet' for my purposes, but it
> is obsolete and `cl-flet' doesn't do what I need (see attached
> example).
>
> According to (info "(cl) Obsolete Macros"), `flet' makes a dynamic
> binding (unlike `cl-flet'). So the second question is: how can I
> avoid using obsolete `flet` if I need a dynamic binding?
Am I right that this could be done with advising?
HTH,
--
Marcin Borkowski
http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski
Adam Mickiewicz University
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
2014-01-26 14:50 ` Stefan Monnier
@ 2014-01-26 19:24 ` Alex Kost
2014-01-26 22:08 ` Stefan Monnier
0 siblings, 1 reply; 16+ messages in thread
From: Alex Kost @ 2014-01-26 19:24 UTC (permalink / raw)
To: help-gnu-emacs
[-- Attachment #1: Type: text/plain, Size: 1199 bytes --]
Stefan Monnier (2014-01-26 18:50 +0400) wrote:
>> 1. The main question is: how can I override a function with another
>> compatible function (with the same args) temporarily?
>
> Be careful with "temporarily": it can be interpreted as "lexically" or
> "dynamically". From your example, it seems you want "dynamically".
> Note, tho, that
>
> (defun 8+ (arg)
> (+ 8 arg))
>
> (flet ((+ (&rest args)
> (apply '- args)))
> (8+ 3)) ; => 5
>
> will give you 11 when byte-compiled.
Thank you, I didn't know about that.
> IOW, you had better look for
> another solution to your problem. One option could be something along
> the following lines:
>
> (defvar my-plus-is-subtraction nil)
>
> (defun 8+ (arg)
> (funcall (if my-plus-is-subtraction #'- #'+) 8 arg))
>
> (let ((my-plus-is-subtraction t))
> (8+ 3)) ; => 5
It was an example, I cannot modify `8+' function.
Here is what I actiually need: I want to make `read-color' function to
use my functions instead of `foreground-color-at-point' and
`background-color-at-point', so I tried the following (but now I see
that it's not suitable):
[-- Attachment #2: Type: application/emacs-lisp, Size: 313 bytes --]
[-- Attachment #3: Type: text/plain, Size: 97 bytes --]
Now i don't see another solution except of using the code of
`read-color' in `my-read-color'.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
2014-01-26 16:22 ` Emanuel Berg
@ 2014-01-26 19:25 ` Alex Kost
0 siblings, 0 replies; 16+ messages in thread
From: Alex Kost @ 2014-01-26 19:25 UTC (permalink / raw)
To: help-gnu-emacs
Emanuel Berg (2014-01-26 20:22 +0400) wrote:
> Alex Kost <alezost@gmail.com> writes:
>
>> 1. The main question is: how can I override a
>> function with another compatible function (with the
>> same args) temporarily?
>
> Why do you want to do that? It might help if you tell
> us, because there might be other (better) ways to do
> what you want.
I have written why I need it in a response to Stephan's letter.
> I don't know of an interface to do that, if you want to
> do it habitually, but on a per function-basis, you can
> use fset to redefine (set) the functions of symbols:
>
> (fset '+ (lambda (&rest args) (apply '- args)))
>
> And it is "temporary" in the sense that it works as
> long as you don't reset it. But if you go around
> mucking about like that, I don't know what will break
> first - Emacs or your mind. So I don't think you have
> to worry about the "temporary" aspect :)
Thank you, I know about `fset', I can even do (fset '+ '-), I just
wanted a `let'-like form to be sure that I will not stay with `-'
instead of `+' in a case of error or quit.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
2014-01-26 19:03 ` Marcin Borkowski
@ 2014-01-26 19:31 ` Alex Kost
0 siblings, 0 replies; 16+ messages in thread
From: Alex Kost @ 2014-01-26 19:31 UTC (permalink / raw)
To: help-gnu-emacs
Marcin Borkowski (2014-01-26 23:03 +0400) wrote:
> Dnia 2014-01-26, o godz. 18:11:11
> Alex Kost <alezost@gmail.com> napisał(a):
>
>> Hello, I have 2 questions.
>>
>> 1. The main question is: how can I override a function with another
>> compatible function (with the same args) temporarily?
>>
>> I want something like this:
>>
>> (let-shadow ((+ '-))
>> (+ 3 2)) ; should return 1, not 5
>>
>> 2. If there is no such macro, I can use `flet' for my purposes, but it
>> is obsolete and `cl-flet' doesn't do what I need (see attached
>> example).
>>
>> According to (info "(cl) Obsolete Macros"), `flet' makes a dynamic
>> binding (unlike `cl-flet'). So the second question is: how can I
>> avoid using obsolete `flet` if I need a dynamic binding?
>
> Am I right that this could be done with advising?
Thanks, but i don't want to make an advice mainly because i need it for
emacs package, not for my own config.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
[not found] <mailman.12843.1390745495.10748.help-gnu-emacs@gnu.org>
2014-01-26 16:22 ` Emanuel Berg
2014-01-26 18:32 ` Emanuel Berg
@ 2014-01-26 19:36 ` Barry Margolin
2014-01-26 19:45 ` Michael Heerdegen
2014-01-26 22:07 ` Alex Kost
2 siblings, 2 replies; 16+ messages in thread
From: Barry Margolin @ 2014-01-26 19:36 UTC (permalink / raw)
To: help-gnu-emacs
In article <mailman.12843.1390745495.10748.help-gnu-emacs@gnu.org>,
Alex Kost <alezost@gmail.com> wrote:
> Hello, I have 2 questions.
>
> 1. The main question is: how can I override a function with another
> compatible function (with the same args) temporarily?
>
> I want something like this:
>
> (let-shadow ((+ '-))
> (+ 3 2)) ; should return 1, not 5
>
> 2. If there is no such macro, I can use `flet' for my purposes, but it
> is obsolete and `cl-flet' doesn't do what I need (see attached example).
>
> According to (info "(cl) Obsolete Macros"), `flet' makes a dynamic
> binding (unlike `cl-flet'). So the second question is: how can I avoid
> using obsolete `flet` if I need a dynamic binding?
Use `letf' of `symbol-function':
(letf ((symbol-function 'function-name) (symbol-function
'other-function))
...)
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
2014-01-26 18:32 ` Emanuel Berg
@ 2014-01-26 19:38 ` Alex Kost
0 siblings, 0 replies; 16+ messages in thread
From: Alex Kost @ 2014-01-26 19:38 UTC (permalink / raw)
To: help-gnu-emacs
Emanuel Berg (2014-01-26 22:32 +0400) wrote:
> Alex Kost <alezost@gmail.com> writes:
>
>> 1. The main question is: how can I override a
>> function with another compatible function (with the
>> same args) temporarily?
>
> ;;;; dynamic (Emacs wide)
>
> ;; first store the correct functions so we have them
> ;; (note: "subr" as in "subroutine", not "subtract")
> (setq addition-fun (symbol-function '+)) ; #<subr +>
> (setq subtraction-fun (symbol-function '-)) ; #<subr ->
>
> ;; change + to do subtraction
> (fset '+ subtraction-fun)
> (+ 1 2 3) ; -4
>
> ;; revert
> (fset '+ addition-fun)
> (+ 1 2 3) ; 6
>
> ;;; lexical
>
> (cl-labels ((+ (&rest args) (apply '- args)))
> (+ 1 2 3) ) ; -4
> (+ 1 2 3) ; still 6
Thank you, I know all that stuff. That's not exactly what i need, but
your will to help always impress me.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
2014-01-26 19:36 ` Barry Margolin
@ 2014-01-26 19:45 ` Michael Heerdegen
2014-01-26 22:07 ` Alex Kost
1 sibling, 0 replies; 16+ messages in thread
From: Michael Heerdegen @ 2014-01-26 19:45 UTC (permalink / raw)
To: help-gnu-emacs
Barry Margolin <barmar@alum.mit.edu> writes:
> Use `letf' of `symbol-function':
>
> (letf ((symbol-function 'function-name) (symbol-function
> 'other-function))
> ...)
That was my idea too, but that also doesn't work when compiled. Try
with Stefan's counter example.
Michael.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
2014-01-26 19:36 ` Barry Margolin
2014-01-26 19:45 ` Michael Heerdegen
@ 2014-01-26 22:07 ` Alex Kost
1 sibling, 0 replies; 16+ messages in thread
From: Alex Kost @ 2014-01-26 22:07 UTC (permalink / raw)
To: help-gnu-emacs
Barry Margolin (2014-01-26 23:36 +0400) wrote:
> Use `letf' of `symbol-function':
>
> (letf ((symbol-function 'function-name) (symbol-function
> 'other-function))
> ...)
That's what I wanted (not sure about byte-compiled yet): I couldn't
figure it out how to use `letf' to set functions, but now I know about
`symbol-function'.
Thank you very much.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
2014-01-26 19:24 ` Alex Kost
@ 2014-01-26 22:08 ` Stefan Monnier
2014-01-27 5:57 ` Alex Kost
0 siblings, 1 reply; 16+ messages in thread
From: Stefan Monnier @ 2014-01-26 22:08 UTC (permalink / raw)
To: help-gnu-emacs
> (defun my-read-color (&optional prompt convert-to-RGB allow-empty-name msg)
> (interactive "i\np\ni\np")
> (flet ((foreground-color-at-point () (my-foreground-color-at-point))
> (background-color-at-point () (my-background-color-at-point)))
> (read-color prompt convert-to-RGB allow-empty-name msg)))
> Now i don't see another solution except of using the code of
> `read-color' in `my-read-color'.
IIUC foreground-color-at-point and background-color-at-point don't
suffer from the same problem as + when byte-compiled, so the above
should work.
But I'd recommend you use advice, which is cleaner (e.g. C-h f will
make it clear that something's messing with the function):
(defvar use-my-color-improvement nil)
(defadvice foreground-color-at-point (around my-improvement activate)
(if use-my-color-improvement
(setq ad-return-value (my-foreground-color-at-point))
ad-do-it))
(defadvice background-color-at-point (around my-improvement activate)
(if use-my-color-improvement
(setq ad-return-value (my-background-color-at-point))
ad-do-it))
...
...(let ((use-my-color-improvement t))
(read-color prompt convert-to-RGB allow-empty-name msg))
...
If that's for code within Emacs rather than a separate package, you'll
want to use the new advice-add instead of defadvice, of course.
Stefan
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
2014-01-26 22:08 ` Stefan Monnier
@ 2014-01-27 5:57 ` Alex Kost
2014-01-27 13:40 ` Stefan Monnier
0 siblings, 1 reply; 16+ messages in thread
From: Alex Kost @ 2014-01-27 5:57 UTC (permalink / raw)
To: help-gnu-emacs
[-- Attachment #1: Type: text/plain, Size: 1322 bytes --]
Stefan Monnier (2014-01-27 02:08 +0400) wrote:
> IIUC foreground-color-at-point and background-color-at-point don't
> suffer from the same problem as + when byte-compiled, so the above
> should work.
>
> But I'd recommend you use advice, which is cleaner (e.g. C-h f will
> make it clear that something's messing with the function):
>
> (defvar use-my-color-improvement nil)
>
> (defadvice foreground-color-at-point (around my-improvement activate)
> (if use-my-color-improvement
> (setq ad-return-value (my-foreground-color-at-point))
> ad-do-it))
>
> (defadvice background-color-at-point (around my-improvement activate)
> (if use-my-color-improvement
> (setq ad-return-value (my-background-color-at-point))
> ad-do-it))
>
> ...
> ...(let ((use-my-color-improvement t))
> (read-color prompt convert-to-RGB allow-empty-name msg))
> ...
>
> If that's for code within Emacs rather than a separate package, you'll
> want to use the new advice-add instead of defadvice, of course.
Thank you for the suggestion, but is it a normal practice to use advices
for packages? I use several advices in my own emacs config, but as a
user of an emacs package, I don't want to see that it advises some
functions.
I prefer the following (thanks to Barry Margolin):
[-- Attachment #2: Type: application/emacs-lisp, Size: 640 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
2014-01-27 5:57 ` Alex Kost
@ 2014-01-27 13:40 ` Stefan Monnier
2014-01-27 14:59 ` Alex Kost
0 siblings, 1 reply; 16+ messages in thread
From: Stefan Monnier @ 2014-01-27 13:40 UTC (permalink / raw)
To: help-gnu-emacs
> Thank you for the suggestion, but is it a normal practice to use advices
> for packages? I use several advices in my own emacs config, but as a
> user of an emacs package, I don't want to see that it advises some
> functions.
Why would you not want to see it?
> (defun macol-read-color (&optional prompt convert-to-RGB allow-empty-name msg)
> "Read a color name or RGB triplet.
> Same as `read-color', but use `macol-foreground-color-at-point'
> and `macol-background-color-at-point' instead of
> `foreground-color-at-point' and `background-color-at-point'."
> (interactive "i\np\ni\np")
> (cl-letf (((symbol-function 'foreground-color-at-point)
> (symbol-function 'macol-foreground-color-at-point))
> ((symbol-function 'background-color-at-point)
> (symbol-function 'macol-background-color-at-point)))
> (read-color prompt convert-to-RGB allow-empty-name msg)))
Now, if someone sees a problem in the behavior of
background-color-at-point, he may try to Edebug
background-color-at-point and won't understand why it's not called (or
why it *is* called but the value it returns is the value that the caller
receives, or ...).
Or someone else may start writing code relying on that new behavior
without realizing that it won't work in an Emacs that hasn't loaded this
"macol" package.
Of course, all that can happen as well with my `advice', but at least
the function's docstring will give you a hint. You can also more easily
deactivate this behavior either by re-binding use-my-color-improvement
to nil while `read-color' is in progress, or by deactivating this
particular advice.
Stefan
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: How to shadow a function temporarily? (flet and cl-flet)
2014-01-27 13:40 ` Stefan Monnier
@ 2014-01-27 14:59 ` Alex Kost
0 siblings, 0 replies; 16+ messages in thread
From: Alex Kost @ 2014-01-27 14:59 UTC (permalink / raw)
To: help-gnu-emacs
Stefan Monnier (2014-01-27 17:40 +0400) wrote:
>> (defun macol-read-color (&optional prompt convert-to-RGB allow-empty-name msg)
>> "Read a color name or RGB triplet.
>> Same as `read-color', but use `macol-foreground-color-at-point'
>> and `macol-background-color-at-point' instead of
>> `foreground-color-at-point' and `background-color-at-point'."
>> (interactive "i\np\ni\np")
>> (cl-letf (((symbol-function 'foreground-color-at-point)
>> (symbol-function 'macol-foreground-color-at-point))
>> ((symbol-function 'background-color-at-point)
>> (symbol-function 'macol-background-color-at-point)))
>> (read-color prompt convert-to-RGB allow-empty-name msg)))
>
> Now, if someone sees a problem in the behavior of
> background-color-at-point, he may try to Edebug
> background-color-at-point and won't understand why it's not called (or
> why it *is* called but the value it returns is the value that the caller
> receives, or ...).
>
> Or someone else may start writing code relying on that new behavior
> without realizing that it won't work in an Emacs that hasn't loaded this
> "macol" package.
>
> Of course, all that can happen as well with my `advice', but at least
> the function's docstring will give you a hint. You can also more easily
> deactivate this behavior either by re-binding use-my-color-improvement
> to nil while `read-color' is in progress, or by deactivating this
> particular advice.
Thank you very much for the detailed description. Now I understand the
point and am going to follow your advice about using advices.
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2014-01-27 14:59 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-26 14:11 How to shadow a function temporarily? (flet and cl-flet) Alex Kost
2014-01-26 14:50 ` Stefan Monnier
2014-01-26 19:24 ` Alex Kost
2014-01-26 22:08 ` Stefan Monnier
2014-01-27 5:57 ` Alex Kost
2014-01-27 13:40 ` Stefan Monnier
2014-01-27 14:59 ` Alex Kost
2014-01-26 19:03 ` Marcin Borkowski
2014-01-26 19:31 ` Alex Kost
[not found] <mailman.12843.1390745495.10748.help-gnu-emacs@gnu.org>
2014-01-26 16:22 ` Emanuel Berg
2014-01-26 19:25 ` Alex Kost
2014-01-26 18:32 ` Emanuel Berg
2014-01-26 19:38 ` Alex Kost
2014-01-26 19:36 ` Barry Margolin
2014-01-26 19:45 ` Michael Heerdegen
2014-01-26 22:07 ` Alex Kost
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).