[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: inline function expansion
From: |
Lynn Winebarger |
Subject: |
Re: inline function expansion |
Date: |
Sat, 27 May 2023 10:34:23 -0400 |
On Sat, May 20, 2023 at 11:48 AM Stefan Monnier
<monnier@iro.umontreal.ca> wrote:
> > For my purposes, an "interface" spec is just a list of method and slot
> > signatures associated to some object, which will be realized by a set
> > of bindings specified via special forms and bound to some name.
> > Then a compile-time generic f is a factoring of a regular generic into
> > a generic function of interface realizations that produces a concrete
> > runtime function. I'm thinking to adopt the "place name" technique of
> > naming the concrete function by the form that created it, ie. \(f\
> > arg1-iface-realizer\ arg2-iface-realizer\ ...\). Note the check is
> > that the realizer provides all the required signatures (a superset),
> > which is why I refer to it as a "constraint" on the interface
> > implementation.
> >
> > Then the generic method could dispatch on simple wrappers created by
> > the iface-realizers. If constructors are invoked at compile time when
> > they appear in constant expressions and have constant arguments, then
> > the generic multi-dispatch method specialized on those realizers can
> > inline the call to the specialized method in the compiler macro, while
> > a residual generic method could do the same dispatch at run-time.
> >
> > But the point is to separate the expression of the algorithm from the
> > expression of the bindings that are used by the algorithm, without
> > resorting to either dynamic dispatch tables or ad hoc macros per
> > algorithm.
>
> I'm still lost. An example might help.
For my purposes, interfaces and realizations of interfaces are just a
way to specify bindings of symbols in a more structured and
encapsulated way than raw macros.
I'm still spit-balling here, but I'm thinking a generic
compile-time-dispatched (inlineable) "max" might be defined along
these lines:
;; ordering interface has two parameters
(define-interface ordering (bool-T elt-T)
;; return value of `lt' method satisfies bool-T interface
(method (bool-T lt) (elt-T a) (elt-T b)))
(define-realized-interface integer-ordering (ordering boolean integer)
;; bind lt method to built-in `<'
(method lt <))
(defgeneric max (< a b)
"Determine the larger of a and b according to <")
(define-inline-method max ((ordering <) &opaque a b)
"Determine the larger of a and b according to ordering <"
;; < is treated syntactically as a dispatcher
(if (< lt a b) a b))
;; because elisp does not allow applications in the operator position
(define-inlined-method integer-max (max integer-ordering))
;; Alternatively,
;; (integer-ordering lt) reduces at compile time to something like
;; #s(interface-method
;; #s(interface-realization
;; #s(interface ordering boolean integer)
;; <)
;; lt
;; <)
;; which `max' is specialized for by define-inline-method above, so
(defun integer-max (a b)
;; inlined by compile-time dispatch of the max generic method
(max (integer-ordering lt) a b))
;; These should produce t
(= (max integer-ordering 5 6) (integer-max 5 6))
(= (max (integer-ordering lt) 5 6) (integer-max 5 6))
(macroexp-const-p (macroexpand-all '(max (integer-ordering lt) 5 6)))
>
> >> (define-inline my-plus (&rest args)
> >> (inline-letevals args
> >> (if (seq-every-p (lambda (x) (inline-const-p x)) args)
> >> (apply #'+ (mapcar (lambda (x) (inline-const-val x)) args))
> >> (inline-quote (+ . ,args)))))
> >>
> >> seems to do (more or less) what your code illustrated.
> >
> > But then inline-const-val will (and inline-const-p) will get the
> > symbol 'x as the operand, right?
>
> I don't think so. Have you tried it (Edebug should work correctly)?
Ok, now I see why inline--testconst-p expands to include a call to
macroexp-const-p.
> >> I'm still not sure why you're not using a `compiler-macro` which seems
> >> to be exactly what you're after.
> >
> > I'm very finicky I suppose. I want to get constant expression
> > evaluation as automatically as possible, to enable the compile-time
> > dispatch cleanly. Or are you saying that generic methods can be
> > directly made into compiler macros?
>
> And here I'm lost as well. AFAICT there's just as little "directly made
> into" for define-inline as for compiler-macros (`define-inline` is just
> a way to define a function and its `compiler-macro` in one go).
Hopefully the example above clarified what I'm talking about - `max'
is specialized at compile-time, and reduced completely at compile-time
as well if all the arguments are constant. Although I would change
"inline-const-p" to test for function purity (exclude stateful
closures or otherwise impure functions).
> > I was thinking I needed the original symbol redefined to avoid
> > multiple macro expansions of the operands,
>
> `compiler-macro`s can decide to keep the call as-is without introducing
> an infinite macro-expansion loop.
>
I was concerned about an exponential rather than infinite number of
expansions , though I may have just been thinking conservatively.
Lynn
- Re: inline function expansion, (continued)
- Re: inline function expansion, Lynn Winebarger, 2023/05/18
- Re: inline function expansion, Stefan Monnier, 2023/05/19
- Re: inline function expansion, Lynn Winebarger, 2023/05/20
- Re: inline function expansion, Stefan Monnier, 2023/05/20
- Re: inline function expansion, Lynn Winebarger, 2023/05/21
- Re: inline function expansion, Stefan Monnier, 2023/05/18
- Re: inline function expansion, Lynn Winebarger, 2023/05/18
- Re: inline function expansion, Stefan Monnier, 2023/05/19
- Re: inline function expansion, Lynn Winebarger, 2023/05/20
- Re: inline function expansion, Stefan Monnier, 2023/05/20
- Re: inline function expansion,
Lynn Winebarger <=
- Re: inline function expansion, Lynn Winebarger, 2023/05/28
- Re: inline function expansion, Stefan Monnier, 2023/05/28
- Re: inline function expansion, Lynn Winebarger, 2023/05/28
- Re: inline function expansion, Stefan Monnier, 2023/05/28