inline

Homepage: https://www.gnu.org/software/emacs

Author: Stefan Monnier

Summary

Define functions by their inliner

Commentary

This package provides the macro `define-inline' which lets you define
functions by defining their (exhaustive) compiler macro.

The idea is that instead of doing like defsubst and cl-defsubst (i.e. from
the function's definition, guess the best way to inline the function),
we go the other way around: the programmer provides the code that does the
inlining (as a compiler-macro) and from that we derive the definition of the
function itself.  The idea originated in an attempt to clean up `cl-typep',
whose function definition amounted to (eval (cl--make-type-test EXP TYPE)).

The simplest use is for plain and simple inlinable functions.  Rather than:

    (defmacro myaccessor (obj)
      (macroexp-let2 macroexp-copyable-p obj obj
        `(if (foop ,obj) (aref (cdr ,obj) 3) (aref ,obj 2))))
Or
    (defsubst myaccessor (obj)
      (if (foop obj) (aref (cdr obj) 3) (aref obj 2)))
Or
    (cl-defsubst myaccessor (obj)
      (if (foop obj) (aref (cdr obj) 3) (aref obj 2)))

You'd do

    (define-inline myaccessor (obj)
      (inline-letevals (obj)
        (inline-quote (if (foop ,obj) (aref (cdr ,obj) 3) (aref ,obj 2)))))

Other than verbosity, you get the best of all 3 above without their
respective downsides:
- defmacro: can't be passed to `mapcar' since it's not a function.
- defsubst: not as efficient, and doesn't work as a `gv' place.
- cl-defsubst: only works by accident, since it has latent bugs in its
  handling of variables and scopes which could bite you at any time.
  (e.g. try (cl-defsubst my-test1 (x) (let ((y 5)) (+ x y)))
        and then M-: (macroexpand-all '(my-test1 y)) RET)
There is still one downside shared with the defmacro and cl-defsubst
approach: when the function is inlined, the scoping rules (dynamic or
lexical) will be inherited from the call site.

Of course, since define-inline defines a compiler macro, you can also do
call-site optimizations, just like you can with `defmacro', but not with
defsubst nor cl-defsubst.

Dependencies

Reverse dependencies