-
-
Notifications
You must be signed in to change notification settings - Fork 426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Switch from class-star to nclasses. #2784
Conversation
8fbf480
to
fee7d5c
Compare
I'll probably review after type inference PR is merged, so that we don't do it twice へ(゜∇、°)へ |
Type inference should be merged in nclasses (see atlas-engineer/nclasses#5), so it won't disturb this PR which can be review now I believe. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All good, except that :accessor nil
spilt everywhere (and not spilt somewhere it probably should be consistently spilt, like in prompter:constructor
). Maybe inherit accessors from superclasses, if present? Otherwise it feels like yet another syntactical trap.
source/buffer.lisp
Outdated
@@ -1302,7 +1290,8 @@ proceeding." | |||
(prompter:enable-marks-p t) | |||
(prompter:actions-on-return (list (lambda-unmapped-command set-current-buffer) | |||
(lambda-mapped-command buffer-delete) | |||
'reload-buffers)) | |||
'reload-buffers) | |||
:accessor nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is weird. Should we maybe not generate accessor if it's present already? We pull moptilities
in already, so why not use it for accessor inspection too?
@@ -253,8 +252,7 @@ It's the complement of `nyxt-packages' and `nyxt-user-packages'." | |||
((name nil | |||
:type (or symbol null)) | |||
(class-sym nil | |||
:type (or symbol null))) | |||
(:accessor-name-transformer (class*:make-name-transformer name))) | |||
:type (or symbol null)))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then, nil
is a symbol
too. However hacky it is :P
source/lisp-system.lisp
Outdated
@@ -27,7 +27,8 @@ | |||
((prompter:name "Quicklisp systems") | |||
(prompter:constructor (mapcar #'ql-dist:short-description (ql:system-list))) | |||
(prompter:actions-on-return (lambda-command quickload* (systems) | |||
(ql:quickload (first systems)))))) | |||
(ql:quickload (first systems))) | |||
:accessor nil))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's alarming yet again...
Accessors cannot easily be inherited, because unlike the situation with types, generating accessors has a global side effect. Generating the wrong accessor would be an important bug. The issue is the same with hu.dwim.defclass-star. If you think about it, it's normal to say "do not generate an accessor for inherited slots", because the global class option is otherwise to generate accessors for all slots. There is no way to infer that the user does not effectively want to generate the accessor from the inherited slot, as "package polluting" as it might be. |
But then, if the package is different, then the slot is most likely inherited, right? For those, we most probably, should not generate anything. It's a hacky heyristic, but a reasonable one, isn't it? |
@Ambrevar, CI was failing because |
Done, thanks for catching the bug! |
Oh, sems like some accessors are not generated, failing the CI... |
I've investigated this and there are multiple issues.
Issue 2 is a fundamental problem with CL and CLOS. Let me describe it:
Recipe: (in-package :cl)
(export 'foofoo)
(defpackage :child (:use :cl))
(in-package :child)
(defclass dummy () ((foofoo :accessor foofoo)))
; => ERROR! Any idea how we are supposed to deal with this kind of issues in CL? |
The only idea that comes to my mind is checking the status of the slot symbol for being inherited. But that's yet another heuristic. Not sure that we can do any better, though (´・_・`) |
What do you mean? Can you give an example? |
I mean using (and *automatic-accessors-p*
(or (and (eq (symbol-package name) *package*)
;; NEW CHECK:
(not (eq :inherited
(nth-value 1 (find-symbol name *package*)))))
(not (eq *accessor-name-package* :slot-name)))) |
Note that the snippet above has a type error, so don't use it verbatim :P But the idea should be clear, I hope ( ̄(エ) ̄)ゞ |
That changes nothing because if the symbol is inherited, then the |
Right... Then, I guess, we have to live with it, debug it, and lock as many packages as we can (҂⌣̀_⌣́) |
Debug what? And we are already locking all our packages, what do you mean? |
@aadcg Any insights on this? I have one: in the case of Thoughts? |
I didn't follow this PR closely as I don't think I can provide much insight... I trust your judgement! |
It finally passes! I'll rebase and squash. |
Another issue, although this time it's an easy one: nclasses does not bind slots by default. Shall we explicitly pass nil, or shall we add an option to nclasses to default to NIL? |
I can't think of a use case of such an option, so I'd go with the first idea. |
It's standard CLOS: think of it like a symbol that can be I agree that it is very rarely needed in practice. One use case I can think of is when writing generic code to instantiate object, and you need to tell apart But in this case, nclasses Conclusion: I'd go with first option too! |
@Ambrevar, thanks for the clarification! It helped me to understand the context of the question :) |
Let's leave unbound that which shall be unbound. |
What do you mean? Example? |
19c7c65
to
8006b4c
Compare
The Everything is ready as far as I'm concerned. I'll merge tomorrow if there is no objection. |
I mean we shouldn't default to any value if it's not provided. Yes, Rationale: unbound slot is semantically different from the NIL slot. There are Think of it as the |
A particular example: I use unbound slots in my cl-telegram-bot-auto-api, because Telegram APIs always return incomplete objects, in which defaulting to NIL means misinterpreting the values into being false, while they are just unbound/unknown. And that's the basis of all this library—leaving unbound that which is truly unbound/unknown. |
In practice, I find that Also adopting this default makes for minimal changes in Nyxt itself (this PR is almost exclusively limitied to removing the accessor names). If you think this is really unreasonable, we could add a class option to specify the slot default. |
Yes, but
That sounds like the best course of action, yes. |
OK to merge this and add the nclasses option later? |
All good from my side! |
yes! |
a2048bb
to
b266dfd
Compare
Done, thank you all! |
Thanks for working on it <3 |
Description
Switches from class-star to https://github.com/atlas-engineer/nclasses.
News:
Fixes #1102.
Discussion
:accessor nil
. Seeprompter:active-attributes-keys
for instance. It makes sense, but it's a bit unwieldy. Can we do better?To do:
nclasses
for Guix.Checklist:
Everything in this checklist is required for each PR. Please do not approve a PR that does not have all of these items.
cd /path/to/nyxt/checkout git submodule add https://gitlab.common-lisp.net/nyxt/py-configparser _build/py-configparser
:documentation
s written in the aforementioned style. (It's OK to skip the docstring for really trivial parts.)changelog.lisp
with my changes if it's anything user-facing (new features, important bug fix, compatibility breakage).migration.lisp
entry for all compatibility-breaking changes.