emacs-devel
[Top][All Lists]
Advanced

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

Re: Un-deprecating oset


From: Stefan Monnier
Subject: Re: Un-deprecating oset
Date: Tue, 05 May 2020 10:50:39 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

> I used to assume that `oref' and `oset' were traditional CLOS functions
> but now that I have actually looked around a bit I realize I likely was
> wrong about that.

Indeed, CLOS uses `slot-value` instead.

> I found some documents about CLOS that mention `slot-value' and
> `with-slots'

In my mind (and I expect it's also the case in all implementations),
`with-slots` is built on top of `slot-value`.

> but never `oref' and `oset'; so now I assume that the latter two are
> EIEIO additions.

Indeed.

> I can think of the following approaches to set a slot:
>   1. (oset object slot value)
>   2. (eieio-oset object 'slot value)
>   3. (setf (oref object slot) value)
>   4. (setf (eieio-oref object 'slot) value)
>   5. (setf (slot-value object 'slot) value)
>   6. (with-slots (slot) object (setq slot value))

Right.  And only 5 and 6 work in CLOS.

> Above you state the goal of "namespace sanity" and suggest the use of
> [2].  That seems to make a lot more sense and one might argue that the
> deprecation warning should be changed to make that suggestion.

I don't have a strong preference either way: I'm more interested in
deprecating `oset` than in the choice of the alternative we
should recommend.

But FWIW, I chose (3) as the recommendation on the following basis:

- I expect most people to consider `eieio-oset` as an ugly name.

- `setf` on `slot-value` is significantly more verbose and hence will
  encounter more resistance.

- I like `setf` and using it sometimes makes further rewrite more
  obvious when the textually identical (oref X Y) appears.  E.g.

      (oset X Y (cons Z (oref X Y)))
  vs
      (setf (oref X Y) (cons Z (oref X Y)))

  where I don't know about you, but my brain tends to suggest

      (push Z (oref X Y))

  when it sees the second but not the first.

But again I'm not at all wedded to this suggestion (and we can also
recommend *several* options if we want).

> You mention that you do NOT intend to remove `eieio-oset'.  And that
> can only mean that `eieio-oref' is safe too -- right?

Yes.  They're safe because they use the `eieio-` prefix which cleanly
belongs to (and is used by) the `eieio` package.

> But what about `slot-value'?

Good question.  There's something to be said for bringing it into the
`cl-` namespace (along with `defclass`) but it hasn't happened yet and
I haven't found the stamina to undertake this job.

[ To be honest, I dislike EIEIO: not only it stomps all over the
  namespace but I dislike objects whose field access requires
  a hash-table lookup, which is why I only use `cl-defstruct`.  ]

> "get/set the value"-functions should all have rather short names and
> that this does not only apply to the most important such functions,
> like `setf', but also to e.g. `get'/`put' and, yes, `oref'/`oset'.

Makes sense (tho I'm in the camp of those who prefer to strive for
immutable objects, so I do want a concise object-access but I'm quite
willing to use a significantly more verbose object-modification syntax).

> Object-oriented programming is not a core language feature, but does
> that mean it has to be treated as a second class citizen?

That is definitely not the intention.

> The deprecation of `oset' appears to be motivated by two IMO unrelated
> goals:
>
>   A. Take another step towards the elimination of prefix-less symbols.
>
>   B. Avoid unnecessary setters.  Use `setf' instead.

The goal was only (A): we can't avoid setters because they are visible
in the macroexpansion of `setf` and get stored in `.elc` files.
So while I did choose the `(setf (oref ..) ...)` recommendation based on
a preference for `setf` there is no intention to *avoid* setter
functions, because setter functions are indispensable (even if they
don't appear in the source code).

Common Lisp does try to avoid setter functions and *can* hide them, but
Elisp can't really hide them.

>   II.  I might come to agree that `oref' and `oset' should get a
>        prefix.  I would probably argue that it should not be `eieio-'
>        but maybe `cl-' or `slot-'.  Or `object-get' and `object-set',
>        I suppose.

I think the design of the namespacing of `oref` would have to be done
along with that of `slot-value`, `defclass`, etc...

>   III. But I simply do not understand how it makes sense to deprecate
>        `oset' without *at the same time* deprecating `oref' as well.

I could go along with that.  I expect this will encounter more
resistance, tho.

>        - Without assurances otherwise, I cannot shake off the feeling
>          that as soon as I have gotten used to `oset' not being around
>          anymore, then `oref' will be removed as well. (I would rather
>          get it over with in one go.)

"As soon as": I'd say it's unlikely.

> It does however take away the programmers choice whether to use
> `setf' or not, but only when it comes to OOP, which seems unfair.

I don't understand this "programmers choice" argument.
You can use either `eieio-oset` or (lambda (..) (setf (oref ..) ..)) if
you need a function, so the choice still exists just as much as before.


        Stefan




reply via email to

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