emacs-devel
[Top][All Lists]
Advanced

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

Re: Semantics of :initform and oset-default


From: Eric Ludlam
Subject: Re: Semantics of :initform and oset-default
Date: Mon, 09 Feb 2015 08:06:21 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0

On 02/08/2015 09:48 PM, Stefan Monnier wrote:
Hi Eric,

I have some questions about the default values of object slots:

- The Texinfo docs say:

      [...]
      The value passed to initform is automatically quoted.  Thus,
           :initform (1 2 3)
      appears as the specified list in the default object.  A symbol that
      [...]

   this seems to say that :initform is really an init*value*.  But then
   in eieio-tests.el we have:

      (defclass inittest nil
        ((staticval :initform 1)
         (symval :initform eieio-test-permuting-value)
         (evalval :initform (symbol-value 'eieio-test-permuting-value))
         (evalnow :initform (symbol-value 'eieio-test-permuting-value)
            :allocation :class)
         )
        "Test initforms that eval.")

      (ert-deftest eieio-test-21-eval-at-construction-time ()
        ;; initforms that need to be evalled at construction time.
        (setq eieio-test-permuting-value 2)
        (setq eitest-pvinit (inittest))

        (should (eq (oref eitest-pvinit staticval) 1))
        (should (eq (oref eitest-pvinit symval) 'eieio-test-permuting-value))
        (should (eq (oref eitest-pvinit evalval) 2))
        (should (eq (oref eitest-pvinit evalnow) 1)))

   which gives a different picture, and I don't really understand it: in
   the `symval' slot the :initform seems to be quoted (as documented),
   but in the other two (`evalval' and `evalnow') the :initforms are
   actually evaluated.

Hi Stefan,

Originally eieio only had an initvalue as you named it above because I didn't get what was supposed to happen with the initform, and I had a lame lambda form for cases where you might want to evaluate the form at construction time. The doc may not have been updated correctly when I tried to make eieio more CLOS compatible based on the feedback I was getting.

It was pointed out that the initform is supposed to be evaluated so there is a bit of a hybrid behavior which allows:

:initform "string"

which would work regardless of how/when things are evaluated. It also enables the very old eieio behavior:

:initform (1 2 and other constants)  ;; No quote needed

and also what a CLOS user might expect:

:initform '(1 2 and other constants)  ;; same end result as above

plus function evaluation:

:initform (symbol-value 'some-variable)

which is in the test you quoted.

The logic is up in `eieio-default-eval-maybe'.

The 'evalnow, and 'evalval slots in the test differ based on when they get evaluated.

A slot with :allocation :instance (the default) would have the form evaluated when it is constructed. A slot with :allocation :class is evaluated when the class is created. If just the symbol is in there, it acts as a constant value (ie - no function form to call)


- How is it supposed to interact with oset-default?  Is the value passed
   to `oset-default' interpreted as a plain value (to which the slot
   will always be initialized), or is it interpreted as a "maybe
   value maybe expression to be evaluated", like the :initform?

oset default doesn't have anything special around when the VALUE argument is evaluated, so that form is evaluated the way arguments to other functions are evaluated.

If you wrote:

(oset-default 'myclass someslot '(symbol-value 'moose))

then the first quote would be 'evaluated' sticking the form (symbol-value 'moose) into the initform for that slot. Then at instantiation time, the symbol value of moose would be calculated and stuck in as the slot value. ie:

ELISP> (setq moose 1)
1
ELISP> (oset-default 'foo test '(symbol-value 'moose))
(symbol-value 'moose)

ELISP> (foo "hi")
[object foo "hi" 1]


I don't know if that is correct or not. It didn't occur to me that you could do that until I tried explaining just now.

Here is the documentation I had used at the time:

http://www.lispworks.com/documentation/HyperSpec/Body/m_defcla.htm

and the key bit of text:

> The :initform slot option is used to provide a default initial value
> form to be used in the initialization of the slot. This form is
> evaluated every time it is used to initialize the slot.

It goes on to talk about the lexical environment which I didn't/don't know how to deal with.

I hope this helps.
Eric



reply via email to

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