Print debugging statement
From Wikipedia:
Print debugging (or tracing) is the act of watching (live or recorded) trace statements, or print statements, that indicate the flow of execution of a process. This is sometimes called printf debugging, due to the use of the printf function in C.
- Task
- Show the print debugging statements in the language.
- Demonstrate their ability to track provenance by displaying information about source code (e.g., code fragment, line and column number).
C
C doesn't have a built-in print debugging statement. However, it can be defined by users as a macro.
<lang C>#include <stdio.h>
- define DEBUG_INT(x) printf( #x " at line %d\nresult: %d\n\n", __LINE__, x)
int add(int x, int y) {
int result = x + y; DEBUG_INT(x); DEBUG_INT(y); DEBUG_INT(result); DEBUG_INT(result+1); return result;
}
int main() {
add(2, 7); return 0;
}</lang>
- Output:
x at line 7 result: 2 y at line 8 result: 7 result at line 9 result: 9 result+1 at line 10 result: 10
Go
Go doesn't have a built-in print debugging statement as such. Nor does it have macros.
However, as the following example shows, it is easy enough to mimic a C-like approach by writing a short 'debug' function which can show the value of an expression and its type at the appropriate line number in the program's source code.
Note that a label for the expression (whether it's a simple variable or not) must be passed to the 'debug' function as there is no way to deduce it otherwise. <lang go>package main
import (
"fmt" "runtime"
)
type point struct {
x, y float64
}
func add(x, y int) int {
result := x + y debug("x", x) debug("y", y) debug("result", result) debug("result+1", result+1) return result
}
func debug(s string, x interface{}) {
_, _, lineNo, _ := runtime.Caller(1) fmt.Printf("%q at line %d type '%T'\nvalue: %#v\n\n", s, lineNo, x, x)
}
func main() {
add(2, 7) b := true debug("b", b) s := "Hello" debug("s", s) p := point{2, 3} debug("p", p) q := &p debug("q", q)
}</lang>
- Output:
"x" at line 14 type 'int' value: 2 "y" at line 15 type 'int' value: 7 "result" at line 16 type 'int' value: 9 "result+1" at line 17 type 'int' value: 10 "b" at line 29 type 'bool' value: true "s" at line 31 type 'string' value: "Hello" "p" at line 33 type 'main.point' value: main.point{x:2, y:3} "q" at line 35 type '*main.point' value: &main.point{x:2, y:3}
Pyret
Pyret has the spy
expression. The expression can print the value of an identifier, using the identifier itself as a label if it's not already given. It could also print the value of an arbitrary expression, but it needs an explicit label in this case.
<lang pyret>fun add(x, y):
result = x + y spy "in add": x, y, result, result-plus-one: result + 1 end result
end
add(2, 7)</lang>
- Output:
Spying "in add" (at file:///spies.arr:3:2-8:5) x: 2 y: 7 result: 9 result-plus-one: 10 9
Racket
Racket doesn't have a built-in print debugging statement. However, it can be defined by users as a macro.
<lang racket>#lang racket
(require syntax/parse/define)
(define (debug:core line col code val #:label [label #f])
;; if label exists, use it instead of the code fragment (printf "~a at line ~a column ~a\n" (or label code) line col) (printf "result: ~a\n\n" val) ;; return the value itself, so that we can wrap macro around an expression ;; without restructuring any code val)
(define-simple-macro (debug <x> option ...)
#:with line (datum->syntax this-syntax (syntax-line #'<x>)) #:with col (datum->syntax this-syntax (syntax-column #'<x>)) (debug:core line col (quote <x>) <x> option ...))
(define (add x y)
(define result (+ x y)) (debug x) (debug y) (debug (if #t (+ x y) (error 'impossible))) (debug (add1 result) #:label "result plus one") (debug result))
(add 2 7)</lang>
- Output:
x at line 20 column 9 result: 2 y at line 21 column 9 result: 7 (if #t (+ x y) (error 'impossible)) at line 22 column 9 result: 9 result plus one at line 23 column 9 result: 10 result at line 24 column 9 result: 9 9