Skip to content

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 (see 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 peek procedure, more commonly known as pk (pronounced by naming the letters), as a convenient and powerful tool for this kind of debugging.

Scheme Procedure: peek stuff …

Scheme Procedure: pk stuff …

Print stuff to the current output port using write. Return the last argument.

pk improves on using 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:

emacs-lisp
(define fire 'burns)

(pk fire)


;;; (burns)
burns

Here is an example of inspecting a value in the midst of code flow:

emacs-lisp
(map (lambda (v)
       (if (number? v)
           (pk 'number->string (number->string v))
           v))
     '(1 "2" "3" 4))


;;; ("1")

;;; ("4")
("1" "2" "3" "4")

A common technique when using 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:

emacs-lisp
(define (pk-identity x)
  (pk 'arg-to-identity x))

(pk-identity 42)


;;; (arg-to-identity 42)
42

pk has one small quirk of note. Currently, it only returns the first value returned from any multi-value returns. So for example:

emacs-lisp
(pk 'vals (values 1 2 3))


;;; (vals 1)
1

The way to get around this limitation is to bind such multi-value returns then inspect the results. Still, pk can only return a single value:

emacs-lisp
(use-modules (srfi srfi-11))

(let-values (((x y z)
              (values 1 2 3)))
  (pk 'vals x y z))


;;; (vals 1 2 3)
3