unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Change a symbol's plist member with (let ...)?
@ 2014-03-14 21:17 Thorsten Jolitz
  2014-03-14 21:37 ` Nicolas Richard
  2014-03-16 18:10 ` Stefan
  0 siblings, 2 replies; 7+ messages in thread
From: Thorsten Jolitz @ 2014-03-14 21:17 UTC (permalink / raw)
  To: help-gnu-emacs


Hi List, 

the title says it all - is it possible to temporarily change a symbol's
plist member within (let ...)?

#+begin_src emacs-lisp
  (plist-get (symbol-plist 'outline-mode)
             'derived-mode-parent) 
#+end_src

#+results:
: text-mode

For the sake of this example, say I want to "con" the function
`derived-mode-p' and make it believe outline-mode is actually derived
from lisp-mode (or so ...).

How to do this with working code (not pseudo-code)?

#+begin_src emacs-lisp
  (defadvice derived-mode-p' (around derived-mode-p-around)
    "Con `derived-mode-p' about the true parent-mode of outline-mode."
    (when (eq major-mode 'outline-mode)
      (let ((...<plist-key derived-mode-parent> 'lisp-mode ...)) ; pseudo-code
        ad-do-it))
#+end_src

Or do I have to do it the pedestrian way: do plist-get first, store the
original value, do plist-put with the new value, call ad-do-it, and then
restore the original value again with plist-put?

-- 
cheers,
Thorsten




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

* Re: Change a symbol's plist member with (let ...)?
  2014-03-14 21:17 Change a symbol's plist member with (let ...)? Thorsten Jolitz
@ 2014-03-14 21:37 ` Nicolas Richard
  2014-03-14 22:25   ` Thorsten Jolitz
  2014-03-16 18:10 ` Stefan
  1 sibling, 1 reply; 7+ messages in thread
From: Nicolas Richard @ 2014-03-14 21:37 UTC (permalink / raw)
  To: Thorsten Jolitz; +Cc: help-gnu-emacs

Thorsten Jolitz <tjolitz@gmail.com> writes:
> #+begin_src emacs-lisp
>   (plist-get (symbol-plist 'outline-mode)
>              'derived-mode-parent) 
> #+end_src
>

(get 'outline-mode 'derived-mode-parent) looks better to me.

> For the sake of this example, say I want to "con" the function
> `derived-mode-p' and make it believe outline-mode is actually derived
> from lisp-mode (or so ...).
>
> How to do this with working code (not pseudo-code)?

I'm in message-mode right now, and :
  (derived-mode-p 'text-mode)
returns: text-mode

But
(letf (((get major-mode 'derived-mode-parent) 'special-mode))
           (derived-mode-p 'text-mode))
returns nil.

You could also let-bind major-mode to whatever the code you're calling
expects.

> Or do I have to do it the pedestrian way: do plist-get first, store the
> original value, do plist-put with the new value, call ad-do-it, and then
> restore the original value again with plist-put?

If you already know what you want the function to return, you could simply make
the advice return that value and not call ad-do-it at all.

-- 
Nico.



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

* Re: Change a symbol's plist member with (let ...)?
  2014-03-14 21:37 ` Nicolas Richard
@ 2014-03-14 22:25   ` Thorsten Jolitz
  2014-03-15 21:28     ` Nicolas Richard
  0 siblings, 1 reply; 7+ messages in thread
From: Thorsten Jolitz @ 2014-03-14 22:25 UTC (permalink / raw)
  To: help-gnu-emacs

Nicolas Richard <theonewiththeevillook@yahoo.fr> writes:

> Thorsten Jolitz <tjolitz@gmail.com> writes:
>> #+begin_src emacs-lisp
>>   (plist-get (symbol-plist 'outline-mode)
>>              'derived-mode-parent) 
>> #+end_src
>>
>
> (get 'outline-mode 'derived-mode-parent) looks better to me.
>
>> For the sake of this example, say I want to "con" the function
>> `derived-mode-p' and make it believe outline-mode is actually derived
>> from lisp-mode (or so ...).
>>
>> How to do this with working code (not pseudo-code)?
>
> I'm in message-mode right now, and :
>   (derived-mode-p 'text-mode)
> returns: text-mode
>
> But
> (letf (((get major-mode 'derived-mode-parent) 'special-mode))
>            (derived-mode-p 'text-mode))
> returns nil.

I have to get more involved with this cl stuff it seems ... 

> You could also let-bind major-mode to whatever the code you're calling
> expects.
>
>> Or do I have to do it the pedestrian way: do plist-get first, store the
>> original value, do plist-put with the new value, call ad-do-it, and then
>> restore the original value again with plist-put?
>
> If you already know what you want the function to return, you could
> simply make
> the advice return that value and not call ad-do-it at all.

yes, I just figured out that a simple (conditional) after advice that sets
ad-return-value to t is all I need. 

Thanks for the tips.

-- 
cheers,
Thorsten




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

* Re: Change a symbol's plist member with (let ...)?
  2014-03-14 22:25   ` Thorsten Jolitz
@ 2014-03-15 21:28     ` Nicolas Richard
  2014-03-16 16:01       ` Thorsten Jolitz
  0 siblings, 1 reply; 7+ messages in thread
From: Nicolas Richard @ 2014-03-15 21:28 UTC (permalink / raw)
  To: Thorsten Jolitz; +Cc: help-gnu-emacs

Thorsten Jolitz <tjolitz@gmail.com> writes:
>> (letf (((get major-mode 'derived-mode-parent) 'special-mode))
>>            (derived-mode-p 'text-mode))
>> returns nil.
>
> I have to get more involved with this cl stuff it seems ... 

This one is rather easy to understand. 'letf' does a temporary 'setf'
and then puts the previous value back. So what is 'setf' ?

'setf' is a generic way to *change* a value if you know how to *get*
that value.

Example : if foo is a cons cell, you know how to get its car
: (car foo). Well, now (setf (car foo) 'bar) will change the car of foo
to 'bar. IOW, setf arranges so that the next invocations of (car foo)
will now return 'bar instead of its previous value. And it knows
internally how to do it : it uses 'setcar' :
(macroexpand '(setf (car foo) 'special-mode))
=> (let* ((v foo)) (setcar v (quote special-mode)))
(the surrounding let*-binding isn't needed in this case, is needed in
other cases, but let's ignore it.)

So now :
(setf (get major-mode 'derived-mode-parent) 'special-mode)
simply arranges to change whatever is required so that (get major-mode
'derived-mode-parent) will return 'special-mode. Internally, it knows
what to do :
(macroexpand '(setf (get major-mode 'derived-mode-parent) 'special-mode))
gives :
(let* ((v major-mode)) (put v (quote derived-mode-parent) (quote special-mode)))

And now if you want to do that temporarily, you use letf : letf will
arrange to revert the change upon exiting the letf form.
(macroexpand'(letf (((get major-mode 'derived-mode-parent) 'special-mode))
           (derived-mode-p 'text-mode)))
will give (I added comments) :
(let* ((v major-mode)
       (old (get v (quote derived-mode-parent)))) ; save old value
  (unwind-protect
      (progn
        (put v ; set new value
             (quote derived-mode-parent)
             (quote special-mode))
        (derived-mode-p ; run the body
         (quote text-mode)))
    (put v ; set old value back.
         (quote derived-mode-parent)
         old)))

Simple, yet powerful.

-- 
Nico.



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

* Re: Change a symbol's plist member with (let ...)?
  2014-03-15 21:28     ` Nicolas Richard
@ 2014-03-16 16:01       ` Thorsten Jolitz
  0 siblings, 0 replies; 7+ messages in thread
From: Thorsten Jolitz @ 2014-03-16 16:01 UTC (permalink / raw)
  To: help-gnu-emacs

Nicolas Richard <theonewiththeevillook@yahoo.fr> writes:

> Thorsten Jolitz <tjolitz@gmail.com> writes:
>>> (letf (((get major-mode 'derived-mode-parent) 'special-mode))
>>>            (derived-mode-p 'text-mode))
>>> returns nil.
>>
>> I have to get more involved with this cl stuff it seems ... 
>
> This one is rather easy to understand. 'letf' does a temporary 'setf'
> and then puts the previous value back. So what is 'setf' ?
>
> 'setf' is a generic way to *change* a value if you know how to *get*
> that value.
>
> Example : if foo is a cons cell, you know how to get its car
> : (car foo). Well, now (setf (car foo) 'bar) will change the car of foo
> to 'bar. IOW, setf arranges so that the next invocations of (car foo)
> will now return 'bar instead of its previous value. And it knows
> internally how to do it : it uses 'setcar' :
> (macroexpand '(setf (car foo) 'special-mode))
> => (let* ((v foo)) (setcar v (quote special-mode)))
> (the surrounding let*-binding isn't needed in this case, is needed in
> other cases, but let's ignore it.)
>
> So now :
> (setf (get major-mode 'derived-mode-parent) 'special-mode)
> simply arranges to change whatever is required so that (get major-mode
> 'derived-mode-parent) will return 'special-mode. Internally, it knows
> what to do :
> (macroexpand '(setf (get major-mode 'derived-mode-parent) 'special-mode))
> gives :
> (let* ((v major-mode)) (put v (quote derived-mode-parent) (quote special-mode)))
>
> And now if you want to do that temporarily, you use letf : letf will
> arrange to revert the change upon exiting the letf form.
> (macroexpand'(letf (((get major-mode 'derived-mode-parent) 'special-mode))
>            (derived-mode-p 'text-mode)))
> will give (I added comments) :
> (let* ((v major-mode)
>        (old (get v (quote derived-mode-parent)))) ; save old value
>   (unwind-protect
>       (progn
>         (put v ; set new value
>              (quote derived-mode-parent)
>              (quote special-mode))
>         (derived-mode-p ; run the body
>          (quote text-mode)))
>     (put v ; set old value back.
>          (quote derived-mode-parent)
>          old)))
>
> Simple, yet powerful.

Interesting, thanks for the explanations!
Amazing how intelligent this macro is ...

I do have those Paul Graham CL books, and with these CL idioms becoming
more standard in Elisp, I should take a second look at them I guess.

-- 
cheers,
Thorsten




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

* Re: Change a symbol's plist member with (let ...)?
  2014-03-14 21:17 Change a symbol's plist member with (let ...)? Thorsten Jolitz
  2014-03-14 21:37 ` Nicolas Richard
@ 2014-03-16 18:10 ` Stefan
  2014-03-17  0:49   ` Thorsten Jolitz
  1 sibling, 1 reply; 7+ messages in thread
From: Stefan @ 2014-03-16 18:10 UTC (permalink / raw)
  To: help-gnu-emacs

> For the sake of this example, say I want to "con" the function
> `derived-mode-p' and make it believe outline-mode is actually derived
> from lisp-mode (or so ...).

In case this is not just a silly example, I'd have to ask why on earth
would you do that?


        Stefan




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

* Re: Change a symbol's plist member with (let ...)?
  2014-03-16 18:10 ` Stefan
@ 2014-03-17  0:49   ` Thorsten Jolitz
  0 siblings, 0 replies; 7+ messages in thread
From: Thorsten Jolitz @ 2014-03-17  0:49 UTC (permalink / raw)
  To: help-gnu-emacs

Stefan <monnier@iro.umontreal.ca> writes:

>> For the sake of this example, say I want to "con" the function
>> `derived-mode-p' and make it believe outline-mode is actually derived
>> from lisp-mode (or so ...).
>
> In case this is not just a silly example, I'd have to ask why on earth
> would you do that?

Thats why I said "For the sake of this example...", its just a contrived
example used to abstract away the detailles of my real use case (that is
about functions in Org-mode that start with (when (derived-mode-p
'org-mode) ...) but otherwise do exactly what I want ...

-- 
cheers,
Thorsten




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

end of thread, other threads:[~2014-03-17  0:49 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-14 21:17 Change a symbol's plist member with (let ...)? Thorsten Jolitz
2014-03-14 21:37 ` Nicolas Richard
2014-03-14 22:25   ` Thorsten Jolitz
2014-03-15 21:28     ` Nicolas Richard
2014-03-16 16:01       ` Thorsten Jolitz
2014-03-16 18:10 ` Stefan
2014-03-17  0:49   ` Thorsten Jolitz

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).