diff --git a/collects/unstable/cat.rkt b/collects/unstable/cat.rkt deleted file mode 100644 index 419a1800d3..0000000000 --- a/collects/unstable/cat.rkt +++ /dev/null @@ -1,459 +0,0 @@ -#lang racket/base -(require racket/contract/base) - -;; cat = "consider as text" :) - -;; TO DO: -;; - avoid unnecessary intermediate strings -;; - see "Printing Floating-Point Numbers Quickly and Accurately" -;; by Berger & Dybvig, PLDI 1996 for ideas - -;; MAYBE TO DO: -;; - rename 'cat' -> 'catd' ("cat like display") and make 'cat' -;; recur into lists, vectors, etc? -;; - decimal separators (see "man 7 locale", lconv numeric fields) -;; - 'catmon' : like 'catn' but for monetary amounts (see strfmon)? -;; (perhaps as separate library) -;; - prop:cat, separate from prop:custom-write? - -(define (non-empty-string? x) - (and (string? x) (positive? (string-length x)))) - -(define align-mode/c - (or/c 'left 'right 'center)) -(define padding/c non-empty-string?) - -(define sign-mode/c - (or/c #f '+ '++ 'parens - (let ([ind/c (or/c string? (list/c string? string?))]) - (list/c ind/c ind/c ind/c)))) - -(define base/c - (or/c (integer-in 2 36) - (list/c 'up (integer-in 2 36)))) - -;; Precision is one of -;; - Nat, for "up to N" -;; - '(= N), for "exactly N" -(define precision/c - (or/c exact-nonnegative-integer? - (list/c '= exact-nonnegative-integer?))) - -(define cat-n-c - (->* () - (#:width (or/c exact-nonnegative-integer? #f) - #:limit (or/c exact-nonnegative-integer? +inf.0) - #:limit-marker string? - #:pad-to exact-nonnegative-integer? - #:align align-mode/c - #:padding padding/c - #:left-padding padding/c - #:right-padding padding/c) - #:rest list? - string?)) - -(define cat-1-c - (->* (any/c) - (#:width (or/c exact-nonnegative-integer? #f) - #:limit (or/c exact-nonnegative-integer? +inf.0) - #:limit-marker string? - #:pad-to exact-nonnegative-integer? - #:align align-mode/c - #:padding padding/c - #:left-padding padding/c - #:right-padding padding/c) - string?)) - -(provide/contract - [cat cat-n-c] - [catw cat-1-c] - [catp cat-1-c] - [catn - (->* (rational?) - (#:sign sign-mode/c - #:base base/c - #:precision precision/c - #:pos/exp-range (list/c (or/c exact-integer? +inf.0) - (or/c exact-integer? -inf.0)) - #:exp-precision precision/c - #:exp-format-exponent (or/c #f string? (-> exact-integer? string?)) - #:pad-digits-to exact-positive-integer? - #:digits-padding padding/c) - string?)] - [catnp - (->* (rational?) - (#:sign sign-mode/c - #:base base/c - #:precision precision/c - #:pad-digits-to exact-positive-integer? - #:digits-padding padding/c) - string?)] - [catne - (->* (rational?) - (#:sign sign-mode/c - #:base base/c - #:precision precision/c - #:format-exponent (or/c #f string? (-> exact-integer? string?)) - #:pad-digits-to exact-positive-integer? - #:digits-padding padding/c) - string?)]) - -;; ---------------------------------------- - -(define (%limit #:limit limit - #:limit-marker limit-marker - s) - (cond [(> (string-length s) limit) - (string-append (substring s 0 (- limit (string-length limit-marker))) - limit-marker)] - [else s])) - -(define (%pad #:pad-to pad-to - #:align align-mode - #:left-padding left-padding - #:right-padding right-padding - s) - (cond [(< (string-length s) pad-to) - (let* ([s-length (string-length s)] - [to-pad-length (max 0 (- pad-to s-length))]) - (let-values ([(left-pad-length right-pad-length) - (case align-mode - ((left) (values 0 to-pad-length)) - ((right) (values to-pad-length 0)) - ((center) - (values (floor (/ to-pad-length 2)) - (ceiling (/ to-pad-length 2)))))]) - (string-append - (build-padding 'left left-padding left-pad-length) - s - (build-padding 'right right-padding right-pad-length))))] - [else s])) - -(define (build-padding side padding pad-length) - (cond [(zero? pad-length) ""] - [(char? padding) - (make-string pad-length padding)] - [(and (string? padding) (= (string-length padding) 1)) - (make-string pad-length (string-ref padding 0))] - [(string? padding) - (let* ([pattern padding] - [pattern-length (string-length pattern)] - [whole-copies (quotient pad-length pattern-length)] - [part-length (remainder pad-length pattern-length)] - [pattern-copies (for/list ([i (in-range whole-copies)]) pattern)]) - (apply string-append - ;; For left, start at start of string - ;; For right, end at end of string. - (case side - ((left) - (append pattern-copies - (list (substring pattern 0 part-length)))) - ((right) - (cons (substring pattern (- pattern-length part-length) pattern-length) - pattern-copies)))))])) - -(define (do-checks who limit limit-marker width) - (when (> width limit) - (error who "pad-to length greater than limit (~s): ~s" limit width)) - (when (> (string-length limit-marker) limit) - (error who "limit-marker string longer than limit (~s): ~e" - limit limit-marker))) - -;; ---------------------------------------- - -(define (%cat s - #:who who - #:limit limit - #:limit-marker limit-marker - #:pad-to pad-to - #:align align - #:right-padding right-padding - #:left-padding left-padding) - (do-checks who limit limit-marker pad-to) - (%pad (%limit (if (list? s) (apply string-append s) s) - #:limit limit - #:limit-marker limit-marker) - #:pad-to pad-to - #:align align - #:left-padding left-padding - #:right-padding right-padding)) - -(define (cat #:width [width #f] - ;; I was greatly tempted to name this keyword option #:nip instead - ;; (or maybe #:nip-to) - #:limit [limit (or width +inf.0)] - #:limit-marker [limit-marker "..."] - #:pad-to [pad-to (or width 0)] - #:align [align 'left] - #:padding [padding " "] - #:right-padding [right-padding padding] - #:left-padding [left-padding padding] - . vs) - (%cat (map (lambda (v) (if (string? v) v (format "~a" v))) vs) - #:who 'cat - #:limit limit - #:limit-marker limit-marker - #:pad-to pad-to - #:align align - #:right-padding right-padding - #:left-padding left-padding)) - -(define (catw #:width [width #f] - #:limit [limit (or width +inf.0)] - #:limit-marker [limit-marker "..."] - #:pad-to [pad-to (or width 0)] - #:align [align 'left] - #:padding [padding " "] - #:right-padding [right-padding padding] - #:left-padding [left-padding padding] - v) - (%cat (format "~s" v) - #:who 'catw - #:limit limit - #:limit-marker limit-marker - #:pad-to pad-to - #:align align - #:right-padding right-padding - #:left-padding left-padding)) - -(define (catp #:width [width #f] - #:limit [limit (or width +inf.0)] - #:limit-marker [limit-marker "..."] - #:pad-to [pad-to (or width 0)] - #:align [align 'left] - #:padding [padding " "] - #:right-padding [right-padding padding] - #:left-padding [left-padding padding] - v) - (%cat (format "~v" v) - #:who 'cat - #:limit limit - #:limit-marker limit-marker - #:pad-to pad-to - #:align align - #:right-padding right-padding - #:left-padding left-padding)) - -;; ---- - -(define (catn N - #:sign [sign-mode #f] - #:base [base 10] - #:precision [precision 3] - #:pos/exp-range [pos/exp-range #f] - #:exp-precision [exp-precision 5] - #:exp-format-exponent [exp-format-exponent #f] - #:pad-digits-to [pad-digits-to 1] - #:digits-padding [digits-padding " "]) - (let* ([N-abs (abs N)] - [positional? - (or (zero? N-abs) - (not pos/exp-range) - (let ([max-neg-exp (car pos/exp-range)] - [min-pos-exp (cadr pos/exp-range)]) - (< (expt base max-neg-exp) N-abs (expt base min-pos-exp))))]) - (if positional? - (catnp N - #:who 'catn - #:sign sign-mode - #:base base - #:precision precision - #:pad-digits-to pad-digits-to - #:digits-padding digits-padding) - (catne N - #:who 'catn - #:sign sign-mode - #:base base - #:precision exp-precision - #:format-exponent exp-format-exponent - #:pad-digits-to pad-digits-to - #:digits-padding digits-padding)))) - -(define (catnp N - #:who [who 'catnp] - #:sign [sign-mode #f] - #:base [base 10] - #:precision [precision 3] - #:pad-digits-to [pad-digits-to 1] - #:digits-padding [digits-padding " "]) - ;; precision: up to (or exactly) this many digits after decimal point - ;; precision = 0 means no decimal point - ;; precision = '(= 0) means keep decimal point - ;; pad-digits-to: includes decimal point, doesn't include sign - (let*-values ([(upper? base) (normalize-base base)] - [(exactly? precision) (normalize-precision precision)]) - (let* ([N-abs (abs N)] - [digits-part (%positional N-abs base upper? precision exactly?)] - [padded-digits-part - (%pad digits-part - #:pad-to pad-digits-to - #:align 'right - #:left-padding digits-padding - #:right-padding #f)]) - (let-values ([(pre-sign-part post-sign-part) (get-sign-parts N sign-mode)]) - (string-append pre-sign-part padded-digits-part post-sign-part))))) - -(define (catne N - #:who [who 'catne] - #:sign [sign-mode #f] - #:base [base 10] - #:precision [precision 5] - #:format-exponent [format-exponent #f] - #:pad-digits-to [pad-digits-to 1] - #:digits-padding [digits-padding " "]) - (let*-values ([(upper? base) (normalize-base base)] - [(exactly? precision) (normalize-precision precision)]) - (let* ([N-abs (abs N)] - [digits-part - (%exponential N-abs base format-exponent precision exactly?)] - [padded-digits-part - (%pad digits-part - #:pad-to pad-digits-to - #:align 'right - #:left-padding digits-padding - #:right-padding #f)]) - (let-values ([(pre-sign-part post-sign-part) (get-sign-parts N sign-mode)]) - (string-append pre-sign-part padded-digits-part post-sign-part))))) - -(define (normalize-base base) - (if (pair? base) - (values (eq? (car base) 'up) (cadr base)) - (values #f base))) - -(define (normalize-precision precision) - (if (pair? precision) - (values #t (cadr precision)) - (values #f precision))) - -(define (%positional N-abs base upper? precision exactly?) - (let* ([Nw (inexact->exact (floor N-abs))] - [Nf (- N-abs Nw)] - [whole-part (number->string* Nw base upper?)] - [frac-part - (let* ([Nf* (inexact->exact (round (* Nf (expt base precision))))]) - (cond [(and exactly? (= precision 0)) ""] - [exactly? (number->fraction-string Nf* base upper? precision)] - [(= Nf* 0) #f] - [else - (let-values ([(needed-precision Nf**) - (let loop ([np precision] [Nf* Nf*]) - (let-values ([(q r) (quotient/remainder Nf* base)]) - (cond [(zero? r) (loop (sub1 np) q)] - [else (values np Nf*)])))]) - (number->fraction-string Nf** base upper? needed-precision))]))] - [digits-part - (cond [frac-part (string-append whole-part "." frac-part)] - [else whole-part])]) - digits-part)) - -(define (%exponential N-abs base format-exponent significand-precision exactly?) - (define-values (N* e-adjust actual-precision) - (scale N-abs base significand-precision exactly?)) - ;; hack: from 1234 want "1.234"; convert to "1234", mutate to ".234" after saving "1" - (let* ([digits (number->string* N* base #f)] - [leading-digit (string (string-ref digits 0))] - [exponent (- significand-precision e-adjust)]) - (string-set! digits 0 #\.) - (string-append leading-digit - (if (or exactly? (positive? actual-precision)) digits "") - (cond [(procedure? format-exponent) - (format-exponent exponent)] - [else - (string-append - (cond [(string? format-exponent) format-exponent] - [(= base 10) "e"] - [else (format "×~s^" base)]) - (if (negative? exponent) "-" "+") - (%pad (number->string (abs exponent)) - #:pad-to 2 - #:align 'right - #:left-padding "0" - #:right-padding #f))])))) - -(define (scale N-abs base significand-precision exactly?) - (if (zero? N-abs) - (values 0 0 (if exactly? significand-precision 0)) - (scale/nz N-abs base significand-precision exactly?))) - -(define (scale/nz N-abs base significand-precision exactly?) - (let* ([N (inexact->exact N-abs)] - [normalized-min (expt base significand-precision)] - [normalized-max (* base normalized-min)]) - (let*-values ([(N*0 e-adjust0) - (let ([e-est (- significand-precision - (inexact->exact (floor (/ (log N-abs) (log base)))))]) - (values (* N (expt base e-est)) e-est))] - [(N* e-adjust) - (let loop ([N N*0] [e e-adjust0] [r #f]) - ;; if r != #f, then N is integer - (cond [(< N normalized-min) - (loop (* N base) (add1 e) #f)] - [(>= N normalized-max) - (let-values ([(q r) (quotient/remainder (floor N) base)]) - (loop q (sub1 e) r))] - [else - (let ([N* (if r - (if (>= (* 2 r) base) (add1 N) N) - (round* N))]) - (cond [(< N* normalized-max) - (values N* e)] - [else (loop N* e #f)]))]))] - [(N* actual-precision) - (if exactly? - (values N* significand-precision) - (let loop ([N N*] [p significand-precision]) - (let-values ([(q r) (quotient/remainder N base)]) - (cond [(zero? r) (loop q (sub1 p))] - [else (values N p)]))))]) - (values N* e-adjust actual-precision)))) - -;; ---- - -(define (get-sign-parts N sign-mode) - (define (get indicator) - (if (string? indicator) - (values indicator "") - (values (car indicator) (cadr indicator)))) - (let ([indicator-table - (case sign-mode - ((#f) '("" "" "-")) - ((+) '("+" "" "-")) - ((++) '("+" "+" "-")) - ((parens) '("" "" ("(" ")"))) - (else sign-mode))]) - (cond [(or (negative? N) (eqv? -0.0 N)) - (get (caddr indicator-table))] - [(zero? N) - (get (cadr indicator-table))] - [else ;; positive - (get (car indicator-table))]))) - -(define (number->string* N base upper?) - (cond [(memv base '(2 8 10 16)) - (let ([s (number->string N base)]) - (if (and (= base 16) upper?) - (string-upcase s) - s))] - [(zero? N) - (string #\0)] - [else - (apply string - (let loop ([N N] [digits null]) - (cond [(zero? N) (reverse digits)] - [else (let-values ([(q r) (quotient/remainder N base)]) - (loop q (cons (get-digit r upper?) digits)))])))])) - -(define (number->fraction-string N base upper? precision) - (let ([s (number->string* N base upper?)]) - (string-append (make-string (- precision (string-length s)) #\0) s))) - -;; Allow base up to 36! -(define (get-digit d upper?) - (cond [(< d 10) (integer->char (+ d (char->integer #\0)))] - [else (integer->char (+ (- d 10) (char->integer (if upper? #\A #\a))))])) - -(define (round* x) ;; round is round-to-even :( - (if (integer? x) - x - (+ (truncate x) - (if (even? (truncate (+ x x))) 0 1)))) diff --git a/collects/unstable/scribblings/cat.scrbl b/collects/unstable/scribblings/cat.scrbl deleted file mode 100644 index 3d4d22e672..0000000000 --- a/collects/unstable/scribblings/cat.scrbl +++ /dev/null @@ -1,472 +0,0 @@ -#lang scribble/doc -@(require scribble/manual - scribble/struct - scribble/eval - (for-label racket/base - racket/contract - racket/math - unstable/cat - unstable/contract)) - -@(begin - (define the-eval (make-base-eval)) - (the-eval '(require racket/math unstable/cat))) - -@title[#:tag "cat"]{Converting Values to Strings} -@author[@author+email["Ryan Culpepper" "ryanc@racket-lang.org"]] - -@defmodule[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 @racket[format] (with -format string), @racket[number->string], or @racket[string-append]. - -@defproc[(cat [v any/c] ... - [#:width width (or/c exact-nonnegative-integer? #f) #f] - [#:limit limit (or/c exact-nonnegative-integer? +inf.0) (or width +inf.0)] - [#:limit-marker limit-marker string? "..."] - [#:pad-to pad-to exact-nonnegative-integer? (or width 0)] - [#:align align (or/c 'left 'center 'right) 'left] - [#:padding padding non-empty-string? " "] - [#:left-padding left-padding non-empty-string? padding] - [#:right-padding right-padding non-empty-string? padding]) - string?]{ - -Converts each @racket[v] to a string in @racket[display] mode---that -is, like @racket[(format "~a" v)]---then concatentates the results and -pads or truncates the string to be at least @racket[pad-to] characters -and at most @racket[limit] characters. - -@interaction[#:eval the-eval -(cat "north") -(cat 'south) -(cat #"east") -(cat #\w "e" 'st) -(cat (list "red" 'green #"blue")) -(cat 17) -(cat #e1e20) -(cat pi) -(cat (expt 6.1 87)) -] - -The @racket[cat] function is primarily useful for strings, numbers, and other -atomic data. The @racket[catp] and @racket[catw] functions are better suited to -compound data. - -Let @racket[_s] be the concatenated string forms of the -@racket[v]s. If @racket[_s] is longer than @racket[limit] characters, -it is truncated to exactly @racket[limit] characters. If @racket[_s] -is shorter than @racket[pad-to] characters, it is padded to exactly -@racket[pad-to] characters. Otherwise @racket[_s] is returned -unchanged. If @racket[pad-to] is greater than @racket[limit], an -exception is raised. - -If @racket[_s] is longer than @racket[limit] characters, it is truncated and the -end of the string is replaced with @racket[limit-marker]. If -@racket[limit-marker] is longer than @racket[limit], an exception is raised. - -@interaction[#:eval the-eval -(cat "abcde" #:limit 5) -(cat "abcde" #:limit 4) -(cat "abcde" #:limit 4 #:limit-marker "*") -(cat "abcde" #:limit 4 #:limit-marker "") -(cat "The quick brown fox" #:limit 15 #:limit-marker "") -(cat "The quick brown fox" #:limit 15 #:limit-marker "...") -] - -If @racket[_s] is shorter than @racket[pad-to], it is padded to at -least @racket[pad-to] characters. If @racket[align] is -@racket['left], then only right padding is added; if @racket[align] -is @racket['right], then only left padding is added; and if -@racket[align] is @racket['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 -@racket[left-padding] repeated in its entirety as many times as -possible followed by a @emph{prefix} of @racket[left-padding] to fill -the remaining space. In contrast, right padding consists of a -@emph{suffix} of @racket[right-padding] followed by a number of copies -of @racket[right-padding] in its entirety. Thus left padding starts -with the start of @racket[left-padding] and right padding ends with -the end of @racket[right-padding]. - -@interaction[#:eval the-eval -(cat "apple" #:pad-to 20 #:align 'left) -(cat "pear" #:pad-to 20 #:align 'left #:right-padding " .") -(cat "plum" #:pad-to 20 #:align 'right #:left-padding ". ") -(cat "orange" #:pad-to 20 #:align 'center - #:left-padding "- " #:right-padding " -") -] - -Use @racket[width] to set both @racket[limit] and @racket[pad-to] -simultaneously, ensuring that the resulting string is exactly -@racket[width] characters long: - -@interaction[#:eval the-eval -(cat "terse" #:width 6) -(cat "loquacious" #:width 6) -] -} - -@;{----------------------------------------} - -@defproc[(catp [v any/c] - [#:width width (or/c exact-nonnegative-integer? #f) #f] - [#:limit limit (or/c exact-nonnegative-integer? +inf.0) (or width +inf.0)] - [#:limit-marker limit-marker string? "..."] - [#:pad-to pad-to exact-nonnegative-integer? (or width 0)] - [#:align align (or/c 'left 'center 'right) 'left] - [#:padding padding non-empty-string? " "] - [#:left-padding left-padding non-empty-string? padding] - [#:right-padding right-padding non-empty-string? padding]) - string?]{ - -Like @racket[cat], but converts a single @racket[v] to a string in -@racket[print] mode---that is, like @racket[(format "~v" v)]. - -@interaction[#:eval the-eval -(catp "north") -(catp 'south) -(catp #"east") -(catp #\w) -(catp (list "red" 'green #"blue")) -] - -Use @racket[catp] to produce text that talks about Racket values. - -@interaction[#:eval the-eval -(let ([nums (for/list ([i 10]) i)]) - (cat "The even numbers in " (catp nums) - " are " (catp (filter even? nums)) ".")) -] -} - -@;{----------------------------------------} - -@defproc[(catw [v any/c] - [#:width width (or/c exact-nonnegative-integer? #f) #f] - [#:limit limit (or/c exact-nonnegative-integer? +inf.0) (or width +inf.0)] - [#:limit-marker limit-marker string? "..."] - [#:pad-to pad-to exact-nonnegative-integer? (or width 0)] - [#:align align (or/c 'left 'center 'right) 'left] - [#:padding padding non-empty-string? " "] - [#:left-padding left-padding non-empty-string? padding] - [#:right-padding right-padding non-empty-string? padding]) - string?]{ - -Like @racket[cat], but converts a single @racket[v] to a string in -@racket[write] mode---that is, like @racket[(format "~s" v)]. - -@interaction[#:eval the-eval -(catw "north") -(catw 'south) -(catw #"east") -(catw #\w) -(catw (list "red" 'green #"blue")) -] -} - -@;{----------------------------------------} - -@defproc[(catn [x rational?] - [#:sign sign - (or/c #f '+ '++ 'parens - (let ([ind (or/c string? (list/c string? string?))]) - (list/c ind ind ind))) - #f] - [#:base base - (or/c (integer-in 2 36) (list/c 'up (integer-in 2 36))) - 10] - [#:precision precision - (or/c exact-nonnegative-integer? - (list/c '= exact-nonnegative-integer?)) - 3] - [#:pos/exp-range - pos/exp-range - (list/c (or/c exact-integer? +inf.0) - (or/c exact-integer? -inf.0)) - (list -inf.0 +inf.0)] - [#:exp-precision exp-precision - (or/c exact-nonnegative-integer? - (list/c '= exact-nonnegative-integer?)) - 5] - [#:exp-format-exponent exp-format-exponent - (or/c #f string? (-> exact-integer? string?)) - #f] - [#:pad-digits-to pad-digits-to exact-positive-integer? 1] - [#:digits-padding digits-padding non-empty-string? " "]) - string?]{ - -Converts the rational number @racket[x] to a string in either -positional or exponential notation. The exactness or inexactness of -@racket[x] does not affect its formatting. - -Numbers whose order of magnitude (with respect to @racket[base]) fall -strictly within @racket[pos/exp-range] are formatted using positional -notation. More precisely, if the following condition holds: - -@racketblock[(or (zero? x) - (< (expt base (car pos/exp-range)) - (abs x) - (expt base (cadr pos/exp-range))))] - -then the result is equivalent to - -@racketblock[(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 - -@racketblock[(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[#:eval the-eval -(catn 999 #:pos/exp-range '(0 3)) -(catn 1000 #:pos/exp-range '(0 3)) -(catn 0.9876 #:pos/exp-range '(0 3)) -] - -Note that the default value of @racket[pos/exp-range] ensures that -positional notation will be used for any rational @racket[x]. -} - - -@defproc[(catnp [x rational?] - [#:sign sign - (or/c #f '+ '++ 'parens - (let ([ind (or/c string? (list/c string? string?))]) - (list/c ind ind ind))) - #f] - [#:base base - (or/c (integer-in 2 36) (list/c 'up (integer-in 2 36))) - 10] - [#:precision precision - (or/c exact-nonnegative-integer? - (list/c '= exact-nonnegative-integer?)) - 3] - [#:pad-digits-to pad-digits-to exact-positive-integer? 1] - [#:digits-padding digits-padding non-empty-string? " "]) - string?]{ - -Formats the rational number @racket[x] using positional notation according to -the following arguments: - -@itemize[ - -@item{@racket[precision] controls the number of digits after the decimal point -(or more accurately, the -@hyperlink["http://en.wikipedia.org/wiki/Radix_point"]{radix point}). If -@racket[precision] is a natural number, then up to @racket[precision] digits are -displayed, but trailing zeroes are dropped, and if all digits after the decimal -point are dropped the decimal point is also dropped. If @racket[precision] is -@racket[(list '= _digits)], then exactly @racket[_digits] digits after the -decimal point are used, and the decimal point is never dropped. - -@interaction[#:eval the-eval -(catnp pi) -(catnp pi #:precision 4) -(catnp pi #:precision 0) -(catnp 1.5 #:precision 4) -(catnp 1.5 #:precision '(= 4)) -(catnp 50 #:precision 2) -(catnp 50 #:precision '(= 2)) -(catnp 50 #:precision '(= 0)) -]} - -@item{@racket[pad-digits-to]: if @racket[x] would normally be printed -with fewer than @racket[pad-digits-to] digits (including the decimal -point but not including the sign indicator), the output is left-padded -using @racket[digits-padding]. - -@interaction[#:eval the-eval -(catnp 17) -(catnp 17 #:pad-digits-to 4) -(catnp -42 #:pad-digits-to 4) -(catnp 1.5 #:pad-digits-to 4) -(catnp 1.5 #:precision 4 #:pad-digits-to 10) -(catnp 1.5 #:precision '(= 4) #:pad-digits-to 10) -]} - -@item{@racket[digits-padding] specifies the string used to pad the -number to at least @racket[pad-digits-to] characters (not including the -sign indicator). The padding is placed between the sign and the normal -digits of @racket[x]. - -@interaction[#:eval the-eval -(catnp 17 #:pad-digits-to 4 #:digits-padding "0") -(catnp -42 #:pad-digits-to 4 #:digits-padding "0") -]} - -@item{@racket[sign] controls how the sign of the number is -indicated. - @itemlist[ - - @item{If @racket[sign] is @racket[#f] (the default), no sign output is - generated if @racket[x] is either positive or zero, and a minus sign is - prefixed if @racket[x] is negative. - - @interaction[#:eval the-eval - (for/list ([x '(17 0 -42)]) (catnp x)) - ]} - - @item{If @racket[sign] is @racket['+], no sign output is generated if - @racket[x] is zero, a plus sign is prefixed if @racket[x] is positive, and a - minus sign is prefixed if @racket[x] is negative. - - @interaction[#:eval the-eval - (for/list ([x '(17 0 -42)]) (catnp x #:sign '+)) - ]} - - @item{If @racket[sign] is @racket['++], a plus sign is prefixed if @racket[x] - is zero or positive, and a minus sign is prefixed if @racket[x] is negative. - - @interaction[#:eval the-eval - (for/list ([x '(17 0 -42)]) (catnp x #:sign '++)) - ]} - - @item{If @racket[sign] is @racket['parens], no sign output is generated if - @racket[x] is zero or positive, and the number is enclosed in parentheses if - @racket[x] is negative. - - @interaction[#:eval the-eval - (for/list ([x '(17 0 -42)]) (catnp x #:sign 'parens)) - ]} - - @item{If @racket[sign] is @racket[(list _pos-ind _zero-ind _neg-ind)], then - @racket[_pos-ind], @racket[_zero-ind], and @racket[_neg-ind] are used to - indicate positive, zero, and negative numbers, respectively. Each indicator is - either a string to be used as a prefix or a list containing two strings: a - prefix and a suffix. - - @interaction[#:eval the-eval - (let ([sign-table '(("" " up") "an even " ("" " down"))]) - (for/list ([x '(17 0 -42)]) (catnp x #:sign sign-table))) - ] - - The default behavior is equivalent to @racket['("" "" "-")]; the - @racket['parens] mode is equivalent to @racket['("" "" ("(" ")"))]. - } -]} - -@item{@racket[base] controls the base that @racket[x] is formatted in. If -@racket[base] is a number greater than @racket[10], then lower-case letters are -used. If @racket[base] is @racket[(list 'up _base*)] and @racket[_base*] is -greater than @racket[10], then upper-case letters are used. - -@interaction[#:eval the-eval -(catnp 100 #:base 7) -(catnp 4.5 #:base 2) -(catnp 3735928559 #:base 16) -(catnp 3735928559 #:base '(up 16)) -]} - -] -} - - -@defproc[(catne [x rational?] - [#:sign sign - (or/c #f '+ '++ 'parens - (let ([ind (or/c string? (list/c string? string?))]) - (list/c ind ind ind))) - #f] - [#:base base - (or/c (integer-in 2 36) (list/c 'up (integer-in 2 36))) - 10] - [#:precision precision - (or/c exact-nonnegative-integer? - (list/c '= exact-nonnegative-integer?)) - 5] - [#:format-exponent - format-exponent - (or/c #f string? (-> exact-integer? string?)) - #f] - [#:pad-digits-to pad-digits-to exact-positive-integer? 1] - [#:digits-padding digits-padding non-empty-string? " "]) - string?]{ - -Formats the rational number @racket[x] in exponential notation according to the -following arguments: - -@itemlist[ - -@item{@racket[base], @racket[sign] are interpreted as in positional notation, -described above, except that they apply only to the significand, not the -exponent. - -@interaction[#:eval the-eval -(catne -100 #:base 2) -]} - -@item{@racket[format-exponent] determines how the exponent is displayed. - -If @racket[format-exponent] is a string, the exponent is displayed with an -explicit sign (as with a @racket[sign-mode] of @racket['++]) and at least two -digits, separated from the significand by the ``exponent marker'' -@racket[format-exponent]: - -@interaction[#:eval the-eval -(catne 1234 #:format-exponent "E") -] - -If @racket[format-exponent] is @racket[#f], the ``exponent marker'' is -@racket["e"] if @racket[base] is @racket[10] and a string involving -@racket[base] otherwise: - -@interaction[#:eval the-eval -(catne 1234) -(catne 1234 #:base 8) -] - -If @racket[format-exponent] is a procedure, it is applied to the exponent and -the resulting string is appended to the significand: - -@interaction[#:eval the-eval -(catne 1234 #:format-exponent (lambda (e) (format "E~a" e))) -]} - -@item{@racket[precision] determines how many digits after the radix point the -significand contains. Like the @racket[precision] argument of @racket[catnp], -the form @racket[(list '= _digits)] causes trailing zeroes to be retained. - -@interaction[#:eval the-eval -(catne 12345 #:precision 3) -(catne 12345 #:precision 2) -(catne 10000 #:precision 2) -(catne 10000 #:precision '(= 2)) -]} - -@item{@racket[pad-digits-to] and @racket[digits-padding] are interpreted as in -positional notation. - -@interaction[#:eval the-eval -(catne 12345 #:pad-digits-to 12 #:digits-padding " ") -]} - -] - -@;{ -Note that unlike @racket[string->number] (and thus @racket[cat]), @racket[catn] -does not use exponential notation for large (or small) inexact numbers. Large -numbers will be displayed with a large number of digits, many of which are not -significant. - -@interaction[#:eval the-eval -(cat (expt 6.1 87)) -(catn (expt 6.1 87)) -(code:line (catn (+ (expt 6.1 87) 1000)) (code:comment "how many of these digits are significant?")) -]} -} - -@(close-eval the-eval) diff --git a/collects/unstable/scribblings/unstable.scrbl b/collects/unstable/scribblings/unstable.scrbl index 071f5ea3ca..1a5c93a1d0 100644 --- a/collects/unstable/scribblings/unstable.scrbl +++ b/collects/unstable/scribblings/unstable.scrbl @@ -77,7 +77,6 @@ Keep documentation and tests up to date. @include-section["../automata/scribblings/automata.scrbl"] @include-section["bytes.scrbl"] @include-section["contract.scrbl"] -@include-section["cat.scrbl"] @include-section["wrapc.scrbl"] @include-section["debug.scrbl"] @include-section["define.scrbl"]