Skip to content

autoloading functions defined by yourself #13

Open
@Luis-Henriquez-Perez

Description

Hi Noctuid! I'm a big fan of your work. I think that evil-lispyville and general are excellent packages. And your dotfiles are a great example to look at. I actually agree a lot with your dotfiles readme. It should definitely be in awesome emacs configs. Actually I'll probably pull request it soon.

In your awaken.org file you mention that you aggressively autoload functions to reduce startup time. With functions from other packages, I see how that happens using the :commands keywords. However, for some packages I have a lot of functions that are defined by me in my big org file. If it's a just a few, using with-eval-after-load on them (or the :config keyword in use-package) is fine. But what if there are a lot, like hundreds of them? If we try to use with-eval-after-load it will likely produce a small lag when the feature is loaded because many functions are being defined. In your awaken.org file it doesn't look like you've run into such a case yet, you only define a relatively small number of functions for each package.

The basic problem is that emacs's autoload facility assumes you're going to use separate files for your autoloads.

There are two ways I thought of to deal with this.

  1. is to tangle to multiple autoload .el files and place calls to autoload in the org file. (This could be automated say with a :autoload switch in code blocks so you wouldn't actually have to create your own autoload calls).)

The problem is that tangling time (with a custom tangle function) increases significantly when tangling to multiple files. This potentially could be resolved if you could somehow only tangle to a file only if source blocks that tangle to it have changed, but I'm not sure how to check that.

  1. Use a custom autoload method powered by with-eval-after-load

I hacked together my own autoload method. The gist is to have a list alist of (FEATURE . LOAD-FEATURE-FN). When you have a function you want to autoload (in this example it's an autoload adding evil integration to eshell) function:

(with-eval-after-load '+eshell-evil-autoloads
  (defun my-autoload-fun ()
    ...))
(fset 'my-autoload-fun (alist-get '+eshell-evil=autoloads my-autoload-alist))

The call to the my-autoload-alist will return this lambda:

(lambda (&rest args)
  (interactive)
  (provide 'eshell-evil-autoloads)
  (funcall this-command args))

So all of the evil eshell autoloads point to the same lambda.

Of course this needs to be tidied up a bit perhaps one lambda for all interactive functions and one lambda for all non-interactive. Also if we only create one lambda the neither docstring will nor the arguments not be available in advance.

The big qualm I have is I'm not sure how efficient this is and whether it's worth it. I know autoload is coded in c which I assume was to avoid the overhead of creating these so many functions in lisp.

I'd appreciate any ideas you'd have on this.

Activity

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

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