Skip to content
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 (setf (get-default ...)) to hooks #381

Closed
Ambrevar opened this issue Sep 17, 2019 · 13 comments
Closed

Switch from (setf (get-default ...)) to hooks #381

Ambrevar opened this issue Sep 17, 2019 · 13 comments

Comments

@Ambrevar
Copy link
Member

Hooks could effectively supersede the setf-ability of get-default.
The latter has multiple issues:

  • Restarting Next from the REPL does not reset the slot default values.
  • If the user appends to default slot values in init.lisp, every restart from the REPL will stack more of the same values.
  • Changes are irreversible. If A sets a default and B too, we lose information.
  • It's not compatible with all compilers, e.g. CCL. Ultimately it would be nice to have CCL/ECL support.
@vindarel
Copy link
Contributor

Those are usability problems indeed. My guts tell me we'd rather do it in pure CL though.

@Ambrevar
Copy link
Member Author

What do you mean "pure CL"?

@vindarel
Copy link
Contributor

With standard CL mechanism, thus without the hooks library.

@Ambrevar
Copy link
Member Author

Ambrevar commented Sep 17, 2019 via email

@Ambrevar Ambrevar mentioned this issue Sep 17, 2019
@easbarba
Copy link
Contributor

easbarba commented Sep 24, 2019

Cant say about hooks, but that syntax is rather verbose, would be interesting a simpler interface to accessors as

(with 'minibuffer (setf minibuffer-font-size "1em"
                              minibuffer-style '((body ...))))

As in Python context-manager.

@Ambrevar
Copy link
Member Author

Ambrevar commented Sep 24, 2019 via email

@easbarba
Copy link
Contributor

easbarba commented Sep 24, 2019

That's even better.

@Ambrevar
Copy link
Member Author

What do you mean? Emacs' setq does not deal with classes.

@Ambrevar
Copy link
Member Author

Ambrevar commented Sep 26, 2019

I thought a little bit about this and I realized a big issue with hooks: if they are not named, the user essentially loses control over what's in it. Lambda are hard to introspect (you can disassemble them...) plus they cannot be compared, which means that adding the same lambda twice to the hook will effectively run it twice.

We could write macros to automatically name the functions, but automatic names don't really help telling what's inside the function, so we've got the same introspection problem.

So here is my suggest: in their init.lisp, the user writes their own functions in which they configure all the slots they want.
Then they write a function that adds the handlers to the write hooks.
Then they add this last function to *after-init-hook*.

Example:

(defun my-minibuffer-defaults (minibuffer)
  (setf
   (minibuffer-line-height minibuffer) "1.1em"
   (minibuffer-font-size minibuffer) "1.1em"))

(defun my-interface-defaults ()
  (push (search-engines *interface*) "https://foo.org...")
  (hooks:add-hook (hooks:object-hook *interface* 'minibuffer-make-hook)
                  #'my-minibuffer-defaults))

(hooks:add-hook '*after-init-hook* #'my-interface-defaults)

Pros:

  • It's concise.
  • We keep full control, we can introspect everything.
  • Changes are reversible, it's easy to delete any handler.
  • Handlers are not duplicated when reloading init.lisp.
  • No need for convoluted macros.
  • No global variables.
  • No generate functions.

Cons:

  • This is a rather unconventional (very "functional programming" style) approach to configuring a program. But with the right documentation and the right examples, this could be The Right Thing©. Thoughts? @vindarel @jmercouris ?

@Ambrevar
Copy link
Member Author

@vindarel
Copy link
Contributor

Is it required that the first add-hook be inside my-interface-default ?

@Ambrevar
Copy link
Member Author

You mean the configuration of minibuffer-hook? Yes, because the hook only exists once *interface* is instantiated.

@Ambrevar
Copy link
Member Author

Closing this in favor of #419.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants