From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Pip Cet Newsgroups: gmane.emacs.devel Subject: Re: Always-true predicate? Date: Fri, 19 Feb 2021 19:04:34 +0000 Message-ID: References: <875z2qoqc6.fsf@gnus.org> <87h7ma25so.fsf@tcd.ie> <8735xu33jy.fsf@gnus.org> <87lfbm1o5s.fsf@gnus.org> <874kiaxxbs.fsf@iki.fi> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="426"; mail-complaints-to="usenet@ciao.gmane.io" Cc: "Basil L. Contovounesios" , Lars Ingebrigtsen , emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Fri Feb 19 20:06:22 2021 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lDB6b-000ASj-Qd for ged-emacs-devel@m.gmane-mx.org; Fri, 19 Feb 2021 20:06:21 +0100 Original-Received: from localhost ([::1]:59092 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lDB6a-00082u-SS for ged-emacs-devel@m.gmane-mx.org; Fri, 19 Feb 2021 14:06:20 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:39296) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lDB5W-0007TD-Qo for emacs-devel@gnu.org; Fri, 19 Feb 2021 14:05:15 -0500 Original-Received: from mail-oo1-xc2b.google.com ([2607:f8b0:4864:20::c2b]:45434) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lDB5T-0004LZ-SI for emacs-devel@gnu.org; Fri, 19 Feb 2021 14:05:14 -0500 Original-Received: by mail-oo1-xc2b.google.com with SMTP id s23so1498257oot.12 for ; Fri, 19 Feb 2021 11:05:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=YRQ1BgVQlAOi+i7ADyd2JBjSxvVoWKfYYAom729H11Q=; b=eD+ze36a22cBAs0Rf3c2F8gazaU8krZb0nPx9fPFa5iUSXAFMZT3dylOjAJ46knbSl BofU+XQ/mFzyrQzE0ItRySDlJqbYPkeaTqHTi3zQwwxlSz/eBxiqQZMdNSxshjpeaO+x M89cGFaDhAo4XwVJu3SCsn40loTXzf77Gz1VZnEKd8owwt8JjdMMZkBt46olutZwdmVh Wwmz+qQZq2Z+ht9XPMkirFbyFrkoIV8MXU6ygMYeXB2ZjRf7bUN7XIswoeZNHub8OXTW y1MX7kWKpcP1BBbKRaE9eFXkLo1DDW1XdntHGGpptCJG8tg2TO2CY/ChEwPXDgBD5B6f R5/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=YRQ1BgVQlAOi+i7ADyd2JBjSxvVoWKfYYAom729H11Q=; b=jrG813hUU16baRjYqWrecfzY89eku83i3eGw/7GzS5OtRUchYZ7qemKuZNt0ySH1Gc nT1Cmn8UkmSJ+9lkZlkRrTfHu4Vy4oUbvOZET1pr196N4EzkLGFj4jFxI6ZVZD7jXAtX QufJwqe2bRHuMckEiF0wZfmowr7wofwKjtDRnrNp+u3xl8Bg0ncCoZALcQ/u76+G0poG /KAeE0Xraeq7L9XAQ/LOjgjbZ+UJvU+m+LgcowbljgtGoA6Yqpu0VYsgTzfIIl54IKy9 m6CfejsMVt77PRqdZ6FHUuxUtJFJL4CBsM8Jkg9w5wErijexd3H67bfHzkRcN7adkaoB uUjQ== X-Gm-Message-State: AOAM533ENVyTOq58O7fnR2WppzLC4DpNCiH3PmWP0Qx2aI3Pon+f7/mo PyAKaYrW22xZlaI2OHr4+oeGIg71rb6Pyqkuojw= X-Google-Smtp-Source: ABdhPJzmC3GhiXtXX/EOUdxqWr1G04O8FTtMmfGlsaP/CMJP2Rhz0EvYfdXEZGKbAObBeQp/aH8k3lN7/9c5jQ0Bmpc= X-Received: by 2002:a4a:9873:: with SMTP id z48mr8153582ooi.44.1613761510447; Fri, 19 Feb 2021 11:05:10 -0800 (PST) In-Reply-To: Received-SPF: pass client-ip=2607:f8b0:4864:20::c2b; envelope-from=pipcet@gmail.com; helo=mail-oo1-xc2b.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:265283 Archived-At: On Fri, Feb 19, 2021 at 3:07 PM Stefan Monnier wrote: > >> Maybe we should let `lambda` take arguments like Scheme does, i.e. > >> (lambda (a b . c) FOO) instead of (lambda (a b &rest c) FOO), and in that > >> case we could simple use "lambda _" as a shorthand for "constantly". > > That would break things like pcase-lambda, though: we would no longer > > be able to generalize lambda meaningfully. > > [ Not sure if you missed the implied smiley or if you're going along with > the crazy idea. ] I mistook it for a serious proposal, sorry. > `pcase-lambda` wouldn't have to follow suit, so it'd be affected only if > it decides to. Then its docstring would need changing, because it would no longer be like lambda. > > Anyway, my problem with variadic functions isn't defining them, it's > > calling them. I think I should be able to say > > > > (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, but if we're making sunk-cost arguments, one could argue against fairly much any change... > 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. Note that it would be valid, but not required, for us to define what (or &rest args) means, something apply cannot provide. > > (f &rest a &rest b) = (apply #'f (append a b)) > > > > and > > > > (f &rest keywords values) = (apply #'f (zip keywords values)) > > I find the left hand side worse than the right hand side, FWIW. That's probably a matter of taste and JavaScript exposure :-) > 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... > (since it ends up > having to take the list of args, put them on the stack only to recreate > a new list for them on the other side; in theory it can optimized in > many cases, but in practice it's extremely hard to find those cases > reliably). I agree our current way of doing things needs work, FWIW. > > And if we can require optional arguments, why can't we provide them > > optionally? For example, let's say in Emacs 33 we want to expand > > copy-marker with a new argument to more clearly describe how the > > marker repositions itself relative to other markers (or implicit) > > markers at the same character position. But (copy-marker marker nil > > &optional 'something) would work in Emacs 32 (which would include the > > optionally-provided argument extension), and be equivalent to > > (copy-marker marker nil) there. > > This seems difficult to make it work reliably. > E.g. imagine the case where you've added an advice to `copy-marker`, so > it's now redefined to > > (lambda (rest args) > (message "About to call copy-marker") > (apply # args)) > > how would the caller know whether it should pass that `&optional 'something` ? The alternative is to use func-arity at runtime, which breaks just as badly. 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))) except not even the symbol "args" is part of the interface or function type. To me, a function is defined like (defun f (a b) "Add A and B." (+ a b)) The docstring, argument list, argument names, function name, and the actual lambda are all part of what makes "f" "f", and it's legitimate to use them all when calling it. 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. So, yes, wrappers would need a special symbol to use instead of &rest which would make them receive (at run time) all the information the caller provided (potentially at compile time). That would also be the natural place to trap calls inquiring about the docstring, function name, or arg spec. So something like (defun wrap (f) "Wrap F into a function object indistinguishable from it." (lambda (&universal-arg-list args) (cond ((eq args 'docstring) (function-docstring f)) ((eq args 'argspec) (function-argspec f)) ((eq args 'name) (function-name f)) ((apply-universal-arg-list f args))))) > I can see ways it could work, but I can't see an easy way to get there > from where we are without introducing either a lot of extra complexity > (and runtime cost) in the implementation, or backward incompatibility > for some use cases, or both. I don't think we can have all three, but then, we're in a pretty sorry state to begin with. As far as I know, there's no way to define a wrapper today that preserves arity, docstring, and arg spec, not even if you cons and eval a lambda list at run time. On the other hand, there's no way to define a "fast" wrapper function even if you keep all those things fixed, because you have to go through the apply machinery, which is fairly slow at present. Pip