From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Maxim Cournoyer Newsgroups: gmane.lisp.guile.bugs Subject: bug#71684: [PATCH] doc: Document the peek and pk procedures. Date: Mon, 01 Jul 2024 23:54:56 -0400 Message-ID: <87jzi45tyn.fsf@gmail.com> References: <20240620185415.9088-1-juli@incana.org> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="35258"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: 71684@debbugs.gnu.org To: Juliana Sims Original-X-From: bug-guile-bounces+guile-bugs=m.gmane-mx.org@gnu.org Tue Jul 02 05:57:34 2024 Return-path: Envelope-to: guile-bugs@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 1sOUe5-0008wS-LA for guile-bugs@m.gmane-mx.org; Tue, 02 Jul 2024 05:57:33 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sOUdc-0000cO-4x; Mon, 01 Jul 2024 23:57:04 -0400 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 1sOUdb-0000cF-1b for bug-guile@gnu.org; Mon, 01 Jul 2024 23:57:03 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sOUdZ-0002gN-6f for bug-guile@gnu.org; Mon, 01 Jul 2024 23:57:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1sOUdZ-000236-Pv for bug-guile@gnu.org; Mon, 01 Jul 2024 23:57:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Maxim Cournoyer Original-Sender: "Debbugs-submit" Resent-CC: bug-guile@gnu.org Resent-Date: Tue, 02 Jul 2024 03:57:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 71684 X-GNU-PR-Package: guile X-GNU-PR-Keywords: patch Original-Received: via spool by 71684-submit@debbugs.gnu.org id=B71684.17198925727817 (code B ref 71684); Tue, 02 Jul 2024 03:57:01 +0000 Original-Received: (at 71684) by debbugs.gnu.org; 2 Jul 2024 03:56:12 +0000 Original-Received: from localhost ([127.0.0.1]:35377 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1sOUcl-000220-CO for submit@debbugs.gnu.org; Mon, 01 Jul 2024 23:56:12 -0400 Original-Received: from mail-qv1-f42.google.com ([209.85.219.42]:42412) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1sOUcg-00021R-0j for 71684@debbugs.gnu.org; Mon, 01 Jul 2024 23:56:09 -0400 Original-Received: by mail-qv1-f42.google.com with SMTP id 6a1803df08f44-6b4ffc2a7abso27789256d6.1 for <71684@debbugs.gnu.org>; Mon, 01 Jul 2024 20:56:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1719892498; x=1720497298; darn=debbugs.gnu.org; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to; bh=9j/Pml5AwNNPAUsrr0H5DRoXeqWvRy8X7ihGwIFFXVE=; b=eyYnVerbMo36bj2H5HOrffTAGmuZ5X6RCxNuC07uDe+08AtIuXDAyTnzk85B49JB5S O6i3SbmGXyvSCNfibuNSobTbsJ2E2BCyVGZwUvnpOUfOIEXBprS6ZKcqEpbiB+nRE1Q6 VnDxR5Vf71Xly9WK6FvbdNDUlM+XGOvFblrgfTvflb9K2jtu2OGKE7+mKZmGRRVxGopM u41Z0z3APjOm7eUG1Q75ZKtk4tQsXxsGokd6zkAN++YVukp2OrusTbLlSNo45U9j1680 YDTcekJpMPbMH/x6pQIIo5vv9aD1me/+4m9yzN6or76Dn2IO9OhPsXYL/YktnMzk6hh2 OwFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719892498; x=1720497298; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=9j/Pml5AwNNPAUsrr0H5DRoXeqWvRy8X7ihGwIFFXVE=; b=w2qNyoHK45j7phI2rxVh6+u5jwCqQ3zSR2rEVa9uykJx7fM9HA+adDRS3AVPnzLesZ 9uKFHTrVg14gzTu7DxN4Y2M+7qD6jGpeMuOkfIPup/BsYsJpd4Sy9Ns/50XlShDRCt7s 9hc1AqjakBHUyYQaEqBHnsIpuKg6tPmp3EjbEQ6gkl2+uRZMAlRIlxq8oOxdk/oSRi6f 6TikK5dopmGRLDdOZPJzKc3fTrvBiPN2IUebJczfx37GxG7IOXKeWZVoMZhwke9apk5P bqUGV78JtTXzhsI2SJkQ6kJHtI/h6dwY5T2VWxGzB9txIJhy4kYn4lj0Tv/4XRezaxVC OdUA== X-Gm-Message-State: AOJu0Yy7rydVPjnjmO5Bhe1+fK7MFM5lCY34Guo5h+vMFjafgXe1AnY1 qTIbnGATMq3voAmnZi20K208HEXcPVKZQ/NlIaBU/smrgyFRNtpF46kcmA== X-Google-Smtp-Source: AGHT+IEJgZnxPB/WpoUenZUCcrpBSayzgMbnFHjssat2LRI/heu0E9vTwEk8SYQrJlWElLpqbk9xOA== X-Received: by 2002:a05:6214:27ce:b0:6b5:335e:8ae4 with SMTP id 6a1803df08f44-6b5b6e75deamr131264576d6.1.1719892498295; Mon, 01 Jul 2024 20:54:58 -0700 (PDT) Original-Received: from hurd (dsl-159-108.b2b2c.ca. [66.158.159.108]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-6b59e5f262asm39567726d6.89.2024.07.01.20.54.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 01 Jul 2024 20:54:57 -0700 (PDT) In-Reply-To: <20240620185415.9088-1-juli@incana.org> (Juliana Sims's message of "Thu, 20 Jun 2024 14:54:15 -0400") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-guile@gnu.org List-Id: "Bug reports for GUILE, GNU's Ubiquitous Extension Language" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-guile-bounces+guile-bugs=m.gmane-mx.org@gnu.org Original-Sender: bug-guile-bounces+guile-bugs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.lisp.guile.bugs:10879 Archived-At: Hi Juliana! Juliana Sims writes: > * doc/ref/api-debug.texi: Document the peek and pk procedures. This looks very useful! Thanks for authoring it. > --- > doc/ref/api-debug.texi | 187 +++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 179 insertions(+), 8 deletions(-) > > diff --git a/doc/ref/api-debug.texi b/doc/ref/api-debug.texi > index faa0c40bd..486473cdb 100644 > --- a/doc/ref/api-debug.texi > +++ b/doc/ref/api-debug.texi > @@ -1,27 +1,198 @@ > @c -*-texinfo-*- > @c This is part of the GNU Guile Reference Manual. > -@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2010, 2011, 2012, 2013, 2014, 2018, 2021 > +@c Copyright (C) 1996-1997, 2000-2004, 2007, 2010-2014, 2018, 2021, 2024 > @c Free Software Foundation, Inc. > @c See the file guile.texi for copying conditions. > > @node Debugging > @section Debugging Infrastructure > > -@cindex Debugging > -In order to understand Guile's debugging facilities, you first need to > -understand a little about how Guile represents the Scheme control stack. > -With that in place we explain the low level trap calls that the virtual > -machine can be configured to make, and the trap and breakpoint > -infrastructure that builds on top of those calls. > +@cindex debugging > +Guile provides facilities for simple print-based debugging as well as > +more advanced debugging features. In order to understand Guile's > +advanced debugging facilities, one first must understand a little about > +how Guile represents the Scheme control stack. With that in place, we > +can explain the low level trap calls that the virtual machine can be > +configured to make, and the trap and breakpoint infrastructure that > +builds on top of those calls. The typographical convention for Texinfo/Guile documentation is to use two spaces to separate sentences. > > @menu > +* Simple Debugging:: Print-based debugging. > * Evaluation Model:: Evaluation and the Scheme stack. > * Source Properties:: From expressions to source locations. > -* Programmatic Error Handling:: Debugging when an error occurs. > +* Programmatic Error Handling:: Debugging when an error occurs. To be valid, Texinfo menu entry description must be indented at least 2 spaces from the node name (so you should drop the above hunk). I use in Emacs: Menu 'Texinfo -> Update all menus' to ease maintaining these, in case it's useful. > * Traps:: Breakpoints, tracepoints, oh my! > * GDB Support:: C-level debugging with GDB. > @end menu > > + > +@node Simple Debugging > +@subsection Simple Debugging > + > +Guile offers powerful tools for introspection and debugging at the REPL, > +covered in the rest of this section and elsewhere in this manual > +(@pxref{Interactive Debugging}). Here we deal with a more primitive > +approach, commonly called ``print debugging.'' Let's be honest: for most > +of us, this is our first line of debugging. And Guile doesn't judge us > +for it! Instead, Guile provides a powerful and convenient tool to > +facilitate print debugging: the @code{peek} procedure, more commonly > +known as @code{pk} (pronounced by naming the letters). > + > +@deffn {Scheme Procedure} peek stuff @dots{} > +@deffnx {Scheme Procedure} pk stuff @dots{} > +Print @var{stuff} to the current output port using @code{write}. Return > +the last argument. > +@end deffn > + > +@code{pk} allows us to look at the state of our code as it runs without > +having to step through it or break the normal code flow. Let's take a > +look at how one might use it. Let's say we have a procedure to make a > +smore, perhaps as part of a mod for a cozy space exploration game. I think using an impersonal tone would match better the style of the rest of the manual (for example, replacing the above with "@code{pk} allows looking at the state of a program as it runs without having to [...]) -- that is, removing the 'we' and 'us'. I find it otherwise reads a bit more like a tutorial (it's more engaging with the reader, which isn't bad, but it clashes with the rest of this reference manual). > +@lisp > +(define (make-smore marshmallow graham-crackers chocolate fire) > + "Toast @var{mashmallow} over @var{fire} then sandwich it and > +@var{chocolate} between @var{graham-crackers}." > + (let ((toasted-marshmallow > + (toast marshmallow fire))) > + (unless (or (burned? toasted-marshmallow) > + (undercooked? toasted-marshmallow)) > + (cons (car graham-crackers) > + (cons toasted-marshmallow > + (cons chocolate > + (cons (cdr graham-crackers) '()))))))) > +@end lisp > + > +We've run this procedure a few times, and it isn't doing what we expect. > +Instead of getting a tasty smore, we get nothing. Let's use @code{pk} to > +find out what's going on. > + > +@lisp > +(pk (make-smore (grab-one marshmallow-bag) > + (cons graham-cracker graham-cracker) > + campfire)) > + > +;;; (#) > +@end lisp > + > +@code{#} is a value in Guile which indicates that no Scheme > +standard specifies a return value for whatever is returning it. In this > +case, it probably means that our @code{unless} check is not proving > +true, so the procedure returns nothing. Let's add a @code{pk} around the > +call to @code{toast} and see what happens. > + > +@lisp > +(define (make-smore marshmallow graham-crackers chocolate fire) > + "Toast @var{mashmallow} over @var{fire} then sandwich it and > +@var{chocolate} between @var{graham-crackers}." > + (let ((toasted-marshmallow > + ;; Let's see what state the toasted-marshmallow is in > + (pk 'toasted-marshmallow (toast marshmallow fire)))) > + (unless (or (burned? toasted-marshmallow) > + (undercooked? toasted-marshmallow)) > + (cons (car graham-crackers) > + (cons toasted-marshmallow > + (cons chocolate > + (cons (cdr graham-crackers) '()))))))) > + > +(make-smore (grab-one marshmallow-bag) > + (cons graham-cracker graham-cracker) > + campfire) > + > +;;; (toasted-marshmallow #< state: raw>) > +@end lisp > + > +Our marshmallow isn't getting cooked at all! Let's see if we can find > +out why. We'll check on the state of @var{fire} since we know that > +@code{toast} just operates on the state of the fire and of the > +marshmallow. @code{toasted-marshmallow} matches the state we expect for > +a fresh marshmallow, so the problem is probably with the fire. > + > +@lisp > +(define (make-smore marshmallow graham-crackers chocolate fire) > + "Toast @var{mashmallow} over @var{fire} then sandwich it and > +@var{chocolate} between @var{graham-crackers}." > + (let ((toasted-marshmallow > + ;; Now we'll check on the fire, too > + (pk 'toasted-marshmallow (toast marshmallow (pk 'fire fire))))) > + (unless (or (burned? toasted-marshmallow) > + (undercooked? toasted-marshmallow)) > + (cons (car graham-crackers) > + (cons toasted-marshmallow > + (cons chocolate > + (cons (cdr graham-crackers) '()))))))) > + > +(make-smore (grab-one marshmallow-bag) > + (cons graham-cracker graham-cracker) > + campfire) > + > +;;; (fire #< state: unlit>) > + > +;;; (toasted-marshmallow #< state: raw>) > +@end lisp > + > +Oh, well that makes sense! A fire can't cook a marshmallow if it isn't > +lit! > + > +Notice that the result of evaluating the @code{pk} around @code{fire} is > +printed before the one around @code{toast}. This is just the result of > +the normal process of evaluating s-expressions from the inside out. We > +highlight it because it can be confusing at first, especially with more > +@code{pk}s in more complex code. > + > +Let's add a guard to light the fire and run our procedure again. > + > +@lisp > +(define (make-smore marshmallow graham-crackers chocolate fire) > + "Toast @var{mashmallow} over @var{fire} then sandwich it and > +@var{chocolate} between @var{graham-crackers}." > + (let ((toasted-marshmallow > + (toast marshmallow fire))) > + (unless (lit? fire) > + (light fire)) > + (unless (or (burned? toasted-marshmallow) > + (undercooked? toasted-marshmallow)) > + (cons (car graham-crackers) > + (cons toasted-marshmallow > + (cons chocolate > + (cons (cdr graham-crackers) '()))))))) > + > +(make-smore (grab-one marshmallow-bag) > + (cons graham-cracker graham-cracker) > + campfire) > +@result{} (#<> #< state: cooked> #<> #<>) > +@end lisp > + > +Yay! Now it works, and we have a tasty smore! The examples were fun, but it's very verbose to explain what it does, and the examples can't be evaluated at the REPL, which departs from the rest of the manual. I think a simple example that can be evaluated at the REPL may more succinctly express the effect of 'pk'. > +As we demonstrated, you can pass in any number of arguments and the > +result of evaluating the last argument is the value returned from > +@code{pk}. This is handy to, as we showed, wrap code in-line without > +needing to add extra steps along the way while still providing > +informative labels about what, exactly, is getting printed. We could as > +easily have put @code{pk}s completely on their own, rather than wrapping > +other code. This is commonly used to, for example, test if a given > +procedure or part of a procedure is entered. Earlier, we could have put > +a @code{pk} in the body of the @code{unless} clause to let us know if we > +entered it, such as: > + > +@lisp > +(define (make-smore ...) > + ... > + (unless ... > + (pk 'inside-unless) > + ...)) > +@end lisp > + > +As a final note, labels don't have to be symbols. @code{pk} will happily > +print any object we pass it. We could have used strings or anything else > +we wanted alongside the code we were interested in. > + > +Hopefully this silly little example has shown the utility of @code{pk}. > +Now that it's in your toolbox, go forth, newly empowered, and happy > +hacking! The last sentence reads like the end of a blog post rather than a section of the manual, at least to me. Perhaps I have too many gray hairs :-) If you agree to my feedback, I think a v2 with a switch to impersonal verbs, as well as using the two spaces convention would be an easy improvement. I'd personally prefer a simpler, perhaps boring example that can be evaluated directly at the REPL to the more verbose (but funny) smore adventure that I can't readily experiment with, but I'll leave others to comment. -- Thanks, Maxim