File: inline.el.html

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)))


Youd 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.

Defined variables (0)

Defined functions (20)

define-inline(NAME ARGS &rest BODY)
inline--alwaysconst-p(EXP)
inline--alwaysconst-val(EXP)
inline--do-leteval(VAR-EXP &rest BODY)
inline--do-letlisteval(LISTVAR &rest BODY)
inline--do-quote(EXP)
inline--dont-leteval(VAR-EXP &rest BODY)
inline--dont-letlisteval(LISTVAR &rest BODY)
inline--dont-quote(EXP)
inline--error(&rest ARGS)
inline--getconst-val(EXP)
inline--leteval(VAR-EXP &rest BODY)
inline--letlisteval(LIST &rest BODY)
inline--testconst-p(EXP)
inline--warning(&rest ARGS)
inline-const-p(EXP)
inline-const-val(EXP)
inline-error(FORMAT &rest ARGS)
inline-letevals(VARS &rest BODY)
inline-quote(EXP)

Defined faces (0)