walseb · 2022-12-19 03:17
Hi!
I have been searching for packages that allow me to define custom data types. My shopping list of features is:
- Generates a constructor function
- Generates getters and perhaps even setters for the data type.
- The fields defined have auto completion when constructing. Preferably it's scoped so that you don't get all fields of any data type ever defined in your auto completion results.
- Option to require the data type to be fully populated or not. Preferably this would trigger an error during macro expansion.
`cl-defstruct` is the closest I have found to having all of these features. Are there any more that I have missed in my search?
Thanks!
ieure · 2022-12-19 05:05
Have you looked at EIEIO / `defclass`?
walseb · 2022-12-19 18:06
Thanks! I haven't, I will check it out.
00-11 · 2022-12-20 21:07
"Type" can mean lots of things.
Unlike many languages, Lisp generally types *values*, not *variables*. But apart from defining and using either (1) an *abstract data type* / class (with type-defining operations etc.), (2) an explicit *set of values* as a type, or (3) a predicate (to define such a set implicitly), and apart from (4) using Common Lisp thingies such as `cl-deftype`, you might (5) consider using Elisp `defcustom` and its related functions.
Of course:
1. `defcustom` is for defining a *variable* of a type that you specify/define. And you might not want your typing only for global variables.
2. `defcustom` is for *user options*, and even if you do want to use your typing for global variables you might not want to have those be user options, i.e., pollute the user-option namespace and let users change the variable values.
You can nevertheless take advantage of the expressibility and relatively easy definition of types using `defcustom` keyword `:type`.
**For #1:** if you don't want your typing only for global variables, you can use predicate `custom-value-satisfies-type-p`, defined in library [`cus-edit+.el`](https://www.emacswiki.org/emacs/download/cus-edit%2b.el). It lets you check whether a given Lisp value satisfies any of a set of `defcustom` types. Each type tested against a value such as what `(get OPTION 'custom-type)` returns for an `OPTION`. (There are other similar functions and predicates in the library.)
> `custom-value-satisfies-type-p` is a compiled Lisp function in
[`cus-edit+.el`](https://www.emacswiki.org/emacs/download/cus-edit%2b.el).
>
> `(custom-value-satisfies-type-p VALUE TYPES)`
>
> Return non-`nil` if `VALUE` satisfies a type in the list `TYPES`.
>
> Strings and `nil` are ignored as elements of `TYPES`.
**For (#2):** I proposed as long ago as [2009](https://lists.gnu.org/archive/html/emacs-devel/2009-10/msg00668.html) that Elisp let you have global vars (defvars) whose definitions can use all of the features provided by `defcustom` (e.g. keywords such as `:type` and `:set`, but which are *not* user options.
And in 2015 bug (enhancement request) #[27348](https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27348) I provided a patch that implements this. That patch, with a couple trivial tweaks, is still valid against Emacs 28. (The enhancement was rejected, saying no one would want such a feature.)
The patch adds keyword `:not-custom-var` to `defcustom`. If its value is non-`nil` then the variable doesn't satisfy `custom-variable-p`, which means it's not available for interactive use (completion, `set-variable`, `apropos-user-option` output, etc.). IOW, it's for code more than for user configuration.
The patch also defines macro `defvarc`, which is just `defmacro` with `:not-custom-var` set to `t`. The `defcustom` keywords etc. could have just been added to `defvar` itself, for optional use. I defined a separate macro just to not interfere with any existing uses of `defvar`.
In sum, the patch uncouples interactive customization from the other features that Customize offers, in particular, ***type-checking*** and ***persistence***, and to provide those features for *non*-option variables.
The ability to *type-check*, provide `:set` and `:initialize` trigger functions, automatically `:require` libraries, add links to doc, associate with one or more `:groups`, etc. - I think these are useful things to be able to do with at least some defvars, not just with defcustoms.
Similarly, the ability to *persist* non-option variables in a user's custom file can be useful. (Persistence alone is a frequent question, to which the answer is `savehistsavehist-additional-variables`, `desktop.el`, or [Bookmark+ variable-list bookmarks](https://www.emacswiki.org/emacs/BookmarkPlus#FunctionSequenceVarlistBookmarks).)
The patch also includes a macro `with-user-vars`, which temporarily lets a set of variables be customizable. That is, it lets you treat a `defvarc` variable as if it were a `defcustom` option. So if you want you can use the Customize UI to change a defvarc's value, or define commands that use (e.g. complete) `defvarc` variable names.
Again, I have no idea whether either of these things helps you. Dunno what kind of Elisp typing you're looking for. HTH.