From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: =?UTF-8?B?Sm/Do28gVMOhdm9yYQ==?= Newsgroups: gmane.emacs.devel Subject: Re: Attaching context info to an error Date: Thu, 28 Dec 2023 14:12:09 +0000 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="27364"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Thu Dec 28 15:13:00 2023 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 1rIr88-0006y6-GU for ged-emacs-devel@m.gmane-mx.org; Thu, 28 Dec 2023 15:13:00 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rIr7e-0001fF-FJ; Thu, 28 Dec 2023 09:12:30 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rIr7d-0001f0-Lb for emacs-devel@gnu.org; Thu, 28 Dec 2023 09:12:29 -0500 Original-Received: from mail-lj1-x231.google.com ([2a00:1450:4864:20::231]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rIr7b-0001wo-Bg for emacs-devel@gnu.org; Thu, 28 Dec 2023 09:12:29 -0500 Original-Received: by mail-lj1-x231.google.com with SMTP id 38308e7fff4ca-2ccc7d7e399so28167861fa.0 for ; Thu, 28 Dec 2023 06:12:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1703772745; x=1704377545; darn=gnu.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=Y6UkUp3pQsWyXGXBKpd6RkKOhZCBx+D4rA+e1TrcI4w=; b=mgEHhhnxUH6R5itL/2kMX6DwjogCZdjql0RX5jqGqAmoqbg6otCwONMiwkcfvMgckU w2iep0jQhyvaOY3A1M/zGHPDiRHl+Z+lGEDWisPzSSIMFfqekT6rdTx5hc+kFNm2YElk 9Assf9E8xQUuFd5xyA61VgNJYZQp/KIGVkM+jRDZa/qRPDkuEu3hU3HyBIYRceLLZUf9 rWLkaE7VKfhDO49U72hyJxGP2K+NSS12BojkVbik2tnCPSvRvJGcrSxnou+vST7Zwyay qjSvkNyjQgW6BcAqj49VpfpYj6UkbNeJajYr15nxvGKTTA+TFZ/4xFSRu4uH5WmvZiTr /SvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703772745; x=1704377545; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Y6UkUp3pQsWyXGXBKpd6RkKOhZCBx+D4rA+e1TrcI4w=; b=j9uG+X5C2yWIxhAkJedLIN0Yd37SNoEaYVk5NB395dNhaneL34kk4F2w3JL288Kp6b kqjZ6B4c/zjJNHKTuzeKp0OMn0rwS9yLtMqAaQBz71/XKdia5Nn7m5AhZgSxcP39vheu 6zhIcZCc8Wgo384LksvURT+aioIDxwT/BF+dLzGgX48yPjRNRWIUJSlUhomo1APNPGA9 GT9Wu5CCudrR1kWxpIHmZ751RzHbm5UY7IU0mvj+3Gnr9k2eTrNt4lHsm6SrMU3ThaPr 5uOLnCZiBggG1mSGItXOXxsaWH+Kr0wNqMTp2u29vATtBIRNykDDK/s9b+KfLYMssH6q eWyQ== X-Gm-Message-State: AOJu0YwiYo6qvV5nZIP6JwgtzzN818L35IyiwkDqPnjJridtGTcOsYkO 6DITUvifDFLlIfkBYvi6i/fm10OR3QQmFhsz6glS43nx1P4= X-Google-Smtp-Source: AGHT+IGR9DdD5O/nEHnisEUZWTLfTHtHhdE9BeFGrFRgG9sbqnHJMrGecJFSKI6z/AG3y5rcuGHiLIX7M1JNJsw64kU= X-Received: by 2002:a2e:8052:0:b0:2cc:d547:7f07 with SMTP id p18-20020a2e8052000000b002ccd5477f07mr1640903ljg.13.1703772745223; Thu, 28 Dec 2023 06:12:25 -0800 (PST) In-Reply-To: Received-SPF: pass client-ip=2a00:1450:4864:20::231; envelope-from=joaotavora@gmail.com; helo=mail-lj1-x231.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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 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-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:314279 Archived-At: On Thu, Dec 28, 2023 at 7:05=E2=80=AFAM Stefan Monnier wrote: > > >> >> [ Not clear what `initialize-instance` would be used for. > >> > It is passed the keyword arguments that are passed to CL:ERROR > >> > or CL:SIGNAL [1,2]. > >> Yes, I know, but that doesn't tell me what it lets us do that we can't > >> do right now. > > I guess we can do everything with symbol and cons, > > I don't mean "do" as in "Turing equivalent". > "less work" is a good thing to "do". I just don't know in which way > `initialize-instance` lets one do less work. It's not just initialize-instance, of course, it's CLOS or an equivalent. And what does that give us? Much that we are reinventing. And reinventing is "more work" (TM). Top of my head, CLOS gives you hierarchies easily, with generic functions doing the right thing by default when called with an instance of the subclass. That's the "standard method combination" [1], easy to define readers, writers or full accessors... all as generic functions. A uniform data representation for which you can someday (TM) write an interactive object inspector. > > I'd guess the cl-averse are still doing structs with vectors :-) > > I don't think I'm strongly "cl-averse", but I'm rather not familiar > enough with it to know its benefits. Having modified some of its code > I'm familiar with its cost and what it does, but that doesn't > immediately translate into ideas for how I could make good use of it. Yes, I have a lot of experience with both Lisps so it's easy to see the difference where one trumps the other, sometimes spectacularly. Elisp does trump CL in some every specific areas, Edebug is easily one of them. I'm enjoying reading this new "community spec" of CL (links below), it's really well done. And if anyone can learn CL in a weekend, it's you ;-) > I don't think this has anything to do with `&rest` or not. It sounds > like a bug in `shared-initialize` or `initialize-instance` (or > a disagreement between the two). I suggest you try and write a short > recipe for it and make it a bug report. I think I already did (well maybe not report-emacs-bug, but here's the problem again) ; SLY 1.0.43 (#) CL-USER> (defclass foo () ((bar :initarg :bar) (baz :initarg :baz))) # CL-USER> (make-instance 'foo :bar 42 :baz 42) ; presumed client code # CL-USER> (defclass foo () ((bar :initarg :bar))) # CL-USER> (make-instance 'foo :bar 42 :baz 42) ; whoops ; Debugger entered on # CL-USER> (defvar *bazzes* (make-hash-table :weakness :key)) *BAZZES* CL-USER> (defmethod initialize-instance :after ((x foo) &key baz &allow-other-keys) (setf (gethash x *bazzes*) baz)) # CL-USER> (make-instance 'foo :bar 42 :baz 42) ; now works again # CL-USER> *** Welcome to IELM *** Type (describe-mode) or press C-h m for help. ELISP> (defclass foo () ((bar :initarg :bar) (baz :initarg :baz))) foo ELISP> (make-instance 'foo :bar 42 :baz 42) ; so far so good # ELISP> (defclass foo () ((bar :initarg :bar))) ; redef foo ELISP> (make-instance 'foo :bar 42 :baz 42) ; will error, good, expected *** Eval error *** Invalid slot name: "#", :baz ELISP> (cl-defmethod initialize-instance :after ((x foo) ((&key baz &allow-other-keys) t)) (setf (gethash x *bazzes*) baz)) ^^^^ odd specializer, but OK initialize-instance ELISP> (defvar bazzes (make-hash-table :weakness 'key)) bazzes ELISP> (make-instance 'foo :bar 42 :baz 42) ;; will error unexpected *** Eval error *** Invalid slot name: "#", :baz Yes, happens in shared-initialize, but can it be fixed while also keeping the expected error above? Doesn't seem easy. In CLOS, the initialize-instance generic automagically becomes "other-key" friendly if -- and only if -- one of its methods is. >From [2]: The set of valid initialization arguments for a class is the set of valid initialization arguments that either fill slots or supply arguments to methods, along with the predefined initialization argument :allow-other-keys. The default value for :allow-other-keys is nil. In fact, this allows you to keep the tight initarg validation behaviour even without &allow-other-keys in there. So in CLOS, you can (defmethod initialize-instance :after ((x foo) &key baz) (setf (gethash x *bazzes*) baz)) So that (make-instance 'foo :blergh 42) still reassuringly errors. > >> I'm afraid that doesn't tell me how to attach context to an > >> error object. The context I'm talking about are orthogonal to the err= or > >> objects themselves: any kind of context info could be attached to any > >> kind of error object. > > I don't know what "context" you are talking about (I guess it > > was in the initial email, but I couldn't grok it). > > In different cases we may want to add contextual info about an error, > such as the time at which it was signaled, the backtrace, some subset of > the backtrace (e.g. just the name of the innermost function), or the > list of files we're in the middle of loading, or some node in > a data structure within which we were operating when the error occurred, > ... > > Usually which info to collect will depend on what it will be used for, > so it's under the control of the outer code, and is thus orthogonal to > the error that's signaled. OK, I think I'm starting to see. You're looking at this from a data representation perspective, and CL solves (presumably) the same problem you are trying to solve from more of a behavioral perspective. What CL implementations do for the "conveniences "I presume you're talking about is establish restarts and keep this information in the stack. Say you have this generic form (with-foo-convenience () (with-bar-convenience () (the-great-unknown))) So if a CALL-WITH-FOO-CONVENIENCE is dynamically wrapping some error throwing code, it will typically let-bind *FOO-DATA*, some restart that operates (reading or writing) on that *FOO-DATA* and a handler-bind. Note that restarts aren't only invocable, stack-unwinding things: they're also self-reporting and can hide themselves. This becomes relevant as other handlers -- or the human operating the debugger -- tries to find them to fix the course of the program. Anyway, when an error crosses the handler-bind in its upstack path, *FOO-DATA* may be augmented with the "context" and nothing else happens. When ultimately the human-operated debugger is reached the restarts that are available there can are nicely listed with formatted details as their report functions are invoked and read from the enriched *FOO-DATA*. For example, *FOO-DATA* could keep track of the time it observed the LITTLE-GREEN-MAN condition C pass by. And the REPORT-TO-SETI restart's human readable :REPORT would look something like "Report suspicious sighting at XX:XX:XX UTC" or something. Importantly, a HANDLER-BIND in the inner CALL-WITH-BAR-CONVENIENCE can _also_ invoke restarts previously established by CALL-WITH-FOO-CONVENIENCE, that are only "findable" if those restarts' :TEST functions [3] say they are. These functions also have access to C and lexical access to *FOO-DATA*. In summary, I think the "context" you are thinking about can just be good old dynamic context, i.e. let-bindings of special variables, with the new HANDLER-BIND-powered twist that these variables can remain private to their users _and_ be augmented after they are initially established. Right? Wrong? It would at least seem to alleviate your own doubts about the context "going unused most of the time". It keeps the "orthogonal" property and no general-purpose duck-typed "context" needed in the base object or in a hash table or somesuch. > > Ugh indeed. 40 years of leaky abstractions, =C2=AF\_(=E3=83=84)_/=C2= =AF > > > > So yes, "error" err would have that poor man's cons. Maybe > > condition-case would only catch those? A new shiny > > handler-case on the other hand, would catch proper richie > > rich errors (and have the better syntax). > > That entails a heavy amount of churn to change old code to use that new > form (while we'd want to support both for backward compatibility, we'd Not sure if you understand that what I proposed _was_ in principle 100% backward compatible. So on day 0 that 'error' (or in fact 'signal) starts throwing objects and condition-case reconstructs the cons nothing needs to change immediately. > also want to slowly get rid of the old form to keep the overall > complexity in check). That's never stopped us from introducing better abstractions. In fact there's talk right of introducing a cond* to replace 10 year old pcase, with very heavy question marks whether it is really better. Where I think these question marks simply are not there for handler-bind and handler-case (restarts, CLOS and very many CL things). And -- I'm not kidding -- i think 90-95% of this particular trivial code churn (turning condition-case to handler-case) is easily handled by AI things these days. See [4] for a brilliant presentation of something I plan to use soon. > The upside doesn't seem worth the cost for now. It'll be harder 40 years from now. Jo=C3=A3o [1]: https://cl-community-spec.github.io/pages/Standard-Method-Combination.= html [2]: https://cl-community-spec.github.io/pages/Declaring-the-Validity-of-In= itialization-Arguments.html#Declaring-the-Validity-of-Initialization-Argume= nts [3]: https://cl-community-spec.github.io/pages/restart_002dcase.html [4]: https://www.youtube.com/watch?v=3DbsRnh_brggM