On this page:
cat
catp
catw
catn
catnp
catne

5 Converting Values to Strings

Ryan Culpepper <ryanc@racket-lang.org>

 (require unstable/cat)

This module provides a few functions for converting Racket values to strings. In addition to features like padding and numeric formatting, the functions have the virtue of being shorter and more pleasant to type than format (with format string), number->string, or string-append.

procedure

(cat v    
  ...    
  [#:width width    
  #:limit limit    
  #:limit-marker limit-marker    
  #:pad-to pad-to    
  #:align align    
  #:padding padding    
  #:left-padding left-padding    
  #:right-padding right-padding])  string?
  v : any/c
  width : (or/c exact-nonnegative-integer? #f) = #f
  limit : (or/c exact-nonnegative-integer? +inf.0)
   = (or width +inf.0)
  limit-marker : string? = "..."
  pad-to : exact-nonnegative-integer? = (or width 0)
  align : (or/c 'left 'center 'right) = 'left
  padding : non-empty-string? = " "
  left-padding : non-empty-string? = padding
  right-padding : non-empty-string? = padding
Converts each v to a string in display mode—that is, like (format "~a" v)then concatentates the results and pads or truncates the string to be at least pad-to characters and at most limit characters.

> (cat "north")

"north"

> (cat 'south)

"south"

> (cat #"east")

"east"

> (cat #\w "e" 'st)

"west"

> (cat (list "red" 'green #"blue"))

"(red green blue)"

> (cat 17)

"17"

> (cat 100000000000000000000)

"100000000000000000000"

> (cat pi)

"3.141592653589793"

> (cat (expt 6.1 87))

"2.1071509386211452e+68"

The cat function is primarily useful for strings, numbers, and other atomic data. The catp and catw functions are better suited to compound data.

Let s be the concatenated string forms of the vs. If s is longer than limit characters, it is truncated to exactly limit characters. If s is shorter than pad-to characters, it is padded to exactly pad-to characters. Otherwise s is returned unchanged. If pad-to is greater than limit, an exception is raised.

If s is longer than limit characters, it is truncated and the end of the string is replaced with limit-marker. If limit-marker is longer than limit, an exception is raised.

> (cat "abcde" #:limit 5)

"abcde"

> (cat "abcde" #:limit 4)

"a..."

> (cat "abcde" #:limit 4 #:limit-marker "*")

"abc*"

> (cat "abcde" #:limit 4 #:limit-marker "")

"abcd"

> (cat "The quick brown fox" #:limit 15 #:limit-marker "")

"The quick brown"

> (cat "The quick brown fox" #:limit 15 #:limit-marker "...")

"The quick br..."

If s is shorter than pad-to, it is padded to at least pad-to characters. If align is 'left, then only right padding is added; if align is 'right, then only left padding is added; and if align is 'center, then roughly equal amounts of left padding and right padding are added.

Padding is specified as a non-empty string. Left padding consists of left-padding repeated in its entirety as many times as possible followed by a prefix of left-padding to fill the remaining space. In contrast, right padding consists of a suffix of right-padding followed by a number of copies of right-padding in its entirety. Thus left padding starts with the start of left-padding and right padding ends with the end of right-padding.

> (cat "apple" #:pad-to 20 #:align 'left)

"apple               "

> (cat "pear" #:pad-to 20 #:align 'left #:right-padding " .")

"pear . . . . . . . ."

> (cat "plum" #:pad-to 20 #:align 'right #:left-padding ". ")

". . . . . . . . plum"

> (cat "orange" #:pad-to 20 #:align 'center
                #:left-padding "- " #:right-padding " -")

"- - - -orange- - - -"

Use width to set both limit and pad-to simultaneously, ensuring that the resulting string is exactly width characters long:

> (cat "terse" #:width 6)

"terse "

> (cat "loquacious" #:width 6)

"loq..."

procedure

(catp v    
  [#:width width    
  #:limit limit    
  #:limit-marker limit-marker    
  #:pad-to pad-to    
  #:align align    
  #:padding padding    
  #:left-padding left-padding    
  #:right-padding right-padding])  string?
  v : any/c
  width : (or/c exact-nonnegative-integer? #f) = #f
  limit : (or/c exact-nonnegative-integer? +inf.0)
   = (or width +inf.0)
  limit-marker : string? = "..."
  pad-to : exact-nonnegative-integer? = (or width 0)
  align : (or/c 'left 'center 'right) = 'left
  padding : non-empty-string? = " "
  left-padding : non-empty-string? = padding
  right-padding : non-empty-string? = padding
Like cat, but converts a single v to a string in print mode—that is, like (format "~v" v).

> (catp "north")

"\"north\""

> (catp 'south)

"'south"

> (catp #"east")

"#\"east\""

> (catp #\w)

"#\\w"

> (catp (list "red" 'green #"blue"))

"'(\"red\" green #\"blue\")"

Use catp to produce text that talks about Racket values.

> (let ([nums (for/list ([i 10]) i)])
    (cat "The even numbers in " (catp nums)
         " are " (catp (filter even? nums)) "."))

"The even numbers in '(0 1 2 3 4 5 6 7 8 9) are '(0 2 4 6 8)."

procedure

(catw v    
  [#:width width    
  #:limit limit    
  #:limit-marker limit-marker    
  #:pad-to pad-to    
  #:align align    
  #:padding padding    
  #:left-padding left-padding    
  #:right-padding right-padding])  string?
  v : any/c
  width : (or/c exact-nonnegative-integer? #f) = #f
  limit : (or/c exact-nonnegative-integer? +inf.0)
   = (or width +inf.0)
  limit-marker : string? = "..."
  pad-to : exact-nonnegative-integer? = (or width 0)
  align : (or/c 'left 'center 'right) = 'left
  padding : non-empty-string? = " "
  left-padding : non-empty-string? = padding
  right-padding : non-empty-string? = padding
Like cat, but converts a single v to a string in write mode—that is, like (format "~s" v).

> (catw "north")

"\"north\""

> (catw 'south)

"south"

> (catw #"east")

"#\"east\""

> (catw #\w)

"#\\w"

> (catw (list "red" 'green #"blue"))

"(\"red\" green #\"blue\")"

procedure

(catn x    
  [#:sign sign    
  #:base base    
  #:precision precision    
  #:pos/exp-range pos/exp-range    
  #:exp-precision exp-precision    
  #:exp-format-exponent exp-format-exponent    
  #:pad-digits-to pad-digits-to    
  #:digits-padding digits-padding])  string?
  x : rational?
  sign : 
(or/c #f '+ '++ 'parens
      (let ([ind (or/c string? (list/c string? string?))])
        (list/c ind ind ind)))
   = #f
  base : (or/c (integer-in 2 36) (list/c 'up (integer-in 2 36)))
   = 10
  precision : 
(or/c exact-nonnegative-integer?
      (list/c '= exact-nonnegative-integer?))
 = 3
  pos/exp-range : 
(list/c (or/c exact-integer? +inf.0)
        (or/c exact-integer? -inf.0))
   = (list -inf.0 +inf.0)
  exp-precision : 
(or/c exact-nonnegative-integer?
      (list/c '= exact-nonnegative-integer?))
   = 5
  exp-format-exponent : (or/c #f string? (-> exact-integer? string?))
   = #f
  pad-digits-to : exact-positive-integer? = 1
  digits-padding : non-empty-string? = " "
Converts the rational number x to a string in either positional or exponential notation. The exactness or inexactness of x does not affect its formatting.

Numbers whose order of magnitude (with respect to base) fall strictly within pos/exp-range are formatted using positional notation. More precisely, if the following condition holds:

(or (zero? x)
    (< (expt base (car pos/exp-range))
       (abs x)
       (expt base (cadr pos/exp-range))))

then the result is equivalent to

(catnp x
       #:sign sign-mode
       #:base base
       #:precision precision
       #:pad-digits-to pad-digits-to
       #:digits-padding digits-padding)

Otherwise, the number is formatted in exponential notation, and the result is equivalent to

(catne x
       #:sign sign-mode
       #:base base
       #:precision exp-precision
       #:format-exponent exp-format-exponent
       #:pad-digits-to pad-digits-to
       #:digits-padding digits-padding)

Examples:

> (catn 999 #:pos/exp-range '(0 3))

"999"

> (catn 1000 #:pos/exp-range '(0 3))

"1e+03"

> (catn 0.9876 #:pos/exp-range '(0 3))

"9.876e-01"

Note that the default value of pos/exp-range ensures that positional notation will be used for any rational x.

procedure

(catnp x    
  [#:sign sign    
  #:base base    
  #:precision precision    
  #:pad-digits-to pad-digits-to    
  #:digits-padding digits-padding])  string?
  x : rational?
  sign : 
(or/c #f '+ '++ 'parens
      (let ([ind (or/c string? (list/c string? string?))])
        (list/c ind ind ind)))
   = #f
  base : (or/c (integer-in 2 36) (list/c 'up (integer-in 2 36)))
   = 10
  precision : 
(or/c exact-nonnegative-integer?
      (list/c '= exact-nonnegative-integer?))
 = 3
  pad-digits-to : exact-positive-integer? = 1
  digits-padding : non-empty-string? = " "
Formats the rational number x using positional notation according to the following arguments:

procedure

(catne x    
  [#:sign sign    
  #:base base    
  #:precision precision    
  #:format-exponent format-exponent    
  #:pad-digits-to pad-digits-to    
  #:digits-padding digits-padding])  string?
  x : rational?
  sign : 
(or/c #f '+ '++ 'parens
      (let ([ind (or/c string? (list/c string? string?))])
        (list/c ind ind ind)))
   = #f
  base : (or/c (integer-in 2 36) (list/c 'up (integer-in 2 36)))
   = 10
  precision : 
(or/c exact-nonnegative-integer?
      (list/c '= exact-nonnegative-integer?))
 = 5
  format-exponent : (or/c #f string? (-> exact-integer? string?))
   = #f
  pad-digits-to : exact-positive-integer? = 1
  digits-padding : non-empty-string? = " "
Formats the rational number x in exponential notation according to the following arguments: