help-gnu-emacs
[Top][All Lists]
Advanced

[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, 20 May 2023 11:01:00 -0400

On Fri, May 19, 2023 at 9:07 AM Stefan Monnier <monnier@iro.umontreal.ca> wrote:
> > I'm trying to provide myself a tool for generic programming that
> > dispatches at compile time.
>
> I still don't understand what you mean by that.
> Do you mean that the programmers write
>
>     (my-foo a b c)
>
> and during macroexpansion this is turned into
>
>     (my-foo-for-thurbies a b c)
>
> when we somehow figure out that `a` is a "thurby"?

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've been writing too much repetitive
> > code, but I'm not a fan of ad hoc macros either.  Basically, I'm
> > trying to provide a C#-ish system for writing generic code
> > parameterized by interface requirements.
>
> [ "generic code" and "interface requirements" are ... generic terms with
> wildly different meanings in different communities, and I'm not familiar
> enough with the C# world to guess what you mean by that.  ]

I only hacked on C#'s generics for about a month a decade ago, so it
really is just my memory of the "flavor" of the generics being
expressed by constraints on interfaces.

>
> >> > (define-inline inline-+ (&rest args)
> >> >    (if (seq-every-p #'inline-const-p args)
> >> >        (apply (eval-when-compile (symbol-function '+)) args)
> >> >     (inline-quote (,(eval-when-compile (symbol-function '+)) . ,args))))
> >>
> >> IIRC you definitely need an `inline-letvals` somewhere here.
> >
> > That's the issue - if you use inline-letvals, then the code can't make
> > use of constant values provided as operands.
>
> Are you sure?  I think the real problem is that `inline-const-p` is not
> a function but a macro, so you can pass it as a first-class function
> E.g.:
>
>     (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?

>
> >> But also this will define the non-inlined version as something along the
> >> lines of:
> >>
> >>     (defun inline-+ (&rest args)
> >>        (if (seq-every-p ... args)
> >>            (apply '+ args)
> >>         (apply (symbol-function '+) args)))
> >>
> >> which is much too slow IMO.
> >
> > I agree.
> >
> > I posted a patch to emacs-devel for define-inline-pure-subr that
> > adapts the technique of define-inline.
>
> 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?

I was thinking I needed the original symbol redefined to avoid
multiple macro expansions of the operands, as define-inline-pure-subr
expands its operands before returning, so returning the inline-form is
problematic.  I also  consider the property that inlining is
uncooperative with advice to be a feature, particularly for pure
functions.  After all, the advice facility makes every function
identified by a symbol impure.

Lynn



reply via email to

[Prev in Thread] Current Thread [Next in Thread]