String Formatting in Racket
#lang racket
(struct point (x y))
(define (main)
; Racket offers several printing functions for formatting values.
; For example, this prints an instance of our `point` struct.
(let ([p (point 1 2)])
(printf "struct1: ~a\n" p)
; To include the struct's field names, we can use `~v`.
(printf "struct2: ~v\n" p)
; The `~s` format specifier prints a Racket syntax representation
; of the value, i.e. the source code snippet that would produce that value.
(printf "struct3: ~s\n" p)
; To print the type of a value, we can use `object-name`.
(printf "type: ~a\n" (object-name (point-x p)))
; Formatting booleans is straightforward.
(printf "bool: ~a\n" #t)
; There are many options for formatting integers.
; Use `~a` for standard formatting.
(printf "int: ~a\n" 123)
; This prints a binary representation.
(printf "bin: ~b\n" 14)
; This prints the character corresponding to the given integer.
(printf "char: ~a\n" (integer->char 33))
; `~x` provides hex encoding.
(printf "hex: ~x\n" 456)
; For basic decimal formatting of floats, use `~f`.
(printf "float1: ~f\n" 78.9)
; `~e` formats the float in scientific notation.
(printf "float2: ~e\n" 123400000.0)
; For basic string printing, use `~a`.
(printf "str1: ~a\n" "\"string\"")
; To double-quote strings, use `~s`.
(printf "str2: ~s\n" "\"string\"")
; To print a representation of a pointer, we can use `eq-hash-code`.
(printf "pointer: ~x\n" (eq-hash-code p))
; When formatting numbers, you can control the width and precision.
; To specify the width of an integer, use a number after `~`.
(printf "width1: |~6a|~6a|\n" 12 345)
; For floats, you can specify both width and precision.
(printf "width2: |~6,2f|~6,2f|\n" 1.2 3.45)
; To left-justify, use the `-` flag.
(printf "width3: |~-6,2f|~-6,2f|\n" 1.2 3.45)
; You can also control width when formatting strings.
(printf "width4: |~6a|~6a|\n" "foo" "b")
; To left-justify strings, use the `-` flag as with numbers.
(printf "width5: |~-6a|~-6a|\n" "foo" "b")
; `format` returns a formatted string without printing it.
(let ([s (format "format: a ~a" "string")])
(displayln s))
; You can format+print to output ports other than
; the current output port using `fprintf`.
(fprintf (current-error-port) "io: an ~a\n" "error"))
)
(main)
To run this program, save it as string-formatting.rkt
and use the racket
command:
$ racket string-formatting.rkt
struct1: #<point>
struct2: #(struct:point 1 2)
struct3: (point 1 2)
type: integer
bool: #t
int: 123
bin: 1110
char: !
hex: 1c8
float1: 78.9
float2: 1.234e+8
str1: "string"
str2: "\"string\""
pointer: 1234567 ; This will be a different number each time
width1: | 12| 345|
width2: | 1.20| 3.45|
width3: |1.20 |3.45 |
width4: | foo| b|
width5: |foo |b |
format: a string
io: an error
This Racket program demonstrates various string formatting techniques, similar to the original Go example. It uses Racket’s printf
function, which is similar to Go’s fmt.Printf
. The format specifiers are slightly different:
~a
is used for general formatting (similar to%v
in Go)~s
is used for Racket syntax representation (similar to%#v
in Go)~v
is used for detailed structure printing (similar to%+v
in Go)~f
is used for float formatting~e
is used for scientific notation~x
is used for hexadecimal formatting~b
is used for binary formatting
Racket doesn’t have a built-in way to print type information like Go’s %T
, so we use object-name
on a struct field instead.
The program also demonstrates width and precision control, left-justification, and using different output ports (like current-error-port
, which is similar to os.Stderr
in Go).
Note that Racket doesn’t have a direct equivalent to Go’s pointers, so we use eq-hash-code
to get a unique identifier for an object, which serves a similar purpose in this context.