Print debugging statement: Difference between revisions
mNo edit summary |
(Added Go) |
||
Line 46: | Line 46: | ||
result+1 at line 10 |
result+1 at line 10 |
||
result: 10 |
result: 10 |
||
</pre> |
|||
=={{header|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> |
|||
{{out}} |
|||
<pre> |
|||
"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} |
|||
</pre> |
</pre> |
||
Revision as of 15:49, 27 August 2019
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