GNU bug report logs - #71684
[PATCH] doc: Document the peek and pk procedures.

Previous Next

Package: guile;

Reported by: Juliana Sims <juli <at> incana.org>

Date: Thu, 20 Jun 2024 18:56:01 UTC

Severity: normal

Tags: patch

Merged with 36002

Done: Ludovic Courtès <ludo <at> gnu.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 71684 in the body.
You can then email your comments to 71684 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Thu, 20 Jun 2024 18:56:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Juliana Sims <juli <at> incana.org>:
New bug report received and forwarded. Copy sent to bug-guile <at> gnu.org. (Thu, 20 Jun 2024 18:56:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Juliana Sims <juli <at> incana.org>
To: bug-guile <at> gnu.org
Cc: Juliana Sims <juli <at> incana.org>
Subject: [PATCH] doc: Document the peek and pk procedures.
Date: Thu, 20 Jun 2024 14:54:15 -0400
* doc/ref/api-debug.texi: Document the peek and pk procedures.
---
 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.
 
 @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.
 * 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.
+
+@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))
+
+;;; (#<unspecified>)
+@end lisp
+
+@code{#<unspecified>} 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 #<<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 #<<fire> state: unlit>)
+
+;;; (toasted-marshmallow #<<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{} (#<<graham-cracker>> #<<marshmallow> state: cooked> #<<chocolate>> #<<graham-cracker>>)
+@end lisp
+
+Yay! Now it works, and we have a tasty smore!
+
+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!
+
+
 @node Evaluation Model
 @subsection Evaluation and the Scheme Stack
 
-- 
2.45.1





Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Tue, 02 Jul 2024 03:57:01 GMT) Full text and rfc822 format available.

Message #8 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: Maxim Cournoyer <maxim.cournoyer <at> gmail.com>
To: Juliana Sims <juli <at> incana.org>
Cc: 71684 <at> debbugs.gnu.org
Subject: Re: bug#71684: [PATCH] doc: Document the peek and pk procedures.
Date: Mon, 01 Jul 2024 23:54:56 -0400
Hi Juliana!

Juliana Sims <juli <at> incana.org> 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))
> +
> +;;; (#<unspecified>)
> +@end lisp
> +
> +@code{#<unspecified>} 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 #<<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 #<<fire> state: unlit>)
> +
> +;;; (toasted-marshmallow #<<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{} (#<<graham-cracker>> #<<marshmallow> state: cooked> #<<chocolate>> #<<graham-cracker>>)
> +@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




Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Tue, 02 Jul 2024 16:46:02 GMT) Full text and rfc822 format available.

Message #11 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: Juliana Sims <juli <at> incana.org>
To: maxim.cournoyer <at> gmail.com
Cc: 71684 <at> debbugs.gnu.org, Juliana Sims <juli <at> incana.org>
Subject: [PATCH v2] doc: Document the peek and pk procedures.
Date: Tue,  2 Jul 2024 12:28:17 -0400
* doc/ref/api-debug.texi: Document the peek and pk procedures.
---

Hi Maxim,

Thanks for the quick review! I thought I'd made sure to double-space after
periods, but I guess my Emacs fill settings overwrote that when I made sure
everything flowed properly. The contemporary consensus on double spaces in
English is to not use them, and I write a lot so I have my text-mode settings
geared to that purpose. I used manual filling this time so hopefully that issue
has been resolved.

I didn't use Emacs to regenerate all the menus in this file because it produced
diffs in unrelated sections. Otherwise, I've taken all of your feedback into
account. If someone chimes in to say they really liked the smores example, we
can always build out from the first version of the patch. There was a lot of
code involved in making that actually work (three record types, two predicates,
and a utility function) so I don't think that's the right solution.

Best,
Juli

 doc/ref/api-debug.texi | 120 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 109 insertions(+), 11 deletions(-)

diff --git a/doc/ref/api-debug.texi b/doc/ref/api-debug.texi
index faa0c40bd..76d636d13 100644
--- a/doc/ref/api-debug.texi
+++ b/doc/ref/api-debug.texi
@@ -1,27 +1,125 @@
 @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.
 
 @menu
-* Evaluation Model::            Evaluation and the Scheme stack.
-* Source Properties::           From expressions to source locations.
+* 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.
-* Traps::                       Breakpoints, tracepoints, oh my!
-* GDB Support::                 C-level debugging with GDB.
+* 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,'' which is a quick way to
+diagnose simple errors by printing values during a program's execution.
+Guile provides the @code{peek} procedure, more commonly known as
+@code{pk} (pronounced by naming the letters), as a convenient and
+powerful tool for this kind of debugging.
+
+@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} improves on using @code{write} directly because it enables
+inspection of the state of code as it runs without breaking the normal
+code flow.  It is also more convenient than a full debugger because it
+does not require the program to be stopped for inspection.  Here is a
+basic example:
+
+@lisp
+(define fire 'burns)
+
+(pk fire)
+@result{}
+
+;;; (burns)
+burns
+@end
+
+Here is an example of inspecting a value in the midst of code flow:
+
+@lisp
+(map (lambda (v)
+       (if (number? v)
+           (number->string v)
+           (pk v)))
+     '(1 "2" "3" 4))
+@result{}
+
+;;; ("2")
+
+;;; ("3")
+("1" "2" "3" "4")
+@end
+
+A common technique when using @code{pk} is to label values with symbols
+to keep track of where they're coming from.  There's no reason these
+labels need to be symbols; symbols are just convenient.  Here's a
+slightly more complex example demonstrating that pattern:
+
+@lisp
+(define (pk-identity x)
+  (pk 'arg-to-identity x))
+
+(pk-identity 42)
+@result{}
+
+;;; (arg-to-identity 42)
+42
+@end
+
+@code{pk} has one small quirk of note.  Currently, it only returns the
+first value returned from any multi-value returns.  So for example:
+
+@lisp
+(pk 'vals (values 1 2 3))
+@result{}
+
+;;; (vals 1)
+1
+@end
+
+The way to get around this limitation is to bind such multi-value
+returns then inspect the results.  Still, @code{pk} can only return a
+single value:
+
+@lisp
+(use-modules (srfi srfi-11))
+
+(let-values (((x y z)
+              (values 1 2 3)))
+  (pk 'vals x y z))
+@result{}
+
+;;; (vals 1 2 3)
+3
+@end
+
+
 @node Evaluation Model
 @subsection Evaluation and the Scheme Stack
 
-- 
2.45.1





Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Tue, 09 Jul 2024 02:59:02 GMT) Full text and rfc822 format available.

Message #14 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: Maxim Cournoyer <maxim.cournoyer <at> gmail.com>
To: Juliana Sims <juli <at> incana.org>
Cc: 71684 <at> debbugs.gnu.org
Subject: Re: [PATCH v2] doc: Document the peek and pk procedures.
Date: Mon, 08 Jul 2024 22:56:55 -0400
Hi Juliana,

Juliana Sims <juli <at> incana.org> writes:

> * doc/ref/api-debug.texi: Document the peek and pk procedures.
> ---
>
> Hi Maxim,
>
> Thanks for the quick review! I thought I'd made sure to double-space after
> periods, but I guess my Emacs fill settings overwrote that when I made sure
> everything flowed properly. The contemporary consensus on double spaces in
> English is to not use them, and I write a lot so I have my text-mode settings
> geared to that purpose. I used manual filling this time so hopefully that issue
> has been resolved.

Thanks!  It's a peculiar/historical typography choice that seems rooted
in being able to navigate unambiguously between sentences in Emacs (and
elsewhere where implemented).

> I didn't use Emacs to regenerate all the menus in this file because it produced
> diffs in unrelated sections.

Fair enough!

> Otherwise, I've taken all of your feedback into
> account. If someone chimes in to say they really liked the smores example, we
> can always build out from the first version of the patch. There was a lot of
> code involved in making that actually work (three record types, two predicates,
> and a utility function) so I don't think that's the right solution.

Sounds good.

[...]


> diff --git a/doc/ref/api-debug.texi b/doc/ref/api-debug.texi
> index faa0c40bd..76d636d13 100644
> --- a/doc/ref/api-debug.texi
> +++ b/doc/ref/api-debug.texi
> @@ -1,27 +1,125 @@
>  @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.
>  
>  @menu
> -* Evaluation Model::            Evaluation and the Scheme stack.
> -* Source Properties::           From expressions to source locations.
> +* 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.
> -* Traps::                       Breakpoints, tracepoints, oh my!
> -* GDB Support::                 C-level debugging with GDB.
> +* 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,'' which is a quick way to
> +diagnose simple errors by printing values during a program's execution.
> +Guile provides the @code{peek} procedure, more commonly known as
> +@code{pk} (pronounced by naming the letters), as a convenient and
> +powerful tool for this kind of debugging.
> +
> +@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} improves on using @code{write} directly because it enables
> +inspection of the state of code as it runs without breaking the normal
> +code flow.  It is also more convenient than a full debugger because it
> +does not require the program to be stopped for inspection.  Here is a
> +basic example:

I hadn't commented on that last sentence before, but if I knew how to
have the Guile debugger reliably break where I want it to (I don't, or
somehow haven't managed to have it work well), I don't think using 'pk',
which requires editing files before and after debugging, could be
described as more convenient :-).

> +@lisp
> +(define fire 'burns)
> +
> +(pk fire)
> +@result{}
> +
> +;;; (burns)
> +burns
> +@end
> +
> +Here is an example of inspecting a value in the midst of code flow:
> +
> +@lisp
> +(map (lambda (v)
> +       (if (number? v)
> +           (number->string v)
> +           (pk v)))
> +     '(1 "2" "3" 4))
> +@result{}
> +
> +;;; ("2")
> +
> +;;; ("3")
> +("1" "2" "3" "4")
> +@end
> +
> +A common technique when using @code{pk} is to label values with symbols
> +to keep track of where they're coming from.  There's no reason these
> +labels need to be symbols; symbols are just convenient.  Here's a
> +slightly more complex example demonstrating that pattern:
> +
> +@lisp
> +(define (pk-identity x)
> +  (pk 'arg-to-identity x))
> +
> +(pk-identity 42)
> +@result{}
> +
> +;;; (arg-to-identity 42)
> +42
> +@end
> +
> +@code{pk} has one small quirk of note.  Currently, it only returns the
> +first value returned from any multi-value returns.  So for example:
> +
> +@lisp
> +(pk 'vals (values 1 2 3))
> +@result{}
> +
> +;;; (vals 1)
> +1
> +@end
> +
> +The way to get around this limitation is to bind such multi-value
> +returns then inspect the results.  Still, @code{pk} can only return a
> +single value:
> +
> +@lisp
> +(use-modules (srfi srfi-11))
> +
> +(let-values (((x y z)
> +              (values 1 2 3)))
> +  (pk 'vals x y z))
> +@result{}
> +
> +;;; (vals 1 2 3)
> +3
> +@end
> +
> +
>  @node Evaluation Model
>  @subsection Evaluation and the Scheme Stack

I like the new, 'evaluatable' examples :-).  It's also a much shorter
read.  Thanks for sending a v2!

I would commit this if I was a committer, but I am not, so here's at
least my reviewed trailer:

Reviewed-by: Maxim Cournoyer <maxim.cournoyer <at> gmail>

-- 
Thanks,
Maxim




Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Wed, 10 Jul 2024 18:43:02 GMT) Full text and rfc822 format available.

Message #17 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: Simon Tournier <zimon.toutoune <at> gmail.com>
To: Juliana Sims <juli <at> incana.org>
Cc: 71684 <at> debbugs.gnu.org, maxim.cournoyer <at> gmail.com
Subject: Re: bug#71684: [PATCH v2] doc: Document the peek and pk procedures.
Date: Wed, 10 Jul 2024 20:21:10 +0200
Hi,

On Tue, 02 Jul 2024 at 12:28, Juliana Sims <juli <at> incana.org> wrote:
> * doc/ref/api-debug.texi: Document the peek and pk procedures.

Cool!  Thanks.


> Thanks for the quick review! I thought I'd made sure to double-space after
> periods, but I guess my Emacs fill settings overwrote that when I made sure
> everything flowed properly. The contemporary consensus on double spaces in
> English is to not use them, and I write a lot so I have my text-mode settings
> geared to that purpose. I used manual filling this time so hopefully that issue
> has been resolved.

Yeah, that’s because double-space after period fixes ambiguous cases as
this example: “The author J. R. R. Tolkien wrote The Hobbit. George
R. R. Martin wrote many fantasy books.”  The brain is able to determine
it’s only two sentences, but it becomes more difficult otherwise; it
could count 7 sentences.

https://en.wikipedia.org/wiki/Sentence_spacing#Computer_era

Anyway. :-)


> +@lisp
> +(map (lambda (v)
> +       (if (number? v)
> +           (number->string v)
> +           (pk v)))
> +     '(1 "2" "3" 4))
> +@result{}
> +
> +;;; ("2")
> +
> +;;; ("3")
> +("1" "2" "3" "4")
> +@end

For what it is worth, I would suggest something as:

--8<---------------cut here---------------start------------->8---
(map (lambda (v)
       (if (number? v)
           (number->string v)
           (begin
             (pk 'else v)
             (pk (string-append "-" v "0")))))
     '(1 "2" "3" 4))
--8<---------------cut here---------------end--------------->8---

For two reasons:

 1. ’begin’ helps to mark a sequence of expressions; IMHO, that’s a good
     habit when playing with ’pk’ for debugging purpose.

 2. it exposes that ’stuff’ above can be anything.


Well, my suggestion could be two other examples in addition to the
current one instead of the complexification.

My 2 cents. :-)

Cheers,
simon




Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Wed, 10 Jul 2024 20:22:02 GMT) Full text and rfc822 format available.

Message #20 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: Maxim Cournoyer <maxim.cournoyer <at> gmail.com>
To: Simon Tournier <zimon.toutoune <at> gmail.com>
Cc: 71684 <at> debbugs.gnu.org, Juliana Sims <juli <at> incana.org>
Subject: Re: bug#71684: [PATCH v2] doc: Document the peek and pk procedures.
Date: Wed, 10 Jul 2024 15:48:53 -0400
Hi Simon,

Simon Tournier <zimon.toutoune <at> gmail.com> writes:

[...]

>> +@lisp
>> +(map (lambda (v)
>> +       (if (number? v)
>> +           (number->string v)
>> +           (pk v)))
>> +     '(1 "2" "3" 4))
>> +@result{}
>> +
>> +;;; ("2")
>> +
>> +;;; ("3")
>> +("1" "2" "3" "4")
>> +@end
>
> For what it is worth, I would suggest something as:
>
> (map (lambda (v)
>        (if (number? v)
>            (number->string v)
>            (begin
>              (pk 'else v)
>              (pk (string-append "-" v "0")))))
>      '(1 "2" "3" 4))
>
> For two reasons:
>
>  1. ’begin’ helps to mark a sequence of expressions; IMHO, that’s a good
>      habit when playing with ’pk’ for debugging purpose.
>
>  2. it exposes that ’stuff’ above can be anything.
>
>
> Well, my suggestion could be two other examples in addition to the
> current one instead of the complexification.

I think I'd prefer more simple examples than a single more complicated
one, if we go that route.  I think the text explained 'peek' clearly
already, though, so I personally would opt to leave it as is, especially
since adding a 'begin' block to showcase multiple 'pk' calls goes
against the merit of peek of being least intrusive (it prints then
returns the value, so the code structure needs not be changed).

-- 
Thanks,
Maxim




Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Thu, 11 Jul 2024 10:00:02 GMT) Full text and rfc822 format available.

Message #23 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: Simon Tournier <zimon.toutoune <at> gmail.com>
To: Maxim Cournoyer <maxim.cournoyer <at> gmail.com>
Cc: 71684 <at> debbugs.gnu.org, Juliana Sims <juli <at> incana.org>
Subject: Re: bug#71684: [PATCH v2] doc: Document the peek and pk procedures.
Date: Thu, 11 Jul 2024 10:59:08 +0200
Hi Maxim,

On Wed, 10 Jul 2024 at 15:48, Maxim Cournoyer <maxim.cournoyer <at> gmail.com> wrote:

> I think I'd prefer more simple examples than a single more complicated
> one, if we go that route.  I think the text explained 'peek' clearly
> already, though, so I personally would opt to leave it as is, especially
> since adding a 'begin' block to showcase multiple 'pk' calls goes
> against the merit of peek of being least intrusive (it prints then
> returns the value, so the code structure needs not be changed).

Well, I do not have a strong opinion on the topic. :-)

I would suggest to apply the ’pk’ on the other branch, something as:

--8<---------------cut here---------------start------------->8---
(map (lambda (v)
       (if (number? v)
           (pk 'number v (number->string v))
           v))
     '(1 "2" "3" 4))
--8<---------------cut here---------------end--------------->8---


Cheers,
simon




Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Tue, 16 Jul 2024 02:48:02 GMT) Full text and rfc822 format available.

Message #26 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: Juliana Sims <juli <at> incana.org>
To: Simon Tournier <zimon.toutoune <at> gmail.com>
Cc: 71684 <at> debbugs.gnu.org, Maxim Cournoyer <maxim.cournoyer <at> gmail.com>
Subject: Re: bug#71684: [PATCH v2] doc: Document the peek and pk procedures.
Date: Mon, 15 Jul 2024 22:46:24 -0400
Hi y'all,
Thanks for the (continued) reviews!

> I hadn't commented on that last sentence before, but if I knew how to
> have the Guile debugger reliably break where I want it to (I don't, or
> somehow haven't managed to have it work well), I don't think using 
> 'pk',
> which requires editing files before and after debugging, could be
> described as more convenient :-).

A fair point!  I can change that wording in a next version of the patch.

> I would suggest to apply the ’pk’ on the other branch, something 
> as:
> 
> --8<---------------cut here---------------start------------->8---
> (map (lambda (v)
>        (if (number? v)
>            (pk 'number v (number->string v))
>            v))
>      '(1 "2" "3" 4))
> --8<---------------cut here---------------end--------------->8---

I'm not sure I understand how this improves the demonstration of 'pk'.  
What does this form of the example demonstrate that the version in the 
patch does not?  It's a minor change so I'm happy to make it; I just 
want to ensure that we have the best possible version of the solution 
to the problem you see.

Best,
Juli






Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Tue, 23 Jul 2024 15:26:01 GMT) Full text and rfc822 format available.

Message #29 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: jgart <jgart <at> dismail.de>
To: 71684 <at> debbugs.gnu.org
Cc: Simon Tournier <zimon.toutoune <at> gmail.com>,
 Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Juliana Sims <juli <at> incana.org>
Subject: Re: [PATCH] doc: Document the peek and pk procedures.
Date: Tue, 23 Jul 2024 10:24:44 -0500
hi,

this looks good to me. let's merge it y'all!
-- 
all best,
jgart




Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Fri, 13 Sep 2024 15:44:01 GMT) Full text and rfc822 format available.

Message #32 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: Maxim Cournoyer <maxim.cournoyer <at> gmail.com>
To: Juliana Sims <juli <at> incana.org>
Cc: 71684 <at> debbugs.gnu.org, Simon Tournier <zimon.toutoune <at> gmail.com>
Subject: Re: bug#71684: [PATCH v2] doc: Document the peek and pk procedures.
Date: Sat, 14 Sep 2024 00:42:39 +0900
Hi Juliana,

Juliana Sims <juli <at> incana.org> writes:

> Hi y'all,
> Thanks for the (continued) reviews!
>
>> I hadn't commented on that last sentence before, but if I knew how to
>> have the Guile debugger reliably break where I want it to (I don't, or
>> somehow haven't managed to have it work well), I don't think using
>> 'pk',
>> which requires editing files before and after debugging, could be
>> described as more convenient :-).
>
> A fair point!  I can change that wording in a next version of the patch.
>
>> I would suggest to apply the ’pk’ on the other branch, something as:
>> --8<---------------cut here---------------start------------->8---
>> (map (lambda (v)
>>        (if (number? v)
>>            (pk 'number v (number->string v))
>>            v))
>>      '(1 "2" "3" 4))
>> --8<---------------cut here---------------end--------------->8---
>
> I'm not sure I understand how this improves the demonstration of 'pk'.
> What does this form of the example demonstrate that the version in the
> patch does not?  It's a minor change so I'm happy to make it; I just
> want to ensure that we have the best possible version of the solution
> to the problem you see.

I'm not sure I understand the motivation too. To me the v2 patch looked
fine as-is.

-- 
Thanks,
Maxim




Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Fri, 13 Sep 2024 15:50:01 GMT) Full text and rfc822 format available.

Message #35 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: Maxim Cournoyer <maxim.cournoyer <at> gmail.com>
To: Juliana Sims <juli <at> incana.org>
Cc: 71684 <at> debbugs.gnu.org
Subject: Re: bug#71684: [PATCH v2] doc: Document the peek and pk procedures.
Date: Sat, 14 Sep 2024 00:47:43 +0900
Hi Juliana,

I hope you are still around.

[...]

>> +@code{pk} improves on using @code{write} directly because it enables
>> +inspection of the state of code as it runs without breaking the normal
>> +code flow.  It is also more convenient than a full debugger because it
>> +does not require the program to be stopped for inspection.  Here is a
>> +basic example:
>
> I hadn't commented on that last sentence before, but if I knew how to
> have the Guile debugger reliably break where I want it to (I don't, or
> somehow haven't managed to have it work well), I don't think using 'pk',
> which requires editing files before and after debugging, could be
> described as more convenient :-).

I think your new addition above could be modified lightly like:

+@code{pk} improves on using @code{write} directly because it enables
+inspection of the state of code as it runs without breaking the normal
+code flow.  It is also sometimes more practical than a full debugger
+because it does not require the program to be stopped for inspection.
+Here is a basic example:

With the above change, I'd like to see this in the Guile manual :-).
Would you be able to send an easily applicable v3?  Then the last step
would be to tap on the shoulder of a committer in #guile.

-- 
Thanks,
Maxim




Merged 36002 71684. Request was from Maxim Cournoyer <maxim.cournoyer <at> gmail.com> to control <at> debbugs.gnu.org. (Fri, 13 Sep 2024 15:50:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Fri, 13 Sep 2024 16:06:01 GMT) Full text and rfc822 format available.

Message #40 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: Simon Tournier <zimon.toutoune <at> gmail.com>
To: Maxim Cournoyer <maxim.cournoyer <at> gmail.com>
Cc: 71684 <at> debbugs.gnu.org, Juliana Sims <juli <at> incana.org>
Subject: Re: bug#71684: [PATCH v2] doc: Document the peek and pk procedures.
Date: Fri, 13 Sep 2024 18:03:36 +0200
Hi,

On Fri, 13 Sept 2024 at 17:42, Maxim Cournoyer
<maxim.cournoyer <at> gmail.com> wrote:

> >> I would suggest to apply the ’pk’ on the other branch, something as:
> >>
> >> --8<---------------cut here---------------start------------->8---
> >> (map (lambda (v)
> >>        (if (number? v)
> >>            (pk 'number v (number->string v))
> >>            v))
> >>      '(1 "2" "3" 4))
> >> --8<---------------cut here---------------end--------------->8---
> >
> > I'm not sure I understand how this improves the demonstration of 'pk'.
> > What does this form of the example demonstrate that the version in the
> > patch does not?  It's a minor change so I'm happy to make it; I just
> > want to ensure that we have the best possible version of the solution
> > to the problem you see.
>
> I'm not sure I understand the motivation too. To me the v2 patch looked
> fine as-is.

Becasue it shows that you can put more than only one.  Qui peut le
plus, peut le moins. ;-)

And it also shows that you can call stuff.

Well, IMHO, once 'pk' is clear for you, you do not see the difference.
However, the example I suggest appears to me that it provides more
information when learning.

Cheers,
simon




Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Fri, 13 Sep 2024 20:06:02 GMT) Full text and rfc822 format available.

Message #43 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: Juliana Sims <juli <at> incana.org>
To: zimon.toutoune <at> gmail.com
Cc: 71684 <at> debbugs.gnu.org, maxim.cournoyer <at> gmail.com, juli <at> incana.org
Subject: [PATCH v3] doc: Document the peek and pk procedures.
Date: Fri, 13 Sep 2024 16:03:52 -0400
* doc/ref/api-debug.texi: Document the peek and pk procedures.
---

Hey y'all,

Thanks for the feedback!  I've incorporated both suggestions in this new patch.

Best,
Juli

 doc/ref/api-debug.texi | 120 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 109 insertions(+), 11 deletions(-)

diff --git a/doc/ref/api-debug.texi b/doc/ref/api-debug.texi
index faa0c40bd..df109d390 100644
--- a/doc/ref/api-debug.texi
+++ b/doc/ref/api-debug.texi
@@ -1,27 +1,125 @@
 @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.
 
 @menu
-* Evaluation Model::            Evaluation and the Scheme stack.
-* Source Properties::           From expressions to source locations.
+* 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.
-* Traps::                       Breakpoints, tracepoints, oh my!
-* GDB Support::                 C-level debugging with GDB.
+* 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,'' which is a quick way to
+diagnose simple errors by printing values during a program's execution.
+Guile provides the @code{peek} procedure, more commonly known as
+@code{pk} (pronounced by naming the letters), as a convenient and
+powerful tool for this kind of debugging.
+
+@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} improves on using @code{write} directly because it enables
+inspection of the state of code as it runs without breaking the normal
+code flow.  It is also sometimes more practical than a full debugger
+because it does not require the program to be stopped for inspection.
+Here is a basic example:
+
+@lisp
+(define fire 'burns)
+
+(pk fire)
+@result{}
+
+;;; (burns)
+burns
+@end
+
+Here is an example of inspecting a value in the midst of code flow:
+
+@lisp
+(map (lambda (v)
+       (if (number? v)
+           (pk 'number->string (number->string v))
+           v))
+     '(1 "2" "3" 4))
+@result{}
+
+;;; ("1")
+
+;;; ("4")
+("1" "2" "3" "4")
+@end
+
+A common technique when using @code{pk} is to label values with symbols
+to keep track of where they're coming from.  There's no reason these
+labels need to be symbols; symbols are just convenient.  Here's a
+slightly more complex example demonstrating that pattern:
+
+@lisp
+(define (pk-identity x)
+  (pk 'arg-to-identity x))
+
+(pk-identity 42)
+@result{}
+
+;;; (arg-to-identity 42)
+42
+@end
+
+@code{pk} has one small quirk of note.  Currently, it only returns the
+first value returned from any multi-value returns.  So for example:
+
+@lisp
+(pk 'vals (values 1 2 3))
+@result{}
+
+;;; (vals 1)
+1
+@end
+
+The way to get around this limitation is to bind such multi-value
+returns then inspect the results.  Still, @code{pk} can only return a
+single value:
+
+@lisp
+(use-modules (srfi srfi-11))
+
+(let-values (((x y z)
+              (values 1 2 3)))
+  (pk 'vals x y z))
+@result{}
+
+;;; (vals 1 2 3)
+3
+@end
+
+
 @node Evaluation Model
 @subsection Evaluation and the Scheme Stack
 

base-commit: d0790d766bedf08fb65231eff53f6c8044eb94f1
-- 
2.46.0





Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Mon, 14 Oct 2024 08:19:02 GMT) Full text and rfc822 format available.

Message #46 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: Janneke Nieuwenhuizen <janneke <at> gnu.org>
To: Juliana Sims via "Bug reports for GUILE, GNU's Ubiquitous Extension
 Language" <bug-guile <at> gnu.org>
Cc: 71684 <at> debbugs.gnu.org, Juliana Sims <juli <at> incana.org>,
 maxim.cournoyer <at> gmail.com, zimon.toutoune <at> gmail.com
Subject: Re: bug#71684: [PATCH v3] doc: Document the peek and pk procedures.
Date: Mon, 14 Oct 2024 09:57:43 +0200
Juliana Sims via Bug reports for GUILE, GNU's Ubiquitous Extension Language writes:

> * doc/ref/api-debug.texi: Document the peek and pk procedures.
> ---
>
> Hey y'all,
>
> Thanks for the feedback!  I've incorporated both suggestions in this new patch.
[..]

> +@lisp
> +(define fire 'burns)
> +
> +(pk fire)
> +@result{}
> +
> +;;; (burns)
> +burns
> +@end

These should read
@end lisp

--8<---------------cut here---------------start------------->8---
diff --git a/doc/ref/api-debug.texi b/doc/ref/api-debug.texi
index df109d390..ca5175b35 100644
--- a/doc/ref/api-debug.texi
+++ b/doc/ref/api-debug.texi
@@ -58,7 +58,7 @@ Here is a basic example:
 
 ;;; (burns)
 burns
-@end
+@end lisp
 
 Here is an example of inspecting a value in the midst of code flow:
 
@@ -74,7 +74,7 @@ Here is an example of inspecting a value in the midst of code flow:
 
 ;;; ("4")
 ("1" "2" "3" "4")
-@end
+@end lisp
 
 A common technique when using @code{pk} is to label values with symbols
 to keep track of where they're coming from.  There's no reason these
@@ -90,7 +90,7 @@ slightly more complex example demonstrating that pattern:
 
 ;;; (arg-to-identity 42)
 42
-@end
+@end lisp
 
 @code{pk} has one small quirk of note.  Currently, it only returns the
 first value returned from any multi-value returns.  So for example:
@@ -101,7 +101,7 @@ first value returned from any multi-value returns.  So for example:
 
 ;;; (vals 1)
 1
-@end
+@end lisp
 
 The way to get around this limitation is to bind such multi-value
 returns then inspect the results.  Still, @code{pk} can only return a
@@ -117,7 +117,7 @@ single value:
 
 ;;; (vals 1 2 3)
 3
-@end
+@end lisp
 
 
 @node Evaluation Model
--8<---------------cut here---------------end--------------->8---

Greetings,
Janneke

-- 
Janneke Nieuwenhuizen <janneke <at> gnu.org>  | GNU LilyPond https://LilyPond.org
Freelance IT https://www.JoyOfSource.com | Avatar® https://AvatarAcademy.com




Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Mon, 14 Oct 2024 08:37:01 GMT) Full text and rfc822 format available.

Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Mon, 14 Oct 2024 12:56:02 GMT) Full text and rfc822 format available.

Message #52 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: Juliana Sims <juli <at> incana.org>
To: janneke <at> gnu.org
Cc: 71684 <at> debbugs.gnu.org, Juliana Sims <juli <at> incana.org>,
 maxim.cournoyer <at> gmail.com, zimon.toutoune <at> gmail.com
Subject: [PATCH v4] doc: Document the peek and pk procedures.
Date: Mon, 14 Oct 2024 08:53:47 -0400
* doc/ref/api-debug.texi: Document the peek and pk procedures.
---
 doc/ref/api-debug.texi | 120 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 109 insertions(+), 11 deletions(-)

Hi Janneke,

Thanks for the catch!  That's fixed in this version :)

Best,
Juli

diff --git a/doc/ref/api-debug.texi b/doc/ref/api-debug.texi
index faa0c40bd..ca5175b35 100644
--- a/doc/ref/api-debug.texi
+++ b/doc/ref/api-debug.texi
@@ -1,27 +1,125 @@
 @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.
 
 @menu
-* Evaluation Model::            Evaluation and the Scheme stack.
-* Source Properties::           From expressions to source locations.
+* 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.
-* Traps::                       Breakpoints, tracepoints, oh my!
-* GDB Support::                 C-level debugging with GDB.
+* 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,'' which is a quick way to
+diagnose simple errors by printing values during a program's execution.
+Guile provides the @code{peek} procedure, more commonly known as
+@code{pk} (pronounced by naming the letters), as a convenient and
+powerful tool for this kind of debugging.
+
+@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} improves on using @code{write} directly because it enables
+inspection of the state of code as it runs without breaking the normal
+code flow.  It is also sometimes more practical than a full debugger
+because it does not require the program to be stopped for inspection.
+Here is a basic example:
+
+@lisp
+(define fire 'burns)
+
+(pk fire)
+@result{}
+
+;;; (burns)
+burns
+@end lisp
+
+Here is an example of inspecting a value in the midst of code flow:
+
+@lisp
+(map (lambda (v)
+       (if (number? v)
+           (pk 'number->string (number->string v))
+           v))
+     '(1 "2" "3" 4))
+@result{}
+
+;;; ("1")
+
+;;; ("4")
+("1" "2" "3" "4")
+@end lisp
+
+A common technique when using @code{pk} is to label values with symbols
+to keep track of where they're coming from.  There's no reason these
+labels need to be symbols; symbols are just convenient.  Here's a
+slightly more complex example demonstrating that pattern:
+
+@lisp
+(define (pk-identity x)
+  (pk 'arg-to-identity x))
+
+(pk-identity 42)
+@result{}
+
+;;; (arg-to-identity 42)
+42
+@end lisp
+
+@code{pk} has one small quirk of note.  Currently, it only returns the
+first value returned from any multi-value returns.  So for example:
+
+@lisp
+(pk 'vals (values 1 2 3))
+@result{}
+
+;;; (vals 1)
+1
+@end lisp
+
+The way to get around this limitation is to bind such multi-value
+returns then inspect the results.  Still, @code{pk} can only return a
+single value:
+
+@lisp
+(use-modules (srfi srfi-11))
+
+(let-values (((x y z)
+              (values 1 2 3)))
+  (pk 'vals x y z))
+@result{}
+
+;;; (vals 1 2 3)
+3
+@end lisp
+
+
 @node Evaluation Model
 @subsection Evaluation and the Scheme Stack
 
-- 
2.46.0





Reply sent to Ludovic Courtès <ludo <at> gnu.org>:
You have taken responsibility. (Sat, 26 Oct 2024 17:33:01 GMT) Full text and rfc822 format available.

Notification sent to Juliana Sims <juli <at> incana.org>:
bug acknowledged by developer. (Sat, 26 Oct 2024 17:33:02 GMT) Full text and rfc822 format available.

Message #57 received at 71684-done <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: Juliana Sims <juli <at> incana.org>
Cc: 71684-done <at> debbugs.gnu.org, zimon.toutoune <at> gmail.com,
 maxim.cournoyer <at> gmail.com, janneke <at> gnu.org
Subject: Re: bug#71684: [PATCH v4] doc: Document the peek and pk procedures.
Date: Sat, 26 Oct 2024 19:32:10 +0200
Hi!

Juliana Sims <juli <at> incana.org> skribis:

> * doc/ref/api-debug.texi: Document the peek and pk procedures.

Nice work; documenting it was long overdue!  Finally applied.

Thank you and thanks to everyone who helped along the way!

Ludo’.




Reply sent to Ludovic Courtès <ludo <at> gnu.org>:
You have taken responsibility. (Sat, 26 Oct 2024 17:33:02 GMT) Full text and rfc822 format available.

Notification sent to Robert Vollmert <rob <at> vllmrt.net>:
bug acknowledged by developer. (Sat, 26 Oct 2024 17:33:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-guile <at> gnu.org:
bug#71684; Package guile. (Mon, 28 Oct 2024 10:37:02 GMT) Full text and rfc822 format available.

Message #65 received at 71684 <at> debbugs.gnu.org (full text, mbox):

From: <janneke <at> gnu.org>
To: guile-devel <at> gnu.org
Cc: 71684 <at> debbugs.gnu.org
Subject: Re: [PATCH v2] Add peek-error, pke.
Date: Mon, 28 Oct 2024 11:33:49 +0100
[Message part 1 (text/plain, inline)]
Janneke Nieuwenhuizen writes:

With #71684 merged, this needs an update.  New in this version:
    * document it!

Greetings,
Janneke

[v2-0001-Add-peek-error-pke.patch (text/x-patch, inline)]
From c0a856ac60a672db53d3ab7df8098a323fbb999a Mon Sep 17 00:00:00 2001
From: Janneke Nieuwenhuizen <janneke <at> gnu.org>
Date: Fri, 3 Mar 2023 11:26:34 +0100
Subject: [PATCH v2] Add peek-error, pke.
Content-Transfer-Encoding: 8bit
Content-Type: text/plain; charset=UTF-8

Debuging using `pk' is popular in Guile, but not really usable if the
program is as (pseudo-)filter, i.e., writing its output to stdout.

* module/ice-9/boot-9.scm (peek-error, pke): New procedures.
* doc/ref/api-debug.texi (Simple Debugging): Document them.
---
 doc/ref/api-debug.texi  | 13 ++++++++++---
 module/ice-9/boot-9.scm | 10 ++++++++++
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/doc/ref/api-debug.texi b/doc/ref/api-debug.texi
index ca5175b35c..35092fbdaf 100644
--- a/doc/ref/api-debug.texi
+++ b/doc/ref/api-debug.texi
@@ -34,9 +34,10 @@ 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,'' which is a quick way to
 diagnose simple errors by printing values during a program's execution.
-Guile provides the @code{peek} procedure, more commonly known as
-@code{pk} (pronounced by naming the letters), as a convenient and
-powerful tool for this kind of debugging.
+Guile provides the @code{peek} and @code{peek-error} procedures, more
+commonly known as @code{pk} and @code{pke} respectively (pronounced by
+naming the letters), as a convenient and powerful tool for this kind of
+debugging.
 
 @deffn {Scheme Procedure} peek stuff @dots{}
 @deffnx {Scheme Procedure} pk stuff @dots{}
@@ -44,6 +45,12 @@ Print @var{stuff} to the current output port using @code{write}.  Return
 the last argument.
 @end deffn
 
+@deffn {Scheme Procedure} peek-error stuff @dots{}
+@deffnx {Scheme Procedure} pke stuff @dots{}
+Print @var{stuff} to the current error port using @code{write}.  Return
+the last argument.
+@end deffn
+
 @code{pk} improves on using @code{write} directly because it enables
 inspection of the state of code as it runs without breaking the normal
 code flow.  It is also sometimes more practical than a full debugger
diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index 04f84215c9..4b611f6a9d 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -183,6 +183,16 @@ This is handy for tracing function calls, e.g.:
 
 (define pk peek)
 
+(define (peek-error . stuff)
+  "Like PEEK (PK), writing to (CURRENT-ERROR-PORT)."
+  (newline (current-error-port))
+  (display ";;; " (current-error-port))
+  (write stuff (current-error-port))
+  (newline (current-error-port))
+  (car (last-pair stuff)))
+
+(define pke peek-error)
+
 (define (warn . stuff)
   (newline (current-warning-port))
   (display ";;; WARNING " (current-warning-port))
-- 
Janneke Nieuwenhuizen <janneke <at> gnu.org>  | GNU LilyPond https://LilyPond.org
Freelance IT https://www.JoyOfSource.com | Avatar® https://AvatarAcademy.com

[Message part 3 (text/plain, inline)]
-- 
Janneke Nieuwenhuizen <janneke <at> gnu.org>  | GNU LilyPond https://LilyPond.org
Freelance IT https://www.JoyOfSource.com | Avatar® https://AvatarAcademy.com

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Mon, 25 Nov 2024 12:24:06 GMT) Full text and rfc822 format available.

This bug report was last modified 223 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.