emacs-devel
[Top][All Lists]
Advanced

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

Re: Subprojects in project.el (Was: Eglot, project.el, and python virtua


From: Dmitry Gutov
Subject: Re: Subprojects in project.el (Was: Eglot, project.el, and python virtual environments)
Date: Fri, 2 Dec 2022 03:32:42 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.4.2

Hi again,

It's probably time to continue here.

On 26/11/2022 09:26, Eli Zaretskii wrote:

Again, you are talking about project kinds already supported by project.el
as its built-ins.  I'm asking how to produce a project of a custom type.

To produce a project of custom type, you decide the data structure for
that type, write implementations for all the required (and perhaps some
optional) generic methods, then create that structure.

It seems I need to spell out everything every time I'm writing something
because otherwise you interpret it out of context.  So here: I'm asking how
to produce a customized project whose type is 'transient', but which doesn't
go by the rules of the built-in 'transient' project.

I'm trying to be precise both to avoid misunderstanding. Even here you were using the terminology that seems to conflict with established practice.

IIUC, you want to produce a project whose type is not 'transient', but which inherits from 'transient' some of its behaviors.

As for "project of custom type", where "custom" means "not one of the known
types", there's still a situation where my project is similar enough to one
of the built-in types to make reimplementation of all the APIs overkill.
One could want to use some of the APIs without change and customize others.
So this, too, is something that project.el should IMO allow without too much
fuss.

So, what you are asking for is perfectly reasonable in theory. Also the current theory of OOP suggests that type inheritance comes with its downsides as well. For instance, the straightforward way Joao was suggesting (create a defclass) will mean nailing down the internal structure of a type which would make it more difficult to create internal changes to it -- because somebody might have inherited from it, and might be using the exposed fields, etc.

Asking for a public constructor, however, can help in this regard as well, if you understand how to implement delegation using it. Meaning, you would still create your own type, but then to delegate the implementations of methods you would create an instance of the type to delegate to, and call said methods on it. This the type's evolution would only be limited by the backward compatibility of its constructor.

You asked, however, how to instantiate a project of a type belonging to
"someone else". But didn't explain why.

The "why" is "because one needs to".

The question also sounded odd because there is little point to "inherit" from 'transient'. Because that type's definition is only two lines:

  (cl-defmethod project-root ((project (head transient)))
    (cdr project))

There is literally nothing to reuse. The rest of that type's behaviors reside in the default definitions of other generic functions. So you can just create your own type, create its method for the above generic function, and then override the rest of the behaviors as needed.

If you wanted to inherit from the 'VC-aware' backend, however, that is a different discussion. I would ask which parts of it you need, and whether you intend to honor the project-vc-* user options, as its methods do. Or whether perhaps you just wanted to reuse the VC-based fast file listing implementation. Which would be a little easier to make public with an established signature.

The reasons not to rely on internal structure, as a reminder:

- The internal structures are prone to change, and you don't want your
code to break when that happens.
- When implementing some feature that works with projects, you generally
want it to work with all kinds of projects (which was the whole point of
project.el -- to make this approach work). And that would mean talking
to them through common methods, rather that examine the internals of
this or that project type.

I'm fine with all that, but it sounds like the above makes it impossible to
implement custom project objects, maybe because there's no make-project
method that one could use and/or subclass.

I usually answer this way because often it's not a good idea, and there are better ways to reach the goals of the person who's asking.

Still, if you do want to inherit from 'VC-aware', we can make a public constructor for it. Probably after Emacs 29 is released, and we can see that the structure is settled (it's looking this way now).

As for 'transient', well, the constructor can be added as well. The structure is stable and least likely to change; unless we just make an executive decision to turn them all into structs or whatever. I just didn't want to encourage people using it -- even Joao's usage is odd because he not only calls the 'project-root' function, but also 'project-files', and it's just luck that its behavior suits his current goals.



reply via email to

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