emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Always-true predicate?


From: Pip Cet
Subject: Re: Always-true predicate?
Date: Sat, 20 Feb 2021 09:40:38 +0000

On Fri, Feb 19, 2021 at 8:11 PM Stefan Monnier <monnier@iro.umontreal.ca> wrote:
> >> > (f a b c &rest d)
> >> > rather than
> >> > (apply #'f a b c d)
> >> I don't think it's sufficiently nicer to justify making such a change,
> >
> > I think "usage mimics declaration" is a very important concept,
>
> I generally agree and the above syntax is indeed satisfactory from that
> point of view (and funnily enough Scheme's neat (lambda (x . y) body)
> syntax (which is arguably inspired by a similar desire) does not enjoy
> such a nice equivalent at call sites since (f x . (append a b)) can't
> be distinguished from (f x append a . b)).

I discovered this the hard way :-)

> >> OTOH, the nice thing about `apply` is that it's just a function: no
> >> special treatment, no new syntax, nothing.  Try `grep apply
> >> lisp/emacs-lisp/bytecomp.el` and see how it really needs no
> >> special treatment.
> > ...but it gets that special treatment, which is why (apply #'or) is
> > mis-compiled.
>
> Actually, it's not the compiler, it's the optimizer.

I didn't say "by bytecomp.el", I only said it's mis-compiled. Which it
is. By the optimizer. Which is part of the compiler.

> [ Yes, it's a nitpick, but nevertheless...

If you think the optimizer isn't part of the byte compiler, please
change the first line of byte-opt.el which says it is ;-)

>   Also, I'm not completely sure in which sense it "miscompiles" it,
>   since it can't be compiled correctly, AFAIK.  ]

???

It's perfectly valid ELisp. It should throw. It doesn't.

> >> I'd rather reduce the use of `&rest` and `apply` than try to make it
> >> more sexy, since it's fundamentally quite inefficient
> > I think the inefficiency is fundamental to "apply", not to "&rest".
> > When you call a known procedure all the packing and unpacking of
> > arguments can be inlined...
>
> IMO it's more fundamental to `&rest` because the callee can rely on the
> `&rest` list being a fresh new list (it can safely perform destructive
> update on it).

So to avoid having to cons up a new list you have to know about the
callee to know it doesn't do that, which apply prevents you from
doing.

> > I think we're back to a fundamental question here: if I understand
> > correctly, to you, an ELisp function is fundamentally of the "take a
> > list, return a Lisp object or throw" type, as though it were defined
> > like this:
> >
> > (defan f args (if (/= (length args) 2) (throw
> > 'wrong-number-of-arguments)) (+ (car args) (cadr args)))
>
> Indeed.

Looking forward to your patch removing all argument names from defuns
everywhere ;-)

I'd like to know what equivalence relation you're using when you say
two bare functions f and g are "the same".

I'm pretty sure it's not any of the following:
- their defuns are the same
- they produce the same values for the same inputs
- they produce the same values for the same inputs at the same complexity

> > In your world, (lambda (&rest args) (apply #'f args)) is the same as
> > f. In my world, we have "func-arity", to which it isn't.
>
> In my view, a function value of the form (closure ...) or (lambda ...)
> or #[...] has arity, but a function value represented by a SYMBOL does
> not because it can change at any time.

In my view, every callable function has arity, which can change at any
time in the case of functions that are symbols (which might become
uncallable, too). (It can also change for closures or lambdas if their
underlying lists are mutable).

It seems obvious to me that if f and g are "the same", (func-arity f)
and (func-arity g) should return equal cons cells. That means unless f
is a subr of arity (0 . many), f is not the same as (lambda (&rest
args) (apply #'f args)).

BTW, I made a mistake in my previous email:

(f a &rest b c) should be equivalent to (apply #'f a (append b (list
c))). No zips, and no spreadification of the last argument.

Pip



reply via email to

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