Skip to content

Simplify deftypeonce #283

@gilch

Description

@gilch

I don't like the once-decorators and I think I should remove them. Decorators can already be added on top (via :@##) and execute again on each reload. But decorators can have arbitrary effects and aren't necessarily idempotent. If you're writing them yourself, write them so they're reloadable. But sometimes one has to use libraries.

There is an easy way to ensure they've only run once after the fact: use a zap@ expression in a defonce. You could have a series of them in a progn as well. It doesn't particularly matter what the resulting value is. A None or () is fine. The fact that the global exists will prevent it from running again on a reload.

Metaclasses may also be tricky. And some are even in the standard library.

One can always use defonce directly on a type() call to work around limitations (or write some modules in Python). Maybe doing tricky things should feel tricky. Make the right way obvious.


deftypeonce can't do __slots__. It has to be done at class creation time and can't be added later. (Or it can, but doesn't work.) This isn't very compatible with reloading anyway. Maybe the docs should recommend using type or types..new_class in certain cases. With a decorator, this almost looks like a class declaration:

:@##X#(types..new_class X.__name__ () None X)
(defun Spam (env)
  (.update env : __slots__ '(x y)))

;;; or

(define Spam
  (type 'Spam ()
   (dict : __slots__ '(x y))))

Of course, this is no more reloadable than a normal class statement.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions